Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

iseq.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 iseq.c -
4
5 $Author$
6 created at: 2006-07-11(Tue) 09:00:03 +0900
7
8 Copyright (C) 2006 Koichi Sasada
9
10 **********************************************************************/
11
12 #include "internal.h"
13 #include "ruby/util.h"
14 #include "eval_intern.h"
15
16 #ifdef HAVE_DLADDR
17 # include <dlfcn.h>
18 #endif
19
20 #define RUBY_VM_INSNS_INFO 1
21 /* #define RUBY_MARK_FREE_DEBUG 1 */
22 #include "gc.h"
23 #include "vm_core.h"
24 #include "iseq.h"
25 #include "id_table.h"
26 #include "builtin.h"
27
28 #include "insns.inc"
29 #include "insns_info.inc"
30 #include "mjit.h"
31
32 VALUE rb_cISeq;
33 static VALUE iseqw_new(const rb_iseq_t *iseq);
34 static const rb_iseq_t *iseqw_check(VALUE iseqw);
35
36 #if VM_INSN_INFO_TABLE_IMPL == 2
37 static struct succ_index_table *succ_index_table_create(int max_pos, int *data, int size);
38 static unsigned int *succ_index_table_invert(int max_pos, struct succ_index_table *sd, int size);
39 static int succ_index_lookup(const struct succ_index_table *sd, int x);
40 #endif
41
42 #define hidden_obj_p(obj) (!SPECIAL_CONST_P(obj) && !RBASIC(obj)->klass)
43
44 static inline VALUE
45 obj_resurrect(VALUE obj)
46 {
47 if (hidden_obj_p(obj)) {
48 switch (BUILTIN_TYPE(obj)) {
49 case T_STRING:
50 obj = rb_str_resurrect(obj);
51 break;
52 case T_ARRAY:
53 obj = rb_ary_resurrect(obj);
54 break;
55 case T_HASH:
56 obj = rb_hash_resurrect(obj);
57 break;
58 }
59 }
60 return obj;
61 }
62
63 static void
64 free_arena(struct iseq_compile_data_storage *cur)
65 {
66 struct iseq_compile_data_storage *next;
67
68 while (cur) {
69 next = cur->next;
70 ruby_xfree(cur);
71 cur = next;
72 }
73 }
74
75 static void
76 compile_data_free(struct iseq_compile_data *compile_data)
77 {
78 if (compile_data) {
79 free_arena(compile_data->node.storage_head);
80 free_arena(compile_data->insn.storage_head);
81 if (compile_data->ivar_cache_table) {
82 rb_id_table_free(compile_data->ivar_cache_table);
83 }
84 ruby_xfree(compile_data);
85 }
86 }
87
88 void
89 rb_iseq_free(const rb_iseq_t *iseq)
90 {
91 RUBY_FREE_ENTER("iseq");
92
93 if (iseq && iseq->body) {
94 struct rb_iseq_constant_body *const body = iseq->body;
95 mjit_free_iseq(iseq); /* Notify MJIT */
96 ruby_xfree((void *)body->iseq_encoded);
97 ruby_xfree((void *)body->insns_info.body);
98 if (body->insns_info.positions) ruby_xfree((void *)body->insns_info.positions);
99 #if VM_INSN_INFO_TABLE_IMPL == 2
100 if (body->insns_info.succ_index_table) ruby_xfree(body->insns_info.succ_index_table);
101 #endif
102 if (LIKELY(body->local_table != rb_iseq_shared_exc_local_tbl))
103 ruby_xfree((void *)body->local_table);
104 ruby_xfree((void *)body->is_entries);
105
106 if (body->call_data) {
107 unsigned int i;
108 struct rb_kwarg_call_data *kw_calls = (struct rb_kwarg_call_data *)&body->call_data[body->ci_size];
109 for (i=0; i<body->ci_kw_size; i++) {
110 const struct rb_call_info_kw_arg *kw_arg = kw_calls[i].ci_kw.kw_arg;
111 ruby_xfree((void *)kw_arg);
112 }
113 ruby_xfree(body->call_data);
114 }
115 ruby_xfree((void *)body->catch_table);
116 ruby_xfree((void *)body->param.opt_table);
117
118 if (body->param.keyword != NULL) {
119 ruby_xfree((void *)body->param.keyword->default_values);
120 ruby_xfree((void *)body->param.keyword);
121 }
122 compile_data_free(ISEQ_COMPILE_DATA(iseq));
123 ruby_xfree(body);
124 }
125
126 if (iseq && ISEQ_EXECUTABLE_P(iseq) && iseq->aux.exec.local_hooks) {
127 rb_hook_list_free(iseq->aux.exec.local_hooks);
128 }
129
130 RUBY_FREE_LEAVE("iseq");
131 }
132
133 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
134 static VALUE
135 rb_vm_insn_addr2insn2(const void *addr)
136 {
137 return (VALUE)rb_vm_insn_addr2insn(addr);
138 }
139 #endif
140
141 static VALUE
142 rb_vm_insn_null_translator(const void *addr)
143 {
144 return (VALUE)addr;
145 }
146
147 typedef VALUE iseq_value_itr_t(void *ctx, VALUE obj);
148 typedef VALUE rb_vm_insns_translator_t(const void *addr);
149
150 static int
151 iseq_extract_values(VALUE *code, size_t pos, iseq_value_itr_t * func, void *data, rb_vm_insns_translator_t * translator)
152 {
153 VALUE insn = translator((void *)code[pos]);
154 int len = insn_len(insn);
155 int op_no;
156 const char *types = insn_op_types(insn);
157
158 for (op_no = 0; types[op_no]; op_no++) {
159 char type = types[op_no];
160 switch (type) {
161 case TS_CDHASH:
162 case TS_ISEQ:
163 case TS_VALUE:
164 {
165 VALUE op = code[pos + op_no + 1];
166 if (!SPECIAL_CONST_P(op)) {
167 VALUE newop = func(data, op);
168 if (newop != op) {
169 code[pos + op_no + 1] = newop;
170 }
171 }
172 }
173 break;
174 case TS_ISE:
175 {
176 union iseq_inline_storage_entry *const is = (union iseq_inline_storage_entry *)code[pos + op_no + 1];
177 if (is->once.value) {
178 VALUE nv = func(data, is->once.value);
179 if (is->once.value != nv) {
180 is->once.value = nv;
181 }
182 }
183 }
184 break;
185 default:
186 break;
187 }
188 }
189
190 return len;
191 }
192
193 static void
194 rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data)
195 {
196 unsigned int size;
197 VALUE *code;
198 size_t n;
199 rb_vm_insns_translator_t *const translator =
200 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
201 (FL_TEST(iseq, ISEQ_TRANSLATED)) ? rb_vm_insn_addr2insn2 :
202 #endif
203 rb_vm_insn_null_translator;
204 const struct rb_iseq_constant_body *const body = iseq->body;
205
206 size = body->iseq_size;
207 code = body->iseq_encoded;
208
209 for (n = 0; n < size;) {
210 n += iseq_extract_values(code, n, func, data, translator);
211 }
212 }
213
214 static VALUE
215 update_each_insn_value(void *ctx, VALUE obj)
216 {
217 return rb_gc_location(obj);
218 }
219
220 void
221 rb_iseq_update_references(rb_iseq_t *iseq)
222 {
223 if (iseq->body) {
224 struct rb_iseq_constant_body *body = iseq->body;
225
226 body->variable.coverage = rb_gc_location(body->variable.coverage);
227 body->variable.pc2branchindex = rb_gc_location(body->variable.pc2branchindex);
228 body->location.label = rb_gc_location(body->location.label);
229 body->location.base_label = rb_gc_location(body->location.base_label);
230 body->location.pathobj = rb_gc_location(body->location.pathobj);
231 if (body->local_iseq) {
232 body->local_iseq = (struct rb_iseq_struct *)rb_gc_location((VALUE)body->local_iseq);
233 }
234 if (body->parent_iseq) {
235 body->parent_iseq = (struct rb_iseq_struct *)rb_gc_location((VALUE)body->parent_iseq);
236 }
237 if (FL_TEST(iseq, ISEQ_MARKABLE_ISEQ)) {
238 rb_iseq_each_value(iseq, update_each_insn_value, NULL);
239 VALUE *original_iseq = ISEQ_ORIGINAL_ISEQ(iseq);
240 if (original_iseq) {
241 size_t n = 0;
242 const unsigned int size = body->iseq_size;
243 while (n < size) {
244 n += iseq_extract_values(original_iseq, n, update_each_insn_value, NULL, rb_vm_insn_null_translator);
245 }
246 }
247 }
248
249 if (body->param.flags.has_kw && ISEQ_COMPILE_DATA(iseq) == NULL) {
250 int i, j;
251
252 i = body->param.keyword->required_num;
253
254 for (j = 0; i < body->param.keyword->num; i++, j++) {
255 VALUE obj = body->param.keyword->default_values[j];
256 if (obj != Qundef) {
257 body->param.keyword->default_values[j] = rb_gc_location(obj);
258 }
259 }
260 }
261
262 if (body->catch_table) {
263 struct iseq_catch_table *table = body->catch_table;
264 unsigned int i;
265 for (i = 0; i < table->size; i++) {
266 struct iseq_catch_table_entry *entry;
267 entry = UNALIGNED_MEMBER_PTR(table, entries[i]);
268 if (entry->iseq) {
269 entry->iseq = (rb_iseq_t *)rb_gc_location((VALUE)entry->iseq);
270 }
271 }
272 }
273 #if USE_MJIT
274 mjit_update_references(iseq);
275 #endif
276 }
277 }
278
279 static VALUE
280 each_insn_value(void *ctx, VALUE obj)
281 {
282 rb_gc_mark_movable(obj);
283 return obj;
284 }
285
286 void
287 rb_iseq_mark(const rb_iseq_t *iseq)
288 {
289 RUBY_MARK_ENTER("iseq");
290
291 RUBY_MARK_UNLESS_NULL(iseq->wrapper);
292
293 if (iseq->body) {
294 const struct rb_iseq_constant_body *const body = iseq->body;
295
296 if (FL_TEST(iseq, ISEQ_MARKABLE_ISEQ)) {
297 rb_iseq_each_value(iseq, each_insn_value, NULL);
298 }
299
300 rb_gc_mark_movable(body->variable.coverage);
301 rb_gc_mark_movable(body->variable.pc2branchindex);
302 rb_gc_mark_movable(body->location.label);
303 rb_gc_mark_movable(body->location.base_label);
304 rb_gc_mark_movable(body->location.pathobj);
305 RUBY_MARK_NO_PIN_UNLESS_NULL((VALUE)body->parent_iseq);
306
307 if (body->param.flags.has_kw && ISEQ_COMPILE_DATA(iseq) == NULL) {
308 const struct rb_iseq_param_keyword *const keyword = body->param.keyword;
309 int i, j;
310
311 i = keyword->required_num;
312
313 for (j = 0; i < keyword->num; i++, j++) {
314 VALUE obj = keyword->default_values[j];
315 if (!SPECIAL_CONST_P(obj)) {
316 rb_gc_mark_movable(obj);
317 }
318 }
319 }
320
321 if (body->catch_table) {
322 const struct iseq_catch_table *table = body->catch_table;
323 unsigned int i;
324 for (i = 0; i < table->size; i++) {
325 const struct iseq_catch_table_entry *entry;
326 entry = UNALIGNED_MEMBER_PTR(table, entries[i]);
327 if (entry->iseq) {
328 rb_gc_mark_movable((VALUE)entry->iseq);
329 }
330 }
331 }
332 }
333
334 if (FL_TEST_RAW(iseq, ISEQ_NOT_LOADED_YET)) {
335 rb_gc_mark(iseq->aux.loader.obj);
336 }
337 else if (FL_TEST_RAW(iseq, ISEQ_USE_COMPILE_DATA)) {
338 const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq);
339
340 rb_iseq_mark_insn_storage(compile_data->insn.storage_head);
341
342 RUBY_MARK_UNLESS_NULL(compile_data->err_info);
343 if (RTEST(compile_data->catch_table_ary)) {
344 rb_gc_mark(compile_data->catch_table_ary);
345 }
346 VM_ASSERT(compile_data != NULL);
347 }
348 else {
349 /* executable */
350 VM_ASSERT(ISEQ_EXECUTABLE_P(iseq));
351 if (iseq->aux.exec.local_hooks) {
352 rb_hook_list_mark(iseq->aux.exec.local_hooks);
353 }
354 }
355
356 RUBY_MARK_LEAVE("iseq");
357 }
358
359 static size_t
360 param_keyword_size(const struct rb_iseq_param_keyword *pkw)
361 {
362 size_t size = 0;
363
364 if (!pkw) return size;
365
366 size += sizeof(struct rb_iseq_param_keyword);
367 size += sizeof(VALUE) * (pkw->num - pkw->required_num);
368
369 return size;
370 }
371
372 size_t
373 rb_iseq_memsize(const rb_iseq_t *iseq)
374 {
375 size_t size = 0; /* struct already counted as RVALUE size */
376 const struct rb_iseq_constant_body *body = iseq->body;
377 const struct iseq_compile_data *compile_data;
378
379 /* TODO: should we count original_iseq? */
380
381 if (ISEQ_EXECUTABLE_P(iseq) && body) {
382 struct rb_kwarg_call_data *kw_calls = (struct rb_kwarg_call_data *)&body->call_data[body->ci_size];
383
384 size += sizeof(struct rb_iseq_constant_body);
385 size += body->iseq_size * sizeof(VALUE);
386 size += body->insns_info.size * (sizeof(struct iseq_insn_info_entry) + sizeof(unsigned int));
387 size += body->local_table_size * sizeof(ID);
388 if (body->catch_table) {
389 size += iseq_catch_table_bytes(body->catch_table->size);
390 }
391 size += (body->param.opt_num + 1) * sizeof(VALUE);
392 size += param_keyword_size(body->param.keyword);
393
394 /* body->is_entries */
395 size += body->is_size * sizeof(union iseq_inline_storage_entry);
396
397 /* body->call_data */
398 size += body->ci_size * sizeof(struct rb_call_data);
399 size += body->ci_kw_size * sizeof(struct rb_kwarg_call_data);
400
401 if (kw_calls) {
402 unsigned int i;
403
404 for (i = 0; i < body->ci_kw_size; i++) {
405 const struct rb_call_info_kw_arg *kw_arg = kw_calls[i].ci_kw.kw_arg;
406
407 if (kw_arg) {
408 size += rb_call_info_kw_arg_bytes(kw_arg->keyword_len);
409 }
410 }
411 }
412 }
413
414 compile_data = ISEQ_COMPILE_DATA(iseq);
415 if (compile_data) {
416 struct iseq_compile_data_storage *cur;
417
418 size += sizeof(struct iseq_compile_data);
419
420 cur = compile_data->node.storage_head;
421 while (cur) {
422 size += cur->size + offsetof(struct iseq_compile_data_storage, buff);
423 cur = cur->next;
424 }
425 }
426
427 return size;
428 }
429
430 static uintptr_t fresh_iseq_unique_id = 0; /* -- Remove In 3.0 -- */
431
432 struct rb_iseq_constant_body *
433 rb_iseq_constant_body_alloc(void)
434 {
435 struct rb_iseq_constant_body *iseq_body;
436 iseq_body = ZALLOC(struct rb_iseq_constant_body);
437 iseq_body->iseq_unique_id = fresh_iseq_unique_id++; /* -- Remove In 3.0 -- */
438 return iseq_body;
439 }
440
441 static rb_iseq_t *
442 iseq_alloc(void)
443 {
444 rb_iseq_t *iseq = iseq_imemo_alloc();
445 iseq->body = rb_iseq_constant_body_alloc();
446 return iseq;
447 }
448
449 VALUE
450 rb_iseq_pathobj_new(VALUE path, VALUE realpath)
451 {
452 VALUE pathobj;
453 VM_ASSERT(RB_TYPE_P(path, T_STRING));
454 VM_ASSERT(realpath == Qnil || RB_TYPE_P(realpath, T_STRING));
455
456 if (path == realpath ||
457 (!NIL_P(realpath) && rb_str_cmp(path, realpath) == 0)) {
458 pathobj = rb_fstring(path);
459 }
460 else {
461 if (!NIL_P(realpath)) realpath = rb_fstring(realpath);
462 pathobj = rb_ary_new_from_args(2, rb_fstring(path), realpath);
463 rb_obj_freeze(pathobj);
464 }
465 return pathobj;
466 }
467
468 void
469 rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath)
470 {
471 RB_OBJ_WRITE(iseq, &iseq->body->location.pathobj,
472 rb_iseq_pathobj_new(path, realpath));
473 }
474
475 static rb_iseq_location_t *
476 iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_code_location_t *code_location, const int node_id)
477 {
478 rb_iseq_location_t *loc = &iseq->body->location;
479
480 rb_iseq_pathobj_set(iseq, path, realpath);
481 RB_OBJ_WRITE(iseq, &loc->label, name);
482 RB_OBJ_WRITE(iseq, &loc->base_label, name);
483 loc->first_lineno = first_lineno;
484 if (code_location) {
485 loc->node_id = node_id;
486 loc->code_location = *code_location;
487 }
488 else {
489 loc->code_location.beg_pos.lineno = 0;
490 loc->code_location.beg_pos.column = 0;
491 loc->code_location.end_pos.lineno = -1;
492 loc->code_location.end_pos.column = -1;
493 }
494
495 return loc;
496 }
497
498 static void
499 set_relation(rb_iseq_t *iseq, const rb_iseq_t *piseq)
500 {
501 struct rb_iseq_constant_body *const body = iseq->body;
502 const VALUE type = body->type;
503
504 /* set class nest stack */
505 if (type == ISEQ_TYPE_TOP) {
506 body->local_iseq = iseq;
507 }
508 else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
509 body->local_iseq = iseq;
510 }
511 else if (piseq) {
512 body->local_iseq = piseq->body->local_iseq;
513 }
514
515 if (piseq) {
516 body->parent_iseq = piseq;
517 }
518
519 if (type == ISEQ_TYPE_MAIN) {
520 body->local_iseq = iseq;
521 }
522 }
523
524 static struct iseq_compile_data_storage *
525 new_arena(void)
526 {
527 struct iseq_compile_data_storage * new_arena =
528 (struct iseq_compile_data_storage *)
529 ALLOC_N(char, INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE +
530 offsetof(struct iseq_compile_data_storage, buff));
531
532 new_arena->pos = 0;
533 new_arena->next = 0;
534 new_arena->size = INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE;
535
536 return new_arena;
537 }
538
539 static VALUE
540 prepare_iseq_build(rb_iseq_t *iseq,
541 VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_code_location_t *code_location, const int node_id,
542 const rb_iseq_t *parent, enum iseq_type type,
543 const rb_compile_option_t *option)
544 {
545 VALUE coverage = Qfalse;
546 VALUE err_info = Qnil;
547 struct rb_iseq_constant_body *const body = iseq->body;
548
549 if (parent && (type == ISEQ_TYPE_MAIN || type == ISEQ_TYPE_TOP))
550 err_info = Qfalse;
551
552 body->type = type;
553 set_relation(iseq, parent);
554
555 name = rb_fstring(name);
556 iseq_location_setup(iseq, name, path, realpath, first_lineno, code_location, node_id);
557 if (iseq != body->local_iseq) {
558 RB_OBJ_WRITE(iseq, &body->location.base_label, body->local_iseq->body->location.label);
559 }
560 ISEQ_COVERAGE_SET(iseq, Qnil);
561 ISEQ_ORIGINAL_ISEQ_CLEAR(iseq);
562 body->variable.flip_count = 0;
563
564 ISEQ_COMPILE_DATA_ALLOC(iseq);
565 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err_info);
566 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, Qnil);
567
568 ISEQ_COMPILE_DATA(iseq)->node.storage_head = ISEQ_COMPILE_DATA(iseq)->node.storage_current = new_arena();
569 ISEQ_COMPILE_DATA(iseq)->insn.storage_head = ISEQ_COMPILE_DATA(iseq)->insn.storage_current = new_arena();
570 ISEQ_COMPILE_DATA(iseq)->option = option;
571
572 ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = NULL;
573
574 ISEQ_COMPILE_DATA(iseq)->builtin_function_table = GET_VM()->builtin_function_table;
575
576 if (option->coverage_enabled) {
577 VALUE coverages = rb_get_coverages();
578 if (RTEST(coverages)) {
579 coverage = rb_hash_lookup(coverages, rb_iseq_path(iseq));
580 if (NIL_P(coverage)) coverage = Qfalse;
581 }
582 }
583 ISEQ_COVERAGE_SET(iseq, coverage);
584 if (coverage && ISEQ_BRANCH_COVERAGE(iseq))
585 ISEQ_PC2BRANCHINDEX_SET(iseq, rb_ary_tmp_new(0));
586
587 return Qtrue;
588 }
589
590 #if VM_CHECK_MODE > 0 && VM_INSN_INFO_TABLE_IMPL > 0
591 static void validate_get_insn_info(const rb_iseq_t *iseq);
592 #endif
593
594 void
595 rb_iseq_insns_info_encode_positions(const rb_iseq_t *iseq)
596 {
597 #if VM_INSN_INFO_TABLE_IMPL == 2
598 struct rb_iseq_constant_body *const body = iseq->body;
599 int size = body->insns_info.size;
600 int max_pos = body->iseq_size;
601 int *data = (int *)body->insns_info.positions;
602 if (body->insns_info.succ_index_table) ruby_xfree(body->insns_info.succ_index_table);
603 body->insns_info.succ_index_table = succ_index_table_create(max_pos, data, size);
604 #if VM_CHECK_MODE == 0
605 ruby_xfree(body->insns_info.positions);
606 body->insns_info.positions = NULL;
607 #endif
608 #endif
609 }
610
611 #if VM_INSN_INFO_TABLE_IMPL == 2
612 unsigned int *
613 rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body)
614 {
615 int size = body->insns_info.size;
616 int max_pos = body->iseq_size;
617 struct succ_index_table *sd = body->insns_info.succ_index_table;
618 return succ_index_table_invert(max_pos, sd, size);
619 }
620 #endif
621
622 void
623 rb_iseq_init_trace(rb_iseq_t *iseq)
624 {
625 iseq->aux.exec.global_trace_events = 0;
626 if (ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS) {
627 rb_iseq_trace_set(iseq, ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS);
628 }
629 }
630
631 static VALUE
632 finish_iseq_build(rb_iseq_t *iseq)
633 {
634 struct iseq_compile_data *data = ISEQ_COMPILE_DATA(iseq);
635 const struct rb_iseq_constant_body *const body = iseq->body;
636 VALUE err = data->err_info;
637 ISEQ_COMPILE_DATA_CLEAR(iseq);
638 compile_data_free(data);
639
640 #if VM_INSN_INFO_TABLE_IMPL == 2 /* succinct bitvector */
641 /* create succ_index_table */
642 if (body->insns_info.succ_index_table == NULL) {
643 rb_iseq_insns_info_encode_positions(iseq);
644 }
645 #endif
646
647 #if VM_CHECK_MODE > 0 && VM_INSN_INFO_TABLE_IMPL > 0
648 validate_get_insn_info(iseq);
649 #endif
650
651 if (RTEST(err)) {
652 VALUE path = pathobj_path(body->location.pathobj);
653 if (err == Qtrue) err = rb_exc_new_cstr(rb_eSyntaxError, "compile error");
654 rb_funcallv(err, rb_intern("set_backtrace"), 1, &path);
655 rb_exc_raise(err);
656 }
657
658 rb_iseq_init_trace(iseq);
659 return Qtrue;
660 }
661
662 static rb_compile_option_t COMPILE_OPTION_DEFAULT = {
663 OPT_INLINE_CONST_CACHE, /* int inline_const_cache; */
664 OPT_PEEPHOLE_OPTIMIZATION, /* int peephole_optimization; */
665 OPT_TAILCALL_OPTIMIZATION, /* int tailcall_optimization */
666 OPT_SPECIALISED_INSTRUCTION, /* int specialized_instruction; */
667 OPT_OPERANDS_UNIFICATION, /* int operands_unification; */
668 OPT_INSTRUCTIONS_UNIFICATION, /* int instructions_unification; */
669 OPT_STACK_CACHING, /* int stack_caching; */
670 OPT_FROZEN_STRING_LITERAL,
671 OPT_DEBUG_FROZEN_STRING_LITERAL,
672 TRUE, /* coverage_enabled */
673 };
674
675 static const rb_compile_option_t COMPILE_OPTION_FALSE = {0};
676
677 static void
678 set_compile_option_from_hash(rb_compile_option_t *option, VALUE opt)
679 {
680 #define SET_COMPILE_OPTION(o, h, mem) \
681 { VALUE flag = rb_hash_aref((h), ID2SYM(rb_intern(#mem))); \
682 if (flag == Qtrue) { (o)->mem = 1; } \
683 else if (flag == Qfalse) { (o)->mem = 0; } \
684 }
685 #define SET_COMPILE_OPTION_NUM(o, h, mem) \
686 { VALUE num = rb_hash_aref(opt, ID2SYM(rb_intern(#mem))); \
687 if (!NIL_P(num)) (o)->mem = NUM2INT(num); \
688 }
689 SET_COMPILE_OPTION(option, opt, inline_const_cache);
690 SET_COMPILE_OPTION(option, opt, peephole_optimization);
691 SET_COMPILE_OPTION(option, opt, tailcall_optimization);
692 SET_COMPILE_OPTION(option, opt, specialized_instruction);
693 SET_COMPILE_OPTION(option, opt, operands_unification);
694 SET_COMPILE_OPTION(option, opt, instructions_unification);
695 SET_COMPILE_OPTION(option, opt, stack_caching);
696 SET_COMPILE_OPTION(option, opt, frozen_string_literal);
697 SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal);
698 SET_COMPILE_OPTION(option, opt, coverage_enabled);
699 SET_COMPILE_OPTION_NUM(option, opt, debug_level);
700 #undef SET_COMPILE_OPTION
701 #undef SET_COMPILE_OPTION_NUM
702 }
703
704 static void
705 rb_iseq_make_compile_option(rb_compile_option_t *option, VALUE opt)
706 {
707 Check_Type(opt, T_HASH);
708 set_compile_option_from_hash(option, opt);
709 }
710
711 static void
712 make_compile_option(rb_compile_option_t *option, VALUE opt)
713 {
714 if (opt == Qnil) {
715 *option = COMPILE_OPTION_DEFAULT;
716 }
717 else if (opt == Qfalse) {
718 *option = COMPILE_OPTION_FALSE;
719 }
720 else if (opt == Qtrue) {
721 int i;
722 for (i = 0; i < (int)(sizeof(rb_compile_option_t) / sizeof(int)); ++i)
723 ((int *)option)[i] = 1;
724 }
725 else if (RB_TYPE_P(opt, T_HASH)) {
726 *option = COMPILE_OPTION_DEFAULT;
727 set_compile_option_from_hash(option, opt);
728 }
729 else {
730 rb_raise(rb_eTypeError, "Compile option must be Hash/true/false/nil");
731 }
732 }
733
734 static VALUE
735 make_compile_option_value(rb_compile_option_t *option)
736 {
737 VALUE opt = rb_hash_new_with_size(11);
738 #define SET_COMPILE_OPTION(o, h, mem) \
739 rb_hash_aset((h), ID2SYM(rb_intern(#mem)), (o)->mem ? Qtrue : Qfalse)
740 #define SET_COMPILE_OPTION_NUM(o, h, mem) \
741 rb_hash_aset((h), ID2SYM(rb_intern(#mem)), INT2NUM((o)->mem))
742 {
743 SET_COMPILE_OPTION(option, opt, inline_const_cache);
744 SET_COMPILE_OPTION(option, opt, peephole_optimization);
745 SET_COMPILE_OPTION(option, opt, tailcall_optimization);
746 SET_COMPILE_OPTION(option, opt, specialized_instruction);
747 SET_COMPILE_OPTION(option, opt, operands_unification);
748 SET_COMPILE_OPTION(option, opt, instructions_unification);
749 SET_COMPILE_OPTION(option, opt, stack_caching);
750 SET_COMPILE_OPTION(option, opt, frozen_string_literal);
751 SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal);
752 SET_COMPILE_OPTION(option, opt, coverage_enabled);
753 SET_COMPILE_OPTION_NUM(option, opt, debug_level);
754 }
755 #undef SET_COMPILE_OPTION
756 #undef SET_COMPILE_OPTION_NUM
757 return opt;
758 }
759
760 rb_iseq_t *
761 rb_iseq_new(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath,
762 const rb_iseq_t *parent, enum iseq_type type)
763 {
764 return rb_iseq_new_with_opt(ast, name, path, realpath, INT2FIX(0), parent, type,
765 &COMPILE_OPTION_DEFAULT);
766 }
767
768 rb_iseq_t *
769 rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
770 {
771 VALUE coverages = rb_get_coverages();
772 if (RTEST(coverages)) {
773 if (ast->line_count >= 0) {
774 int len = (rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES) ? 0 : ast->line_count;
775 VALUE coverage = rb_default_coverage(len);
776 rb_hash_aset(coverages, path, coverage);
777 }
778 }
779
780 return rb_iseq_new_with_opt(ast, name, path, realpath, INT2FIX(0), parent, ISEQ_TYPE_TOP,
781 &COMPILE_OPTION_DEFAULT);
782 }
783
784 rb_iseq_t *
785 rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent)
786 {
787 return rb_iseq_new_with_opt(ast, rb_fstring_lit("<main>"),
788 path, realpath, INT2FIX(0),
789 parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT);
790 }
791
792 static inline rb_iseq_t *
793 iseq_translate(rb_iseq_t *iseq)
794 {
795 if (rb_respond_to(rb_cISeq, rb_intern("translate"))) {
796 VALUE v1 = iseqw_new(iseq);
797 VALUE v2 = rb_funcall(rb_cISeq, rb_intern("translate"), 1, v1);
798 if (v1 != v2 && CLASS_OF(v2) == rb_cISeq) {
799 iseq = (rb_iseq_t *)iseqw_check(v2);
800 }
801 }
802
803 return iseq;
804 }
805
806 rb_iseq_t *
807 rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath,
808 VALUE first_lineno, const rb_iseq_t *parent,
809 enum iseq_type type, const rb_compile_option_t *option)
810 {
811 const NODE *node = ast ? ast->root : 0;
812 /* TODO: argument check */
813 rb_iseq_t *iseq = iseq_alloc();
814 rb_compile_option_t new_opt;
815
816 new_opt = option ? *option : COMPILE_OPTION_DEFAULT;
817 if (ast && ast->compile_option) rb_iseq_make_compile_option(&new_opt, ast->compile_option);
818
819 prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, node ? nd_node_id(node) : -1, parent, type, &new_opt);
820
821 rb_iseq_compile_node(iseq, node);
822 finish_iseq_build(iseq);
823
824 return iseq_translate(iseq);
825 }
826
827 rb_iseq_t *
828 rb_iseq_new_with_callback(
829 const struct rb_iseq_new_with_callback_callback_func * ifunc,
830 VALUE name, VALUE path, VALUE realpath,
831 VALUE first_lineno, const rb_iseq_t *parent,
832 enum iseq_type type, const rb_compile_option_t *option)
833 {
834 /* TODO: argument check */
835 rb_iseq_t *iseq = iseq_alloc();
836
837 if (!option) option = &COMPILE_OPTION_DEFAULT;
838 prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, type, option);
839
840 rb_iseq_compile_callback(iseq, ifunc);
841 finish_iseq_build(iseq);
842
843 return iseq_translate(iseq);
844 }
845
846 const rb_iseq_t *
847 rb_iseq_load_iseq(VALUE fname)
848 {
849 VALUE iseqv = rb_check_funcall(rb_cISeq, rb_intern("load_iseq"), 1, &fname);
850
851 if (!SPECIAL_CONST_P(iseqv) && RBASIC_CLASS(iseqv) == rb_cISeq) {
852 return iseqw_check(iseqv);
853 }
854
855 return NULL;
856 }
857
858 #define CHECK_ARRAY(v) rb_to_array_type(v)
859 #define CHECK_HASH(v) rb_to_hash_type(v)
860 #define CHECK_STRING(v) rb_str_to_str(v)
861 #define CHECK_SYMBOL(v) rb_to_symbol_type(v)
862 static inline VALUE CHECK_INTEGER(VALUE v) {(void)NUM2LONG(v); return v;}
863
864 static enum iseq_type
865 iseq_type_from_sym(VALUE type)
866 {
867 const ID id_top = rb_intern("top");
868 const ID id_method = rb_intern("method");
869 const ID id_block = rb_intern("block");
870 const ID id_class = rb_intern("class");
871 const ID id_rescue = rb_intern("rescue");
872 const ID id_ensure = rb_intern("ensure");
873 const ID id_eval = rb_intern("eval");
874 const ID id_main = rb_intern("main");
875 const ID id_plain = rb_intern("plain");
876 /* ensure all symbols are static or pinned down before
877 * conversion */
878 const ID typeid = rb_check_id(&type);
879 if (typeid == id_top) return ISEQ_TYPE_TOP;
880 if (typeid == id_method) return ISEQ_TYPE_METHOD;
881 if (typeid == id_block) return ISEQ_TYPE_BLOCK;
882 if (typeid == id_class) return ISEQ_TYPE_CLASS;
883 if (typeid == id_rescue) return ISEQ_TYPE_RESCUE;
884 if (typeid == id_ensure) return ISEQ_TYPE_ENSURE;
885 if (typeid == id_eval) return ISEQ_TYPE_EVAL;
886 if (typeid == id_main) return ISEQ_TYPE_MAIN;
887 if (typeid == id_plain) return ISEQ_TYPE_PLAIN;
888 return (enum iseq_type)-1;
889 }
890
891 static VALUE
892 iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt)
893 {
894 rb_iseq_t *iseq = iseq_alloc();
895
896 VALUE magic, version1, version2, format_type, misc;
897 VALUE name, path, realpath, first_lineno, code_location, node_id;
898 VALUE type, body, locals, params, exception;
899
900 st_data_t iseq_type;
901 rb_compile_option_t option;
902 int i = 0;
903 rb_code_location_t tmp_loc = { {0, 0}, {-1, -1} };
904
905 /* [magic, major_version, minor_version, format_type, misc,
906 * label, path, first_lineno,
907 * type, locals, args, exception_table, body]
908 */
909
910 data = CHECK_ARRAY(data);
911
912 magic = CHECK_STRING(rb_ary_entry(data, i++));
913 version1 = CHECK_INTEGER(rb_ary_entry(data, i++));
914 version2 = CHECK_INTEGER(rb_ary_entry(data, i++));
915 format_type = CHECK_INTEGER(rb_ary_entry(data, i++));
916 misc = CHECK_HASH(rb_ary_entry(data, i++));
917 ((void)magic, (void)version1, (void)version2, (void)format_type);
918
919 name = CHECK_STRING(rb_ary_entry(data, i++));
920 path = CHECK_STRING(rb_ary_entry(data, i++));
921 realpath = rb_ary_entry(data, i++);
922 realpath = NIL_P(realpath) ? Qnil : CHECK_STRING(realpath);
923 first_lineno = CHECK_INTEGER(rb_ary_entry(data, i++));
924
925 type = CHECK_SYMBOL(rb_ary_entry(data, i++));
926 locals = CHECK_ARRAY(rb_ary_entry(data, i++));
927 params = CHECK_HASH(rb_ary_entry(data, i++));
928 exception = CHECK_ARRAY(rb_ary_entry(data, i++));
929 body = CHECK_ARRAY(rb_ary_entry(data, i++));
930
931 iseq->body->local_iseq = iseq;
932
933 iseq_type = iseq_type_from_sym(type);
934 if (iseq_type == (enum iseq_type)-1) {
935 rb_raise(rb_eTypeError, "unsupported type: :%"PRIsVALUE, rb_sym2str(type));
936 }
937
938 node_id = rb_hash_aref(misc, ID2SYM(rb_intern("node_id")));
939
940 code_location = rb_hash_aref(misc, ID2SYM(rb_intern("code_location")));
941 if (RB_TYPE_P(code_location, T_ARRAY) && RARRAY_LEN(code_location) == 4) {
942 tmp_loc.beg_pos.lineno = NUM2INT(rb_ary_entry(code_location, 0));
943 tmp_loc.beg_pos.column = NUM2INT(rb_ary_entry(code_location, 1));
944 tmp_loc.end_pos.lineno = NUM2INT(rb_ary_entry(code_location, 2));
945 tmp_loc.end_pos.column = NUM2INT(rb_ary_entry(code_location, 3));
946 }
947
948 make_compile_option(&option, opt);
949 option.peephole_optimization = FALSE; /* because peephole optimization can modify original iseq */
950 prepare_iseq_build(iseq, name, path, realpath, first_lineno, &tmp_loc, NUM2INT(node_id),
951 parent, (enum iseq_type)iseq_type, &option);
952
953 rb_iseq_build_from_ary(iseq, misc, locals, params, exception, body);
954
955 finish_iseq_build(iseq);
956
957 return iseqw_new(iseq);
958 }
959
960 /*
961 * :nodoc:
962 */
963 static VALUE
964 iseq_s_load(int argc, VALUE *argv, VALUE self)
965 {
966 VALUE data, opt=Qnil;
967 rb_scan_args(argc, argv, "11", &data, &opt);
968 return iseq_load(data, NULL, opt);
969 }
970
971 VALUE
972 rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
973 {
974 return iseq_load(data, RTEST(parent) ? (rb_iseq_t *)parent : NULL, opt);
975 }
976
977 static rb_iseq_t *
978 rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, VALUE opt)
979 {
980 rb_iseq_t *iseq = NULL;
981 rb_compile_option_t option;
982 #if !defined(__GNUC__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 8)
983 # define INITIALIZED volatile /* suppress warnings by gcc 4.8 */
984 #else
985 # define INITIALIZED /* volatile */
986 #endif
987 rb_ast_t *(*parse)(VALUE vparser, VALUE fname, VALUE file, int start);
988 int ln;
989 rb_ast_t *INITIALIZED ast;
990
991 /* safe results first */
992 make_compile_option(&option, opt);
993 ln = NUM2INT(line);
994 StringValueCStr(file);
995 if (RB_TYPE_P(src, T_FILE)) {
996 parse = rb_parser_compile_file_path;
997 }
998 else {
999 parse = rb_parser_compile_string_path;
1000 StringValue(src);
1001 }
1002 {
1003 const VALUE parser = rb_parser_new();
1004 VALUE name = rb_fstring_lit("<compiled>");
1005 const rb_iseq_t *outer_scope = rb_iseq_new(NULL, name, name, Qnil, 0, ISEQ_TYPE_TOP);
1006 VALUE outer_scope_v = (VALUE)outer_scope;
1007 rb_parser_set_context(parser, outer_scope, FALSE);
1008 RB_GC_GUARD(outer_scope_v);
1009 ast = (*parse)(parser, file, src, ln);
1010 }
1011
1012 if (!ast->body.root) {
1013 rb_ast_dispose(ast);
1014 rb_exc_raise(GET_EC()->errinfo);
1015 }
1016 else {
1017 INITIALIZED VALUE label = rb_fstring_lit("<compiled>");
1018 iseq = rb_iseq_new_with_opt(&ast->body, label, file, realpath, line,
1019 0, ISEQ_TYPE_TOP, &option);
1020 rb_ast_dispose(ast);
1021 }
1022
1023 return iseq;
1024 }
1025
1026 VALUE
1027 rb_iseq_path(const rb_iseq_t *iseq)
1028 {
1029 return pathobj_path(iseq->body->location.pathobj);
1030 }
1031
1032 VALUE
1033 rb_iseq_realpath(const rb_iseq_t *iseq)
1034 {
1035 return pathobj_realpath(iseq->body->location.pathobj);
1036 }
1037
1038 VALUE
1039 rb_iseq_absolute_path(const rb_iseq_t *iseq)
1040 {
1041 return rb_iseq_realpath(iseq);
1042 }
1043
1044 VALUE
1045 rb_iseq_label(const rb_iseq_t *iseq)
1046 {
1047 return iseq->body->location.label;
1048 }
1049
1050 VALUE
1051 rb_iseq_base_label(const rb_iseq_t *iseq)
1052 {
1053 return iseq->body->location.base_label;
1054 }
1055
1056 VALUE
1057 rb_iseq_first_lineno(const rb_iseq_t *iseq)
1058 {
1059 return iseq->body->location.first_lineno;
1060 }
1061
1062 VALUE
1063 rb_iseq_method_name(const rb_iseq_t *iseq)
1064 {
1065 struct rb_iseq_constant_body *const body = iseq->body->local_iseq->body;
1066
1067 if (body->type == ISEQ_TYPE_METHOD) {
1068 return body->location.base_label;
1069 }
1070 else {
1071 return Qnil;
1072 }
1073 }
1074
1075 void
1076 rb_iseq_code_location(const rb_iseq_t *iseq, int *beg_pos_lineno, int *beg_pos_column, int *end_pos_lineno, int *end_pos_column)
1077 {
1078 const rb_code_location_t *loc = &iseq->body->location.code_location;
1079 if (beg_pos_lineno) *beg_pos_lineno = loc->beg_pos.lineno;
1080 if (beg_pos_column) *beg_pos_column = loc->beg_pos.column;
1081 if (end_pos_lineno) *end_pos_lineno = loc->end_pos.lineno;
1082 if (end_pos_column) *end_pos_column = loc->end_pos.column;
1083 }
1084
1085 VALUE
1086 rb_iseq_coverage(const rb_iseq_t *iseq)
1087 {
1088 return ISEQ_COVERAGE(iseq);
1089 }
1090
1091 static int
1092 remove_coverage_i(void *vstart, void *vend, size_t stride, void *data)
1093 {
1094 VALUE v = (VALUE)vstart;
1095 for (; v != (VALUE)vend; v += stride) {
1096 void *ptr = asan_poisoned_object_p(v);
1097 asan_unpoison_object(v, false);
1098
1099 if (rb_obj_is_iseq(v)) {
1100 rb_iseq_t *iseq = (rb_iseq_t *)v;
1101 ISEQ_COVERAGE_SET(iseq, Qnil);
1102 }
1103
1104 asan_poison_object_if(ptr, v);
1105 }
1106 return 0;
1107 }
1108
1109 void
1110 rb_iseq_remove_coverage_all(void)
1111 {
1112 rb_objspace_each_objects(remove_coverage_i, NULL);
1113 }
1114
1115 /* define wrapper class methods (RubyVM::InstructionSequence) */
1116
1117 static void
1118 iseqw_mark(void *ptr)
1119 {
1120 rb_gc_mark((VALUE)ptr);
1121 }
1122
1123 static size_t
1124 iseqw_memsize(const void *ptr)
1125 {
1126 return rb_iseq_memsize((const rb_iseq_t *)ptr);
1127 }
1128
1129 static const rb_data_type_t iseqw_data_type = {
1130 "T_IMEMO/iseq",
1131 {iseqw_mark, NULL, iseqw_memsize,},
1132 0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
1133 };
1134
1135 static VALUE
1136 iseqw_new(const rb_iseq_t *iseq)
1137 {
1138 if (iseq->wrapper) {
1139 return iseq->wrapper;
1140 }
1141 else {
1142 union { const rb_iseq_t *in; void *out; } deconst;
1143 VALUE obj;
1144 deconst.in = iseq;
1145 obj = TypedData_Wrap_Struct(rb_cISeq, &iseqw_data_type, deconst.out);
1146 RB_OBJ_WRITTEN(obj, Qundef, iseq);
1147
1148 /* cache a wrapper object */
1149 RB_OBJ_WRITE((VALUE)iseq, &iseq->wrapper, obj);
1150 RB_OBJ_FREEZE((VALUE)iseq);
1151
1152 return obj;
1153 }
1154 }
1155
1156 VALUE
1157 rb_iseqw_new(const rb_iseq_t *iseq)
1158 {
1159 return iseqw_new(iseq);
1160 }
1161
1162 /*
1163 * call-seq:
1164 * InstructionSequence.compile(source[, file[, path[, line[, options]]]]) -> iseq
1165 * InstructionSequence.new(source[, file[, path[, line[, options]]]]) -> iseq
1166 *
1167 * Takes +source+, a String of Ruby code and compiles it to an
1168 * InstructionSequence.
1169 *
1170 * Optionally takes +file+, +path+, and +line+ which describe the file path,
1171 * real path and first line number of the ruby code in +source+ which are
1172 * metadata attached to the returned +iseq+.
1173 *
1174 * +file+ is used for `__FILE__` and exception backtrace. +path+ is used for
1175 * +require_relative+ base. It is recommended these should be the same full
1176 * path.
1177 *
1178 * +options+, which can be +true+, +false+ or a +Hash+, is used to
1179 * modify the default behavior of the Ruby iseq compiler.
1180 *
1181 * For details regarding valid compile options see ::compile_option=.
1182 *
1183 * RubyVM::InstructionSequence.compile("a = 1 + 2")
1184 * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
1185 *
1186 * path = "test.rb"
1187 * RubyVM::InstructionSequence.compile(File.read(path), path, File.expand_path(path))
1188 * #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1>
1189 *
1190 * path = File.expand_path("test.rb")
1191 * RubyVM::InstructionSequence.compile(File.read(path), path, path)
1192 * #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
1193 *
1194 */
1195 static VALUE
1196 iseqw_s_compile(int argc, VALUE *argv, VALUE self)
1197 {
1198 VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil;
1199 int i;
1200
1201 i = rb_scan_args(argc, argv, "1*:", &src, NULL, &opt);
1202 if (i > 4+NIL_P(opt)) rb_error_arity(argc, 1, 5);
1203 switch (i) {
1204 case 5: opt = argv[--i];
1205 case 4: line = argv[--i];
1206 case 3: path = argv[--i];
1207 case 2: file = argv[--i];
1208 }
1209
1210 if (NIL_P(file)) file = rb_fstring_lit("<compiled>");
1211 if (NIL_P(path)) path = file;
1212 if (NIL_P(line)) line = INT2FIX(1);
1213
1214 Check_Type(path, T_STRING);
1215 Check_Type(file, T_STRING);
1216
1217 return iseqw_new(rb_iseq_compile_with_option(src, file, path, line, opt));
1218 }
1219
1220 /*
1221 * call-seq:
1222 * InstructionSequence.compile_file(file[, options]) -> iseq
1223 *
1224 * Takes +file+, a String with the location of a Ruby source file, reads,
1225 * parses and compiles the file, and returns +iseq+, the compiled
1226 * InstructionSequence with source location metadata set.
1227 *
1228 * Optionally takes +options+, which can be +true+, +false+ or a +Hash+, to
1229 * modify the default behavior of the Ruby iseq compiler.
1230 *
1231 * For details regarding valid compile options see ::compile_option=.
1232 *
1233 * # /tmp/hello.rb
1234 * puts "Hello, world!"
1235 *
1236 * # elsewhere
1237 * RubyVM::InstructionSequence.compile_file("/tmp/hello.rb")
1238 * #=> <RubyVM::InstructionSequence:<main>@/tmp/hello.rb>
1239 */
1240 static VALUE
1241 iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
1242 {
1243 VALUE file, line = INT2FIX(1), opt = Qnil;
1244 VALUE parser, f, exc = Qnil, ret;
1245 rb_ast_t *ast;
1246 rb_compile_option_t option;
1247 int i;
1248
1249 i = rb_scan_args(argc, argv, "1*:", &file, NULL, &opt);
1250 if (i > 1+NIL_P(opt)) rb_error_arity(argc, 1, 2);
1251 switch (i) {
1252 case 2: opt = argv[--i];
1253 }
1254 FilePathValue(file);
1255 file = rb_fstring(file); /* rb_io_t->pathv gets frozen anyways */
1256
1257 f = rb_file_open_str(file, "r");
1258
1259 parser = rb_parser_new();
1260 rb_parser_set_context(parser, NULL, FALSE);
1261 ast = rb_parser_compile_file_path(parser, file, f, NUM2INT(line));
1262 if (!ast->body.root) exc = GET_EC()->errinfo;
1263
1264 rb_io_close(f);
1265 if (!ast->body.root) {
1266 rb_ast_dispose(ast);
1267 rb_exc_raise(exc);
1268 }
1269
1270 make_compile_option(&option, opt);
1271
1272 ret = iseqw_new(rb_iseq_new_with_opt(&ast->body, rb_fstring_lit("<main>"),
1273 file,
1274 rb_realpath_internal(Qnil, file, 1),
1275 line, NULL, ISEQ_TYPE_TOP, &option));
1276 rb_ast_dispose(ast);
1277 return ret;
1278 }
1279
1280 /*
1281 * call-seq:
1282 * InstructionSequence.compile_option = options
1283 *
1284 * Sets the default values for various optimizations in the Ruby iseq
1285 * compiler.
1286 *
1287 * Possible values for +options+ include +true+, which enables all options,
1288 * +false+ which disables all options, and +nil+ which leaves all options
1289 * unchanged.
1290 *
1291 * You can also pass a +Hash+ of +options+ that you want to change, any
1292 * options not present in the hash will be left unchanged.
1293 *
1294 * Possible option names (which are keys in +options+) which can be set to
1295 * +true+ or +false+ include:
1296 *
1297 * * +:inline_const_cache+
1298 * * +:instructions_unification+
1299 * * +:operands_unification+
1300 * * +:peephole_optimization+
1301 * * +:specialized_instruction+
1302 * * +:stack_caching+
1303 * * +:tailcall_optimization+
1304 *
1305 * Additionally, +:debug_level+ can be set to an integer.
1306 *
1307 * These default options can be overwritten for a single run of the iseq
1308 * compiler by passing any of the above values as the +options+ parameter to
1309 * ::new, ::compile and ::compile_file.
1310 */
1311 static VALUE
1312 iseqw_s_compile_option_set(VALUE self, VALUE opt)
1313 {
1314 rb_compile_option_t option;
1315 make_compile_option(&option, opt);
1316 COMPILE_OPTION_DEFAULT = option;
1317 return opt;
1318 }
1319
1320 /*
1321 * call-seq:
1322 * InstructionSequence.compile_option -> options
1323 *
1324 * Returns a hash of default options used by the Ruby iseq compiler.
1325 *
1326 * For details, see InstructionSequence.compile_option=.
1327 */
1328 static VALUE
1329 iseqw_s_compile_option_get(VALUE self)
1330 {
1331 return make_compile_option_value(&COMPILE_OPTION_DEFAULT);
1332 }
1333
1334 static const rb_iseq_t *
1335 iseqw_check(VALUE iseqw)
1336 {
1337 rb_iseq_t *iseq = DATA_PTR(iseqw);
1338
1339 if (!iseq->body) {
1340 rb_ibf_load_iseq_complete(iseq);
1341 }
1342
1343 if (!iseq->body->location.label) {
1344 rb_raise(rb_eTypeError, "uninitialized InstructionSequence");
1345 }
1346 return iseq;
1347 }
1348
1349 const rb_iseq_t *
1350 rb_iseqw_to_iseq(VALUE iseqw)
1351 {
1352 return iseqw_check(iseqw);
1353 }
1354
1355 /*
1356 * call-seq:
1357 * iseq.eval -> obj
1358 *
1359 * Evaluates the instruction sequence and returns the result.
1360 *
1361 * RubyVM::InstructionSequence.compile("1 + 2").eval #=> 3
1362 */
1363 static VALUE
1364 iseqw_eval(VALUE self)
1365 {
1366 return rb_iseq_eval(iseqw_check(self));
1367 }
1368
1369 /*
1370 * Returns a human-readable string representation of this instruction
1371 * sequence, including the #label and #path.
1372 */
1373 static VALUE
1374 iseqw_inspect(VALUE self)
1375 {
1376 const rb_iseq_t *iseq = iseqw_check(self);
1377 const struct rb_iseq_constant_body *const body = iseq->body;
1378 VALUE klass = rb_class_name(rb_obj_class(self));
1379
1380 if (!body->location.label) {
1381 return rb_sprintf("#<%"PRIsVALUE": uninitialized>", klass);
1382 }
1383 else {
1384 return rb_sprintf("<%"PRIsVALUE":%"PRIsVALUE"@%"PRIsVALUE":%d>",
1385 klass,
1386 body->location.label, rb_iseq_path(iseq),
1387 FIX2INT(rb_iseq_first_lineno(iseq)));
1388 }
1389 }
1390
1391 /*
1392 * Returns the path of this instruction sequence.
1393 *
1394 * <code><compiled></code> if the iseq was evaluated from a string.
1395 *
1396 * For example, using irb:
1397 *
1398 * iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
1399 * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
1400 * iseq.path
1401 * #=> "<compiled>"
1402 *
1403 * Using ::compile_file:
1404 *
1405 * # /tmp/method.rb
1406 * def hello
1407 * puts "hello, world"
1408 * end
1409 *
1410 * # in irb
1411 * > iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
1412 * > iseq.path #=> /tmp/method.rb
1413 */
1414 static VALUE
1415 iseqw_path(VALUE self)
1416 {
1417 return rb_iseq_path(iseqw_check(self));
1418 }
1419
1420 /*
1421 * Returns the absolute path of this instruction sequence.
1422 *
1423 * +nil+ if the iseq was evaluated from a string.
1424 *
1425 * For example, using ::compile_file:
1426 *
1427 * # /tmp/method.rb
1428 * def hello
1429 * puts "hello, world"
1430 * end
1431 *
1432 * # in irb
1433 * > iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
1434 * > iseq.absolute_path #=> /tmp/method.rb
1435 */
1436 static VALUE
1437 iseqw_absolute_path(VALUE self)
1438 {
1439 return rb_iseq_realpath(iseqw_check(self));
1440 }
1441
1442 /* Returns the label of this instruction sequence.
1443 *
1444 * <code><main></code> if it's at the top level, <code><compiled></code> if it
1445 * was evaluated from a string.
1446 *
1447 * For example, using irb:
1448 *
1449 * iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
1450 * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
1451 * iseq.label
1452 * #=> "<compiled>"
1453 *
1454 * Using ::compile_file:
1455 *
1456 * # /tmp/method.rb
1457 * def hello
1458 * puts "hello, world"
1459 * end
1460 *
1461 * # in irb
1462 * > iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
1463 * > iseq.label #=> <main>
1464 */
1465 static VALUE
1466 iseqw_label(VALUE self)
1467 {
1468 return rb_iseq_label(iseqw_check(self));
1469 }
1470
1471 /* Returns the base label of this instruction sequence.
1472 *
1473 * For example, using irb:
1474 *
1475 * iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
1476 * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
1477 * iseq.base_label
1478 * #=> "<compiled>"
1479 *
1480 * Using ::compile_file:
1481 *
1482 * # /tmp/method.rb
1483 * def hello
1484 * puts "hello, world"
1485 * end
1486 *
1487 * # in irb
1488 * > iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
1489 * > iseq.base_label #=> <main>
1490 */
1491 static VALUE
1492 iseqw_base_label(VALUE self)
1493 {
1494 return rb_iseq_base_label(iseqw_check(self));
1495 }
1496
1497 /* Returns the number of the first source line where the instruction sequence
1498 * was loaded from.
1499 *
1500 * For example, using irb:
1501 *
1502 * iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
1503 * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
1504 * iseq.first_lineno
1505 * #=> 1
1506 */
1507 static VALUE
1508 iseqw_first_lineno(VALUE self)
1509 {
1510 return rb_iseq_first_lineno(iseqw_check(self));
1511 }
1512
1513 static VALUE iseq_data_to_ary(const rb_iseq_t *iseq);
1514
1515 /*
1516 * call-seq:
1517 * iseq.to_a -> ary
1518 *
1519 * Returns an Array with 14 elements representing the instruction sequence
1520 * with the following data:
1521 *
1522 * [magic]
1523 * A string identifying the data format. <b>Always
1524 * +YARVInstructionSequence/SimpleDataFormat+.</b>
1525 *
1526 * [major_version]
1527 * The major version of the instruction sequence.
1528 *
1529 * [minor_version]
1530 * The minor version of the instruction sequence.
1531 *
1532 * [format_type]
1533 * A number identifying the data format. <b>Always 1</b>.
1534 *
1535 * [misc]
1536 * A hash containing:
1537 *
1538 * [+:arg_size+]
1539 * the total number of arguments taken by the method or the block (0 if
1540 * _iseq_ doesn't represent a method or block)
1541 * [+:local_size+]
1542 * the number of local variables + 1
1543 * [+:stack_max+]
1544 * used in calculating the stack depth at which a SystemStackError is
1545 * thrown.
1546 *
1547 * [#label]
1548 * The name of the context (block, method, class, module, etc.) that this
1549 * instruction sequence belongs to.
1550 *
1551 * <code><main></code> if it's at the top level, <code><compiled></code> if
1552 * it was evaluated from a string.
1553 *
1554 * [#path]
1555 * The relative path to the Ruby file where the instruction sequence was
1556 * loaded from.
1557 *
1558 * <code><compiled></code> if the iseq was evaluated from a string.
1559 *
1560 * [#absolute_path]
1561 * The absolute path to the Ruby file where the instruction sequence was
1562 * loaded from.
1563 *
1564 * +nil+ if the iseq was evaluated from a string.
1565 *
1566 * [#first_lineno]
1567 * The number of the first source line where the instruction sequence was
1568 * loaded from.
1569 *
1570 * [type]
1571 * The type of the instruction sequence.
1572 *
1573 * Valid values are +:top+, +:method+, +:block+, +:class+, +:rescue+,
1574 * +:ensure+, +:eval+, +:main+, and +plain+.
1575 *
1576 * [locals]
1577 * An array containing the names of all arguments and local variables as
1578 * symbols.
1579 *
1580 * [params]
1581 * An Hash object containing parameter information.
1582 *
1583 * More info about these values can be found in +vm_core.h+.
1584 *
1585 * [catch_table]
1586 * A list of exceptions and control flow operators (rescue, next, redo,
1587 * break, etc.).
1588 *
1589 * [bytecode]
1590 * An array of arrays containing the instruction names and operands that
1591 * make up the body of the instruction sequence.
1592 *
1593 * Note that this format is MRI specific and version dependent.
1594 *
1595 */
1596 static VALUE
1597 iseqw_to_a(VALUE self)
1598 {
1599 const rb_iseq_t *iseq = iseqw_check(self);
1600 return iseq_data_to_ary(iseq);
1601 }
1602
1603 #if VM_INSN_INFO_TABLE_IMPL == 1 /* binary search */
1604 static const struct iseq_insn_info_entry *
1605 get_insn_info_binary_search(const rb_iseq_t *iseq, size_t pos)
1606 {
1607 const struct rb_iseq_constant_body *const body = iseq->body;
1608 size_t size = body->insns_info.size;
1609 const struct iseq_insn_info_entry *insns_info = body->insns_info.body;
1610 const unsigned int *positions = body->insns_info.positions;
1611 const int debug = 0;
1612
1613 if (debug) {
1614 printf("size: %"PRIuSIZE"\n", size);
1615 printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
1616 (size_t)0, positions[0], insns_info[0].line_no, pos);
1617 }
1618
1619 if (size == 0) {
1620 return NULL;
1621 }
1622 else if (size == 1) {
1623 return &insns_info[0];
1624 }
1625 else {
1626 size_t l = 1, r = size - 1;
1627 while (l <= r) {
1628 size_t m = l + (r - l) / 2;
1629 if (positions[m] == pos) {
1630 return &insns_info[m];
1631 }
1632 if (positions[m] < pos) {
1633 l = m + 1;
1634 }
1635 else {
1636 r = m - 1;
1637 }
1638 }
1639 if (l >= size) {
1640 return &insns_info[size-1];
1641 }
1642 if (positions[l] > pos) {
1643 return &insns_info[l-1];
1644 }
1645 return &insns_info[l];
1646 }
1647 }
1648
1649 static const struct iseq_insn_info_entry *
1650 get_insn_info(const rb_iseq_t *iseq, size_t pos)
1651 {
1652 return get_insn_info_binary_search(iseq, pos);
1653 }
1654 #endif
1655
1656 #if VM_INSN_INFO_TABLE_IMPL == 2 /* succinct bitvector */
1657 static const struct iseq_insn_info_entry *
1658 get_insn_info_succinct_bitvector(const rb_iseq_t *iseq, size_t pos)
1659 {
1660 const struct rb_iseq_constant_body *const body = iseq->body;
1661 size_t size = body->insns_info.size;
1662 const struct iseq_insn_info_entry *insns_info = body->insns_info.body;
1663 const int debug = 0;
1664
1665 if (debug) {
1666 #if VM_CHECK_MODE > 0
1667 const unsigned int *positions = body->insns_info.positions;
1668 printf("size: %"PRIuSIZE"\n", size);
1669 printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
1670 (size_t)0, positions[0], insns_info[0].line_no, pos);
1671 #else
1672 printf("size: %"PRIuSIZE"\n", size);
1673 printf("insns_info[%"PRIuSIZE"]: line: %d, pos: %"PRIuSIZE"\n",
1674 (size_t)0, insns_info[0].line_no, pos);
1675 #endif
1676 }
1677
1678 if (size == 0) {
1679 return NULL;
1680 }
1681 else if (size == 1) {
1682 return &insns_info[0];
1683 }
1684 else {
1685 int index;
1686 VM_ASSERT(body->insns_info.succ_index_table != NULL);
1687 index = succ_index_lookup(body->insns_info.succ_index_table, (int)pos);
1688 return &insns_info[index-1];
1689 }
1690 }
1691
1692 static const struct iseq_insn_info_entry *
1693 get_insn_info(const rb_iseq_t *iseq, size_t pos)
1694 {
1695 return get_insn_info_succinct_bitvector(iseq, pos);
1696 }
1697 #endif
1698
1699 #if VM_CHECK_MODE > 0 || VM_INSN_INFO_TABLE_IMPL == 0
1700 static const struct iseq_insn_info_entry *
1701 get_insn_info_linear_search(const rb_iseq_t *iseq, size_t pos)
1702 {
1703 const struct rb_iseq_constant_body *const body = iseq->body;
1704 size_t i = 0, size = body->insns_info.size;
1705 const struct iseq_insn_info_entry *insns_info = body->insns_info.body;
1706 const unsigned int *positions = body->insns_info.positions;
1707 const int debug = 0;
1708
1709 if (debug) {
1710 printf("size: %"PRIuSIZE"\n", size);
1711 printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
1712 i, positions[i], insns_info[i].line_no, pos);
1713 }
1714
1715 if (size == 0) {
1716 return NULL;
1717 }
1718 else if (size == 1) {
1719 return &insns_info[0];
1720 }
1721 else {
1722 for (i=1; i<size; i++) {
1723 if (debug) printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
1724 i, positions[i], insns_info[i].line_no, pos);
1725
1726 if (positions[i] == pos) {
1727 return &insns_info[i];
1728 }
1729 if (positions[i] > pos) {
1730 return &insns_info[i-1];
1731 }
1732 }
1733 }
1734 return &insns_info[i-1];
1735 }
1736 #endif
1737
1738 #if VM_INSN_INFO_TABLE_IMPL == 0 /* linear search */
1739 static const struct iseq_insn_info_entry *
1740 get_insn_info(const rb_iseq_t *iseq, size_t pos)
1741 {
1742 return get_insn_info_linear_search(iseq, pos);
1743 }
1744 #endif
1745
1746 #if VM_CHECK_MODE > 0 && VM_INSN_INFO_TABLE_IMPL > 0
1747 static void
1748 validate_get_insn_info(const rb_iseq_t *iseq)
1749 {
1750 const struct rb_iseq_constant_body *const body = iseq->body;
1751 size_t i;
1752 for (i = 0; i < body->iseq_size; i++) {
1753 if (get_insn_info_linear_search(iseq, i) != get_insn_info(iseq, i)) {
1754 rb_bug("validate_get_insn_info: get_insn_info_linear_search(iseq, %"PRIuSIZE") != get_insn_info(iseq, %"PRIuSIZE")", i, i);
1755 }
1756 }
1757 }
1758 #endif
1759
1760 unsigned int
1761 rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
1762 {
1763 const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos);
1764
1765 if (entry) {
1766 return entry->line_no;
1767 }
1768 else {
1769 return 0;
1770 }
1771 }
1772
1773 MJIT_FUNC_EXPORTED rb_event_flag_t
1774 rb_iseq_event_flags(const rb_iseq_t *iseq, size_t pos)
1775 {
1776 const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos);
1777 if (entry) {
1778 return entry->events;
1779 }
1780 else {
1781 return 0;
1782 }
1783 }
1784
1785 void
1786 rb_iseq_clear_event_flags(const rb_iseq_t *iseq, size_t pos, rb_event_flag_t reset)
1787 {
1788 struct iseq_insn_info_entry *entry = (struct iseq_insn_info_entry *)get_insn_info(iseq, pos);
1789 if (entry) {
1790 entry->events &= ~reset;
1791 if (!(entry->events & iseq->aux.exec.global_trace_events)) {
1792 void rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos);
1793 rb_iseq_trace_flag_cleared(iseq, pos);
1794 }
1795 }
1796 }
1797
1798 static VALUE
1799 local_var_name(const rb_iseq_t *diseq, VALUE level, VALUE op)
1800 {
1801 VALUE i;
1802 VALUE name;
1803 ID lid;
1804 int idx;
1805
1806 for (i = 0; i < level; i++) {
1807 diseq = diseq->body->parent_iseq;
1808 }
1809 idx = diseq->body->local_table_size - (int)op - 1;
1810 lid = diseq->body->local_table[idx];
1811 name = rb_id2str(lid);
1812 if (!name) {
1813 name = rb_str_new_cstr("?");
1814 }
1815 else if (!rb_str_symname_p(name)) {
1816 name = rb_str_inspect(name);
1817 }
1818 else {
1819 name = rb_str_dup(name);
1820 }
1821 rb_str_catf(name, "@%d", idx);
1822 return name;
1823 }
1824
1825 int rb_insn_unified_local_var_level(VALUE);
1826
1827 VALUE
1828 rb_insn_operand_intern(const rb_iseq_t *iseq,
1829 VALUE insn, int op_no, VALUE op,
1830 int len, size_t pos, const VALUE *pnop, VALUE child)
1831 {
1832 const char *types = insn_op_types(insn);
1833 char type = types[op_no];
1834 VALUE ret = Qundef;
1835
1836 switch (type) {
1837 case TS_OFFSET: /* LONG */
1838 ret = rb_sprintf("%"PRIdVALUE, (VALUE)(pos + len + op));
1839 break;
1840
1841 case TS_NUM: /* ULONG */
1842 if (insn == BIN(defined) && op_no == 0) {
1843 enum defined_type deftype = (enum defined_type)op;
1844 switch (deftype) {
1845 case DEFINED_FUNC:
1846 ret = rb_fstring_lit("func");
1847 break;
1848 case DEFINED_REF:
1849 ret = rb_fstring_lit("ref");
1850 break;
1851 case DEFINED_CONST_FROM:
1852 ret = rb_fstring_lit("constant-from");
1853 break;
1854 default:
1855 ret = rb_iseq_defined_string(deftype);
1856 break;
1857 }
1858 if (ret) break;
1859 }
1860 else if (insn == BIN(checktype) && op_no == 0) {
1861 const char *type_str = rb_type_str((enum ruby_value_type)op);
1862 if (type_str) {
1863 ret = rb_str_new_cstr(type_str); break;
1864 }
1865 }
1866 ret = rb_sprintf("%"PRIuVALUE, op);
1867 break;
1868
1869 case TS_LINDEX:{
1870 int level;
1871 if (types[op_no+1] == TS_NUM && pnop) {
1872 ret = local_var_name(iseq, *pnop, op - VM_ENV_DATA_SIZE);
1873 }
1874 else if ((level = rb_insn_unified_local_var_level(insn)) >= 0) {
1875 ret = local_var_name(iseq, (VALUE)level, op - VM_ENV_DATA_SIZE);
1876 }
1877 else {
1878 ret = rb_inspect(INT2FIX(op));
1879 }
1880 break;
1881 }
1882 case TS_ID: /* ID (symbol) */
1883 ret = rb_inspect(ID2SYM(op));
1884 break;
1885
1886 case TS_VALUE: /* VALUE */
1887 op = obj_resurrect(op);
1888 if (insn == BIN(defined) && op_no == 1 && FIXNUM_P(op)) {
1889 /* should be DEFINED_REF */
1890 int type = NUM2INT(op);
1891 if (type) {
1892 if (type & 1) {
1893 ret = rb_sprintf(":$%c", (type >> 1));
1894 }
1895 else {
1896 ret = rb_sprintf(":$%d", (type >> 1));
1897 }
1898 break;
1899 }
1900 }
1901 ret = rb_inspect(op);
1902 if (CLASS_OF(op) == rb_cISeq) {
1903 if (child) {
1904 rb_ary_push(child, op);
1905 }
1906 }
1907 break;
1908
1909 case TS_ISEQ: /* iseq */
1910 {
1911 if (op) {
1912 const rb_iseq_t *iseq = rb_iseq_check((rb_iseq_t *)op);
1913 ret = iseq->body->location.label;
1914 if (child) {
1915 rb_ary_push(child, (VALUE)iseq);
1916 }
1917 }
1918 else {
1919 ret = rb_str_new2("nil");
1920 }
1921 break;
1922 }
1923 case TS_GENTRY:
1924 {
1925 struct rb_global_entry *entry = (struct rb_global_entry *)op;
1926 ret = rb_str_dup(rb_id2str(entry->id));
1927 }
1928 break;
1929
1930 case TS_IC:
1931 case TS_IVC:
1932 case TS_ISE:
1933 ret = rb_sprintf("<is:%"PRIdPTRDIFF">", (union iseq_inline_storage_entry *)op - iseq->body->is_entries);
1934 break;
1935
1936 case TS_CALLDATA:
1937 {
1938 struct rb_call_data *cd = (struct rb_call_data *)op;
1939 struct rb_call_info *ci = &cd->ci;
1940 VALUE ary = rb_ary_new();
1941
1942 if (ci->mid) {
1943 rb_ary_push(ary, rb_sprintf("mid:%"PRIsVALUE, rb_id2str(ci->mid)));
1944 }
1945
1946 rb_ary_push(ary, rb_sprintf("argc:%d", ci->orig_argc));
1947
1948 if (ci->flag & VM_CALL_KWARG) {
1949 struct rb_call_info_kw_arg *kw_args = ((struct rb_call_info_with_kwarg *)ci)->kw_arg;
1950 VALUE kw_ary = rb_ary_new_from_values(kw_args->keyword_len, kw_args->keywords);
1951 rb_ary_push(ary, rb_sprintf("kw:[%"PRIsVALUE"]", rb_ary_join(kw_ary, rb_str_new2(","))));
1952 }
1953
1954 if (ci->flag) {
1955 VALUE flags = rb_ary_new();
1956 # define CALL_FLAG(n) if (ci->flag & VM_CALL_##n) rb_ary_push(flags, rb_str_new2(#n))
1957 CALL_FLAG(ARGS_SPLAT);
1958 CALL_FLAG(ARGS_BLOCKARG);
1959 CALL_FLAG(FCALL);
1960 CALL_FLAG(VCALL);
1961 CALL_FLAG(ARGS_SIMPLE);
1962 CALL_FLAG(BLOCKISEQ);
1963 CALL_FLAG(TAILCALL);
1964 CALL_FLAG(SUPER);
1965 CALL_FLAG(ZSUPER);
1966 CALL_FLAG(KWARG);
1967 CALL_FLAG(KW_SPLAT);
1968 CALL_FLAG(OPT_SEND); /* maybe not reachable */
1969 rb_ary_push(ary, rb_ary_join(flags, rb_str_new2("|")));
1970 }
1971
1972 ret = rb_sprintf("<calldata!%"PRIsVALUE">", rb_ary_join(ary, rb_str_new2(", ")));
1973 }
1974 break;
1975
1976 case TS_CDHASH:
1977 ret = rb_str_new2("<cdhash>");
1978 break;
1979
1980 case TS_FUNCPTR:
1981 {
1982 #ifdef HAVE_DLADDR
1983 Dl_info info;
1984 if (dladdr((void *)op, &info) && info.dli_sname) {
1985 ret = rb_str_new_cstr(info.dli_sname);
1986 break;
1987 }
1988 #endif
1989 ret = rb_str_new2("<funcptr>");
1990 }
1991 break;
1992
1993 case TS_BUILTIN:
1994 {
1995 const struct rb_builtin_function *bf = (const struct rb_builtin_function *)op;
1996 ret = rb_sprintf("<builtin!%s/%d>",
1997 bf->name, bf->argc);
1998 }
1999 break;
2000
2001 default:
2002 rb_bug("unknown operand type: %c", type);
2003 }
2004 return ret;
2005 }
2006
2007 static VALUE
2008 right_strip(VALUE str)
2009 {
2010 const char *beg = RSTRING_PTR(str), *end = RSTRING_END(str);
2011 while (end-- > beg && *end == ' ');
2012 rb_str_set_len(str, end - beg + 1);
2013 return str;
2014 }
2015
2020 int
2021 rb_iseq_disasm_insn(VALUE ret, const VALUE *code, size_t pos,
2022 const rb_iseq_t *iseq, VALUE child)
2023 {
2024 VALUE insn = code[pos];
2025 int len = insn_len(insn);
2026 int j;
2027 const char *types = insn_op_types(insn);
2028 VALUE str = rb_str_new(0, 0);
2029 const char *insn_name_buff;
2030
2031 insn_name_buff = insn_name(insn);
2032 if (1) {
2033 extern const int rb_vm_max_insn_name_size;
2034 rb_str_catf(str, "%04"PRIuSIZE" %-*s ", pos, rb_vm_max_insn_name_size, insn_name_buff);
2035 }
2036 else {
2037 rb_str_catf(str, "%04"PRIuSIZE" %-28.*s ", pos,
2038 (int)strcspn(insn_name_buff, "_"), insn_name_buff);
2039 }
2040
2041 for (j = 0; types[j]; j++) {
2042 VALUE opstr = rb_insn_operand_intern(iseq, insn, j, code[pos + j + 1],
2043 len, pos, &code[pos + j + 2],
2044 child);
2045 rb_str_concat(str, opstr);
2046
2047 if (types[j + 1]) {
2048 rb_str_cat2(str, ", ");
2049 }
2050 }
2051
2052 {
2053 unsigned int line_no = rb_iseq_line_no(iseq, pos);
2054 unsigned int prev = pos == 0 ? 0 : rb_iseq_line_no(iseq, pos - 1);
2055 if (line_no && line_no != prev) {
2056 long slen = RSTRING_LEN(str);
2057 slen = (slen > 70) ? 0 : (70 - slen);
2058 str = rb_str_catf(str, "%*s(%4d)", (int)slen, "", line_no);
2059 }
2060 }
2061
2062 {
2063 rb_event_flag_t events = rb_iseq_event_flags(iseq, pos);
2064 if (events) {
2065 str = rb_str_catf(str, "[%s%s%s%s%s%s%s%s%s%s%s]",
2066 events & RUBY_EVENT_LINE ? "Li" : "",
2067 events & RUBY_EVENT_CLASS ? "Cl" : "",
2068 events & RUBY_EVENT_END ? "En" : "",
2069 events & RUBY_EVENT_CALL ? "Ca" : "",
2070 events & RUBY_EVENT_RETURN ? "Re" : "",
2071 events & RUBY_EVENT_C_CALL ? "Cc" : "",
2072 events & RUBY_EVENT_C_RETURN ? "Cr" : "",
2073 events & RUBY_EVENT_B_CALL ? "Bc" : "",
2074 events & RUBY_EVENT_B_RETURN ? "Br" : "",
2075 events & RUBY_EVENT_COVERAGE_LINE ? "Cli" : "",
2076 events & RUBY_EVENT_COVERAGE_BRANCH ? "Cbr" : "");
2077 }
2078 }
2079
2080 right_strip(str);
2081 if (ret) {
2082 rb_str_cat2(str, "\n");
2083 rb_str_concat(ret, str);
2084 }
2085 else {
2086 printf("%.*s\n", (int)RSTRING_LEN(str), RSTRING_PTR(str));
2087 }
2088 return len;
2089 }
2090
2091 static const char *
2092 catch_type(int type)
2093 {
2094 switch (type) {
2095 case CATCH_TYPE_RESCUE:
2096 return "rescue";
2097 case CATCH_TYPE_ENSURE:
2098 return "ensure";
2099 case CATCH_TYPE_RETRY:
2100 return "retry";
2101 case CATCH_TYPE_BREAK:
2102 return "break";
2103 case CATCH_TYPE_REDO:
2104 return "redo";
2105 case CATCH_TYPE_NEXT:
2106 return "next";
2107 default:
2108 rb_bug("unknown catch type: %d", type);
2109 return 0;
2110 }
2111 }
2112
2113 static VALUE
2114 iseq_inspect(const rb_iseq_t *iseq)
2115 {
2116 const struct rb_iseq_constant_body *const body = iseq->body;
2117 if (!body->location.label) {
2118 return rb_sprintf("#<ISeq: uninitialized>");
2119 }
2120 else {
2121 const rb_code_location_t *loc = &body->location.code_location;
2122 return rb_sprintf("#<ISeq:%"PRIsVALUE"@%"PRIsVALUE":%d (%d,%d)-(%d,%d)>",
2123 body->location.label, rb_iseq_path(iseq),
2124 loc->beg_pos.lineno,
2125 loc->beg_pos.lineno,
2126 loc->beg_pos.column,
2127 loc->end_pos.lineno,
2128 loc->end_pos.column);
2129 }
2130 }
2131
2132 static const rb_data_type_t tmp_set = {
2133 "tmpset",
2134 {(void (*)(void *))rb_mark_set, (void (*)(void *))st_free_table, 0, 0,},
2135 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2136 };
2137
2138 static VALUE
2139 rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent)
2140 {
2141 const struct rb_iseq_constant_body *const body = iseq->body;
2142 VALUE *code;
2143 VALUE str = rb_str_new(0, 0);
2144 VALUE child = rb_ary_tmp_new(3);
2145 unsigned int size;
2146 unsigned int i;
2147 long l;
2148 size_t n;
2149 enum {header_minlen = 72};
2150 st_table *done_iseq = 0;
2151 VALUE done_iseq_wrapper = Qnil;
2152 const char *indent_str;
2153 long indent_len;
2154
2155 size = body->iseq_size;
2156
2157 indent_len = RSTRING_LEN(indent);
2158 indent_str = RSTRING_PTR(indent);
2159
2160 rb_str_cat(str, indent_str, indent_len);
2161 rb_str_cat2(str, "== disasm: ");
2162
2163 rb_str_append(str, iseq_inspect(iseq));
2164 rb_str_catf(str, " (catch: %s)", body->catch_except_p ? "TRUE" : "FALSE");
2165 if ((l = RSTRING_LEN(str) - indent_len) < header_minlen) {
2166 rb_str_modify_expand(str, header_minlen - l);
2167 memset(RSTRING_END(str), '=', header_minlen - l);
2168 }
2169 rb_str_cat2(str, "\n");
2170
2171 /* show catch table information */
2172 if (body->catch_table) {
2173 rb_str_cat(str, indent_str, indent_len);
2174 rb_str_cat2(str, "== catch table\n");
2175 }
2176 if (body->catch_table) {
2177 rb_str_cat_cstr(indent, "| ");
2178 indent_str = RSTRING_PTR(indent);
2179 for (i = 0; i < body->catch_table->size; i++) {
2180 const struct iseq_catch_table_entry *entry =
2181 UNALIGNED_MEMBER_PTR(body->catch_table, entries[i]);
2182 rb_str_cat(str, indent_str, indent_len);
2183 rb_str_catf(str,
2184 "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
2185 catch_type((int)entry->type), (int)entry->start,
2186 (int)entry->end, (int)entry->sp, (int)entry->cont);
2187 if (entry->iseq && !(done_iseq && st_is_member(done_iseq, (st_data_t)entry->iseq))) {
2188 rb_str_concat(str, rb_iseq_disasm_recursive(rb_iseq_check(entry->iseq), indent));
2189 if (!done_iseq) {
2190 done_iseq = st_init_numtable();
2191 done_iseq_wrapper = TypedData_Wrap_Struct(0, &tmp_set, done_iseq);
2192 }
2193 st_insert(done_iseq, (st_data_t)entry->iseq, (st_data_t)0);
2194 indent_str = RSTRING_PTR(indent);
2195 }
2196 }
2197 rb_str_resize(indent, indent_len);
2198 indent_str = RSTRING_PTR(indent);
2199 }
2200 if (body->catch_table) {
2201 rb_str_cat(str, indent_str, indent_len);
2202 rb_str_cat2(str, "|-------------------------------------"
2203 "-----------------------------------\n");
2204 }
2205
2206 /* show local table information */
2207 if (body->local_table) {
2208 const struct rb_iseq_param_keyword *const keyword = body->param.keyword;
2209 rb_str_cat(str, indent_str, indent_len);
2210 rb_str_catf(str,
2211 "local table (size: %d, argc: %d "
2212 "[opts: %d, rest: %d, post: %d, block: %d, kw: %d@%d, kwrest: %d])\n",
2213 body->local_table_size,
2214 body->param.lead_num,
2215 body->param.opt_num,
2216 body->param.flags.has_rest ? body->param.rest_start : -1,
2217 body->param.post_num,
2218 body->param.flags.has_block ? body->param.block_start : -1,
2219 body->param.flags.has_kw ? keyword->num : -1,
2220 body->param.flags.has_kw ? keyword->required_num : -1,
2221 body->param.flags.has_kwrest ? keyword->rest_start : -1);
2222
2223 for (i = body->local_table_size; i > 0;) {
2224 int li = body->local_table_size - --i - 1;
2225 long width;
2226 VALUE name = local_var_name(iseq, 0, i);
2227 char argi[0x100];
2228 char opti[0x100];
2229
2230 opti[0] = '\0';
2231 if (body->param.flags.has_opt) {
2232 int argc = body->param.lead_num;
2233 int opts = body->param.opt_num;
2234 if (li >= argc && li < argc + opts) {
2235 snprintf(opti, sizeof(opti), "Opt=%"PRIdVALUE,
2236 body->param.opt_table[li - argc]);
2237 }
2238 }
2239
2240 snprintf(argi, sizeof(argi), "%s%s%s%s%s%s", /* arg, opts, rest, post, kwrest, block */
2241 body->param.lead_num > li ? "Arg" : "",
2242 opti,
2243 (body->param.flags.has_rest && body->param.rest_start == li) ? "Rest" : "",
2244 (body->param.flags.has_post && body->param.post_start <= li && li < body->param.post_start + body->param.post_num) ? "Post" : "",
2245 (body->param.flags.has_kwrest && keyword->rest_start == li) ? "Kwrest" : "",
2246 (body->param.flags.has_block && body->param.block_start == li) ? "Block" : "");
2247
2248 rb_str_cat(str, indent_str, indent_len);
2249 rb_str_catf(str, "[%2d] ", i + 1);
2250 width = RSTRING_LEN(str) + 11;
2251 rb_str_append(str, name);
2252 if (*argi) rb_str_catf(str, "<%s>", argi);
2253 if ((width -= RSTRING_LEN(str)) > 0) rb_str_catf(str, "%*s", (int)width, "");
2254 }
2255 rb_str_cat_cstr(right_strip(str), "\n");
2256 }
2257
2258 /* show each line */
2259 code = rb_iseq_original_iseq(iseq);
2260 for (n = 0; n < size;) {
2261 rb_str_cat(str, indent_str, indent_len);
2262 n += rb_iseq_disasm_insn(str, code, n, iseq, child);
2263 }
2264
2265 for (l = 0; l < RARRAY_LEN(child); l++) {
2266 VALUE isv = rb_ary_entry(child, l);
2267 if (done_iseq && st_is_member(done_iseq, (st_data_t)isv)) continue;
2268 rb_str_cat_cstr(str, "\n");
2269 rb_str_concat(str, rb_iseq_disasm_recursive(rb_iseq_check((rb_iseq_t *)isv), indent));
2270 indent_str = RSTRING_PTR(indent);
2271 }
2272 RB_GC_GUARD(done_iseq_wrapper);
2273
2274 return str;
2275 }
2276
2277 VALUE
2278 rb_iseq_disasm(const rb_iseq_t *iseq)
2279 {
2280 return rb_iseq_disasm_recursive(iseq, rb_str_new(0, 0));
2281 }
2282
2283 /*
2284 * call-seq:
2285 * iseq.disasm -> str
2286 * iseq.disassemble -> str
2287 *
2288 * Returns the instruction sequence as a +String+ in human readable form.
2289 *
2290 * puts RubyVM::InstructionSequence.compile('1 + 2').disasm
2291 *
2292 * Produces:
2293 *
2294 * == disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
2295 * 0000 trace 1 ( 1)
2296 * 0002 putobject 1
2297 * 0004 putobject 2
2298 * 0006 opt_plus <ic:1>
2299 * 0008 leave
2300 */
2301 static VALUE
2302 iseqw_disasm(VALUE self)
2303 {
2304 return rb_iseq_disasm(iseqw_check(self));
2305 }
2306
2307 static int
2308 iseq_iterate_children(const rb_iseq_t *iseq, void (*iter_func)(const rb_iseq_t *child_iseq, void *data), void *data)
2309 {
2310 unsigned int i;
2311 VALUE *code = rb_iseq_original_iseq(iseq);
2312 const struct rb_iseq_constant_body *const body = iseq->body;
2313 const rb_iseq_t *child;
2314 VALUE all_children = rb_obj_hide(rb_ident_hash_new());
2315
2316 if (body->catch_table) {
2317 for (i = 0; i < body->catch_table->size; i++) {
2318 const struct iseq_catch_table_entry *entry =
2319 UNALIGNED_MEMBER_PTR(body->catch_table, entries[i]);
2320 child = entry->iseq;
2321 if (child) {
2322 if (rb_hash_aref(all_children, (VALUE)child) == Qnil) {
2323 rb_hash_aset(all_children, (VALUE)child, Qtrue);
2324 (*iter_func)(child, data);
2325 }
2326 }
2327 }
2328 }
2329
2330 for (i=0; i<body->iseq_size;) {
2331 VALUE insn = code[i];
2332 int len = insn_len(insn);
2333 const char *types = insn_op_types(insn);
2334 int j;
2335
2336 for (j=0; types[j]; j++) {
2337 switch (types[j]) {
2338 case TS_ISEQ:
2339 child = (const rb_iseq_t *)code[i+j+1];
2340 if (child) {
2341 if (rb_hash_aref(all_children, (VALUE)child) == Qnil) {
2342 rb_hash_aset(all_children, (VALUE)child, Qtrue);
2343 (*iter_func)(child, data);
2344 }
2345 }
2346 break;
2347 default:
2348 break;
2349 }
2350 }
2351 i += len;
2352 }
2353
2354 return (int)RHASH_SIZE(all_children);
2355 }
2356
2357 static void
2358 yield_each_children(const rb_iseq_t *child_iseq, void *data)
2359 {
2360 rb_yield(iseqw_new(child_iseq));
2361 }
2362
2363 /*
2364 * call-seq:
2365 * iseq.each_child{|child_iseq| ...} -> iseq
2366 *
2367 * Iterate all direct child instruction sequences.
2368 * Iteration order is implementation/version defined
2369 * so that people should not rely on the order.
2370 */
2371 static VALUE
2372 iseqw_each_child(VALUE self)
2373 {
2374 const rb_iseq_t *iseq = iseqw_check(self);
2375 iseq_iterate_children(iseq, yield_each_children, NULL);
2376 return self;
2377 }
2378
2379 static void
2380 push_event_info(const rb_iseq_t *iseq, rb_event_flag_t events, int line, VALUE ary)
2381 {
2382 #define C(ev, cstr, l) if (events & ev) rb_ary_push(ary, rb_ary_new_from_args(2, l, ID2SYM(rb_intern(cstr))));
2383 C(RUBY_EVENT_CLASS, "class", rb_iseq_first_lineno(iseq));
2384 C(RUBY_EVENT_CALL, "call", rb_iseq_first_lineno(iseq));
2385 C(RUBY_EVENT_B_CALL, "b_call", rb_iseq_first_lineno(iseq));
2386 C(RUBY_EVENT_LINE, "line", INT2FIX(line));
2387 C(RUBY_EVENT_END, "end", INT2FIX(line));
2388 C(RUBY_EVENT_RETURN, "return", INT2FIX(line));
2389 C(RUBY_EVENT_B_RETURN, "b_return", INT2FIX(line));
2390 #undef C
2391 }
2392
2393 /*
2394 * call-seq:
2395 * iseq.trace_points -> ary
2396 *
2397 * Return trace points in the instruction sequence.
2398 * Return an array of [line, event_symbol] pair.
2399 */
2400 static VALUE
2401 iseqw_trace_points(VALUE self)
2402 {
2403 const rb_iseq_t *iseq = iseqw_check(self);
2404 const struct rb_iseq_constant_body *const body = iseq->body;
2405 unsigned int i;
2406 VALUE ary = rb_ary_new();
2407
2408 for (i=0; i<body->insns_info.size; i++) {
2409 const struct iseq_insn_info_entry *entry = &body->insns_info.body[i];
2410 if (entry->events) {
2411 push_event_info(iseq, entry->events, entry->line_no, ary);
2412 }
2413 }
2414 return ary;
2415 }
2416
2417 /*
2418 * Returns the instruction sequence containing the given proc or method.
2419 *
2420 * For example, using irb:
2421 *
2422 * # a proc
2423 * > p = proc { num = 1 + 2 }
2424 * > RubyVM::InstructionSequence.of(p)
2425 * > #=> <RubyVM::InstructionSequence:block in irb_binding@(irb)>
2426 *
2427 * # for a method
2428 * > def foo(bar); puts bar; end
2429 * > RubyVM::InstructionSequence.of(method(:foo))
2430 * > #=> <RubyVM::InstructionSequence:foo@(irb)>
2431 *
2432 * Using ::compile_file:
2433 *
2434 * # /tmp/iseq_of.rb
2435 * def hello
2436 * puts "hello, world"
2437 * end
2438 *
2439 * $a_global_proc = proc { str = 'a' + 'b' }
2440 *
2441 * # in irb
2442 * > require '/tmp/iseq_of.rb'
2443 *
2444 * # first the method hello
2445 * > RubyVM::InstructionSequence.of(method(:hello))
2446 * > #=> #<RubyVM::InstructionSequence:0x007fb73d7cb1d0>
2447 *
2448 * # then the global proc
2449 * > RubyVM::InstructionSequence.of($a_global_proc)
2450 * > #=> #<RubyVM::InstructionSequence:0x007fb73d7caf78>
2451 */
2452 static VALUE
2453 iseqw_s_of(VALUE klass, VALUE body)
2454 {
2455 const rb_iseq_t *iseq = NULL;
2456
2457 if (rb_obj_is_proc(body)) {
2458 iseq = vm_proc_iseq(body);
2459
2460 if (!rb_obj_is_iseq((VALUE)iseq)) {
2461 iseq = NULL;
2462 }
2463 }
2464 else if (rb_obj_is_method(body)) {
2465 iseq = rb_method_iseq(body);
2466 }
2467 else if (rb_typeddata_is_instance_of(body, &iseqw_data_type)) {
2468 return body;
2469 }
2470
2471 return iseq ? iseqw_new(iseq) : Qnil;
2472 }
2473
2474 /*
2475 * call-seq:
2476 * InstructionSequence.disasm(body) -> str
2477 * InstructionSequence.disassemble(body) -> str
2478 *
2479 * Takes +body+, a Method or Proc object, and returns a String with the
2480 * human readable instructions for +body+.
2481 *
2482 * For a Method object:
2483 *
2484 * # /tmp/method.rb
2485 * def hello
2486 * puts "hello, world"
2487 * end
2488 *
2489 * puts RubyVM::InstructionSequence.disasm(method(:hello))
2490 *
2491 * Produces:
2492 *
2493 * == disasm: <RubyVM::InstructionSequence:hello@/tmp/method.rb>============
2494 * 0000 trace 8 ( 1)
2495 * 0002 trace 1 ( 2)
2496 * 0004 putself
2497 * 0005 putstring "hello, world"
2498 * 0007 send :puts, 1, nil, 8, <ic:0>
2499 * 0013 trace 16 ( 3)
2500 * 0015 leave ( 2)
2501 *
2502 * For a Proc:
2503 *
2504 * # /tmp/proc.rb
2505 * p = proc { num = 1 + 2 }
2506 * puts RubyVM::InstructionSequence.disasm(p)
2507 *
2508 * Produces:
2509 *
2510 * == disasm: <RubyVM::InstructionSequence:block in <main>@/tmp/proc.rb>===
2511 * == catch table
2512 * | catch type: redo st: 0000 ed: 0012 sp: 0000 cont: 0000
2513 * | catch type: next st: 0000 ed: 0012 sp: 0000 cont: 0012
2514 * |------------------------------------------------------------------------
2515 * local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
2516 * [ 2] num
2517 * 0000 trace 1 ( 1)
2518 * 0002 putobject 1
2519 * 0004 putobject 2
2520 * 0006 opt_plus <ic:1>
2521 * 0008 dup
2522 * 0009 setlocal num, 0
2523 * 0012 leave
2524 *
2525 */
2526 static VALUE
2527 iseqw_s_disasm(VALUE klass, VALUE body)
2528 {
2529 VALUE iseqw = iseqw_s_of(klass, body);
2530 return NIL_P(iseqw) ? Qnil : rb_iseq_disasm(iseqw_check(iseqw));
2531 }
2532
2533 const char *
2534 ruby_node_name(int node)
2535 {
2536 switch (node) {
2537 #include "node_name.inc"
2538 default:
2539 rb_bug("unknown node: %d", node);
2540 return 0;
2541 }
2542 }
2543
2544 #define DECL_SYMBOL(name) \
2545 static ID sym_##name
2546
2547 #define INIT_SYMBOL(name) \
2548 sym_##name = rb_intern(#name)
2549
2550 static VALUE
2551 register_label(struct st_table *table, unsigned long idx)
2552 {
2553 VALUE sym = rb_str_intern(rb_sprintf("label_%lu", idx));
2554 st_insert(table, idx, sym);
2555 return sym;
2556 }
2557
2558 static VALUE
2559 exception_type2symbol(VALUE type)
2560 {
2561 ID id;
2562 switch (type) {
2563 case CATCH_TYPE_RESCUE: CONST_ID(id, "rescue"); break;
2564 case CATCH_TYPE_ENSURE: CONST_ID(id, "ensure"); break;
2565 case CATCH_TYPE_RETRY: CONST_ID(id, "retry"); break;
2566 case CATCH_TYPE_BREAK: CONST_ID(id, "break"); break;
2567 case CATCH_TYPE_REDO: CONST_ID(id, "redo"); break;
2568 case CATCH_TYPE_NEXT: CONST_ID(id, "next"); break;
2569 default:
2570 rb_bug("unknown exception type: %d", (int)type);
2571 }
2572 return ID2SYM(id);
2573 }
2574
2575 static int
2576 cdhash_each(VALUE key, VALUE value, VALUE ary)
2577 {
2578 rb_ary_push(ary, obj_resurrect(key));
2579 rb_ary_push(ary, value);
2580 return ST_CONTINUE;
2581 }
2582
2583 static const rb_data_type_t label_wrapper = {
2584 "label_wrapper",
2585 {(void (*)(void *))rb_mark_tbl, (void (*)(void *))st_free_table, 0, 0,},
2586 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
2587 };
2588
2589 static VALUE
2590 iseq_data_to_ary(const rb_iseq_t *iseq)
2591 {
2592 unsigned int i;
2593 long l;
2594 const struct rb_iseq_constant_body *const iseq_body = iseq->body;
2595 const struct iseq_insn_info_entry *prev_insn_info;
2596 unsigned int pos;
2597 int last_line = 0;
2598 VALUE *seq, *iseq_original;
2599
2600 VALUE val = rb_ary_new();
2601 ID type; /* Symbol */
2602 VALUE locals = rb_ary_new();
2603 VALUE params = rb_hash_new();
2604 VALUE body = rb_ary_new(); /* [[:insn1, ...], ...] */
2605 VALUE nbody;
2606 VALUE exception = rb_ary_new(); /* [[....]] */
2607 VALUE misc = rb_hash_new();
2608
2609 static ID insn_syms[VM_INSTRUCTION_SIZE/2]; /* w/o-trace only */
2610 struct st_table *labels_table = st_init_numtable();
2611 VALUE labels_wrapper = TypedData_Wrap_Struct(0, &label_wrapper, labels_table);
2612
2613 DECL_SYMBOL(top);
2614 DECL_SYMBOL(method);
2615 DECL_SYMBOL(block);
2616 DECL_SYMBOL(class);
2617 DECL_SYMBOL(rescue);
2618 DECL_SYMBOL(ensure);
2619 DECL_SYMBOL(eval);
2620 DECL_SYMBOL(main);
2621 DECL_SYMBOL(plain);
2622
2623 if (sym_top == 0) {
2624 int i;
2625 for (i=0; i<numberof(insn_syms); i++) {
2626 insn_syms[i] = rb_intern(insn_name(i));
2627 }
2628 INIT_SYMBOL(top);
2629 INIT_SYMBOL(method);
2630 INIT_SYMBOL(block);
2631 INIT_SYMBOL(class);
2632 INIT_SYMBOL(rescue);
2633 INIT_SYMBOL(ensure);
2634 INIT_SYMBOL(eval);
2635 INIT_SYMBOL(main);
2636 INIT_SYMBOL(plain);
2637 }
2638
2639 /* type */
2640 switch (iseq_body->type) {
2641 case ISEQ_TYPE_TOP: type = sym_top; break;
2642 case ISEQ_TYPE_METHOD: type = sym_method; break;
2643 case ISEQ_TYPE_BLOCK: type = sym_block; break;
2644 case ISEQ_TYPE_CLASS: type = sym_class; break;
2645 case ISEQ_TYPE_RESCUE: type = sym_rescue; break;
2646 case ISEQ_TYPE_ENSURE: type = sym_ensure; break;
2647 case ISEQ_TYPE_EVAL: type = sym_eval; break;
2648 case ISEQ_TYPE_MAIN: type = sym_main; break;
2649 case ISEQ_TYPE_PLAIN: type = sym_plain; break;
2650 default: rb_bug("unsupported iseq type: %d", (int)iseq_body->type);
2651 };
2652
2653 /* locals */
2654 for (i=0; i<iseq_body->local_table_size; i++) {
2655 ID lid = iseq_body->local_table[i];
2656 if (lid) {
2657 if (rb_id2str(lid)) {
2658 rb_ary_push(locals, ID2SYM(lid));
2659 }
2660 else { /* hidden variable from id_internal() */
2661 rb_ary_push(locals, ULONG2NUM(iseq_body->local_table_size-i+1));
2662 }
2663 }
2664 else {
2665 rb_ary_push(locals, ID2SYM(rb_intern("#arg_rest")));
2666 }
2667 }
2668
2669 /* params */
2670 {
2671 const struct rb_iseq_param_keyword *const keyword = iseq_body->param.keyword;
2672 int j;
2673
2674 if (iseq_body->param.flags.has_opt) {
2675 int len = iseq_body->param.opt_num + 1;
2676 VALUE arg_opt_labels = rb_ary_new2(len);
2677
2678 for (j = 0; j < len; j++) {
2679 VALUE l = register_label(labels_table, iseq_body->param.opt_table[j]);
2680 rb_ary_push(arg_opt_labels, l);
2681 }
2682 rb_hash_aset(params, ID2SYM(rb_intern("opt")), arg_opt_labels);
2683 }
2684
2685 /* commit */
2686 if (iseq_body->param.flags.has_lead) rb_hash_aset(params, ID2SYM(rb_intern("lead_num")), INT2FIX(iseq_body->param.lead_num));
2687 if (iseq_body->param.flags.has_post) rb_hash_aset(params, ID2SYM(rb_intern("post_num")), INT2FIX(iseq_body->param.post_num));
2688 if (iseq_body->param.flags.has_post) rb_hash_aset(params, ID2SYM(rb_intern("post_start")), INT2FIX(iseq_body->param.post_start));
2689 if (iseq_body->param.flags.has_rest) rb_hash_aset(params, ID2SYM(rb_intern("rest_start")), INT2FIX(iseq_body->param.rest_start));
2690 if (iseq_body->param.flags.has_block) rb_hash_aset(params, ID2SYM(rb_intern("block_start")), INT2FIX(iseq_body->param.block_start));
2691 if (iseq_body->param.flags.has_kw) {
2692 VALUE keywords = rb_ary_new();
2693 int i, j;
2694 for (i=0; i<keyword->required_num; i++) {
2695 rb_ary_push(keywords, ID2SYM(keyword->table[i]));
2696 }
2697 for (j=0; i<keyword->num; i++, j++) {
2698 VALUE key = rb_ary_new_from_args(1, ID2SYM(keyword->table[i]));
2699 if (keyword->default_values[j] != Qundef) {
2700 rb_ary_push(key, keyword->default_values[j]);
2701 }
2702 rb_ary_push(keywords, key);
2703 }
2704
2705 rb_hash_aset(params, ID2SYM(rb_intern("kwbits")),
2706 INT2FIX(keyword->bits_start));
2707 rb_hash_aset(params, ID2SYM(rb_intern("keyword")), keywords);
2708 }
2709 if (iseq_body->param.flags.has_kwrest) rb_hash_aset(params, ID2SYM(rb_intern("kwrest")), INT2FIX(keyword->rest_start));
2710 if (iseq_body->param.flags.ambiguous_param0) rb_hash_aset(params, ID2SYM(rb_intern("ambiguous_param0")), Qtrue);
2711 }
2712
2713 /* body */
2714 iseq_original = rb_iseq_original_iseq((rb_iseq_t *)iseq);
2715
2716 for (seq = iseq_original; seq < iseq_original + iseq_body->iseq_size; ) {
2717 VALUE insn = *seq++;
2718 int j, len = insn_len(insn);
2719 VALUE *nseq = seq + len - 1;
2720 VALUE ary = rb_ary_new2(len);
2721
2722 rb_ary_push(ary, ID2SYM(insn_syms[insn%numberof(insn_syms)]));
2723 for (j=0; j<len-1; j++, seq++) {
2724 switch (insn_op_type(insn, j)) {
2725 case TS_OFFSET: {
2726 unsigned long idx = nseq - iseq_original + *seq;
2727 rb_ary_push(ary, register_label(labels_table, idx));
2728 break;
2729 }
2730 case TS_LINDEX:
2731 case TS_NUM:
2732 rb_ary_push(ary, INT2FIX(*seq));
2733 break;
2734 case TS_VALUE:
2735 rb_ary_push(ary, obj_resurrect(*seq));
2736 break;
2737 case TS_ISEQ:
2738 {
2739 const rb_iseq_t *iseq = (rb_iseq_t *)*seq;
2740 if (iseq) {
2741 VALUE val = iseq_data_to_ary(rb_iseq_check(iseq));
2742 rb_ary_push(ary, val);
2743 }
2744 else {
2745 rb_ary_push(ary, Qnil);
2746 }
2747 }
2748 break;
2749 case TS_GENTRY:
2750 {
2751 struct rb_global_entry *entry = (struct rb_global_entry *)*seq;
2752 rb_ary_push(ary, ID2SYM(entry->id));
2753 }
2754 break;
2755 case TS_IC:
2756 case TS_IVC:
2757 case TS_ISE:
2758 {
2759 union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)*seq;
2760 rb_ary_push(ary, INT2FIX(is - iseq_body->is_entries));
2761 }
2762 break;
2763 case TS_CALLDATA:
2764 {
2765 struct rb_call_data *cd = (struct rb_call_data *)*seq;
2766 struct rb_call_info *ci = &cd->ci;
2767 VALUE e = rb_hash_new();
2768 int orig_argc = ci->orig_argc;
2769
2770 rb_hash_aset(e, ID2SYM(rb_intern("mid")), ci->mid ? ID2SYM(ci->mid) : Qnil);
2771 rb_hash_aset(e, ID2SYM(rb_intern("flag")), UINT2NUM(ci->flag));
2772
2773 if (ci->flag & VM_CALL_KWARG) {
2774 struct rb_call_info_with_kwarg *ci_kw = (struct rb_call_info_with_kwarg *)ci;
2775 int i;
2776 VALUE kw = rb_ary_new2((long)ci_kw->kw_arg->keyword_len);
2777
2778 orig_argc -= ci_kw->kw_arg->keyword_len;
2779 for (i = 0; i < ci_kw->kw_arg->keyword_len; i++) {
2780 rb_ary_push(kw, ci_kw->kw_arg->keywords[i]);
2781 }
2782 rb_hash_aset(e, ID2SYM(rb_intern("kw_arg")), kw);
2783 }
2784
2785 rb_hash_aset(e, ID2SYM(rb_intern("orig_argc")),
2786 INT2FIX(orig_argc));
2787 rb_ary_push(ary, e);
2788 }
2789 break;
2790 case TS_ID:
2791 rb_ary_push(ary, ID2SYM(*seq));
2792 break;
2793 case TS_CDHASH:
2794 {
2795 VALUE hash = *seq;
2796 VALUE val = rb_ary_new();
2797 int i;
2798
2799 rb_hash_foreach(hash, cdhash_each, val);
2800
2801 for (i=0; i<RARRAY_LEN(val); i+=2) {
2802 VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
2803 unsigned long idx = nseq - iseq_original + pos;
2804
2805 rb_ary_store(val, i+1,
2806 register_label(labels_table, idx));
2807 }
2808 rb_ary_push(ary, val);
2809 }
2810 break;
2811 case TS_FUNCPTR:
2812 {
2813 #if SIZEOF_VALUE <= SIZEOF_LONG
2814 VALUE val = LONG2NUM((SIGNED_VALUE)*seq);
2815 #else
2816 VALUE val = LL2NUM((SIGNED_VALUE)*seq);
2817 #endif
2818 rb_ary_push(ary, val);
2819 }
2820 break;
2821 case TS_BUILTIN:
2822 {
2823 VALUE val = rb_hash_new();
2824 #if SIZEOF_VALUE <= SIZEOF_LONG
2825 VALUE func_ptr = LONG2NUM((SIGNED_VALUE)((RB_BUILTIN)*seq)->func_ptr);
2826 #else
2827 VALUE func_ptr = LL2NUM((SIGNED_VALUE)((RB_BUILTIN)*seq)->func_ptr);
2828 #endif
2829 rb_hash_aset(val, ID2SYM(rb_intern("func_ptr")), func_ptr);
2830 rb_hash_aset(val, ID2SYM(rb_intern("argc")), INT2NUM(((RB_BUILTIN)*seq)->argc));
2831 rb_hash_aset(val, ID2SYM(rb_intern("index")), INT2NUM(((RB_BUILTIN)*seq)->index));
2832 rb_hash_aset(val, ID2SYM(rb_intern("name")), rb_str_new_cstr(((RB_BUILTIN)*seq)->name));
2833 rb_ary_push(ary, val);
2834 }
2835 break;
2836 default:
2837 rb_bug("unknown operand: %c", insn_op_type(insn, j));
2838 }
2839 }
2840 rb_ary_push(body, ary);
2841 }
2842
2843 nbody = body;
2844
2845 /* exception */
2846 if (iseq_body->catch_table) for (i=0; i<iseq_body->catch_table->size; i++) {
2847 VALUE ary = rb_ary_new();
2848 const struct iseq_catch_table_entry *entry =
2849 UNALIGNED_MEMBER_PTR(iseq_body->catch_table, entries[i]);
2850 rb_ary_push(ary, exception_type2symbol(entry->type));
2851 if (entry->iseq) {
2852 rb_ary_push(ary, iseq_data_to_ary(rb_iseq_check(entry->iseq)));
2853 }
2854 else {
2855 rb_ary_push(ary, Qnil);
2856 }
2857 rb_ary_push(ary, register_label(labels_table, entry->start));
2858 rb_ary_push(ary, register_label(labels_table, entry->end));
2859 rb_ary_push(ary, register_label(labels_table, entry->cont));
2860 rb_ary_push(ary, UINT2NUM(entry->sp));
2861 rb_ary_push(exception, ary);
2862 }
2863
2864 /* make body with labels and insert line number */
2865 body = rb_ary_new();
2866 prev_insn_info = NULL;
2867
2868 for (l=0, pos=0; l<RARRAY_LEN(nbody); l++) {
2869 const struct iseq_insn_info_entry *info;
2870 VALUE ary = RARRAY_AREF(nbody, l);
2871 st_data_t label;
2872
2873 if (st_lookup(labels_table, pos, &label)) {
2874 rb_ary_push(body, (VALUE)label);
2875 }
2876
2877 info = get_insn_info(iseq, pos);
2878
2879 if (prev_insn_info != info) {
2880 int line = info->line_no;
2881 rb_event_flag_t events = info->events;
2882
2883 if (line > 0 && last_line != line) {
2884 rb_ary_push(body, INT2FIX(line));
2885 last_line = line;
2886 }
2887 #define CHECK_EVENT(ev) if (events & ev) rb_ary_push(body, ID2SYM(rb_intern(#ev)));
2888 CHECK_EVENT(RUBY_EVENT_LINE);
2889 CHECK_EVENT(RUBY_EVENT_CLASS);
2890 CHECK_EVENT(RUBY_EVENT_END);
2891 CHECK_EVENT(RUBY_EVENT_CALL);
2892 CHECK_EVENT(RUBY_EVENT_RETURN);
2893 CHECK_EVENT(RUBY_EVENT_B_CALL);
2894 CHECK_EVENT(RUBY_EVENT_B_RETURN);
2895 #undef CHECK_EVENT
2896 prev_insn_info = info;
2897 }
2898
2899 rb_ary_push(body, ary);
2900 pos += RARRAY_LENINT(ary); /* reject too huge data */
2901 }
2902 RB_GC_GUARD(nbody);
2903 RB_GC_GUARD(labels_wrapper);
2904
2905 rb_hash_aset(misc, ID2SYM(rb_intern("arg_size")), INT2FIX(iseq_body->param.size));
2906 rb_hash_aset(misc, ID2SYM(rb_intern("local_size")), INT2FIX(iseq_body->local_table_size));
2907 rb_hash_aset(misc, ID2SYM(rb_intern("stack_max")), INT2FIX(iseq_body->stack_max));
2908 rb_hash_aset(misc, ID2SYM(rb_intern("node_id")), INT2FIX(iseq_body->location.node_id));
2909 rb_hash_aset(misc, ID2SYM(rb_intern("code_location")),
2910 rb_ary_new_from_args(4,
2911 INT2FIX(iseq_body->location.code_location.beg_pos.lineno),
2912 INT2FIX(iseq_body->location.code_location.beg_pos.column),
2913 INT2FIX(iseq_body->location.code_location.end_pos.lineno),
2914 INT2FIX(iseq_body->location.code_location.end_pos.column)));
2915
2916 /*
2917 * [:magic, :major_version, :minor_version, :format_type, :misc,
2918 * :name, :path, :absolute_path, :start_lineno, :type, :locals, :args,
2919 * :catch_table, :bytecode]
2920 */
2921 rb_ary_push(val, rb_str_new2("YARVInstructionSequence/SimpleDataFormat"));
2922 rb_ary_push(val, INT2FIX(ISEQ_MAJOR_VERSION)); /* major */
2923 rb_ary_push(val, INT2FIX(ISEQ_MINOR_VERSION)); /* minor */
2924 rb_ary_push(val, INT2FIX(1));
2925 rb_ary_push(val, misc);
2926 rb_ary_push(val, iseq_body->location.label);
2927 rb_ary_push(val, rb_iseq_path(iseq));
2928 rb_ary_push(val, rb_iseq_realpath(iseq));
2929 rb_ary_push(val, iseq_body->location.first_lineno);
2930 rb_ary_push(val, ID2SYM(type));
2931 rb_ary_push(val, locals);
2932 rb_ary_push(val, params);
2933 rb_ary_push(val, exception);
2934 rb_ary_push(val, body);
2935 return val;
2936 }
2937
2938 VALUE
2939 rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
2940 {
2941 int i, r;
2942 const struct rb_iseq_constant_body *const body = iseq->body;
2943 const struct rb_iseq_param_keyword *const keyword = body->param.keyword;
2944 VALUE a, args = rb_ary_new2(body->param.size);
2945 ID req, opt, rest, block, key, keyrest;
2946 #define PARAM_TYPE(type) rb_ary_push(a = rb_ary_new2(2), ID2SYM(type))
2947 #define PARAM_ID(i) body->local_table[(i)]
2948 #define PARAM(i, type) ( \
2949 PARAM_TYPE(type), \
2950 rb_id2str(PARAM_ID(i)) ? \
2951 rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \
2952 a)
2953
2954 CONST_ID(req, "req");
2955 CONST_ID(opt, "opt");
2956 if (is_proc) {
2957 for (i = 0; i < body->param.lead_num; i++) {
2958 PARAM_TYPE(opt);
2959 rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil);
2960 rb_ary_push(args, a);
2961 }
2962 }
2963 else {
2964 for (i = 0; i < body->param.lead_num; i++) {
2965 rb_ary_push(args, PARAM(i, req));
2966 }
2967 }
2968 r = body->param.lead_num + body->param.opt_num;
2969 for (; i < r; i++) {
2970 PARAM_TYPE(opt);
2971 if (rb_id2str(PARAM_ID(i))) {
2972 rb_ary_push(a, ID2SYM(PARAM_ID(i)));
2973 }
2974 rb_ary_push(args, a);
2975 }
2976 if (body->param.flags.has_rest) {
2977 CONST_ID(rest, "rest");
2978 rb_ary_push(args, PARAM(body->param.rest_start, rest));
2979 }
2980 r = body->param.post_start + body->param.post_num;
2981 if (is_proc) {
2982 for (i = body->param.post_start; i < r; i++) {
2983 PARAM_TYPE(opt);
2984 rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil);
2985 rb_ary_push(args, a);
2986 }
2987 }
2988 else {
2989 for (i = body->param.post_start; i < r; i++) {
2990 rb_ary_push(args, PARAM(i, req));
2991 }
2992 }
2993 if (body->param.flags.accepts_no_kwarg) {
2994 ID nokey;
2995 CONST_ID(nokey, "nokey");
2996 PARAM_TYPE(nokey);
2997 rb_ary_push(args, a);
2998 }
2999 if (body->param.flags.has_kw) {
3000 i = 0;
3001 if (keyword->required_num > 0) {
3002 ID keyreq;
3003 CONST_ID(keyreq, "keyreq");
3004 for (; i < keyword->required_num; i++) {
3005 PARAM_TYPE(keyreq);
3006 if (rb_id2str(keyword->table[i])) {
3007 rb_ary_push(a, ID2SYM(keyword->table[i]));
3008 }
3009 rb_ary_push(args, a);
3010 }
3011 }
3012 CONST_ID(key, "key");
3013 for (; i < keyword->num; i++) {
3014 PARAM_TYPE(key);
3015 if (rb_id2str(keyword->table[i])) {
3016 rb_ary_push(a, ID2SYM(keyword->table[i]));
3017 }
3018 rb_ary_push(args, a);
3019 }
3020 }
3021 if (body->param.flags.has_kwrest) {
3022 CONST_ID(keyrest, "keyrest");
3023 rb_ary_push(args, PARAM(keyword->rest_start, keyrest));
3024 }
3025 if (body->param.flags.has_block) {
3026 CONST_ID(block, "block");
3027 rb_ary_push(args, PARAM(body->param.block_start, block));
3028 }
3029 return args;
3030 }
3031
3032 VALUE
3033 rb_iseq_defined_string(enum defined_type type)
3034 {
3035 static const char expr_names[][18] = {
3036 "nil",
3037 "instance-variable",
3038 "local-variable",
3039 "global-variable",
3040 "class variable",
3041 "constant",
3042 "method",
3043 "yield",
3044 "super",
3045 "self",
3046 "true",
3047 "false",
3048 "assignment",
3049 "expression",
3050 };
3051 const char *estr;
3052 VALUE *defs, str;
3053
3054 if ((unsigned)(type - 1) >= (unsigned)numberof(expr_names)) return 0;
3055 estr = expr_names[type - 1];
3056 if (!estr[0]) return 0;
3057 defs = GET_VM()->defined_strings;
3058 if (!defs) {
3059 defs = ruby_xcalloc(numberof(expr_names), sizeof(VALUE));
3060 GET_VM()->defined_strings = defs;
3061 }
3062 str = defs[type-1];
3063 if (!str) {
3064 str = rb_str_new_cstr(estr);
3065 OBJ_FREEZE(str);
3066 defs[type-1] = str;
3067 rb_gc_register_mark_object(str);
3068 }
3069 return str;
3070 }
3071
3072 /* A map from encoded_insn to insn_data: decoded insn number, its len,
3073 * non-trace version of encoded insn, and trace version. */
3074
3075 static st_table *encoded_insn_data;
3076 typedef struct insn_data_struct {
3077 int insn;
3078 int insn_len;
3079 void *notrace_encoded_insn;
3080 void *trace_encoded_insn;
3081 } insn_data_t;
3082 static insn_data_t insn_data[VM_INSTRUCTION_SIZE/2];
3083
3084 void
3085 rb_vm_encoded_insn_data_table_init(void)
3086 {
3087 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
3088 const void * const *table = rb_vm_get_insns_address_table();
3089 #define INSN_CODE(insn) ((VALUE)table[insn])
3090 #else
3091 #define INSN_CODE(insn) (insn)
3092 #endif
3093 st_data_t insn;
3094 encoded_insn_data = st_init_numtable_with_size(VM_INSTRUCTION_SIZE / 2);
3095
3096 for (insn = 0; insn < VM_INSTRUCTION_SIZE/2; insn++) {
3097 st_data_t key1 = (st_data_t)INSN_CODE(insn);
3098 st_data_t key2 = (st_data_t)INSN_CODE(insn + VM_INSTRUCTION_SIZE/2);
3099
3100 insn_data[insn].insn = (int)insn;
3101 insn_data[insn].insn_len = insn_len(insn);
3102 insn_data[insn].notrace_encoded_insn = (void *) key1;
3103 insn_data[insn].trace_encoded_insn = (void *) key2;
3104
3105 st_add_direct(encoded_insn_data, key1, (st_data_t)&insn_data[insn]);
3106 st_add_direct(encoded_insn_data, key2, (st_data_t)&insn_data[insn]);
3107 }
3108 }
3109
3110 int
3111 rb_vm_insn_addr2insn(const void *addr)
3112 {
3113 st_data_t key = (st_data_t)addr;
3114 st_data_t val;
3115
3116 if (st_lookup(encoded_insn_data, key, &val)) {
3117 insn_data_t *e = (insn_data_t *)val;
3118 return (int)e->insn;
3119 }
3120
3121 rb_bug("rb_vm_insn_addr2insn: invalid insn address: %p", addr);
3122 }
3123
3124 static inline int
3125 encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon)
3126 {
3127 st_data_t key = (st_data_t)*iseq_encoded_insn;
3128 st_data_t val;
3129
3130 if (st_lookup(encoded_insn_data, key, &val)) {
3131 insn_data_t *e = (insn_data_t *)val;
3132 *iseq_encoded_insn = (VALUE) (turnon ? e->trace_encoded_insn : e->notrace_encoded_insn);
3133 return e->insn_len;
3134 }
3135
3136 rb_bug("trace_instrument: invalid insn address: %p", (void *)*iseq_encoded_insn);
3137 }
3138
3139 void
3140 rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos)
3141 {
3142 const struct rb_iseq_constant_body *const body = iseq->body;
3143 VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
3144 encoded_iseq_trace_instrument(&iseq_encoded[pos], 0);
3145 }
3146
3147 static int
3148 iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line)
3149 {
3150 unsigned int pc;
3151 int n = 0;
3152 const struct rb_iseq_constant_body *const body = iseq->body;
3153 VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
3154
3155 VM_ASSERT(ISEQ_EXECUTABLE_P(iseq));
3156
3157 for (pc=0; pc<body->iseq_size;) {
3158 const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pc);
3159 rb_event_flag_t pc_events = entry->events;
3160 rb_event_flag_t target_events = turnon_events;
3161 unsigned int line = (int)entry->line_no;
3162
3163 if (target_line == 0 || target_line == line) {
3164 /* ok */
3165 }
3166 else {
3167 target_events &= ~RUBY_EVENT_LINE;
3168 }
3169
3170 if (pc_events & target_events) {
3171 n++;
3172 }
3173 pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (target_events | iseq->aux.exec.global_trace_events));
3174 }
3175
3176 if (n > 0) {
3177 if (iseq->aux.exec.local_hooks == NULL) {
3178 ((rb_iseq_t *)iseq)->aux.exec.local_hooks = RB_ZALLOC(rb_hook_list_t);
3179 }
3180 rb_hook_list_connect_tracepoint((VALUE)iseq, iseq->aux.exec.local_hooks, tpval, target_line);
3181 }
3182
3183 return n;
3184 }
3185
3186 struct trace_set_local_events_struct {
3187 rb_event_flag_t turnon_events;
3188 VALUE tpval;
3189 unsigned int target_line;
3190 int n;
3191 };
3192
3193 static void
3194 iseq_add_local_tracepoint_i(const rb_iseq_t *iseq, void *p)
3195 {
3196 struct trace_set_local_events_struct *data = (struct trace_set_local_events_struct *)p;
3197 data->n += iseq_add_local_tracepoint(iseq, data->turnon_events, data->tpval, data->target_line);
3198 iseq_iterate_children(iseq, iseq_add_local_tracepoint_i, p);
3199 }
3200
3201 int
3202 rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line)
3203 {
3204 struct trace_set_local_events_struct data;
3205 data.turnon_events = turnon_events;
3206 data.tpval = tpval;
3207 data.target_line = target_line;
3208 data.n = 0;
3209
3210 iseq_add_local_tracepoint_i(iseq, (void *)&data);
3211 if (0) rb_funcall(Qnil, rb_intern("puts"), 1, rb_iseq_disasm(iseq)); /* for debug */
3212 return data.n;
3213 }
3214
3215 static int
3216 iseq_remove_local_tracepoint(const rb_iseq_t *iseq, VALUE tpval)
3217 {
3218 int n = 0;
3219
3220 if (iseq->aux.exec.local_hooks) {
3221 unsigned int pc;
3222 const struct rb_iseq_constant_body *const body = iseq->body;
3223 VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
3224 rb_event_flag_t local_events = 0;
3225
3226 rb_hook_list_remove_tracepoint(iseq->aux.exec.local_hooks, tpval);
3227 local_events = iseq->aux.exec.local_hooks->events;
3228
3229 if (local_events == 0) {
3230 if (iseq->aux.exec.local_hooks->running == 0) {
3231 rb_hook_list_free(iseq->aux.exec.local_hooks);
3232 }
3233 ((rb_iseq_t *)iseq)->aux.exec.local_hooks = NULL;
3234 }
3235
3236 for (pc = 0; pc<body->iseq_size;) {
3237 rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pc);
3238 pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (local_events | iseq->aux.exec.global_trace_events));
3239 }
3240 }
3241 return n;
3242 }
3243
3244 struct trace_clear_local_events_struct {
3245 VALUE tpval;
3246 int n;
3247 };
3248
3249 static void
3250 iseq_remove_local_tracepoint_i(const rb_iseq_t *iseq, void *p)
3251 {
3252 struct trace_clear_local_events_struct *data = (struct trace_clear_local_events_struct *)p;
3253 data->n += iseq_remove_local_tracepoint(iseq, data->tpval);
3254 iseq_iterate_children(iseq, iseq_remove_local_tracepoint_i, p);
3255 }
3256
3257 int
3258 rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval)
3259 {
3260 struct trace_clear_local_events_struct data;
3261 data.tpval = tpval;
3262 data.n = 0;
3263
3264 iseq_remove_local_tracepoint_i(iseq, (void *)&data);
3265 return data.n;
3266 }
3267
3268 void
3269 rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events)
3270 {
3271 if (iseq->aux.exec.global_trace_events == turnon_events) {
3272 return;
3273 }
3274
3275 if (!ISEQ_EXECUTABLE_P(iseq)) {
3276 /* this is building ISeq */
3277 return;
3278 }
3279 else {
3280 unsigned int pc;
3281 const struct rb_iseq_constant_body *const body = iseq->body;
3282 VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
3283 rb_event_flag_t enabled_events;
3284 rb_event_flag_t local_events = iseq->aux.exec.local_hooks ? iseq->aux.exec.local_hooks->events : 0;
3285 ((rb_iseq_t *)iseq)->aux.exec.global_trace_events = turnon_events;
3286 enabled_events = turnon_events | local_events;
3287
3288 for (pc=0; pc<body->iseq_size;) {
3289 rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pc);
3290 pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & enabled_events);
3291 }
3292 }
3293 }
3294
3295 static int
3296 trace_set_i(void *vstart, void *vend, size_t stride, void *data)
3297 {
3298 rb_event_flag_t turnon_events = *(rb_event_flag_t *)data;
3299
3300 VALUE v = (VALUE)vstart;
3301 for (; v != (VALUE)vend; v += stride) {
3302 void *ptr = asan_poisoned_object_p(v);
3303 asan_unpoison_object(v, false);
3304
3305 if (rb_obj_is_iseq(v)) {
3306 rb_iseq_trace_set(rb_iseq_check((rb_iseq_t *)v), turnon_events);
3307 }
3308
3309 asan_poison_object_if(ptr, v);
3310 }
3311 return 0;
3312 }
3313
3314 void
3315 rb_iseq_trace_set_all(rb_event_flag_t turnon_events)
3316 {
3317 rb_objspace_each_objects(trace_set_i, &turnon_events);
3318 }
3319
3320 VALUE
3321 rb_iseqw_local_variables(VALUE iseqval)
3322 {
3323 return rb_iseq_local_variables(iseqw_check(iseqval));
3324 }
3325
3326 /*
3327 * call-seq:
3328 * iseq.to_binary(extra_data = nil) -> binary str
3329 *
3330 * Returns serialized iseq binary format data as a String object.
3331 * A corresponding iseq object is created by
3332 * RubyVM::InstructionSequence.load_from_binary() method.
3333 *
3334 * String extra_data will be saved with binary data.
3335 * You can access this data with
3336 * RubyVM::InstructionSequence.load_from_binary_extra_data(binary).
3337 *
3338 * Note that the translated binary data is not portable.
3339 * You can not move this binary data to another machine.
3340 * You can not use the binary data which is created by another
3341 * version/another architecture of Ruby.
3342 */
3343 static VALUE
3344 iseqw_to_binary(int argc, VALUE *argv, VALUE self)
3345 {
3346 VALUE opt = !rb_check_arity(argc, 0, 1) ? Qnil : argv[0];
3347 return rb_iseq_ibf_dump(iseqw_check(self), opt);
3348 }
3349
3350 /*
3351 * call-seq:
3352 * RubyVM::InstructionSequence.load_from_binary(binary) -> iseq
3353 *
3354 * Load an iseq object from binary format String object
3355 * created by RubyVM::InstructionSequence.to_binary.
3356 *
3357 * This loader does not have a verifier, so that loading broken/modified
3358 * binary causes critical problem.
3359 *
3360 * You should not load binary data provided by others.
3361 * You should use binary data translated by yourself.
3362 */
3363 static VALUE
3364 iseqw_s_load_from_binary(VALUE self, VALUE str)
3365 {
3366 return iseqw_new(rb_iseq_ibf_load(str));
3367 }
3368
3369 /*
3370 * call-seq:
3371 * RubyVM::InstructionSequence.load_from_binary_extra_data(binary) -> str
3372 *
3373 * Load extra data embed into binary format String object.
3374 */
3375 static VALUE
3376 iseqw_s_load_from_binary_extra_data(VALUE self, VALUE str)
3377 {
3378 return rb_iseq_ibf_load_extra_data(str);
3379 }
3380
3381 #if VM_INSN_INFO_TABLE_IMPL == 2
3382
3383 /* An implementation of succinct bit-vector for insn_info table.
3384 *
3385 * A succinct bit-vector is a small and efficient data structure that provides
3386 * a bit-vector augmented with an index for O(1) rank operation:
3387 *
3388 * rank(bv, n): the number of 1's within a range from index 0 to index n
3389 *
3390 * This can be used to lookup insn_info table from PC.
3391 * For example, consider the following iseq and insn_info_table:
3392 *
3393 * iseq insn_info_table
3394 * PC insn+operand position lineno event
3395 * 0: insn1 0: 1 [Li]
3396 * 2: insn2 2: 2 [Li] <= (A)
3397 * 5: insn3 8: 3 [Li] <= (B)
3398 * 8: insn4
3399 *
3400 * In this case, a succinct bit-vector whose indexes 0, 2, 8 is "1" and
3401 * other indexes is "0", i.e., "101000001", is created.
3402 * To lookup the lineno of insn2, calculate rank("10100001", 2) = 2, so
3403 * the line (A) is the entry in question.
3404 * To lookup the lineno of insn4, calculate rank("10100001", 8) = 3, so
3405 * the line (B) is the entry in question.
3406 *
3407 * A naive implementation of succinct bit-vector works really well
3408 * not only for large size but also for small size. However, it has
3409 * tiny overhead for very small size. So, this implementation consist
3410 * of two parts: one part is the "immediate" table that keeps rank result
3411 * as a raw table, and the other part is a normal succinct bit-vector.
3412 */
3413
3414 #define IMMEDIATE_TABLE_SIZE 54 /* a multiple of 9, and < 128 */
3415
3416 struct succ_index_table {
3417 uint64_t imm_part[IMMEDIATE_TABLE_SIZE / 9];
3418 struct succ_dict_block {
3419 unsigned int rank;
3420 uint64_t small_block_ranks; /* 9 bits * 7 = 63 bits */
3421 uint64_t bits[512/64];
3422 } succ_part[FLEX_ARY_LEN];
3423 };
3424
3425 #define imm_block_rank_set(v, i, r) (v) |= (uint64_t)(r) << (7 * (i))
3426 #define imm_block_rank_get(v, i) (((int)((v) >> ((i) * 7))) & 0x7f)
3427 #define small_block_rank_set(v, i, r) (v) |= (uint64_t)(r) << (9 * ((i) - 1))
3428 #define small_block_rank_get(v, i) ((i) == 0 ? 0 : (((int)((v) >> (((i) - 1) * 9))) & 0x1ff))
3429
3430 static struct succ_index_table *
3431 succ_index_table_create(int max_pos, int *data, int size)
3432 {
3433 const int imm_size = (max_pos < IMMEDIATE_TABLE_SIZE ? max_pos + 8 : IMMEDIATE_TABLE_SIZE) / 9;
3434 const int succ_size = (max_pos < IMMEDIATE_TABLE_SIZE ? 0 : (max_pos - IMMEDIATE_TABLE_SIZE + 511)) / 512;
3435 struct succ_index_table *sd =
3436 rb_xcalloc_mul_add_mul(
3437 imm_size, sizeof(uint64_t),
3438 succ_size, sizeof(struct succ_dict_block));
3439 int i, j, k, r;
3440
3441 r = 0;
3442 for (j = 0; j < imm_size; j++) {
3443 for (i = 0; i < 9; i++) {
3444 if (r < size && data[r] == j * 9 + i) r++;
3445 imm_block_rank_set(sd->imm_part[j], i, r);
3446 }
3447 }
3448 for (k = 0; k < succ_size; k++) {
3449 struct succ_dict_block *sd_block = &sd->succ_part[k];
3450 int small_rank = 0;
3451 sd_block->rank = r;
3452 for (j = 0; j < 8; j++) {
3453 uint64_t bits = 0;
3454 if (j) small_block_rank_set(sd_block->small_block_ranks, j, small_rank);
3455 for (i = 0; i < 64; i++) {
3456 if (r < size && data[r] == k * 512 + j * 64 + i + IMMEDIATE_TABLE_SIZE) {
3457 bits |= ((uint64_t)1) << i;
3458 r++;
3459 }
3460 }
3461 sd_block->bits[j] = bits;
3462 small_rank += rb_popcount64(bits);
3463 }
3464 }
3465 return sd;
3466 }
3467
3468 static unsigned int *
3469 succ_index_table_invert(int max_pos, struct succ_index_table *sd, int size)
3470 {
3471 const int imm_size = (max_pos < IMMEDIATE_TABLE_SIZE ? max_pos + 8 : IMMEDIATE_TABLE_SIZE) / 9;
3472 const int succ_size = (max_pos < IMMEDIATE_TABLE_SIZE ? 0 : (max_pos - IMMEDIATE_TABLE_SIZE + 511)) / 512;
3473 unsigned int *positions = ALLOC_N(unsigned int, size), *p;
3474 int i, j, k, r = -1;
3475 p = positions;
3476 for (j = 0; j < imm_size; j++) {
3477 for (i = 0; i < 9; i++) {
3478 int nr = imm_block_rank_get(sd->imm_part[j], i);
3479 if (r != nr) *p++ = j * 9 + i;
3480 r = nr;
3481 }
3482 }
3483 for (k = 0; k < succ_size; k++) {
3484 for (j = 0; j < 8; j++) {
3485 for (i = 0; i < 64; i++) {
3486 if (sd->succ_part[k].bits[j] & (((uint64_t)1) << i)) {
3487 *p++ = k * 512 + j * 64 + i + IMMEDIATE_TABLE_SIZE;
3488 }
3489 }
3490 }
3491 }
3492 return positions;
3493 }
3494
3495 static int
3496 succ_index_lookup(const struct succ_index_table *sd, int x)
3497 {
3498 if (x < IMMEDIATE_TABLE_SIZE) {
3499 const int i = x / 9;
3500 const int j = x % 9;
3501 return imm_block_rank_get(sd->imm_part[i], j);
3502 }
3503 else {
3504 const int block_index = (x - IMMEDIATE_TABLE_SIZE) / 512;
3505 const struct succ_dict_block *block = &sd->succ_part[block_index];
3506 const int block_bit_index = (x - IMMEDIATE_TABLE_SIZE) % 512;
3507 const int small_block_index = block_bit_index / 64;
3508 const int small_block_popcount = small_block_rank_get(block->small_block_ranks, small_block_index);
3509 const int popcnt = rb_popcount64(block->bits[small_block_index] << (63 - block_bit_index % 64));
3510
3511 return block->rank + small_block_popcount + popcnt;
3512 }
3513 }
3514 #endif
3515
3516 /*
3517 * Document-class: RubyVM::InstructionSequence
3518 *
3519 * The InstructionSequence class represents a compiled sequence of
3520 * instructions for the Virtual Machine used in MRI. Not all implementations of Ruby
3521 * may implement this class, and for the implementations that implement it,
3522 * the methods defined and behavior of the methods can change in any version.
3523 *
3524 * With it, you can get a handle to the instructions that make up a method or
3525 * a proc, compile strings of Ruby code down to VM instructions, and
3526 * disassemble instruction sequences to strings for easy inspection. It is
3527 * mostly useful if you want to learn how YARV works, but it also lets
3528 * you control various settings for the Ruby iseq compiler.
3529 *
3530 * You can find the source for the VM instructions in +insns.def+ in the Ruby
3531 * source.
3532 *
3533 * The instruction sequence results will almost certainly change as Ruby
3534 * changes, so example output in this documentation may be different from what
3535 * you see.
3536 *
3537 * Of course, this class is MRI specific.
3538 */
3539
3540 void
3541 Init_ISeq(void)
3542 {
3543 /* declare ::RubyVM::InstructionSequence */
3544 rb_cISeq = rb_define_class_under(rb_cRubyVM, "InstructionSequence", rb_cObject);
3545 rb_undef_alloc_func(rb_cISeq);
3546 rb_define_method(rb_cISeq, "inspect", iseqw_inspect, 0);
3547 rb_define_method(rb_cISeq, "disasm", iseqw_disasm, 0);
3548 rb_define_method(rb_cISeq, "disassemble", iseqw_disasm, 0);
3549 rb_define_method(rb_cISeq, "to_a", iseqw_to_a, 0);
3550 rb_define_method(rb_cISeq, "eval", iseqw_eval, 0);
3551
3552 rb_define_method(rb_cISeq, "to_binary", iseqw_to_binary, -1);
3553 rb_define_singleton_method(rb_cISeq, "load_from_binary", iseqw_s_load_from_binary, 1);
3554 rb_define_singleton_method(rb_cISeq, "load_from_binary_extra_data", iseqw_s_load_from_binary_extra_data, 1);
3555
3556
3557 /* location APIs */
3558 rb_define_method(rb_cISeq, "path", iseqw_path, 0);
3559 rb_define_method(rb_cISeq, "absolute_path", iseqw_absolute_path, 0);
3560 rb_define_method(rb_cISeq, "label", iseqw_label, 0);
3561 rb_define_method(rb_cISeq, "base_label", iseqw_base_label, 0);
3562 rb_define_method(rb_cISeq, "first_lineno", iseqw_first_lineno, 0);
3563 rb_define_method(rb_cISeq, "trace_points", iseqw_trace_points, 0);
3564 rb_define_method(rb_cISeq, "each_child", iseqw_each_child, 0);
3565
3566 #if 0 /* TBD */
3567 rb_define_private_method(rb_cISeq, "marshal_dump", iseqw_marshal_dump, 0);
3568 rb_define_private_method(rb_cISeq, "marshal_load", iseqw_marshal_load, 1);
3569 /* disable this feature because there is no verifier. */
3570 rb_define_singleton_method(rb_cISeq, "load", iseq_s_load, -1);
3571 #endif
3572 (void)iseq_s_load;
3573
3574 rb_define_singleton_method(rb_cISeq, "compile", iseqw_s_compile, -1);
3575 rb_define_singleton_method(rb_cISeq, "new", iseqw_s_compile, -1);
3576 rb_define_singleton_method(rb_cISeq, "compile_file", iseqw_s_compile_file, -1);
3577 rb_define_singleton_method(rb_cISeq, "compile_option", iseqw_s_compile_option_get, 0);
3578 rb_define_singleton_method(rb_cISeq, "compile_option=", iseqw_s_compile_option_set, 1);
3579 rb_define_singleton_method(rb_cISeq, "disasm", iseqw_s_disasm, 1);
3580 rb_define_singleton_method(rb_cISeq, "disassemble", iseqw_s_disasm, 1);
3581 rb_define_singleton_method(rb_cISeq, "of", iseqw_s_of, 1);
3582
3583 rb_undef_method(CLASS_OF(rb_cISeq), "translate");
3584 rb_undef_method(CLASS_OF(rb_cISeq), "load_iseq");
3585 }
rb_iseq_realpath
VALUE rb_iseq_realpath(const rb_iseq_t *iseq)
Definition: iseq.c:1033
rb_parser_new
VALUE rb_parser_new(void)
Definition: ripper.c:19224
rb_str_symname_p
int rb_str_symname_p(VALUE)
Definition: string.c:10695
rb_kwarg_call_data
Definition: vm_core.h:257
ID
unsigned long ID
Definition: ruby.h:103
rb_check_funcall
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:505
ruby_xfree
void ruby_xfree(void *x)
Definition: gc.c:10150
rb_str_concat
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:3065
rb_iseq_memsize
size_t rb_iseq_memsize(const rb_iseq_t *iseq)
Definition: iseq.c:373
OPT_INSTRUCTIONS_UNIFICATION
#define OPT_INSTRUCTIONS_UNIFICATION
Definition: vm_opts.h:59
rb_iseq_local_variables
VALUE rb_iseq_local_variables(const rb_iseq_t *iseq)
Definition: vm.c:849
ruby_node_name
const char * ruby_node_name(int node)
Definition: iseq.c:2534
IMMEDIATE_TABLE_SIZE
#define IMMEDIATE_TABLE_SIZE
Definition: iseq.c:3414
PARAM
#define PARAM(i, type)
void
void
Definition: rb_mjit_min_header-2.7.0.h:13273
rb_fstring
VALUE rb_fstring(VALUE)
Definition: string.c:312
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
rb_hook_list_struct
Definition: vm_core.h:565
rb_xcalloc_mul_add_mul
void * rb_xcalloc_mul_add_mul(size_t x, size_t y, size_t z, size_t w)
Definition: gc.c:10177
TRUE
#define TRUE
Definition: nkf.h:175
rb_iseq_load
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
Definition: iseq.c:972
DEFINED_FUNC
@ DEFINED_FUNC
Definition: iseq.h:301
rb_iseq_eval
VALUE rb_iseq_eval(const rb_iseq_t *iseq)
Definition: vm.c:2163
rb_check_id
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
Definition: symbol.c:919
rb_iseq_label
VALUE rb_iseq_label(const rb_iseq_t *iseq)
Definition: iseq.c:1045
SET_COMPILE_OPTION_NUM
#define SET_COMPILE_OPTION_NUM(o, h, mem)
rb_iseq_first_lineno
VALUE rb_iseq_first_lineno(const rb_iseq_t *iseq)
Definition: iseq.c:1057
RUBY_MARK_NO_PIN_UNLESS_NULL
#define RUBY_MARK_NO_PIN_UNLESS_NULL(ptr)
Definition: gc.h:62
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
LL2NUM
#define LL2NUM(v)
Definition: rb_mjit_min_header-2.7.0.h:4240
rb_obj_hide
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition: object.c:78
RUBY_MARK_LEAVE
#define RUBY_MARK_LEAVE(msg)
Definition: gc.h:56
succ_index_table::succ_dict_block::rank
unsigned int rank
Definition: iseq.c:3419
iseq_catch_table_entry::iseq
rb_iseq_t * iseq
Definition: iseq.h:247
rb_ast_struct::body
rb_ast_body_t body
Definition: node.h:402
rb_builtin_function
Definition: builtin.h:6
rb_io_close
VALUE rb_io_close(VALUE)
Definition: io.c:4820
id
const int id
Definition: nkf.c:209
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:717
rb_iseq_struct
Definition: vm_core.h:456
ruby_value_type
ruby_value_type
Definition: ruby.h:486
rb_ident_hash_new
VALUE rb_ident_hash_new(void)
Definition: hash.c:4203
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1501
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7063
path
VALUE path
Definition: rb_mjit_min_header-2.7.0.h:7351
rb_iseq_new_with_callback_callback_func
Definition: vm_core.h:1018
rb_hash_resurrect
MJIT_FUNC_EXPORTED VALUE rb_hash_resurrect(VALUE hash)
Definition: hash.c:1548
iseq_compile_data_storage::buff
char buff[FLEX_ARY_LEN]
Definition: iseq.h:278
memset
void * memset(void *, int, size_t)
rb_type_str
const char * rb_type_str(enum ruby_value_type type)
Definition: vm_eval.c:572
rb_iseq_constant_body::insns_info
struct rb_iseq_constant_body::iseq_insn_info insns_info
succ_index_table::succ_part
struct succ_index_table::succ_dict_block succ_part[FLEX_ARY_LEN]
uint64_t
#define uint64_t
Definition: siphash.h:15
trace_set_local_events_struct::target_line
unsigned int target_line
Definition: iseq.c:3189
gc.h
rb_iseq_disasm
VALUE rb_iseq_disasm(const rb_iseq_t *iseq)
Definition: iseq.c:2278
rb_ary_new_from_args
#define rb_ary_new_from_args(n,...)
Definition: rb_mjit_min_header-2.7.0.h:7214
rb_ast_dispose
void rb_ast_dispose(rb_ast_t *ast)
Definition: node.c:1389
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
iseq_insn_info_entry
Definition: iseq.h:220
rb_iseq_constant_body::iseq_insn_info::succ_index_table
struct succ_index_table * succ_index_table
Definition: vm_core.h:407
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
rb_iseq_pathobj_new
VALUE rb_iseq_pathobj_new(VALUE path, VALUE realpath)
Definition: iseq.c:450
rb_call_info_kw_arg::keywords
VALUE keywords[1]
Definition: vm_core.h:242
st_is_member
#define st_is_member(table, key)
Definition: st.h:97
snprintf
int snprintf(char *__restrict, size_t, const char *__restrict,...) __attribute__((__format__(__printf__
iseq_compile_data::storage_head
struct iseq_compile_data_storage * storage_head
Definition: iseq.h:104
iseq_catch_table_entry::cont
unsigned int cont
Definition: iseq.h:251
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
insn_data_struct
Definition: iseq.c:3076
INITIALIZED
#define INITIALIZED
trace_set_local_events_struct::turnon_events
rb_event_flag_t turnon_events
Definition: iseq.c:3187
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
rb_iseq_constant_body::coverage
VALUE coverage
Definition: vm_core.h:430
rb_iseq_new_top
rb_iseq_t * rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
Definition: iseq.c:769
rb_iseq_constant_body::rest_start
int rest_start
Definition: vm_core.h:369
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:1964
st_init_numtable
st_table * st_init_numtable(void)
Definition: st.c:653
rb_iseq_constant_body::ISEQ_TYPE_CLASS
@ ISEQ_TYPE_CLASS
Definition: vm_core.h:316
VALUE
unsigned long VALUE
Definition: ruby.h:102
index
int index
Definition: rb_mjit_min_header-2.7.0.h:11246
GET_VM
#define GET_VM()
Definition: vm_core.h:1764
rb_ast_body_struct
Definition: node.h:394
rb_iseq_location_struct::code_location
rb_code_location_t code_location
Definition: vm_core.h:278
ZALLOC
#define ZALLOC(type)
Definition: ruby.h:1666
rb_intern
#define rb_intern(str)
rb_ary_store
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:1079
offsetof
#define offsetof(p_type, field)
Definition: addrinfo.h:186
rb_eSyntaxError
VALUE rb_eSyntaxError
Definition: error.c:938
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
ISEQ_MINOR_VERSION
#define ISEQ_MINOR_VERSION
Definition: iseq.h:17
rb_gc_location
VALUE rb_gc_location(VALUE value)
Definition: gc.c:8111
iseq_catch_table_entry
Definition: iseq.h:225
ruby_vm_event_enabled_global_flags
rb_event_flag_t ruby_vm_event_enabled_global_flags
Definition: vm.c:376
ISEQ_NOT_LOADED_YET
#define ISEQ_NOT_LOADED_YET
Definition: iseq.h:85
st_add_direct
void st_add_direct(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1251
rb_iseq_struct::wrapper
VALUE wrapper
Definition: vm_core.h:458
RUBY_EVENT_END
#define RUBY_EVENT_END
Definition: ruby.h:2244
VM_ENV_DATA_SIZE
#define VM_ENV_DATA_SIZE
Definition: vm_core.h:1191
DEFINED_REF
@ DEFINED_REF
Definition: iseq.h:300
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
iseq_catch_table_entry::end
unsigned int end
Definition: iseq.h:250
insn_data_struct::insn
int insn
Definition: iseq.c:3077
SIGNED_VALUE
#define SIGNED_VALUE
Definition: ruby.h:104
rb_iseq_path
VALUE rb_iseq_path(const rb_iseq_t *iseq)
Definition: iseq.c:1027
rb_iseq_struct::loader
struct rb_iseq_struct::@181::@182 loader
rb_iseq_constant_body::ISEQ_TYPE_EVAL
@ ISEQ_TYPE_EVAL
Definition: vm_core.h:319
UINT2NUM
#define UINT2NUM(x)
Definition: ruby.h:1610
uint64_t
unsigned long long uint64_t
Definition: sha2.h:102
rb_iseq_constant_body::location
rb_iseq_location_t location
Definition: vm_core.h:399
OPT_OPERANDS_UNIFICATION
#define OPT_OPERANDS_UNIFICATION
Definition: vm_opts.h:58
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
rb_ary_resurrect
VALUE rb_ary_resurrect(VALUE ary)
Definition: array.c:2251
rb_code_position_struct::lineno
int lineno
Definition: node.h:131
id_ensure
ID id_ensure
Definition: eventids1.c:48
StringValue
use StringValue() instead")))
rb_parser_compile_file_path
rb_ast_t * rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE file, int start)
Definition: ripper.c:12912
rb_iseq_constant_body::keyword
const struct rb_iseq_constant_body::@178::rb_iseq_param_keyword * keyword
rb_iseq_constant_body::local_iseq
struct rb_iseq_struct * local_iseq
Definition: vm_core.h:418
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
RUBY_EVENT_B_RETURN
#define RUBY_EVENT_B_RETURN
Definition: ruby.h:2254
rb_iseq_location_struct::first_lineno
VALUE first_lineno
Definition: vm_core.h:276
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
BIN
#define BIN(n)
Definition: rb_mjit_min_header-2.7.0.h:11968
ci
rb_control_frame_t struct rb_calling_info const struct rb_call_info * ci
Definition: rb_mjit_min_header-2.7.0.h:15146
Qundef
#define Qundef
Definition: ruby.h:470
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
trace_clear_local_events_struct::n
int n
Definition: iseq.c:3246
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
GET_EC
#define GET_EC()
Definition: vm_core.h:1766
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1609
hidden_obj_p
#define hidden_obj_p(obj)
Definition: iseq.c:42
ptr
struct RIMemo * ptr
Definition: debug.c:74
mjit_update_references
void mjit_update_references(const rb_iseq_t *iseq)
rb_str_inspect
VALUE rb_str_inspect(VALUE)
Definition: string.c:5930
rb_call_info_kw_arg::keyword_len
int keyword_len
Definition: vm_core.h:241
Qfalse
#define Qfalse
Definition: ruby.h:467
id_rescue
ID id_rescue
Definition: eventids1.c:93
Init_ISeq
void Init_ISeq(void)
Definition: iseq.c:3541
uintptr_t
unsigned int uintptr_t
Definition: win32.h:106
rb_iseq_new
rb_iseq_t * rb_iseq_new(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum iseq_type type)
Definition: iseq.c:761
FilePathValue
#define FilePathValue(v)
Definition: ruby.h:624
rb_id2str
#define rb_id2str(id)
Definition: vm_backtrace.c:30
rb_iseq_constant_body::parent_iseq
const struct rb_iseq_struct * parent_iseq
Definition: vm_core.h:417
rb_iseq_struct::aux
union rb_iseq_struct::@181 aux
SPECIAL_CONST_P
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1313
printf
int int int printf(const char *__restrict,...) __attribute__((__format__(__printf__
VM_CALL_KWARG
#define VM_CALL_KWARG
Definition: vm_core.h:1107
rb_ibf_load_iseq_complete
void rb_ibf_load_iseq_complete(rb_iseq_t *iseq)
Definition: compile.c:11436
insn_data_t
struct insn_data_struct insn_data_t
NULL
#define NULL
Definition: _sdbm.c:101
succ_index_table::succ_dict_block::bits
uint64_t bits[512/64]
Definition: iseq.c:3421
rb_iseq_constant_body::ISEQ_TYPE_TOP
@ ISEQ_TYPE_TOP
Definition: vm_core.h:313
FL_TEST
#define FL_TEST(x, f)
Definition: ruby.h:1353
rb_compile_option_struct::coverage_enabled
unsigned int coverage_enabled
Definition: iseq.h:216
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
RUBY_EVENT_CALL
#define RUBY_EVENT_CALL
Definition: ruby.h:2245
st_insert
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
iseq_catch_table::size
unsigned int size
Definition: rb_mjit_min_header-2.7.0.h:10860
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1377
SET_COMPILE_OPTION
#define SET_COMPILE_OPTION(o, h, mem)
rb_mark_set
void rb_mark_set(st_table *tbl)
Definition: gc.c:4798
rb_call_info::orig_argc
int orig_argc
Definition: internal.h:2391
VM_ASSERT
#define VM_ASSERT(expr)
Definition: vm_core.h:56
rb_iseq_constant_body
Definition: vm_core.h:311
rb_iseq_constant_body::opt_table
const VALUE * opt_table
Definition: vm_core.h:374
PARAM_TYPE
#define PARAM_TYPE(type)
iseq_compile_data_storage
Definition: iseq.h:274
iseq_compile_data::insn
struct iseq_compile_data::@117 insn
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2190
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1575
rb_iseq_coverage
VALUE rb_iseq_coverage(const rb_iseq_t *iseq)
Definition: iseq.c:1086
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
rb_hash_new_with_size
MJIT_FUNC_EXPORTED VALUE rb_hash_new_with_size(st_index_t size)
Definition: hash.c:1507
pc
rb_control_frame_t const VALUE * pc
Definition: rb_mjit_min_header-2.7.0.h:16923
debug
#define debug(lvl, x...)
Definition: ffi.c:52
rb_iseq_constant_body_alloc
struct rb_iseq_constant_body * rb_iseq_constant_body_alloc(void)
Definition: iseq.c:433
RARRAY_LENINT
#define RARRAY_LENINT(ary)
Definition: ruby.h:1071
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
trace_set_local_events_struct::n
int n
Definition: iseq.c:3190
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
rb_funcallv
#define rb_funcallv(recv, mid, argc, argv)
Definition: rb_mjit_min_header-2.7.0.h:7899
rb_iseq_code_location
void rb_iseq_code_location(const rb_iseq_t *iseq, int *beg_pos_lineno, int *beg_pos_column, int *end_pos_lineno, int *end_pos_column)
Definition: iseq.c:1076
rb_kwarg_call_data::ci_kw
struct rb_call_info_with_kwarg ci_kw
Definition: vm_core.h:259
rb_ast_body_struct::compile_option
VALUE compile_option
Definition: node.h:396
rb_call_info_kw_arg
Definition: vm_core.h:240
rb_iseq_original_iseq
VALUE * rb_iseq_original_iseq(const rb_iseq_t *iseq)
Definition: compile.c:778
rb_iseq_constant_body::ISEQ_TYPE_METHOD
@ ISEQ_TYPE_METHOD
Definition: vm_core.h:314
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
const
#define const
Definition: strftime.c:103
rb_iseq_remove_local_tracepoint_recursively
int rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval)
Definition: iseq.c:3258
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
T_FILE
#define T_FILE
Definition: ruby.h:534
rb_iseq_constant_body::local_table
const ID * local_table
Definition: vm_core.h:411
ISEQ_PC2BRANCHINDEX_SET
#define ISEQ_PC2BRANCHINDEX_SET(iseq, h)
Definition: iseq.h:40
if
if((ID)(DISPID) nameid !=nameid)
Definition: win32ole.c:357
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1644
rb_exc_new_cstr
#define rb_exc_new_cstr(klass, ptr)
Definition: rb_mjit_min_header-2.7.0.h:6127
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
INSN_CODE
#define INSN_CODE(insn)
rb_obj_class
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
iseq_compile_data::node
struct iseq_compile_data::@116 node
PARAM_ID
#define PARAM_ID(i)
rb_obj_is_proc
VALUE rb_obj_is_proc(VALUE)
Definition: proc.c:152
rb_iseq_event_flags
MJIT_FUNC_EXPORTED rb_event_flag_t rb_iseq_event_flags(const rb_iseq_t *iseq, size_t pos)
Definition: iseq.c:1774
ISEQ_TRANSLATED
#define ISEQ_TRANSLATED
Definition: iseq.h:87
PRIuSIZE
#define PRIuSIZE
Definition: ruby.h:208
rb_global_entry::id
ID id
Definition: internal.h:1352
ULONG2NUM
#define ULONG2NUM(x)
Definition: ruby.h:1645
rb_iseq_constant_body::param
struct rb_iseq_constant_body::@178 param
parameter information
rb_ast_struct
Definition: node.h:399
rb_iseq_constant_body::ISEQ_TYPE_BLOCK
@ ISEQ_TYPE_BLOCK
Definition: vm_core.h:315
rb_iseq_constant_body::lead_num
int lead_num
Definition: vm_core.h:367
rb_file_open_str
VALUE rb_file_open_str(VALUE, const char *)
Definition: io.c:6252
rb_iseq_constant_body::pc2branchindex
VALUE pc2branchindex
Definition: vm_core.h:431
ISEQ_BRANCH_COVERAGE
#define ISEQ_BRANCH_COVERAGE(iseq)
Definition: iseq.h:37
rb_iseq_location_struct
Definition: vm_core.h:272
RUBY_EVENT_COVERAGE_LINE
#define RUBY_EVENT_COVERAGE_LINE
Definition: vm_core.h:1956
rb_iseqw_to_iseq
const rb_iseq_t * rb_iseqw_to_iseq(VALUE iseqw)
Definition: iseq.c:1350
DATA_PTR
#define DATA_PTR(dta)
Definition: ruby.h:1175
LIKELY
#define LIKELY(x)
Definition: ffi_common.h:125
rb_cRubyVM
VALUE rb_cRubyVM
Definition: vm.c:365
rb_iseq_new_main
rb_iseq_t * rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent)
Definition: iseq.c:785
rb_str_intern
VALUE rb_str_intern(VALUE)
Definition: symbol.c:710
RHASH_SIZE
#define RHASH_SIZE(hsh)
Definition: fbuffer.h:8
rb_iseqw_new
VALUE rb_iseqw_new(const rb_iseq_t *iseq)
Definition: iseq.c:1157
rb_iseq_init_trace
void rb_iseq_init_trace(rb_iseq_t *iseq)
Definition: iseq.c:623
rb_iseq_mark_insn_storage
void rb_iseq_mark_insn_storage(struct iseq_compile_data_storage *storage)
Definition: compile.c:9197
st_init_numtable_with_size
st_table * st_init_numtable_with_size(st_index_t size)
Definition: st.c:660
iseq.h
rb_iseq_load_iseq
const rb_iseq_t * rb_iseq_load_iseq(VALUE fname)
Definition: iseq.c:847
rb_vm_get_insns_address_table
const void ** rb_vm_get_insns_address_table(void)
Definition: vm_exec.c:126
rb_iseq_location_struct::label
VALUE label
Definition: vm_core.h:275
OPT_FROZEN_STRING_LITERAL
#define OPT_FROZEN_STRING_LITERAL
Definition: vm_opts.h:25
rb_iseq_constant_body::local_table_size
unsigned int local_table_size
Definition: vm_core.h:435
rb_iseq_constant_body::is_entries
union iseq_inline_storage_entry * is_entries
Definition: vm_core.h:420
insn_data_struct::trace_encoded_insn
void * trace_encoded_insn
Definition: iseq.c:3080
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:768
COVERAGE_TARGET_ONESHOT_LINES
#define COVERAGE_TARGET_ONESHOT_LINES
Definition: internal.h:2216
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
nd_node_id
#define nd_node_id(n)
Definition: node.h:211
imm_block_rank_get
#define imm_block_rank_get(v, i)
Definition: iseq.c:3426
rb_iseqw_local_variables
VALUE rb_iseqw_local_variables(VALUE iseqval)
Definition: iseq.c:3321
RB_OBJ_WRITTEN
#define RB_OBJ_WRITTEN(a, oldv, b)
Definition: ruby.h:1509
sym
#define sym(x)
Definition: date_core.c:3716
rb_iseq_defined_string
VALUE rb_iseq_defined_string(enum defined_type type)
Definition: iseq.c:3033
rb_compile_option_struct
Definition: iseq.h:206
st_data_t
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:22
rb_iseq_build_from_ary
void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, VALUE exception, VALUE body)
Definition: compile.c:9249
rb_iseq_disasm_insn
int rb_iseq_disasm_insn(VALUE ret, const VALUE *code, size_t pos, const rb_iseq_t *iseq, VALUE child)
Disassemble a instruction Iseq -> Iseq inspect object.
Definition: iseq.c:2021
rb_realpath_internal
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
Definition: file.c:4409
rb_iseq_constant_body::ci_size
unsigned int ci_size
Definition: vm_core.h:437
rb_hook_list_remove_tracepoint
void rb_hook_list_remove_tracepoint(rb_hook_list_t *list, VALUE tpval)
Definition: vm_trace.c:1256
rb_hook_list_connect_tracepoint
void rb_hook_list_connect_tracepoint(VALUE target, rb_hook_list_t *list, VALUE tpval, unsigned int target_line)
Definition: vm_trace.c:1246
rb_iseq_constant_body::variable
struct rb_iseq_constant_body::@179 variable
INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE
#define INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE
Definition: iseq.h:272
rb_iseq_constant_body::size
unsigned int size
Definition: vm_core.h:365
mjit.h
rb_hook_list_free
void rb_hook_list_free(rb_hook_list_t *hooks)
Definition: vm_trace.c:66
rb_hash_lookup
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:1990
iseq_value_itr_t
VALUE iseq_value_itr_t(void *ctx, VALUE obj)
Definition: iseq.c:147
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
rb_call_info_with_kwarg::kw_arg
struct rb_call_info_kw_arg * kw_arg
Definition: vm_core.h:247
rb_code_position_struct::column
int column
Definition: node.h:132
ruby_xcalloc
void * ruby_xcalloc(size_t n, size_t size)
Definition: gc.c:11970
rb_iseq_free
void rb_iseq_free(const rb_iseq_t *iseq)
Definition: iseq.c:89
OPT_SPECIALISED_INSTRUCTION
#define OPT_SPECIALISED_INSTRUCTION
Definition: vm_opts.h:23
rb_iseq_constant_body::catch_table
struct iseq_catch_table * catch_table
Definition: vm_core.h:414
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1080
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1231
vm_core.h
iseq_inline_storage_entry::value
VALUE value
Definition: vm_core.h:234
rb_iseq_constant_body::type
enum rb_iseq_constant_body::iseq_type type
succ_index_table::succ_dict_block
Definition: iseq.c:3418
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
rb_iseq_remove_coverage_all
void rb_iseq_remove_coverage_all(void)
Definition: iseq.c:1110
RBASIC_CLASS
#define RBASIC_CLASS(obj)
Definition: ruby.h:906
rb_compile_option_struct::peephole_optimization
unsigned int peephole_optimization
Definition: iseq.h:208
entries
struct iseq_catch_table_entry entries[]
Definition: rb_mjit_min_header-2.7.0.h:10827
rb_get_coverages
VALUE rb_get_coverages(void)
Definition: thread.c:5477
rb_iseq_compile_node
VALUE rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
Definition: compile.c:644
RUBY_FREE_LEAVE
#define RUBY_FREE_LEAVE(msg)
Definition: gc.h:58
insn_data_struct::insn_len
int insn_len
Definition: iseq.c:3078
mjit_free_iseq
void mjit_free_iseq(const rb_iseq_t *iseq)
RUBY_FREE_ENTER
#define RUBY_FREE_ENTER(msg)
Definition: gc.h:57
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
size
int size
Definition: encoding.c:58
rb_iseq_constant_body::block_start
int block_start
Definition: vm_core.h:372
rb_str_set_len
void rb_str_set_len(VALUE, long)
Definition: string.c:2692
CHECK_HASH
#define CHECK_HASH(v)
Definition: iseq.c:859
OPT_TAILCALL_OPTIMIZATION
#define OPT_TAILCALL_OPTIMIZATION
Definition: vm_opts.h:21
FALSE
#define FALSE
Definition: nkf.h:174
rb_ast_body_struct::line_count
int line_count
Definition: node.h:397
rb_iseq_constant_body::iseq_insn_info::body
const struct iseq_insn_info_entry * body
Definition: vm_core.h:403
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
CHECK_EVENT
#define CHECK_EVENT(ev)
rb_gc_mark_movable
void rb_gc_mark_movable(VALUE ptr)
Definition: gc.c:5206
rb_typeddata_is_instance_of
int rb_typeddata_is_instance_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:883
CHECK_STRING
#define CHECK_STRING(v)
Definition: iseq.c:860
rb_iseq_base_label
VALUE rb_iseq_base_label(const rb_iseq_t *iseq)
Definition: iseq.c:1051
rb_parser_compile_string_path
rb_ast_t * rb_parser_compile_string_path(VALUE vparser, VALUE f, VALUE s, int line)
Definition: ripper.c:12897
rb_iseq_constant_body::flags
struct rb_iseq_constant_body::@178::@180 flags
rb_hash_foreach
void rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
Definition: hash.c:1461
C
#define C(ev, cstr, l)
rb_vm_insns_translator_t
VALUE rb_vm_insns_translator_t(const void *addr)
Definition: iseq.c:148
rb_str_new_cstr
#define rb_str_new_cstr(str)
Definition: rb_mjit_min_header-2.7.0.h:6117
iseq_catch_table_entry::type
enum iseq_catch_table_entry::catch_type type
OPT_STACK_CACHING
#define OPT_STACK_CACHING
Definition: vm_opts.h:61
rb_error_arity
MJIT_STATIC void rb_error_arity(int argc, int min, int max)
Definition: vm_insnhelper.c:387
rb_iseq_location_struct::pathobj
VALUE pathobj
Definition: vm_core.h:273
RB_OBJ_WRITE
#define RB_OBJ_WRITE(a, slot, b)
Definition: ruby.h:1508
CONST_ID
#define CONST_ID(var, str)
Definition: ruby.h:1841
iseq_compile_data_storage::size
unsigned int size
Definition: iseq.h:277
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:604
rb_vm_encoded_insn_data_table_init
void rb_vm_encoded_insn_data_table_init(void)
Definition: iseq.c:3085
key
key
Definition: openssl_missing.h:181
T_HASH
#define T_HASH
Definition: ruby.h:531
rb_vm_insn_addr2insn
int rb_vm_insn_addr2insn(const void *addr)
Definition: iseq.c:3111
CALL_FLAG
#define CALL_FLAG(n)
rb_cISeq
VALUE rb_cISeq
Definition: iseq.c:32
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
src
__inline__ const void *__restrict src
Definition: rb_mjit_min_header-2.7.0.h:2836
rb_iseq_constant_body::iseq_unique_id
uintptr_t iseq_unique_id
Definition: vm_core.h:451
rb_iseq_line_no
unsigned int rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
Definition: iseq.c:1761
trace_clear_local_events_struct::tpval
VALUE tpval
Definition: iseq.c:3245
RUBY_MARK_UNLESS_NULL
#define RUBY_MARK_UNLESS_NULL(ptr)
Definition: gc.h:66
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
ISEQ_USE_COMPILE_DATA
#define ISEQ_USE_COMPILE_DATA
Definition: iseq.h:86
iseq_catch_table_entry::catch_type
catch_type
Definition: iseq.h:226
rb_id_table_free
void rb_id_table_free(struct rb_id_table *tbl)
Definition: id_table.c:102
iseq_compile_data
Definition: iseq.h:92
rb_hook_list_mark
void rb_hook_list_mark(rb_hook_list_t *hooks)
Definition: vm_trace.c:53
DECL_SYMBOL
#define DECL_SYMBOL(name)
Definition: iseq.c:2544
FL_TEST_RAW
#define FL_TEST_RAW(x, f)
Definition: ruby.h:1352
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
rb_event_flag_t
uint32_t rb_event_flag_t
Definition: ruby.h:2278
id_class
ID id_class
Definition: eventids1.c:32
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
rb_str_cat_cstr
#define rb_str_cat_cstr(str, ptr)
Definition: rb_mjit_min_header-2.7.0.h:6126
ISEQ_COVERAGE_SET
#define ISEQ_COVERAGE_SET(iseq, cov)
Definition: iseq.h:35
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:667
iseq_compile_data_storage::pos
unsigned int pos
Definition: iseq.h:276
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
rb_objspace_each_objects
void rb_objspace_each_objects(each_obj_callback *callback, void *data)
Definition: gc.c:3025
OPT_INLINE_CONST_CACHE
#define OPT_INLINE_CONST_CACHE
Definition: vm_opts.h:24
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
rb_ary_new_from_values
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
Definition: array.c:762
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:634
RUBY_MARK_ENTER
#define RUBY_MARK_ENTER(msg)
Definition: gc.h:55
internal.h
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
iseq_compile_data::ivar_cache_table
struct rb_id_table * ivar_cache_table
Definition: iseq.h:118
argv
char ** argv
Definition: ruby.c:223
f
#define f
RNode::nd_loc
rb_code_location_t nd_loc
Definition: node.h:172
iseq_alloc
rb_iseq_t * iseq_alloc(void)
ST_CONTINUE
@ ST_CONTINUE
Definition: st.h:99
PRIdPTRDIFF
#define PRIdPTRDIFF
Definition: ruby.h:190
rb_iseq_constant_body::iseq_encoded
VALUE * iseq_encoded
Definition: vm_core.h:325
INIT_SYMBOL
#define INIT_SYMBOL(name)
Definition: iseq.c:2547
rb_iseq_parameters
VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
Definition: iseq.c:2939
small_block_rank_get
#define small_block_rank_get(v, i)
Definition: iseq.c:3428
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1197
rb_insn_operand_intern
VALUE rb_insn_operand_intern(const rb_iseq_t *iseq, VALUE insn, int op_no, VALUE op, int len, size_t pos, const VALUE *pnop, VALUE child)
Definition: iseq.c:1828
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
CHECK_ARRAY
#define CHECK_ARRAY(v)
Definition: iseq.c:858
rb_iseq_mark
void rb_iseq_mark(const rb_iseq_t *iseq)
Definition: iseq.c:287
st_data_t
unsigned long st_data_t
Definition: rb_mjit_min_header-2.7.0.h:5363
rb_ary_join
VALUE rb_ary_join(VALUE ary, VALUE sep)
Definition: array.c:2347
DEFINED_CONST_FROM
@ DEFINED_CONST_FROM
Definition: iseq.h:302
rb_iseq_insns_info_encode_positions
void rb_iseq_insns_info_encode_positions(const rb_iseq_t *iseq)
Definition: iseq.c:595
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
rb_iseq_constant_body::opt_num
int opt_num
Definition: vm_core.h:368
ISEQ_MAJOR_VERSION
#define ISEQ_MAJOR_VERSION
Definition: iseq.h:16
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
iseq_insn_info_entry::events
rb_event_flag_t events
Definition: iseq.h:222
CHECK_SYMBOL
#define CHECK_SYMBOL(v)
Definition: iseq.c:861
PRIuVALUE
#define PRIuVALUE
Definition: ruby.h:163
rb_iseq_constant_body::ISEQ_TYPE_RESCUE
@ ISEQ_TYPE_RESCUE
Definition: vm_core.h:317
types
enum imemo_type types
Definition: debug.c:72
rb_parser_set_context
VALUE rb_parser_set_context(VALUE vparser, const struct rb_iseq_struct *base, int main)
Definition: ripper.c:19234
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2779
rb_iseq_constant_body::ISEQ_TYPE_ENSURE
@ ISEQ_TYPE_ENSURE
Definition: vm_core.h:318
rb_iseq_clear_event_flags
void rb_iseq_clear_event_flags(const rb_iseq_t *iseq, size_t pos, rb_event_flag_t reset)
Definition: iseq.c:1786
rb_iseq_constant_body::post_num
int post_num
Definition: vm_core.h:371
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
ISEQ_MARKABLE_ISEQ
#define ISEQ_MARKABLE_ISEQ
Definition: iseq.h:88
rb_str_modify_expand
void rb_str_modify_expand(VALUE, long)
Definition: string.c:2122
rb_iseq_constant_body::post_start
int post_start
Definition: vm_core.h:370
RB_OBJ_FREEZE
#define RB_OBJ_FREEZE(x)
Definition: ruby.h:1344
argc
int argc
Definition: ruby.c:222
ISEQ_COVERAGE
#define ISEQ_COVERAGE(iseq)
Definition: iseq.h:34
rb_iseq_shared_exc_local_tbl
const ID rb_iseq_shared_exc_local_tbl[]
Definition: compile.c:110
rb_code_location_struct::beg_pos
rb_code_position_t beg_pos
Definition: node.h:136
err
int err
Definition: win32.c:135
RUBY_EVENT_B_CALL
#define RUBY_EVENT_B_CALL
Definition: ruby.h:2253
rb_get_coverage_mode
int rb_get_coverage_mode(void)
Definition: thread.c:5483
succ_index_table::imm_part
uint64_t imm_part[IMMEDIATE_TABLE_SIZE/9]
Definition: iseq.c:3417
rb_data_type_struct
Definition: ruby.h:1148
BUILTIN_TYPE
#define BUILTIN_TYPE(x)
Definition: ruby.h:551
imm_block_rank_set
#define imm_block_rank_set(v, i, r)
Definition: iseq.c:3425
rb_iseq_new_with_opt
rb_iseq_t * rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, enum iseq_type type, const rb_compile_option_t *option)
Definition: iseq.c:807
rb_call_data::ci
struct rb_call_info ci
Definition: internal.h:2395
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.0.h:6116
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5212
trace_set_local_events_struct::tpval
VALUE tpval
Definition: iseq.c:3188
MJIT_FUNC_EXPORTED
#define MJIT_FUNC_EXPORTED
Definition: defines.h:396
rb_iseq_location_struct::node_id
int node_id
Definition: vm_core.h:277
asan_poison_object_if
#define asan_poison_object_if(ptr, obj)
Definition: internal.h:159
RUBY_EVENT_C_RETURN
#define RUBY_EVENT_C_RETURN
Definition: ruby.h:2248
rb_iseq_trace_set_all
void rb_iseq_trace_set_all(rb_event_flag_t turnon_events)
Definition: iseq.c:3315
rb_iseq_new_with_callback
rb_iseq_t * rb_iseq_new_with_callback(const struct rb_iseq_new_with_callback_callback_func *ifunc, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, enum iseq_type type, const rb_compile_option_t *option)
Definition: iseq.c:828
rb_iseq_add_local_tracepoint_recursively
int rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line)
Definition: iseq.c:3202
Qtrue
#define Qtrue
Definition: ruby.h:468
rb_str_catf
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1237
rb_iseq_ibf_load_extra_data
VALUE rb_iseq_ibf_load_extra_data(VALUE str)
Definition: compile.c:11630
rb_obj_is_method
VALUE rb_obj_is_method(VALUE)
Definition: proc.c:1459
rb_iseq_constant_body::iseq_insn_info::size
unsigned int size
Definition: vm_core.h:405
VM_INSTRUCTION_SIZE
@ VM_INSTRUCTION_SIZE
Definition: rb_mjit_min_header-2.7.0.h:12176
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:274
rb_iseq_pathobj_set
void rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath)
Definition: iseq.c:469
len
uint8_t len
Definition: escape.c:17
rb_iseq_trace_flag_cleared
void rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos)
Definition: iseq.c:3140
rb_builtin_function::argc
const int argc
Definition: builtin.h:9
PRIdVALUE
#define PRIdVALUE
Definition: ruby.h:161
rb_mark_tbl
void rb_mark_tbl(st_table *tbl)
Definition: gc.c:5005
rb_iseq_struct::body
struct rb_iseq_constant_body * body
Definition: vm_core.h:460
iseq_catch_table_entry::sp
unsigned int sp
Definition: iseq.h:252
defined_type
defined_type
Definition: iseq.h:283
iseq_compile_data::catch_table_ary
const VALUE catch_table_ary
Definition: iseq.h:95
FLEX_ARY_LEN
#define FLEX_ARY_LEN
Definition: internal.h:2620
rb_iseq_ibf_load
const rb_iseq_t * rb_iseq_ibf_load(VALUE str)
Definition: compile.c:11602
succ_index_table
Definition: iseq.c:3416
RUBY_EVENT_RETURN
#define RUBY_EVENT_RETURN
Definition: ruby.h:2246
rb_iseq_constant_body::iseq_size
unsigned int iseq_size
Definition: vm_core.h:324
insn_data_struct::notrace_encoded_insn
void * notrace_encoded_insn
Definition: iseq.c:3079
T_STRING
#define T_STRING
Definition: ruby.h:528
top
unsigned int top
Definition: nkf.c:4323
rb_insn_unified_local_var_level
int rb_insn_unified_local_var_level(VALUE)
RUBY_EVENT_C_CALL
#define RUBY_EVENT_C_CALL
Definition: ruby.h:2247
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
rb_sym2str
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
rb_iseq_constant_body::ci_kw_size
unsigned int ci_kw_size
Definition: vm_core.h:438
iseq
const rb_iseq_t * iseq
Definition: rb_mjit_min_header-2.7.0.h:13504
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
eval_intern.h
rb_str_resurrect
VALUE rb_str_resurrect(VALUE str)
Definition: string.c:1522
rb_iseq_constant_body::catch_except_p
char catch_except_p
Definition: vm_core.h:441
OPT_DEBUG_FROZEN_STRING_LITERAL
#define OPT_DEBUG_FROZEN_STRING_LITERAL
Definition: vm_opts.h:26
rb_call_info
Definition: internal.h:2387
rb_method_iseq
const rb_iseq_t * rb_method_iseq(VALUE body)
Definition: proc.c:2679
rb_iseq_constant_body::iseq_insn_info::positions
unsigned int * positions
Definition: vm_core.h:404
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
rb_code_location_struct::end_pos
rb_code_position_t end_pos
Definition: node.h:137
rb_code_location_struct
Definition: node.h:135
OPT_PEEPHOLE_OPTIMIZATION
#define OPT_PEEPHOLE_OPTIMIZATION
Definition: vm_opts.h:22
builtin.h
rb_ast_body_struct::root
const NODE * root
Definition: node.h:395
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
trace_clear_local_events_struct
Definition: iseq.c:3244
realpath
char * realpath(const char *__restrict path, char *__restrict resolved_path)
RUBY_EVENT_COVERAGE_BRANCH
#define RUBY_EVENT_COVERAGE_BRANCH
Definition: vm_core.h:1957
rb_fstring_lit
#define rb_fstring_lit(str)
Definition: internal.h:2123
exc
const rb_iseq_t const VALUE exc
Definition: rb_mjit_min_header-2.7.0.h:13504
unsigned
#define unsigned
Definition: rb_mjit_min_header-2.7.0.h:2875
rb_iseq_ibf_dump
VALUE rb_iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt)
Definition: compile.c:11378
st_lookup
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
Definition: st.c:1101
util.h
rb_iseq_absolute_path
VALUE rb_iseq_absolute_path(const rb_iseq_t *iseq)
Definition: iseq.c:1039
UNALIGNED_MEMBER_PTR
#define UNALIGNED_MEMBER_PTR(ptr, mem)
Definition: internal.h:2685
iseq_catch_table
Definition: rb_mjit_min_header-2.7.0.h:10860
rb_iseq_constant_body::ISEQ_TYPE_PLAIN
@ ISEQ_TYPE_PLAIN
Definition: vm_core.h:321
rb_iseq_constant_body::call_data
struct rb_call_data * call_data
Definition: vm_core.h:421
rb_iseq_struct::exec
struct rb_iseq_struct::@181::@183 exec
succ_index_table::succ_dict_block::small_block_ranks
uint64_t small_block_ranks
Definition: iseq.c:3420
rb_undef_alloc_func
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:722
rb_iseq_trace_set
void rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events)
Definition: iseq.c:3269
rb_iseq_method_name
VALUE rb_iseq_method_name(const rb_iseq_t *iseq)
Definition: iseq.c:1063
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
numberof
#define numberof(array)
Definition: etc.c:618
rb_iseq_update_references
void rb_iseq_update_references(rb_iseq_t *iseq)
Definition: iseq.c:221
rb_call_data
Definition: internal.h:2393
rb_iseq_constant_body::is_size
unsigned int is_size
Definition: vm_core.h:436
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
st_free_table
void st_free_table(st_table *tab)
Definition: st.c:709
st_table
Definition: st.h:79
rb_call_info_with_kwarg
Definition: vm_core.h:245
iseq_catch_table_entry::start
unsigned int start
Definition: iseq.h:249
rb_define_private_method
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1569
iseq_compile_data_storage::next
struct iseq_compile_data_storage * next
Definition: iseq.h:275
strcspn
size_t strcspn(const char *, const char *)
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2812
rb_default_coverage
VALUE rb_default_coverage(int)
Definition: thread.c:5519
id_table.h
rb_builtin_function::name
const char *const name
Definition: builtin.h:13
RTEST
#define RTEST(v)
Definition: ruby.h:481
rb_iseq_constant_body::flip_count
rb_snum_t flip_count
Definition: vm_core.h:429
rb_iseq_insns_info_decode_positions
unsigned int * rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body)
Definition: iseq.c:613
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
main
int main(void)
Definition: closure_fn0.c:49
iseq_compile_data::err_info
const VALUE err_info
Definition: iseq.h:94
trace_set_local_events_struct
Definition: iseq.c:3186
RB_ZALLOC
#define RB_ZALLOC(type)
Definition: ruby.h:1660
RNode
Definition: node.h:149
rb_iseq_location_struct::base_label
VALUE base_label
Definition: vm_core.h:274
rb_iseq_compile_callback
VALUE rb_iseq_compile_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback_callback_func *ifunc)
Definition: compile.c:630
ISEQ_TRACE_EVENTS
#define ISEQ_TRACE_EVENTS
Definition: iseq.h:75
ISEQ_EXECUTABLE_P
#define ISEQ_EXECUTABLE_P(iseq)
Definition: iseq.h:90
rb_global_entry
Definition: internal.h:1350
RUBY_TYPED_WB_PROTECTED
#define RUBY_TYPED_WB_PROTECTED
Definition: ruby.h:1208
RUBY_EVENT_LINE
#define RUBY_EVENT_LINE
Definition: ruby.h:2242
small_block_rank_set
#define small_block_rank_set(v, i, r)
Definition: iseq.c:3427
rb_iseq_constant_body::stack_max
unsigned int stack_max
Definition: vm_core.h:439
RUBY_EVENT_CLASS
#define RUBY_EVENT_CLASS
Definition: ruby.h:2243
iseq_insn_info_entry::line_no
int line_no
Definition: iseq.h:221
RSTRING_END
#define RSTRING_END(str)
Definition: ruby.h:1013
rb_iseq_constant_body::iseq_type
iseq_type
Definition: vm_core.h:312
rb_str_cmp
int rb_str_cmp(VALUE, VALUE)
Definition: string.c:3228
rb_iseq_constant_body::ISEQ_TYPE_MAIN
@ ISEQ_TYPE_MAIN
Definition: vm_core.h:320
iseq_inline_storage_entry
Definition: vm_core.h:231
iseq_inline_storage_entry::once
struct iseq_inline_storage_entry::@177 once
name
const char * name
Definition: nkf.c:208