Skip to content

Commit

Permalink
Only create arg processing context if needed
Browse files Browse the repository at this point in the history
Most specialized frames do not need it, since they rewrite their
argument processing code into something far cheaper. We can also save
the cost of cleaning it up afterwards. On a benchmark doing quite a lot
of non-inlinable calls, this saved ~2% of the total CPU cycles, as
measured by callgrind.
  • Loading branch information
jnthn committed Sep 5, 2019
1 parent 5f177f5 commit 18654e8
Show file tree
Hide file tree
Showing 12 changed files with 1,019 additions and 50 deletions.
20 changes: 15 additions & 5 deletions src/core/args.c
Expand Up @@ -26,18 +26,28 @@ static void init_named_used(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuin
ctx->named_used.bit_field = 0;
}

/* Initialize arguments processing context. */
void MVM_args_proc_init(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMCallsite *callsite, MVMRegister *args) {
/* Stash callsite and argument counts/pointers. */
/* Store the callsite and args, but don't do any further args processing
* context setup work. Used when we just need enough to create it later. */
void MVM_args_proc_prepare(MVMArgProcContext *ctx, MVMCallsite *callsite, MVMRegister *args) {
ctx->callsite = callsite;
/* initial counts and values; can be altered by flatteners */
init_named_used(tc, ctx, MVM_callsite_num_nameds(tc, callsite));
ctx->args = args;
}

/* Finish setup of an argument processing context. Called if we deopt
* and need to complete the work. */
void MVM_args_proc_finish(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMCallsite *callsite, MVMRegister *args) {
init_named_used(tc, ctx, MVM_callsite_num_nameds(tc, callsite));
ctx->num_pos = callsite->num_pos;
ctx->arg_count = callsite->arg_count;
ctx->arg_flags = NULL; /* will be populated by flattener if needed */
}

/* Initialize arguments processing context. */
void MVM_args_proc_init(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMCallsite *callsite, MVMRegister *args) {
MVM_args_proc_prepare(ctx, callsite, args);
MVM_args_proc_finish(tc, ctx, callsite, args);
}

/* Clean up an arguments processing context. */
void MVM_args_proc_cleanup(MVMThreadContext *tc, MVMArgProcContext *ctx) {
if (ctx->arg_flags) {
Expand Down
2 changes: 2 additions & 0 deletions src/core/args.h
Expand Up @@ -47,6 +47,8 @@ struct MVMArgInfo {
};

/* Argument processing context handling. */
void MVM_args_proc_prepare(MVMArgProcContext *ctx, MVMCallsite *callsite, MVMRegister *args);
void MVM_args_proc_finish(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMCallsite *callsite, MVMRegister *args);
void MVM_args_proc_init(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMCallsite *callsite, MVMRegister *args);
void MVM_args_proc_cleanup(MVMThreadContext *tc, MVMArgProcContext *ctx);
void MVM_args_checkarity(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint16 min, MVMuint16 max);
Expand Down
15 changes: 11 additions & 4 deletions src/core/frame.c
Expand Up @@ -520,6 +520,12 @@ void MVM_frame_invoke(MVMThreadContext *tc, MVMStaticFrame *static_frame,
else {
chosen_bytecode = chosen_cand->bytecode;
}
/* Only set up args processing context if we really need it. If not,
* just store enough that we can create it later. */
if (chosen_cand->needs_arg_proc_context)
MVM_args_proc_init(tc, &frame->params, callsite, args);
else
MVM_args_proc_prepare(&frame->params, callsite, args);
frame->effective_spesh_slots = chosen_cand->spesh_slots;
frame->spesh_cand = chosen_cand;
}
Expand Down Expand Up @@ -557,6 +563,9 @@ void MVM_frame_invoke(MVMThreadContext *tc, MVMStaticFrame *static_frame,
});
}
}

/* Unspecialized code always needs an args processing context. */
MVM_args_proc_init(tc, &frame->params, callsite, args);
}

