mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 08:25:20 +08:00
Use mark context when marking execution_context
This commit is contained in:
1 parent
67cd6aa51a
commit
4c2968348e
9 files changed
+87
-79
Notes:
git
2026-10-16 16:34:24 +00:00
No files matched your search
@@ -1268,44 +1268,50 @@ cont_compact(void *ptr)
|
||||
}
|
||||
|
||||
static void
|
||||
cont_mark(void *ptr)
|
||||
cont_mark_ctx(const struct rb_gc_mark_ctx *ctx, rb_context_t *cont)
|
||||
{
|
||||
rb_context_t *cont = ptr;
|
||||
|
||||
RUBY_MARK_ENTER("cont");
|
||||
if (cont->self) {
|
||||
rb_gc_mark_movable(cont->self);
|
||||
rb_gc_mark_movable_ctx(ctx, cont->self);
|
||||
}
|
||||
rb_gc_mark_movable(cont->value);
|
||||
rb_gc_mark_movable_ctx(ctx, cont->value);
|
||||
|
||||
rb_execution_context_mark(&cont->saved_ec);
|
||||
rb_gc_mark(cont_thread_value(cont));
|
||||
rb_execution_context_mark_ctx(ctx, &cont->saved_ec);
|
||||
rb_gc_mark_ctx(ctx, cont_thread_value(cont));
|
||||
|
||||
if (cont->saved_vm_stack.ptr) {
|
||||
#ifdef CAPTURE_JUST_VALID_VM_STACK
|
||||
rb_gc_mark_locations(cont->saved_vm_stack.ptr,
|
||||
cont->saved_vm_stack.ptr + cont->saved_vm_stack.slen + cont->saved_vm_stack.clen);
|
||||
rb_gc_mark_locations_ctx(ctx, cont->saved_vm_stack.ptr,
|
||||
cont->saved_vm_stack.ptr + cont->saved_vm_stack.slen + cont->saved_vm_stack.clen);
|
||||
#else
|
||||
rb_gc_mark_locations(cont->saved_vm_stack.ptr,
|
||||
cont->saved_vm_stack.ptr, cont->saved_ec.stack_size);
|
||||
rb_gc_mark_locations_ctx(ctx, cont->saved_vm_stack.ptr,
|
||||
cont->saved_vm_stack.ptr, cont->saved_ec.stack_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cont->machine.stack) {
|
||||
if (cont->type == CONTINUATION_CONTEXT) {
|
||||
/* cont */
|
||||
rb_gc_mark_locations(cont->machine.stack,
|
||||
cont->machine.stack + cont->machine.stack_size);
|
||||
rb_gc_mark_locations_ctx(ctx, cont->machine.stack,
|
||||
cont->machine.stack + cont->machine.stack_size);
|
||||
}
|
||||
else {
|
||||
/* fiber machine context is marked as part of rb_execution_context_mark, no need to
|
||||
* do anything here. */
|
||||
/* fiber machine context is marked as part of rb_execution_context_mark_ctx, no need
|
||||
* to do anything here. */
|
||||
}
|
||||
}
|
||||
|
||||
RUBY_MARK_LEAVE("cont");
|
||||
}
|
||||
|
||||
static void
|
||||
cont_mark(void *ptr)
|
||||
{
|
||||
const struct rb_gc_mark_ctx ctx = rb_gc_current_mark_ctx();
|
||||
|
||||
cont_mark_ctx(&ctx, (rb_context_t *)ptr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
fiber_is_root_p(const rb_fiber_t *fiber)
|
||||
@@ -1382,9 +1388,9 @@ rb_fiber_update_self(rb_fiber_t *fiber)
|
||||
}
|
||||
|
||||
void
|
||||
rb_fiber_mark_self(const rb_fiber_t *fiber)
|
||||
rb_fiber_mark_self(const struct rb_gc_mark_ctx *ctx, const rb_fiber_t *fiber)
|
||||
{
|
||||
rb_gc_mark_movable(fiber->cont.self);
|
||||
rb_gc_mark_movable_ctx(ctx, fiber->cont.self);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1403,11 +1409,13 @@ static void
|
||||
fiber_mark(void *ptr)
|
||||
{
|
||||
rb_fiber_t *fiber = ptr;
|
||||
const struct rb_gc_mark_ctx ctx = rb_gc_current_mark_ctx();
|
||||
|
||||
RUBY_MARK_ENTER("cont");
|
||||
fiber_verify(fiber);
|
||||
rb_gc_mark_movable(fiber->first_proc);
|
||||
if (fiber->prev) rb_fiber_mark_self(fiber->prev);
|
||||
cont_mark(&fiber->cont);
|
||||
rb_gc_mark_movable_ctx(&ctx, fiber->first_proc);
|
||||
if (fiber->prev) rb_fiber_mark_self(&ctx, fiber->prev);
|
||||
cont_mark_ctx(&ctx, &fiber->cont);
|
||||
RUBY_MARK_LEAVE("cont");
|
||||
}
|
||||
|
||||
@@ -1901,7 +1909,7 @@ fiber_setcontext(rb_fiber_t *new_fiber, rb_fiber_t *old_fiber)
|
||||
}
|
||||
}
|
||||
|
||||
/* these values are used in rb_gc_mark_machine_context to mark the fiber's stack. */
|
||||
/* these values are used in rb_gc_mark_machine_context_ctx to mark the fiber's stack. */
|
||||
old_fiber->cont.saved_ec.machine.stack_start = th->ec->machine.stack_start;
|
||||
old_fiber->cont.saved_ec.machine.stack_end = FIBER_TERMINATED_P(old_fiber) ? NULL : th->ec->machine.stack_end;
|
||||
|
||||
|
||||
@@ -759,7 +759,7 @@ dump_output(struct dump_config *dc, VALUE output, VALUE full, VALUE since, VALUE
|
||||
// Mark functions generally can't handle these possibilities so
|
||||
// the usual IO code is unsafe in this context. (For example,
|
||||
// there are many ways to crash when ruby code runs and mutates
|
||||
// the execution context while rb_execution_context_mark() is in
|
||||
// the execution context while rb_execution_context_mark_ctx() is in
|
||||
// progress.)
|
||||
//
|
||||
// Using FILE* isn't perfect, but it avoids the most acute problems.
|
||||
|
||||
@@ -3431,11 +3431,9 @@ gc_mark_machine_context(const struct rb_gc_mark_ctx *ctx, const rb_execution_con
|
||||
}
|
||||
|
||||
void
|
||||
rb_gc_mark_machine_context(const rb_execution_context_t *ec)
|
||||
rb_gc_mark_machine_context_ctx(const struct rb_gc_mark_ctx *ctx, const rb_execution_context_t *ec)
|
||||
{
|
||||
const struct rb_gc_mark_ctx ctx = gc_current_mark_ctx();
|
||||
|
||||
gc_mark_machine_context(&ctx, ec);
|
||||
gc_mark_machine_context(ctx, ec);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
+2
-1
@@ -13,6 +13,7 @@
|
||||
#include "ccan/list/list.h" /* for list in rb_io_close_wait_list */
|
||||
|
||||
struct rb_execution_context_struct; /* in vm_core.h */
|
||||
struct rb_gc_mark_ctx; /* in internal/gc.h */
|
||||
struct rb_thread_struct; /* in vm_core.h */
|
||||
struct rb_io;
|
||||
|
||||
@@ -104,6 +105,6 @@ void rb_threadptr_interrupt_exec_task_mark(struct rb_thread_struct *th);
|
||||
|
||||
/* Mark the roots of the heap objects a thread owns, excluding ec and fiber. Used by
|
||||
* thread_mark and by the Ractor's local-root marking (rb_ractor_mark_local_roots). */
|
||||
void rb_thread_mark_owned_roots(struct rb_thread_struct *th);
|
||||
void rb_thread_mark_owned_roots(const struct rb_gc_mark_ctx *ctx, struct rb_thread_struct *th);
|
||||
|
||||
#endif /* INTERNAL_THREAD_H */
|
||||
@@ -243,30 +243,30 @@ mark_targeted_hook_list(st_data_t key, st_data_t value, st_data_t _arg)
|
||||
}
|
||||
|
||||
static void
|
||||
ractor_mark_thread(rb_thread_t *th)
|
||||
ractor_mark_thread(const struct rb_gc_mark_ctx *ctx, rb_thread_t *th)
|
||||
{
|
||||
rb_gc_mark(th->self);
|
||||
rb_gc_mark_ctx(ctx, th->self);
|
||||
|
||||
/* A thread's ec lives inside the root fiber struct and is freed with that
|
||||
* fiber's wrapper object, so keep the fiber wrappers alive from here too. */
|
||||
if (th->root_fiber) {
|
||||
VALUE root_fiber_self = rb_fiberptr_self(th->root_fiber);
|
||||
if (root_fiber_self) rb_gc_mark(root_fiber_self);
|
||||
if (root_fiber_self) rb_gc_mark_ctx(ctx, root_fiber_self);
|
||||
}
|
||||
/* The ec sits inside its fiber, so marking that fiber's wrapper scans the ec
|
||||
* as well. Only when there is no wrapper yet (mid-creation, teardown) does
|
||||
* the ec need marking of its own. */
|
||||
VALUE ec_fiber_self = (th->ec && th->ec->fiber_ptr) ? rb_fiberptr_self(th->ec->fiber_ptr) : 0;
|
||||
if (ec_fiber_self) {
|
||||
rb_gc_mark(ec_fiber_self);
|
||||
rb_gc_mark_ctx(ctx, ec_fiber_self);
|
||||
}
|
||||
else if (th->ec) {
|
||||
rb_execution_context_mark(th->ec);
|
||||
rb_execution_context_mark_ctx(ctx, th->ec);
|
||||
}
|
||||
|
||||
/* Root the thread's remaining possessions directly as well; thgroup in
|
||||
* particular has no other root. */
|
||||
rb_thread_mark_owned_roots(th);
|
||||
rb_thread_mark_owned_roots(ctx, th);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -295,7 +295,7 @@ ractor_mark_unshareable_parts(const struct rb_gc_mark_ctx *ctx, rb_ractor_t *r)
|
||||
rb_thread_t *th = 0;
|
||||
ccan_list_for_each(&r->threads.set, th, lt_node) {
|
||||
VM_ASSERT(th != NULL);
|
||||
ractor_mark_thread(th);
|
||||
ractor_mark_thread(ctx, th);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,7 +306,7 @@ ractor_mark_unshareable_parts(const struct rb_gc_mark_ctx *ctx, rb_ractor_t *r)
|
||||
* thread_mark walks whenever a terminated Thread's wrapper is still
|
||||
* referenced, and ractor_mark_thread performs the same marks. */
|
||||
rb_thread_t *dying_th = RUBY_ATOMIC_PTR_LOAD(r->threads.dying_th);
|
||||
if (dying_th) ractor_mark_thread(dying_th);
|
||||
if (dying_th) ractor_mark_thread(ctx, dying_th);
|
||||
|
||||
ractor_local_storage_mark(r);
|
||||
}
|
||||
|
||||
@@ -3918,12 +3918,12 @@ rb_execution_context_update(rb_execution_context_t *ec)
|
||||
static enum rb_id_table_iterator_result
|
||||
mark_local_storage_i(VALUE local, void *data)
|
||||
{
|
||||
rb_gc_mark(local);
|
||||
rb_gc_mark_ctx((const struct rb_gc_mark_ctx *)data, local);
|
||||
return ID_TABLE_CONTINUE;
|
||||
}
|
||||
|
||||
void
|
||||
rb_execution_context_mark(const rb_execution_context_t *ec)
|
||||
rb_execution_context_mark_ctx(const struct rb_gc_mark_ctx *ctx, const rb_execution_context_t *ec)
|
||||
{
|
||||
/* mark VM stack */
|
||||
if (ec->vm_stack) {
|
||||
@@ -3937,10 +3937,10 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
|
||||
if (rb_zjit_enabled_p) {
|
||||
// ZJIT leaves uninitialized slots on the VM stack, so we need
|
||||
// to mark such slots conservatively.
|
||||
rb_gc_mark_maybe(p[i]);
|
||||
rb_gc_mark_maybe_ctx(ctx, p[i]);
|
||||
}
|
||||
else {
|
||||
rb_gc_mark_movable(p[i]);
|
||||
rb_gc_mark_movable_ctx(ctx, p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3948,39 +3948,39 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
|
||||
const VALUE *ep = cfp->ep;
|
||||
VM_ASSERT(!!VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED) == vm_ep_in_heap_p_(ec, ep));
|
||||
|
||||
rb_gc_mark_movable(cfp->self);
|
||||
rb_gc_mark_movable_ctx(ctx, cfp->self);
|
||||
if (CFP_ZJIT_FRAME_P(cfp)) {
|
||||
const zjit_jit_frame_t *jit_frame = CFP_ZJIT_FRAME(cfp);
|
||||
rb_gc_mark_movable((VALUE)jit_frame->iseq);
|
||||
rb_gc_mark_movable_ctx(ctx, (VALUE)jit_frame->iseq);
|
||||
// materialize_block_code means cfp->block_code is lazy and may
|
||||
// still contain stale data from a previous frame. Otherwise it
|
||||
// was initialized by ZJIT and may have been written later by
|
||||
// vm_caller_setup_arg_block (ISEQ frames) or rb_iterate0 (C frames).
|
||||
if (!jit_frame->materialize_block_code) {
|
||||
rb_gc_mark_movable((VALUE)cfp->block_code);
|
||||
rb_gc_mark_movable_ctx(ctx, (VALUE)cfp->block_code);
|
||||
}
|
||||
}
|
||||
else {
|
||||
rb_gc_mark_movable((VALUE)cfp->_iseq);
|
||||
rb_gc_mark_movable((VALUE)cfp->block_code);
|
||||
rb_gc_mark_movable_ctx(ctx, (VALUE)cfp->_iseq);
|
||||
rb_gc_mark_movable_ctx(ctx, (VALUE)cfp->block_code);
|
||||
}
|
||||
|
||||
if (VM_ENV_LOCAL_P(ep) && VM_ENV_BOXED_P(ep)) {
|
||||
const rb_box_t *box = VM_ENV_BOX(ep);
|
||||
if (BOX_USER_P(box)) {
|
||||
rb_gc_mark_movable(box->box_object);
|
||||
rb_gc_mark_movable_ctx(ctx, box->box_object);
|
||||
}
|
||||
}
|
||||
|
||||
if (!VM_ENV_LOCAL_P(ep)) {
|
||||
const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
|
||||
if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) {
|
||||
rb_gc_mark_movable(prev_ep[VM_ENV_DATA_INDEX_ENV]);
|
||||
rb_gc_mark_movable_ctx(ctx, prev_ep[VM_ENV_DATA_INDEX_ENV]);
|
||||
}
|
||||
|
||||
if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED)) {
|
||||
rb_gc_mark_movable(ep[VM_ENV_DATA_INDEX_ENV]);
|
||||
rb_gc_mark(ep[VM_ENV_DATA_INDEX_ME_CREF]);
|
||||
rb_gc_mark_movable_ctx(ctx, ep[VM_ENV_DATA_INDEX_ENV]);
|
||||
rb_gc_mark_ctx(ctx, ep[VM_ENV_DATA_INDEX_ME_CREF]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3992,22 +3992,22 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
|
||||
if (ec->machine.stack_start && ec->machine.stack_end &&
|
||||
/* marked for current ec at the first stage of marking */
|
||||
ec != rb_gc_get_ec()) {
|
||||
rb_gc_mark_machine_context(ec);
|
||||
rb_gc_mark_machine_context_ctx(ctx, ec);
|
||||
}
|
||||
|
||||
rb_gc_mark(ec->errinfo);
|
||||
rb_gc_mark(ec->root_svar);
|
||||
rb_gc_mark_ctx(ctx, ec->errinfo);
|
||||
rb_gc_mark_ctx(ctx, ec->root_svar);
|
||||
if (ec->local_storage) {
|
||||
rb_id_table_foreach_values(ec->local_storage, mark_local_storage_i, NULL);
|
||||
rb_id_table_foreach_values(ec->local_storage, mark_local_storage_i, (void *)ctx);
|
||||
}
|
||||
rb_gc_mark(ec->local_storage_recursive_hash);
|
||||
rb_gc_mark(ec->local_storage_recursive_hash_for_trace);
|
||||
rb_gc_mark(ec->private_const_reference);
|
||||
rb_gc_mark_ctx(ctx, ec->local_storage_recursive_hash);
|
||||
rb_gc_mark_ctx(ctx, ec->local_storage_recursive_hash_for_trace);
|
||||
rb_gc_mark_ctx(ctx, ec->private_const_reference);
|
||||
|
||||
rb_gc_mark_movable(ec->storage);
|
||||
rb_gc_mark_movable_ctx(ctx, ec->storage);
|
||||
}
|
||||
|
||||
void rb_fiber_mark_self(rb_fiber_t *fib);
|
||||
void rb_fiber_mark_self(const struct rb_gc_mark_ctx *ctx, const rb_fiber_t *fib);
|
||||
void rb_fiber_update_self(rb_fiber_t *fib);
|
||||
void rb_threadptr_root_fiber_setup(rb_thread_t *th);
|
||||
void rb_root_fiber_obj_setup(rb_thread_t *th, void *objspace);
|
||||
@@ -4025,32 +4025,32 @@ thread_compact(void *ptr)
|
||||
* out of thread_mark so that a local GC can root them straight from the Ractor's
|
||||
* local roots (rb_ractor_mark_local_roots). */
|
||||
void
|
||||
rb_thread_mark_owned_roots(rb_thread_t *th)
|
||||
rb_thread_mark_owned_roots(const struct rb_gc_mark_ctx *ctx, rb_thread_t *th)
|
||||
{
|
||||
/* mark ruby objects */
|
||||
switch (th->invoke_type) {
|
||||
case thread_invoke_type_proc:
|
||||
case thread_invoke_type_ractor_proc:
|
||||
rb_gc_mark(th->invoke_arg.proc.proc);
|
||||
rb_gc_mark(th->invoke_arg.proc.args);
|
||||
rb_gc_mark_ctx(ctx, th->invoke_arg.proc.proc);
|
||||
rb_gc_mark_ctx(ctx, th->invoke_arg.proc.args);
|
||||
break;
|
||||
case thread_invoke_type_func:
|
||||
rb_gc_mark_maybe((VALUE)th->invoke_arg.func.arg);
|
||||
rb_gc_mark_maybe_ctx(ctx, (VALUE)th->invoke_arg.func.arg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rb_gc_mark(th->thgroup);
|
||||
rb_gc_mark(th->value);
|
||||
rb_gc_mark(th->pending_interrupt_queue);
|
||||
rb_gc_mark(th->pending_interrupt_mask_stack);
|
||||
rb_gc_mark(th->top_self);
|
||||
rb_gc_mark(th->top_wrapper);
|
||||
rb_gc_mark(th->last_status);
|
||||
rb_gc_mark(th->locking_mutex);
|
||||
rb_gc_mark(th->name);
|
||||
rb_gc_mark(th->scheduler);
|
||||
rb_gc_mark_ctx(ctx, th->thgroup);
|
||||
rb_gc_mark_ctx(ctx, th->value);
|
||||
rb_gc_mark_ctx(ctx, th->pending_interrupt_queue);
|
||||
rb_gc_mark_ctx(ctx, th->pending_interrupt_mask_stack);
|
||||
rb_gc_mark_ctx(ctx, th->top_self);
|
||||
rb_gc_mark_ctx(ctx, th->top_wrapper);
|
||||
rb_gc_mark_ctx(ctx, th->last_status);
|
||||
rb_gc_mark_ctx(ctx, th->locking_mutex);
|
||||
rb_gc_mark_ctx(ctx, th->name);
|
||||
rb_gc_mark_ctx(ctx, th->scheduler);
|
||||
|
||||
rb_threadptr_interrupt_exec_task_mark(th);
|
||||
}
|
||||
@@ -4059,22 +4059,23 @@ static void
|
||||
thread_mark(void *ptr)
|
||||
{
|
||||
rb_thread_t *th = ptr;
|
||||
const struct rb_gc_mark_ctx ctx = rb_gc_current_mark_ctx();
|
||||
RUBY_MARK_ENTER("thread");
|
||||
|
||||
// ec is null when setting up the thread in rb_threadptr_root_fiber_setup
|
||||
if (th->ec) {
|
||||
rb_fiber_mark_self(th->ec->fiber_ptr);
|
||||
rb_fiber_mark_self(&ctx, th->ec->fiber_ptr);
|
||||
}
|
||||
|
||||
/* A live thread wrapper keeps its Ractor object alive (and through its dfree the
|
||||
* rb_ractor_t), so an inherited Thread keeps a dead Ractor alive just as it does
|
||||
* upstream. */
|
||||
if (th->ractor) rb_gc_mark(rb_ractor_self(th->ractor));
|
||||
if (th->root_fiber) rb_fiber_mark_self(th->root_fiber);
|
||||
if (th->ractor) rb_gc_mark_ctx(&ctx, rb_ractor_self(th->ractor));
|
||||
if (th->root_fiber) rb_fiber_mark_self(&ctx, th->root_fiber);
|
||||
|
||||
RUBY_ASSERT(th->ec == NULL || th->ec == rb_fiberptr_get_ec(th->ec->fiber_ptr));
|
||||
|
||||
rb_thread_mark_owned_roots(th);
|
||||
rb_thread_mark_owned_roots(&ctx, th);
|
||||
|
||||
RUBY_MARK_LEAVE("thread");
|
||||
}
|
||||
|
||||
@@ -2125,7 +2125,7 @@ void rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE
|
||||
#define rb_vm_register_special_exception(sp, e, m) \
|
||||
rb_vm_register_special_exception_str(sp, e, rb_usascii_str_new_static((m), (rb_len_t)rb_strlen_lit(m)))
|
||||
|
||||
void rb_gc_mark_machine_context(const rb_execution_context_t *ec);
|
||||
void rb_gc_mark_machine_context_ctx(const struct rb_gc_mark_ctx *ctx, const rb_execution_context_t *ec);
|
||||
|
||||
const rb_callable_method_entry_t *rb_vm_frame_method_entry(const rb_control_frame_t *cfp);
|
||||
const rb_callable_method_entry_t *rb_vm_frame_method_entry_unchecked(const rb_control_frame_t *cfp);
|
||||
@@ -2362,7 +2362,7 @@ void rb_threadptr_pending_interrupt_enque(rb_thread_t *th, VALUE v);
|
||||
VALUE rb_ec_get_errinfo(const rb_execution_context_t *ec);
|
||||
void rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo);
|
||||
void rb_execution_context_update(rb_execution_context_t *ec);
|
||||
void rb_execution_context_mark(const rb_execution_context_t *ec);
|
||||
void rb_execution_context_mark_ctx(const struct rb_gc_mark_ctx *ctx, const rb_execution_context_t *ec);
|
||||
void rb_fiber_close(rb_fiber_t *fib);
|
||||
void Init_native_thread(rb_thread_t *th);
|
||||
int rb_vm_check_ints_blocking(rb_execution_context_t *ec);
|
||||
|
||||
@@ -17,7 +17,7 @@ typedef struct zjit_jit_frame {
|
||||
// Program counter for this frame, used for backtraces and GC.
|
||||
// NULL for C frames (they don't have a Ruby PC).
|
||||
const VALUE *pc;
|
||||
// The ISEQ this frame belongs to. Marked via rb_execution_context_mark.
|
||||
// The ISEQ this frame belongs to. Marked via rb_execution_context_mark_ctx.
|
||||
// NULL for C frames.
|
||||
const rb_iseq_t *iseq;
|
||||
// Whether to materialize block_code when this frame is materialized.
|
||||
|
||||
+1
-1
@@ -245,7 +245,7 @@ pub extern "C" fn rb_zjit_mark_all_executable() {
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn rb_zjit_root_mark() {
|
||||
// Mark iseq pointers in all JITFrames. JITFrames that are currently on the
|
||||
// stack are also marked via rb_execution_context_mark, but JITFrames not on
|
||||
// stack are also marked via rb_execution_context_mark_ctx, but JITFrames not on
|
||||
// the stack still need their iseqs kept alive because JIT code will reuse them.
|
||||
if !ZJITState::has_instance() {
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user