Commit 770631cc79

Michael Dusan <michael.dusan@gmail.com>
2020-02-20 08:45:58
stage1: free more heap after analysis
- immediately free dangling IrInstGenConst after analysis - fixup mem::List params `&Allocator` → `*Allocator`
1 parent e381a42
src/ir.cpp
@@ -14,6 +14,7 @@
 #include "range_set.hpp"
 #include "softfloat.hpp"
 #include "util.hpp"
+#include "mem_list.hpp"
 
 #include <errno.h>
 
@@ -28,6 +29,9 @@ struct IrBuilderGen {
     CodeGen *codegen;
     IrExecutableGen *exec;
     IrBasicBlockGen *current_basic_block;
+
+    // track for immediate post-analysis destruction
+    mem::List<IrInstGenConst *> constants;
 };
 
 struct IrAnalyze {
@@ -741,6 +745,10 @@ static void ira_ref(IrAnalyze *ira) {
 static void ira_deref(IrAnalyze *ira) {
     if (ira->ref_count > 1) {
         ira->ref_count -= 1;
+
+        // immediate destruction of dangling IrInstGenConst is not possible
+        // free tracking memory because it will never be used
+        ira->new_irb.constants.deinit(&heap::c_allocator);
         return;
     }
     assert(ira->ref_count != 0);
@@ -758,6 +766,15 @@ static void ira_deref(IrAnalyze *ira) {
     heap::c_allocator.destroy(ira->old_irb.exec);
     ira->src_implicit_return_type_list.deinit();
     ira->resume_stack.deinit();
+
+    // destroy dangling IrInstGenConst
+    for (size_t i = 0; i < ira->new_irb.constants.length; i += 1) {
+        auto constant = ira->new_irb.constants.items[i];
+        if (constant->base.base.ref_count == 0 && !ir_inst_gen_has_side_effects(&constant->base))
+            destroy_instruction_gen(&constant->base);
+    }
+    ira->new_irb.constants.deinit(&heap::c_allocator);
+
     heap::c_allocator.destroy(ira);
 }
 
@@ -12746,12 +12763,14 @@ static IrInstGen *ir_const(IrAnalyze *ira, IrInst *inst, ZigType *ty) {
     IrInstGen *new_instruction = &const_instruction->base;
     new_instruction->value->type = ty;
     new_instruction->value->special = ConstValSpecialStatic;
+    ira->new_irb.constants.append(&heap::c_allocator, const_instruction);
     return new_instruction;
 }
 
 static IrInstGen *ir_const_noval(IrAnalyze *ira, IrInst *old_instruction) {
     IrInstGenConst *const_instruction = ir_create_inst_noval<IrInstGenConst>(&ira->new_irb,
             old_instruction->scope, old_instruction->source_node);
+    ira->new_irb.constants.append(&heap::c_allocator, const_instruction);
     return &const_instruction->base;
 }
 
src/mem_list.hpp
@@ -14,11 +14,14 @@ namespace mem {
 
 template<typename T>
 struct List {
-    void deinit(Allocator& allocator) {
-        allocator.deallocate<T>(items, capacity);
+    void deinit(Allocator *allocator) {
+        allocator->deallocate<T>(items, capacity);
+        items = nullptr;
+        length = 0;
+        capacity = 0;
     }
 
-    void append(Allocator& allocator, const T& item) {
+    void append(Allocator *allocator, const T& item) {
         ensure_capacity(allocator, length + 1);
         items[length++] = item;
     }
@@ -57,7 +60,7 @@ struct List {
         return items[length - 1];
     }
 
-    void resize(Allocator& allocator, size_t new_length) {
+    void resize(Allocator *allocator, size_t new_length) {
         assert(new_length != SIZE_MAX);
         ensure_capacity(allocator, new_length);
         length = new_length;
@@ -67,7 +70,7 @@ struct List {
         length = 0;
     }
 
-    void ensure_capacity(Allocator& allocator, size_t new_capacity) {
+    void ensure_capacity(Allocator *allocator, size_t new_capacity) {
         if (capacity >= new_capacity)
             return;
 
@@ -76,7 +79,7 @@ struct List {
             better_capacity = better_capacity * 5 / 2 + 8;
         } while (better_capacity < new_capacity);
 
-        items = allocator.reallocate_nonzero<T>(items, capacity, better_capacity);
+        items = allocator->reallocate_nonzero<T>(items, capacity, better_capacity);
         capacity = better_capacity;
     }
 
src/mem_profile.cpp
@@ -92,7 +92,7 @@ void Profile::print_report(FILE *file) {
         auto entry = it.next();
         if (!entry)
             break;
-        list.append(heap::bootstrap_allocator, &entry->value);
+        list.append(&heap::bootstrap_allocator, &entry->value);
     }
 
     qsort(list.items, list.length, sizeof(const Entry *), entry_compare);
@@ -143,7 +143,7 @@ void Profile::print_report(FILE *file) {
     fprintf(file, "\n  Total calls alloc: %zu, dealloc: %zu, remain: %zu\n",
         total_calls_alloc, total_calls_dealloc, (total_calls_alloc - total_calls_dealloc));
 
-    list.deinit(heap::bootstrap_allocator);
+    list.deinit(&heap::bootstrap_allocator);
 }
 
 uint32_t Profile::usage_hash(UsageKey key) {