Skip to content

Commit

Permalink
Eliminate redundant checks/logic during return
Browse files Browse the repository at this point in the history
Thanks to having a callstack record type to indicate the boundary of a
nested runloop (used in NativeCall callbacks), we no longer need to
explicitly check for the threaded interpreter boundary anywhere. We can
return NULL from the callstack unwind function, upon encountering the
native call boundary, to indicate interpreter exit instead. This gets
rid of a bunch of logic in remove_one_frame, and a little logic in
exit_frame.
  • Loading branch information
jnthn committed Nov 3, 2021
1 parent 92e829c commit b6523de
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 29 deletions.
15 changes: 4 additions & 11 deletions src/core/callstack.c
Expand Up @@ -569,7 +569,7 @@ static void handle_end_of_dispatch_record(MVMThreadContext *tc, MVMuint32 *thunk
}
static void exit_frame(MVMThreadContext *tc, MVMFrame *returner) {
MVMFrame *caller = returner->caller;
if (caller && (returner != tc->thread_entry_frame || tc->nested_interpreter)) {
if (caller) {
if (tc->jit_return_address != NULL) {
/* on a JIT frame, exit to interpreter afterwards */
MVMJitCode *jitcode = returner->spesh_cand->body.jitcode;
Expand All @@ -579,20 +579,12 @@ static void exit_frame(MVMThreadContext *tc, MVMFrame *returner) {
tc->jit_return_address = NULL;
}

tc->cur_frame = caller;

/* Always sync these up in case of an exception throw in a C
* function dispatcher that comes after a bytecode dispatcher.
* It is a little wasteful since we repeat it in frame.c's
* remove_one_frame, in that case for the sake of lazy deopt. */
*(tc->interp_cur_op) = caller->return_address;
*(tc->interp_bytecode_start) = MVM_frame_effective_bytecode(caller);
*(tc->interp_reg_base) = caller->work;
*(tc->interp_cu) = caller->static_info->body.cu;
}
else {
tc->cur_frame = NULL;
}
tc->cur_frame = caller;
}
static void handle_bind_control(MVMThreadContext *tc, MVMCallStackBindControl *control_record,
MVMRegister *flag_ptr) {
Expand Down Expand Up @@ -702,7 +694,8 @@ MVMFrame * MVM_callstack_unwind_frame(MVMThreadContext *tc, MVMuint8 exceptional
break;
}
case MVM_CALLSTACK_RECORD_NESTED_RUNLOOP: {
return ((MVMCallStackNestedRunloop*)tc->stack_top)->cur_frame;
/* Return NULL to signal to exit the nested runloop. */
return NULL;
}
case MVM_CALLSTACK_RECORD_SPECIAL_RETURN: {
/* Read the callback info, and then remove this record (as we
Expand Down
19 changes: 1 addition & 18 deletions src/core/frame.c
Expand Up @@ -900,24 +900,7 @@ static MVMuint64 remove_one_frame(MVMThreadContext *tc, MVMuint8 unwind) {
}
if (thunked)
return 1;

/* Switch back to the caller frame if there is one. */
if (caller && (returner != tc->thread_entry_frame || tc->nested_interpreter)) {
if (returner == tc->thread_entry_frame && tc->cur_frame == caller) {
tc->cur_frame = NULL;
return 0;
}
else {
/* We're either somewhere in a nested call or already up in the top
most frame but still need to run some finalizer, so keep the
runloop running */
return 1;
}
}
else {
tc->cur_frame = NULL;
return 0;
}
return caller != NULL;
}

/* Attempt to return from the current frame. Returns non-zero if we can,
Expand Down

0 comments on commit b6523de

Please sign in to comment.