Commit a647a88dfc

Michael Dusan <michael.dusan@gmail.com>
2019-11-25 21:04:49
const interning for 1-possible-value types
1 parent 8f3e972
src/all_types.hpp
@@ -2021,6 +2021,13 @@ struct CodeGen {
         ZigType *entry_any_frame;
     } builtin_types;
 
+    struct {
+        ZigValue x_undefined;
+        ZigValue x_void;
+        ZigValue x_null;
+        ZigValue x_unreachable;
+    } intern_values;
+
     ZigType *align_amt_type;
     ZigType *stack_trace_type;
     ZigType *err_tag_type;
src/bigint.cpp
@@ -195,6 +195,11 @@ void bigint_init_bigint(BigInt *dest, const BigInt *src) {
     memcpy(dest->data.digits, src->data.digits, sizeof(uint64_t) * dest->digit_count);
 }
 
+void bigint_deinit(BigInt *bi) {
+    if (bi->digit_count > 1)
+        deallocate<uint64_t>(bi->data.digits, bi->digit_count);
+}
+
 void bigint_init_bigfloat(BigInt *dest, const BigFloat *op) {
     float128_t zero;
     ui32_to_f128M(0, &zero);
src/bigint.hpp
@@ -34,6 +34,7 @@ void bigint_init_signed(BigInt *dest, int64_t x);
 void bigint_init_bigint(BigInt *dest, const BigInt *src);
 void bigint_init_bigfloat(BigInt *dest, const BigFloat *op);
 void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative);
+void bigint_deinit(BigInt *bi);
 
 // panics if number won't fit
 uint64_t bigint_as_u64(const BigInt *bigint);
src/codegen.cpp
@@ -8008,6 +8008,33 @@ static void define_builtin_types(CodeGen *g) {
     }
 }
 
+static void define_intern_values(CodeGen *g) {
+    {
+        auto& value = g->intern_values.x_undefined;
+        value.type = g->builtin_types.entry_undef;
+        value.global_refs = allocate<ConstGlobalRefs>(1, "ConstGlobalRefs.undefined");
+        value.special = ConstValSpecialStatic;
+    }
+    {
+        auto& value = g->intern_values.x_void;
+        value.type = g->builtin_types.entry_void;
+        value.global_refs = allocate<ConstGlobalRefs>(1, "ConstGlobalRefs.void");
+        value.special = ConstValSpecialStatic;
+    }
+    {
+        auto& value = g->intern_values.x_null;
+        value.type = g->builtin_types.entry_null;
+        value.global_refs = allocate<ConstGlobalRefs>(1, "ConstGlobalRefs.null");
+        value.special = ConstValSpecialStatic;
+    }
+    {
+        auto& value = g->intern_values.x_unreachable;
+        value.type = g->builtin_types.entry_unreachable;
+        value.global_refs = allocate<ConstGlobalRefs>(1, "ConstGlobalRefs.unreachable");
+        value.special = ConstValSpecialStatic;
+    }
+}
+
 static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name, size_t count) {
     BuiltinFnEntry *builtin_fn = allocate<BuiltinFnEntry>(1);
     buf_init_from_str(&builtin_fn->name, name);
@@ -8629,6 +8656,7 @@ static void init(CodeGen *g) {
     g->dummy_di_file = nullptr;
 
     define_builtin_types(g);
+    define_intern_values(g);
 
     IrInstruction *sentinel_instructions = allocate<IrInstruction>(2);
     g->invalid_instruction = &sentinel_instructions[0];
src/hash_map.hpp
@@ -23,10 +23,10 @@ public:
     }
 
     struct Entry {
-        bool used;
-        int distance_from_start_index;
         K key;
         V value;
+        bool used;
+        int distance_from_start_index;
     };
 
     void clear() {
@@ -187,10 +187,10 @@ private:
                     if (distance_from_start_index > _max_distance_from_start_index)
                         _max_distance_from_start_index = distance_from_start_index;
                     *entry = {
-                        true,
-                        distance_from_start_index,
                         key,
                         value,
+                        true,
+                        distance_from_start_index,
                     };
                     key = tmp.key;
                     value = tmp.value;
@@ -208,10 +208,10 @@ private:
             if (distance_from_start_index > _max_distance_from_start_index)
                 _max_distance_from_start_index = distance_from_start_index;
             *entry = {
-                true,
-                distance_from_start_index,
                 key,
                 value,
+                true,
+                distance_from_start_index,
             };
             return;
         }
src/ir.cpp
@@ -1161,6 +1161,22 @@ static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_no
     return special_instruction;
 }
 
