Stop exporting symbols for MJIT
[ruby.git] / iseq.c
blob8365356d20ae8cf6d7cc2a046e4cfd102d35232b
1 /**********************************************************************
3 iseq.c -
5 $Author$
6 created at: 2006-07-11(Tue) 09:00:03 +0900
8 Copyright (C) 2006 Koichi Sasada
10 **********************************************************************/
12 #define RUBY_VM_INSNS_INFO 1
13 /* #define RUBY_MARK_FREE_DEBUG 1 */
15 #include "ruby/internal/config.h"
17 #ifdef HAVE_DLADDR
18 # include <dlfcn.h>
19 #endif
21 #include "eval_intern.h"
22 #include "id_table.h"
23 #include "internal.h"
24 #include "internal/bits.h"
25 #include "internal/class.h"
26 #include "internal/compile.h"
27 #include "internal/error.h"
28 #include "internal/file.h"
29 #include "internal/gc.h"
30 #include "internal/hash.h"
31 #include "internal/parse.h"
32 #include "internal/sanitizers.h"
33 #include "internal/symbol.h"
34 #include "internal/thread.h"
35 #include "internal/variable.h"
36 #include "iseq.h"
37 #include "mjit.h"
38 #include "ruby/util.h"
39 #include "vm_core.h"
40 #include "vm_callinfo.h"
41 #include "yjit.h"
42 #include "ruby/ractor.h"
43 #include "builtin.h"
44 #include "insns.inc"
45 #include "insns_info.inc"
47 VALUE rb_cISeq;
48 static VALUE iseqw_new(const rb_iseq_t *iseq);
49 static const rb_iseq_t *iseqw_check(VALUE iseqw);
51 #if VM_INSN_INFO_TABLE_IMPL == 2
52 static struct succ_index_table *succ_index_table_create(int max_pos, int *data, int size);
53 static unsigned int *succ_index_table_invert(int max_pos, struct succ_index_table *sd, int size);
54 static int succ_index_lookup(const struct succ_index_table *sd, int x);
55 #endif
57 #define hidden_obj_p(obj) (!SPECIAL_CONST_P(obj) && !RBASIC(obj)->klass)
59 static inline VALUE
60 obj_resurrect(VALUE obj)
62 if (hidden_obj_p(obj)) {
63 switch (BUILTIN_TYPE(obj)) {
64 case T_STRING:
65 obj = rb_str_resurrect(obj);
66 break;
67 case T_ARRAY:
68 obj = rb_ary_resurrect(obj);
69 break;
70 case T_HASH:
71 obj = rb_hash_resurrect(obj);
72 break;
73 default:
74 break;
77 return obj;
80 static void
81 free_arena(struct iseq_compile_data_storage *cur)
83 struct iseq_compile_data_storage *next;
85 while (cur) {
86 next = cur->next;
87 ruby_xfree(cur);
88 cur = next;
92 static void
93 compile_data_free(struct iseq_compile_data *compile_data)
95 if (compile_data) {
96 free_arena(compile_data->node.storage_head);
97 free_arena(compile_data->insn.storage_head);
98 if (compile_data->ivar_cache_table) {
99 rb_id_table_free(compile_data->ivar_cache_table);
101 ruby_xfree(compile_data);
105 static void
106 remove_from_constant_cache(ID id, IC ic)
108 rb_vm_t *vm = GET_VM();
109 VALUE lookup_result;
110 st_data_t ic_data = (st_data_t)ic;
112 if (rb_id_table_lookup(vm->constant_cache, id, &lookup_result)) {
113 st_table *ics = (st_table *)lookup_result;
114 st_delete(ics, &ic_data, NULL);
116 if (ics->num_entries == 0) {
117 rb_id_table_delete(vm->constant_cache, id);
118 st_free_table(ics);
123 // When an ISEQ is being freed, all of its associated ICs are going to go away
124 // as well. Because of this, we need to iterate over the ICs, and clear them
125 // from the VM's constant cache.
126 static void
127 iseq_clear_ic_references(const rb_iseq_t *iseq)
129 // In some cases (when there is a compilation error), we end up with
130 // ic_size greater than 0, but no allocated is_entries buffer.
131 // If there's no is_entries buffer to loop through, return early.
132 // [Bug #19173]
133 if (!ISEQ_BODY(iseq)->is_entries) {
134 return;
137 for (unsigned int ic_idx = 0; ic_idx < ISEQ_BODY(iseq)->ic_size; ic_idx++) {
138 IC ic = &ISEQ_IS_IC_ENTRY(ISEQ_BODY(iseq), ic_idx);
140 // Iterate over the IC's constant path's segments and clean any references to
141 // the ICs out of the VM's constant cache table.
142 const ID *segments = ic->segments;
144 // It's possible that segments is NULL if we overallocated an IC but
145 // optimizations removed the instruction using it
146 if (segments == NULL)
147 continue;
149 for (int i = 0; segments[i]; i++) {
150 ID id = segments[i];
151 if (id == idNULL) continue;
152 remove_from_constant_cache(id, ic);
155 ruby_xfree((void *)segments);
159 void
160 rb_iseq_free(const rb_iseq_t *iseq)
162 RUBY_FREE_ENTER("iseq");
164 if (iseq && ISEQ_BODY(iseq)) {
165 iseq_clear_ic_references(iseq);
166 struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
167 mjit_free_iseq(iseq); /* Notify MJIT */
168 #if USE_YJIT
169 rb_yjit_iseq_free(body->yjit_payload);
170 #endif
171 ruby_xfree((void *)body->iseq_encoded);
172 ruby_xfree((void *)body->insns_info.body);
173 if (body->insns_info.positions) ruby_xfree((void *)body->insns_info.positions);
174 #if VM_INSN_INFO_TABLE_IMPL == 2
175 if (body->insns_info.succ_index_table) ruby_xfree(body->insns_info.succ_index_table);
176 #endif
177 if (LIKELY(body->local_table != rb_iseq_shared_exc_local_tbl))
178 ruby_xfree((void *)body->local_table);
179 ruby_xfree((void *)body->is_entries);
181 if (body->call_data) {
182 ruby_xfree(body->call_data);
184 ruby_xfree((void *)body->catch_table);
185 ruby_xfree((void *)body->param.opt_table);
186 if (ISEQ_MBITS_BUFLEN(body->iseq_size) > 1 && body->mark_bits.list) {
187 ruby_xfree((void *)body->mark_bits.list);
190 if (body->param.keyword != NULL) {
191 ruby_xfree((void *)body->param.keyword->default_values);
192 ruby_xfree((void *)body->param.keyword);
194 compile_data_free(ISEQ_COMPILE_DATA(iseq));
195 if (body->outer_variables) rb_id_table_free(body->outer_variables);
196 ruby_xfree(body);
199 if (iseq && ISEQ_EXECUTABLE_P(iseq) && iseq->aux.exec.local_hooks) {
200 rb_hook_list_free(iseq->aux.exec.local_hooks);
203 RUBY_FREE_LEAVE("iseq");
206 typedef VALUE iseq_value_itr_t(void *ctx, VALUE obj);
208 static inline void
209 iseq_scan_bits(unsigned int page, iseq_bits_t bits, VALUE *code, VALUE *original_iseq)
211 unsigned int offset;
212 unsigned int page_offset = (page * ISEQ_MBITS_BITLENGTH);
214 while (bits) {
215 offset = ntz_intptr(bits);
216 VALUE op = code[page_offset + offset];
217 rb_gc_mark_and_move(&code[page_offset + offset]);
218 VALUE newop = code[page_offset + offset];
219 if (original_iseq && newop != op) {
220 original_iseq[page_offset + offset] = newop;
222 bits &= bits - 1; // Reset Lowest Set Bit (BLSR)
226 static void
227 rb_iseq_mark_and_move_each_value(const rb_iseq_t *iseq, VALUE *original_iseq)
229 unsigned int size;
230 VALUE *code;
231 const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
233 size = body->iseq_size;
234 code = body->iseq_encoded;
236 union iseq_inline_storage_entry *is_entries = body->is_entries;
238 if (body->is_entries) {
239 // Skip iterating over ivc caches
240 is_entries += body->ivc_size;
242 // ICVARC entries
243 for (unsigned int i = 0; i < body->icvarc_size; i++, is_entries++) {
244 ICVARC icvarc = (ICVARC)is_entries;
245 if (icvarc->entry) {
246 RUBY_ASSERT(!RB_TYPE_P(icvarc->entry->class_value, T_NONE));
248 rb_gc_mark_and_move(&icvarc->entry->class_value);
252 // ISE entries
253 for (unsigned int i = 0; i < body->ise_size; i++, is_entries++) {
254 union iseq_inline_storage_entry *const is = (union iseq_inline_storage_entry *)is_entries;
255 if (is->once.value) {
256 rb_gc_mark_and_move(&is->once.value);
260 // IC Entries
261 for (unsigned int i = 0; i < body->ic_size; i++, is_entries++) {
262 IC ic = (IC)is_entries;
263 if (ic->entry) {
264 rb_gc_mark_and_move_ptr(&ic->entry);
269 // Embedded VALUEs
270 if (body->mark_bits.list) {
271 if (ISEQ_MBITS_BUFLEN(size) == 1) {
272 iseq_scan_bits(0, body->mark_bits.single, code, original_iseq);
274 else {
275 if (body->mark_bits.list) {
276 for (unsigned int i = 0; i < ISEQ_MBITS_BUFLEN(size); i++) {
277 iseq_bits_t bits = body->mark_bits.list[i];
278 iseq_scan_bits(i, bits, code, original_iseq);
285 void
286 rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating)
288 RUBY_MARK_ENTER("iseq");
290 rb_gc_mark_and_move(&iseq->wrapper);
292 if (ISEQ_BODY(iseq)) {
293 struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
295 rb_iseq_mark_and_move_each_value(iseq, reference_updating ? ISEQ_ORIGINAL_ISEQ(iseq) : NULL);
297 rb_gc_mark_and_move(&body->variable.coverage);
298 rb_gc_mark_and_move(&body->variable.pc2branchindex);
299 rb_gc_mark_and_move(&body->variable.script_lines);
300 rb_gc_mark_and_move(&body->location.label);
301 rb_gc_mark_and_move(&body->location.base_label);
302 rb_gc_mark_and_move(&body->location.pathobj);
303 if (body->local_iseq) rb_gc_mark_and_move_ptr(&body->local_iseq);
304 if (body->parent_iseq) rb_gc_mark_and_move_ptr(&body->parent_iseq);
305 if (body->mandatory_only_iseq) rb_gc_mark_and_move_ptr(&body->mandatory_only_iseq);
307 if (body->call_data) {
308 for (unsigned int i = 0; i < body->ci_size; i++) {
309 struct rb_call_data *cds = body->call_data;
311 if (cds[i].ci) rb_gc_mark_and_move_ptr(&cds[i].ci);
313 const struct rb_callcache *cc = cds[i].cc;
314 if (cc) {
315 if (reference_updating) {
316 cc = (const struct rb_callcache *)rb_gc_location((VALUE)cc);
319 if (vm_cc_markable(cc)) {
320 VM_ASSERT((cc->flags & VM_CALLCACHE_ON_STACK) == 0);
322 const struct rb_callable_method_entry_struct *cme = vm_cc_cme(cc);
323 if (reference_updating) {
324 cme = (const struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cme);
327 if (cc->klass && !METHOD_ENTRY_INVALIDATED(cme)) {
328 rb_gc_mark_and_move_ptr(&cds[i].cc);
330 else {
331 cds[i].cc = rb_vm_empty_cc();
338 if (body->param.flags.has_kw && ISEQ_COMPILE_DATA(iseq) == NULL) {
339 const struct rb_iseq_param_keyword *const keyword = body->param.keyword;
341 for (int j = 0, i = keyword->required_num; i < keyword->num; i++, j++) {
342 rb_gc_mark_and_move(&keyword->default_values[j]);
346 if (body->catch_table) {
347 struct iseq_catch_table *table = body->catch_table;
349 for (unsigned int i = 0; i < table->size; i++) {
350 struct iseq_catch_table_entry *entry;
351 entry = UNALIGNED_MEMBER_PTR(table, entries[i]);
352 if (entry->iseq) {
353 rb_gc_mark_and_move_ptr(&entry->iseq);
358 if (reference_updating) {
359 #if USE_MJIT
360 rb_mjit_iseq_update_references(body);
361 #endif
362 #if USE_YJIT
363 rb_yjit_iseq_update_references(body->yjit_payload);
364 #endif
366 else {
367 #if USE_MJIT
368 rb_mjit_iseq_mark(body->mjit_blocks);
369 #endif
370 #if USE_YJIT
371 rb_yjit_iseq_mark(body->yjit_payload);
372 #endif
376 if (FL_TEST_RAW((VALUE)iseq, ISEQ_NOT_LOADED_YET)) {
377 rb_gc_mark_and_move(&iseq->aux.loader.obj);
379 else if (FL_TEST_RAW((VALUE)iseq, ISEQ_USE_COMPILE_DATA)) {
380 const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq);
382 rb_iseq_mark_and_move_insn_storage(compile_data->insn.storage_head);
384 rb_gc_mark_and_move((VALUE *)&compile_data->err_info);
385 rb_gc_mark_and_move((VALUE *)&compile_data->catch_table_ary);
387 else {
388 /* executable */
389 VM_ASSERT(ISEQ_EXECUTABLE_P(iseq));
391 if (iseq->aux.exec.local_hooks) {
392 rb_hook_list_mark_and_update(iseq->aux.exec.local_hooks);
396 RUBY_MARK_LEAVE("iseq");
399 static size_t
400 param_keyword_size(const struct rb_iseq_param_keyword *pkw)
402 size_t size = 0;
404 if (!pkw) return size;
406 size += sizeof(struct rb_iseq_param_keyword);
407 size += sizeof(VALUE) * (pkw->num - pkw->required_num);
409 return size;
412 size_t
413 rb_iseq_memsize(const rb_iseq_t *iseq)
415 size_t size = 0; /* struct already counted as RVALUE size */
416 const struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
417 const struct iseq_compile_data *compile_data;
419 /* TODO: should we count original_iseq? */
421 if (ISEQ_EXECUTABLE_P(iseq) && body) {
422 size += sizeof(struct rb_iseq_constant_body);
423 size += body->iseq_size * sizeof(VALUE);
424 size += body->insns_info.size * (sizeof(struct iseq_insn_info_entry) + sizeof(unsigned int));
425 size += body->local_table_size * sizeof(ID);
426 size += ISEQ_MBITS_BUFLEN(body->iseq_size) * ISEQ_MBITS_SIZE;
427 if (body->catch_table) {
428 size += iseq_catch_table_bytes(body->catch_table->size);
430 size += (body->param.opt_num + 1) * sizeof(VALUE);
431 size += param_keyword_size(body->param.keyword);
433 /* body->is_entries */
434 size += ISEQ_IS_SIZE(body) * sizeof(union iseq_inline_storage_entry);
436 if (ISEQ_BODY(iseq)->is_entries) {
437 /* IC entries constant segments */
438 for (unsigned int ic_idx = 0; ic_idx < body->ic_size; ic_idx++) {
439 IC ic = &ISEQ_IS_IC_ENTRY(body, ic_idx);
440 const ID *ids = ic->segments;
441 if (!ids) continue;
442 while (*ids++) {
443 size += sizeof(ID);
445 size += sizeof(ID); // null terminator
449 /* body->call_data */
450 size += body->ci_size * sizeof(struct rb_call_data);
451 // TODO: should we count imemo_callinfo?
454 compile_data = ISEQ_COMPILE_DATA(iseq);
455 if (compile_data) {
456 struct iseq_compile_data_storage *cur;
458 size += sizeof(struct iseq_compile_data);
460 cur = compile_data->node.storage_head;
461 while (cur) {
462 size += cur->size + offsetof(struct iseq_compile_data_storage, buff);
463 cur = cur->next;
467 return size;
470 struct rb_iseq_constant_body *
471 rb_iseq_constant_body_alloc(void)
473 struct rb_iseq_constant_body *iseq_body;
474 iseq_body = ZALLOC(struct rb_iseq_constant_body);
475 return iseq_body;
478 static rb_iseq_t *
479 iseq_alloc(void)
481 rb_iseq_t *iseq = iseq_imemo_alloc();
482 ISEQ_BODY(iseq) = rb_iseq_constant_body_alloc();
483 return iseq;
486 VALUE
487 rb_iseq_pathobj_new(VALUE path, VALUE realpath)
489 VALUE pathobj;
490 VM_ASSERT(RB_TYPE_P(path, T_STRING));
491 VM_ASSERT(NIL_P(realpath) || RB_TYPE_P(realpath, T_STRING));
493 if (path == realpath ||
494 (!NIL_P(realpath) && rb_str_cmp(path, realpath) == 0)) {
495 pathobj = rb_fstring(path);
497 else {
498 if (!NIL_P(realpath)) realpath = rb_fstring(realpath);
499 pathobj = rb_ary_new_from_args(2, rb_fstring(path), realpath);
500 rb_obj_freeze(pathobj);
502 return pathobj;
505 void
506 rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath)
508 RB_OBJ_WRITE(iseq, &ISEQ_BODY(iseq)->location.pathobj,
509 rb_iseq_pathobj_new(path, realpath));
512 static rb_iseq_location_t *
513 iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_code_location_t *code_location, const int node_id)
515 rb_iseq_location_t *loc = &ISEQ_BODY(iseq)->location;
517 rb_iseq_pathobj_set(iseq, path, realpath);
518 RB_OBJ_WRITE(iseq, &loc->label, name);
519 RB_OBJ_WRITE(iseq, &loc->base_label, name);
520 loc->first_lineno = first_lineno;
521 if (code_location) {
522 loc->node_id = node_id;
523 loc->code_location = *code_location;
525 else {
526 loc->code_location.beg_pos.lineno = 0;
527 loc->code_location.beg_pos.column = 0;
528 loc->code_location.end_pos.lineno = -1;
529 loc->code_location.end_pos.column = -1;
532 return loc;
535 static void
536 set_relation(rb_iseq_t *iseq, const rb_iseq_t *piseq)
538 struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
539 const VALUE type = body->type;
541 /* set class nest stack */
542 if (type == ISEQ_TYPE_TOP) {
543 body->local_iseq = iseq;
545 else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
546 body->local_iseq = iseq;
548 else if (piseq) {
549 body->local_iseq = ISEQ_BODY(piseq)->local_iseq;
552 if (piseq) {
553 body->parent_iseq = piseq;
556 if (type == ISEQ_TYPE_MAIN) {
557 body->local_iseq = iseq;
561 static struct iseq_compile_data_storage *
562 new_arena(void)
564 struct iseq_compile_data_storage * new_arena =
565 (struct iseq_compile_data_storage *)
566 ALLOC_N(char, INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE +
567 offsetof(struct iseq_compile_data_storage, buff));
569 new_arena->pos = 0;
570 new_arena->next = 0;
571 new_arena->size = INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE;
573 return new_arena;
576 static VALUE
577 prepare_iseq_build(rb_iseq_t *iseq,
578 VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_code_location_t *code_location, const int node_id,
579 const rb_iseq_t *parent, int isolated_depth, enum rb_iseq_type type,
580 VALUE script_lines, const rb_compile_option_t *option)
582 VALUE coverage = Qfalse;
583 VALUE err_info = Qnil;
584 struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
586 if (parent && (type == ISEQ_TYPE_MAIN || type == ISEQ_TYPE_TOP))
587 err_info = Qfalse;
589 body->type = type;
590 set_relation(iseq, parent);
592 name = rb_fstring(name);
593 iseq_location_setup(iseq, name, path, realpath, first_lineno, code_location, node_id);
594 if (iseq != body->local_iseq) {
595 RB_OBJ_WRITE(iseq, &body->location.base_label, ISEQ_BODY(body->local_iseq)->location.label);
597 ISEQ_COVERAGE_SET(iseq, Qnil);
598 ISEQ_ORIGINAL_ISEQ_CLEAR(iseq);
599 body->variable.flip_count = 0;
601 if (NIL_P(script_lines)) {
602 RB_OBJ_WRITE(iseq, &body->variable.script_lines, Qnil);
604 else {
605 RB_OBJ_WRITE(iseq, &body->variable.script_lines, rb_ractor_make_shareable(script_lines));
608 ISEQ_COMPILE_DATA_ALLOC(iseq);
609 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err_info);
610 RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, Qnil);
612 ISEQ_COMPILE_DATA(iseq)->node.storage_head = ISEQ_COMPILE_DATA(iseq)->node.storage_current = new_arena();
613 ISEQ_COMPILE_DATA(iseq)->insn.storage_head = ISEQ_COMPILE_DATA(iseq)->insn.storage_current = new_arena();
614 ISEQ_COMPILE_DATA(iseq)->isolated_depth = isolated_depth;
615 ISEQ_COMPILE_DATA(iseq)->option = option;
616 ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = NULL;
617 ISEQ_COMPILE_DATA(iseq)->builtin_function_table = GET_VM()->builtin_function_table;
619 if (option->coverage_enabled) {
620 VALUE coverages = rb_get_coverages();
621 if (RTEST(coverages)) {
622 coverage = rb_hash_lookup(coverages, rb_iseq_path(iseq));
623 if (NIL_P(coverage)) coverage = Qfalse;
626 ISEQ_COVERAGE_SET(iseq, coverage);
627 if (coverage && ISEQ_BRANCH_COVERAGE(iseq))
628 ISEQ_PC2BRANCHINDEX_SET(iseq, rb_ary_hidden_new(0));
630 return Qtrue;
633 #if VM_CHECK_MODE > 0 && VM_INSN_INFO_TABLE_IMPL > 0
634 static void validate_get_insn_info(const rb_iseq_t *iseq);
635 #endif
637 void
638 rb_iseq_insns_info_encode_positions(const rb_iseq_t *iseq)
640 #if VM_INSN_INFO_TABLE_IMPL == 2
641 /* create succ_index_table */
642 struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
643 int size = body->insns_info.size;
644 int max_pos = body->iseq_size;
645 int *data = (int *)body->insns_info.positions;
646 if (body->insns_info.succ_index_table) ruby_xfree(body->insns_info.succ_index_table);
647 body->insns_info.succ_index_table = succ_index_table_create(max_pos, data, size);
648 #if VM_CHECK_MODE == 0
649 ruby_xfree(body->insns_info.positions);
650 body->insns_info.positions = NULL;
651 #endif
652 #endif
655 #if VM_INSN_INFO_TABLE_IMPL == 2
656 unsigned int *
657 rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body)
659 int size = body->insns_info.size;
660 int max_pos = body->iseq_size;
661 struct succ_index_table *sd = body->insns_info.succ_index_table;
662 return succ_index_table_invert(max_pos, sd, size);
664 #endif
666 void
667 rb_iseq_init_trace(rb_iseq_t *iseq)
669 iseq->aux.exec.global_trace_events = 0;
670 if (ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS) {
671 rb_iseq_trace_set(iseq, ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS);
675 static VALUE
676 finish_iseq_build(rb_iseq_t *iseq)
678 struct iseq_compile_data *data = ISEQ_COMPILE_DATA(iseq);
679 const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
680 VALUE err = data->err_info;
681 ISEQ_COMPILE_DATA_CLEAR(iseq);
682 compile_data_free(data);
684 #if VM_CHECK_MODE > 0 && VM_INSN_INFO_TABLE_IMPL > 0
685 validate_get_insn_info(iseq);
686 #endif
688 if (RTEST(err)) {
689 VALUE path = pathobj_path(body->location.pathobj);
690 if (err == Qtrue) err = rb_exc_new_cstr(rb_eSyntaxError, "compile error");
691 rb_funcallv(err, rb_intern("set_backtrace"), 1, &path);
692 rb_exc_raise(err);
695 RB_DEBUG_COUNTER_INC(iseq_num);
696 RB_DEBUG_COUNTER_ADD(iseq_cd_num, ISEQ_BODY(iseq)->ci_size);
698 rb_iseq_init_trace(iseq);
699 return Qtrue;
702 static rb_compile_option_t COMPILE_OPTION_DEFAULT = {
703 OPT_INLINE_CONST_CACHE, /* int inline_const_cache; */
704 OPT_PEEPHOLE_OPTIMIZATION, /* int peephole_optimization; */
705 OPT_TAILCALL_OPTIMIZATION, /* int tailcall_optimization */
706 OPT_SPECIALISED_INSTRUCTION, /* int specialized_instruction; */
707 OPT_OPERANDS_UNIFICATION, /* int operands_unification; */
708 OPT_INSTRUCTIONS_UNIFICATION, /* int instructions_unification; */
709 OPT_STACK_CACHING, /* int stack_caching; */
710 OPT_FROZEN_STRING_LITERAL,
711 OPT_DEBUG_FROZEN_STRING_LITERAL,
712 TRUE, /* coverage_enabled */
715 static const rb_compile_option_t COMPILE_OPTION_FALSE = {0};
717 static void
718 set_compile_option_from_hash(rb_compile_option_t *option, VALUE opt)
720 #define SET_COMPILE_OPTION(o, h, mem) \
721 { VALUE flag = rb_hash_aref((h), ID2SYM(rb_intern(#mem))); \
722 if (flag == Qtrue) { (o)->mem = 1; } \
723 else if (flag == Qfalse) { (o)->mem = 0; } \
725 #define SET_COMPILE_OPTION_NUM(o, h, mem) \
726 { VALUE num = rb_hash_aref(opt, ID2SYM(rb_intern(#mem))); \
727 if (!NIL_P(num)) (o)->mem = NUM2INT(num); \
729 SET_COMPILE_OPTION(option, opt, inline_const_cache);
730 SET_COMPILE_OPTION(option, opt, peephole_optimization);
731 SET_COMPILE_OPTION(option, opt, tailcall_optimization);
732 SET_COMPILE_OPTION(option, opt, specialized_instruction);
733 SET_COMPILE_OPTION(option, opt, operands_unification);
734 SET_COMPILE_OPTION(option, opt, instructions_unification);
735 SET_COMPILE_OPTION(option, opt, stack_caching);
736 SET_COMPILE_OPTION(option, opt, frozen_string_literal);
737 SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal);
738 SET_COMPILE_OPTION(option, opt, coverage_enabled);
739 SET_COMPILE_OPTION_NUM(option, opt, debug_level);
740 #undef SET_COMPILE_OPTION
741 #undef SET_COMPILE_OPTION_NUM
744 static void
745 rb_iseq_make_compile_option(rb_compile_option_t *option, VALUE opt)
747 Check_Type(opt, T_HASH);
748 set_compile_option_from_hash(option, opt);
751 static void
752 make_compile_option(rb_compile_option_t *option, VALUE opt)
754 if (NIL_P(opt)) {
755 *option = COMPILE_OPTION_DEFAULT;
757 else if (opt == Qfalse) {
758 *option = COMPILE_OPTION_FALSE;
760 else if (opt == Qtrue) {
761 int i;
762 for (i = 0; i < (int)(sizeof(rb_compile_option_t) / sizeof(int)); ++i)
763 ((int *)option)[i] = 1;
765 else if (RB_TYPE_P(opt, T_HASH)) {
766 *option = COMPILE_OPTION_DEFAULT;
767 set_compile_option_from_hash(option, opt);
769 else {
770 rb_raise(rb_eTypeError, "Compile option must be Hash/true/false/nil");
774 static VALUE
775 make_compile_option_value(rb_compile_option_t *option)
777 VALUE opt = rb_hash_new_with_size(11);
778 #define SET_COMPILE_OPTION(o, h, mem) \
779 rb_hash_aset((h), ID2SYM(rb_intern(#mem)), RBOOL((o)->mem))
780 #define SET_COMPILE_OPTION_NUM(o, h, mem) \
781 rb_hash_aset((h), ID2SYM(rb_intern(#mem)), INT2NUM((o)->mem))
783 SET_COMPILE_OPTION(option, opt, inline_const_cache);
784 SET_COMPILE_OPTION(option, opt, peephole_optimization);
785 SET_COMPILE_OPTION(option, opt, tailcall_optimization);
786 SET_COMPILE_OPTION(option, opt, specialized_instruction);
787 SET_COMPILE_OPTION(option, opt, operands_unification);
788 SET_COMPILE_OPTION(option, opt, instructions_unification);
789 SET_COMPILE_OPTION(option, opt, stack_caching);
790 SET_COMPILE_OPTION(option, opt, frozen_string_literal);
791 SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal);
792 SET_COMPILE_OPTION(option, opt, coverage_enabled);
793 SET_COMPILE_OPTION_NUM(option, opt, debug_level);
795 #undef SET_COMPILE_OPTION
796 #undef SET_COMPILE_OPTION_NUM
797 return opt;
800 rb_iseq_t *
801 rb_iseq_new(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath,
802 const rb_iseq_t *parent, enum rb_iseq_type type)
804 return rb_iseq_new_with_opt(ast, name, path, realpath, 0, parent,
805 0, type, &COMPILE_OPTION_DEFAULT);
808 static int
809 ast_line_count(const rb_ast_body_t *ast)
811 if (ast->script_lines == Qfalse) {
812 // this occurs when failed to parse the source code with a syntax error
813 return 0;
815 if (RB_TYPE_P(ast->script_lines, T_ARRAY)){
816 return (int)RARRAY_LEN(ast->script_lines);
818 return FIX2INT(ast->script_lines);
821 static VALUE
822 iseq_setup_coverage(VALUE coverages, VALUE path, const rb_ast_body_t *ast, int line_offset)
824 int line_count = line_offset + ast_line_count(ast);
826 if (line_count >= 0) {
827 int len = (rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES) ? 0 : line_count;
829 VALUE coverage = rb_default_coverage(len);
830 rb_hash_aset(coverages, path, coverage);
832 return coverage;
835 return Qnil;
838 static inline void
839 iseq_new_setup_coverage(VALUE path, const rb_ast_body_t *ast, int line_offset)
841 VALUE coverages = rb_get_coverages();
843 if (RTEST(coverages)) {
844 iseq_setup_coverage(coverages, path, ast, line_offset);
848 rb_iseq_t *
849 rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
851 iseq_new_setup_coverage(path, ast, 0);
853 return rb_iseq_new_with_opt(ast, name, path, realpath, 0, parent, 0,
854 ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT);
857 rb_iseq_t *
858 rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt)
860 iseq_new_setup_coverage(path, ast, 0);
862 return rb_iseq_new_with_opt(ast, rb_fstring_lit("<main>"),
863 path, realpath, 0,
864 parent, 0, ISEQ_TYPE_MAIN, opt ? &COMPILE_OPTION_DEFAULT : &COMPILE_OPTION_FALSE);
867 rb_iseq_t *
868 rb_iseq_new_eval(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth)
870 if (rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) {
871 VALUE coverages = rb_get_coverages();
872 if (RTEST(coverages) && RTEST(path) && !RTEST(rb_hash_has_key(coverages, path))) {
873 iseq_setup_coverage(coverages, path, ast, first_lineno - 1);
877 return rb_iseq_new_with_opt(ast, name, path, realpath, first_lineno,
878 parent, isolated_depth, ISEQ_TYPE_EVAL, &COMPILE_OPTION_DEFAULT);
881 static inline rb_iseq_t *
882 iseq_translate(rb_iseq_t *iseq)
884 if (rb_respond_to(rb_cISeq, rb_intern("translate"))) {
885 VALUE v1 = iseqw_new(iseq);
886 VALUE v2 = rb_funcall(rb_cISeq, rb_intern("translate"), 1, v1);
887 if (v1 != v2 && CLASS_OF(v2) == rb_cISeq) {
888 iseq = (rb_iseq_t *)iseqw_check(v2);
892 return iseq;
895 rb_iseq_t *
896 rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath,
897 int first_lineno, const rb_iseq_t *parent, int isolated_depth,
898 enum rb_iseq_type type, const rb_compile_option_t *option)
900 const NODE *node = ast ? ast->root : 0;
901 /* TODO: argument check */
902 rb_iseq_t *iseq = iseq_alloc();
903 rb_compile_option_t new_opt;
905 if (option) {
906 new_opt = *option;
908 else {
909 new_opt = COMPILE_OPTION_DEFAULT;
911 if (ast && ast->compile_option) rb_iseq_make_compile_option(&new_opt, ast->compile_option);
913 VALUE script_lines = Qnil;
915 if (ast && !FIXNUM_P(ast->script_lines) && ast->script_lines) {
916 script_lines = ast->script_lines;
918 else if (parent) {
919 script_lines = ISEQ_BODY(parent)->variable.script_lines;
922 prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, node ? nd_node_id(node) : -1,
923 parent, isolated_depth, type, script_lines, &new_opt);
925 rb_iseq_compile_node(iseq, node);
926 finish_iseq_build(iseq);
928 return iseq_translate(iseq);
931 rb_iseq_t *
932 rb_iseq_new_with_callback(
933 const struct rb_iseq_new_with_callback_callback_func * ifunc,
934 VALUE name, VALUE path, VALUE realpath,
935 int first_lineno, const rb_iseq_t *parent,
936 enum rb_iseq_type type, const rb_compile_option_t *option)
938 /* TODO: argument check */
939 rb_iseq_t *iseq = iseq_alloc();
941 if (!option) option = &COMPILE_OPTION_DEFAULT;
942 prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, 0, type, Qnil, option);
944 rb_iseq_compile_callback(iseq, ifunc);
945 finish_iseq_build(iseq);
947 return iseq;
950 const rb_iseq_t *
951 rb_iseq_load_iseq(VALUE fname)
953 VALUE iseqv = rb_check_funcall(rb_cISeq, rb_intern("load_iseq"), 1, &fname);
955 if (!SPECIAL_CONST_P(iseqv) && RBASIC_CLASS(iseqv) == rb_cISeq) {
956 return iseqw_check(iseqv);
959 return NULL;
962 #define CHECK_ARRAY(v) rb_to_array_type(v)
963 #define CHECK_HASH(v) rb_to_hash_type(v)
964 #define CHECK_STRING(v) rb_str_to_str(v)
965 #define CHECK_SYMBOL(v) rb_to_symbol_type(v)
966 static inline VALUE CHECK_INTEGER(VALUE v) {(void)NUM2LONG(v); return v;}
968 static enum rb_iseq_type
969 iseq_type_from_sym(VALUE type)
971 const ID id_top = rb_intern("top");
972 const ID id_method = rb_intern("method");
973 const ID id_block = rb_intern("block");
974 const ID id_class = rb_intern("class");
975 const ID id_rescue = rb_intern("rescue");
976 const ID id_ensure = rb_intern("ensure");
977 const ID id_eval = rb_intern("eval");
978 const ID id_main = rb_intern("main");
979 const ID id_plain = rb_intern("plain");
980 /* ensure all symbols are static or pinned down before
981 * conversion */
982 const ID typeid = rb_check_id(&type);
983 if (typeid == id_top) return ISEQ_TYPE_TOP;
984 if (typeid == id_method) return ISEQ_TYPE_METHOD;
985 if (typeid == id_block) return ISEQ_TYPE_BLOCK;
986 if (typeid == id_class) return ISEQ_TYPE_CLASS;
987 if (typeid == id_rescue) return ISEQ_TYPE_RESCUE;
988 if (typeid == id_ensure) return ISEQ_TYPE_ENSURE;
989 if (typeid == id_eval) return ISEQ_TYPE_EVAL;
990 if (typeid == id_main) return ISEQ_TYPE_MAIN;
991 if (typeid == id_plain) return ISEQ_TYPE_PLAIN;
992 return (enum rb_iseq_type)-1;
995 static VALUE
996 iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt)
998 rb_iseq_t *iseq = iseq_alloc();
1000 VALUE magic, version1, version2, format_type, misc;
1001 VALUE name, path, realpath, code_location, node_id;
1002 VALUE type, body, locals, params, exception;
1004 st_data_t iseq_type;
1005 rb_compile_option_t option;
1006 int i = 0;
1007 rb_code_location_t tmp_loc = { {0, 0}, {-1, -1} };
1009 /* [magic, major_version, minor_version, format_type, misc,
1010 * label, path, first_lineno,
1011 * type, locals, args, exception_table, body]
1014 data = CHECK_ARRAY(data);
1016 magic = CHECK_STRING(rb_ary_entry(data, i++));
1017 version1 = CHECK_INTEGER(rb_ary_entry(data, i++));
1018 version2 = CHECK_INTEGER(rb_ary_entry(data, i++));
1019 format_type = CHECK_INTEGER(rb_ary_entry(data, i++));
1020 misc = CHECK_HASH(rb_ary_entry(data, i++));
1021 ((void)magic, (void)version1, (void)version2, (void)format_type);
1023 name = CHECK_STRING(rb_ary_entry(data, i++));
1024 path = CHECK_STRING(rb_ary_entry(data, i++));
1025 realpath = rb_ary_entry(data, i++);
1026 realpath = NIL_P(realpath) ? Qnil : CHECK_STRING(realpath);
1027 int first_lineno = RB_NUM2INT(rb_ary_entry(data, i++));
1029 type = CHECK_SYMBOL(rb_ary_entry(data, i++));
1030 locals = CHECK_ARRAY(rb_ary_entry(data, i++));
1031 params = CHECK_HASH(rb_ary_entry(data, i++));
1032 exception = CHECK_ARRAY(rb_ary_entry(data, i++));
1033 body = CHECK_ARRAY(rb_ary_entry(data, i++));
1035 ISEQ_BODY(iseq)->local_iseq = iseq;
1037 iseq_type = iseq_type_from_sym(type);
1038 if (iseq_type == (enum rb_iseq_type)-1) {
1039 rb_raise(rb_eTypeError, "unsupported type: :%"PRIsVALUE, rb_sym2str(type));
1042 node_id = rb_hash_aref(misc, ID2SYM(rb_intern("node_id")));
1044 code_location = rb_hash_aref(misc, ID2SYM(rb_intern("code_location")));
1045 if (RB_TYPE_P(code_location, T_ARRAY) && RARRAY_LEN(code_location) == 4) {
1046 tmp_loc.beg_pos.lineno = NUM2INT(rb_ary_entry(code_location, 0));
1047 tmp_loc.beg_pos.column = NUM2INT(rb_ary_entry(code_location, 1));
1048 tmp_loc.end_pos.lineno = NUM2INT(rb_ary_entry(code_location, 2));
1049 tmp_loc.end_pos.column = NUM2INT(rb_ary_entry(code_location, 3));
1052 make_compile_option(&option, opt);
1053 option.peephole_optimization = FALSE; /* because peephole optimization can modify original iseq */
1054 prepare_iseq_build(iseq, name, path, realpath, first_lineno, &tmp_loc, NUM2INT(node_id),
1055 parent, 0, (enum rb_iseq_type)iseq_type, Qnil, &option);
1057 rb_iseq_build_from_ary(iseq, misc, locals, params, exception, body);
1059 finish_iseq_build(iseq);
1061 return iseqw_new(iseq);
1065 * :nodoc:
1067 static VALUE
1068 iseq_s_load(int argc, VALUE *argv, VALUE self)
1070 VALUE data, opt=Qnil;
1071 rb_scan_args(argc, argv, "11", &data, &opt);
1072 return iseq_load(data, NULL, opt);
1075 VALUE
1076 rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
1078 return iseq_load(data, RTEST(parent) ? (rb_iseq_t *)parent : NULL, opt);
1081 static rb_iseq_t *
1082 rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, VALUE opt)
1084 rb_iseq_t *iseq = NULL;
1085 rb_compile_option_t option;
1086 #if !defined(__GNUC__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 8)
1087 # define INITIALIZED volatile /* suppress warnings by gcc 4.8 */
1088 #else
1089 # define INITIALIZED /* volatile */
1090 #endif
1091 rb_ast_t *(*parse)(VALUE vparser, VALUE fname, VALUE file, int start);
1092 int ln;
1093 rb_ast_t *INITIALIZED ast;
1094 VALUE name = rb_fstring_lit("<compiled>");
1096 /* safe results first */
1097 make_compile_option(&option, opt);
1098 ln = NUM2INT(line);
1099 StringValueCStr(file);
1100 if (RB_TYPE_P(src, T_FILE)) {
1101 parse = rb_parser_compile_file_path;
1103 else {
1104 parse = rb_parser_compile_string_path;
1105 StringValue(src);
1108 const VALUE parser = rb_parser_new();
1109 const rb_iseq_t *outer_scope = rb_iseq_new(NULL, name, name, Qnil, 0, ISEQ_TYPE_TOP);
1110 VALUE outer_scope_v = (VALUE)outer_scope;
1111 rb_parser_set_context(parser, outer_scope, FALSE);
1112 RB_GC_GUARD(outer_scope_v);
1113 ast = (*parse)(parser, file, src, ln);
1116 if (!ast->body.root) {
1117 rb_ast_dispose(ast);
1118 rb_exc_raise(GET_EC()->errinfo);
1120 else {
1121 iseq = rb_iseq_new_with_opt(&ast->body, name, file, realpath, ln,
1122 NULL, 0, ISEQ_TYPE_TOP, &option);
1123 rb_ast_dispose(ast);
1126 return iseq;
1129 VALUE
1130 rb_iseq_path(const rb_iseq_t *iseq)
1132 return pathobj_path(ISEQ_BODY(iseq)->location.pathobj);
1135 VALUE
1136 rb_iseq_realpath(const rb_iseq_t *iseq)
1138 return pathobj_realpath(ISEQ_BODY(iseq)->location.pathobj);
1141 VALUE
1142 rb_iseq_absolute_path(const rb_iseq_t *iseq)
1144 return rb_iseq_realpath(iseq);
1148 rb_iseq_from_eval_p(const rb_iseq_t *iseq)
1150 return NIL_P(rb_iseq_realpath(iseq));
1153 VALUE
1154 rb_iseq_label(const rb_iseq_t *iseq)
1156 return ISEQ_BODY(iseq)->location.label;
1159 VALUE
1160 rb_iseq_base_label(const rb_iseq_t *iseq)
1162 return ISEQ_BODY(iseq)->location.base_label;
1165 VALUE
1166 rb_iseq_first_lineno(const rb_iseq_t *iseq)
1168 return RB_INT2NUM(ISEQ_BODY(iseq)->location.first_lineno);
1171 VALUE
1172 rb_iseq_method_name(const rb_iseq_t *iseq)
1174 struct rb_iseq_constant_body *const body = ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq);
1176 if (body->type == ISEQ_TYPE_METHOD) {
1177 return body->location.base_label;
1179 else {
1180 return Qnil;
1184 void
1185 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)
1187 const rb_code_location_t *loc = &ISEQ_BODY(iseq)->location.code_location;
1188 if (beg_pos_lineno) *beg_pos_lineno = loc->beg_pos.lineno;
1189 if (beg_pos_column) *beg_pos_column = loc->beg_pos.column;
1190 if (end_pos_lineno) *end_pos_lineno = loc->end_pos.lineno;
1191 if (end_pos_column) *end_pos_column = loc->end_pos.column;
1194 static ID iseq_type_id(enum rb_iseq_type type);
1196 VALUE
1197 rb_iseq_type(const rb_iseq_t *iseq)
1199 return ID2SYM(iseq_type_id(ISEQ_BODY(iseq)->type));
1202 VALUE
1203 rb_iseq_coverage(const rb_iseq_t *iseq)
1205 return ISEQ_COVERAGE(iseq);
1208 static int
1209 remove_coverage_i(void *vstart, void *vend, size_t stride, void *data)
1211 VALUE v = (VALUE)vstart;
1212 for (; v != (VALUE)vend; v += stride) {
1213 void *ptr = asan_poisoned_object_p(v);
1214 asan_unpoison_object(v, false);
1216 if (rb_obj_is_iseq(v)) {
1217 rb_iseq_t *iseq = (rb_iseq_t *)v;
1218 ISEQ_COVERAGE_SET(iseq, Qnil);
1221 asan_poison_object_if(ptr, v);
1223 return 0;
1226 void
1227 rb_iseq_remove_coverage_all(void)
1229 rb_objspace_each_objects(remove_coverage_i, NULL);
1232 /* define wrapper class methods (RubyVM::InstructionSequence) */
1234 static void
1235 iseqw_mark(void *ptr)
1237 rb_gc_mark((VALUE)ptr);
1240 static size_t
1241 iseqw_memsize(const void *ptr)
1243 return rb_iseq_memsize((const rb_iseq_t *)ptr);
1246 static const rb_data_type_t iseqw_data_type = {
1247 "T_IMEMO/iseq",
1248 {iseqw_mark, NULL, iseqw_memsize,},
1249 0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
1252 static VALUE
1253 iseqw_new(const rb_iseq_t *iseq)
1255 if (iseq->wrapper) {
1256 return iseq->wrapper;
1258 else {
1259 union { const rb_iseq_t *in; void *out; } deconst;
1260 VALUE obj;
1261 deconst.in = iseq;
1262 obj = TypedData_Wrap_Struct(rb_cISeq, &iseqw_data_type, deconst.out);
1263 RB_OBJ_WRITTEN(obj, Qundef, iseq);
1265 /* cache a wrapper object */
1266 RB_OBJ_WRITE((VALUE)iseq, &iseq->wrapper, obj);
1267 RB_OBJ_FREEZE((VALUE)iseq);
1269 return obj;
1273 VALUE
1274 rb_iseqw_new(const rb_iseq_t *iseq)
1276 return iseqw_new(iseq);
1280 * call-seq:
1281 * InstructionSequence.compile(source[, file[, path[, line[, options]]]]) -> iseq
1282 * InstructionSequence.new(source[, file[, path[, line[, options]]]]) -> iseq
1284 * Takes +source+, a String of Ruby code and compiles it to an
1285 * InstructionSequence.
1287 * Optionally takes +file+, +path+, and +line+ which describe the file path,
1288 * real path and first line number of the ruby code in +source+ which are
1289 * metadata attached to the returned +iseq+.
1291 * +file+ is used for `__FILE__` and exception backtrace. +path+ is used for
1292 * +require_relative+ base. It is recommended these should be the same full
1293 * path.
1295 * +options+, which can be +true+, +false+ or a +Hash+, is used to
1296 * modify the default behavior of the Ruby iseq compiler.
1298 * For details regarding valid compile options see ::compile_option=.
1300 * RubyVM::InstructionSequence.compile("a = 1 + 2")
1301 * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
1303 * path = "test.rb"
1304 * RubyVM::InstructionSequence.compile(File.read(path), path, File.expand_path(path))
1305 * #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1>
1307 * path = File.expand_path("test.rb")
1308 * RubyVM::InstructionSequence.compile(File.read(path), path, path)
1309 * #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
1312 static VALUE
1313 iseqw_s_compile(int argc, VALUE *argv, VALUE self)
1315 VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil;
1316 int i;
1318 i = rb_scan_args(argc, argv, "1*:", &src, NULL, &opt);
1319 if (i > 4+NIL_P(opt)) rb_error_arity(argc, 1, 5);
1320 switch (i) {
1321 case 5: opt = argv[--i];
1322 case 4: line = argv[--i];
1323 case 3: path = argv[--i];
1324 case 2: file = argv[--i];
1327 if (NIL_P(file)) file = rb_fstring_lit("<compiled>");
1328 if (NIL_P(path)) path = file;
1329 if (NIL_P(line)) line = INT2FIX(1);
1331 Check_Type(path, T_STRING);
1332 Check_Type(file, T_STRING);
1334 return iseqw_new(rb_iseq_compile_with_option(src, file, path, line, opt));
1338 * call-seq:
1339 * InstructionSequence.compile_file(file[, options]) -> iseq
1341 * Takes +file+, a String with the location of a Ruby source file, reads,
1342 * parses and compiles the file, and returns +iseq+, the compiled
1343 * InstructionSequence with source location metadata set.
1345 * Optionally takes +options+, which can be +true+, +false+ or a +Hash+, to
1346 * modify the default behavior of the Ruby iseq compiler.
1348 * For details regarding valid compile options see ::compile_option=.
1350 * # /tmp/hello.rb
1351 * puts "Hello, world!"
1353 * # elsewhere
1354 * RubyVM::InstructionSequence.compile_file("/tmp/hello.rb")
1355 * #=> <RubyVM::InstructionSequence:<main>@/tmp/hello.rb>
1357 static VALUE
1358 iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
1360 VALUE file, opt = Qnil;
1361 VALUE parser, f, exc = Qnil, ret;
1362 rb_ast_t *ast;
1363 rb_compile_option_t option;
1364 int i;
1366 i = rb_scan_args(argc, argv, "1*:", &file, NULL, &opt);
1367 if (i > 1+NIL_P(opt)) rb_error_arity(argc, 1, 2);
1368 switch (i) {
1369 case 2: opt = argv[--i];
1371 FilePathValue(file);
1372 file = rb_fstring(file); /* rb_io_t->pathv gets frozen anyways */
1374 f = rb_file_open_str(file, "r");
1376 rb_execution_context_t *ec = GET_EC();
1377 VALUE v = rb_vm_push_frame_fname(ec, file);
1379 parser = rb_parser_new();
1380 rb_parser_set_context(parser, NULL, FALSE);
1381 ast = (rb_ast_t *)rb_parser_load_file(parser, file);
1382 if (!ast->body.root) exc = GET_EC()->errinfo;
1384 rb_io_close(f);
1385 if (!ast->body.root) {
1386 rb_ast_dispose(ast);
1387 rb_exc_raise(exc);
1390 make_compile_option(&option, opt);
1392 ret = iseqw_new(rb_iseq_new_with_opt(&ast->body, rb_fstring_lit("<main>"),
1393 file,
1394 rb_realpath_internal(Qnil, file, 1),
1395 1, NULL, 0, ISEQ_TYPE_TOP, &option));
1396 rb_ast_dispose(ast);
1398 rb_vm_pop_frame(ec);
1399 RB_GC_GUARD(v);
1400 return ret;
1404 * call-seq:
1405 * InstructionSequence.compile_option = options
1407 * Sets the default values for various optimizations in the Ruby iseq
1408 * compiler.
1410 * Possible values for +options+ include +true+, which enables all options,
1411 * +false+ which disables all options, and +nil+ which leaves all options
1412 * unchanged.
1414 * You can also pass a +Hash+ of +options+ that you want to change, any
1415 * options not present in the hash will be left unchanged.
1417 * Possible option names (which are keys in +options+) which can be set to
1418 * +true+ or +false+ include:
1420 * * +:inline_const_cache+
1421 * * +:instructions_unification+
1422 * * +:operands_unification+
1423 * * +:peephole_optimization+
1424 * * +:specialized_instruction+
1425 * * +:stack_caching+
1426 * * +:tailcall_optimization+
1428 * Additionally, +:debug_level+ can be set to an integer.
1430 * These default options can be overwritten for a single run of the iseq
1431 * compiler by passing any of the above values as the +options+ parameter to
1432 * ::new, ::compile and ::compile_file.
1434 static VALUE
1435 iseqw_s_compile_option_set(VALUE self, VALUE opt)
1437 rb_compile_option_t option;
1438 make_compile_option(&option, opt);
1439 COMPILE_OPTION_DEFAULT = option;
1440 return opt;
1444 * call-seq:
1445 * InstructionSequence.compile_option -> options
1447 * Returns a hash of default options used by the Ruby iseq compiler.
1449 * For details, see InstructionSequence.compile_option=.
1451 static VALUE
1452 iseqw_s_compile_option_get(VALUE self)
1454 return make_compile_option_value(&COMPILE_OPTION_DEFAULT);
1457 static const rb_iseq_t *
1458 iseqw_check(VALUE iseqw)
1460 rb_iseq_t *iseq = DATA_PTR(iseqw);
1462 if (!ISEQ_BODY(iseq)) {
1463 rb_ibf_load_iseq_complete(iseq);
1466 if (!ISEQ_BODY(iseq)->location.label) {
1467 rb_raise(rb_eTypeError, "uninitialized InstructionSequence");
1469 return iseq;
1472 const rb_iseq_t *
1473 rb_iseqw_to_iseq(VALUE iseqw)
1475 return iseqw_check(iseqw);
1479 * call-seq:
1480 * iseq.eval -> obj
1482 * Evaluates the instruction sequence and returns the result.
1484 * RubyVM::InstructionSequence.compile("1 + 2").eval #=> 3
1486 static VALUE
1487 iseqw_eval(VALUE self)
1489 return rb_iseq_eval(iseqw_check(self));
1493 * Returns a human-readable string representation of this instruction
1494 * sequence, including the #label and #path.
1496 static VALUE
1497 iseqw_inspect(VALUE self)
1499 const rb_iseq_t *iseq = iseqw_check(self);
1500 const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
1501 VALUE klass = rb_class_name(rb_obj_class(self));
1503 if (!body->location.label) {
1504 return rb_sprintf("#<%"PRIsVALUE": uninitialized>", klass);
1506 else {
1507 return rb_sprintf("<%"PRIsVALUE":%"PRIsVALUE"@%"PRIsVALUE":%d>",
1508 klass,
1509 body->location.label, rb_iseq_path(iseq),
1510 FIX2INT(rb_iseq_first_lineno(iseq)));
1515 * Returns the path of this instruction sequence.
1517 * <code><compiled></code> if the iseq was evaluated from a string.
1519 * For example, using irb:
1521 * iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
1522 * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
1523 * iseq.path
1524 * #=> "<compiled>"
1526 * Using ::compile_file:
1528 * # /tmp/method.rb
1529 * def hello
1530 * puts "hello, world"
1531 * end
1533 * # in irb
1534 * > iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
1535 * > iseq.path #=> /tmp/method.rb
1537 static VALUE
1538 iseqw_path(VALUE self)
1540 return rb_iseq_path(iseqw_check(self));
1544 * Returns the absolute path of this instruction sequence.
1546 * +nil+ if the iseq was evaluated from a string.
1548 * For example, using ::compile_file:
1550 * # /tmp/method.rb
1551 * def hello
1552 * puts "hello, world"
1553 * end
1555 * # in irb
1556 * > iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
1557 * > iseq.absolute_path #=> /tmp/method.rb
1559 static VALUE
1560 iseqw_absolute_path(VALUE self)
1562 return rb_iseq_realpath(iseqw_check(self));
1565 /* Returns the label of this instruction sequence.
1567 * <code><main></code> if it's at the top level, <code><compiled></code> if it
1568 * was evaluated from a string.
1570 * For example, using irb:
1572 * iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
1573 * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
1574 * iseq.label
1575 * #=> "<compiled>"
1577 * Using ::compile_file:
1579 * # /tmp/method.rb
1580 * def hello
1581 * puts "hello, world"
1582 * end
1584 * # in irb
1585 * > iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
1586 * > iseq.label #=> <main>
1588 static VALUE
1589 iseqw_label(VALUE self)
1591 return rb_iseq_label(iseqw_check(self));
1594 /* Returns the base label of this instruction sequence.
1596 * For example, using irb:
1598 * iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
1599 * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
1600 * iseq.base_label
1601 * #=> "<compiled>"
1603 * Using ::compile_file:
1605 * # /tmp/method.rb
1606 * def hello
1607 * puts "hello, world"
1608 * end
1610 * # in irb
1611 * > iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
1612 * > iseq.base_label #=> <main>
1614 static VALUE
1615 iseqw_base_label(VALUE self)
1617 return rb_iseq_base_label(iseqw_check(self));
1620 /* Returns the number of the first source line where the instruction sequence
1621 * was loaded from.
1623 * For example, using irb:
1625 * iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
1626 * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
1627 * iseq.first_lineno
1628 * #=> 1
1630 static VALUE
1631 iseqw_first_lineno(VALUE self)
1633 return rb_iseq_first_lineno(iseqw_check(self));
1636 static VALUE iseq_data_to_ary(const rb_iseq_t *iseq);
1639 * call-seq:
1640 * iseq.to_a -> ary
1642 * Returns an Array with 14 elements representing the instruction sequence
1643 * with the following data:
1645 * [magic]
1646 * A string identifying the data format. <b>Always
1647 * +YARVInstructionSequence/SimpleDataFormat+.</b>
1649 * [major_version]
1650 * The major version of the instruction sequence.
1652 * [minor_version]
1653 * The minor version of the instruction sequence.
1655 * [format_type]
1656 * A number identifying the data format. <b>Always 1</b>.
1658 * [misc]
1659 * A hash containing:
1661 * [+:arg_size+]
1662 * the total number of arguments taken by the method or the block (0 if
1663 * _iseq_ doesn't represent a method or block)
1664 * [+:local_size+]
1665 * the number of local variables + 1
1666 * [+:stack_max+]
1667 * used in calculating the stack depth at which a SystemStackError is
1668 * thrown.
1670 * [#label]
1671 * The name of the context (block, method, class, module, etc.) that this
1672 * instruction sequence belongs to.
1674 * <code><main></code> if it's at the top level, <code><compiled></code> if
1675 * it was evaluated from a string.
1677 * [#path]
1678 * The relative path to the Ruby file where the instruction sequence was
1679 * loaded from.
1681 * <code><compiled></code> if the iseq was evaluated from a string.
1683 * [#absolute_path]
1684 * The absolute path to the Ruby file where the instruction sequence was
1685 * loaded from.
1687 * +nil+ if the iseq was evaluated from a string.
1689 * [#first_lineno]
1690 * The number of the first source line where the instruction sequence was
1691 * loaded from.
1693 * [type]
1694 * The type of the instruction sequence.
1696 * Valid values are +:top+, +:method+, +:block+, +:class+, +:rescue+,
1697 * +:ensure+, +:eval+, +:main+, and +plain+.
1699 * [locals]
1700 * An array containing the names of all arguments and local variables as
1701 * symbols.
1703 * [params]
1704 * An Hash object containing parameter information.
1706 * More info about these values can be found in +vm_core.h+.
1708 * [catch_table]
1709 * A list of exceptions and control flow operators (rescue, next, redo,
1710 * break, etc.).
1712 * [bytecode]
1713 * An array of arrays containing the instruction names and operands that
1714 * make up the body of the instruction sequence.
1716 * Note that this format is MRI specific and version dependent.
1719 static VALUE
1720 iseqw_to_a(VALUE self)
1722 const rb_iseq_t *iseq = iseqw_check(self);
1723 return iseq_data_to_ary(iseq);
1726 #if VM_INSN_INFO_TABLE_IMPL == 1 /* binary search */
1727 static const struct iseq_insn_info_entry *
1728 get_insn_info_binary_search(const rb_iseq_t *iseq, size_t pos)
1730 const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
1731 size_t size = body->insns_info.size;
1732 const struct iseq_insn_info_entry *insns_info = body->insns_info.body;
1733 const unsigned int *positions = body->insns_info.positions;
1734 const int debug = 0;
1736 if (debug) {
1737 printf("size: %"PRIuSIZE"\n", size);
1738 printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
1739 (size_t)0, positions[0], insns_info[0].line_no, pos);
1742 if (size == 0) {
1743 return NULL;
1745 else if (size == 1) {
1746 return &insns_info[0];
1748 else {
1749 size_t l = 1, r = size - 1;
1750 while (l <= r) {
1751 size_t m = l + (r - l) / 2;
1752 if (positions[m] == pos) {
1753 return &insns_info[m];
1755 if (positions[m] < pos) {
1756 l = m + 1;
1758 else {
1759 r = m - 1;
1762 if (l >= size) {
1763 return &insns_info[size-1];
1765 if (positions[l] > pos) {
1766 return &insns_info[l-1];
1768 return &insns_info[l];
1772 static const struct iseq_insn_info_entry *
1773 get_insn_info(const rb_iseq_t *iseq, size_t pos)
1775 return get_insn_info_binary_search(iseq, pos);
1777 #endif
1779 #if VM_INSN_INFO_TABLE_IMPL == 2 /* succinct bitvector */
1780 static const struct iseq_insn_info_entry *
1781 get_insn_info_succinct_bitvector(const rb_iseq_t *iseq, size_t pos)
1783 const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
1784 size_t size = body->insns_info.size;
1785 const struct iseq_insn_info_entry *insns_info = body->insns_info.body;
1786 const int debug = 0;
1788 if (debug) {
1789 #if VM_CHECK_MODE > 0
1790 const unsigned int *positions = body->insns_info.positions;
1791 printf("size: %"PRIuSIZE"\n", size);
1792 printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
1793 (size_t)0, positions[0], insns_info[0].line_no, pos);
1794 #else
1795 printf("size: %"PRIuSIZE"\n", size);
1796 printf("insns_info[%"PRIuSIZE"]: line: %d, pos: %"PRIuSIZE"\n",
1797 (size_t)0, insns_info[0].line_no, pos);
1798 #endif
1801 if (size == 0) {
1802 return NULL;
1804 else if (size == 1) {
1805 return &insns_info[0];
1807 else {
1808 int index;
1809 VM_ASSERT(body->insns_info.succ_index_table != NULL);
1810 index = succ_index_lookup(body->insns_info.succ_index_table, (int)pos);
1811 return &insns_info[index-1];
1815 static const struct iseq_insn_info_entry *
1816 get_insn_info(const rb_iseq_t *iseq, size_t pos)
1818 return get_insn_info_succinct_bitvector(iseq, pos);
1820 #endif
1822 #if VM_CHECK_MODE > 0 || VM_INSN_INFO_TABLE_IMPL == 0
1823 static const struct iseq_insn_info_entry *
1824 get_insn_info_linear_search(const rb_iseq_t *iseq, size_t pos)
1826 const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
1827 size_t i = 0, size = body->insns_info.size;
1828 const struct iseq_insn_info_entry *insns_info = body->insns_info.body;
1829 const unsigned int *positions = body->insns_info.positions;
1830 const int debug = 0;
1832 if (debug) {
1833 printf("size: %"PRIuSIZE"\n", size);
1834 printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
1835 i, positions[i], insns_info[i].line_no, pos);
1838 if (size == 0) {
1839 return NULL;
1841 else if (size == 1) {
1842 return &insns_info[0];
1844 else {
1845 for (i=1; i<size; i++) {
1846 if (debug) printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
1847 i, positions[i], insns_info[i].line_no, pos);
1849 if (positions[i] == pos) {
1850 return &insns_info[i];
1852 if (positions[i] > pos) {
1853 return &insns_info[i-1];
1857 return &insns_info[i-1];
1859 #endif
1861 #if VM_INSN_INFO_TABLE_IMPL == 0 /* linear search */
1862 static const struct iseq_insn_info_entry *
1863 get_insn_info(const rb_iseq_t *iseq, size_t pos)
1865 return get_insn_info_linear_search(iseq, pos);
1867 #endif
1869 #if VM_CHECK_MODE > 0 && VM_INSN_INFO_TABLE_IMPL > 0
1870 static void
1871 validate_get_insn_info(const rb_iseq_t *iseq)
1873 const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
1874 size_t i;
1875 for (i = 0; i < body->iseq_size; i++) {
1876 if (get_insn_info_linear_search(iseq, i) != get_insn_info(iseq, i)) {
1877 rb_bug("validate_get_insn_info: get_insn_info_linear_search(iseq, %"PRIuSIZE") != get_insn_info(iseq, %"PRIuSIZE")", i, i);
1881 #endif
1883 unsigned int
1884 rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
1886 const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos);
1888 if (entry) {
1889 return entry->line_no;
1891 else {
1892 return 0;
1896 #ifdef USE_ISEQ_NODE_ID
1898 rb_iseq_node_id(const rb_iseq_t *iseq, size_t pos)
1900 const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos);
1902 if (entry) {
1903 return entry->node_id;
1905 else {
1906 return 0;
1909 #endif
1911 rb_event_flag_t
1912 rb_iseq_event_flags(const rb_iseq_t *iseq, size_t pos)
1914 const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos);
1915 if (entry) {
1916 return entry->events;
1918 else {
1919 return 0;
1923 void
1924 rb_iseq_clear_event_flags(const rb_iseq_t *iseq, size_t pos, rb_event_flag_t reset)
1926 struct iseq_insn_info_entry *entry = (struct iseq_insn_info_entry *)get_insn_info(iseq, pos);
1927 if (entry) {
1928 entry->events &= ~reset;
1929 if (!(entry->events & iseq->aux.exec.global_trace_events)) {
1930 void rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos);
1931 rb_iseq_trace_flag_cleared(iseq, pos);
1936 static VALUE
1937 local_var_name(const rb_iseq_t *diseq, VALUE level, VALUE op)
1939 VALUE i;
1940 VALUE name;
1941 ID lid;
1942 int idx;
1944 for (i = 0; i < level; i++) {
1945 diseq = ISEQ_BODY(diseq)->parent_iseq;
1947 idx = ISEQ_BODY(diseq)->local_table_size - (int)op - 1;
1948 lid = ISEQ_BODY(diseq)->local_table[idx];
1949 name = rb_id2str(lid);
1950 if (!name) {
1951 name = rb_str_new_cstr("?");
1953 else if (!rb_str_symname_p(name)) {
1954 name = rb_str_inspect(name);
1956 else {
1957 name = rb_str_dup(name);
1959 rb_str_catf(name, "@%d", idx);
1960 return name;
1963 int rb_insn_unified_local_var_level(VALUE);
1964 VALUE rb_dump_literal(VALUE lit);
1966 VALUE
1967 rb_insn_operand_intern(const rb_iseq_t *iseq,
1968 VALUE insn, int op_no, VALUE op,
1969 int len, size_t pos, const VALUE *pnop, VALUE child)
1971 const char *types = insn_op_types(insn);
1972 char type = types[op_no];
1973 VALUE ret = Qundef;
1975 switch (type) {
1976 case TS_OFFSET: /* LONG */
1977 ret = rb_sprintf("%"PRIdVALUE, (VALUE)(pos + len + op));
1978 break;
1980 case TS_NUM: /* ULONG */
1981 if (insn == BIN(defined) && op_no == 0) {
1982 enum defined_type deftype = (enum defined_type)op;
1983 switch (deftype) {
1984 case DEFINED_FUNC:
1985 ret = rb_fstring_lit("func");
1986 break;
1987 case DEFINED_REF:
1988 ret = rb_fstring_lit("ref");
1989 break;
1990 case DEFINED_CONST_FROM:
1991 ret = rb_fstring_lit("constant-from");
1992 break;
1993 default:
1994 ret = rb_iseq_defined_string(deftype);
1995 break;
1997 if (ret) break;
1999 else if (insn == BIN(checktype) && op_no == 0) {
2000 const char *type_str = rb_type_str((enum ruby_value_type)op);
2001 if (type_str) {
2002 ret = rb_str_new_cstr(type_str); break;
2005 ret = rb_sprintf("%"PRIuVALUE, op);
2006 break;
2008 case TS_LINDEX:{
2009 int level;
2010 if (types[op_no+1] == TS_NUM && pnop) {
2011 ret = local_var_name(iseq, *pnop, op - VM_ENV_DATA_SIZE);
2013 else if ((level = rb_insn_unified_local_var_level(insn)) >= 0) {
2014 ret = local_var_name(iseq, (VALUE)level, op - VM_ENV_DATA_SIZE);
2016 else {
2017 ret = rb_inspect(INT2FIX(op));
2019 break;
2021 case TS_ID: /* ID (symbol) */
2022 ret = rb_inspect(ID2SYM(op));
2023 break;
2025 case TS_VALUE: /* VALUE */
2026 op = obj_resurrect(op);
2027 if (insn == BIN(defined) && op_no == 1 && FIXNUM_P(op)) {
2028 /* should be DEFINED_REF */
2029 int type = NUM2INT(op);
2030 if (type) {
2031 if (type & 1) {
2032 ret = rb_sprintf(":$%c", (type >> 1));
2034 else {
2035 ret = rb_sprintf(":$%d", (type >> 1));
2037 break;
2040 ret = rb_dump_literal(op);
2041 if (CLASS_OF(op) == rb_cISeq) {
2042 if (child) {
2043 rb_ary_push(child, op);
2046 break;
2048 case TS_ISEQ: /* iseq */
2050 if (op) {
2051 const rb_iseq_t *iseq = rb_iseq_check((rb_iseq_t *)op);
2052 ret = ISEQ_BODY(iseq)->location.label;
2053 if (child) {
2054 rb_ary_push(child, (VALUE)iseq);
2057 else {
2058 ret = rb_str_new2("nil");
2060 break;
2063 case TS_IC:
2065 ret = rb_sprintf("<ic:%"PRIdPTRDIFF" ", (union iseq_inline_storage_entry *)op - ISEQ_BODY(iseq)->is_entries);
2066 const ID *segments = ((IC)op)->segments;
2067 rb_str_cat2(ret, rb_id2name(*segments++));
2068 while (*segments) {
2069 rb_str_catf(ret, "::%s", rb_id2name(*segments++));
2071 rb_str_cat2(ret, ">");
2073 break;
2074 case TS_IVC:
2075 case TS_ICVARC:
2076 case TS_ISE:
2077 ret = rb_sprintf("<is:%"PRIdPTRDIFF">", (union iseq_inline_storage_entry *)op - ISEQ_BODY(iseq)->is_entries);
2078 break;
2080 case TS_CALLDATA:
2082 struct rb_call_data *cd = (struct rb_call_data *)op;
2083 const struct rb_callinfo *ci = cd->ci;
2084 VALUE ary = rb_ary_new();
2085 ID mid = vm_ci_mid(ci);
2087 if (mid) {
2088 rb_ary_push(ary, rb_sprintf("mid:%"PRIsVALUE, rb_id2str(mid)));
2091 rb_ary_push(ary, rb_sprintf("argc:%d", vm_ci_argc(ci)));
2093 if (vm_ci_flag(ci) & VM_CALL_KWARG) {
2094 const struct rb_callinfo_kwarg *kw_args = vm_ci_kwarg(ci);
2095 VALUE kw_ary = rb_ary_new_from_values(kw_args->keyword_len, kw_args->keywords);
2096 rb_ary_push(ary, rb_sprintf("kw:[%"PRIsVALUE"]", rb_ary_join(kw_ary, rb_str_new2(","))));
2099 if (vm_ci_flag(ci)) {
2100 VALUE flags = rb_ary_new();
2101 # define CALL_FLAG(n) if (vm_ci_flag(ci) & VM_CALL_##n) rb_ary_push(flags, rb_str_new2(#n))
2102 CALL_FLAG(ARGS_SPLAT);
2103 CALL_FLAG(ARGS_BLOCKARG);
2104 CALL_FLAG(FCALL);
2105 CALL_FLAG(VCALL);
2106 CALL_FLAG(ARGS_SIMPLE);
2107 CALL_FLAG(BLOCKISEQ);
2108 CALL_FLAG(TAILCALL);
2109 CALL_FLAG(SUPER);
2110 CALL_FLAG(ZSUPER);
2111 CALL_FLAG(KWARG);
2112 CALL_FLAG(KW_SPLAT);
2113 CALL_FLAG(KW_SPLAT_MUT);
2114 CALL_FLAG(OPT_SEND); /* maybe not reachable */
2115 rb_ary_push(ary, rb_ary_join(flags, rb_str_new2("|")));
2118 ret = rb_sprintf("<calldata!%"PRIsVALUE">", rb_ary_join(ary, rb_str_new2(", ")));
2120 break;
2122 case TS_CDHASH:
2123 ret = rb_str_new2("<cdhash>");
2124 break;
2126 case TS_FUNCPTR:
2128 #ifdef HAVE_DLADDR
2129 Dl_info info;
2130 if (dladdr((void *)op, &info) && info.dli_sname) {
2131 ret = rb_str_new_cstr(info.dli_sname);
2132 break;
2134 #endif
2135 ret = rb_str_new2("<funcptr>");
2137 break;
2139 case TS_BUILTIN:
2141 const struct rb_builtin_function *bf = (const struct rb_builtin_function *)op;
2142 ret = rb_sprintf("<builtin!%s/%d>",
2143 bf->name, bf->argc);