Skip to content

Commit

Permalink
Don't use special return for finalizer running
Browse files Browse the repository at this point in the history
For now, we'll handle this by checking if there's anything in the
finalizer queue each time we exit a frame. It's not ideal, in that it
costs something every frame exit, but it unblocks eliminating the
special return mechanism, which will in turn unlock removing many other
checks on frame exit, so it's a reasonable trade-off.
  • Loading branch information
jnthn committed Nov 3, 2021
1 parent 22e1926 commit 3b1d3cc
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 36 deletions.
2 changes: 2 additions & 0 deletions src/core/callstack.c
Expand Up @@ -732,6 +732,8 @@ MVMFrame * MVM_callstack_unwind_frame(MVMThreadContext *tc, MVMuint8 exceptional
MVM_panic(1, "Unknown call stack record type in unwind");
}
} while (tc->stack_top && !is_bytecode_frame(tc->stack_top->kind));
if (tc->num_finalizing && !exceptional && MVM_gc_finalize_run_handler(tc))
*thunked = 1;
return tc->stack_top ? MVM_callstack_record_to_frame(tc->stack_top) : NULL;
}

Expand Down
59 changes: 23 additions & 36 deletions src/gc/finalize.c
Expand Up @@ -26,39 +26,6 @@ void MVM_gc_finalize_add_to_queue(MVMThreadContext *tc, MVMObject *obj) {
tc->num_finalize++;
}

/* Sets the passed thread context's thread up so that we'll run a finalize
* handler on it in the near future. */
static void finalize_handler_caller(MVMThreadContext *tc, void *sr_data) {
MVMCode *handler = MVM_hll_current(tc)->finalize_handler;
if (handler) {
/* Drain the finalizing queue to an array. */
MVMObject *drain;
MVMROOT(tc, handler, {
drain = MVM_repr_alloc_init(tc, tc->instance->boot_types.BOOTArray);
while (tc->num_finalizing > 0)
MVM_repr_push_o(tc, drain, tc->finalizing[--tc->num_finalizing]);
});

/* Invoke the handler. */
MVMCallStackArgsFromC *args_record = MVM_callstack_allocate_args_from_c(tc,
MVM_callsite_get_common(tc, MVM_CALLSITE_ID_OBJ));
args_record->args.source[0].o = drain;
MVM_frame_dispatch_from_c(tc, handler, args_record, NULL, MVM_RETURN_VOID);
}
}
static void setup_finalize_handler_call(MVMThreadContext *tc) {
MVMFrame *install_on = tc->cur_frame;
while (install_on) {
if (!install_on->extra || !install_on->extra->special_return)
if (install_on->static_info->body.cu->body.hll_config)
break;
install_on = install_on->caller;
}
if (install_on)
MVM_frame_special_return(tc, install_on, finalize_handler_caller, NULL,
NULL, NULL);
}

/* Walks through the per-thread finalize queues, identifying objects that
* should be finalized, pushing them onto a finalize list, and then marking
* that list entry. Assumes the world is stopped. */
Expand Down Expand Up @@ -108,11 +75,31 @@ void MVM_finalize_walk_queues(MVMThreadContext *tc, MVMuint8 gen) {
while (cur_thread) {
if (cur_thread->body.tc) {
walk_thread_finalize_queue(cur_thread->body.tc, gen);
if (cur_thread->body.tc->num_finalizing > 0) {
if (cur_thread->body.tc->num_finalizing > 0)
MVM_gc_collect(cur_thread->body.tc, MVMGCWhatToDo_Finalizing, gen);
setup_finalize_handler_call(cur_thread->body.tc);
}
}
cur_thread = cur_thread->body.next;
}
}

/* Try to run a finalization handler. Returns a true value if we do so */
MVMint32 MVM_gc_finalize_run_handler(MVMThreadContext *tc) {
MVMCode *handler = MVM_hll_current(tc)->finalize_handler;
if (handler) {
/* Drain the finalizing queue to an array. */
MVMObject *drain;
MVMROOT(tc, handler, {
drain = MVM_repr_alloc_init(tc, tc->instance->boot_types.BOOTArray);
while (tc->num_finalizing > 0)
MVM_repr_push_o(tc, drain, tc->finalizing[--tc->num_finalizing]);
});

/* Invoke the handler. */
MVMCallStackArgsFromC *args_record = MVM_callstack_allocate_args_from_c(tc,
MVM_callsite_get_common(tc, MVM_CALLSITE_ID_OBJ));
args_record->args.source[0].o = drain;
MVM_frame_dispatch_from_c(tc, handler, args_record, NULL, MVM_RETURN_VOID);
return 1;
}
return 0;
}
1 change: 1 addition & 0 deletions src/gc/finalize.h
@@ -1,3 +1,4 @@
void MVM_gc_finalize_set(MVMThreadContext *tc, MVMObject *type, MVMint64 finalize);
void MVM_gc_finalize_add_to_queue(MVMThreadContext *tc, MVMObject *obj);
void MVM_finalize_walk_queues(MVMThreadContext *tc, MVMuint8 gen);
MVMint32 MVM_gc_finalize_run_handler(MVMThreadContext *tc);

0 comments on commit 3b1d3cc

Please sign in to comment.