+template<typename T>
+static T *ir_create_instruction_noval(IrBuilder *irb, Scope *scope, AstNode *source_node) {
+    const char *name = nullptr;
+#ifdef ZIG_ENABLE_MEM_PROFILE
+    T *dummy = nullptr;
+    name = ir_instruction_type_str(ir_instruction_id(dummy));
+#endif
+    T *special_instruction = allocate<T>(1, name);
+    special_instruction->base.id = ir_instruction_id(special_instruction);
+    special_instruction->base.scope = scope;
+    special_instruction->base.source_node = source_node;
+    special_instruction->base.debug_id = exec_next_debug_id(irb->exec);
+    special_instruction->base.owner_bb = irb->current_basic_block;
+    return special_instruction;
+}
+
 template<typename T>
 static T *ir_build_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
     T *special_instruction = ir_create_instruction<T>(irb, scope, source_node);
@@ -1214,16 +1230,22 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou
 }
 
 static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {
-    IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
-    const_instruction->base.value->type = irb->codegen->builtin_types.entry_void;
-    const_instruction->base.value->special = ConstValSpecialStatic;
+#ifdef ZIG_ENABLE_MEM_PROFILE
+    memprof_intern_count.x_void += 1;
+#endif
+    IrInstructionConst *const_instruction = ir_create_instruction_noval<IrInstructionConst>(irb, scope, source_node);
+    ir_instruction_append(irb->current_basic_block, &const_instruction->base);
+    const_instruction->base.value = &irb->codegen->intern_values.x_void;
     return &const_instruction->base;
 }
 
 static IrInstruction *ir_build_const_undefined(IrBuilder *irb, Scope *scope, AstNode *source_node) {
-    IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
-    const_instruction->base.value->special = ConstValSpecialUndef;
-    const_instruction->base.value->type = irb->codegen->builtin_types.entry_undef;
+#ifdef ZIG_ENABLE_MEM_PROFILE
+    memprof_intern_count.x_undefined += 1;
+#endif
+    IrInstructionConst *const_instruction = ir_create_instruction_noval<IrInstructionConst>(irb, scope, source_node);
+    ir_instruction_append(irb->current_basic_block, &const_instruction->base);
+    const_instruction->base.value = &irb->codegen->intern_values.x_undefined;
     return &const_instruction->base;
 }
 
@@ -1252,9 +1274,12 @@ static IrInstruction *ir_build_const_bigfloat(IrBuilder *irb, Scope *scope, AstN
 }
 
 static IrInstruction *ir_build_const_null(IrBuilder *irb, Scope *scope, AstNode *source_node) {
-    IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
-    const_instruction->base.value->type = irb->codegen->builtin_types.entry_null;
-    const_instruction->base.value->special = ConstValSpecialStatic;
+#ifdef ZIG_ENABLE_MEM_PROFILE
+    memprof_intern_count.x_null += 1;
+#endif
+    IrInstructionConst *const_instruction = ir_create_instruction_noval<IrInstructionConst>(irb, scope, source_node);
+    ir_instruction_append(irb->current_basic_block, &const_instruction->base);
+    const_instruction->base.value = &irb->codegen->intern_values.x_null;
     return &const_instruction->base;
 }
 
@@ -11113,6 +11138,12 @@ static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, Z
     return new_instruction;
 }
 
