| author | |
| committer | |
| log | 770631cc79a655bc5e21184ca15bdb6192e905de |
| tree | 9d9952d5e25df9891217a99f2d0f9aff2ef14caf |
| parent | e381a42de9c0f0c5439a926b0ac99026a0373f49 |
| signature | Commit is signed but in an unrecognized format. |
- immediately free dangling IrInstGenConst after analysis
- fixup mem::List params `&Allocator` → `*Allocator`3 files changed, 30 insertions(+), 8 deletions(-)
src/ir.cpp+19| ... | ... | @@ -14,6 +14,7 @@ |
| 14 | 14 | #include "range_set.hpp" |
| 15 | 15 | #include "softfloat.hpp" |
| 16 | 16 | #include "util.hpp" |
| 17 | #include "mem_list.hpp" | |
| 17 | 18 | |
| 18 | 19 | #include <errno.h> |
| 19 | 20 | |
| ... | ... | @@ -28,6 +29,9 @@ struct IrBuilderGen { |
| 28 | 29 | CodeGen *codegen; |
| 29 | 30 | IrExecutableGen *exec; |
| 30 | 31 | IrBasicBlockGen *current_basic_block; |
| 32 | ||
| 33 | // track for immediate post-analysis destruction | |
| 34 | mem::List<IrInstGenConst *> constants; | |
| 31 | 35 | }; |
| 32 | 36 | |
| 33 | 37 | struct IrAnalyze { |
| ... | ... | @@ -741,6 +745,10 @@ static void ira_ref(IrAnalyze *ira) { |
| 741 | 745 | static void ira_deref(IrAnalyze *ira) { |
| 742 | 746 | if (ira->ref_count > 1) { |
| 743 | 747 | ira->ref_count -= 1; |
| 748 | ||
| 749 | // immediate destruction of dangling IrInstGenConst is not possible | |
| 750 | // free tracking memory because it will never be used | |
| 751 | ira->new_irb.constants.deinit(&heap::c_allocator); | |
| 744 | 752 | return; |
| 745 | 753 | } |
| 746 | 754 | assert(ira->ref_count != 0); |
| ... | ... | @@ -758,6 +766,15 @@ static void ira_deref(IrAnalyze *ira) { |
| 758 | 766 | heap::c_allocator.destroy(ira->old_irb.exec); |
| 759 | 767 | ira->src_implicit_return_type_list.deinit(); |
| 760 | 768 | ira->resume_stack.deinit(); |
| 769 | ||
| 770 | // destroy dangling IrInstGenConst | |
| 771 | for (size_t i = 0; i < ira->new_irb.constants.length; i += 1) { | |
| 772 | auto constant = ira->new_irb.constants.items[i]; | |
| 773 | if (constant->base.base.ref_count == 0 && !ir_inst_gen_has_side_effects(&constant->base)) | |
| 774 | destroy_instruction_gen(&constant->base); | |
| 775 | } | |
| 776 | ira->new_irb.constants.deinit(&heap::c_allocator); | |
| 777 | ||
| 761 | 778 | heap::c_allocator.destroy(ira); |
| 762 | 779 | } |
| 763 | 780 | |
| ... | ... | @@ -12746,12 +12763,14 @@ static IrInstGen *ir_const(IrAnalyze *ira, IrInst *inst, ZigType *ty) { |
| 12746 | 12763 | IrInstGen *new_instruction = &const_instruction->base; |
| 12747 | 12764 | new_instruction->value->type = ty; |
| 12748 | 12765 | new_instruction->value->special = ConstValSpecialStatic; |
| 12766 | ira->new_irb.constants.append(&heap::c_allocator, const_instruction); | |
| 12749 | 12767 | return new_instruction; |
| 12750 | 12768 | } |
| 12751 | 12769 | |
| 12752 | 12770 | static IrInstGen *ir_const_noval(IrAnalyze *ira, IrInst *old_instruction) { |
| 12753 | 12771 | IrInstGenConst *const_instruction = ir_create_inst_noval<IrInstGenConst>(&ira->new_irb, |
| 12754 | 12772 | old_instruction->scope, old_instruction->source_node); |
| 12773 | ira->new_irb.constants.append(&heap::c_allocator, const_instruction); | |
| 12755 | 12774 | return &const_instruction->base; |
| 12756 | 12775 | } |
| 12757 | 12776 |
src/mem_list.hpp+9-6| ... | ... | @@ -14,11 +14,14 @@ namespace mem { |
| 14 | 14 | |
| 15 | 15 | template<typename T> |
| 16 | 16 | struct List { |
| 17 | void deinit(Allocator& allocator) { | |
| 18 | allocator.deallocate<T>(items, capacity); | |
| 17 | void deinit(Allocator *allocator) { | |
| 18 | allocator->deallocate<T>(items, capacity); | |
| 19 | items = nullptr; | |
| 20 | length = 0; | |
| 21 | capacity = 0; | |
| 19 | 22 | } |
| 20 | 23 | |
| 21 | void append(Allocator& allocator, const T& item) { | |
| 24 | void append(Allocator *allocator, const T& item) { | |
| 22 | 25 | ensure_capacity(allocator, length + 1); |
| 23 | 26 | items[length++] = item; |
| 24 | 27 | } |
| ... | ... | @@ -57,7 +60,7 @@ struct List { |
| 57 | 60 | return items[length - 1]; |
| 58 | 61 | } |
| 59 | 62 | |
| 60 | void resize(Allocator& allocator, size_t new_length) { | |
| 63 | void resize(Allocator *allocator, size_t new_length) { | |
| 61 | 64 | assert(new_length != SIZE_MAX); |
| 62 | 65 | ensure_capacity(allocator, new_length); |
| 63 | 66 | length = new_length; |
| ... | ... | @@ -67,7 +70,7 @@ struct List { |
| 67 | 70 | length = 0; |
| 68 | 71 | } |
| 69 | 72 | |
| 70 | void ensure_capacity(Allocator& allocator, size_t new_capacity) { | |
| 73 | void ensure_capacity(Allocator *allocator, size_t new_capacity) { | |
| 71 | 74 | if (capacity >= new_capacity) |
| 72 | 75 | return; |
| 73 | 76 | |
| ... | ... | @@ -76,7 +79,7 @@ struct List { |
| 76 | 79 | better_capacity = better_capacity * 5 / 2 + 8; |
| 77 | 80 | } while (better_capacity < new_capacity); |
| 78 | 81 | |
| 79 | items = allocator.reallocate_nonzero<T>(items, capacity, better_capacity); | |
| 82 | items = allocator->reallocate_nonzero<T>(items, capacity, better_capacity); | |
| 80 | 83 | capacity = better_capacity; |
| 81 | 84 | } |
| 82 | 85 |
src/mem_profile.cpp+2-2| ... | ... | @@ -92,7 +92,7 @@ void Profile::print_report(FILE *file) { |
| 92 | 92 | auto entry = it.next(); |
| 93 | 93 | if (!entry) |
| 94 | 94 | break; |
| 95 | list.append(heap::bootstrap_allocator, &entry->value); | |
| 95 | list.append(&heap::bootstrap_allocator, &entry->value); | |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | 98 | qsort(list.items, list.length, sizeof(const Entry *), entry_compare); |
| ... | ... | @@ -143,7 +143,7 @@ void Profile::print_report(FILE *file) { |
| 143 | 143 | fprintf(file, "\n Total calls alloc: %zu, dealloc: %zu, remain: %zu\n", |
| 144 | 144 | total_calls_alloc, total_calls_dealloc, (total_calls_alloc - total_calls_dealloc)); |
| 145 | 145 | |
| 146 | list.deinit(heap::bootstrap_allocator); | |
| 146 | list.deinit(&heap::bootstrap_allocator); | |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | 149 | uint32_t Profile::usage_hash(UsageKey key) { |