@TypeOf avoids heap allocation for only 1 parameter

This commit is contained in:
Andrew Kelley 2020-03-04 17:43:23 -05:00
parent 2e3e8d0c74
commit 3e3d464884
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
3 changed files with 48 additions and 21 deletions

View File

@ -3286,7 +3286,10 @@ struct IrInstGenUnreachable {
struct IrInstSrcTypeOf {
IrInstSrc base;
IrInstSrc **values;
union {
IrInstSrc *scalar; // value_count == 1
IrInstSrc **list; // value_count > 1
} value;
size_t value_count;
};

View File

@ -2766,9 +2766,13 @@ static IrInstGen *ir_build_load_ptr_gen(IrAnalyze *ira, IrInst *source_instructi
return &instruction->base;
}
static IrInstSrc *ir_build_typeof(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc **values, size_t value_count) {
static IrInstSrc *ir_build_typeof_n(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
IrInstSrc **values, size_t value_count)
{
assert(value_count >= 2);
IrInstSrcTypeOf *instruction = ir_build_instruction<IrInstSrcTypeOf>(irb, scope, source_node);
instruction->values = values;
instruction->value.list = values;
instruction->value_count = value_count;
for (size_t i = 0; i < value_count; i++)
@ -2777,6 +2781,15 @@ static IrInstSrc *ir_build_typeof(IrBuilderSrc *irb, Scope *scope, AstNode *sour
return &instruction->base;
}
static IrInstSrc *ir_build_typeof_1(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) {
IrInstSrcTypeOf *instruction = ir_build_instruction<IrInstSrcTypeOf>(irb, scope, source_node);
instruction->value.scalar = value;
ir_ref_instruction(value, irb->current_basic_block);
return &instruction->base;
}
static IrInstSrc *ir_build_set_cold(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *is_cold) {
IrInstSrcSetCold *instruction = ir_build_instruction<IrInstSrcSetCold>(irb, scope, source_node);
instruction->is_cold = is_cold;
@ -6045,9 +6058,7 @@ static IrInstSrc *ir_gen_fn_call_with_args(IrBuilderSrc *irb, Scope *scope, AstN
if (fn_ref == irb->codegen->invalid_inst_src)
return fn_ref;
IrInstSrc **typeof_args = heap::c_allocator.allocate<IrInstSrc*>(1);
typeof_args[0] = fn_ref;
IrInstSrc *fn_type = ir_build_typeof(irb, scope, source_node, typeof_args, 1);
IrInstSrc *fn_type = ir_build_typeof_1(irb, scope, source_node, fn_ref);
IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(args_len);
for (size_t i = 0; i < args_len; i += 1) {
@ -6110,22 +6121,31 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
size_t arg_count = node->data.fn_call_expr.params.length;
if (arg_count < 1) {
IrInstSrc *type_of;
if (arg_count == 0) {
add_node_error(irb->codegen, node,
buf_sprintf("expected at least 1 argument, found 0"));
return irb->codegen->invalid_inst_src;
}
} else if (arg_count == 1) {
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, sub_scope);
if (arg0_value == irb->codegen->invalid_inst_src)
return arg0_value;
IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(arg_count);
for (size_t i = 0; i < arg_count; i += 1) {
AstNode *arg_node = node->data.fn_call_expr.params.at(i);
IrInstSrc *arg = ir_gen_node(irb, arg_node, sub_scope);
if (arg == irb->codegen->invalid_inst_src)
return irb->codegen->invalid_inst_src;
args[i] = arg;
}
type_of = ir_build_typeof_1(irb, scope, node, arg0_value);
} else {
IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(arg_count);
for (size_t i = 0; i < arg_count; i += 1) {
AstNode *arg_node = node->data.fn_call_expr.params.at(i);
IrInstSrc *arg = ir_gen_node(irb, arg_node, sub_scope);
if (arg == irb->codegen->invalid_inst_src)
return irb->codegen->invalid_inst_src;
args[i] = arg;
}
IrInstSrc *type_of = ir_build_typeof(irb, scope, node, args, arg_count);
type_of = ir_build_typeof_n(irb, scope, node, args, arg_count);
}
return ir_lval_wrap(irb, scope, type_of, lval, result_loc);
}
case BuiltinFnIdSetCold:
@ -21684,11 +21704,11 @@ static IrInstGen *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstSrcTypeOf
// Fast path for the common case of TypeOf with a single argument
if (value_count < 2) {
type_entry = typeof_instruction->values[0]->child->value->type;
type_entry = typeof_instruction->value.scalar->child->value->type;
} else {
IrInstGen **args = heap::c_allocator.allocate<IrInstGen*>(value_count);
for (size_t i = 0; i < value_count; i += 1) {
IrInstGen *value = typeof_instruction->values[i]->child;
IrInstGen *value = typeof_instruction->value.list[i]->child;
if (type_is_invalid(value->value->type))
return ira->codegen->invalid_inst_gen;
args[i] = value;

View File

@ -1118,8 +1118,12 @@ static void ir_print_vector_store_elem(IrPrintGen *irp, IrInstGenVectorStoreElem
static void ir_print_typeof(IrPrintSrc *irp, IrInstSrcTypeOf *instruction) {
fprintf(irp->f, "@TypeOf(");
for (size_t i = 0; i < instruction->value_count; i += 1) {
ir_print_other_inst_src(irp, instruction->values[i]);
if (instruction->value_count == 1) {
ir_print_other_inst_src(irp, instruction->value.scalar);
} else {
for (size_t i = 0; i < instruction->value_count; i += 1) {
ir_print_other_inst_src(irp, instruction->value.list[i]);
}
}
fprintf(irp->f, ")");
}