+static IrInstruction *ir_const_noval(IrAnalyze *ira, IrInstruction *old_instruction) {
+    IrInstructionConst *const_instruction = ir_create_instruction_noval<IrInstructionConst>(&ira->new_irb,
+            old_instruction->scope, old_instruction->source_node);
+    return &const_instruction->base;
+}
+
 static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
         ZigType *wanted_type, CastOp cast_op)
 {
@@ -11429,13 +11460,21 @@ static IrInstruction *ir_const_undef(IrAnalyze *ira, IrInstruction *source_instr
 }
 
 static IrInstruction *ir_const_unreachable(IrAnalyze *ira, IrInstruction *source_instruction) {
-    IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_unreachable);
-    result->value->special = ConstValSpecialStatic;
+#ifdef ZIG_ENABLE_MEM_PROFILE
+    memprof_intern_count.x_unreachable += 1;
+#endif
+    IrInstruction *result = ir_const_noval(ira, source_instruction);
+    result->value = &ira->codegen->intern_values.x_unreachable;
     return result;
 }
 
 static IrInstruction *ir_const_void(IrAnalyze *ira, IrInstruction *source_instruction) {
-    return ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_void);
+#ifdef ZIG_ENABLE_MEM_PROFILE
+    memprof_intern_count.x_void += 1;
+#endif
+    IrInstruction *result = ir_const_noval(ira, source_instruction);
+    result->value = &ira->codegen->intern_values.x_void;
+    return result;
 }
 
 static IrInstruction *ir_const_unsigned(IrAnalyze *ira, IrInstruction *source_instruction, uint64_t value) {
src/memory_profiling.cpp
@@ -6,6 +6,8 @@
 
 #ifdef ZIG_ENABLE_MEM_PROFILE
 
+MemprofInternCount memprof_intern_count;
+
 static bool str_eql_str(const char *a, const char *b) {
     return strcmp(a, b) == 0;
 }
@@ -29,7 +31,6 @@ ZigList<const char *> unknown_names = {};
 HashMap<const char *, CountAndSize, str_hash, str_eql_str> usage_table = {};
 bool table_active = false;
 
-
 static const char *get_default_name(const char *name_or_null, size_t type_size) {
     if (name_or_null != nullptr) return name_or_null;
     if (type_size >= unknown_names.length) {
@@ -134,6 +135,12 @@ void memprof_dump_stats(FILE *file) {
 
     list.deinit();
     table_active = true;
+
+    fprintf(stderr, "\n");
+    fprintf(stderr, "undefined: interned %zu times\n", memprof_intern_count.x_undefined);
+    fprintf(stderr, "void: interned %zu times\n", memprof_intern_count.x_void);
+    fprintf(stderr, "null: interned %zu times\n", memprof_intern_count.x_null);
+    fprintf(stderr, "unreachable: interned %zu times\n", memprof_intern_count.x_unreachable);
 }
 
 #endif
src/memory_profiling.hpp
@@ -13,6 +13,14 @@
 #include <stddef.h>
 #include <stdio.h>
 
+struct MemprofInternCount {
+    size_t x_undefined;
+    size_t x_void;
+    size_t x_null;
+    size_t x_unreachable;
+};
+extern MemprofInternCount memprof_intern_count;
+
 void memprof_init(void);
 
 void memprof_alloc(const char *name, size_t item_count, size_t type_size);
src/util.cpp
@@ -121,18 +121,18 @@ SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes) {
 
 void zig_pretty_print_bytes(FILE *f, double n) {
     if (n > 1024.0 * 1024.0 * 1024.0) {
-        fprintf(f, "%.02f GiB", n / 1024.0 / 1024.0 / 1024.0);
+        fprintf(f, "%.03f GiB", n / 1024.0 / 1024.0 / 1024.0);
         return;
     }
     if (n > 1024.0 * 1024.0) {
-        fprintf(f, "%.02f MiB", n / 1024.0 / 1024.0);
+        fprintf(f, "%.03f MiB", n / 1024.0 / 1024.0);
         return;
     }
     if (n > 1024.0) {
-        fprintf(f, "%.02f KiB", n / 1024.0);
+        fprintf(f, "%.03f KiB", n / 1024.0);
         return;
     }
-    fprintf(f, "%.02f bytes", n );
+    fprintf(f, "%.03f bytes", n );
     return;
 }