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 
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:
51  break;
52  case T_ARRAY:
54  break;
55  case T_HASH:
57  break;
58  }
59  }
60  return obj;
61 }
62 
63 static void
64 free_arena(struct iseq_compile_data_storage *cur)
65 {
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
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
101 #endif
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
222 {
223  if (iseq->body) {
224  struct rb_iseq_constant_body *body = iseq->body;
225 
228  body->location.label = rb_gc_location(body->location.label);
231  if (body->local_iseq) {
233  }
234  if (body->parent_iseq) {
236  }
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
275 #endif
276  }
277 }
278 
279 static VALUE
280 each_insn_value(void *ctx, VALUE obj)
281 {
283  return obj;
284 }
285 
286 void
288 {
289  RUBY_MARK_ENTER("iseq");
290 
292 
293  if (iseq->body) {
294  const struct rb_iseq_constant_body *const body = iseq->body;
295 
297  rb_iseq_each_value(iseq, each_insn_value, NULL);
298  }
299 
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)) {
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 
335  rb_gc_mark(iseq->aux.loader.obj);
336  }
338  const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq);
339 
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 */
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
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 *
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();
446  return iseq;
447 }
448 
449 VALUE
451 {
452  VALUE pathobj;
455 
456  if (path == realpath ||
457  (!NIL_P(realpath) && rb_str_cmp(path, realpath) == 0)) {
458  pathobj = rb_fstring(path);
459  }
460  else {
463  rb_obj_freeze(pathobj);
464  }
465  return pathobj;
466 }
467 
468 void
470 {
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 {
479 
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 *)
531 
532  new_arena->pos = 0;
533  new_arena->next = 0;
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) {
559  }
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  }
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
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;
603  body->insns_info.succ_index_table = succ_index_table_create(max_pos, data, size);
604 #if VM_CHECK_MODE == 0
606  body->insns_info.positions = NULL;
607 #endif
608 #endif
609 }
610 
611 #if VM_INSN_INFO_TABLE_IMPL == 2
612 unsigned int *
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
624 {
625  iseq->aux.exec.global_trace_events = 0;
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) {
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 
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; */
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 *
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 *
770 {
771  VALUE coverages = rb_get_coverages();
772  if (RTEST(coverages)) {
773  if (ast->line_count >= 0) {
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 *
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 *
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 */
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 *
829  const struct rb_iseq_new_with_callback_callback_func * ifunc,
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 */
836 
837  if (!option) option = &COMPILE_OPTION_DEFAULT;
838  prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, type, option);
839 
841  finish_iseq_build(iseq);
842 
843  return iseq_translate(iseq);
844 }
845 
846 const rb_iseq_t *
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 {
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 
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++);
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)) {
997  }
998  else {
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
1028 {
1029  return pathobj_path(iseq->body->location.pathobj);
1030 }
1031 
1032 VALUE
1034 {
1035  return pathobj_realpath(iseq->body->location.pathobj);
1036 }
1037 
1038 VALUE
1040 {
1041  return rb_iseq_realpath(iseq);
1042 }
1043 
1044 VALUE
1046 {
1047  return iseq->body->location.label;
1048 }
1049 
1050 VALUE
1052 {
1053  return iseq->body->location.base_label;
1054 }
1055 
1056 VALUE
1058 {
1059  return iseq->body->location.first_lineno;
1060 }
1061 
1062 VALUE
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 {
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
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;
1102  }
1103 
1105  }
1106  return 0;
1107 }
1108 
1109 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,},
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);
1147 
1148  /* cache a wrapper object */
1151 
1152  return obj;
1153  }
1154 }
1155 
1156 VALUE
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 
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) {
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 *
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;
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),
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;
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 
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
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);
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)) {
1817  }
1818  else {
1819  name = rb_str_dup(name);
1820  }
1821  rb_str_catf(name, "@%d", idx);
1822  return name;
1823 }
1824 
1826 
1827 VALUE
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,},
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 =
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;
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
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 =
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))));
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 *
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,},
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)));
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")),
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));
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);
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);
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
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;
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;
3081 } insn_data_t;
3082 static insn_data_t insn_data[VM_INSTRUCTION_SIZE/2];
3083 
3084 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);
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
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 
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 
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 {
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
3203 {
3204  struct trace_set_local_events_struct data;
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;) {
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 
3246  int n;
3247 };
3248 
3249 static void
3250 iseq_remove_local_tracepoint_i(const rb_iseq_t *iseq, void *p)
3251 {
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
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
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;) {
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 
3310  }
3311  return 0;
3312 }
3313 
3314 void
3316 {
3317  rb_objspace_each_objects(trace_set_i, &turnon_events);
3318 }
3319 
3320 VALUE
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 {
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 
3419  unsigned int rank;
3420  uint64_t small_block_ranks; /* 9 bits * 7 = 63 bits */
3421  uint64_t bits[512/64];
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 =
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
3542 {
3543  /* declare ::RubyVM::InstructionSequence */
3544  rb_cISeq = rb_define_class_under(rb_cRubyVM, "InstructionSequence", rb_cObject);
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