Ruby  1.9.3p448(2013-06-27revision41675)
iseq.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  iseq.c -
4 
5  $Author: usa $
6  created at: 2006-07-11(Tue) 09:00:03 +0900
7 
8  Copyright (C) 2006 Koichi Sasada
9 
10 **********************************************************************/
11 
12 #include "ruby/ruby.h"
13 #include "internal.h"
14 
15 /* #define RUBY_MARK_FREE_DEBUG 1 */
16 #include "gc.h"
17 #include "vm_core.h"
18 #include "iseq.h"
19 
20 #include "insns.inc"
21 #include "insns_info.inc"
22 
23 #define ISEQ_MAJOR_VERSION 1
24 #define ISEQ_MINOR_VERSION 2
25 
27 
28 #define hidden_obj_p(obj) (!SPECIAL_CONST_P(obj) && !RBASIC(obj)->klass)
29 
30 static inline VALUE
32 {
33  if (hidden_obj_p(obj)) {
34  switch (BUILTIN_TYPE(obj)) {
35  case T_STRING:
36  obj = rb_str_resurrect(obj);
37  break;
38  case T_ARRAY:
39  obj = rb_ary_resurrect(obj);
40  break;
41  }
42  }
43  return obj;
44 }
45 
46 static void
47 compile_data_free(struct iseq_compile_data *compile_data)
48 {
49  if (compile_data) {
50  struct iseq_compile_data_storage *cur, *next;
51  cur = compile_data->storage_head;
52  while (cur) {
53  next = cur->next;
54  ruby_xfree(cur);
55  cur = next;
56  }
57  ruby_xfree(compile_data);
58  }
59 }
60 
61 static void
62 iseq_free(void *ptr)
63 {
64  rb_iseq_t *iseq;
65  RUBY_FREE_ENTER("iseq");
66 
67  if (ptr) {
68  iseq = ptr;
69  if (!iseq->orig) {
70  /* It's possible that strings are freed */
71  if (0) {
72  RUBY_GC_INFO("%s @ %s\n", RSTRING_PTR(iseq->name),
73  RSTRING_PTR(iseq->filename));
74  }
75 
76  if (iseq->iseq != iseq->iseq_encoded) {
78  }
79 
87  }
88  ruby_xfree(ptr);
89  }
90  RUBY_FREE_LEAVE("iseq");
91 }
92 
93 static void
94 iseq_mark(void *ptr)
95 {
96  RUBY_MARK_ENTER("iseq");
97 
98  if (ptr) {
99  rb_iseq_t *iseq = ptr;
100 
101  RUBY_GC_INFO("%s @ %s\n", RSTRING_PTR(iseq->name), RSTRING_PTR(iseq->filename));
109 #if 0
110  RUBY_MARK_UNLESS_NULL((VALUE)iseq->node);
111  RUBY_MARK_UNLESS_NULL(iseq->cached_special_block);
112 #endif
114 
115  if (iseq->compile_data != 0) {
116  struct iseq_compile_data *const compile_data = iseq->compile_data;
117  RUBY_MARK_UNLESS_NULL(compile_data->mark_ary);
118  RUBY_MARK_UNLESS_NULL(compile_data->err_info);
119  RUBY_MARK_UNLESS_NULL(compile_data->catch_table_ary);
120  }
121  }
122  RUBY_MARK_LEAVE("iseq");
123 }
124 
125 static size_t
126 iseq_memsize(const void *ptr)
127 {
128  size_t size = sizeof(rb_iseq_t);
129  const rb_iseq_t *iseq;
130 
131  if (ptr) {
132  iseq = ptr;
133  if (!iseq->orig) {
134  if (iseq->iseq != iseq->iseq_encoded) {
135  size += iseq->iseq_size * sizeof(VALUE);
136  }
137 
138  size += iseq->iseq_size * sizeof(VALUE);
139  size += iseq->insn_info_size * sizeof(struct iseq_insn_info_entry);
140  size += iseq->local_table_size * sizeof(ID);
141  size += iseq->catch_table_size * sizeof(struct iseq_catch_table_entry);
142  size += iseq->arg_opts * sizeof(VALUE);
143  size += iseq->ic_size * sizeof(struct iseq_inline_cache_entry);
144 
145  if (iseq->compile_data) {
146  struct iseq_compile_data_storage *cur;
147 
148  cur = iseq->compile_data->storage_head;
149  while (cur) {
150  size += cur->size + sizeof(struct iseq_compile_data_storage);
151  cur = cur->next;
152  }
153  size += sizeof(struct iseq_compile_data);
154  }
155  }
156  }
157 
158  return size;
159 }
160 
162  "iseq",
163  {
164  iseq_mark,
165  iseq_free,
166  iseq_memsize,
167  },
168 };
169 
170 static VALUE
172 {
173  rb_iseq_t *iseq;
174  return TypedData_Make_Struct(klass, rb_iseq_t, &iseq_data_type, iseq);
175 }
176 
177 static void
178 set_relation(rb_iseq_t *iseq, const VALUE parent)
179 {
180  const VALUE type = iseq->type;
181  rb_thread_t *th = GET_THREAD();
182 
183  /* set class nest stack */
184  if (type == ISEQ_TYPE_TOP) {
185  /* toplevel is private */
187  iseq->cref_stack->nd_visi = NOEX_PRIVATE;
188  if (th->top_wrapper) {
189  NODE *cref = NEW_BLOCK(th->top_wrapper);
190  cref->nd_visi = NOEX_PRIVATE;
191  cref->nd_next = iseq->cref_stack;
192  iseq->cref_stack = cref;
193  }
194  }
195  else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
196  iseq->cref_stack = NEW_BLOCK(0); /* place holder */
197  }
198  else if (RTEST(parent)) {
199  rb_iseq_t *piseq;
200  GetISeqPtr(parent, piseq);
201  iseq->cref_stack = piseq->cref_stack;
202  }
203 
204  if (type == ISEQ_TYPE_TOP ||
205  type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
206  iseq->local_iseq = iseq;
207  }
208  else if (RTEST(parent)) {
209  rb_iseq_t *piseq;
210  GetISeqPtr(parent, piseq);
211  iseq->local_iseq = piseq->local_iseq;
212  }
213 
214  if (RTEST(parent)) {
215  rb_iseq_t *piseq;
216  GetISeqPtr(parent, piseq);
217  iseq->parent_iseq = piseq;
218  }
219 
220  if (type == ISEQ_TYPE_MAIN) {
221  iseq->local_iseq = iseq;
222  }
223 }
224 
225 static VALUE
227  VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
228  VALUE parent, enum iseq_type type, VALUE block_opt,
230 {
231  OBJ_FREEZE(name);
232  OBJ_FREEZE(filename);
233 
234  iseq->name = name;
235  iseq->filename = filename;
236  iseq->filepath = filepath;
237  iseq->line_no = (unsigned short)line_no; /* TODO: really enough? */
238  iseq->defined_method_id = 0;
239  iseq->mark_ary = rb_ary_tmp_new(3);
240  OBJ_UNTRUST(iseq->mark_ary);
241  RBASIC(iseq->mark_ary)->klass = 0;
242 
243  iseq->type = type;
244  iseq->arg_rest = -1;
245  iseq->arg_block = -1;
246  iseq->klass = 0;
247 
248  /*
249  * iseq->special_block_builder = GC_GUARDED_PTR_REF(block_opt);
250  * iseq->cached_special_block_builder = 0;
251  * iseq->cached_special_block = 0;
252  */
253 
254  iseq->compile_data = ALLOC(struct iseq_compile_data);
255  MEMZERO(iseq->compile_data, struct iseq_compile_data, 1);
256  iseq->compile_data->err_info = Qnil;
258 
260  (struct iseq_compile_data_storage *)
262  sizeof(struct iseq_compile_data_storage));
263 
265  iseq->compile_data->storage_head->pos = 0;
266  iseq->compile_data->storage_head->next = 0;
267  iseq->compile_data->storage_head->size =
269  iseq->compile_data->storage_head->buff =
270  (char *)(&iseq->compile_data->storage_head->buff + 1);
271  iseq->compile_data->option = option;
272  iseq->compile_data->last_coverable_line = -1;
273 
274  set_relation(iseq, parent);
275 
276  iseq->coverage = Qfalse;
277  if (!GET_THREAD()->parse_in_eval) {
278  VALUE coverages = rb_get_coverages();
279  if (RTEST(coverages)) {
280  iseq->coverage = rb_hash_lookup(coverages, filename);
281  if (NIL_P(iseq->coverage)) iseq->coverage = Qfalse;
282  }
283  }
284 
285  return Qtrue;
286 }
287 
288 static VALUE
290 {
291  struct iseq_compile_data *data = iseq->compile_data;
292  VALUE err = data->err_info;
293  iseq->compile_data = 0;
294  compile_data_free(data);
295 
296  if (RTEST(err)) {
297  rb_funcall2(err, rb_intern("set_backtrace"), 1, &iseq->filename);
298  rb_exc_raise(err);
299  }
300  return Qtrue;
301 }
302 
304  OPT_INLINE_CONST_CACHE, /* int inline_const_cache; */
305  OPT_PEEPHOLE_OPTIMIZATION, /* int peephole_optimization; */
306  OPT_TAILCALL_OPTIMIZATION, /* int tailcall_optimization */
307  OPT_SPECIALISED_INSTRUCTION, /* int specialized_instruction; */
308  OPT_OPERANDS_UNIFICATION, /* int operands_unification; */
309  OPT_INSTRUCTIONS_UNIFICATION, /* int instructions_unification; */
310  OPT_STACK_CACHING, /* int stack_caching; */
311  OPT_TRACE_INSTRUCTION, /* int trace_instruction */
312 };
314 
315 static void
317 {
318  if (opt == Qnil) {
319  *option = COMPILE_OPTION_DEFAULT;
320  }
321  else if (opt == Qfalse) {
322  *option = COMPILE_OPTION_FALSE;
323  }
324  else if (opt == Qtrue) {
325  memset(option, 1, sizeof(rb_compile_option_t));
326  }
327  else if (CLASS_OF(opt) == rb_cHash) {
328  *option = COMPILE_OPTION_DEFAULT;
329 
330 #define SET_COMPILE_OPTION(o, h, mem) \
331  { VALUE flag = rb_hash_aref((h), ID2SYM(rb_intern(#mem))); \
332  if (flag == Qtrue) { (o)->mem = 1; } \
333  else if (flag == Qfalse) { (o)->mem = 0; } \
334  }
335 #define SET_COMPILE_OPTION_NUM(o, h, mem) \
336  { VALUE num = rb_hash_aref(opt, ID2SYM(rb_intern(#mem))); \
337  if (!NIL_P(num)) (o)->mem = NUM2INT(num); \
338  }
339  SET_COMPILE_OPTION(option, opt, inline_const_cache);
340  SET_COMPILE_OPTION(option, opt, peephole_optimization);
341  SET_COMPILE_OPTION(option, opt, tailcall_optimization);
342  SET_COMPILE_OPTION(option, opt, specialized_instruction);
343  SET_COMPILE_OPTION(option, opt, operands_unification);
344  SET_COMPILE_OPTION(option, opt, instructions_unification);
345  SET_COMPILE_OPTION(option, opt, stack_caching);
346  SET_COMPILE_OPTION(option, opt, trace_instruction);
347  SET_COMPILE_OPTION_NUM(option, opt, debug_level);
348 #undef SET_COMPILE_OPTION
349 #undef SET_COMPILE_OPTION_NUM
350  }
351  else {
352  rb_raise(rb_eTypeError, "Compile option must be Hash/true/false/nil");
353  }
354 }
355 
356 static VALUE
358 {
359  VALUE opt = rb_hash_new();
360 #define SET_COMPILE_OPTION(o, h, mem) \
361  rb_hash_aset((h), ID2SYM(rb_intern(#mem)), (o)->mem ? Qtrue : Qfalse)
362 #define SET_COMPILE_OPTION_NUM(o, h, mem) \
363  rb_hash_aset((h), ID2SYM(rb_intern(#mem)), INT2NUM((o)->mem))
364  {
365  SET_COMPILE_OPTION(option, opt, inline_const_cache);
366  SET_COMPILE_OPTION(option, opt, peephole_optimization);
367  SET_COMPILE_OPTION(option, opt, tailcall_optimization);
368  SET_COMPILE_OPTION(option, opt, specialized_instruction);
369  SET_COMPILE_OPTION(option, opt, operands_unification);
370  SET_COMPILE_OPTION(option, opt, instructions_unification);
371  SET_COMPILE_OPTION(option, opt, stack_caching);
372  SET_COMPILE_OPTION_NUM(option, opt, debug_level);
373  }
374 #undef SET_COMPILE_OPTION
375 #undef SET_COMPILE_OPTION_NUM
376  return opt;
377 }
378 
379 VALUE
380 rb_iseq_new(NODE *node, VALUE name, VALUE filename, VALUE filepath,
381  VALUE parent, enum iseq_type type)
382 {
383  return rb_iseq_new_with_opt(node, name, filename, filepath, INT2FIX(0), parent, type,
384  &COMPILE_OPTION_DEFAULT);
385 }
386 
387 VALUE
388 rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE parent)
389 {
390  return rb_iseq_new_with_opt(node, name, filename, filepath, INT2FIX(0), parent, ISEQ_TYPE_TOP,
391  &COMPILE_OPTION_DEFAULT);
392 }
393 
394 VALUE
395 rb_iseq_new_main(NODE *node, VALUE filename, VALUE filepath)
396 {
397  rb_thread_t *th = GET_THREAD();
398  VALUE parent = th->base_block->iseq->self;
399  return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), filename, filepath, INT2FIX(0),
400  parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT);
401 }
402 
403 static VALUE
404 rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
405  VALUE parent, enum iseq_type type, VALUE bopt,
407 {
408  rb_iseq_t *iseq;
409  VALUE self = iseq_alloc(rb_cISeq);
410 
411  GetISeqPtr(self, iseq);
412  iseq->self = self;
413 
414  prepare_iseq_build(iseq, name, filename, filepath, line_no, parent, type, bopt, option);
415  rb_iseq_compile_node(self, node);
416  cleanup_iseq_build(iseq);
417  return self;
418 }
419 
420 VALUE
421 rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
422  VALUE parent, enum iseq_type type,
424 {
425  /* TODO: argument check */
426  return rb_iseq_new_with_bopt_and_opt(node, name, filename, filepath, line_no, parent, type,
427  Qfalse, option);
428 }
429 
430 VALUE
431 rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
432  VALUE parent, enum iseq_type type, VALUE bopt)
433 {
434  /* TODO: argument check */
435  return rb_iseq_new_with_bopt_and_opt(node, name, filename, filepath, line_no, parent, type,
436  bopt, &COMPILE_OPTION_DEFAULT);
437 }
438 
439 #define CHECK_ARRAY(v) rb_convert_type((v), T_ARRAY, "Array", "to_ary")
440 #define CHECK_STRING(v) rb_convert_type((v), T_STRING, "String", "to_str")
441 #define CHECK_SYMBOL(v) rb_convert_type((v), T_SYMBOL, "Symbol", "to_sym")
442 static inline VALUE CHECK_INTEGER(VALUE v) {(void)NUM2LONG(v); return v;}
443 static VALUE
444 iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
445 {
446  VALUE iseqval = iseq_alloc(self);
447 
448  VALUE magic, version1, version2, format_type, misc;
449  VALUE name, filename, filepath, line_no;
450  VALUE type, body, locals, args, exception;
451 
452  st_data_t iseq_type;
453  struct st_table *type_map = 0;
454  rb_iseq_t *iseq;
455  rb_compile_option_t option;
456  int i = 0;
457 
458  /* [magic, major_version, minor_version, format_type, misc,
459  * name, filename, line_no,
460  * type, locals, args, exception_table, body]
461  */
462 
463  data = CHECK_ARRAY(data);
464 
465  magic = CHECK_STRING(rb_ary_entry(data, i++));
466  version1 = CHECK_INTEGER(rb_ary_entry(data, i++));
467  version2 = CHECK_INTEGER(rb_ary_entry(data, i++));
468  format_type = CHECK_INTEGER(rb_ary_entry(data, i++));
469  misc = rb_ary_entry(data, i++); /* TODO */
470 
471  name = CHECK_STRING(rb_ary_entry(data, i++));
472  filename = CHECK_STRING(rb_ary_entry(data, i++));
473  filepath = rb_ary_entry(data, i++);
474  filepath = NIL_P(filepath) ? Qnil : CHECK_STRING(filepath);
475  line_no = CHECK_INTEGER(rb_ary_entry(data, i++));
476 
477  type = CHECK_SYMBOL(rb_ary_entry(data, i++));
478  locals = CHECK_ARRAY(rb_ary_entry(data, i++));
479 
480  args = rb_ary_entry(data, i++);
481  if (FIXNUM_P(args) || (args = CHECK_ARRAY(args))) {
482  /* */
483  }
484 
485  exception = CHECK_ARRAY(rb_ary_entry(data, i++));
486  body = CHECK_ARRAY(rb_ary_entry(data, i++));
487 
488  GetISeqPtr(iseqval, iseq);
489  iseq->self = iseqval;
490 
491  if (type_map == 0) {
492  type_map = st_init_numtable();
493  st_insert(type_map, ID2SYM(rb_intern("top")), ISEQ_TYPE_TOP);
494  st_insert(type_map, ID2SYM(rb_intern("method")), ISEQ_TYPE_METHOD);
495  st_insert(type_map, ID2SYM(rb_intern("block")), ISEQ_TYPE_BLOCK);
496  st_insert(type_map, ID2SYM(rb_intern("class")), ISEQ_TYPE_CLASS);
497  st_insert(type_map, ID2SYM(rb_intern("rescue")), ISEQ_TYPE_RESCUE);
498  st_insert(type_map, ID2SYM(rb_intern("ensure")), ISEQ_TYPE_ENSURE);
499  st_insert(type_map, ID2SYM(rb_intern("eval")), ISEQ_TYPE_EVAL);
500  st_insert(type_map, ID2SYM(rb_intern("main")), ISEQ_TYPE_MAIN);
501  st_insert(type_map, ID2SYM(rb_intern("defined_guard")), ISEQ_TYPE_DEFINED_GUARD);
502  }
503 
504  if (st_lookup(type_map, type, &iseq_type) == 0) {
505  const char *typename = rb_id2name(type);
506  if (typename)
507  rb_raise(rb_eTypeError, "unsupport type: :%s", typename);
508  else
509  rb_raise(rb_eTypeError, "unsupport type: %p", (void *)type);
510  }
511 
512  if (parent == Qnil) {
513  parent = 0;
514  }
515 
516  make_compile_option(&option, opt);
517  prepare_iseq_build(iseq, name, filename, filepath, line_no,
518  parent, (enum iseq_type)iseq_type, 0, &option);
519 
520  rb_iseq_build_from_ary(iseq, locals, args, exception, body);
521 
522  cleanup_iseq_build(iseq);
523  return iseqval;
524 }
525 
526 static VALUE
528 {
529  VALUE data, opt=Qnil;
530  rb_scan_args(argc, argv, "11", &data, &opt);
531 
532  return iseq_load(self, data, 0, opt);
533 }
534 
535 VALUE
536 rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
537 {
538  return iseq_load(rb_cISeq, data, parent, opt);
539 }
540 
541 static NODE *
542 parse_string(VALUE str, const char *file, int line)
543 {
544  VALUE parser = rb_parser_new();
545  NODE *node = rb_parser_compile_string(parser, file, str, line);
546 
547  if (!node) {
548  rb_exc_raise(GET_THREAD()->errinfo); /* TODO: check err */
549  }
550  return node;
551 }
552 
553 VALUE
554 rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE filepath, VALUE line, VALUE opt)
555 {
556  rb_compile_option_t option;
557  const char *fn = StringValueCStr(file);
558  int ln = NUM2INT(line);
559  NODE *node = parse_string(StringValue(src), fn, ln);
560  rb_thread_t *th = GET_THREAD();
561  make_compile_option(&option, opt);
562 
563  if (th->base_block && th->base_block->iseq) {
564  return rb_iseq_new_with_opt(node, th->base_block->iseq->name,
565  file, filepath, line, th->base_block->iseq->self,
566  ISEQ_TYPE_EVAL, &option);
567  }
568  else {
569  return rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file, filepath, line, Qfalse,
570  ISEQ_TYPE_TOP, &option);
571  }
572 }
573 
574 VALUE
576 {
577  return rb_iseq_compile_with_option(src, file, Qnil, line, Qnil);
578 }
579 
580 static VALUE
582 {
583  VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil;
584 
585  rb_secure(1);
586 
587  rb_scan_args(argc, argv, "14", &src, &file, &path, &line, &opt);
588  if (NIL_P(file)) file = rb_str_new2("<compiled>");
589  if (NIL_P(line)) line = INT2FIX(1);
590 
591  return rb_iseq_compile_with_option(src, file, path, line, opt);
592 }
593 
594 static VALUE
596 {
597  VALUE file, line = INT2FIX(1), opt = Qnil;
598  VALUE parser;
599  VALUE f;
600  NODE *node;
601  const char *fname;
602  rb_compile_option_t option;
603 
604  rb_secure(1);
605  rb_scan_args(argc, argv, "11", &file, &opt);
606  FilePathValue(file);
607  fname = StringValueCStr(file);
608 
609  f = rb_file_open_str(file, "r");
610 
611  parser = rb_parser_new();
612  node = rb_parser_compile_file(parser, fname, f, NUM2INT(line));
613  make_compile_option(&option, opt);
614  return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file,
615  rb_realpath_internal(Qnil, file, 1), line, Qfalse,
616  ISEQ_TYPE_TOP, &option);
617 }
618 
619 static VALUE
621 {
622  rb_compile_option_t option;
623  rb_secure(1);
624  make_compile_option(&option, opt);
625  COMPILE_OPTION_DEFAULT = option;
626  return opt;
627 }
628 
629 static VALUE
631 {
632  return make_compile_option_value(&COMPILE_OPTION_DEFAULT);
633 }
634 
635 static rb_iseq_t *
637 {
638  rb_iseq_t *iseq;
639  GetISeqPtr(val, iseq);
640  if (!iseq->name) {
641  rb_raise(rb_eTypeError, "uninitialized InstructionSequence");
642  }
643  return iseq;
644 }
645 
646 static VALUE
648 {
649  rb_secure(1);
650  return rb_iseq_eval(self);
651 }
652 
653 static VALUE
655 {
656  rb_iseq_t *iseq;
657  GetISeqPtr(self, iseq);
658  if (!iseq->name) {
659  return rb_sprintf("#<%s: uninitialized>", rb_obj_classname(self));
660  }
661 
662  return rb_sprintf("<%s:%s@%s>",
663  rb_obj_classname(self),
664  RSTRING_PTR(iseq->name), RSTRING_PTR(iseq->filename));
665 }
666 
667 static
669 
670 static VALUE
672 {
673  rb_iseq_t *iseq = iseq_check(self);
674  rb_secure(1);
675  return iseq_data_to_ary(iseq);
676 }
677 
678 int
680 {
681  return FIX2INT(iseq->line_no);
682 }
683 
684 /* TODO: search algorithm is brute force.
685  this should be binary search or so. */
686 
687 static struct iseq_insn_info_entry *
688 get_insn_info(const rb_iseq_t *iseq, const unsigned long pos)
689 {
690  unsigned long i, size = iseq->insn_info_size;
691  struct iseq_insn_info_entry *table = iseq->insn_info_table;
692 
693  for (i = 0; i < size; i++) {
694  if (table[i].position == pos) {
695  return &table[i];
696  }
697  }
698 
699  return 0;
700 }
701 
702 static unsigned short
703 find_line_no(rb_iseq_t *iseq, unsigned long pos)
704 {
705  struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos);
706  if (entry) {
707  return entry->line_no;
708  }
709  else {
710  return 0;
711  }
712 }
713 
714 static unsigned short
715 find_prev_line_no(rb_iseq_t *iseqdat, unsigned long pos)
716 {
717  unsigned long i, size = iseqdat->insn_info_size;
718  struct iseq_insn_info_entry *iiary = iseqdat->insn_info_table;
719 
720  for (i = 0; i < size; i++) {
721  if (iiary[i].position == pos) {
722  if (i > 0) {
723  return iiary[i - 1].line_no;
724  }
725  else {
726  return 0;
727  }
728  }
729  }
730 
731  return 0;
732 }
733 
734 static VALUE
736  VALUE insn, int op_no, VALUE op,
737  int len, size_t pos, VALUE *pnop, VALUE child)
738 {
739  const char *types = insn_op_types(insn);
740  char type = types[op_no];
741  VALUE ret;
742 
743  switch (type) {
744  case TS_OFFSET: /* LONG */
745  ret = rb_sprintf("%"PRIdVALUE, (VALUE)(pos + len + op));
746  break;
747 
748  case TS_NUM: /* ULONG */
749  ret = rb_sprintf("%"PRIuVALUE, op);
750  break;
751 
752  case TS_LINDEX:
753  {
754  rb_iseq_t *liseq = iseq->local_iseq;
755  int lidx = liseq->local_size - (int)op;
756  const char *name = rb_id2name(liseq->local_table[lidx]);
757 
758  if (name) {
759  ret = rb_str_new2(name);
760  }
761  else {
762  ret = rb_str_new2("*");
763  }
764  break;
765  }
766  case TS_DINDEX:{
767  if (insn == BIN(getdynamic) || insn == BIN(setdynamic)) {
768  rb_iseq_t *diseq = iseq;
769  VALUE level = *pnop, i;
770  const char *name;
771  for (i = 0; i < level; i++) {
772  diseq = diseq->parent_iseq;
773  }
774  name = rb_id2name(diseq->local_table[diseq->local_size - op]);
775 
776  if (!name) {
777  name = "*";
778  }
779  ret = rb_str_new2(name);
780  }
781  else {
782  ret = rb_inspect(INT2FIX(op));
783  }
784  break;
785  }
786  case TS_ID: /* ID (symbol) */
787  op = ID2SYM(op);
788 
789  case TS_VALUE: /* VALUE */
790  op = obj_resurrect(op);
791  ret = rb_inspect(op);
792  if (CLASS_OF(op) == rb_cISeq) {
793  rb_ary_push(child, op);
794  }
795  break;
796 
797  case TS_ISEQ: /* iseq */
798  {
799  rb_iseq_t *iseq = (rb_iseq_t *)op;
800  if (iseq) {
801  ret = iseq->name;
802  if (child) {
803  rb_ary_push(child, iseq->self);
804  }
805  }
806  else {
807  ret = rb_str_new2("nil");
808  }
809  break;
810  }
811  case TS_GENTRY:
812  {
813  struct rb_global_entry *entry = (struct rb_global_entry *)op;
814  ret = rb_str_dup(rb_id2str(entry->id));
815  }
816  break;
817 
818  case TS_IC:
819  ret = rb_sprintf("<ic:%"PRIdPTRDIFF">", (struct iseq_inline_cache_entry *)op - iseq->ic_entries);
820  break;
821 
822  case TS_CDHASH:
823  ret = rb_str_new2("<cdhash>");
824  break;
825 
826  case TS_FUNCPTR:
827  ret = rb_str_new2("<funcptr>");
828  break;
829 
830  default:
831  rb_bug("rb_iseq_disasm: unknown operand type: %c", type);
832  }
833  return ret;
834 }
835 
840 int
841 rb_iseq_disasm_insn(VALUE ret, VALUE *iseq, size_t pos,
842  rb_iseq_t *iseqdat, VALUE child)
843 {
844  VALUE insn = iseq[pos];
845  int len = insn_len(insn);
846  int j;
847  const char *types = insn_op_types(insn);
848  VALUE str = rb_str_new(0, 0);
849  const char *insn_name_buff;
850 
851  insn_name_buff = insn_name(insn);
852  if (1) {
853  rb_str_catf(str, "%04"PRIdSIZE" %-16s ", pos, insn_name_buff);
854  }
855  else {
856  rb_str_catf(str, "%04"PRIdSIZE" %-16.*s ", pos,
857  (int)strcspn(insn_name_buff, "_"), insn_name_buff);
858  }
859 
860  for (j = 0; types[j]; j++) {
861  const char *types = insn_op_types(insn);
862  VALUE opstr = insn_operand_intern(iseqdat, insn, j, iseq[pos + j + 1],
863  len, pos, &iseq[pos + j + 2],
864  child);
865  rb_str_concat(str, opstr);
866 
867  if (types[j + 1]) {
868  rb_str_cat2(str, ", ");
869  }
870  }
871 
872  if (1) {
873  int line_no = find_line_no(iseqdat, pos);
874  int prev = find_prev_line_no(iseqdat, pos);
875  if (line_no && line_no != prev) {
876  long slen = RSTRING_LEN(str);
877  slen = (slen > 70) ? 0 : (70 - slen);
878  str = rb_str_catf(str, "%*s(%4d)", (int)slen, "", line_no);
879  }
880  }
881  else {
882  /* for debug */
883  struct iseq_insn_info_entry *entry = get_insn_info(iseqdat, pos);
884  long slen = RSTRING_LEN(str);
885  slen = (slen > 60) ? 0 : (60 - slen);
886  str = rb_str_catf(str, "%*s(line: %d, sp: %d)",
887  (int)slen, "", entry->line_no, entry->sp);
888  }
889 
890  if (ret) {
891  rb_str_cat2(str, "\n");
892  rb_str_concat(ret, str);
893  }
894  else {
895  printf("%s\n", RSTRING_PTR(str));
896  }
897  return len;
898 }
899 
900 static const char *
902 {
903  switch (type) {
904  case CATCH_TYPE_RESCUE:
905  return "rescue";
906  case CATCH_TYPE_ENSURE:
907  return "ensure";
908  case CATCH_TYPE_RETRY:
909  return "retry";
910  case CATCH_TYPE_BREAK:
911  return "break";
912  case CATCH_TYPE_REDO:
913  return "redo";
914  case CATCH_TYPE_NEXT:
915  return "next";
916  default:
917  rb_bug("unknown catch type (%d)", type);
918  return 0;
919  }
920 }
921 
922 VALUE
924 {
925  rb_iseq_t *iseqdat = iseq_check(self);
926  VALUE *iseq;
927  VALUE str = rb_str_new(0, 0);
928  VALUE child = rb_ary_new();
929  unsigned long size;
930  int i;
931  long l;
932  ID *tbl;
933  size_t n;
934  enum {header_minlen = 72};
935 
936  rb_secure(1);
937 
938  iseq = iseqdat->iseq;
939  size = iseqdat->iseq_size;
940 
941  rb_str_cat2(str, "== disasm: ");
942 
943  rb_str_concat(str, iseq_inspect(iseqdat->self));
944  if ((l = RSTRING_LEN(str)) < header_minlen) {
945  rb_str_resize(str, header_minlen);
946  memset(RSTRING_PTR(str) + l, '=', header_minlen - l);
947  }
948  rb_str_cat2(str, "\n");
949 
950  /* show catch table information */
951  if (iseqdat->catch_table_size != 0) {
952  rb_str_cat2(str, "== catch table\n");
953  }
954  for (i = 0; i < iseqdat->catch_table_size; i++) {
955  struct iseq_catch_table_entry *entry = &iseqdat->catch_table[i];
956  rb_str_catf(str,
957  "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
958  catch_type((int)entry->type), (int)entry->start,
959  (int)entry->end, (int)entry->sp, (int)entry->cont);
960  if (entry->iseq) {
961  rb_str_concat(str, rb_iseq_disasm(entry->iseq));
962  }
963  }
964  if (iseqdat->catch_table_size != 0) {
965  rb_str_cat2(str, "|-------------------------------------"
966  "-----------------------------------\n");
967  }
968 
969  /* show local table information */
970  tbl = iseqdat->local_table;
971 
972  if (tbl) {
973  rb_str_catf(str,
974  "local table (size: %d, argc: %d "
975  "[opts: %d, rest: %d, post: %d, block: %d] s%d)\n",
976  iseqdat->local_size, iseqdat->argc,
977  iseqdat->arg_opts, iseqdat->arg_rest,
978  iseqdat->arg_post_len, iseqdat->arg_block,
979  iseqdat->arg_simple);
980 
981  for (i = 0; i < iseqdat->local_table_size; i++) {
982  const char *name = rb_id2name(tbl[i]);
983  char info[0x100];
984  char argi[0x100] = "";
985  char opti[0x100] = "";
986 
987  if (iseqdat->arg_opts) {
988  int argc = iseqdat->argc;
989  int opts = iseqdat->arg_opts;
990  if (i >= argc && i < argc + opts - 1) {
991  snprintf(opti, sizeof(opti), "Opt=%"PRIdVALUE,
992  iseqdat->arg_opt_table[i - argc]);
993  }
994  }
995 
996  snprintf(argi, sizeof(argi), "%s%s%s%s%s", /* arg, opts, rest, post block */
997  iseqdat->argc > i ? "Arg" : "",
998  opti,
999  iseqdat->arg_rest == i ? "Rest" : "",
1000  (iseqdat->arg_post_start <= i &&
1001  i < iseqdat->arg_post_start + iseqdat->arg_post_len) ? "Post" : "",
1002  iseqdat->arg_block == i ? "Block" : "");
1003 
1004  snprintf(info, sizeof(info), "%s%s%s%s", name ? name : "?",
1005  *argi ? "<" : "", argi, *argi ? ">" : "");
1006 
1007  rb_str_catf(str, "[%2d] %-11s", iseqdat->local_size - i, info);
1008  }
1009  rb_str_cat2(str, "\n");
1010  }
1011 
1012  /* show each line */
1013  for (n = 0; n < size;) {
1014  n += rb_iseq_disasm_insn(str, iseq, n, iseqdat, child);
1015  }
1016 
1017  for (i = 0; i < RARRAY_LEN(child); i++) {
1018  VALUE isv = rb_ary_entry(child, i);
1019  rb_str_concat(str, rb_iseq_disasm(isv));
1020  }
1021 
1022  return str;
1023 }
1024 
1025 static VALUE
1027 {
1028  VALUE ret = Qnil;
1029  rb_iseq_t *iseq;
1030 
1031  rb_secure(1);
1032 
1033  if (rb_obj_is_proc(body)) {
1034  rb_proc_t *proc;
1035  GetProcPtr(body, proc);
1036  iseq = proc->block.iseq;
1037  if (RUBY_VM_NORMAL_ISEQ_P(iseq)) {
1038  ret = rb_iseq_disasm(iseq->self);
1039  }
1040  }
1041  else if ((iseq = rb_method_get_iseq(body)) != 0) {
1042  ret = rb_iseq_disasm(iseq->self);
1043  }
1044 
1045  return ret;
1046 }
1047 
1048 const char *
1050 {
1051  switch (node) {
1052 #include "node_name.inc"
1053  default:
1054  rb_bug("unknown node (%d)", node);
1055  return 0;
1056  }
1057 }
1058 
1059 #define DECL_SYMBOL(name) \
1060  static VALUE sym_##name
1061 
1062 #define INIT_SYMBOL(name) \
1063  sym_##name = ID2SYM(rb_intern(#name))
1064 
1065 static VALUE
1066 register_label(struct st_table *table, unsigned long idx)
1067 {
1068  VALUE sym;
1069  char buff[8 + (sizeof(idx) * CHAR_BIT * 32 / 100)];
1070 
1071  snprintf(buff, sizeof(buff), "label_%lu", idx);
1072  sym = ID2SYM(rb_intern(buff));
1073  st_insert(table, idx, sym);
1074  return sym;
1075 }
1076 
1077 static VALUE
1079 {
1080  ID id;
1081  switch(type) {
1082  case CATCH_TYPE_RESCUE: CONST_ID(id, "rescue"); break;
1083  case CATCH_TYPE_ENSURE: CONST_ID(id, "ensure"); break;
1084  case CATCH_TYPE_RETRY: CONST_ID(id, "retry"); break;
1085  case CATCH_TYPE_BREAK: CONST_ID(id, "break"); break;
1086  case CATCH_TYPE_REDO: CONST_ID(id, "redo"); break;
1087  case CATCH_TYPE_NEXT: CONST_ID(id, "next"); break;
1088  default:
1089  rb_bug("...");
1090  }
1091  return ID2SYM(id);
1092 }
1093 
1094 static int
1096 {
1097  rb_ary_push(ary, obj_resurrect(key));
1098  rb_ary_push(ary, value);
1099  return ST_CONTINUE;
1100 }
1101 
1102 static VALUE
1104 {
1105  long i, pos;
1106  int line = 0;
1107  VALUE *seq;
1108 
1109  VALUE val = rb_ary_new();
1110  VALUE type; /* Symbol */
1111  VALUE locals = rb_ary_new();
1112  VALUE args = rb_ary_new();
1113  VALUE body = rb_ary_new(); /* [[:insn1, ...], ...] */
1114  VALUE nbody;
1115  VALUE exception = rb_ary_new(); /* [[....]] */
1116  VALUE misc = rb_hash_new();
1117 
1118  static VALUE insn_syms[VM_INSTRUCTION_SIZE];
1119  struct st_table *labels_table = st_init_numtable();
1120 
1121  DECL_SYMBOL(top);
1122  DECL_SYMBOL(method);
1123  DECL_SYMBOL(block);
1124  DECL_SYMBOL(class);
1125  DECL_SYMBOL(rescue);
1126  DECL_SYMBOL(ensure);
1127  DECL_SYMBOL(eval);
1128  DECL_SYMBOL(main);
1129  DECL_SYMBOL(defined_guard);
1130 
1131  if (sym_top == 0) {
1132  int i;
1133  for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
1134  insn_syms[i] = ID2SYM(rb_intern(insn_name(i)));
1135  }
1136  INIT_SYMBOL(top);
1137  INIT_SYMBOL(method);
1138  INIT_SYMBOL(block);
1139  INIT_SYMBOL(class);
1140  INIT_SYMBOL(rescue);
1141  INIT_SYMBOL(ensure);
1142  INIT_SYMBOL(eval);
1143  INIT_SYMBOL(main);
1144  INIT_SYMBOL(defined_guard);
1145  }
1146 
1147  /* type */
1148  switch(iseq->type) {
1149  case ISEQ_TYPE_TOP: type = sym_top; break;
1150  case ISEQ_TYPE_METHOD: type = sym_method; break;
1151  case ISEQ_TYPE_BLOCK: type = sym_block; break;
1152  case ISEQ_TYPE_CLASS: type = sym_class; break;
1153  case ISEQ_TYPE_RESCUE: type = sym_rescue; break;
1154  case ISEQ_TYPE_ENSURE: type = sym_ensure; break;
1155  case ISEQ_TYPE_EVAL: type = sym_eval; break;
1156  case ISEQ_TYPE_MAIN: type = sym_main; break;
1157  case ISEQ_TYPE_DEFINED_GUARD: type = sym_defined_guard; break;
1158  default: rb_bug("unsupported iseq type");
1159  };
1160 
1161  /* locals */
1162  for (i=0; i<iseq->local_table_size; i++) {
1163  ID lid = iseq->local_table[i];
1164  if (lid) {
1165  if (rb_id2str(lid)) rb_ary_push(locals, ID2SYM(lid));
1166  }
1167  else {
1168  rb_ary_push(locals, ID2SYM(rb_intern("#arg_rest")));
1169  }
1170  }
1171 
1172  /* args */
1173  {
1174  /*
1175  * [argc, # argc
1176  * [label1, label2, ...] # opts
1177  * rest index,
1178  * post_len
1179  * post_start
1180  * block index,
1181  * simple,
1182  * ]
1183  */
1184  VALUE arg_opt_labels = rb_ary_new();
1185  int j;
1186 
1187  for (j=0; j<iseq->arg_opts; j++) {
1188  rb_ary_push(arg_opt_labels,
1189  register_label(labels_table, iseq->arg_opt_table[j]));
1190  }
1191 
1192  /* commit */
1193  if (iseq->arg_simple == 1) {
1194  args = INT2FIX(iseq->argc);
1195  }
1196  else {
1197  rb_ary_push(args, INT2FIX(iseq->argc));
1198  rb_ary_push(args, arg_opt_labels);
1199  rb_ary_push(args, INT2FIX(iseq->arg_post_len));
1200  rb_ary_push(args, INT2FIX(iseq->arg_post_start));
1201  rb_ary_push(args, INT2FIX(iseq->arg_rest));
1202  rb_ary_push(args, INT2FIX(iseq->arg_block));
1203  rb_ary_push(args, INT2FIX(iseq->arg_simple));
1204  }
1205  }
1206 
1207  /* body */
1208  for (seq = iseq->iseq; seq < iseq->iseq + iseq->iseq_size; ) {
1209  VALUE insn = *seq++;
1210  int j, len = insn_len(insn);
1211  VALUE *nseq = seq + len - 1;
1212  VALUE ary = rb_ary_new2(len);
1213 
1214  rb_ary_push(ary, insn_syms[insn]);
1215  for (j=0; j<len-1; j++, seq++) {
1216  switch (insn_op_type(insn, j)) {
1217  case TS_OFFSET: {
1218  unsigned long idx = nseq - iseq->iseq + *seq;
1219  rb_ary_push(ary, register_label(labels_table, idx));
1220  break;
1221  }
1222  case TS_LINDEX:
1223  case TS_DINDEX:
1224  case TS_NUM:
1225  rb_ary_push(ary, INT2FIX(*seq));
1226  break;
1227  case TS_VALUE:
1228  rb_ary_push(ary, obj_resurrect(*seq));
1229  break;
1230  case TS_ISEQ:
1231  {
1232  rb_iseq_t *iseq = (rb_iseq_t *)*seq;
1233  if (iseq) {
1234  VALUE val = iseq_data_to_ary(iseq);
1235  rb_ary_push(ary, val);
1236  }
1237  else {
1238  rb_ary_push(ary, Qnil);
1239  }
1240  }
1241  break;
1242  case TS_GENTRY:
1243  {
1244  struct rb_global_entry *entry = (struct rb_global_entry *)*seq;
1245  rb_ary_push(ary, ID2SYM(entry->id));
1246  }
1247  break;
1248  case TS_IC: {
1249  struct iseq_inline_cache_entry *ic = (struct iseq_inline_cache_entry *)*seq;
1250  rb_ary_push(ary, INT2FIX(ic - iseq->ic_entries));
1251  }
1252  break;
1253  case TS_ID:
1254  rb_ary_push(ary, ID2SYM(*seq));
1255  break;
1256  case TS_CDHASH:
1257  {
1258  VALUE hash = *seq;
1259  VALUE val = rb_ary_new();
1260  int i;
1261 
1262  rb_hash_foreach(hash, cdhash_each, val);
1263 
1264  for (i=0; i<RARRAY_LEN(val); i+=2) {
1265  VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
1266  unsigned long idx = nseq - iseq->iseq + pos;
1267 
1268  rb_ary_store(val, i+1,
1269  register_label(labels_table, idx));
1270  }
1271  rb_ary_push(ary, val);
1272  }
1273  break;
1274  default:
1275  rb_bug("unknown operand: %c", insn_op_type(insn, j));
1276  }
1277  }
1278  rb_ary_push(body, ary);
1279  }
1280 
1281  nbody = body;
1282 
1283  /* exception */
1284  for (i=0; i<iseq->catch_table_size; i++) {
1285  VALUE ary = rb_ary_new();
1286  struct iseq_catch_table_entry *entry = &iseq->catch_table[i];
1287  rb_ary_push(ary, exception_type2symbol(entry->type));
1288  if (entry->iseq) {
1289  rb_iseq_t *eiseq;
1290  GetISeqPtr(entry->iseq, eiseq);
1291  rb_ary_push(ary, iseq_data_to_ary(eiseq));
1292  }
1293  else {
1294  rb_ary_push(ary, Qnil);
1295  }
1296  rb_ary_push(ary, register_label(labels_table, entry->start));
1297  rb_ary_push(ary, register_label(labels_table, entry->end));
1298  rb_ary_push(ary, register_label(labels_table, entry->cont));
1299  rb_ary_push(ary, INT2FIX(entry->sp));
1300  rb_ary_push(exception, ary);
1301  }
1302 
1303  /* make body with labels and insert line number */
1304  body = rb_ary_new();
1305 
1306  for (i=0, pos=0; i<RARRAY_LEN(nbody); i++) {
1307  VALUE ary = RARRAY_PTR(nbody)[i];
1308  st_data_t label;
1309 
1310  if (st_lookup(labels_table, pos, &label)) {
1311  rb_ary_push(body, (VALUE)label);
1312  }
1313 
1314  if (iseq->insn_info_table[i].line_no != line) {
1315  line = iseq->insn_info_table[i].line_no;
1316  rb_ary_push(body, INT2FIX(line));
1317  }
1318 
1319  rb_ary_push(body, ary);
1320  pos += RARRAY_LENINT(ary); /* reject too huge data */
1321  }
1322 
1323  st_free_table(labels_table);
1324 
1325  rb_hash_aset(misc, ID2SYM(rb_intern("arg_size")), INT2FIX(iseq->arg_size));
1326  rb_hash_aset(misc, ID2SYM(rb_intern("local_size")), INT2FIX(iseq->local_size));
1327  rb_hash_aset(misc, ID2SYM(rb_intern("stack_max")), INT2FIX(iseq->stack_max));
1328 
1329  /*
1330  * [:magic, :major_version, :minor_version, :format_type, :misc,
1331  * :name, :filename, :filepath, :line_no, :type, :locals, :args,
1332  * :catch_table, :bytecode]
1333  */
1334  rb_ary_push(val, rb_str_new2("YARVInstructionSequence/SimpleDataFormat"));
1335  rb_ary_push(val, INT2FIX(ISEQ_MAJOR_VERSION)); /* major */
1336  rb_ary_push(val, INT2FIX(ISEQ_MINOR_VERSION)); /* minor */
1337  rb_ary_push(val, INT2FIX(1));
1338  rb_ary_push(val, misc);
1339  rb_ary_push(val, iseq->name);
1340  rb_ary_push(val, iseq->filename);
1341  rb_ary_push(val, iseq->filepath);
1342  rb_ary_push(val, iseq->line_no);
1343  rb_ary_push(val, type);
1344  rb_ary_push(val, locals);
1345  rb_ary_push(val, args);
1346  rb_ary_push(val, exception);
1347  rb_ary_push(val, body);
1348  return val;
1349 }
1350 
1351 VALUE
1352 rb_iseq_clone(VALUE iseqval, VALUE newcbase)
1353 {
1354  VALUE newiseq = iseq_alloc(rb_cISeq);
1355  rb_iseq_t *iseq0, *iseq1;
1356 
1357  GetISeqPtr(iseqval, iseq0);
1358  GetISeqPtr(newiseq, iseq1);
1359 
1360  *iseq1 = *iseq0;
1361  iseq1->self = newiseq;
1362  if (!iseq1->orig) {
1363  iseq1->orig = iseqval;
1364  }
1365  if (iseq0->local_iseq == iseq0) {
1366  iseq1->local_iseq = iseq1;
1367  }
1368  if (newcbase) {
1369  iseq1->cref_stack = NEW_BLOCK(newcbase);
1370  if (iseq0->cref_stack->nd_next) {
1371  iseq1->cref_stack->nd_next = iseq0->cref_stack->nd_next;
1372  }
1373  iseq1->klass = newcbase;
1374  }
1375 
1376  return newiseq;
1377 }
1378 
1379 VALUE
1380 rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
1381 {
1382  int i, r, s;
1383  VALUE a, args = rb_ary_new2(iseq->arg_size);
1384  ID req, opt, rest, block;
1385 #define PARAM_TYPE(type) rb_ary_push(a = rb_ary_new2(2), ID2SYM(type))
1386 #define PARAM_ID(i) iseq->local_table[(i)]
1387 #define PARAM(i, type) ( \
1388  PARAM_TYPE(type), \
1389  rb_id2name(PARAM_ID(i)) ? \
1390  rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \
1391  a)
1392 
1393  CONST_ID(req, "req");
1394  CONST_ID(opt, "opt");
1395  if (is_proc) {
1396  for (i = 0; i < iseq->argc; i++) {
1397  PARAM_TYPE(opt);
1399  rb_ary_push(args, a);
1400  }
1401  }
1402  else {
1403  for (i = 0; i < iseq->argc; i++) {
1404  rb_ary_push(args, PARAM(i, req));
1405  }
1406  }
1407  r = iseq->arg_rest != -1 ? iseq->arg_rest :
1408  iseq->arg_post_len > 0 ? iseq->arg_post_start :
1409  iseq->arg_block != -1 ? iseq->arg_block :
1410  iseq->arg_size;
1411  for (s = i; i < r; i++) {
1412  PARAM_TYPE(opt);
1413  if (rb_id2name(PARAM_ID(i))) {
1414  rb_ary_push(a, ID2SYM(PARAM_ID(i)));
1415  }
1416  rb_ary_push(args, a);
1417  }
1418  if (iseq->arg_rest != -1) {
1419  CONST_ID(rest, "rest");
1420  rb_ary_push(args, PARAM(iseq->arg_rest, rest));
1421  }
1422  r = iseq->arg_post_start + iseq->arg_post_len;
1423  if (is_proc) {
1424  for (i = iseq->arg_post_start; i < r; i++) {
1425  PARAM_TYPE(opt);
1427  rb_ary_push(args, a);
1428  }
1429  }
1430  else {
1431  for (i = iseq->arg_post_start; i < r; i++) {
1432  rb_ary_push(args, PARAM(i, req));
1433  }
1434  }
1435  if (iseq->arg_block != -1) {
1436  CONST_ID(block, "block");
1437  rb_ary_push(args, PARAM(iseq->arg_block, block));
1438  }
1439  return args;
1440 }
1441 
1442 /* ruby2cext */
1443 
1444 VALUE
1446  const rb_iseq_t *iseq_template,
1447  const rb_insn_func_t *func,
1448  const struct iseq_insn_info_entry *insn_info_table,
1449  const char **local_table,
1450  const VALUE *arg_opt_table,
1451  const struct iseq_catch_table_entry *catch_table,
1452  const char *name,
1453  const char *filename,
1454  const unsigned short line_no)
1455 {
1456  unsigned long i;
1457  VALUE iseqval = iseq_alloc(rb_cISeq);
1458  rb_iseq_t *iseq;
1459  GetISeqPtr(iseqval, iseq);
1460 
1461  /* copy iseq */
1462  *iseq = *iseq_template;
1463  iseq->name = rb_str_new2(name);
1464  iseq->filename = rb_str_new2(filename);
1465  iseq->line_no = line_no;
1466  iseq->mark_ary = rb_ary_tmp_new(3);
1467  OBJ_UNTRUST(iseq->mark_ary);
1468  iseq->self = iseqval;
1469 
1470  iseq->iseq = ALLOC_N(VALUE, iseq->iseq_size);
1471 
1472  for (i=0; i<iseq->iseq_size; i+=2) {
1473  iseq->iseq[i] = BIN(opt_call_c_function);
1474  iseq->iseq[i+1] = (VALUE)func;
1475  }
1476 
1478 
1479 #define ALLOC_AND_COPY(dst, src, type, size) do { \
1480  if (size) { \
1481  (dst) = ALLOC_N(type, (size)); \
1482  MEMCPY((dst), (src), type, (size)); \
1483  } \
1484 } while (0)
1485 
1486  ALLOC_AND_COPY(iseq->insn_info_table, insn_info_table,
1487  struct iseq_insn_info_entry, iseq->insn_info_size);
1488 
1489  ALLOC_AND_COPY(iseq->catch_table, catch_table,
1491 
1492  ALLOC_AND_COPY(iseq->arg_opt_table, arg_opt_table,
1493  VALUE, iseq->arg_opts);
1494 
1495  set_relation(iseq, 0);
1496 
1497  return iseqval;
1498 }
1499 
1500 void
1502 {
1503  /* declare ::RubyVM::InstructionSequence */
1504  rb_cISeq = rb_define_class_under(rb_cRubyVM, "InstructionSequence", rb_cObject);
1506  rb_define_method(rb_cISeq, "inspect", iseq_inspect, 0);
1507  rb_define_method(rb_cISeq, "disasm", rb_iseq_disasm, 0);
1508  rb_define_method(rb_cISeq, "disassemble", rb_iseq_disasm, 0);
1509  rb_define_method(rb_cISeq, "to_a", iseq_to_a, 0);
1510  rb_define_method(rb_cISeq, "eval", iseq_eval, 0);
1511 
1512 #if 0 /* TBD */
1513  rb_define_method(rb_cISeq, "marshal_dump", iseq_marshal_dump, 0);
1514  rb_define_method(rb_cISeq, "marshal_load", iseq_marshal_load, 1);
1515 #endif
1516 
1517  /* disable this feature because there is no verifier. */
1518  /* rb_define_singleton_method(rb_cISeq, "load", iseq_s_load, -1); */
1519  (void)iseq_s_load;
1520 
1528 }
1529 
#define RSTRING_LEN(string)
Definition: generator.h:45
static long NUM2LONG(VALUE x)
Definition: ruby.h:510
int rb_iseq_disasm_insn(VALUE ret, VALUE *iseq, size_t pos, rb_iseq_t *iseqdat, VALUE child)
Disassemble a instruction Iseq -> Iseq inspect object.
Definition: iseq.c:841
int arg_simple
Definition: vm_core.h:215
int rb_iseq_first_lineno(rb_iseq_t *iseq)
Definition: iseq.c:679
VALUE rb_get_coverages(void)
Definition: thread.c:4854
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:956
void rb_bug(const char *fmt,...)
Definition: error.c:265
#define DECL_SYMBOL(name)
Definition: iseq.c:1059
#define rb_hash_lookup
Definition: tcltklib.c:264
NODE * rb_parser_compile_file(volatile VALUE vparser, const char *f, VALUE file, int start)
Definition: ripper.c:10831
static void iseq_mark(void *ptr)
Definition: iseq.c:94
unsigned long size
Definition: iseq.h:73
int i
Definition: win32ole.c:776
Definition: st.h:77
VALUE rb_id2str(ID id)
Definition: ripper.c:15432
unsigned long end
Definition: iseq.h:63
#define OPT_SPECIALISED_INSTRUCTION
#define NUM2INT(x)
Definition: ruby.h:536
static void make_compile_option(rb_compile_option_t *option, VALUE opt)
Definition: iseq.c:316
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1342
Definition: iseq.h:56
#define GetProcPtr(obj, ptr)
Definition: vm_core.h:523
#define RUBY_VM_NORMAL_ISEQ_P(ptr)
Definition: vm_core.h:621
#define FilePathValue(v)
Definition: ruby.h:487
static void set_relation(rb_iseq_t *iseq, const VALUE parent)
Definition: iseq.c:178
#define CLASS_OF(v)
Definition: ruby.h:376
#define Qtrue
Definition: ruby.h:366
struct iseq_compile_data * compile_data
Definition: vm_core.h:258
static unsigned short find_line_no(rb_iseq_t *iseq, unsigned long pos)
Definition: iseq.c:703
VALUE rb_cHash
Definition: hash.c:35
rb_iseq_t * iseq
Definition: vm_core.h:350
VALUE catch_table_ary
Definition: iseq.h:81
struct iseq_compile_data_storage * storage_head
Definition: iseq.h:93
const int id
Definition: nkf.c:209
VALUE coverage
Definition: vm_core.h:175
static VALUE iseq_s_compile(int argc, VALUE *argv, VALUE self)
Definition: iseq.c:581
VALUE rb_eTypeError
Definition: error.c:467
int rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
Definition: compile.c:555
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:740
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:2080
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:380
int local_table_size
Definition: vm_core.h:183
static int cdhash_each(VALUE key, VALUE value, VALUE ary)
Definition: iseq.c:1095
#define RSTRING_PTR(string)
Definition: generator.h:42
struct rb_iseq_struct * local_iseq
Definition: vm_core.h:232
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:514
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1574
#define RUBY_MARK_LEAVE(msg)
Definition: gc.h:54
struct iseq_compile_data_storage * next
Definition: iseq.h:71
unsigned short sp
Definition: iseq.h:49
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
struct iseq_inline_cache_entry * ic_entries
Definition: vm_core.h:188
#define RARRAY_LEN(ARRAY)
Definition: generator.h:39
size_t stack_max
Definition: vm_core.h:224
ID defined_method_id
Definition: vm_core.h:254
#define RUBY_GC_INFO
Definition: gc.h:57
#define T_ARRAY
Definition: ruby.h:420
VALUE rb_iseq_compile_node(VALUE self, NODE *node)
Definition: compile.c:462
#define st_lookup
Definition: regint.h:149
ID id
Definition: ripper.y:478
#define ALLOC_AND_COPY(dst, src, type, size)
VALUE rb_file_open_str(VALUE, const char *)
Definition: io.c:5099
static VALUE rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no, VALUE parent, enum iseq_type type, VALUE bopt, const rb_compile_option_t *option)
Definition: iseq.c:404
#define FIXNUM_P(f)
Definition: ruby.h:338
int arg_post_len
Definition: vm_core.h:219
VALUE orig
Definition: vm_core.h:239
#define ID2SYM(i)
Definition: cparse.c:63
const char * rb_obj_classname(VALUE)
Definition: variable.c:318
const rb_compile_option_t * option
Definition: iseq.h:99
#define GET_THREAD()
Definition: vm_core.h:690
#define sym(x)
Definition: date_core.c:3697
Definition: ripper.y:236
enum iseq_catch_table_entry::catch_type type
unsigned long pos
Definition: iseq.h:72
VALUE name
Definition: vm_core.h:168
#define OPT_STACK_CACHING
VALUE rb_cISeq
Definition: iseq.c:26
void rb_hash_foreach(VALUE hash, int(*func)(ANYARGS), VALUE farg)
Definition: hash.c:204
void rb_exc_raise(VALUE mesg)
Definition: eval.c:460
#define SET_COMPILE_OPTION_NUM(o, h, mem)
VALUE * iseq
Definition: vm_core.h:171
static VALUE iseq_s_compile_file(int argc, VALUE *argv, VALUE self)
Definition: iseq.c:595
int args
Definition: win32ole.c:777
#define CHECK_SYMBOL(v)
Definition: iseq.c:441
enum rb_iseq_struct::iseq_type type
static VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
Definition: iseq.c:444
VALUE filename
Definition: vm_core.h:169
#define MEMZERO(p, type, n)
Definition: ruby.h:1052
static rb_compile_option_t COMPILE_OPTION_DEFAULT
Definition: iseq.c:303
NODE * rb_parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line)
Definition: ripper.c:10796
Definition: iseq.h:54
NODE * cref_stack
Definition: vm_core.h:250
static VALUE CHECK_INTEGER(VALUE v)
Definition: iseq.c:442
#define ALLOC_N(type, n)
Definition: ruby.h:1034
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1123
VALUE mark_ary
Definition: iseq.h:80
Definition: ripper.y:476
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1246
VALUE filepath
Definition: vm_core.h:170
#define PRIdVALUE
Definition: ruby.h:126
#define PARAM(i, type)
static VALUE register_label(struct st_table *table, unsigned long idx)
Definition: iseq.c:1066
#define NEW_BLOCK(a)
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:1900
VALUE rb_ary_new(void)
Definition: array.c:339
static VALUE obj_resurrect(VALUE obj)
Definition: iseq.c:31
VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE parent)
Definition: iseq.c:388
static VALUE make_compile_option_value(rb_compile_option_t *option)
Definition: iseq.c:357
VALUE rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no, VALUE parent, enum iseq_type type, VALUE bopt)
Definition: iseq.c:431
int argc
argument information
Definition: vm_core.h:214
#define snprintf
Definition: subst.h:6
int arg_post_start
Definition: vm_core.h:220
#define NIL_P(v)
Definition: ruby.h:374
static VALUE iseq_eval(VALUE self)
Definition: iseq.c:647
#define CHECK_ARRAY(v)
Definition: iseq.c:439
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:635
VALUE * arg_opt_table
Definition: vm_core.h:222
VALUE rb_cRubyVM
Definition: vm.c:35
#define RUBY_MARK_ENTER(msg)
Definition: gc.h:53
#define OBJ_UNTRUST(x)
Definition: ruby.h:966
int argc
Definition: ruby.c:120
static unsigned short find_prev_line_no(rb_iseq_t *iseqdat, unsigned long pos)
Definition: iseq.c:715
#define Qfalse
Definition: ruby.h:365
rb_block_t * base_block
Definition: vm_core.h:421
int err
Definition: win32.c:78
#define OBJ_FREEZE(x)
Definition: ruby.h:970
#define PRIdPTRDIFF
Definition: ruby.h:155
ID * local_table
Definition: vm_core.h:182
static struct iseq_insn_info_entry * get_insn_info(const rb_iseq_t *iseq, const unsigned long pos)
Definition: iseq.c:688
Definition: error.c:344
unsigned long start
Definition: iseq.h:62
#define ALLOC(type)
Definition: ruby.h:1035
VALUE rb_str_resurrect(VALUE str)
Definition: string.c:911
void Init_ISeq(void)
Definition: iseq.c:1501
#define PRIuVALUE
Definition: ruby.h:129
#define OPT_INLINE_CONST_CACHE
VALUE rb_str_resize(VALUE, long)
Definition: string.c:1771
Definition: vm_core.h:128
static VALUE exception_type2symbol(VALUE type)
Definition: iseq.c:1078
#define INIT_SYMBOL(name)
Definition: iseq.c:1062
Definition: iseq.h:55
#define hidden_obj_p(obj)
Definition: iseq.c:28
Definition: iseq.h:59
VALUE rb_iseq_build_for_ruby2cext(const rb_iseq_t *iseq_template, const rb_insn_func_t *func, const struct iseq_insn_info_entry *insn_info_table, const char **local_table, const VALUE *arg_opt_table, const struct iseq_catch_table_entry *catch_table, const char *name, const char *filename, const unsigned short line_no)
Definition: iseq.c:1445
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:104
VALUE rb_obj_is_proc(VALUE)
Definition: proc.c:88
VALUE rb_funcall2(VALUE, ID, int, const VALUE *)
Calls a method.
Definition: vm_eval.c:669
VALUE rb_iseq_new_main(NODE *node, VALUE filename, VALUE filepath)
Definition: iseq.c:395
#define ISEQ_MINOR_VERSION
Definition: iseq.c:24
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1203
VALUE mark_ary
Definition: vm_core.h:174
static VALUE prepare_iseq_build(rb_iseq_t *iseq, VALUE name, VALUE filename, VALUE filepath, VALUE line_no, VALUE parent, enum iseq_type type, VALUE block_opt, const rb_compile_option_t *option)
Definition: iseq.c:226
VALUE rb_hash_new(void)
Definition: hash.c:229
void ruby_xfree(void *x)
Definition: gc.c:914
VALUE rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args, VALUE exception, VALUE body)
Definition: compile.c:5452
#define OPT_PEEPHOLE_OPTIMIZATION
static VALUE iseq_data_to_ary(rb_iseq_t *iseq)
Definition: iseq.c:1103
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1415
struct rb_iseq_struct * parent_iseq
Definition: vm_core.h:231
unsigned long ID
Definition: ruby.h:89
static VALUE iseq_s_compile_option_set(VALUE self, VALUE opt)
Definition: iseq.c:620
#define Qnil
Definition: ruby.h:367
#define OPT_INSTRUCTIONS_UNIFICATION
int type
Definition: tcltklib.c:107
#define SET_COMPILE_OPTION(o, h, mem)
VALUE * iseq_encoded
Definition: vm_core.h:172
#define BUILTIN_TYPE(x)
Definition: ruby.h:438
unsigned long VALUE
Definition: ruby.h:88
VALUE rb_iseq_eval(VALUE iseqval)
Definition: vm.c:1456
int catch_table_size
Definition: vm_core.h:228
#define RBASIC(obj)
Definition: ruby.h:904
Definition: iseq.h:52
#define FIX2INT(x)
Definition: ruby.h:538
register unsigned int len
Definition: name2ctype.h:22210
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
Definition: iseq.c:536
unsigned short line_no
Definition: vm_core.h:176
#define RARRAY_PTR(ARRAY)
Definition: generator.h:36
#define INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE
Definition: iseq.h:68
Definition: iseq.h:57
#define RARRAY_LENINT(ary)
Definition: ruby.h:718
VALUE err_info
Definition: iseq.h:79
VALUE rb_str_dup(VALUE)
Definition: string.c:905
static VALUE cleanup_iseq_build(rb_iseq_t *iseq)
Definition: iseq.c:289
#define CHAR_BIT
Definition: ruby.h:192
long st_data_t
Definition: syck.h:69
#define PARAM_ID(i)
Definition: iseq.h:58
#define StringValueCStr(v)
Definition: ruby.h:468
static VALUE iseq_s_disasm(VALUE klass, VALUE body)
Definition: iseq.c:1026
static VALUE iseq_s_load(int argc, VALUE *argv, VALUE self)
Definition: iseq.c:527
#define RUBY_FREE_UNLESS_NULL(ptr)
Definition: gc.h:61
struct rb_iseq_struct rb_iseq_t
Definition: method.h:57
unsigned int top
Definition: nkf.c:3914
static VALUE iseq_alloc(VALUE klass)
Definition: iseq.c:171
#define ISEQ_MAJOR_VERSION
Definition: iseq.c:23
unsigned long sp
Definition: iseq.h:65
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
Definition: file.c:3419
static VALUE insn_operand_intern(rb_iseq_t *iseq, VALUE insn, int op_no, VALUE op, int len, size_t pos, VALUE *pnop, VALUE child)
Definition: iseq.c:735
int size
Definition: encoding.c:51
Definition: iseq.h:46
#define PARAM_TYPE(type)
#define INT2FIX(i)
Definition: ruby.h:225
VALUE top_wrapper
Definition: vm_core.h:418
rb_block_t block
Definition: vm_core.h:527
VALUE klass
Definition: vm_core.h:251
static NODE * parse_string(VALUE str, const char *file, int line)
Definition: iseq.c:542
#define st_init_numtable
Definition: regint.h:142
#define RUBY_FREE_LEAVE(msg)
Definition: gc.h:56
#define RUBY_FREE_ENTER(msg)
Definition: gc.h:55
const char * ruby_node_name(int node)
Definition: iseq.c:1049
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1239
struct iseq_compile_data_storage * storage_current
Definition: iseq.h:94
struct iseq_catch_table_entry * catch_table
Definition: vm_core.h:227
rb_control_frame_t *FUNC_FASTCALL rb_insn_func_t(rb_thread_t *, rb_control_frame_t *)
Definition: vm_core.h:605
uint8_t key[16]
Definition: random.c:1284
static VALUE iseq_to_a(VALUE self)
Definition: iseq.c:671
#define RTEST(v)
Definition: ruby.h:373
static VALUE iseq_inspect(VALUE self)
Definition: iseq.c:654
#define T_STRING
Definition: ruby.h:418
int local_size
Definition: vm_core.h:186
VALUE rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE filepath, VALUE line, VALUE opt)
Definition: iseq.c:554
v
Definition: win32ole.c:790
#define RUBY_MARK_UNLESS_NULL(ptr)
Definition: gc.h:60
size_t insn_info_size
Definition: vm_core.h:180
int last_coverable_line
Definition: iseq.h:96
static const rb_data_type_t iseq_data_type
Definition: iseq.c:161
unsigned long iseq_size
Definition: vm_core.h:173
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:829
#define OPT_TRACE_INSTRUCTION
unsigned short line_no
Definition: iseq.h:48
#define OPT_OPERANDS_UNIFICATION
rb_iseq_t * rb_method_get_iseq(VALUE body)
Definition: proc.c:1704
static unsigned int hash(const char *str, unsigned int len)
Definition: lex.c:56
#define OPT_TAILCALL_OPTIMIZATION
#define st_insert
Definition: regint.h:148
VALUE rb_ary_new2(long capa)
Definition: array.c:332
#define CHECK_STRING(v)
Definition: iseq.c:440
static const char * catch_type(int type)
Definition: iseq.c:901
VALUE rb_parser_new(void)
Definition: ripper.c:15718
#define PRIdSIZE
Definition: ruby.h:170
int main(int argc, char **argv)
Definition: nkf.c:6446
const char * name
Definition: nkf.c:208
VALUE self
Definition: vm_core.h:238
#define GetISeqPtr(obj, ptr)
Definition: vm_core.h:146
unsigned long cont
Definition: iseq.h:64
const char * rb_id2name(ID id)
Definition: ripper.c:15493
static const rb_compile_option_t COMPILE_OPTION_FALSE
Definition: iseq.c:313
#define st_free_table
Definition: regint.h:152
VALUE rb_inspect(VALUE)
Definition: object.c:372
VALUE iseq
Definition: iseq.h:61
void rb_secure(int)
Definition: safe.c:79
#define CONST_ID(var, str)
Definition: ruby.h:1127
VALUE rb_iseq_new(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE parent, enum iseq_type type)
Definition: iseq.c:380
struct iseq_insn_info_entry * insn_info_table
Definition: vm_core.h:179
VALUE rb_ary_resurrect(VALUE ary)
Definition: array.c:1606
#define rb_intern(str)
static void iseq_free(void *ptr)
Definition: iseq.c:62
unsigned short position
Definition: iseq.h:47
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1209
VALUE rb_iseq_disasm(VALUE self)
Definition: iseq.c:923
VALUE rb_str_new2(const char *)
VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
Definition: iseq.c:1380
VALUE rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no, VALUE parent, enum iseq_type type, const rb_compile_option_t *option)
Definition: iseq.c:421
static size_t iseq_memsize(const void *ptr)
Definition: iseq.c:126
VALUE rb_iseq_compile(VALUE src, VALUE file, VALUE line)
Definition: iseq.c:575
static void compile_data_free(struct iseq_compile_data *compile_data)
Definition: iseq.c:47
static rb_iseq_t * iseq_check(VALUE val)
Definition: iseq.c:636
char ** argv
Definition: ruby.c:121
#define StringValue(v)
Definition: ruby.h:466
static VALUE iseq_s_compile_option_get(VALUE self)
Definition: iseq.c:630
VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase)
Definition: iseq.c:1352
VALUE rb_str_new(const char *, long)
Definition: string.c:410