diff --git a/compile.c b/compile.c index 9ba55e5bc7..f441b7dca5 100644 --- a/compile.c +++ b/compile.c @@ -8952,6 +8952,57 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords) return keyword; } +void +rb_iseq_mark_insn_storage(struct iseq_compile_data_storage *storage) +{ + INSN *iobj = 0; + size_t size = sizeof(INSN); + unsigned int pos = 0; + + while (storage) { +#ifdef STRICT_ALIGNMENT + size_t padding = calc_padding((void *)&storage->buff[pos], size); +#else + const size_t padding = 0; /* expected to be optimized by compiler */ +#endif /* STRICT_ALIGNMENT */ + size_t offset = pos + size + padding; + if (offset > storage->size || offset > storage->pos) { + pos = 0; + storage = storage->next; + } else { +#ifdef STRICT_ALIGNMENT + pos += (int)padding; +#endif /* STRICT_ALIGNMENT */ + + iobj = (INSN *)&storage->buff[pos]; + + if (iobj->operands) { + int j; + const char *types = insn_op_types(iobj->insn_id); + + for(j = 0; types[j]; j++) { + char type = types[j]; + switch(type) { + case TS_CDHASH: + case TS_ISEQ: + case TS_VALUE: + { + VALUE op = OPERAND_AT(iobj, j); + if (!SPECIAL_CONST_P(op)) { + rb_gc_mark(op); + } + break; + } + default: + break; + } + } + } + pos += (int)size; + } + } +} + void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, VALUE exception, VALUE body) diff --git a/iseq.c b/iseq.c index b5417cba19..f76b350056 100644 --- a/iseq.c +++ b/iseq.c @@ -336,6 +336,9 @@ rb_iseq_mark(const rb_iseq_t *iseq) } else if (FL_TEST_RAW(iseq, ISEQ_USE_COMPILE_DATA)) { const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq); + + rb_iseq_mark_insn_storage(compile_data->insn.storage_head); + if (RTEST(compile_data->mark_ary)) { rb_gc_mark(compile_data->mark_ary); } diff --git a/iseq.h b/iseq.h index 8bb4f30b4b..f1d446ccb7 100644 --- a/iseq.h +++ b/iseq.h @@ -174,6 +174,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_insn_storage(struct iseq_compile_data_storage *arena); /* iseq.c */ VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt);