Feature #14370 » iseq_mark.diff
| compile.c | ||
|---|---|---|
|
#define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem))
|
||
|
#endif
|
||
|
static int
|
||
|
iseq_add_mark_object(const rb_iseq_t *iseq, VALUE v)
|
||
|
{
|
||
|
if (!SPECIAL_CONST_P(v)) {
|
||
|
rb_iseq_add_mark_object(iseq, v);
|
||
|
}
|
||
|
return COMPILE_OK;
|
||
|
}
|
||
|
static int
|
||
|
iseq_add_mark_object_compile_time(const rb_iseq_t *iseq, VALUE v)
|
||
|
{
|
||
| ... | ... | |
|
rb_iseq_path(iseq), rb_iseq_realpath(iseq),
|
||
|
INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option);
|
||
|
debugs("[new_child_iseq]< ---------------------------------------\n");
|
||
|
iseq_add_mark_object(iseq, (VALUE)ret_iseq);
|
||
|
iseq_add_mark_object_compile_time(iseq, (VALUE)ret_iseq);
|
||
|
return ret_iseq;
|
||
|
}
|
||
| ... | ... | |
|
rb_iseq_path(iseq), rb_iseq_realpath(iseq),
|
||
|
INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option);
|
||
|
debugs("[new_child_iseq_ifunc]< ---------------------------------------\n");
|
||
|
iseq_add_mark_object(iseq, (VALUE)ret_iseq);
|
||
|
iseq_add_mark_object_compile_time(iseq, (VALUE)ret_iseq);
|
||
|
return ret_iseq;
|
||
|
}
|
||
| ... | ... | |
|
switch (nd_type(val_node)) {
|
||
|
case NODE_LIT:
|
||
|
dv = val_node->nd_lit;
|
||
|
iseq_add_mark_object(iseq, dv);
|
||
|
break;
|
||
|
case NODE_NIL:
|
||
|
dv = Qnil;
|
||
| ... | ... | |
|
VALUE v = operands[j];
|
||
|
generated_iseq[code_index + 1 + j] = v;
|
||
|
/* to mark ruby object */
|
||
|
iseq_add_mark_object(iseq, v);
|
||
|
break;
|
||
|
}
|
||
|
case TS_IC: /* inline cache */
|
||
| ... | ... | |
|
entry->end = label_get_position((LABEL *)(ptr[2] & ~1));
|
||
|
entry->iseq = (rb_iseq_t *)ptr[3];
|
||
|
/* register iseq as mark object */
|
||
|
if (entry->iseq != 0) {
|
||
|
iseq_add_mark_object(iseq, (VALUE)entry->iseq);
|
||
|
}
|
||
|
/* stack depth */
|
||
|
if (ptr[4]) {
|
||
|
LABEL *lobj = (LABEL *)(ptr[4] & ~1);
|
||
| ... | ... | |
|
}
|
||
|
if (only_special_literals) {
|
||
|
iseq_add_mark_object(iseq, literals);
|
||
|
ADD_INSN(ret, nd_line(orig_node), dup);
|
||
|
ADD_INSN2(ret, nd_line(orig_node), opt_case_dispatch, literals, elselabel);
|
||
| ... | ... | |
|
}
|
||
|
loaded_iseq = rb_iseqw_to_iseq(iseqw);
|
||
|
iseq_add_mark_object(iseq, (VALUE)loaded_iseq);
|
||
|
return loaded_iseq;
|
||
|
}
|
||
| ... | ... | |
|
break;
|
||
|
case TS_VALUE:
|
||
|
argv[j] = op;
|
||
|
iseq_add_mark_object(iseq, op);
|
||
|
break;
|
||
|
case TS_ISEQ:
|
||
|
{
|
||
| ... | ... | |
|
}
|
||
|
RB_GC_GUARD(op);
|
||
|
argv[j] = map;
|
||
|
rb_iseq_add_mark_object(iseq, map);
|
||
|
}
|
||
|
break;
|
||
|
case TS_FUNCPTR:
|
||
| ... | ... | |
|
rb_ary_store(load->obj_list, (long)object_index, obj);
|
||
|
}
|
||
|
iseq_add_mark_object(load->iseq, obj);
|
||
|
return obj;
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
ibf_load_iseq_complete(iseq);
|
||
|
#endif /* !USE_LAZY_LOAD */
|
||
|
if (load->iseq) {
|
||
|
iseq_add_mark_object(load->iseq, (VALUE)iseq);
|
||
|
}
|
||
|
return iseq;
|
||
|
}
|
||
|
}
|
||
| iseq.c | ||
|---|---|---|
|
RUBY_FREE_LEAVE("iseq");
|
||
|
}
|
||
|
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
|
||
|
static int
|
||
|
rb_vm_insn_addr2insn2(const void *addr)
|
||
|
{
|
||
|
int insn;
|
||
|
const void * const *table = rb_vm_get_insns_address_table();
|
||
|
for (insn = 0; insn < VM_INSTRUCTION_SIZE; insn++) {
|
||
|
if (table[insn] == addr) {
|
||
|
return insn;
|
||
|
}
|
||
|
}
|
||
|
rb_bug("rb_vm_insn_addr2insn: invalid insn address: %p", addr);
|
||
|
}
|
||
|
#endif
|
||
|
typedef void iseq_value_itr_t(void *ctx, VALUE obj);
|
||
|
static int
|
||
|
iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void *data)
|
||
|
{
|
||
|
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
|
||
|
VALUE insn = rb_vm_insn_addr2insn2((void *)code[pos]);
|
||
|
#else
|
||
|
VALUE insn = code[pos];
|
||
|
#endif
|
||
|
int len = insn_len(insn);
|
||
|
int op_no;
|
||
|
const char *types = insn_op_types(insn);
|
||
|
for (op_no = 0; types[op_no]; op_no++) {
|
||
|
char type = types[op_no];
|
||
|
switch (type) {
|
||
|
case TS_CDHASH:
|
||
|
case TS_ISEQ:
|
||
|
case TS_VALUE:
|
||
|
{
|
||
|
VALUE op = code[pos + op_no + 1];
|
||
|
if (!SPECIAL_CONST_P(op)) {
|
||
|
func(data, op);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return len;
|
||
|
}
|
||
|
static void
|
||
|
rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data)
|
||
|
{
|
||
|
unsigned int size;
|
||
|
const VALUE *code;
|
||
|
size_t n;
|
||
|
size = iseq->body->iseq_size;
|
||
|
code = iseq->body->iseq_encoded;
|
||
|
for (n = 0; n < size;) {
|
||
|
n += iseq_extract_values(code, n, func, data);
|
||
|
}
|
||
|
}
|
||
|
static void
|
||
|
each_insn_value(void *ctx, VALUE obj)
|
||
|
{
|
||
|
rb_gc_mark(obj);
|
||
|
}
|
||
|
void
|
||
|
rb_iseq_mark(const rb_iseq_t *iseq)
|
||
|
{
|
||
| ... | ... | |
|
if (iseq->body) {
|
||
|
const struct rb_iseq_constant_body *body = iseq->body;
|
||
|
rb_iseq_each_value(iseq, each_insn_value, NULL);
|
||
|
RUBY_MARK_UNLESS_NULL(body->mark_ary);
|
||
|
rb_gc_mark(body->location.label);
|
||
|
rb_gc_mark(body->location.base_label);
|
||
|
rb_gc_mark(body->location.pathobj);
|
||
|
RUBY_MARK_UNLESS_NULL((VALUE)body->parent_iseq);
|
||
|
if (body->catch_table) {
|
||
|
const struct iseq_catch_table *table = body->catch_table;
|
||
|
unsigned int i;
|
||
|
for(i = 0; i < table->size; i++) {
|
||
|
const struct iseq_catch_table_entry *entry;
|
||
|
entry = &table->entries[i];
|
||
|
if (entry->iseq) {
|
||
|
rb_gc_mark((VALUE)entry->iseq);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (FL_TEST(iseq, ISEQ_NOT_LOADED_YET)) {
|
||
|
rb_gc_mark(iseq->aux.loader.obj);
|
||
|
}
|
||