Skip to content

Commit

Permalink
Pin instruction storage
Browse files Browse the repository at this point in the history
The operands in each instruction needs to be pinned because if
auto-compaction runs in iseq_set_sequence, then the objects could exist
on the generated_iseq buffer, which would not be reference updated which
can lead to T_MOVED (and subsequently T_NONE) objects on the iseq.
  • Loading branch information
peterzhu2118 committed Dec 2, 2023
1 parent 092a17e commit d169161
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 10 deletions.
16 changes: 8 additions & 8 deletions compile.c
Expand Up @@ -1375,7 +1375,7 @@ new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line)
}

static void
iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE *, VALUE), VALUE data)
iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE, VALUE), VALUE data)
{
const char *types = insn_op_types(insn->insn_id);
for (int j = 0; types[j]; j++) {
Expand All @@ -1386,7 +1386,7 @@ iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE *, VALUE), VALUE d
case TS_VALUE:
case TS_IC: // constant path array
case TS_CALLDATA: // ci is stored.
func(&OPERAND_AT(insn, j), data);
func(OPERAND_AT(insn, j), data);
break;
default:
break;
Expand All @@ -1395,9 +1395,9 @@ iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE *, VALUE), VALUE d
}

static void
iseq_insn_each_object_write_barrier(VALUE *obj_ptr, VALUE iseq)
iseq_insn_each_object_write_barrier(VALUE obj, VALUE iseq)
{
RB_OBJ_WRITTEN(iseq, Qundef, *obj_ptr);
RB_OBJ_WRITTEN(iseq, Qundef, obj);
}

static INSN *
Expand Down Expand Up @@ -10877,13 +10877,13 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords)
}

static void
iseq_insn_each_object_mark_and_move(VALUE *obj_ptr, VALUE _)
iseq_insn_each_object_mark_and_pin(VALUE obj, VALUE _)
{
rb_gc_mark_and_move(obj_ptr);
rb_gc_mark(obj);
}

void
rb_iseq_mark_and_move_insn_storage(struct iseq_compile_data_storage *storage)
rb_iseq_mark_and_pin_insn_storage(struct iseq_compile_data_storage *storage)
{
INSN *iobj = 0;
size_t size = sizeof(INSN);
Expand All @@ -10908,7 +10908,7 @@ rb_iseq_mark_and_move_insn_storage(struct iseq_compile_data_storage *storage)
iobj = (INSN *)&storage->buff[pos];

if (iobj->operands) {
iseq_insn_each_markable_object(iobj, iseq_insn_each_object_mark_and_move, (VALUE)0);
iseq_insn_each_markable_object(iobj, iseq_insn_each_object_mark_and_pin, (VALUE)0);
}
pos += (int)size;
}
Expand Down
9 changes: 8 additions & 1 deletion iseq.c
Expand Up @@ -393,7 +393,14 @@ rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating)
else if (FL_TEST_RAW((VALUE)iseq, ISEQ_USE_COMPILE_DATA)) {
const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq);

rb_iseq_mark_and_move_insn_storage(compile_data->insn.storage_head);
if (!reference_updating) {
/* The operands in each instruction needs to be pinned because
* if auto-compaction runs in iseq_set_sequence, then the objects
* could exist on the generated_iseq buffer, which would not be
* reference updated which can lead to T_MOVED (and subsequently
* T_NONE) objects on the iseq. */
rb_iseq_mark_and_pin_insn_storage(compile_data->insn.storage_head);
}

rb_gc_mark_and_move((VALUE *)&compile_data->err_info);
rb_gc_mark_and_move((VALUE *)&compile_data->catch_table_ary);
Expand Down
2 changes: 1 addition & 1 deletion iseq.h
Expand Up @@ -189,7 +189,7 @@ VALUE *rb_iseq_original_iseq(const rb_iseq_t *iseq);
void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc,
VALUE locals, VALUE args,
VALUE exception, VALUE body);
void rb_iseq_mark_and_move_insn_storage(struct iseq_compile_data_storage *arena);
void rb_iseq_mark_and_pin_insn_storage(struct iseq_compile_data_storage *arena);

VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt);
VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc);
Expand Down

0 comments on commit d169161

Please sign in to comment.