Skip to content

Backport 21180 pshopify #570

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: v3.4.1-pshopify2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion iseq.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,19 @@ rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath)
rb_iseq_pathobj_new(path, realpath));
}

// Make a dummy iseq for a dummy frame that exposes a path for profilers to inspect
rb_iseq_t *
rb_iseq_alloc_with_dummy_path(VALUE fname)
{
rb_iseq_t *dummy_iseq = iseq_alloc();

ISEQ_BODY(dummy_iseq)->type = ISEQ_TYPE_TOP;
RB_OBJ_WRITE(dummy_iseq, &ISEQ_BODY(dummy_iseq)->location.pathobj, fname);
RB_OBJ_WRITE(dummy_iseq, &ISEQ_BODY(dummy_iseq)->location.label, fname);

return dummy_iseq;
}

static rb_iseq_location_t *
iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_code_location_t *code_location, const int node_id)
{
Expand Down Expand Up @@ -1749,6 +1762,7 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
1, NULL, 0, ISEQ_TYPE_TOP, &option,
Qnil));
rb_ast_dispose(ast);
RB_GC_GUARD(ast_value);

rb_vm_pop_frame(ec);
RB_GC_GUARD(v);
Expand Down Expand Up @@ -1916,7 +1930,11 @@ rb_iseqw_to_iseq(VALUE iseqw)
static VALUE
iseqw_eval(VALUE self)
{
return rb_iseq_eval(iseqw_check(self));
const rb_iseq_t *iseq = iseqw_check(self);
if (0 == ISEQ_BODY(iseq)->iseq_size) {
rb_raise(rb_eTypeError, "attempt to evaluate dummy InstructionSequence");
}
return rb_iseq_eval(iseq);
}

/*
Expand Down
13 changes: 13 additions & 0 deletions test/fiber/test_scheduler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,19 @@ def test_autoload
end
end

def test_iseq_compile_under_gc_stress_bug_21180
Thread.new do
scheduler = Scheduler.new
Fiber.set_scheduler scheduler

Fiber.schedule do
EnvUtil.under_gc_stress do
RubyVM::InstructionSequence.compile_file(File::NULL)
end
end
end.join
end

def test_deadlock
mutex = Thread::Mutex.new
condition = Thread::ConditionVariable.new
Expand Down
6 changes: 6 additions & 0 deletions test/ruby/test_iseq.rb
Original file line number Diff line number Diff line change
Expand Up @@ -919,4 +919,10 @@ def test_while_in_until_condition
assert_predicate(status, :success?)
end
end

def test_compile_empty_under_gc_stress
EnvUtil.under_gc_stress do
RubyVM::InstructionSequence.compile_file(File::NULL)
end
end
end
52 changes: 24 additions & 28 deletions vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3367,22 +3367,20 @@ rb_execution_context_update(rb_execution_context_t *ec)
}

while (cfp != limit_cfp) {
if (VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_DUMMY) {
const VALUE *ep = cfp->ep;
cfp->self = rb_gc_location(cfp->self);
cfp->iseq = (rb_iseq_t *)rb_gc_location((VALUE)cfp->iseq);
cfp->block_code = (void *)rb_gc_location((VALUE)cfp->block_code);

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)) {
VM_FORCE_WRITE(&prev_ep[VM_ENV_DATA_INDEX_ENV], rb_gc_location(prev_ep[VM_ENV_DATA_INDEX_ENV]));
}
const VALUE *ep = cfp->ep;
cfp->self = rb_gc_location(cfp->self);
cfp->iseq = (rb_iseq_t *)rb_gc_location((VALUE)cfp->iseq);
cfp->block_code = (void *)rb_gc_location((VALUE)cfp->block_code);

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)) {
VM_FORCE_WRITE(&prev_ep[VM_ENV_DATA_INDEX_ENV], rb_gc_location(prev_ep[VM_ENV_DATA_INDEX_ENV]));
}

if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED)) {
VM_FORCE_WRITE(&ep[VM_ENV_DATA_INDEX_ENV], rb_gc_location(ep[VM_ENV_DATA_INDEX_ENV]));
VM_FORCE_WRITE(&ep[VM_ENV_DATA_INDEX_ME_CREF], rb_gc_location(ep[VM_ENV_DATA_INDEX_ME_CREF]));
}
if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED)) {
VM_FORCE_WRITE(&ep[VM_ENV_DATA_INDEX_ENV], rb_gc_location(ep[VM_ENV_DATA_INDEX_ENV]));
VM_FORCE_WRITE(&ep[VM_ENV_DATA_INDEX_ME_CREF], rb_gc_location(ep[VM_ENV_DATA_INDEX_ME_CREF]));
}
}

Expand Down Expand Up @@ -3418,21 +3416,19 @@ 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));

if (VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_DUMMY) {
rb_gc_mark_movable(cfp->self);
rb_gc_mark_movable((VALUE)cfp->iseq);
rb_gc_mark_movable((VALUE)cfp->block_code);
rb_gc_mark_movable(cfp->self);
rb_gc_mark_movable((VALUE)cfp->iseq);
rb_gc_mark_movable((VALUE)cfp->block_code);

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]);
}
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]);
}

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]);
}
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]);
}
}

Expand Down
13 changes: 3 additions & 10 deletions vm_insnhelper.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,15 +469,8 @@ rb_vm_pop_frame(rb_execution_context_t *ec)
VALUE
rb_vm_push_frame_fname(rb_execution_context_t *ec, VALUE fname)
{
VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer();
void *ptr = ruby_xcalloc(sizeof(struct rb_iseq_constant_body) + sizeof(struct rb_iseq_struct), 1);
rb_imemo_tmpbuf_set_ptr(tmpbuf, ptr);

struct rb_iseq_struct *dmy_iseq = (struct rb_iseq_struct *)ptr;
struct rb_iseq_constant_body *dmy_body = (struct rb_iseq_constant_body *)&dmy_iseq[1];
dmy_iseq->body = dmy_body;
dmy_body->type = ISEQ_TYPE_TOP;
dmy_body->location.pathobj = fname;
rb_iseq_t *rb_iseq_alloc_with_dummy_path(VALUE fname);
rb_iseq_t *dmy_iseq = rb_iseq_alloc_with_dummy_path(fname);

vm_push_frame(ec,
dmy_iseq, //const rb_iseq_t *iseq,
Expand All @@ -490,7 +483,7 @@ rb_vm_push_frame_fname(rb_execution_context_t *ec, VALUE fname)
0, // int local_size,
0); // int stack_max

return tmpbuf;
return (VALUE)dmy_iseq;
}

/* method dispatch */
Expand Down
Loading