Project

General

Profile

iseq_mark.diff

Mark instructions v3 - tenderlovemaking (Aaron Patterson), 01/20/2018 02:49 AM

View differences:

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 */