/* Store the code ref (NULL at the top-level). */
Expand All @@ -565,9 +574,6 @@ void MVM_frame_invoke(MVMThreadContext *tc, MVMStaticFrame *static_frame,
/* Outer. */
frame->outer = outer;

/* Initialize argument processing. */
MVM_args_proc_init(tc, &frame->params, callsite, args);

MVM_jit_code_trampoline(tc);

/* Update interpreter and thread context, so next execution will use this
Expand Down Expand Up @@ -886,7 +892,8 @@ static MVMuint64 remove_one_frame(MVMThreadContext *tc, MVMuint8 unwind) {

/* Clean up frame working space. */
if (returner->work) {
MVM_args_proc_cleanup(tc, &returner->params);
if (!returner->spesh_cand || returner->spesh_cand->needs_arg_proc_context)
MVM_args_proc_cleanup(tc, &returner->params);
MVM_fixed_size_free(tc, tc->instance->fsa, returner->allocd_work,
returner->work);
}
Expand Down
1 change: 1 addition & 0 deletions src/core/interp.h
Expand Up @@ -49,6 +49,7 @@ struct MVMOpInfo {
MVMuint8 jittivity : 2;
MVMuint8 uses_hll : 1;
MVMuint8 specializable : 1;
MVMuint8 uses_params : 1;
MVMuint8 operands[MVM_MAX_OPERANDS];
};

Expand Down
74 changes: 38 additions & 36 deletions src/core/oplist
Expand Up @@ -55,6 +55,8 @@
# * :specializable means that the op is possible to optimize through type
# specialization (a frame that has no such ops will only ever get a certain
# specialization)
# * :usesparams means that this is a param processing op, which needs the frame
# to have an arg processing context set up

no_op :confprog
const_i8 w(int8) int8 :pure
Expand Down Expand Up @@ -196,25 +198,25 @@ invoke_i -a w(int64) r(obj) :deoptallpoint :maycausedeopt :specializable
invoke_n -a w(num64) r(obj) :deoptallpoint :maycausedeopt :specializable
invoke_s -a w(str) r(obj) :deoptallpoint :maycausedeopt :specializable
invoke_o -a w(obj) r(obj) :deoptallpoint :deoptonepoint :logged :maycausedeopt :specializable
checkarity int16 int16
param_rp_i .p w(int64) int16 :pure :noinline
param_rp_n .p w(num64) int16 :pure :noinline
param_rp_s .p w(str) int16 :pure :noinline
param_rp_o .p w(obj) int16 :pure :noinline :useshll
param_op_i .p w(int64) int16 ins :pure :noinline
param_op_n .p w(num64) int16 ins :pure :noinline
param_op_s .p w(str) int16 ins :pure :noinline
param_op_o .p w(obj) int16 ins :pure :noinline :useshll
param_rn_i w(int64) str :noinline
param_rn_n w(num64) str :noinline
param_rn_s w(str) str :noinline
param_rn_o w(obj) str :noinline :useshll
param_on_i w(int64) str ins :noinline
param_on_n w(num64) str ins :noinline
param_on_s w(str) str ins :noinline
param_on_o w(obj) str ins :noinline :useshll
param_sp .p w(obj) int16 :pure :noinline :useshll
param_sn w(obj) :noinline :useshll
checkarity int16 int16 :usesparams
param_rp_i .p w(int64) int16 :pure :noinline :usesparams
param_rp_n .p w(num64) int16 :pure :noinline :usesparams
param_rp_s .p w(str) int16 :pure :noinline :usesparams
param_rp_o .p w(obj) int16 :pure :noinline :useshll :usesparams
param_op_i .p w(int64) int16 ins :pure :noinline :usesparams
param_op_n .p w(num64) int16 ins :pure :noinline :usesparams
param_op_s .p w(str) int16 ins :pure :noinline :usesparams
param_op_o .p w(obj) int16 ins :pure :noinline :useshll :usesparams
param_rn_i w(int64) str :noinline :usesparams
param_rn_n w(num64) str :noinline :usesparams
param_rn_s w(str) str :noinline :usesparams
param_rn_o w(obj) str :noinline :useshll :usesparams
param_on_i w(int64) str ins :noinline :usesparams
param_on_n w(num64) str ins :noinline :usesparams
param_on_s w(str) str ins :noinline :usesparams
param_on_o w(obj) str ins :noinline :useshll :usesparams
param_sp .p w(obj) int16 :pure :noinline :useshll :usesparams
param_sn w(obj) :noinline :useshll :usesparams
getcode w(obj) coderef :pure
caller w(obj) r(int64) :pure :noinline
capturelex r(obj) :noinline
Expand All @@ -239,8 +241,8 @@ takehandlerresult w(obj)
DEPRECATED_33 w(obj) ins
DEPRECATED_34 w(obj) r(obj)
backtracestrings w(obj) r(obj) :pure
usecapture w(obj) :noinline
savecapture w(obj) :noinline
usecapture w(obj) :noinline :usesparams
savecapture w(obj) :noinline :usesparams
captureposelems w(int64) r(obj) :pure
captureposarg w(obj) r(obj) r(int64) :pure :useshll
captureposarg_i w(int64) r(obj) r(int64) :pure
Expand Down Expand Up @@ -616,7 +618,7 @@ randscale_n w(num64) r(num64)
uniisblock w(int64) r(str) r(int64) r(str) :pure
assertparamcheck r(int64) :noinline :invokish :maycausedeopt
hintfor w(int64) r(obj) r(str)
paramnamesused :noinline
paramnamesused :noinline :usesparams
getuniname w(str) r(int64) :pure
getuniprop_int w(int64) r(int64) r(int64) :pure
getuniprop_bool w(int64) r(int64) r(int64) :pure
Expand Down Expand Up @@ -658,14 +660,14 @@ execname w(str)
const_i64_16 w(int64) int16 :pure :confprog
const_i64_32 w(int64) int32 :pure :confprog
isnonnull w(int64) r(obj) :pure :specializable
param_rn2_i w(int64) str str :noinline
param_rn2_n w(num64) str str :noinline
param_rn2_s w(str) str str :noinline
param_rn2_o w(obj) str str :noinline :useshll
param_on2_i w(int64) str str ins :noinline
param_on2_n w(num64) str str ins :noinline
param_on2_s w(str) str str ins :noinline
param_on2_o w(obj) str str ins :noinline :useshll
param_rn2_i w(int64) str str :noinline :usesparams
param_rn2_n w(num64) str str :noinline :usesparams
param_rn2_s w(str) str str :noinline :usesparams
param_rn2_o w(obj) str str :noinline :useshll :usesparams
param_on2_i w(int64) str str ins :noinline :usesparams
param_on2_n w(num64) str str ins :noinline :usesparams
param_on2_s w(str) str str ins :noinline :usesparams
param_on2_o w(obj) str str ins :noinline :useshll :usesparams
osrpoint :osrpoint
nativecallcast w(obj) r(obj) r(obj) r(obj)
spawnprocasync w(obj) r(obj) r(obj) r(str) r(obj) r(obj)
Expand Down Expand Up @@ -788,12 +790,12 @@ getlexref_u w(obj) rl(uint64) :pure :noinline :useshll
getlexref_u32 w(obj) rl(uint32) :pure :noinline :useshll
getlexref_u16 w(obj) rl(uint16) :pure :noinline :useshll
getlexref_u8 w(obj) rl(uint8) :pure :noinline :useshll
param_rp_u w(uint64) int16 :pure :noinline
param_op_u w(uint64) int16 ins :pure :noinline
param_rn_u w(uint64) str :noinline
param_on_u w(uint64) str ins :noinline
param_rn2_u w(uint64) str str :noinline
param_on2_u w(uint64) str str ins :noinline
param_rp_u w(uint64) int16 :pure :noinline :usesparams
param_op_u w(uint64) int16 ins :pure :noinline :usesparams
param_rn_u w(uint64) str :noinline :usesparams
param_on_u w(uint64) str ins :noinline :usesparams
param_rn2_u w(uint64) str str :noinline :usesparams
param_on2_u w(uint64) str str ins :noinline :usesparams
stat_time w(num64) r(str) r(int64)
lstat_time w(num64) r(str) r(int64)
setdebugtypename r(obj) r(str)
Expand Down

0 comments on commit 18654e8

Please sign in to comment.