authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-07 18:32:19-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-07 18:32:19-07:00
log87cdbb6c25f198fa88dcff530f34bfe3e9b14245
tree7464e006b76f61f7e4443e67abdd5ed627b3e821
parent6b3ce918db0bd73b5b1973b1baf358b6114810ed

improve performance for get_fn_type


4 files changed, 68 insertions(+), 51 deletions(-)

src/all_types.hpp+6-3
...@@ -810,11 +810,13 @@ struct AsmToken {...@@ -810,11 +810,13 @@ struct AsmToken {
810 int end;810 int end;
811};811};
812812
813// this struct is allocated with allocate_nonzero
813struct FnTypeParamInfo {814struct FnTypeParamInfo {
814 bool is_noalias;815 bool is_noalias;
815 TypeTableEntry *type;816 TypeTableEntry *type;
816};817};
817818
819static const int fn_type_id_prealloc_param_info_count = 4;
818struct FnTypeId {820struct FnTypeId {
819 TypeTableEntry *return_type;821 TypeTableEntry *return_type;
820 FnTypeParamInfo *param_info;822 FnTypeParamInfo *param_info;
...@@ -823,10 +825,11 @@ struct FnTypeId {...@@ -823,10 +825,11 @@ struct FnTypeId {
823 bool is_naked;825 bool is_naked;
824 bool is_cold;826 bool is_cold;
825 bool is_extern;827 bool is_extern;
828 FnTypeParamInfo prealloc_param_info[fn_type_id_prealloc_param_info_count];
826};829};
827830
828uint32_t fn_type_id_hash(FnTypeId);831uint32_t fn_type_id_hash(FnTypeId*);
829bool fn_type_id_eql(FnTypeId a, FnTypeId b);832bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
830833
831834
832struct TypeTableEntryPointer {835struct TypeTableEntryPointer {
...@@ -1061,7 +1064,7 @@ struct CodeGen {...@@ -1061,7 +1064,7 @@ struct CodeGen {
1061 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;1064 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
1062 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;1065 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
1063 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> unresolved_top_level_decls;1066 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> unresolved_top_level_decls;
1064 HashMap<FnTypeId, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;1067 HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
1065 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;1068 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
10661069
1067 uint32_t next_unresolved_index;1070 uint32_t next_unresolved_index;
src/analyze.cpp+54-45
...@@ -541,18 +541,21 @@ TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *...@@ -541,18 +541,21 @@ TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *
541}541}
542542
543// accepts ownership of fn_type_id memory543// accepts ownership of fn_type_id memory
544TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {544TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
545 auto table_entry = g->fn_type_table.maybe_get(fn_type_id);545 auto table_entry = g->fn_type_table.maybe_get(fn_type_id);
546 if (table_entry) {546 if (table_entry) {
547 return table_entry->value;547 return table_entry->value;
548 }548 }
549549
550 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);550 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
551 fn_type->data.fn.fn_type_id = fn_type_id;551 fn_type->data.fn.fn_type_id = *fn_type_id;
552 if (fn_type_id->param_info == &fn_type_id->prealloc_param_info[0]) {
553 fn_type->data.fn.fn_type_id.param_info = &fn_type->data.fn.fn_type_id.prealloc_param_info[0];
554 }
552555
553 if (fn_type_id.is_cold) {556 if (fn_type_id->is_cold) {
554 fn_type->data.fn.calling_convention = LLVMColdCallConv;557 fn_type->data.fn.calling_convention = LLVMColdCallConv;
555 } else if (fn_type_id.is_extern) {558 } else if (fn_type_id->is_extern) {
556 fn_type->data.fn.calling_convention = LLVMCCallConv;559 fn_type->data.fn.calling_convention = LLVMCCallConv;
557 } else {560 } else {
558 fn_type->data.fn.calling_convention = LLVMFastCallConv;561 fn_type->data.fn.calling_convention = LLVMFastCallConv;
...@@ -560,12 +563,12 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {...@@ -560,12 +563,12 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {
560563
561 // populate the name of the type564 // populate the name of the type
562 buf_resize(&fn_type->name, 0);565 buf_resize(&fn_type->name, 0);
563 const char *extern_str = fn_type_id.is_extern ? "extern " : "";566 const char *extern_str = fn_type_id->is_extern ? "extern " : "";
564 const char *naked_str = fn_type_id.is_naked ? "naked " : "";567 const char *naked_str = fn_type_id->is_naked ? "naked " : "";
565 const char *cold_str = fn_type_id.is_cold ? "cold " : "";568 const char *cold_str = fn_type_id->is_cold ? "cold " : "";
566 buf_appendf(&fn_type->name, "%s%s%sfn(", extern_str, naked_str, cold_str);569 buf_appendf(&fn_type->name, "%s%s%sfn(", extern_str, naked_str, cold_str);
567 for (int i = 0; i < fn_type_id.param_count; i += 1) {570 for (int i = 0; i < fn_type_id->param_count; i += 1) {
568 FnTypeParamInfo *param_info = &fn_type_id.param_info[i];571 FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
569572
570 TypeTableEntry *param_type = param_info->type;573 TypeTableEntry *param_type = param_info->type;
571 const char *comma = (i == 0) ? "" : ", ";574 const char *comma = (i == 0) ? "" : ", ";
...@@ -573,42 +576,42 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {...@@ -573,42 +576,42 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {
573 buf_appendf(&fn_type->name, "%s%s%s", comma, noalias_str, buf_ptr(&param_type->name));576 buf_appendf(&fn_type->name, "%s%s%s", comma, noalias_str, buf_ptr(&param_type->name));
574 }577 }
575578
576 if (fn_type_id.is_var_args) {579 if (fn_type_id->is_var_args) {
577 const char *comma = (fn_type_id.param_count == 0) ? "" : ", ";580 const char *comma = (fn_type_id->param_count == 0) ? "" : ", ";
578 buf_appendf(&fn_type->name, "%s...", comma);581 buf_appendf(&fn_type->name, "%s...", comma);
579 }582 }
580 buf_appendf(&fn_type->name, ")");583 buf_appendf(&fn_type->name, ")");
581 if (fn_type_id.return_type->id != TypeTableEntryIdVoid) {584 if (fn_type_id->return_type->id != TypeTableEntryIdVoid) {
582 buf_appendf(&fn_type->name, " -> %s", buf_ptr(&fn_type_id.return_type->name));585 buf_appendf(&fn_type->name, " -> %s", buf_ptr(&fn_type_id->return_type->name));
583 }586 }
584587
585588
586 // next, loop over the parameters again and compute debug information589 // next, loop over the parameters again and compute debug information
587 // and codegen information590 // and codegen information
588 bool first_arg_return = handle_is_ptr(fn_type_id.return_type);591 bool first_arg_return = handle_is_ptr(fn_type_id->return_type);
589 // +1 for maybe making the first argument the return value592 // +1 for maybe making the first argument the return value
590 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(1 + fn_type_id.param_count);593 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(1 + fn_type_id->param_count);
591 // +1 because 0 is the return type and +1 for maybe making first arg ret val594 // +1 because 0 is the return type and +1 for maybe making first arg ret val
592 LLVMZigDIType **param_di_types = allocate<LLVMZigDIType*>(2 + fn_type_id.param_count);595 LLVMZigDIType **param_di_types = allocate<LLVMZigDIType*>(2 + fn_type_id->param_count);
593 param_di_types[0] = fn_type_id.return_type->di_type;596 param_di_types[0] = fn_type_id->return_type->di_type;
594 int gen_param_index = 0;597 int gen_param_index = 0;
595 TypeTableEntry *gen_return_type;598 TypeTableEntry *gen_return_type;
596 if (first_arg_return) {599 if (first_arg_return) {
597 TypeTableEntry *gen_type = get_pointer_to_type(g, fn_type_id.return_type, false);600 TypeTableEntry *gen_type = get_pointer_to_type(g, fn_type_id->return_type, false);
598 gen_param_types[gen_param_index] = gen_type->type_ref;601 gen_param_types[gen_param_index] = gen_type->type_ref;
599 gen_param_index += 1;602 gen_param_index += 1;
600 // after the gen_param_index += 1 because 0 is the return type603 // after the gen_param_index += 1 because 0 is the return type
601 param_di_types[gen_param_index] = gen_type->di_type;604 param_di_types[gen_param_index] = gen_type->di_type;
602 gen_return_type = g->builtin_types.entry_void;605 gen_return_type = g->builtin_types.entry_void;
603 } else if (!type_has_bits(fn_type_id.return_type)) {606 } else if (!type_has_bits(fn_type_id->return_type)) {
604 gen_return_type = g->builtin_types.entry_void;607 gen_return_type = g->builtin_types.entry_void;
605 } else {608 } else {
606 gen_return_type = fn_type_id.return_type;609 gen_return_type = fn_type_id->return_type;
607 }610 }
608 fn_type->data.fn.gen_return_type = gen_return_type;611 fn_type->data.fn.gen_return_type = gen_return_type;
609612
610 fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id.param_count);613 fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count);
611 for (int i = 0; i < fn_type_id.param_count; i += 1) {614 for (int i = 0; i < fn_type_id->param_count; i += 1) {
612 FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i];615 FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i];
613 TypeTableEntry *type_entry = src_param_info->type;616 TypeTableEntry *type_entry = src_param_info->type;
614 FnGenParamInfo *gen_param_info = &fn_type->data.fn.gen_param_info[i];617 FnGenParamInfo *gen_param_info = &fn_type->data.fn.gen_param_info[i];
...@@ -639,13 +642,13 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {...@@ -639,13 +642,13 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {
639 fn_type->data.fn.gen_param_count = gen_param_index;642 fn_type->data.fn.gen_param_count = gen_param_index;
640643
641 fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,644 fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,
642 gen_param_types, gen_param_index, fn_type_id.is_var_args);645 gen_param_types, gen_param_index, fn_type_id->is_var_args);
643 fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);646 fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);
644 LLVMZigDIFile *di_file = nullptr;647 LLVMZigDIFile *di_file = nullptr;
645 fn_type->di_type = LLVMZigCreateSubroutineType(g->dbuilder, di_file,648 fn_type->di_type = LLVMZigCreateSubroutineType(g->dbuilder, di_file,
646 param_di_types, gen_param_index + 1, 0);649 param_di_types, gen_param_index + 1, 0);
647650
648 g->fn_type_table.put(fn_type_id, fn_type);651 g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type);
649652
650 return fn_type;653 return fn_type;
651}654}
...@@ -747,7 +750,13 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor...@@ -747,7 +750,13 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
747 fn_type_id.is_naked = is_naked;750 fn_type_id.is_naked = is_naked;
748 fn_type_id.is_cold = is_cold;751 fn_type_id.is_cold = is_cold;
749 fn_type_id.param_count = node->data.fn_proto.params.length;752 fn_type_id.param_count = node->data.fn_proto.params.length;
750 fn_type_id.param_info = allocate<FnTypeParamInfo>(fn_type_id.param_count);753
754 if (fn_type_id.param_count > fn_type_id_prealloc_param_info_count) {
755 fn_type_id.param_info = allocate_nonzero<FnTypeParamInfo>(fn_type_id.param_count);
756 } else {
757 fn_type_id.param_info = &fn_type_id.prealloc_param_info[0];
758 }
759
751 fn_type_id.is_var_args = fn_proto->is_var_args;760 fn_type_id.is_var_args = fn_proto->is_var_args;
752 fn_type_id.return_type = analyze_type_expr(g, import, import->block_context, node->data.fn_proto.return_type);761 fn_type_id.return_type = analyze_type_expr(g, import, import->block_context, node->data.fn_proto.return_type);
753762
...@@ -800,7 +809,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor...@@ -800,7 +809,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
800 return g->builtin_types.entry_invalid;809 return g->builtin_types.entry_invalid;
801 }810 }
802811
803 return get_fn_type(g, fn_type_id);812 return get_fn_type(g, &fn_type_id);
804}813}
805814
806815
...@@ -5855,35 +5864,35 @@ static uint32_t hash_ptr(void *ptr) {...@@ -5855,35 +5864,35 @@ static uint32_t hash_ptr(void *ptr) {
5855 return a ^ b;5864 return a ^ b;
5856}5865}
58575866
5858uint32_t fn_type_id_hash(FnTypeId id) {5867uint32_t fn_type_id_hash(FnTypeId *id) {
5859 uint32_t result = 0;5868 uint32_t result = 0;
5860 result += id.is_extern ? 3349388391 : 0;5869 result += id->is_extern ? 3349388391 : 0;
5861 result += id.is_naked ? 608688877 : 0;5870 result += id->is_naked ? 608688877 : 0;
5862 result += id.is_cold ? 3605523458 : 0;5871 result += id->is_cold ? 3605523458 : 0;
5863 result += id.is_var_args ? 1931444534 : 0;5872 result += id->is_var_args ? 1931444534 : 0;
5864 result += hash_ptr(id.return_type);5873 result += hash_ptr(id->return_type);
5865 result += id.param_count;5874 result += id->param_count;
5866 for (int i = 0; i < id.param_count; i += 1) {5875 for (int i = 0; i < id->param_count; i += 1) {
5867 FnTypeParamInfo *info = &id.param_info[i];5876 FnTypeParamInfo *info = &id->param_info[i];
5868 result += info->is_noalias ? 892356923 : 0;5877 result += info->is_noalias ? 892356923 : 0;
5869 result += hash_ptr(info->type);5878 result += hash_ptr(info->type);
5870 }5879 }
5871 return result;5880 return result;
5872}5881}
58735882
5874bool fn_type_id_eql(FnTypeId a, FnTypeId b) {5883bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
5875 if (a.is_extern != b.is_extern ||5884 if (a->is_extern != b->is_extern ||
5876 a.is_naked != b.is_naked ||5885 a->is_naked != b->is_naked ||
5877 a.is_cold != b.is_cold ||5886 a->is_cold != b->is_cold ||
5878 a.return_type != b.return_type ||5887 a->return_type != b->return_type ||
5879 a.is_var_args != b.is_var_args ||5888 a->is_var_args != b->is_var_args ||
5880 a.param_count != b.param_count)5889 a->param_count != b->param_count)
5881 {5890 {
5882 return false;5891 return false;
5883 }5892 }
5884 for (int i = 0; i < a.param_count; i += 1) {5893 for (int i = 0; i < a->param_count; i += 1) {
5885 FnTypeParamInfo *a_param_info = &a.param_info[i];5894 FnTypeParamInfo *a_param_info = &a->param_info[i];
5886 FnTypeParamInfo *b_param_info = &b.param_info[i];5895 FnTypeParamInfo *b_param_info = &b->param_info[i];
58875896
5888 if (a_param_info->type != b_param_info->type) {5897 if (a_param_info->type != b_param_info->type) {
5889 return false;5898 return false;
src/analyze.hpp+1-1
...@@ -23,7 +23,7 @@ TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits);...@@ -23,7 +23,7 @@ TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits);
23TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);23TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
24TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);24TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);
25TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type);25TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type);
26TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id);26TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
27TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type);27TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type);
28TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size);28TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size);
29TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import,29TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import,
src/parseh.cpp+7-2
...@@ -506,7 +506,12 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const...@@ -506,7 +506,12 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
506 }506 }
507 }507 }
508508
509 fn_type_id.param_info = allocate<FnTypeParamInfo>(fn_type_id.param_count);509 if (fn_type_id.param_count > fn_type_id_prealloc_param_info_count) {
510 fn_type_id.param_info = allocate_nonzero<FnTypeParamInfo>(fn_type_id.param_count);
511 } else {
512 fn_type_id.param_info = &fn_type_id.prealloc_param_info[0];
513 }
514
510 for (int i = 0; i < fn_type_id.param_count; i += 1) {515 for (int i = 0; i < fn_type_id.param_count; i += 1) {
511 QualType qt = fn_proto_ty->getParamType(i);516 QualType qt = fn_proto_ty->getParamType(i);
512 TypeTableEntry *param_type = resolve_qual_type(c, qt, decl);517 TypeTableEntry *param_type = resolve_qual_type(c, qt, decl);
...@@ -521,7 +526,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const...@@ -521,7 +526,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
521 param_info->is_noalias = qt.isRestrictQualified();526 param_info->is_noalias = qt.isRestrictQualified();
522 }527 }
523528
524 return get_fn_type(c->codegen, fn_type_id);529 return get_fn_type(c->codegen, &fn_type_id);
525 }530 }
526 case Type::Record:531 case Type::Record:
527 {532 {