iseq_mark.diff
compile.c | ||
---|---|---|
562 | 562 |
#define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem)) |
563 | 563 |
#endif |
564 | 564 | |
565 |
static int |
|
566 |
iseq_add_mark_object(const rb_iseq_t *iseq, VALUE v) |
|
567 |
{ |
|
568 |
if (!SPECIAL_CONST_P(v)) { |
|
569 |
rb_iseq_add_mark_object(iseq, v); |
|
570 |
} |
|
571 |
return COMPILE_OK; |
|
572 |
} |
|
573 | ||
574 | 565 |
static int |
575 | 566 |
iseq_add_mark_object_compile_time(const rb_iseq_t *iseq, VALUE v) |
576 | 567 |
{ |
... | ... | |
749 | 740 |
encoded[i] = (VALUE)table[insn]; |
750 | 741 |
i += len; |
751 | 742 |
} |
743 |
FL_SET(iseq, ISEQ_TRANSLATED); |
|
752 | 744 |
#endif |
753 | 745 |
return COMPILE_OK; |
754 | 746 |
} |
... | ... | |
1235 | 1227 |
rb_iseq_path(iseq), rb_iseq_realpath(iseq), |
1236 | 1228 |
INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option); |
1237 | 1229 |
debugs("[new_child_iseq]< ---------------------------------------\n"); |
1238 |
iseq_add_mark_object(iseq, (VALUE)ret_iseq); |
|
1230 |
iseq_add_mark_object_compile_time(iseq, (VALUE)ret_iseq);
|
|
1239 | 1231 |
return ret_iseq; |
1240 | 1232 |
} |
1241 | 1233 | |
... | ... | |
1250 | 1242 |
rb_iseq_path(iseq), rb_iseq_realpath(iseq), |
1251 | 1243 |
INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option); |
1252 | 1244 |
debugs("[new_child_iseq_ifunc]< ---------------------------------------\n"); |
1253 |
iseq_add_mark_object(iseq, (VALUE)ret_iseq); |
|
1245 |
iseq_add_mark_object_compile_time(iseq, (VALUE)ret_iseq);
|
|
1254 | 1246 |
return ret_iseq; |
1255 | 1247 |
} |
1256 | 1248 | |
... | ... | |
1501 | 1493 |
switch (nd_type(val_node)) { |
1502 | 1494 |
case NODE_LIT: |
1503 | 1495 |
dv = val_node->nd_lit; |
1504 |
iseq_add_mark_object(iseq, dv); |
|
1505 | 1496 |
break; |
1506 | 1497 |
case NODE_NIL: |
1507 | 1498 |
dv = Qnil; |
... | ... | |
2044 | 2035 |
VALUE v = operands[j]; |
2045 | 2036 |
generated_iseq[code_index + 1 + j] = v; |
2046 | 2037 |
/* to mark ruby object */ |
2047 |
iseq_add_mark_object(iseq, v); |
|
2048 | 2038 |
break; |
2049 | 2039 |
} |
2050 | 2040 |
case TS_IC: /* inline cache */ |
... | ... | |
2209 | 2199 |
entry->end = label_get_position((LABEL *)(ptr[2] & ~1)); |
2210 | 2200 |
entry->iseq = (rb_iseq_t *)ptr[3]; |
2211 | 2201 | |
2212 |
/* register iseq as mark object */ |
|
2213 |
if (entry->iseq != 0) { |
|
2214 |
iseq_add_mark_object(iseq, (VALUE)entry->iseq); |
|
2215 |
} |
|
2216 | ||
2217 | 2202 |
/* stack depth */ |
2218 | 2203 |
if (ptr[4]) { |
2219 | 2204 |
LABEL *lobj = (LABEL *)(ptr[4] & ~1); |
... | ... | |
4790 | 4775 |
} |
4791 | 4776 | |
4792 | 4777 |
if (only_special_literals) { |
4793 |
iseq_add_mark_object(iseq, literals); |
|
4778 |
iseq_add_mark_object_compile_time(iseq, literals);
|
|
4794 | 4779 | |
4795 | 4780 |
ADD_INSN(ret, nd_line(orig_node), dup); |
4796 | 4781 |
ADD_INSN2(ret, nd_line(orig_node), opt_case_dispatch, literals, elselabel); |
... | ... | |
7505 | 7490 |
} |
7506 | 7491 | |
7507 | 7492 |
loaded_iseq = rb_iseqw_to_iseq(iseqw); |
7508 |
iseq_add_mark_object(iseq, (VALUE)loaded_iseq); |
|
7509 | 7493 |
return loaded_iseq; |
7510 | 7494 |
} |
7511 | 7495 | |
... | ... | |
7636 | 7620 |
break; |
7637 | 7621 |
case TS_VALUE: |
7638 | 7622 |
argv[j] = op; |
7639 |
iseq_add_mark_object(iseq, op); |
|
7640 | 7623 |
break; |
7641 | 7624 |
case TS_ISEQ: |
7642 | 7625 |
{ |
... | ... | |
7683 | 7666 |
} |
7684 | 7667 |
RB_GC_GUARD(op); |
7685 | 7668 |
argv[j] = map; |
7686 |
rb_iseq_add_mark_object(iseq, map); |
|
7687 | 7669 |
} |
7688 | 7670 |
break; |
7689 | 7671 |
case TS_FUNCPTR: |
... | ... | |
9285 | 9267 | |
9286 | 9268 |
rb_ary_store(load->obj_list, (long)object_index, obj); |
9287 | 9269 |
} |
9288 |
iseq_add_mark_object(load->iseq, obj); |
|
9289 | 9270 |
return obj; |
9290 | 9271 |
} |
9291 | 9272 |
} |
... | ... | |
9470 | 9451 |
ibf_load_iseq_complete(iseq); |
9471 | 9452 |
#endif /* !USE_LAZY_LOAD */ |
9472 | 9453 | |
9473 |
if (load->iseq) { |
|
9474 |
iseq_add_mark_object(load->iseq, (VALUE)iseq); |
|
9475 |
} |
|
9476 | 9454 |
return iseq; |
9477 | 9455 |
} |
9478 | 9456 |
} |
iseq.c | ||
---|---|---|
113 | 113 |
RUBY_FREE_LEAVE("iseq"); |
114 | 114 |
} |
115 | 115 | |
116 |
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE |
|
117 |
static int |
|
118 |
rb_vm_insn_addr2insn2(const void *addr) |
|
119 |
{ |
|
120 |
int insn; |
|
121 |
const void * const *table = rb_vm_get_insns_address_table(); |
|
122 | ||
123 |
for (insn = 0; insn < VM_INSTRUCTION_SIZE; insn++) { |
|
124 |
if (table[insn] == addr) { |
|
125 |
return insn; |
|
126 |
} |
|
127 |
} |
|
128 |
rb_bug("rb_vm_insn_addr2insn: invalid insn address: %p", addr); |
|
129 |
} |
|
130 |
#endif |
|
131 | ||
132 |
static int |
|
133 |
rb_vm_insn_null_translator(const void *addr) |
|
134 |
{ |
|
135 |
return (int)addr; |
|
136 |
} |
|
137 | ||
138 |
typedef void iseq_value_itr_t(void *ctx, VALUE obj); |
|
139 |
typedef int rb_vm_insns_translator_t(const void *addr); |
|
140 | ||
141 |
static int |
|
142 |
iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void *data, rb_vm_insns_translator_t * translator) |
|
143 |
{ |
|
144 |
VALUE insn = translator((void *)code[pos]); |
|
145 |
int len = insn_len(insn); |
|
146 |
int op_no; |
|
147 |
const char *types = insn_op_types(insn); |
|
148 | ||
149 |
for (op_no = 0; types[op_no]; op_no++) { |
|
150 |
char type = types[op_no]; |
|
151 |
switch (type) { |
|
152 |
case TS_CDHASH: |
|
153 |
case TS_ISEQ: |
|
154 |
case TS_VALUE: |
|
155 |
{ |
|
156 |
VALUE op = code[pos + op_no + 1]; |
|
157 |
if (!SPECIAL_CONST_P(op)) { |
|
158 |
func(data, op); |
|
159 |
} |
|
160 |
break; |
|
161 |
} |
|
162 |
default: |
|
163 |
break; |
|
164 |
} |
|
165 |
} |
|
166 | ||
167 |
return len; |
|
168 |
} |
|
169 | ||
170 |
static void |
|
171 |
rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data) |
|
172 |
{ |
|
173 |
unsigned int size; |
|
174 |
const VALUE *code; |
|
175 |
size_t n; |
|
176 |
rb_vm_insns_translator_t * translator; |
|
177 | ||
178 |
size = iseq->body->iseq_size; |
|
179 |
code = iseq->body->iseq_encoded; |
|
180 | ||
181 |
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE |
|
182 |
if (FL_TEST(iseq, ISEQ_TRANSLATED)) { |
|
183 |
translator = rb_vm_insn_addr2insn2; |
|
184 |
} else { |
|
185 |
translator = rb_vm_insn_null_translator; |
|
186 |
} |
|
187 |
#else |
|
188 |
translator = rb_vm_insn_null_translator; |
|
189 |
#endif |
|
190 | ||
191 |
for (n = 0; n < size;) { |
|
192 |
n += iseq_extract_values(code, n, func, data, translator); |
|
193 |
} |
|
194 |
} |
|
195 | ||
196 |
static void |
|
197 |
each_insn_value(void *ctx, VALUE obj) |
|
198 |
{ |
|
199 |
rb_gc_mark(obj); |
|
200 |
} |
|
201 | ||
116 | 202 |
void |
117 | 203 |
rb_iseq_mark(const rb_iseq_t *iseq) |
118 | 204 |
{ |
... | ... | |
121 | 207 |
if (iseq->body) { |
122 | 208 |
const struct rb_iseq_constant_body *body = iseq->body; |
123 | 209 | |
210 |
rb_iseq_each_value(iseq, each_insn_value, NULL); |
|
124 | 211 |
RUBY_MARK_UNLESS_NULL(body->mark_ary); |
125 | 212 |
rb_gc_mark(body->location.label); |
126 | 213 |
rb_gc_mark(body->location.base_label); |
127 | 214 |
rb_gc_mark(body->location.pathobj); |
128 | 215 |
RUBY_MARK_UNLESS_NULL((VALUE)body->parent_iseq); |
216 | ||
217 |
if (body->catch_table) { |
|
218 |
const struct iseq_catch_table *table = body->catch_table; |
|
219 |
unsigned int i; |
|
220 |
for(i = 0; i < table->size; i++) { |
|
221 |
const struct iseq_catch_table_entry *entry; |
|
222 |
entry = &table->entries[i]; |
|
223 |
if (entry->iseq) { |
|
224 |
rb_gc_mark((VALUE)entry->iseq); |
|
225 |
} |
|
226 |
} |
|
227 |
} |
|
129 | 228 |
} |
130 | 229 | |
230 | ||
131 | 231 |
if (FL_TEST(iseq, ISEQ_NOT_LOADED_YET)) { |
132 | 232 |
rb_gc_mark(iseq->aux.loader.obj); |
133 | 233 |
} |
iseq.h | ||
---|---|---|
94 | 94 | |
95 | 95 |
#define ISEQ_NOT_LOADED_YET IMEMO_FL_USER1 |
96 | 96 |
#define ISEQ_USE_COMPILE_DATA IMEMO_FL_USER2 |
97 |
#define ISEQ_TRANSLATED IMEMO_FL_USER3 |
|
97 | 98 | |
98 | 99 |
struct iseq_compile_data { |
99 | 100 |
/* GC is needed */ |