Ruby  2.1.5p273(2014-11-13revision48405)
compile.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  compile.c - ruby node tree -> VM instruction sequence
4 
5  $Author: nagachika $
6  created at: 04/01/01 03:42:15 JST
7 
8  Copyright (C) 2004-2007 Koichi Sasada
9 
10 **********************************************************************/
11 
12 #include "ruby/ruby.h"
13 #include "internal.h"
14 #include <math.h>
15 
16 #define USE_INSN_STACK_INCREASE 1
17 #include "vm_core.h"
18 #include "iseq.h"
19 #include "insns.inc"
20 #include "insns_info.inc"
21 
22 #define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG))
23 #define FIXNUM_OR(n, i) ((n)|INT2FIX(i))
24 
25 typedef struct iseq_link_element {
26  enum {
31  } type;
34 } LINK_ELEMENT;
35 
36 typedef struct iseq_link_anchor {
39 } LINK_ANCHOR;
40 
41 typedef struct iseq_label_data {
43  int label_no;
44  int position;
45  int sc_state;
46  int set;
47  int sp;
48 } LABEL;
49 
50 typedef struct iseq_insn_data {
52  enum ruby_vminsn_type insn_id;
53  unsigned int line_no;
55  int sc_state;
57 } INSN;
58 
59 typedef struct iseq_adjust_data {
62  int line_no;
63 } ADJUST;
64 
65 struct ensure_range {
68  struct ensure_range *next;
69 };
70 
75 };
76 
90 #ifndef CPDEBUG
91 #define CPDEBUG 0
92 #endif
93 
94 #if CPDEBUG >= 0
95 #define compile_debug CPDEBUG
96 #else
97 #define compile_debug iseq->compile_data->option->debug_level
98 #endif
99 
100 #if CPDEBUG
101 
102 #define compile_debug_print_indent(level) \
103  ruby_debug_print_indent((level), compile_debug, gl_node_level * 2)
104 
105 #define debugp(header, value) (void) \
106  (compile_debug_print_indent(1) && \
107  ruby_debug_print_value(1, compile_debug, (header), (value)))
108 
109 #define debugi(header, id) (void) \
110  (compile_debug_print_indent(1) && \
111  ruby_debug_print_id(1, compile_debug, (header), (id)))
112 
113 #define debugp_param(header, value) (void) \
114  (compile_debug_print_indent(1) && \
115  ruby_debug_print_value(1, compile_debug, (header), (value)))
116 
117 #define debugp_verbose(header, value) (void) \
118  (compile_debug_print_indent(2) && \
119  ruby_debug_print_value(2, compile_debug, (header), (value)))
120 
121 #define debugp_verbose_node(header, value) (void) \
122  (compile_debug_print_indent(10) && \
123  ruby_debug_print_value(10, compile_debug, (header), (value)))
124 
125 #define debug_node_start(node) ((void) \
126  (compile_debug_print_indent(1) && \
127  (ruby_debug_print_node(1, CPDEBUG, "", (NODE *)(node)), gl_node_level)), \
128  gl_node_level++)
129 
130 #define debug_node_end() gl_node_level --
131 
132 #else
133 
134 static inline ID
135 r_id(ID id)
136 {
137  return id;
138 }
139 
140 static inline VALUE
142 {
143  return value;
144 }
145 
146 #define debugi(header, id) r_id(id)
147 #define debugp(header, value) r_value(value)
148 #define debugp_verbose(header, value) r_value(value)
149 #define debugp_verbose_node(header, value) r_value(value)
150 #define debugp_param(header, value) r_value(value)
151 #define debug_node_start(node) ((void)0)
152 #define debug_node_end() ((void)0)
153 #endif
154 
155 #if CPDEBUG > 1 || CPDEBUG < 0
156 #define debugs if (compile_debug_print_indent(1)) ruby_debug_printf
157 #define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs((msg), stderr)), (v))
158 #else
159 #define debugs if(0)printf
160 #define debug_compile(msg, v) (v)
161 #endif
162 
163 
164 /* create new label */
165 #define NEW_LABEL(l) new_label_body(iseq, (l))
166 
167 #define iseq_path(iseq) \
168  (((rb_iseq_t*)DATA_PTR(iseq))->location.path)
169 
170 #define iseq_absolute_path(iseq) \
171  (((rb_iseq_t*)DATA_PTR(iseq))->location.absolute_path)
172 
173 #define NEW_ISEQVAL(node, name, type, line_no) \
174  new_child_iseq(iseq, (node), rb_fstring(name), 0, (type), (line_no))
175 
176 #define NEW_CHILD_ISEQVAL(node, name, type, line_no) \
177  new_child_iseq(iseq, (node), rb_fstring(name), iseq->self, (type), (line_no))
178 
179 /* add instructions */
180 #define ADD_SEQ(seq1, seq2) \
181  APPEND_LIST((seq1), (seq2))
182 
183 /* add an instruction */
184 #define ADD_INSN(seq, line, insn) \
185  ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0))
186 
187 /* add an instruction with some operands (1, 2, 3, 5) */
188 #define ADD_INSN1(seq, line, insn, op1) \
189  ADD_ELEM((seq), (LINK_ELEMENT *) \
190  new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1)))
191 
192 /* add an instruction with label operand (alias of ADD_INSN1) */
193 #define ADD_INSNL(seq, line, insn, label) ADD_INSN1(seq, line, insn, label)
194 
195 #define ADD_INSN2(seq, line, insn, op1, op2) \
196  ADD_ELEM((seq), (LINK_ELEMENT *) \
197  new_insn_body(iseq, (line), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2)))
198 
199 #define ADD_INSN3(seq, line, insn, op1, op2, op3) \
200  ADD_ELEM((seq), (LINK_ELEMENT *) \
201  new_insn_body(iseq, (line), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3)))
202 
203 /* Specific Insn factory */
204 #define ADD_SEND(seq, line, id, argc) \
205  ADD_SEND_R((seq), (line), (id), (argc), (VALUE)Qfalse, (VALUE)INT2FIX(0))
206 
207 #define ADD_CALL_RECEIVER(seq, line) \
208  ADD_INSN((seq), (line), putself)
209 
210 #define ADD_CALL(seq, line, id, argc) \
211  ADD_SEND_R((seq), (line), (id), (argc), (VALUE)Qfalse, (VALUE)INT2FIX(VM_CALL_FCALL))
212 
213 #define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \
214  ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL))
215 
216 #define ADD_SEND_R(seq, line, id, argc, block, flag) \
217  ADD_ELEM((seq), (LINK_ELEMENT *) \
218  new_insn_send(iseq, (line), \
219  (VALUE)(id), (VALUE)(argc), (VALUE)(block), (VALUE)(flag)))
220 
221 #define ADD_TRACE(seq, line, event) \
222  do { \
223  if ((event) == RUBY_EVENT_LINE && iseq->coverage && \
224  (line) != iseq->compile_data->last_coverable_line) { \
225  RARRAY_ASET(iseq->coverage, (line) - 1, INT2FIX(0)); \
226  iseq->compile_data->last_coverable_line = (line); \
227  ADD_INSN1((seq), (line), trace, INT2FIX(RUBY_EVENT_COVERAGE)); \
228  } \
229  if (iseq->compile_data->option->trace_instruction) { \
230  ADD_INSN1((seq), (line), trace, INT2FIX(event)); \
231  } \
232  } while (0)
233 
234 /* add label */
235 #define ADD_LABEL(seq, label) \
236  ADD_ELEM((seq), (LINK_ELEMENT *) (label))
237 
238 #define APPEND_LABEL(seq, before, label) \
239  APPEND_ELEM((seq), (before), (LINK_ELEMENT *) (label))
240 
241 #define ADD_ADJUST(seq, line, label) \
242  ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), (line)))
243 
244 #define ADD_ADJUST_RESTORE(seq, label) \
245  ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1))
246 
247 #define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) \
248  (rb_ary_push(iseq->compile_data->catch_table_ary, \
249  rb_ary_new3(5, (type), \
250  (VALUE)(ls) | 1, (VALUE)(le) | 1, \
251  (VALUE)(iseqv), (VALUE)(lc) | 1)))
252 
253 /* compile node */
254 #define COMPILE(anchor, desc, node) \
255  (debug_compile("== " desc "\n", \
256  iseq_compile_each(iseq, (anchor), (node), 0)))
257 
258 /* compile node, this node's value will be popped */
259 #define COMPILE_POPED(anchor, desc, node) \
260  (debug_compile("== " desc "\n", \
261  iseq_compile_each(iseq, (anchor), (node), 1)))
262 
263 /* compile node, which is popped when 'poped' is true */
264 #define COMPILE_(anchor, desc, node, poped) \
265  (debug_compile("== " desc "\n", \
266  iseq_compile_each(iseq, (anchor), (node), (poped))))
267 
268 #define OPERAND_AT(insn, idx) \
269  (((INSN*)(insn))->operands[(idx)])
270 
271 #define INSN_OF(insn) \
272  (((INSN*)(insn))->insn_id)
273 
274 /* error */
275 #define COMPILE_ERROR(strs) \
276 { \
277  VALUE tmp = GET_THREAD()->errinfo; \
278  if (compile_debug) rb_compile_bug strs; \
279  GET_THREAD()->errinfo = iseq->compile_data->err_info; \
280  rb_compile_error strs; \
281  RB_OBJ_WRITE(iseq->self, &iseq->compile_data->err_info, GET_THREAD()->errinfo); \
282  GET_THREAD()->errinfo = tmp; \
283  ret = 0; \
284  break; \
285 }
286 
287 #define ERROR_ARGS ruby_sourcefile, nd_line(node),
288 
289 
290 #define COMPILE_OK 1
291 #define COMPILE_NG 0
292 
293 
294 /* leave name uninitialized so that compiler warn if INIT_ANCHOR is
295  * missing */
296 #define DECL_ANCHOR(name) \
297  LINK_ANCHOR *name, name##_body__ = {{0,},}
298 #define INIT_ANCHOR(name) \
299  (name##_body__.last = &name##_body__.anchor, name = &name##_body__)
300 
301 #define hide_obj(obj) do {OBJ_FREEZE(obj); RBASIC_CLEAR_CLASS(obj);} while (0)
302 
303 #include "optinsn.inc"
304 #if OPT_INSTRUCTIONS_UNIFICATION
305 #include "optunifs.inc"
306 #endif
307 
308 /* for debug */
309 #if CPDEBUG < 0
310 #define ISEQ_ARG iseq,
311 #define ISEQ_ARG_DECLARE rb_iseq_t *iseq,
312 #else
313 #define ISEQ_ARG
314 #define ISEQ_ARG_DECLARE
315 #endif
316 
317 #if CPDEBUG
318 #define gl_node_level iseq->compile_data->node_level
319 #if 0
320 static void debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor);
321 #endif
322 #endif
323 
324 static void dump_disasm_list(LINK_ELEMENT *elem);
325 
326 static int insn_data_length(INSN *iobj);
327 static int calc_sp_depth(int depth, INSN *iobj);
328 
329 static INSN *new_insn_body(rb_iseq_t *iseq, int line_no, int insn_id, int argc, ...);
330 static LABEL *new_label_body(rb_iseq_t *iseq, long line);
331 static ADJUST *new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line);
332 
333 static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * n, int);
334 static int iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
335 static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
336 static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
337 
338 static int iseq_set_local_table(rb_iseq_t *iseq, ID *tbl);
339 static int iseq_set_exception_local_table(rb_iseq_t *iseq);
340 static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * node);
341 
342 static int iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
343 static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
344 static int iseq_set_exception_table(rb_iseq_t *iseq);
345 static int iseq_set_optargs_table(rb_iseq_t *iseq);
346 
347 /*
348  * To make Array to LinkedList, use link_anchor
349  */
350 
351 static void
353 {
354 #if CPDEBUG
355  int flag = 0;
356  LINK_ELEMENT *list, *plist;
357 
358  if (!compile_debug) return;
359 
360  list = anchor->anchor.next;
361  plist = &anchor->anchor;
362  while (list) {
363  if (plist != list->prev) {
364  flag += 1;
365  }
366  plist = list;
367  list = list->next;
368  }
369 
370  if (anchor->last != plist && anchor->last != 0) {
371  flag |= 0x70000;
372  }
373 
374  if (flag != 0) {
375  rb_bug("list verify error: %08x (%s)", flag, info);
376  }
377 #endif
378 }
379 #if CPDEBUG < 0
380 #define verify_list(info, anchor) verify_list(iseq, (info), (anchor))
381 #endif
382 
383 /*
384  * elem1, elem2 => elem1, elem2, elem
385  */
386 static void
388 {
389  elem->prev = anchor->last;
390  anchor->last->next = elem;
391  anchor->last = elem;
392  verify_list("add", anchor);
393 }
394 
395 /*
396  * elem1, before, elem2 => elem1, before, elem, elem2
397  */
398 static void
400 {
401  elem->prev = before;
402  elem->next = before->next;
403  elem->next->prev = elem;
404  before->next = elem;
405  if (before == anchor->last) anchor->last = elem;
406  verify_list("add", anchor);
407 }
408 #if CPDEBUG < 0
409 #define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, (anchor), (elem))
410 #define APPEND_ELEM(anchor, before, elem) ADD_ELEM(iseq, (anchor), (before), (elem))
411 #endif
412 
413 static int
415 {
416  if (!SPECIAL_CONST_P(v)) {
417  rb_iseq_add_mark_object(iseq, v);
418  }
419  return COMPILE_OK;
420 }
421 
422 #define ruby_sourcefile RSTRING_PTR(iseq->location.path)
423 
424 static int
426 {
427  if (!SPECIAL_CONST_P(v)) {
428  rb_ary_push(iseq->compile_data->mark_ary, v);
429  }
430  return COMPILE_OK;
431 }
432 
433 static int
435 {
436  rb_iseq_t *iseq = (rb_iseq_t *)arg;
437  LABEL *lobj = (LABEL *)label;
438  if (!lobj->link.next) {
439  do {
440  int ret;
442  "%s: undefined label", rb_id2name((ID)name)));
443  if (ret) break;
444  } while (0);
445  }
446  return ST_CONTINUE;
447 }
448 
449 static void
450 validate_labels(rb_iseq_t *iseq, st_table *labels_table)
451 {
452  st_foreach(labels_table, validate_label, (st_data_t)iseq);
453  if (!NIL_P(iseq->compile_data->err_info)) {
454  rb_exc_raise(iseq->compile_data->err_info);
455  }
456 }
457 
458 VALUE
460 {
461  DECL_ANCHOR(ret);
462  rb_iseq_t *iseq;
463  INIT_ANCHOR(ret);
464  GetISeqPtr(self, iseq);
465 
466  if (node == 0) {
467  COMPILE(ret, "nil", node);
468  iseq_set_local_table(iseq, 0);
469  }
470  else if (nd_type(node) == NODE_SCOPE) {
471  /* iseq type of top, method, class, block */
472  iseq_set_local_table(iseq, node->nd_tbl);
473  iseq_set_arguments(iseq, ret, node->nd_args);
474 
475  switch (iseq->type) {
476  case ISEQ_TYPE_BLOCK:
477  {
478  LABEL *start = iseq->compile_data->start_label = NEW_LABEL(0);
479  LABEL *end = iseq->compile_data->end_label = NEW_LABEL(0);
480 
482  ADD_LABEL(ret, start);
483  COMPILE(ret, "block body", node->nd_body);
484  ADD_LABEL(ret, end);
486 
487  /* wide range catch handler must put at last */
488  ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, start);
489  ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, end);
490  break;
491  }
492  case ISEQ_TYPE_CLASS:
493  {
495  COMPILE(ret, "scoped node", node->nd_body);
497  break;
498  }
499  case ISEQ_TYPE_METHOD:
500  {
502  COMPILE(ret, "scoped node", node->nd_body);
504  break;
505  }
506  default: {
507  COMPILE(ret, "scoped node", node->nd_body);
508  break;
509  }
510  }
511  }
512  else if (nd_type(node) == NODE_IFUNC) {
513  /* user callback */
514  (*node->nd_cfnc)(iseq, ret, node->nd_tval);
515  }
516  else {
517  switch (iseq->type) {
518  case ISEQ_TYPE_METHOD:
519  case ISEQ_TYPE_CLASS:
520  case ISEQ_TYPE_BLOCK:
521  case ISEQ_TYPE_EVAL:
522  case ISEQ_TYPE_MAIN:
523  case ISEQ_TYPE_TOP:
524  rb_compile_error(ERROR_ARGS "compile/should not be reached: %s:%d",
525  __FILE__, __LINE__);
526  break;
527  case ISEQ_TYPE_RESCUE:
529  COMPILE(ret, "rescue", node);
530  break;
531  case ISEQ_TYPE_ENSURE:
533  COMPILE_POPED(ret, "ensure", node);
534  break;
535  case ISEQ_TYPE_DEFINED_GUARD:
536  iseq_set_local_table(iseq, 0);
537  COMPILE(ret, "defined guard", node);
538  break;
539  default:
540  rb_bug("unknown scope");
541  }
542  }
543 
544  if (iseq->type == ISEQ_TYPE_RESCUE || iseq->type == ISEQ_TYPE_ENSURE) {
545  ADD_INSN2(ret, 0, getlocal, INT2FIX(2), INT2FIX(0));
546  ADD_INSN1(ret, 0, throw, INT2FIX(0) /* continue throw */ );
547  }
548  else {
549  ADD_INSN(ret, iseq->compile_data->last_line, leave);
550  }
551 
552 #if SUPPORT_JOKE
553  if (iseq->compile_data->labels_table) {
554  validate_labels(iseq, iseq->compile_data->labels_table);
555  }
556 #endif
557  return iseq_setup(iseq, ret);
558 }
559 
560 int
562 {
563 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
564  const void * const *table = rb_vm_get_insns_address_table();
565  unsigned long i;
566 
567  iseq->iseq_encoded = ALLOC_N(VALUE, iseq->iseq_size);
568  MEMCPY(iseq->iseq_encoded, iseq->iseq, VALUE, iseq->iseq_size);
569 
570  for (i = 0; i < iseq->iseq_size; /* */ ) {
571  int insn = (int)iseq->iseq_encoded[i];
572  int len = insn_len(insn);
573  iseq->iseq_encoded[i] = (VALUE)table[insn];
574  i += len;
575  }
576 #else
577  iseq->iseq_encoded = iseq->iseq;
578 #endif
579  return COMPILE_OK;
580 }
581 
582 /*********************************************/
583 /* definition of data structure for compiler */
584 /*********************************************/
585 
586 /*
587  * On 32-bit SPARC, GCC by default generates SPARC V7 code that may require
588  * 8-byte word alignment. On the other hand, Oracle Solaris Studio seems to
589  * generate SPARCV8PLUS code with unaligned memory accesss instructions.
590  * That is why the STRICT_ALIGNMENT is defined only with GCC.
591  */
592 #if defined(__sparc) && SIZEOF_VOIDP == 4 && defined(__GNUC__)
593  #define STRICT_ALIGNMENT
594 #endif
595 
596 #ifdef STRICT_ALIGNMENT
597  #if defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG > SIZEOF_VALUE
598  #define ALIGNMENT_SIZE SIZEOF_LONG_LONG
599  #else
600  #define ALIGNMENT_SIZE SIZEOF_VALUE
601  #endif
602  #define PADDING_SIZE_MAX ((size_t)((ALIGNMENT_SIZE) - 1))
603  #define ALIGNMENT_SIZE_MASK PADDING_SIZE_MAX
604  /* Note: ALIGNMENT_SIZE == (2 ** N) is expected. */
605 #else
606  #define PADDING_SIZE_MAX 0
607 #endif /* STRICT_ALIGNMENT */
608 
609 #ifdef STRICT_ALIGNMENT
610 /* calculate padding size for aligned memory access */
611 static size_t
612 calc_padding(void *ptr, size_t size)
613 {
614  size_t mis;
615  size_t padding = 0;
616 
617  mis = (size_t)ptr & ALIGNMENT_SIZE_MASK;
618  if (mis > 0) {
619  padding = ALIGNMENT_SIZE - mis;
620  }
621 /*
622  * On 32-bit sparc or equivalents, when a single VALUE is requested
623  * and padding == sizeof(VALUE), it is clear that no padding is needed.
624  */
625 #if ALIGNMENT_SIZE > SIZEOF_VALUE
626  if (size == sizeof(VALUE) && padding == sizeof(VALUE)) {
627  padding = 0;
628  }
629 #endif
630 
631  return padding;
632 }
633 #endif /* STRICT_ALIGNMENT */
634 
635 static void *
637 {
638  void *ptr = 0;
639  struct iseq_compile_data_storage *storage =
641 #ifdef STRICT_ALIGNMENT
642  size_t padding = calc_padding((void *)&storage->buff[storage->pos], size);
643 #else
644  const size_t padding = 0; /* expected to be optimized by compiler */
645 #endif /* STRICT_ALIGNMENT */
646 
647  if (storage->pos + size + padding > storage->size) {
648  unsigned long alloc_size = storage->size * 2;
649 
650  retry:
651  if (alloc_size < size + PADDING_SIZE_MAX) {
652  alloc_size *= 2;
653  goto retry;
654  }
655  storage->next = (void *)ALLOC_N(char, alloc_size +
656  sizeof(struct
658  storage = iseq->compile_data->storage_current = storage->next;
659  storage->next = 0;
660  storage->pos = 0;
661  storage->size = alloc_size;
662  storage->buff = (char *)(&storage->buff + 1);
663 #ifdef STRICT_ALIGNMENT
664  padding = calc_padding((void *)&storage->buff[storage->pos], size);
665 #endif /* STRICT_ALIGNMENT */
666  }
667 
668 #ifdef STRICT_ALIGNMENT
669  storage->pos += (int)padding;
670 #endif /* STRICT_ALIGNMENT */
671 
672  ptr = (void *)&storage->buff[storage->pos];
673  storage->pos += size;
674  return ptr;
675 }
676 
677 static INSN *
679 {
680  return (INSN *)compile_data_alloc(iseq, sizeof(INSN));
681 }
682 
683 static LABEL *
685 {
686  return (LABEL *)compile_data_alloc(iseq, sizeof(LABEL));
687 }
688 
689 static ADJUST *
691 {
692  return (ADJUST *)compile_data_alloc(iseq, sizeof(ADJUST));
693 }
694 
695 /*
696  * elem1, elemX => elem1, elem2, elemX
697  */
698 static void
700 {
701  elem2->next = elem1->next;
702  elem2->prev = elem1;
703  elem1->next = elem2;
704  if (elem2->next) {
705  elem2->next->prev = elem2;
706  }
707 }
708 
709 #if 0 /* unused */
710 /*
711  * elemX, elem1 => elemX, elem2, elem1
712  */
713 static void
714 INSERT_ELEM_PREV(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
715 {
716  elem2->prev = elem1->prev;
717  elem2->next = elem1;
718  elem1->prev = elem2;
719  if (elem2->prev) {
720  elem2->prev->next = elem2;
721  }
722 }
723 #endif
724 
725 /*
726  * elemX, elem1, elemY => elemX, elem2, elemY
727  */
728 static void
730 {
731  elem2->prev = elem1->prev;
732  elem2->next = elem1->next;
733  if (elem1->prev) {
734  elem1->prev->next = elem2;
735  }
736  if (elem1->next) {
737  elem1->next->prev = elem2;
738  }
739 }
740 
741 static void
743 {
744  elem->prev->next = elem->next;
745  if (elem->next) {
746  elem->next->prev = elem->prev;
747  }
748 }
749 
750 static LINK_ELEMENT *
752 {
753  return anchor->anchor.next;
754 }
755 
756 #if 0 /* unused */
757 static LINK_ELEMENT *
758 LAST_ELEMENT(LINK_ANCHOR *anchor)
759 {
760  return anchor->last;
761 }
762 #endif
763 
764 static LINK_ELEMENT *
766 {
767  LINK_ELEMENT *elem = anchor->last;
768  anchor->last = anchor->last->prev;
769  anchor->last->next = 0;
770  verify_list("pop", anchor);
771  return elem;
772 }
773 #if CPDEBUG < 0
774 #define POP_ELEMENT(anchor) POP_ELEMENT(iseq, (anchor))
775 #endif
776 
777 #if 0 /* unused */
778 static LINK_ELEMENT *
779 SHIFT_ELEMENT(LINK_ANCHOR *anchor)
780 {
781  LINK_ELEMENT *elem = anchor->anchor.next;
782  if (elem) {
783  anchor->anchor.next = elem->next;
784  }
785  return elem;
786 }
787 #endif
788 
789 #if 0 /* unused */
790 static int
791 LIST_SIZE(LINK_ANCHOR *anchor)
792 {
793  LINK_ELEMENT *elem = anchor->anchor.next;
794  int size = 0;
795  while (elem) {
796  size += 1;
797  elem = elem->next;
798  }
799  return size;
800 }
801 #endif
802 
803 static int
805 {
806  if (anchor->anchor.next == 0) {
807  return 1;
808  }
809  else {
810  return 0;
811  }
812 }
813 
814 /*
815  * anc1: e1, e2, e3
816  * anc2: e4, e5
817  *#=>
818  * anc1: e1, e2, e3, e4, e5
819  * anc2: e4, e5 (broken)
820  */
821 static void
823 {
824  if (anc2->anchor.next) {
825  anc1->last->next = anc2->anchor.next;
826  anc2->anchor.next->prev = anc1->last;
827  anc1->last = anc2->last;
828  }
829  verify_list("append", anc1);
830 }
831 #if CPDEBUG < 0
832 #define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, (anc1), (anc2))
833 #endif
834 
835 /*
836  * anc1: e1, e2, e3
837  * anc2: e4, e5
838  *#=>
839  * anc1: e4, e5, e1, e2, e3
840  * anc2: e4, e5 (broken)
841  */
842 static void
844 {
845  if (anc2->anchor.next) {
846  LINK_ELEMENT *first = anc1->anchor.next;
847  anc1->anchor.next = anc2->anchor.next;
848  anc1->anchor.next->prev = &anc1->anchor;
849  anc2->last->next = first;
850  if (first) {
851  first->prev = anc2->last;
852  }
853  else {
854  anc1->last = anc2->last;
855  }
856  }
857 
858  verify_list("append", anc1);
859 }
860 #if CPDEBUG < 0
861 #define INSERT_LIST(anc1, anc2) INSERT_LIST(iseq, (anc1), (anc2))
862 #endif
863 
864 #if 0 /* unused */
865 /*
866  * anc1: e1, e2, e3
867  * anc2: e4, e5
868  *#=>
869  * anc1: e4, e5
870  * anc2: e1, e2, e3
871  */
872 static void
873 SWAP_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc1, LINK_ANCHOR *anc2)
874 {
875  LINK_ANCHOR tmp = *anc2;
876 
877  /* it has bug */
878  *anc2 = *anc1;
879  *anc1 = tmp;
880 
881  verify_list("swap1", anc1);
882  verify_list("swap2", anc2);
883 }
884 #if CPDEBUG < 0
885 #define SWAP_LIST(anc1, anc2) SWAP_LIST(iseq, (anc1), (anc2))
886 #endif
887 
888 static LINK_ANCHOR *
889 REVERSE_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc)
890 {
891  LINK_ELEMENT *first, *last, *elem, *e;
892  first = &anc->anchor;
893  elem = first->next;
894  last = anc->last;
895 
896  if (elem != 0) {
897  anc->anchor.next = last;
898  anc->last = elem;
899  }
900  else {
901  /* null list */
902  return anc;
903  }
904  while (elem) {
905  e = elem->next;
906  elem->next = elem->prev;
907  elem->prev = e;
908  elem = e;
909  }
910 
911  first->next = last;
912  last->prev = first;
913  anc->last->next = 0;
914 
915  verify_list("reverse", anc);
916  return anc;
917 }
918 #if CPDEBUG < 0
919 #define REVERSE_LIST(anc) REVERSE_LIST(iseq, (anc))
920 #endif
921 #endif
922 
923 #if CPDEBUG && 0
924 static void
925 debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor)
926 {
927  LINK_ELEMENT *list = FIRST_ELEMENT(anchor);
928  printf("----\n");
929  printf("anch: %p, frst: %p, last: %p\n", &anchor->anchor,
930  anchor->anchor.next, anchor->last);
931  while (list) {
932  printf("curr: %p, next: %p, prev: %p, type: %d\n", list, list->next,
933  list->prev, FIX2INT(list->type));
934  list = list->next;
935  }
936  printf("----\n");
937 
938  dump_disasm_list(anchor->anchor.next);
939  verify_list("debug list", anchor);
940 }
941 #if CPDEBUG < 0
942 #define debug_list(anc) debug_list(iseq, (anc))
943 #endif
944 #endif
945 
946 static LABEL *
947 new_label_body(rb_iseq_t *iseq, long line)
948 {
949  LABEL *labelobj = compile_data_alloc_label(iseq);
950 
951  labelobj->link.type = ISEQ_ELEMENT_LABEL;
952  labelobj->link.next = 0;
953 
954  labelobj->label_no = iseq->compile_data->label_no++;
955  labelobj->sc_state = 0;
956  labelobj->sp = -1;
957  return labelobj;
958 }
959 
960 static ADJUST *
961 new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line)
962 {
963  ADJUST *adjust = compile_data_alloc_adjust(iseq);
964  adjust->link.type = ISEQ_ELEMENT_ADJUST;
965  adjust->link.next = 0;
966  adjust->label = label;
967  adjust->line_no = line;
968  return adjust;
969 }
970 
971 static INSN *
972 new_insn_core(rb_iseq_t *iseq, int line_no,
973  int insn_id, int argc, VALUE *argv)
974 {
975  INSN *iobj = compile_data_alloc_insn(iseq);
976  /* printf("insn_id: %d, line: %d\n", insn_id, line_no); */
977 
978  iobj->link.type = ISEQ_ELEMENT_INSN;
979  iobj->link.next = 0;
980  iobj->insn_id = insn_id;
981  iobj->line_no = line_no;
982  iobj->operands = argv;
983  iobj->operand_size = argc;
984  iobj->sc_state = 0;
985  return iobj;
986 }
987 
988 static INSN *
989 new_insn_body(rb_iseq_t *iseq, int line_no, int insn_id, int argc, ...)
990 {
991  VALUE *operands = 0;
992  va_list argv;
993  if (argc > 0) {
994  int i;
995  va_init_list(argv, argc);
996  operands = (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * argc);
997  for (i = 0; i < argc; i++) {
998  VALUE v = va_arg(argv, VALUE);
999  operands[i] = v;
1000  }
1001  va_end(argv);
1002  }
1003  return new_insn_core(iseq, line_no, insn_id, argc, operands);
1004 }
1005 
1006 static rb_call_info_t *
1007 new_callinfo(rb_iseq_t *iseq, ID mid, int argc, VALUE block, unsigned long flag)
1008 {
1010  ci->mid = mid;
1011  ci->flag = flag;
1012  ci->orig_argc = argc;
1013  ci->argc = argc;
1014 
1015  if (block) {
1016  GetISeqPtr(block, ci->blockiseq);
1017  }
1018  else {
1019  ci->blockiseq = 0;
1020  if (!(ci->flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG))) {
1022  }
1023  }
1024  ci->method_state = 0;
1025  ci->class_serial = 0;
1026  ci->blockptr = 0;
1027  ci->recv = Qundef;
1028  ci->call = 0; /* TODO: should set default function? */
1029 
1030  ci->aux.index = iseq->callinfo_size++;
1031 
1032  return ci;
1033 }
1034 
1035 static INSN *
1037 {
1038  VALUE *operands = (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 1);
1039  operands[0] = (VALUE)new_callinfo(iseq, SYM2ID(id), FIX2INT(argc), block, FIX2INT(flag));
1040  return new_insn_core(iseq, line_no, BIN(send), 1, operands);
1041 }
1042 
1043 static VALUE
1045  VALUE name, VALUE parent, enum iseq_type type, int line_no)
1046 {
1047  VALUE ret;
1048 
1049  debugs("[new_child_iseq]> ---------------------------------------\n");
1050  ret = rb_iseq_new_with_opt(node, name,
1051  iseq_path(iseq->self), iseq_absolute_path(iseq->self),
1052  INT2FIX(line_no), parent, type, iseq->compile_data->option);
1053  debugs("[new_child_iseq]< ---------------------------------------\n");
1054  iseq_add_mark_object(iseq, ret);
1055  return ret;
1056 }
1057 
1058 static int
1060 {
1061  /* debugs("[compile step 2] (iseq_array_to_linkedlist)\n"); */
1062 
1063  if (compile_debug > 5)
1065 
1066  debugs("[compile step 3.1 (iseq_optimize)]\n");
1067  iseq_optimize(iseq, anchor);
1068 
1069  if (compile_debug > 5)
1071 
1073  debugs("[compile step 3.2 (iseq_insns_unification)]\n");
1074  iseq_insns_unification(iseq, anchor);
1075  if (compile_debug > 5)
1077  }
1078 
1079  if (iseq->compile_data->option->stack_caching) {
1080  debugs("[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
1081  iseq_set_sequence_stackcaching(iseq, anchor);
1082  if (compile_debug > 5)
1084  }
1085 
1086  debugs("[compile step 4.1 (iseq_set_sequence)]\n");
1087  iseq_set_sequence(iseq, anchor);
1088  if (compile_debug > 5)
1090 
1091  debugs("[compile step 4.2 (iseq_set_exception_table)]\n");
1093 
1094  debugs("[compile step 4.3 (set_optargs_table)] \n");
1095  iseq_set_optargs_table(iseq);
1096 
1097  debugs("[compile step 5 (iseq_translate_threaded_code)] \n");
1099 
1100  if (compile_debug > 1) {
1101  VALUE str = rb_iseq_disasm(iseq->self);
1102  printf("%s\n", StringValueCStr(str));
1103  fflush(stdout);
1104  }
1105  debugs("[compile step: finish]\n");
1106 
1107  return 0;
1108 }
1109 
1110 static int
1112 {
1113  ID id_dollar_bang;
1114 
1115  CONST_ID(id_dollar_bang, "#$!");
1116  iseq->local_table = (ID *)ALLOC_N(ID, 1);
1117  iseq->local_table_size = 1;
1118  iseq->local_size = iseq->local_table_size + 1;
1119  iseq->local_table[0] = id_dollar_bang;
1120  return COMPILE_OK;
1121 }
1122 
1123 static int
1125 {
1126  int lev = 0;
1127  while (iseq != iseq->local_iseq) {
1128  lev++;
1129  iseq = iseq->parent_iseq;
1130  }
1131  return lev;
1132 }
1133 
1134 static int
1136 {
1137  int i;
1138 
1139  for (i = 0; i < iseq->local_table_size; i++) {
1140  if (iseq->local_table[i] == id) {
1141  return i;
1142  }
1143  }
1144  return -1;
1145 }
1146 
1147 static int
1149 {
1150  int idx = get_dyna_var_idx_at_raw(iseq->local_iseq, id);
1151 
1152  if (idx < 0) {
1153  rb_bug("get_local_var_idx: %d", idx);
1154  }
1155 
1156  return idx;
1157 }
1158 
1159 static int
1160 get_dyna_var_idx(rb_iseq_t *iseq, ID id, int *level, int *ls)
1161 {
1162  int lv = 0, idx = -1;
1163 
1164  while (iseq) {
1165  idx = get_dyna_var_idx_at_raw(iseq, id);
1166  if (idx >= 0) {
1167  break;
1168  }
1169  iseq = iseq->parent_iseq;
1170  lv++;
1171  }
1172 
1173  if (idx < 0) {
1174  rb_bug("get_dyna_var_idx: -1");
1175  }
1176 
1177  *level = lv;
1178  *ls = iseq->local_size;
1179  return idx;
1180 }
1181 
1182 static int
1183 iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
1184 {
1185  debugs("iseq_set_arguments: %s\n", node_args ? "" : "0");
1186 
1187  if (node_args) {
1188  struct rb_args_info *args = node_args->nd_ainfo;
1189  ID rest_id = 0;
1190  int last_comma = 0;
1191  ID block_id = 0;
1192 
1193  if (nd_type(node_args) != NODE_ARGS) {
1194  rb_bug("iseq_set_arguments: NODE_ARGS is expected, but %s",
1195  ruby_node_name(nd_type(node_args)));
1196  }
1197 
1198 
1199  iseq->argc = (int)args->pre_args_num;
1200  debugs(" - argc: %d\n", iseq->argc);
1201 
1202  rest_id = args->rest_arg;
1203  if (rest_id == 1) {
1204  last_comma = 1;
1205  rest_id = 0;
1206  }
1207  block_id = args->block_arg;
1208 
1209  if (args->first_post_arg) {
1211  iseq->arg_post_len = args->post_args_num;
1212  }
1213 
1214  if (args->opt_args) {
1215  NODE *node = args->opt_args;
1216  LABEL *label;
1217  VALUE labels = rb_ary_tmp_new(1);
1218  int i = 0, j;
1219 
1220  while (node) {
1221  label = NEW_LABEL(nd_line(node));
1222  rb_ary_push(labels, (VALUE)label | 1);
1223  ADD_LABEL(optargs, label);
1224  COMPILE_POPED(optargs, "optarg", node->nd_body);
1225  node = node->nd_next;
1226  i += 1;
1227  }
1228 
1229  /* last label */
1230  label = NEW_LABEL(nd_line(node_args));
1231  rb_ary_push(labels, (VALUE)label | 1);
1232  ADD_LABEL(optargs, label);
1233  i += 1;
1234 
1235  iseq->arg_opts = i;
1236  iseq->arg_opt_table = ALLOC_N(VALUE, i);
1237  MEMCPY(iseq->arg_opt_table, RARRAY_CONST_PTR(labels), VALUE, i);
1238  for (j = 0; j < i; j++) {
1239  iseq->arg_opt_table[j] &= ~1;
1240  }
1241  rb_ary_clear(labels);
1242  }
1243  else {
1244  iseq->arg_opts = 0;
1245  }
1246 
1247  if (args->kw_args) {
1248  NODE *node = args->kw_args;
1249  VALUE keywords = rb_ary_tmp_new(1);
1250  VALUE required = 0;
1251  int i = 0, j, r = 0;
1252 
1253  iseq->arg_keyword = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_vid);
1254  COMPILE(optargs, "kwarg", args->kw_rest_arg);
1255  while (node) {
1256  VALUE list = keywords;
1257  if (node->nd_body->nd_value == (NODE *)-1) {
1258  ++r;
1259  if (!required) required = rb_ary_tmp_new(1);
1260  list = required;
1261  }
1262  rb_ary_push(list, INT2FIX(node->nd_body->nd_vid));
1263  COMPILE_POPED(optargs, "kwarg", node); /* nd_type(node) == NODE_KW_ARG */
1264  node = node->nd_next;
1265  i += 1;
1266  }
1267  iseq->arg_keyword_check = args->kw_rest_arg->nd_cflag != 0;
1268  iseq->arg_keywords = i;
1269  iseq->arg_keyword_required = r;
1270  iseq->arg_keyword_table = ALLOC_N(ID, i);
1271  if (r) {
1272  rb_ary_concat(required, keywords);
1273  keywords = required;
1274  }
1275  for (j = 0; j < i; j++) {
1276  iseq->arg_keyword_table[j] = FIX2INT(RARRAY_AREF(keywords, j));
1277  }
1278  ADD_INSN(optargs, nd_line(args->kw_args), pop);
1279  }
1280  else if (args->kw_rest_arg) {
1281  iseq->arg_keyword = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_vid);
1282  COMPILE(optargs, "kwarg", args->kw_rest_arg);
1283  ADD_INSN(optargs, nd_line(args->kw_rest_arg), pop);
1284  }
1285  else {
1286  iseq->arg_keyword = -1;
1287  }
1288 
1289  if (args->pre_init) { /* m_init */
1290  COMPILE_POPED(optargs, "init arguments (m)", args->pre_init);
1291  }
1292  if (args->post_init) { /* p_init */
1293  COMPILE_POPED(optargs, "init arguments (p)", args->post_init);
1294  }
1295 
1296  if (rest_id) {
1297  iseq->arg_rest = get_dyna_var_idx_at_raw(iseq, rest_id);
1298 
1299  if (iseq->arg_rest == -1) {
1300  rb_bug("arg_rest: -1");
1301  }
1302 
1303  if (iseq->arg_post_start == 0) {
1304  iseq->arg_post_start = iseq->arg_rest + 1;
1305  }
1306  }
1307 
1308  if (block_id) {
1309  iseq->arg_block = get_dyna_var_idx_at_raw(iseq, block_id);
1310  }
1311 
1312  if (iseq->arg_opts != 0 || iseq->arg_post_len != 0 ||
1313  iseq->arg_rest != -1 || iseq->arg_block != -1 ||
1314  iseq->arg_keyword != -1) {
1315  iseq->arg_simple = 0;
1316 
1317  /* set arg_size: size of arguments */
1318  if (iseq->arg_keyword != -1) {
1319  iseq->arg_size = iseq->arg_keyword + 1;
1320  }
1321  else if (iseq->arg_block != -1) {
1322  iseq->arg_size = iseq->arg_block + 1;
1323  }
1324  else if (iseq->arg_post_len) {
1325  iseq->arg_size = iseq->arg_post_start + iseq->arg_post_len;
1326  }
1327  else if (iseq->arg_rest != -1) {
1328  iseq->arg_size = iseq->arg_rest + 1;
1329  }
1330  else if (iseq->arg_opts) {
1331  iseq->arg_size = iseq->argc + iseq->arg_opts - 1;
1332  }
1333  else {
1334  iseq->arg_size = iseq->argc;
1335  }
1336  }
1337  else {
1338  iseq->arg_simple = 1;
1339  iseq->arg_size = iseq->argc;
1340  }
1341 
1342  if (iseq->type == ISEQ_TYPE_BLOCK) {
1343  if (iseq->arg_opts == 0 && iseq->arg_post_len == 0 &&
1344  iseq->arg_rest == -1 && iseq->arg_keyword == -1) {
1345  if (iseq->argc == 1 && last_comma == 0) {
1346  /* {|a|} */
1347  iseq->arg_simple |= 0x02;
1348  }
1349  }
1350  }
1351  }
1352  else {
1353  iseq->arg_simple = 1;
1354  }
1355 
1356  return COMPILE_OK;
1357 }
1358 
1359 static int
1361 {
1362  int size;
1363 
1364  if (tbl) {
1365  size = (int)*tbl;
1366  tbl++;
1367  }
1368  else {
1369  size = 0;
1370  }
1371 
1372  if (size > 0) {
1373  iseq->local_table = (ID *)ALLOC_N(ID, size);
1374  MEMCPY(iseq->local_table, tbl, ID, size);
1375  }
1376 
1377  iseq->local_size = iseq->local_table_size = size;
1378  iseq->local_size += 1;
1379  /*
1380  if (lfp == dfp ) { // top, class, method
1381  dfp[-1]: svar
1382  else { // block
1383  dfp[-1]: cref
1384  }
1385  */
1386 
1387  debugs("iseq_set_local_table: %d, %d\n", iseq->local_size, iseq->local_table_size);
1388  return COMPILE_OK;
1389 }
1390 
1391 static int
1393 {
1394  if (val == lit) return 0;
1395  if (SPECIAL_CONST_P(lit)) {
1396  return val != lit;
1397  }
1398  if (SPECIAL_CONST_P(val) || BUILTIN_TYPE(val) != BUILTIN_TYPE(lit)) {
1399  return -1;
1400  }
1401  if (BUILTIN_TYPE(lit) == T_STRING) {
1402  return rb_str_hash_cmp(lit, val);
1403  }
1404  return !rb_eql(lit, val);
1405 }
1406 
1407 static st_index_t
1409 {
1410  if (SPECIAL_CONST_P(a)) return (st_index_t)a;
1411  if (RB_TYPE_P(a, T_STRING)) return rb_str_hash(a);
1412  {
1413  VALUE hval = rb_hash(a);
1414  return (st_index_t)FIX2LONG(hval);
1415  }
1416 }
1417 
1418 static const struct st_hash_type cdhash_type = {
1419  cdhash_cmp,
1420  cdhash_hash,
1421 };
1422 
1425  int pos;
1426  int len;
1427 };
1428 
1429 static int
1431 {
1432  struct cdhash_set_label_struct *data = (struct cdhash_set_label_struct *)ptr;
1433  LABEL *lobj = (LABEL *)(val & ~1);
1434  rb_hash_aset(data->hash, key, INT2FIX(lobj->position - (data->pos+data->len)));
1435  return ST_CONTINUE;
1436 }
1437 
1441 static int
1443 {
1444  LABEL *lobj;
1445  INSN *iobj;
1446  struct iseq_line_info_entry *line_info_table;
1447  unsigned int last_line = 0;
1448  LINK_ELEMENT *list;
1449  VALUE *generated_iseq;
1450 
1451  int k, pos, sp, stack_max = 0, line = 0;
1452 
1453  /* set label position */
1454  list = FIRST_ELEMENT(anchor);
1455  k = pos = 0;
1456  while (list) {
1457  switch (list->type) {
1458  case ISEQ_ELEMENT_INSN:
1459  {
1460  iobj = (INSN *)list;
1461  line = iobj->line_no;
1462  pos += insn_data_length(iobj);
1463  k++;
1464  break;
1465  }
1466  case ISEQ_ELEMENT_LABEL:
1467  {
1468  lobj = (LABEL *)list;
1469  lobj->position = pos;
1470  lobj->set = TRUE;
1471  break;
1472  }
1473  case ISEQ_ELEMENT_NONE:
1474  {
1475  /* ignore */
1476  break;
1477  }
1478  case ISEQ_ELEMENT_ADJUST:
1479  {
1480  ADJUST *adjust = (ADJUST *)list;
1481  if (adjust->line_no != -1) {
1482  pos += 2 /* insn + 1 operand */;
1483  k++;
1484  }
1485  break;
1486  }
1487  default:
1489  dump_disasm_list(list);
1491  "error: set_sequence");
1492  break;
1493  }
1494  list = list->next;
1495  }
1496 
1497  /* make instruction sequence */
1498  generated_iseq = ALLOC_N(VALUE, pos);
1499  line_info_table = ALLOC_N(struct iseq_line_info_entry, k);
1500  iseq->is_entries = ALLOC_N(union iseq_inline_storage_entry, iseq->is_size);
1501  MEMZERO(iseq->is_entries, union iseq_inline_storage_entry, iseq->is_size);
1503  /* MEMZERO(iseq->callinfo_entries, rb_call_info_t, iseq->callinfo_size); */
1504 
1505  list = FIRST_ELEMENT(anchor);
1506  k = pos = sp = 0;
1507 
1508  while (list) {
1509  switch (list->type) {
1510  case ISEQ_ELEMENT_INSN:
1511  {
1512  int j, len, insn;
1513  const char *types;
1514  VALUE *operands;
1515 
1516  iobj = (INSN *)list;
1517 
1518  /* update sp */
1519  sp = calc_sp_depth(sp, iobj);
1520  if (sp > stack_max) {
1521  stack_max = sp;
1522  }
1523 
1524  /* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */
1525  operands = iobj->operands;
1526  insn = iobj->insn_id;
1527  generated_iseq[pos] = insn;
1528  types = insn_op_types(insn);
1529  len = insn_len(insn);
1530 
1531  /* operand check */
1532  if (iobj->operand_size != len - 1) {
1533  /* printf("operand size miss! (%d, %d)\n", iobj->operand_size, len); */
1534  dump_disasm_list(list);
1536  "operand size miss! (%d for %d)",
1537  iobj->operand_size, len - 1);
1538  xfree(generated_iseq);
1539  xfree(line_info_table);
1540  return 0;
1541  }
1542 
1543  for (j = 0; types[j]; j++) {
1544  char type = types[j];
1545  /* printf("--> [%c - (%d-%d)]\n", type, k, j); */
1546  switch (type) {
1547  case TS_OFFSET:
1548  {
1549  /* label(destination position) */
1550  lobj = (LABEL *)operands[j];
1551  if (!lobj->set) {
1553  "unknown label");
1554  }
1555  if (lobj->sp == -1) {
1556  lobj->sp = sp;
1557  }
1558  generated_iseq[pos + 1 + j] = lobj->position - (pos + len);
1559  break;
1560  }
1561  case TS_CDHASH:
1562  {
1563  VALUE map = operands[j];
1564  struct cdhash_set_label_struct data;
1565  data.hash = map;
1566  data.pos = pos;
1567  data.len = len;
1569 
1570  hide_obj(map);
1571  generated_iseq[pos + 1 + j] = map;
1572  break;
1573  }
1574  case TS_LINDEX:
1575  case TS_NUM: /* ulong */
1576  generated_iseq[pos + 1 + j] = FIX2INT(operands[j]);
1577  break;
1578  case TS_ISEQ: /* iseq */
1579  {
1580  VALUE v = operands[j];
1581  rb_iseq_t *block = 0;
1582  if (v) {
1583  GetISeqPtr(v, block);
1584  }
1585  generated_iseq[pos + 1 + j] = (VALUE)block;
1586  break;
1587  }
1588  case TS_VALUE: /* VALUE */
1589  {
1590  VALUE v = operands[j];
1591  generated_iseq[pos + 1 + j] = v;
1592  /* to mark ruby object */
1593  iseq_add_mark_object(iseq, v);
1594  break;
1595  }
1596  case TS_IC: /* inline cache */
1597  {
1598  int ic_index = FIX2INT(operands[j]);
1599  IC ic = (IC)&iseq->is_entries[ic_index];
1600  if (UNLIKELY(ic_index >= iseq->is_size)) {
1601  rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->is_size);
1602  }
1603  generated_iseq[pos + 1 + j] = (VALUE)ic;
1604  break;
1605  }
1606  case TS_CALLINFO: /* call info */
1607  {
1608  rb_call_info_t *base_ci = (rb_call_info_t *)operands[j];
1609  rb_call_info_t *ci = &iseq->callinfo_entries[base_ci->aux.index];
1610  *ci = *base_ci;
1611 
1612  if (UNLIKELY(base_ci->aux.index >= iseq->callinfo_size)) {
1613  rb_bug("iseq_set_sequence: ci_index overflow: index: %d, size: %d", base_ci->argc, iseq->callinfo_size);
1614  }
1615  generated_iseq[pos + 1 + j] = (VALUE)ci;
1616  break;
1617  }
1618  case TS_ID: /* ID */
1619  generated_iseq[pos + 1 + j] = SYM2ID(operands[j]);
1620  break;
1621  case TS_GENTRY:
1622  {
1623  struct rb_global_entry *entry =
1624  (struct rb_global_entry *)(operands[j] & (~1));
1625  generated_iseq[pos + 1 + j] = (VALUE)entry;
1626  }
1627  break;
1628  default:
1630  "unknown operand type: %c", type);
1631  xfree(generated_iseq);
1632  xfree(line_info_table);
1633  return 0;
1634  }
1635  }
1636  if (last_line != iobj->line_no) {
1637  line_info_table[k].line_no = last_line = iobj->line_no;
1638  line_info_table[k].position = pos;
1639  k++;
1640  }
1641  pos += len;
1642  break;
1643  }
1644  case ISEQ_ELEMENT_LABEL:
1645  {
1646  lobj = (LABEL *)list;
1647  if (lobj->sp == -1) {
1648  lobj->sp = sp;
1649  }
1650  else {
1651  sp = lobj->sp;
1652  }
1653  break;
1654  }
1655  case ISEQ_ELEMENT_ADJUST:
1656  {
1657  ADJUST *adjust = (ADJUST *)list;
1658  int orig_sp = sp;
1659 
1660  if (adjust->label) {
1661  sp = adjust->label->sp;
1662  }
1663  else {
1664  sp = 0;
1665  }
1666 
1667  if (adjust->line_no != -1) {
1668  if (orig_sp - sp > 0) {
1669  if (last_line != (unsigned int)adjust->line_no) {
1670  line_info_table[k].line_no = last_line = adjust->line_no;
1671  line_info_table[k].position = pos;
1672  k++;
1673  }
1674  generated_iseq[pos++] = BIN(adjuststack);
1675  generated_iseq[pos++] = orig_sp - sp;
1676  }
1677  else if (orig_sp - sp == 0) {
1678  /* jump to next insn */
1679  if (last_line != (unsigned int)adjust->line_no) {
1680  line_info_table[k].line_no = last_line = adjust->line_no;
1681  line_info_table[k].position = pos;
1682  k++;
1683  }
1684  generated_iseq[pos++] = BIN(jump);
1685  generated_iseq[pos++] = 0;
1686  }
1687  else {
1688  rb_bug("iseq_set_sequence: adjust bug");
1689  }
1690  }
1691  break;
1692  }
1693  default:
1694  /* ignore */
1695  break;
1696  }
1697  list = list->next;
1698  }
1699 
1700 #if 0 /* XXX */
1701  /* this check need dead code elimination */
1702  if (sp != 1) {
1703  rb_bug("SP is not 0 on %s (%d)\n", RSTRING_PTR(iseq->name), sp);
1704  }
1705 #endif
1706 
1707  iseq->iseq = (void *)generated_iseq;
1708  iseq->iseq_size = pos;
1709  iseq->stack_max = stack_max;
1710 
1711  line_info_table = ruby_xrealloc(line_info_table, k * sizeof(struct iseq_line_info_entry));
1712  iseq->line_info_table = line_info_table;
1713  iseq->line_info_size = k;
1714 
1715  return COMPILE_OK;
1716 }
1717 
1718 static int
1720 {
1721  return lobj->position;
1722 }
1723 
1724 static int
1726 {
1727  return lobj->sp;
1728 }
1729 
1730 static int
1732 {
1733  const VALUE *tptr, *ptr;
1734  int tlen, i;
1735  struct iseq_catch_table_entry *entry;
1736 
1737  tlen = (int)RARRAY_LEN(iseq->compile_data->catch_table_ary);
1739 
1740  iseq->catch_table = tlen ? ALLOC_N(struct iseq_catch_table_entry, tlen) : 0;
1741  iseq->catch_table_size = tlen;
1742 
1743  for (i = 0; i < tlen; i++) {
1744  ptr = RARRAY_CONST_PTR(tptr[i]);
1745  entry = &iseq->catch_table[i];
1746  entry->type = (enum catch_type)(ptr[0] & 0xffff);
1747  entry->start = label_get_position((LABEL *)(ptr[1] & ~1));
1748  entry->end = label_get_position((LABEL *)(ptr[2] & ~1));
1749  entry->iseq = ptr[3];
1750 
1751  /* register iseq as mark object */
1752  if (entry->iseq != 0) {
1753  iseq_add_mark_object(iseq, entry->iseq);
1754  }
1755 
1756  /* stack depth */
1757  if (ptr[4]) {
1758  LABEL *lobj = (LABEL *)(ptr[4] & ~1);
1759  entry->cont = label_get_position(lobj);
1760  entry->sp = label_get_sp(lobj);
1761 
1762  /* TODO: Dirty Hack! Fix me */
1763  if (entry->type == CATCH_TYPE_RESCUE ||
1764  entry->type == CATCH_TYPE_BREAK ||
1765  entry->type == CATCH_TYPE_NEXT) {
1766  entry->sp--;
1767  }
1768  }
1769  else {
1770  entry->cont = 0;
1771  }
1772  }
1773 
1774  RB_OBJ_WRITE(iseq->self, &iseq->compile_data->catch_table_ary, 0); /* free */
1775  return COMPILE_OK;
1776 }
1777 
1778 /*
1779  * set optional argument table
1780  * def foo(a, b=expr1, c=expr2)
1781  * =>
1782  * b:
1783  * expr1
1784  * c:
1785  * expr2
1786  */
1787 static int
1789 {
1790  int i;
1791 
1792  if (iseq->arg_opts != 0) {
1793  for (i = 0; i < iseq->arg_opts; i++) {
1794  iseq->arg_opt_table[i] =
1795  label_get_position((LABEL *)iseq->arg_opt_table[i]);
1796  }
1797  }
1798  return COMPILE_OK;
1799 }
1800 
1801 static LINK_ELEMENT *
1803 {
1804  LABEL *lobj = (LABEL *)OPERAND_AT(iobj, 0);
1805  LINK_ELEMENT *list;
1806 
1807  list = lobj->link.next;
1808  while (list) {
1809  if (list->type == ISEQ_ELEMENT_INSN || list->type == ISEQ_ELEMENT_ADJUST) {
1810  break;
1811  }
1812  list = list->next;
1813  }
1814  return list;
1815 }
1816 
1817 static LINK_ELEMENT *
1819 {
1820  LINK_ELEMENT *list = iobj->link.next;
1821 
1822  while (list) {
1823  if (list->type == ISEQ_ELEMENT_INSN || list->type == ISEQ_ELEMENT_ADJUST) {
1824  return list;
1825  }
1826  list = list->next;
1827  }
1828  return 0;
1829 }
1830 
1831 static LINK_ELEMENT *
1833 {
1834  LINK_ELEMENT *list = iobj->link.prev;
1835 
1836  while (list) {
1837  if (list->type == ISEQ_ELEMENT_INSN || list->type == ISEQ_ELEMENT_ADJUST) {
1838  return list;
1839  }
1840  list = list->prev;
1841  }
1842  return 0;
1843 }
1844 
1845 static int
1846 iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
1847 {
1848  INSN *iobj = (INSN *)list;
1849  again:
1850  if (iobj->insn_id == BIN(jump)) {
1851  INSN *niobj, *diobj, *piobj;
1852  /*
1853  * useless jump elimination:
1854  * jump LABEL1
1855  * ...
1856  * LABEL1:
1857  * jump LABEL2
1858  *
1859  * => in this case, first jump instruction should jump to
1860  * LABEL2 directly
1861  */
1862  diobj = (INSN *)get_destination_insn(iobj);
1863  niobj = (INSN *)get_next_insn(iobj);
1864 
1865  if (diobj == niobj) {
1866  /*
1867  * jump LABEL
1868  * LABEL:
1869  * =>
1870  * LABEL:
1871  */
1872  REMOVE_ELEM(&iobj->link);
1873  }
1874  else if (iobj != diobj && diobj->insn_id == BIN(jump)) {
1875  if (OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0)) {
1876  OPERAND_AT(iobj, 0) = OPERAND_AT(diobj, 0);
1877  goto again;
1878  }
1879  }
1880  else if (diobj->insn_id == BIN(leave)) {
1881  /*
1882  * jump LABEL
1883  * ...
1884  * LABEL:
1885  * leave
1886  * =>
1887  * leave
1888  * ...
1889  * LABEL:
1890  * leave
1891  */
1892  INSN *eiobj = new_insn_core(iseq, iobj->line_no, BIN(leave),
1893  diobj->operand_size, diobj->operands);
1894  INSN *popiobj = new_insn_core(iseq, iobj->line_no,
1895  BIN(pop), 0, 0);
1896  /* replace */
1897  REPLACE_ELEM((LINK_ELEMENT *)iobj, (LINK_ELEMENT *)eiobj);
1898  INSERT_ELEM_NEXT((LINK_ELEMENT *)eiobj, (LINK_ELEMENT *)popiobj);
1899  iobj = popiobj;
1900  }
1901  /*
1902  * useless jump elimination (if/unless destination):
1903  * if L1
1904  * jump L2
1905  * L1:
1906  * ...
1907  * L2:
1908  *
1909  * ==>
1910  * unless L2
1911  * L1:
1912  * ...
1913  * L2:
1914  */
1915  else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 &&
1916  (piobj->insn_id == BIN(branchif) ||
1917  piobj->insn_id == BIN(branchunless))) {
1918  if (niobj == (INSN *)get_destination_insn(piobj)) {
1919  piobj->insn_id = (piobj->insn_id == BIN(branchif))
1920  ? BIN(branchunless) : BIN(branchif);
1921  OPERAND_AT(piobj, 0) = OPERAND_AT(iobj, 0);
1922  REMOVE_ELEM(&iobj->link);
1923  }
1924  }
1925  }
1926 
1927  if (iobj->insn_id == BIN(branchif) ||
1928  iobj->insn_id == BIN(branchunless)) {
1929  /*
1930  * if L1
1931  * ...
1932  * L1:
1933  * jump L2
1934  * =>
1935  * if L2
1936  */
1937  INSN *nobj = (INSN *)get_destination_insn(iobj);
1938  if (nobj->insn_id == BIN(jump)) {
1939  OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0);
1940  }
1941  }
1942 
1943  if (do_tailcallopt && iobj->insn_id == BIN(leave)) {
1944  /*
1945  * send ...
1946  * leave
1947  * =>
1948  * send ..., ... | VM_CALL_TAILCALL, ...
1949  * leave # unreachable
1950  */
1951  INSN *piobj = (INSN *)get_prev_insn((INSN *)list);
1952  enum ruby_vminsn_type previ = piobj->insn_id;
1953 
1954  if (previ == BIN(send) || previ == BIN(opt_send_simple) || previ == BIN(invokesuper)) {
1955  rb_call_info_t *ci = (rb_call_info_t *)piobj->operands[0];
1956  if (ci->blockiseq == 0) {
1957  ci->flag |= VM_CALL_TAILCALL;
1958  }
1959  }
1960  }
1961  return COMPILE_OK;
1962 }
1963 
1964 static int
1966 {
1967  int old_opsize = iobj->operand_size;
1968  iobj->insn_id = insn_id;
1969  iobj->operand_size = insn_len(insn_id) - 1;
1970 
1971  if (iobj->operand_size > old_opsize) {
1972  VALUE *old_operands = iobj->operands;
1973  if (insn_id != BIN(opt_neq)) {
1974  rb_bug("insn_set_specialized_instruction: unknown insn: %d", insn_id);
1975  }
1976  iobj->operands = (VALUE *)compile_data_alloc(iseq, iobj->operand_size * sizeof(VALUE));
1977  iobj->operands[0] = old_operands[0];
1978  iobj->operands[1] = (VALUE)new_callinfo(iseq, idEq, 1, 0, 0);
1979  }
1980 
1981  return COMPILE_OK;
1982 }
1983 
1984 static int
1986 {
1987  if (iobj->insn_id == BIN(send)) {
1988  rb_call_info_t *ci = (rb_call_info_t *)OPERAND_AT(iobj, 0);
1989 
1990 #define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
1991  if (ci->blockiseq == 0 && (ci->flag & ~VM_CALL_ARGS_SKIP_SETUP) == 0) {
1992  switch (ci->orig_argc) {
1993  case 0:
1994  switch (ci->mid) {
1995  case idLength: SP_INSN(length); return COMPILE_OK;
1996  case idSize: SP_INSN(size); return COMPILE_OK;
1997  case idEmptyP: SP_INSN(empty_p);return COMPILE_OK;
1998  case idSucc: SP_INSN(succ); return COMPILE_OK;
1999  case idNot: SP_INSN(not); return COMPILE_OK;
2000  }
2001  break;
2002  case 1:
2003  switch (ci->mid) {
2004  case idPLUS: SP_INSN(plus); return COMPILE_OK;
2005  case idMINUS: SP_INSN(minus); return COMPILE_OK;
2006  case idMULT: SP_INSN(mult); return COMPILE_OK;
2007  case idDIV: SP_INSN(div); return COMPILE_OK;
2008  case idMOD: SP_INSN(mod); return COMPILE_OK;
2009  case idEq: SP_INSN(eq); return COMPILE_OK;
2010  case idNeq: SP_INSN(neq); return COMPILE_OK;
2011  case idLT: SP_INSN(lt); return COMPILE_OK;
2012  case idLE: SP_INSN(le); return COMPILE_OK;
2013  case idGT: SP_INSN(gt); return COMPILE_OK;
2014  case idGE: SP_INSN(ge); return COMPILE_OK;
2015  case idLTLT: SP_INSN(ltlt); return COMPILE_OK;
2016  case idAREF: SP_INSN(aref); return COMPILE_OK;
2017  }
2018  break;
2019  case 2:
2020  switch (ci->mid) {
2021  case idASET: SP_INSN(aset); return COMPILE_OK;
2022  }
2023  break;
2024  }
2025  }
2026  if (ci->flag & VM_CALL_ARGS_SKIP_SETUP) {
2027  iobj->insn_id = BIN(opt_send_simple);
2028  }
2029  }
2030 #undef SP_INSN
2031 
2032  return COMPILE_OK;
2033 }
2034 
2035 static int
2037 {
2038  LINK_ELEMENT *list;
2039  const int do_peepholeopt = iseq->compile_data->option->peephole_optimization;
2040  const int do_tailcallopt = iseq->compile_data->option->tailcall_optimization;
2041  const int do_si = iseq->compile_data->option->specialized_instruction;
2042  const int do_ou = iseq->compile_data->option->operands_unification;
2043  list = FIRST_ELEMENT(anchor);
2044 
2045  while (list) {
2046  if (list->type == ISEQ_ELEMENT_INSN) {
2047  if (do_peepholeopt) {
2048  iseq_peephole_optimize(iseq, list, do_tailcallopt);
2049  }
2050  if (do_si) {
2051  iseq_specialized_instruction(iseq, (INSN *)list);
2052  }
2053  if (do_ou) {
2054  insn_operands_unification((INSN *)list);
2055  }
2056  }
2057  list = list->next;
2058  }
2059  return COMPILE_OK;
2060 }
2061 
2062 #if OPT_INSTRUCTIONS_UNIFICATION
2063 static INSN *
2064 new_unified_insn(rb_iseq_t *iseq,
2065  int insn_id, int size, LINK_ELEMENT *seq_list)
2066 {
2067  INSN *iobj = 0;
2068  LINK_ELEMENT *list = seq_list;
2069  int i, argc = 0;
2070  VALUE *operands = 0, *ptr = 0;
2071 
2072 
2073  /* count argc */
2074  for (i = 0; i < size; i++) {
2075  iobj = (INSN *)list;
2076  argc += iobj->operand_size;
2077  list = list->next;
2078  }
2079 
2080  if (argc > 0) {
2081  ptr = operands =
2082  (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * argc);
2083  }
2084 
2085  /* copy operands */
2086  list = seq_list;
2087  for (i = 0; i < size; i++) {
2088  iobj = (INSN *)list;
2089  MEMCPY(ptr, iobj->operands, VALUE, iobj->operand_size);
2090  ptr += iobj->operand_size;
2091  list = list->next;
2092  }
2093 
2094  return new_insn_core(iseq, iobj->line_no, insn_id, argc, operands);
2095 }
2096 #endif
2097 
2098 /*
2099  * This scheme can get more performance if do this optimize with
2100  * label address resolving.
2101  * It's future work (if compile time was bottle neck).
2102  */
2103 static int
2105 {
2106 #if OPT_INSTRUCTIONS_UNIFICATION
2107  LINK_ELEMENT *list;
2108  INSN *iobj, *niobj;
2109  int id, k;
2110  intptr_t j;
2111 
2112  list = FIRST_ELEMENT(anchor);
2113  while (list) {
2114  if (list->type == ISEQ_ELEMENT_INSN) {
2115  iobj = (INSN *)list;
2116  id = iobj->insn_id;
2117  if (unified_insns_data[id] != 0) {
2118  const int *const *entry = unified_insns_data[id];
2119  for (j = 1; j < (intptr_t)entry[0]; j++) {
2120  const int *unified = entry[j];
2121  LINK_ELEMENT *li = list->next;
2122  for (k = 2; k < unified[1]; k++) {
2123  if (li->type != ISEQ_ELEMENT_INSN ||
2124  ((INSN *)li)->insn_id != unified[k]) {
2125  goto miss;
2126  }
2127  li = li->next;
2128  }
2129  /* matched */
2130  niobj =
2131  new_unified_insn(iseq, unified[0], unified[1] - 1,
2132  list);
2133 
2134  /* insert to list */
2135  niobj->link.prev = (LINK_ELEMENT *)iobj->link.prev;
2136  niobj->link.next = li;
2137  if (li) {
2138  li->prev = (LINK_ELEMENT *)niobj;
2139  }
2140 
2141  list->prev->next = (LINK_ELEMENT *)niobj;
2142  list = (LINK_ELEMENT *)niobj;
2143  break;
2144  miss:;
2145  }
2146  }
2147  }
2148  list = list->next;
2149  }
2150 #endif
2151  return COMPILE_OK;
2152 }
2153 
2154 #if OPT_STACK_CACHING
2155 
2156 #define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)]
2157 #define SC_NEXT(insn) sc_insn_next[(insn)]
2158 
2159 #include "opt_sc.inc"
2160 
2161 static int
2162 insn_set_sc_state(rb_iseq_t *iseq, INSN *iobj, int state)
2163 {
2164  int nstate;
2165  int insn_id;
2166 
2167  insn_id = iobj->insn_id;
2168  iobj->insn_id = SC_INSN(insn_id, state);
2169  nstate = SC_NEXT(iobj->insn_id);
2170 
2171  if (insn_id == BIN(jump) ||
2172  insn_id == BIN(branchif) || insn_id == BIN(branchunless)) {
2173  LABEL *lobj = (LABEL *)OPERAND_AT(iobj, 0);
2174 
2175  if (lobj->sc_state != 0) {
2176  if (lobj->sc_state != nstate) {
2177  dump_disasm_list((LINK_ELEMENT *)iobj);
2178  dump_disasm_list((LINK_ELEMENT *)lobj);
2179  printf("\n-- %d, %d\n", lobj->sc_state, nstate);
2181  "insn_set_sc_state error\n");
2182  return 0;
2183  }
2184  }
2185  else {
2186  lobj->sc_state = nstate;
2187  }
2188  if (insn_id == BIN(jump)) {
2189  nstate = SCS_XX;
2190  }
2191  }
2192  else if (insn_id == BIN(leave)) {
2193  nstate = SCS_XX;
2194  }
2195 
2196  return nstate;
2197 }
2198 
2199 static int
2200 label_set_sc_state(LABEL *lobj, int state)
2201 {
2202  if (lobj->sc_state != 0) {
2203  if (lobj->sc_state != state) {
2204  state = lobj->sc_state;
2205  }
2206  }
2207  else {
2208  lobj->sc_state = state;
2209  }
2210 
2211  return state;
2212 }
2213 
2214 
2215 #endif
2216 
2217 static int
2219 {
2220 #if OPT_STACK_CACHING
2221  LINK_ELEMENT *list;
2222  int state, insn_id;
2223 
2224  /* initialize */
2225  state = SCS_XX;
2226  list = FIRST_ELEMENT(anchor);
2227  /* dump_disasm_list(list); */
2228 
2229  /* for each list element */
2230  while (list) {
2231  redo_point:
2232  switch (list->type) {
2233  case ISEQ_ELEMENT_INSN:
2234  {
2235  INSN *iobj = (INSN *)list;
2236  insn_id = iobj->insn_id;
2237 
2238  /* dump_disasm_list(list); */
2239 
2240  switch (insn_id) {
2241  case BIN(nop):
2242  {
2243  /* exception merge point */
2244  if (state != SCS_AX) {
2245  INSN *rpobj =
2246  new_insn_body(iseq, 0, BIN(reput), 0);
2247 
2248  /* replace this insn */
2249  REPLACE_ELEM(list, (LINK_ELEMENT *)rpobj);
2250  list = (LINK_ELEMENT *)rpobj;
2251  goto redo_point;
2252  }
2253  break;
2254  }
2255  case BIN(swap):
2256  {
2257  if (state == SCS_AB || state == SCS_BA) {
2258  state = (state == SCS_AB ? SCS_BA : SCS_AB);
2259 
2260  REMOVE_ELEM(list);
2261  list = list->next;
2262  goto redo_point;
2263  }
2264  break;
2265  }
2266  case BIN(pop):
2267  {
2268  switch (state) {
2269  case SCS_AX:
2270  case SCS_BX:
2271  state = SCS_XX;
2272  break;
2273  case SCS_AB:
2274  state = SCS_AX;
2275  break;
2276  case SCS_BA:
2277  state = SCS_BX;
2278  break;
2279  case SCS_XX:
2280  goto normal_insn;
2281  default:
2283  "unreachable");
2284  }
2285  /* remove useless pop */
2286  REMOVE_ELEM(list);
2287  list = list->next;
2288  goto redo_point;
2289  }
2290  default:;
2291  /* none */
2292  } /* end of switch */
2293  normal_insn:
2294  state = insn_set_sc_state(iseq, iobj, state);
2295  break;
2296  }
2297  case ISEQ_ELEMENT_LABEL:
2298  {
2299  LABEL *lobj;
2300  lobj = (LABEL *)list;
2301 
2302  state = label_set_sc_state(lobj, state);
2303  }
2304  default:
2305  break;
2306  }
2307  list = list->next;
2308  }
2309 #endif
2310  return COMPILE_OK;
2311 }
2312 
2313 static int
2315 {
2316  NODE *list = node->nd_next;
2317  VALUE lit = node->nd_lit;
2318  int cnt = 0;
2319 
2320  debugp_param("nd_lit", lit);
2321  if (!NIL_P(lit)) {
2322  cnt++;
2323  if (RB_TYPE_P(lit, T_STRING))
2324  lit = node->nd_lit = rb_fstring(node->nd_lit);
2325  ADD_INSN1(ret, nd_line(node), putobject, lit);
2326  }
2327 
2328  while (list) {
2329  node = list->nd_head;
2330  if (nd_type(node) == NODE_STR) {
2331  node->nd_lit = rb_fstring(node->nd_lit);
2332  ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit);
2333  }
2334  else {
2335  COMPILE(ret, "each string", node);
2336  }
2337  cnt++;
2338  list = list->nd_next;
2339  }
2340  *cntp = cnt;
2341 
2342  return COMPILE_OK;
2343 }
2344 
2345 static int
2347 {
2348  int cnt;
2349  compile_dstr_fragments(iseq, ret, node, &cnt);
2350  ADD_INSN1(ret, nd_line(node), concatstrings, INT2FIX(cnt));
2351  return COMPILE_OK;
2352 }
2353 
2354 static int
2356 {
2357  int cnt;
2358  compile_dstr_fragments(iseq, ret, node, &cnt);
2359  ADD_INSN2(ret, nd_line(node), toregexp, INT2FIX(node->nd_cflag), INT2FIX(cnt));
2360  return COMPILE_OK;
2361 }
2362 
2363 static int
2365  LABEL *then_label, LABEL *else_label)
2366 {
2367  switch (nd_type(cond)) {
2368  case NODE_AND:
2369  {
2370  LABEL *label = NEW_LABEL(nd_line(cond));
2371  compile_branch_condition(iseq, ret, cond->nd_1st, label,
2372  else_label);
2373  ADD_LABEL(ret, label);
2374  compile_branch_condition(iseq, ret, cond->nd_2nd, then_label,
2375  else_label);
2376  break;
2377  }
2378  case NODE_OR:
2379  {
2380  LABEL *label = NEW_LABEL(nd_line(cond));
2381  compile_branch_condition(iseq, ret, cond->nd_1st, then_label,
2382  label);
2383  ADD_LABEL(ret, label);
2384  compile_branch_condition(iseq, ret, cond->nd_2nd, then_label,
2385  else_label);
2386  break;
2387  }
2388  case NODE_LIT: /* NODE_LIT is always not true */
2389  case NODE_TRUE:
2390  case NODE_STR:
2391  /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
2392  ADD_INSNL(ret, nd_line(cond), jump, then_label);
2393  break;
2394  case NODE_FALSE:
2395  case NODE_NIL:
2396  /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
2397  ADD_INSNL(ret, nd_line(cond), jump, else_label);
2398  break;
2399  default:
2400  COMPILE(ret, "branch condition", cond);
2401  ADD_INSNL(ret, nd_line(cond), branchunless, else_label);
2402  ADD_INSNL(ret, nd_line(cond), jump, then_label);
2403  break;
2404  }
2405  return COMPILE_OK;
2406 }
2407 
2412 };
2413 
2414 static int
2416  enum compile_array_type_t type, int poped)
2417 {
2418  NODE *node = node_root;
2419  int line = (int)nd_line(node);
2420  int len = 0;
2421 
2422  if (nd_type(node) == NODE_ZARRAY) {
2423  if (!poped) {
2424  switch (type) {
2425  case COMPILE_ARRAY_TYPE_ARRAY: ADD_INSN1(ret, line, newarray, INT2FIX(0)); break;
2426  case COMPILE_ARRAY_TYPE_HASH: ADD_INSN1(ret, line, newhash, INT2FIX(0)); break;
2427  case COMPILE_ARRAY_TYPE_ARGS: /* do nothing */ break;
2428  }
2429  }
2430  }
2431  else {
2432  int opt_p = 1;
2433  int first = 1, i;
2434 
2435  while (node) {
2436  NODE *start_node = node, *end_node;
2437  NODE *kw = 0;
2438  const int max = 0x100;
2439  DECL_ANCHOR(anchor);
2440  INIT_ANCHOR(anchor);
2441 
2442  for (i=0; i<max && node; i++, len++, node = node->nd_next) {
2443  if (CPDEBUG > 0 && nd_type(node) != NODE_ARRAY) {
2444  rb_bug("compile_array: This node is not NODE_ARRAY, but %s", ruby_node_name(nd_type(node)));
2445  }
2446 
2447  if (type == COMPILE_ARRAY_TYPE_HASH && !node->nd_head) {
2448  opt_p = 0;
2449  kw = node->nd_next;
2450  node = kw->nd_next;
2451  kw = kw->nd_head;
2452  break;
2453  }
2454  if (opt_p && nd_type(node->nd_head) != NODE_LIT) {
2455  opt_p = 0;
2456  }
2457 
2458  COMPILE_(anchor, "array element", node->nd_head, poped);
2459  }
2460 
2461  if (opt_p && type != COMPILE_ARRAY_TYPE_ARGS) {
2462  if (!poped) {
2463  VALUE ary = rb_ary_tmp_new(i);
2464 
2465  end_node = node;
2466  node = start_node;
2467 
2468  while (node != end_node) {
2469  rb_ary_push(ary, node->nd_head->nd_lit);
2470  node = node->nd_next;
2471  }
2472  while (node && nd_type(node->nd_head) == NODE_LIT &&
2473  node->nd_next && nd_type(node->nd_next->nd_head) == NODE_LIT) {
2474  rb_ary_push(ary, node->nd_head->nd_lit);
2475  node = node->nd_next;
2476  rb_ary_push(ary, node->nd_head->nd_lit);
2477  node = node->nd_next;
2478  len++;
2479  }
2480 
2481  OBJ_FREEZE(ary);
2482 
2484 
2485  if (first) {
2486  first = 0;
2487  if (type == COMPILE_ARRAY_TYPE_ARRAY) {
2488  ADD_INSN1(ret, line, duparray, ary);
2489  }
2490  else { /* COMPILE_ARRAY_TYPE_HASH */
2491  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
2492  ADD_INSN1(ret, line, putobject, ary);
2493  ADD_SEND(ret, line, ID2SYM(id_core_hash_from_ary), INT2FIX(1));
2494  }
2495  }
2496  else {
2497  if (type == COMPILE_ARRAY_TYPE_ARRAY) {
2498  ADD_INSN1(ret, line, putobject, ary);
2499  ADD_INSN(ret, line, concatarray);
2500  }
2501  else {
2502  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
2503  ADD_INSN1(ret, line, putobject, ary);
2504  ADD_SEND(ret, line, ID2SYM(id_core_hash_merge_ary), INT2FIX(1));
2505  }
2506  }
2507  }
2508  }
2509  else {
2510  if (!poped) {
2511  switch (type) {
2513  ADD_INSN1(anchor, line, newarray, INT2FIX(i));
2514 
2515  if (first) {
2516  first = 0;
2517  }
2518  else {
2519  ADD_INSN(anchor, line, concatarray);
2520  }
2521 
2522  APPEND_LIST(ret, anchor);
2523  break;
2525  if (i > 0) {
2526  if (first) {
2527  ADD_INSN1(anchor, line, newhash, INT2FIX(i));
2528  APPEND_LIST(ret, anchor);
2529  }
2530  else {
2531  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
2532  ADD_INSN(ret, line, swap);
2533  APPEND_LIST(ret, anchor);
2534  ADD_SEND(ret, line, ID2SYM(id_core_hash_merge_ptr), INT2FIX(i + 1));
2535  }
2536  }
2537  if (kw) {
2538  VALUE nhash = (i > 0 || !first) ? INT2FIX(2) : INT2FIX(1);
2539  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
2540  if (i > 0 || !first) ADD_INSN(ret, line, swap);
2541  COMPILE(ret, "keyword splat", kw);
2542  ADD_SEND(ret, line, ID2SYM(id_core_hash_merge_kwd), nhash);
2543  if (nhash == INT2FIX(1)) ADD_SEND(ret, line, ID2SYM(rb_intern("dup")), INT2FIX(0));
2544  }
2545  first = 0;
2546  break;
2548  APPEND_LIST(ret, anchor);
2549  break;
2550  }
2551  }
2552  else {
2553  /* poped */
2554  APPEND_LIST(ret, anchor);
2555  }
2556  }
2557  }
2558  }
2559  return len;
2560 }
2561 
2562 static VALUE
2564 {
2565  return compile_array_(iseq, ret, node_root, type, 0);
2566 }
2567 
2568 static VALUE
2570 {
2571  switch (nd_type(node)) {
2572  case NODE_LIT: {
2573  VALUE v = node->nd_lit;
2574  double ival;
2575  if (RB_TYPE_P(v, T_FLOAT) &&
2576  modf(RFLOAT_VALUE(v), &ival) == 0.0) {
2577  return FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival);
2578  }
2579  if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) {
2580  return v;
2581  }
2582  break;
2583  }
2584  case NODE_STR:
2585  return node->nd_lit = rb_fstring(node->nd_lit);
2586  }
2587  return Qundef;
2588 }
2589 
2590 static int
2591 when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, int only_special_literals, VALUE literals)
2592 {
2593  while (vals) {
2594  NODE* val = vals->nd_head;
2596 
2597  if (lit == Qundef) {
2598  only_special_literals = 0;
2599  }
2600  else {
2601  if (rb_hash_lookup(literals, lit) != Qnil) {
2602  rb_compile_warning(RSTRING_PTR(iseq->location.path), nd_line(val), "duplicated when clause is ignored");
2603  }
2604  else {
2605  rb_hash_aset(literals, lit, (VALUE)(l1) | 1);
2606  }
2607  }
2608 
2609  ADD_INSN(cond_seq, nd_line(val), dup); /* dup target */
2610 
2611  if (nd_type(val) == NODE_STR) {
2612  val->nd_lit = rb_fstring(val->nd_lit);
2613  debugp_param("nd_lit", val->nd_lit);
2614  ADD_INSN1(cond_seq, nd_line(val), putobject, val->nd_lit);
2615  }
2616  else {
2617  COMPILE(cond_seq, "when cond", val);
2618  }
2619 
2620  ADD_INSN1(cond_seq, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
2621  ADD_INSNL(cond_seq, nd_line(val), branchif, l1);
2622  vals = vals->nd_next;
2623  }
2624  return only_special_literals;
2625 }
2626 
2627 static int
2629 {
2630  switch (nd_type(node)) {
2631  case NODE_ATTRASGN: {
2632  INSN *iobj;
2633  rb_call_info_t *ci;
2634  VALUE dupidx;
2635 
2636  COMPILE_POPED(ret, "masgn lhs (NODE_ATTRASGN)", node);
2637 
2638  POP_ELEMENT(ret); /* pop pop insn */
2639  iobj = (INSN *)POP_ELEMENT(ret); /* pop send insn */
2640  ci = (rb_call_info_t *)iobj->operands[0];
2641  ci->orig_argc += 1; ci->argc = ci->orig_argc;
2642  dupidx = INT2FIX(ci->orig_argc);
2643 
2644  ADD_INSN1(ret, nd_line(node), topn, dupidx);
2645  ADD_ELEM(ret, (LINK_ELEMENT *)iobj);
2646  ADD_INSN(ret, nd_line(node), pop); /* result */
2647  ADD_INSN(ret, nd_line(node), pop); /* rhs */
2648  break;
2649  }
2650  case NODE_MASGN: {
2651  DECL_ANCHOR(anchor);
2652  INIT_ANCHOR(anchor);
2653  COMPILE_POPED(anchor, "nest masgn lhs", node);
2654  REMOVE_ELEM(FIRST_ELEMENT(anchor));
2655  ADD_SEQ(ret, anchor);
2656  break;
2657  }
2658  default: {
2659  DECL_ANCHOR(anchor);
2660  INIT_ANCHOR(anchor);
2661  COMPILE_POPED(anchor, "masgn lhs", node);
2662  REMOVE_ELEM(FIRST_ELEMENT(anchor));
2663  ADD_SEQ(ret, anchor);
2664  }
2665  }
2666 
2667  return COMPILE_OK;
2668 }
2669 
2670 static void
2672 {
2673  if (lhsn) {
2674  compile_massign_opt_lhs(iseq, ret, lhsn->nd_next);
2675  compile_massign_lhs(iseq, ret, lhsn->nd_head);
2676  }
2677 }
2678 
2679 static int
2681  NODE *rhsn, NODE *orig_lhsn)
2682 {
2683  VALUE mem[64];
2684  const int memsize = numberof(mem);
2685  int memindex = 0;
2686  int llen = 0, rlen = 0;
2687  int i;
2688  NODE *lhsn = orig_lhsn;
2689 
2690 #define MEMORY(v) { \
2691  int i; \
2692  if (memindex == memsize) return 0; \
2693  for (i=0; i<memindex; i++) { \
2694  if (mem[i] == (v)) return 0; \
2695  } \
2696  mem[memindex++] = (v); \
2697 }
2698 
2699  if (rhsn == 0 || nd_type(rhsn) != NODE_ARRAY) {
2700  return 0;
2701  }
2702 
2703  while (lhsn) {
2704  NODE *ln = lhsn->nd_head;
2705  switch (nd_type(ln)) {
2706  case NODE_LASGN:
2707  MEMORY(ln->nd_vid);
2708  break;
2709  case NODE_DASGN:
2710  case NODE_DASGN_CURR:
2711  case NODE_IASGN:
2712  case NODE_IASGN2:
2713  case NODE_CVASGN:
2714  MEMORY(ln->nd_vid);
2715  break;
2716  default:
2717  return 0;
2718  }
2719  lhsn = lhsn->nd_next;
2720  llen++;
2721  }
2722 
2723  while (rhsn) {
2724  if (llen <= rlen) {
2725  COMPILE_POPED(ret, "masgn val (popped)", rhsn->nd_head);
2726  }
2727  else {
2728  COMPILE(ret, "masgn val", rhsn->nd_head);
2729  }
2730  rhsn = rhsn->nd_next;
2731  rlen++;
2732  }
2733 
2734  if (llen > rlen) {
2735  for (i=0; i<llen-rlen; i++) {
2736  ADD_INSN(ret, nd_line(orig_lhsn), putnil);
2737  }
2738  }
2739 
2740  compile_massign_opt_lhs(iseq, ret, orig_lhsn);
2741  return 1;
2742 }
2743 
2744 static int
2745 compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int poped)
2746 {
2747  NODE *rhsn = node->nd_value;
2748  NODE *splatn = node->nd_args;
2749  NODE *lhsn = node->nd_head;
2750  int lhs_splat = (splatn && (VALUE)splatn != (VALUE)-1) ? 1 : 0;
2751 
2752  if (!poped || splatn || !compile_massign_opt(iseq, ret, rhsn, lhsn)) {
2753  int llen = 0;
2754  DECL_ANCHOR(lhsseq);
2755 
2756  INIT_ANCHOR(lhsseq);
2757 
2758  while (lhsn) {
2759  compile_massign_lhs(iseq, lhsseq, lhsn->nd_head);
2760  llen += 1;
2761  lhsn = lhsn->nd_next;
2762  }
2763 
2764  COMPILE(ret, "normal masgn rhs", rhsn);
2765 
2766  if (!poped) {
2767  ADD_INSN(ret, nd_line(node), dup);
2768  }
2769 
2770  ADD_INSN2(ret, nd_line(node), expandarray,
2771  INT2FIX(llen), INT2FIX(lhs_splat));
2772  ADD_SEQ(ret, lhsseq);
2773 
2774  if (lhs_splat) {
2775  if (nd_type(splatn) == NODE_POSTARG) {
2776  /*a, b, *r, p1, p2 */
2777  NODE *postn = splatn->nd_2nd;
2778  NODE *restn = splatn->nd_1st;
2779  int num = (int)postn->nd_alen;
2780  int flag = 0x02 | (((VALUE)restn == (VALUE)-1) ? 0x00 : 0x01);
2781 
2782  ADD_INSN2(ret, nd_line(splatn), expandarray,
2783  INT2FIX(num), INT2FIX(flag));
2784 
2785  if ((VALUE)restn != (VALUE)-1) {
2786  compile_massign_lhs(iseq, ret, restn);
2787  }
2788  while (postn) {
2789  compile_massign_lhs(iseq, ret, postn->nd_head);
2790  postn = postn->nd_next;
2791  }
2792  }
2793  else {
2794  /* a, b, *r */
2795  compile_massign_lhs(iseq, ret, splatn);
2796  }
2797  }
2798  }
2799  return COMPILE_OK;
2800 }
2801 
2802 static int
2804  LINK_ANCHOR *pref, LINK_ANCHOR *body)
2805 {
2806  switch (nd_type(node)) {
2807  case NODE_CONST:
2808  debugi("compile_colon2 - colon", node->nd_vid);
2809  ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_vid));
2810  break;
2811  case NODE_COLON3:
2812  debugi("compile_colon2 - colon3", node->nd_mid);
2813  ADD_INSN(body, nd_line(node), pop);
2814  ADD_INSN1(body, nd_line(node), putobject, rb_cObject);
2815  ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid));
2816  break;
2817  case NODE_COLON2:
2818  compile_colon2(iseq, node->nd_head, pref, body);
2819  debugi("compile_colon2 - colon2", node->nd_mid);
2820  ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid));
2821  break;
2822  default:
2823  COMPILE(pref, "const colon2 prefix", node);
2824  break;
2825  }
2826  return COMPILE_OK;
2827 }
2828 
2829 static VALUE
2831 {
2832  if (nd_type(cpath) == NODE_COLON3) {
2833  /* toplevel class ::Foo */
2834  ADD_INSN1(ret, nd_line(cpath), putobject, rb_cObject);
2835  return Qfalse;
2836  }
2837  else if (cpath->nd_head) {
2838  /* Bar::Foo */
2839  COMPILE(ret, "nd_else->nd_head", cpath->nd_head);
2840  return Qfalse;
2841  }
2842  else {
2843  /* class at cbase Foo */
2844  ADD_INSN1(ret, nd_line(cpath), putspecialobject,
2846  return Qtrue;
2847  }
2848 }
2849 
2850 #define defined_expr defined_expr0
2851 static int
2853  NODE *node, LABEL **lfinish, VALUE needstr)
2854 {
2855  enum defined_type expr_type = 0;
2856  enum node_type type;
2857 
2858  switch (type = nd_type(node)) {
2859 
2860  /* easy literals */
2861  case NODE_NIL:
2862  expr_type = DEFINED_NIL;
2863  break;
2864  case NODE_SELF:
2865  expr_type = DEFINED_SELF;
2866  break;
2867  case NODE_TRUE:
2868  expr_type = DEFINED_TRUE;
2869  break;
2870  case NODE_FALSE:
2871  expr_type = DEFINED_FALSE;
2872  break;
2873 
2874  case NODE_ARRAY:{
2875  NODE *vals = node;
2876 
2877  do {
2878  defined_expr(iseq, ret, vals->nd_head, lfinish, Qfalse);
2879 
2880  if (!lfinish[1]) {
2881  lfinish[1] = NEW_LABEL(nd_line(node));
2882  }
2883  ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
2884  } while ((vals = vals->nd_next) != NULL);
2885  }
2886  case NODE_STR:
2887  case NODE_LIT:
2888  case NODE_ZARRAY:
2889  case NODE_AND:
2890  case NODE_OR:
2891  default:
2892  expr_type = DEFINED_EXPR;
2893  break;
2894 
2895  /* variables */
2896  case NODE_LVAR:
2897  case NODE_DVAR:
2898  expr_type = DEFINED_LVAR;
2899  break;
2900 
2901  case NODE_IVAR:
2902  ADD_INSN(ret, nd_line(node), putnil);
2903  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_IVAR),
2904  ID2SYM(node->nd_vid), needstr);
2905  return 1;
2906 
2907  case NODE_GVAR:
2908  ADD_INSN(ret, nd_line(node), putnil);
2909  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_GVAR),
2910  ID2SYM(node->nd_entry->id), needstr);
2911  return 1;
2912 
2913  case NODE_CVAR:
2914  ADD_INSN(ret, nd_line(node), putnil);
2915  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CVAR),
2916  ID2SYM(node->nd_vid), needstr);
2917  return 1;
2918 
2919  case NODE_CONST:
2920  ADD_INSN(ret, nd_line(node), putnil);
2921  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CONST),
2922  ID2SYM(node->nd_vid), needstr);
2923  return 1;
2924  case NODE_COLON2:
2925  if (!lfinish[1]) {
2926  lfinish[1] = NEW_LABEL(nd_line(node));
2927  }
2928  defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
2929  ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
2930 
2931  if (rb_is_const_id(node->nd_mid)) {
2932  COMPILE(ret, "defined/colon2#nd_head", node->nd_head);
2933  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CONST),
2934  ID2SYM(node->nd_mid), needstr);
2935  }
2936  else {
2937  COMPILE(ret, "defined/colon2#nd_head", node->nd_head);
2938  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_METHOD),
2939  ID2SYM(node->nd_mid), needstr);
2940  }
2941  return 1;
2942  case NODE_COLON3:
2943  ADD_INSN1(ret, nd_line(node), putobject, rb_cObject);
2944  ADD_INSN3(ret, nd_line(node), defined,
2945  INT2FIX(DEFINED_CONST), ID2SYM(node->nd_mid), needstr);
2946  return 1;
2947 
2948  /* method dispatch */
2949  case NODE_CALL:
2950  case NODE_VCALL:
2951  case NODE_FCALL:
2952  case NODE_ATTRASGN:{
2953  int self = TRUE;
2954 
2955  switch (type) {
2956  case NODE_ATTRASGN:
2957  if (node->nd_recv == (NODE *)1) break;
2958  case NODE_CALL:
2959  self = FALSE;
2960  break;
2961  default:
2962  /* through */;
2963  }
2964  if (!lfinish[1]) {
2965  lfinish[1] = NEW_LABEL(nd_line(node));
2966  }
2967  if (node->nd_args) {
2968  defined_expr(iseq, ret, node->nd_args, lfinish, Qfalse);
2969  ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
2970  }
2971  if (!self) {
2972  defined_expr(iseq, ret, node->nd_recv, lfinish, Qfalse);
2973  ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
2974  COMPILE(ret, "defined/recv", node->nd_recv);
2975  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_METHOD),
2976  ID2SYM(node->nd_mid), needstr);
2977  }
2978  else {
2979  ADD_INSN(ret, nd_line(node), putself);
2980  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_FUNC),
2981  ID2SYM(node->nd_mid), needstr);
2982  }
2983  return 1;
2984  }
2985 
2986  case NODE_YIELD:
2987  ADD_INSN(ret, nd_line(node), putnil);
2988  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_YIELD), 0,
2989  needstr);
2990  return 1;
2991 
2992  case NODE_BACK_REF:
2993  case NODE_NTH_REF:
2994  ADD_INSN(ret, nd_line(node), putnil);
2995  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_REF),
2996  INT2FIX((node->nd_nth << 1) | (type == NODE_BACK_REF)),
2997  needstr);
2998  return 1;
2999 
3000  case NODE_SUPER:
3001  case NODE_ZSUPER:
3002  ADD_INSN(ret, nd_line(node), putnil);
3003  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_ZSUPER), 0,
3004  needstr);
3005  return 1;
3006 
3007  case NODE_OP_ASGN1:
3008  case NODE_OP_ASGN2:
3009  case NODE_OP_ASGN_OR:
3010  case NODE_OP_ASGN_AND:
3011  case NODE_MASGN:
3012  case NODE_LASGN:
3013  case NODE_DASGN:
3014  case NODE_DASGN_CURR:
3015  case NODE_GASGN:
3016  case NODE_IASGN:
3017  case NODE_CDECL:
3018  case NODE_CVDECL:
3019  case NODE_CVASGN:
3020  expr_type = DEFINED_ASGN;
3021  break;
3022  }
3023 
3024  if (expr_type) {
3025  if (needstr != Qfalse) {
3026  VALUE str = rb_iseq_defined_string(expr_type);
3027  ADD_INSN1(ret, nd_line(node), putobject, str);
3028  }
3029  else {
3030  ADD_INSN1(ret, nd_line(node), putobject, Qtrue);
3031  }
3032  return 1;
3033  }
3034  return 0;
3035 }
3036 #undef defined_expr
3037 
3038 static int
3040  NODE *node, LABEL **lfinish, VALUE needstr)
3041 {
3042  LINK_ELEMENT *lcur = ret->last;
3043  int done = defined_expr0(iseq, ret, node, lfinish, needstr);
3044  if (lfinish[1]) {
3045  int line = nd_line(node);
3046  LABEL *lstart = NEW_LABEL(line);
3047  LABEL *lend = NEW_LABEL(line);
3048  VALUE rescue = NEW_CHILD_ISEQVAL(NEW_NIL(),
3050  ("defined guard in "),
3051  iseq->location.label),
3052  ISEQ_TYPE_DEFINED_GUARD, 0);
3053  APPEND_LABEL(ret, lcur, lstart);
3054  ADD_LABEL(ret, lend);
3055  ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]);
3056  }
3057  return done;
3058 }
3059 
3060 #define BUFSIZE 0x100
3061 
3062 static VALUE
3064 {
3065  int level = 1;
3066  rb_iseq_t *ip = iseq;
3067 
3068  if (iseq->parent_iseq != 0) {
3069  while (ip->local_iseq != ip) {
3070  if (ip->type == ISEQ_TYPE_BLOCK) {
3071  level++;
3072  }
3073  ip = ip->parent_iseq;
3074  }
3075  }
3076 
3077  if (level == 1) {
3078  return rb_sprintf("block in %"PRIsVALUE, ip->location.label);
3079  }
3080  else {
3081  return rb_sprintf("block (%d levels) in %"PRIsVALUE, level, ip->location.label);
3082  }
3083 }
3084 
3085 static void
3088  struct ensure_range *er, NODE *node)
3089 {
3090  enl->ensure_node = node;
3091  enl->prev = iseq->compile_data->ensure_node_stack; /* prev */
3092  enl->erange = er;
3093  iseq->compile_data->ensure_node_stack = enl;
3094 }
3095 
3096 static void
3098  LABEL *lstart, LABEL *lend)
3099 {
3100  struct ensure_range *ne =
3101  compile_data_alloc(iseq, sizeof(struct ensure_range));
3102 
3103  while (erange->next != 0) {
3104  erange = erange->next;
3105  }
3106  ne->next = 0;
3107  ne->begin = lend;
3108  ne->end = erange->end;
3109  erange->end = lstart;
3110 
3111  erange->next = ne;
3112 }
3113 
3114 static void
3115 add_ensure_iseq(LINK_ANCHOR *ret, rb_iseq_t *iseq, int is_return)
3116 {
3119  struct iseq_compile_data_ensure_node_stack *prev_enlp = enlp;
3120  DECL_ANCHOR(ensure);
3121 
3122  INIT_ANCHOR(ensure);
3123  while (enlp) {
3124  if (enlp->erange != 0) {
3125  DECL_ANCHOR(ensure_part);
3126  LABEL *lstart = NEW_LABEL(0);
3127  LABEL *lend = NEW_LABEL(0);
3128  INIT_ANCHOR(ensure_part);
3129 
3130  add_ensure_range(iseq, enlp->erange, lstart, lend);
3131 
3132  iseq->compile_data->ensure_node_stack = enlp->prev;
3133  ADD_LABEL(ensure_part, lstart);
3134  COMPILE_POPED(ensure_part, "ensure part", enlp->ensure_node);
3135  ADD_LABEL(ensure_part, lend);
3136  ADD_SEQ(ensure, ensure_part);
3137  }
3138  else {
3139  if (!is_return) {
3140  break;
3141  }
3142  }
3143  enlp = enlp->prev;
3144  }
3145  iseq->compile_data->ensure_node_stack = prev_enlp;
3146  ADD_SEQ(ret, ensure);
3147 }
3148 
3149 static VALUE
3151 {
3152  VALUE argc = INT2FIX(0);
3153  int nsplat = 0;
3154  DECL_ANCHOR(arg_block);
3155  DECL_ANCHOR(args_splat);
3156 
3157  INIT_ANCHOR(arg_block);
3158  INIT_ANCHOR(args_splat);
3159  if (argn && nd_type(argn) == NODE_BLOCK_PASS) {
3160  COMPILE(arg_block, "block", argn->nd_body);
3161  *flag |= VM_CALL_ARGS_BLOCKARG;
3162  argn = argn->nd_head;
3163  }
3164 
3165  setup_argn:
3166  if (argn) {
3167  switch (nd_type(argn)) {
3168  case NODE_SPLAT: {
3169  COMPILE(args, "args (splat)", argn->nd_head);
3170  argc = INT2FIX(1);
3171  nsplat++;
3172  *flag |= VM_CALL_ARGS_SPLAT;
3173  break;
3174  }
3175  case NODE_ARGSCAT:
3176  case NODE_ARGSPUSH: {
3177  int next_is_array = (nd_type(argn->nd_head) == NODE_ARRAY);
3178  DECL_ANCHOR(tmp);
3179 
3180  INIT_ANCHOR(tmp);
3181  COMPILE(tmp, "args (cat: splat)", argn->nd_body);
3182  if (next_is_array && nsplat == 0) {
3183  /* none */
3184  }
3185  else {
3186  if (nd_type(argn) == NODE_ARGSCAT) {
3187  ADD_INSN1(tmp, nd_line(argn), splatarray, Qfalse);
3188  }
3189  else {
3190  ADD_INSN1(tmp, nd_line(argn), newarray, INT2FIX(1));
3191  }
3192  }
3193  INSERT_LIST(args_splat, tmp);
3194  nsplat++;
3195  *flag |= VM_CALL_ARGS_SPLAT;
3196 
3197  if (next_is_array) {
3198  argc = INT2FIX(compile_array(iseq, args, argn->nd_head, COMPILE_ARRAY_TYPE_ARGS) + 1);
3199  }
3200  else {
3201  argn = argn->nd_head;
3202  goto setup_argn;
3203  }
3204  break;
3205  }
3206  case NODE_ARRAY: {
3207  argc = INT2FIX(compile_array(iseq, args, argn, COMPILE_ARRAY_TYPE_ARGS));
3208  break;
3209  }
3210  default: {
3211  rb_bug("setup_arg: unknown node: %s\n", ruby_node_name(nd_type(argn)));
3212  }
3213  }
3214  }
3215 
3216  if (nsplat > 1) {
3217  int i;
3218  for (i=1; i<nsplat; i++) {
3219  ADD_INSN(args_splat, nd_line(args), concatarray);
3220  }
3221  }
3222 
3223  if (!LIST_SIZE_ZERO(args_splat)) {
3224  ADD_SEQ(args, args_splat);
3225  }
3226 
3227  if (*flag & VM_CALL_ARGS_BLOCKARG) {
3228  ADD_SEQ(args, arg_block);
3229  }
3230  return argc;
3231 }
3232 
3233 static VALUE
3235 {
3236  int line = nd_line(body);
3237  VALUE argc = INT2FIX(0);
3238  VALUE block = NEW_CHILD_ISEQVAL(body, make_name_for_block(iseq->parent_iseq), ISEQ_TYPE_BLOCK, line);
3239  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
3240  ADD_CALL_WITH_BLOCK(ret, line, ID2SYM(id_core_set_postexe), argc, block);
3241  iseq_set_local_table(iseq, 0);
3242  return Qnil;
3243 }
3244 
3252 static int
3253 iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
3254 {
3255  enum node_type type;
3256  LINK_ELEMENT *saved_last_element = 0;
3257  int line;
3258 
3259  if (node == 0) {
3260  if (!poped) {
3261  debugs("node: NODE_NIL(implicit)\n");
3262  ADD_INSN(ret, iseq->compile_data->last_line, putnil);
3263  }
3264  return COMPILE_OK;
3265  }
3266 
3267  iseq->compile_data->last_line = line = (int)nd_line(node);
3268  debug_node_start(node);
3269 
3270  type = nd_type(node);
3271 
3272  if (node->flags & NODE_FL_NEWLINE) {
3273  ADD_TRACE(ret, line, RUBY_EVENT_LINE);
3274  saved_last_element = ret->last;
3275  }
3276 
3277  switch (type) {
3278  case NODE_BLOCK:{
3279  while (node && nd_type(node) == NODE_BLOCK) {
3280  COMPILE_(ret, "BLOCK body", node->nd_head,
3281  (node->nd_next == 0 && poped == 0) ? 0 : 1);
3282  node = node->nd_next;
3283  }
3284  if (node) {
3285  COMPILE_(ret, "BLOCK next", node->nd_next, poped);
3286  }
3287  break;
3288  }
3289  case NODE_IF:{
3290  DECL_ANCHOR(cond_seq);
3291  DECL_ANCHOR(then_seq);
3292  DECL_ANCHOR(else_seq);
3293  LABEL *then_label, *else_label, *end_label;
3294 
3295  INIT_ANCHOR(cond_seq);
3296  INIT_ANCHOR(then_seq);
3297  INIT_ANCHOR(else_seq);
3298  then_label = NEW_LABEL(line);
3299  else_label = NEW_LABEL(line);
3300  end_label = NEW_LABEL(line);
3301 
3302  compile_branch_condition(iseq, cond_seq, node->nd_cond,
3303  then_label, else_label);
3304  COMPILE_(then_seq, "then", node->nd_body, poped);
3305  COMPILE_(else_seq, "else", node->nd_else, poped);
3306 
3307  ADD_SEQ(ret, cond_seq);
3308 
3309  ADD_LABEL(ret, then_label);
3310  ADD_SEQ(ret, then_seq);
3311  ADD_INSNL(ret, line, jump, end_label);
3312 
3313  ADD_LABEL(ret, else_label);
3314  ADD_SEQ(ret, else_seq);
3315 
3316  ADD_LABEL(ret, end_label);
3317 
3318  break;
3319  }
3320  case NODE_CASE:{
3321  NODE *vals;
3322  NODE *tempnode = node;
3323  LABEL *endlabel, *elselabel;
3324  DECL_ANCHOR(head);
3325  DECL_ANCHOR(body_seq);
3326  DECL_ANCHOR(cond_seq);
3327  int only_special_literals = 1;
3328  VALUE literals = rb_hash_new();
3329 
3330  INIT_ANCHOR(head);
3331  INIT_ANCHOR(body_seq);
3332  INIT_ANCHOR(cond_seq);
3333 
3334  rb_hash_tbl_raw(literals)->type = &cdhash_type;
3335 
3336  if (node->nd_head == 0) {
3337  COMPILE_(ret, "when", node->nd_body, poped);
3338  break;
3339  }
3340  COMPILE(head, "case base", node->nd_head);
3341 
3342  node = node->nd_body;
3343  type = nd_type(node);
3344  line = nd_line(node);
3345 
3346  if (type != NODE_WHEN) {
3347  COMPILE_ERROR((ERROR_ARGS "NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type)));
3348  }
3349 
3350  endlabel = NEW_LABEL(line);
3351  elselabel = NEW_LABEL(line);
3352 
3353  ADD_SEQ(ret, head); /* case VAL */
3354 
3355  while (type == NODE_WHEN) {
3356  LABEL *l1;
3357 
3358  l1 = NEW_LABEL(line);
3359  ADD_LABEL(body_seq, l1);
3360  ADD_INSN(body_seq, line, pop);
3361  COMPILE_(body_seq, "when body", node->nd_body, poped);
3362  ADD_INSNL(body_seq, line, jump, endlabel);
3363 
3364  vals = node->nd_head;
3365  if (vals) {
3366  switch (nd_type(vals)) {
3367  case NODE_ARRAY:
3368  only_special_literals = when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals);
3369  break;
3370  case NODE_SPLAT:
3371  case NODE_ARGSCAT:
3372  case NODE_ARGSPUSH:
3373  only_special_literals = 0;
3374  ADD_INSN (cond_seq, nd_line(vals), dup);
3375  COMPILE(cond_seq, "when/cond splat", vals);
3376  ADD_INSN1(cond_seq, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
3377  ADD_INSNL(cond_seq, nd_line(vals), branchif, l1);
3378  break;
3379  default:
3380  rb_bug("NODE_CASE: unknown node (%s)",
3381  ruby_node_name(nd_type(vals)));
3382  }
3383  }
3384  else {
3385  rb_bug("NODE_CASE: must be NODE_ARRAY, but 0");
3386  }
3387 
3388  node = node->nd_next;
3389  if (!node) {
3390  break;
3391  }
3392  type = nd_type(node);
3393  line = nd_line(node);
3394  }
3395  /* else */
3396  if (node) {
3397  ADD_LABEL(cond_seq, elselabel);
3398  ADD_INSN(cond_seq, line, pop);
3399  COMPILE_(cond_seq, "else", node, poped);
3400  ADD_INSNL(cond_seq, line, jump, endlabel);
3401  }
3402  else {
3403  debugs("== else (implicit)\n");
3404  ADD_LABEL(cond_seq, elselabel);
3405  ADD_INSN(cond_seq, nd_line(tempnode), pop);
3406  if (!poped) {
3407  ADD_INSN(cond_seq, nd_line(tempnode), putnil);
3408  }
3409  ADD_INSNL(cond_seq, nd_line(tempnode), jump, endlabel);
3410  }
3411 
3412  if (only_special_literals) {
3413  iseq_add_mark_object(iseq, literals);
3414 
3415  ADD_INSN(ret, nd_line(tempnode), dup);
3416  ADD_INSN2(ret, nd_line(tempnode), opt_case_dispatch, literals, elselabel);
3417  }
3418 
3419  ADD_SEQ(ret, cond_seq);
3420  ADD_SEQ(ret, body_seq);
3421  ADD_LABEL(ret, endlabel);
3422  break;
3423  }
3424  case NODE_WHEN:{
3425  NODE *vals;
3426  NODE *val;
3427  NODE *orig_node = node;
3428  LABEL *endlabel;
3429  DECL_ANCHOR(body_seq);
3430 
3431  INIT_ANCHOR(body_seq);
3432  endlabel = NEW_LABEL(line);
3433 
3434  while (node && nd_type(node) == NODE_WHEN) {
3435  LABEL *l1 = NEW_LABEL(line = nd_line(node));
3436  ADD_LABEL(body_seq, l1);
3437  COMPILE_(body_seq, "when", node->nd_body, poped);
3438  ADD_INSNL(body_seq, line, jump, endlabel);
3439 
3440  vals = node->nd_head;
3441  if (!vals) {
3442  rb_bug("NODE_WHEN: must be NODE_ARRAY, but 0");
3443  }
3444  switch (nd_type(vals)) {
3445  case NODE_ARRAY:
3446  while (vals) {
3447  val = vals->nd_head;
3448  COMPILE(ret, "when2", val);
3449  ADD_INSNL(ret, nd_line(val), branchif, l1);
3450  vals = vals->nd_next;
3451  }
3452  break;
3453  case NODE_SPLAT:
3454  case NODE_ARGSCAT:
3455  case NODE_ARGSPUSH:
3456  ADD_INSN(ret, nd_line(vals), putnil);
3457  COMPILE(ret, "when2/cond splat", vals);
3459  ADD_INSNL(ret, nd_line(vals), branchif, l1);
3460  break;
3461  default:
3462  rb_bug("NODE_WHEN: unknown node (%s)",
3463  ruby_node_name(nd_type(vals)));
3464  }
3465  node = node->nd_next;
3466  }
3467  /* else */
3468  COMPILE_(ret, "else", node, poped);
3469  ADD_INSNL(ret, nd_line(orig_node), jump, endlabel);
3470 
3471  ADD_SEQ(ret, body_seq);
3472  ADD_LABEL(ret, endlabel);
3473 
3474  break;
3475  }
3476  case NODE_OPT_N:
3477  case NODE_WHILE:
3478  case NODE_UNTIL:{
3479  LABEL *prev_start_label = iseq->compile_data->start_label;
3480  LABEL *prev_end_label = iseq->compile_data->end_label;
3481  LABEL *prev_redo_label = iseq->compile_data->redo_label;
3482  int prev_loopval_popped = iseq->compile_data->loopval_popped;
3483 
3485 
3486  LABEL *next_label = iseq->compile_data->start_label = NEW_LABEL(line); /* next */
3487  LABEL *redo_label = iseq->compile_data->redo_label = NEW_LABEL(line); /* redo */
3488  LABEL *break_label = iseq->compile_data->end_label = NEW_LABEL(line); /* break */
3489  LABEL *end_label = NEW_LABEL(line);
3490 
3491  LABEL *next_catch_label = NEW_LABEL(line);
3492  LABEL *tmp_label = NULL;
3493 
3494  iseq->compile_data->loopval_popped = 0;
3495  push_ensure_entry(iseq, &enl, 0, 0);
3496 
3497  if (type == NODE_OPT_N || node->nd_state == 1) {
3498  ADD_INSNL(ret, line, jump, next_label);
3499  }
3500  else {
3501  tmp_label = NEW_LABEL(line);
3502  ADD_INSNL(ret, line, jump, tmp_label);
3503  }
3504  ADD_INSN(ret, line, putnil);
3505  ADD_LABEL(ret, next_catch_label);
3506  ADD_INSN(ret, line, pop);
3507  ADD_INSNL(ret, line, jump, next_label);
3508  if (tmp_label) ADD_LABEL(ret, tmp_label);
3509 
3510  ADD_LABEL(ret, redo_label);
3511  COMPILE_POPED(ret, "while body", node->nd_body);
3512  ADD_LABEL(ret, next_label); /* next */
3513 
3514  if (type == NODE_WHILE) {
3515  compile_branch_condition(iseq, ret, node->nd_cond,
3516  redo_label, end_label);
3517  }
3518  else if (type == NODE_UNTIL) {
3519  /* until */
3520  compile_branch_condition(iseq, ret, node->nd_cond,
3521  end_label, redo_label);
3522  }
3523  else {
3524  ADD_CALL_RECEIVER(ret, line);
3525  ADD_CALL(ret, line, ID2SYM(idGets), INT2FIX(0));
3526  ADD_INSNL(ret, line, branchif, redo_label);
3527  /* opt_n */
3528  }
3529 
3530  ADD_LABEL(ret, end_label);
3531 
3532  if (node->nd_state == Qundef) {
3533  /* ADD_INSN(ret, line, putundef); */
3534  rb_bug("unsupported: putundef");
3535  }
3536  else {
3537  ADD_INSN(ret, line, putnil);
3538  }
3539 
3540  ADD_LABEL(ret, break_label); /* break */
3541 
3542  if (poped) {
3543  ADD_INSN(ret, line, pop);
3544  }
3545 
3546  ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label,
3547  0, break_label);
3548  ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, redo_label, break_label, 0,
3549  next_catch_label);
3550  ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label, 0,
3551  iseq->compile_data->redo_label);
3552 
3553  iseq->compile_data->start_label = prev_start_label;
3554  iseq->compile_data->end_label = prev_end_label;
3555  iseq->compile_data->redo_label = prev_redo_label;
3556  iseq->compile_data->loopval_popped = prev_loopval_popped;
3558  break;
3559  }
3560  case NODE_ITER:
3561  case NODE_FOR:{
3562  VALUE prevblock = iseq->compile_data->current_block;
3563  LABEL *retry_label = NEW_LABEL(line);
3564  LABEL *retry_end_l = NEW_LABEL(line);
3565 
3566  ADD_LABEL(ret, retry_label);
3567  if (nd_type(node) == NODE_FOR) {
3568  COMPILE(ret, "iter caller (for)", node->nd_iter);
3569 
3570  iseq->compile_data->current_block =
3571  NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq),
3572  ISEQ_TYPE_BLOCK, line);
3573 
3574  ADD_SEND_R(ret, line, ID2SYM(idEach), INT2FIX(0),
3575  iseq->compile_data->current_block, INT2FIX(0));
3576  }
3577  else {
3578  iseq->compile_data->current_block =
3579  NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq),
3580  ISEQ_TYPE_BLOCK, line);
3581  COMPILE(ret, "iter caller", node->nd_iter);
3582  }
3583  ADD_LABEL(ret, retry_end_l);
3584 
3585  if (poped) {
3586  ADD_INSN(ret, line, pop);
3587  }
3588 
3589  iseq->compile_data->current_block = prevblock;
3590 
3591  ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, 0, retry_end_l);
3592 
3593  break;
3594  }
3595  case NODE_BREAK:{
3596  unsigned long level = 0;
3597 
3598  if (iseq->compile_data->redo_label != 0) {
3599  /* while/until */
3600  LABEL *splabel = NEW_LABEL(0);
3601  ADD_LABEL(ret, splabel);
3602  ADD_ADJUST(ret, line, iseq->compile_data->redo_label);
3603  COMPILE_(ret, "break val (while/until)", node->nd_stts, iseq->compile_data->loopval_popped);
3604  add_ensure_iseq(ret, iseq, 0);
3605  ADD_INSNL(ret, line, jump, iseq->compile_data->end_label);
3606  ADD_ADJUST_RESTORE(ret, splabel);
3607 
3608  if (!poped) {
3609  ADD_INSN(ret, line, putnil);
3610  }
3611  }
3612  else if (iseq->type == ISEQ_TYPE_BLOCK) {
3613  break_by_insn:
3614  /* escape from block */
3615  COMPILE(ret, "break val (block)", node->nd_stts);
3616  ADD_INSN1(ret, line, throw, INT2FIX(level | 0x02) /* TAG_BREAK */ );
3617  if (poped) {
3618  ADD_INSN(ret, line, pop);
3619  }
3620  }
3621  else if (iseq->type == ISEQ_TYPE_EVAL) {
3622  break_in_eval:
3623  COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with break"));
3624  }
3625  else {
3626  rb_iseq_t *ip = iseq->parent_iseq;
3627  while (ip) {
3628  if (!ip->compile_data) {
3629  ip = 0;
3630  break;
3631  }
3632 
3633  level++;
3634  if (ip->compile_data->redo_label != 0) {
3635  level = 0x8000;
3636  if (ip->compile_data->loopval_popped == 0) {
3637  /* need value */
3638  level |= 0x4000;
3639  }
3640  goto break_by_insn;
3641  }
3642  else if (ip->type == ISEQ_TYPE_BLOCK) {
3643  level <<= 16;
3644  goto break_by_insn;
3645  }
3646  else if (ip->type == ISEQ_TYPE_EVAL) {
3647  goto break_in_eval;
3648  }
3649 
3650  ip = ip->parent_iseq;
3651  }
3652  COMPILE_ERROR((ERROR_ARGS "Invalid break"));
3653  }
3654  break;
3655  }
3656  case NODE_NEXT:{
3657  unsigned long level = 0;
3658 
3659  if (iseq->compile_data->redo_label != 0) {
3660  LABEL *splabel = NEW_LABEL(0);
3661  debugs("next in while loop\n");
3662  ADD_LABEL(ret, splabel);
3663  COMPILE(ret, "next val/valid syntax?", node->nd_stts);
3664  add_ensure_iseq(ret, iseq, 0);
3665  ADD_ADJUST(ret, line, iseq->compile_data->redo_label);
3666  ADD_INSNL(ret, line, jump, iseq->compile_data->start_label);
3667  ADD_ADJUST_RESTORE(ret, splabel);
3668  if (!poped) {
3669  ADD_INSN(ret, line, putnil);
3670  }
3671  }
3672  else if (iseq->compile_data->end_label) {
3673  LABEL *splabel = NEW_LABEL(0);
3674  debugs("next in block\n");
3675  ADD_LABEL(ret, splabel);
3676  ADD_ADJUST(ret, line, iseq->compile_data->start_label);
3677  COMPILE(ret, "next val", node->nd_stts);
3678  add_ensure_iseq(ret, iseq, 0);
3679  ADD_INSNL(ret, line, jump, iseq->compile_data->end_label);
3680  ADD_ADJUST_RESTORE(ret, splabel);
3681 
3682  if (!poped) {
3683  ADD_INSN(ret, line, putnil);
3684  }
3685  }
3686  else if (iseq->type == ISEQ_TYPE_EVAL) {
3687  next_in_eval:
3688  COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with next"));
3689  }
3690  else {
3691  rb_iseq_t *ip;
3692  ip = iseq;
3693  while (ip) {
3694  if (!ip->compile_data) {
3695  ip = 0;
3696  break;
3697  }
3698 
3699  level = 0x8000 | 0x4000;
3700  if (ip->compile_data->redo_label != 0) {
3701  /* while loop */
3702  break;
3703  }
3704  else if (ip->type == ISEQ_TYPE_BLOCK) {
3705  break;
3706  }
3707  else if (ip->type == ISEQ_TYPE_EVAL) {
3708  goto next_in_eval;
3709  }
3710 
3711  ip = ip->parent_iseq;
3712  }
3713  if (ip != 0) {
3714  COMPILE(ret, "next val", node->nd_stts);
3715  ADD_INSN1(ret, line, throw, INT2FIX(level | 0x03) /* TAG_NEXT */ );
3716 
3717  if (poped) {
3718  ADD_INSN(ret, line, pop);
3719  }
3720  }
3721  else {
3722  COMPILE_ERROR((ERROR_ARGS "Invalid next"));
3723  }
3724  }
3725  break;
3726  }
3727  case NODE_REDO:{
3728  if (iseq->compile_data->redo_label) {
3729  LABEL *splabel = NEW_LABEL(0);
3730  debugs("redo in while");
3731  ADD_LABEL(ret, splabel);
3732  ADD_ADJUST(ret, line, iseq->compile_data->redo_label);
3733  add_ensure_iseq(ret, iseq, 0);
3734  ADD_INSNL(ret, line, jump, iseq->compile_data->redo_label);
3735  ADD_ADJUST_RESTORE(ret, splabel);
3736  if (!poped) {
3737  ADD_INSN(ret, line, putnil);
3738  }
3739  }
3740  else if (iseq->type == ISEQ_TYPE_EVAL) {
3741  redo_in_eval:
3742  COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with redo"));
3743  }
3744  else if (iseq->compile_data->start_label) {
3745  LABEL *splabel = NEW_LABEL(0);
3746 
3747  debugs("redo in block");
3748  ADD_LABEL(ret, splabel);
3749  add_ensure_iseq(ret, iseq, 0);
3750  ADD_ADJUST(ret, line, iseq->compile_data->start_label);
3751  ADD_INSNL(ret, line, jump, iseq->compile_data->start_label);
3752  ADD_ADJUST_RESTORE(ret, splabel);
3753 
3754  if (!poped) {
3755  ADD_INSN(ret, line, putnil);
3756  }
3757  }
3758  else {
3759  rb_iseq_t *ip;
3760  unsigned long level;
3761  level = 0x8000 | 0x4000;
3762  ip = iseq;
3763  while (ip) {
3764  if (!ip->compile_data) {
3765  ip = 0;
3766  break;
3767  }
3768 
3769  if (ip->compile_data->redo_label != 0) {
3770  break;
3771  }
3772  else if (ip->type == ISEQ_TYPE_BLOCK) {
3773  break;
3774  }
3775  else if (ip->type == ISEQ_TYPE_EVAL) {
3776  goto redo_in_eval;
3777  }
3778 
3779  ip = ip->parent_iseq;
3780  }
3781  if (ip != 0) {
3782  ADD_INSN(ret, line, putnil);
3783  ADD_INSN1(ret, line, throw, INT2FIX(level | 0x05) /* TAG_REDO */ );
3784 
3785  if (poped) {
3786  ADD_INSN(ret, line, pop);
3787  }
3788  }
3789  else {
3790  COMPILE_ERROR((ERROR_ARGS "Invalid redo"));
3791  }
3792  }
3793  break;
3794  }
3795  case NODE_RETRY:{
3796  if (iseq->type == ISEQ_TYPE_RESCUE) {
3797  ADD_INSN(ret, line, putnil);
3798  ADD_INSN1(ret, line, throw, INT2FIX(0x04) /* TAG_RETRY */ );
3799 
3800  if (poped) {
3801  ADD_INSN(ret, line, pop);
3802  }
3803  }
3804  else {
3805  COMPILE_ERROR((ERROR_ARGS "Invalid retry"));
3806  }
3807  break;
3808  }
3809  case NODE_BEGIN:{
3810  COMPILE_(ret, "NODE_BEGIN", node->nd_body, poped);
3811  break;
3812  }
3813  case NODE_RESCUE:{
3814  LABEL *lstart = NEW_LABEL(line);
3815  LABEL *lend = NEW_LABEL(line);
3816  LABEL *lcont = NEW_LABEL(line);
3817  VALUE rescue = NEW_CHILD_ISEQVAL(
3818  node->nd_resq,
3819  rb_str_concat(rb_str_new2("rescue in "), iseq->location.label),
3820  ISEQ_TYPE_RESCUE, line);
3821 
3822  ADD_LABEL(ret, lstart);
3823  COMPILE(ret, "rescue head", node->nd_head);
3824  ADD_LABEL(ret, lend);
3825  if (node->nd_else) {
3826  ADD_INSN(ret, line, pop);
3827  COMPILE(ret, "rescue else", node->nd_else);
3828  }
3829  ADD_INSN(ret, line, nop);
3830  ADD_LABEL(ret, lcont);
3831 
3832  if (poped) {
3833  ADD_INSN(ret, line, pop);
3834  }
3835 
3836  /* register catch entry */
3837  ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lcont);
3838  ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, 0, lstart);
3839  break;
3840  }
3841  case NODE_RESBODY:{
3842  NODE *resq = node;
3843  NODE *narg;
3844  LABEL *label_miss, *label_hit;
3845 
3846  while (resq) {
3847  label_miss = NEW_LABEL(line);
3848  label_hit = NEW_LABEL(line);
3849 
3850  narg = resq->nd_args;
3851  if (narg) {
3852  switch (nd_type(narg)) {
3853  case NODE_ARRAY:
3854  while (narg) {
3855  ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0));
3856  COMPILE(ret, "rescue arg", narg->nd_head);
3857  ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
3858  ADD_INSNL(ret, line, branchif, label_hit);
3859  narg = narg->nd_next;
3860  }
3861  break;
3862  case NODE_SPLAT:
3863  case NODE_ARGSCAT:
3864  case NODE_ARGSPUSH:
3865  ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0));
3866  COMPILE(ret, "rescue/cond splat", narg);
3868  ADD_INSNL(ret, line, branchif, label_hit);
3869  break;
3870  default:
3871  rb_bug("NODE_RESBODY: unknown node (%s)",
3872  ruby_node_name(nd_type(narg)));
3873  }
3874  }
3875  else {
3876  ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0));
3877  ADD_INSN1(ret, line, putobject, rb_eStandardError);
3878  ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
3879  ADD_INSNL(ret, line, branchif, label_hit);
3880  }
3881  ADD_INSNL(ret, line, jump, label_miss);
3882  ADD_LABEL(ret, label_hit);
3883  COMPILE(ret, "resbody body", resq->nd_body);
3885  ADD_INSN(ret, line, nop);
3886  }
3887  ADD_INSN(ret, line, leave);
3888  ADD_LABEL(ret, label_miss);
3889  resq = resq->nd_head;
3890  }
3891  break;
3892  }
3893  case NODE_ENSURE:{
3894  DECL_ANCHOR(ensr);
3895  VALUE ensure = NEW_CHILD_ISEQVAL(node->nd_ensr,
3897  ("ensure in "),
3898  iseq->location.label),
3899  ISEQ_TYPE_ENSURE, line);
3900  LABEL *lstart = NEW_LABEL(line);
3901  LABEL *lend = NEW_LABEL(line);
3902  LABEL *lcont = NEW_LABEL(line);
3903  struct ensure_range er;
3905  struct ensure_range *erange;
3906 
3907  INIT_ANCHOR(ensr);
3908  COMPILE_POPED(ensr, "ensure ensr", node->nd_ensr);
3909 
3910  er.begin = lstart;
3911  er.end = lend;
3912  er.next = 0;
3913  push_ensure_entry(iseq, &enl, &er, node->nd_ensr);
3914 
3915  ADD_LABEL(ret, lstart);
3916  COMPILE_(ret, "ensure head", node->nd_head, poped);
3917  ADD_LABEL(ret, lend);
3918  if (ensr->anchor.next == 0) {
3919  ADD_INSN(ret, line, nop);
3920  }
3921  else {
3922  ADD_SEQ(ret, ensr);
3923  }
3924  ADD_LABEL(ret, lcont);
3925 
3926  erange = iseq->compile_data->ensure_node_stack->erange;
3927  while (erange) {
3928  ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end,
3929  ensure, lcont);
3930  erange = erange->next;
3931  }
3932 
3933  iseq->compile_data->ensure_node_stack = enl.prev;
3934  break;
3935  }
3936 
3937  case NODE_AND:
3938  case NODE_OR:{
3939  LABEL *end_label = NEW_LABEL(line);
3940  COMPILE(ret, "nd_1st", node->nd_1st);
3941  if (!poped) {
3942  ADD_INSN(ret, line, dup);
3943  }
3944  if (type == NODE_AND) {
3945  ADD_INSNL(ret, line, branchunless, end_label);
3946  }
3947  else {
3948  ADD_INSNL(ret, line, branchif, end_label);
3949  }
3950  if (!poped) {
3951  ADD_INSN(ret, line, pop);
3952  }
3953  COMPILE_(ret, "nd_2nd", node->nd_2nd, poped);
3954  ADD_LABEL(ret, end_label);
3955  break;
3956  }
3957 
3958  case NODE_MASGN:{
3959  compile_massign(iseq, ret, node, poped);
3960  break;
3961  }
3962 
3963  case NODE_LASGN:{
3964  ID id = node->nd_vid;
3965  int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id);
3966 
3967  debugs("lvar: %s idx: %d\n", rb_id2name(id), idx);
3968  COMPILE(ret, "rvalue", node->nd_value);
3969 
3970  if (!poped) {
3971  ADD_INSN(ret, line, dup);
3972  }
3973  ADD_INSN2(ret, line, setlocal, INT2FIX(idx), INT2FIX(get_lvar_level(iseq)));
3974 
3975  break;
3976  }
3977  case NODE_DASGN:
3978  case NODE_DASGN_CURR:{
3979  int idx, lv, ls;
3980  COMPILE(ret, "dvalue", node->nd_value);
3981  debugp_param("dassn id", rb_str_new2(rb_id2name(node->nd_vid) ? rb_id2name(node->nd_vid) : "*"));
3982 
3983  if (!poped) {
3984  ADD_INSN(ret, line, dup);
3985  }
3986 
3987  idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
3988 
3989  if (idx < 0) {
3990  rb_bug("NODE_DASGN(_CURR): unknown id (%s)", rb_id2name(node->nd_vid));
3991  }
3992 
3993  ADD_INSN2(ret, line, setlocal, INT2FIX(ls - idx), INT2FIX(lv));
3994  break;
3995  }
3996  case NODE_GASGN:{
3997  COMPILE(ret, "lvalue", node->nd_value);
3998 
3999  if (!poped) {
4000  ADD_INSN(ret, line, dup);
4001  }
4002  ADD_INSN1(ret, line, setglobal,
4003  ((VALUE)node->nd_entry | 1));
4004  break;
4005  }
4006  case NODE_IASGN:
4007  case NODE_IASGN2:{
4008  COMPILE(ret, "lvalue", node->nd_value);
4009  if (!poped) {
4010  ADD_INSN(ret, line, dup);
4011  }
4012  ADD_INSN2(ret, line, setinstancevariable,
4013  ID2SYM(node->nd_vid), INT2FIX(iseq->is_size++));
4014  break;
4015  }
4016  case NODE_CDECL:{
4017  COMPILE(ret, "lvalue", node->nd_value);
4018 
4019  if (!poped) {
4020  ADD_INSN(ret, line, dup);
4021  }
4022 
4023  if (node->nd_vid) {
4024  ADD_INSN1(ret, line, putspecialobject,
4026  ADD_INSN1(ret, line, setconstant, ID2SYM(node->nd_vid));
4027  }
4028  else {
4029  compile_cpath(ret, iseq, node->nd_else);
4030  ADD_INSN1(ret, line, setconstant, ID2SYM(node->nd_else->nd_mid));
4031  }
4032  break;
4033  }
4034  case NODE_CVASGN:{
4035  COMPILE(ret, "cvasgn val", node->nd_value);
4036  if (!poped) {
4037  ADD_INSN(ret, line, dup);
4038  }
4039  ADD_INSN1(ret, line, setclassvariable,
4040  ID2SYM(node->nd_vid));
4041  break;
4042  }
4043  case NODE_OP_ASGN1: {
4044  DECL_ANCHOR(args);
4045  VALUE argc;
4046  VALUE flag = 0;
4047  ID id = node->nd_mid;
4048  int boff = 0;
4049 
4050  /*
4051  * a[x] (op)= y
4052  *
4053  * nil # nil
4054  * eval a # nil a
4055  * eval x # nil a x
4056  * dupn 2 # nil a x a x
4057  * send :[] # nil a x a[x]
4058  * eval y # nil a x a[x] y
4059  * send op # nil a x ret
4060  * setn 3 # ret a x ret
4061  * send []= # ret ?
4062  * pop # ret
4063  */
4064 
4065  /*
4066  * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head;
4067  * NODE_OP_ASGN nd_recv
4068  * nd_args->nd_head
4069  * nd_args->nd_body
4070  * nd_mid
4071  */
4072 
4073  if (!poped) {
4074  ADD_INSN(ret, line, putnil);
4075  }
4076  COMPILE(ret, "NODE_OP_ASGN1 recv", node->nd_recv);
4077  switch (nd_type(node->nd_args->nd_head)) {
4078  case NODE_ZARRAY:
4079  argc = INT2FIX(0);
4080  break;
4081  case NODE_BLOCK_PASS:
4082  boff = 1;
4083  default:
4084  INIT_ANCHOR(args);
4085  argc = setup_args(iseq, args, node->nd_args->nd_head, &flag);
4086  ADD_SEQ(ret, args);
4087  }
4088  ADD_INSN1(ret, line, dupn, FIXNUM_INC(argc, 1 + boff));
4089  ADD_SEND_R(ret, line, ID2SYM(idAREF), argc, Qfalse, LONG2FIX(flag));
4090 
4091  if (id == 0 || id == 1) {
4092  /* 0: or, 1: and
4093  a[x] ||= y
4094 
4095  unless/if a[x]
4096  a[x]= y
4097  else
4098  nil
4099  end
4100  */
4101  LABEL *label = NEW_LABEL(line);
4102  LABEL *lfin = NEW_LABEL(line);
4103 
4104  ADD_INSN(ret, line, dup);
4105  if (id == 0) {
4106  /* or */
4107  ADD_INSNL(ret, line, branchif, label);
4108  }
4109  else {
4110  /* and */
4111  ADD_INSNL(ret, line, branchunless, label);
4112  }
4113  ADD_INSN(ret, line, pop);
4114 
4115  COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body);
4116  if (!poped) {
4117  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff));
4118  }
4119  if (flag & VM_CALL_ARGS_SPLAT) {
4120  ADD_INSN1(ret, line, newarray, INT2FIX(1));
4121  if (boff > 0) {
4122  ADD_INSN1(ret, line, dupn, INT2FIX(3));
4123  ADD_INSN(ret, line, swap);
4124  ADD_INSN(ret, line, pop);
4125  }
4126  ADD_INSN(ret, line, concatarray);
4127  if (boff > 0) {
4128  ADD_INSN1(ret, line, setn, INT2FIX(3));
4129  ADD_INSN(ret, line, pop);
4130  ADD_INSN(ret, line, pop);
4131  }
4132  ADD_SEND_R(ret, line, ID2SYM(idASET),
4133  argc, Qfalse, LONG2FIX(flag));
4134  }
4135  else {
4136  if (boff > 0)
4137  ADD_INSN(ret, line, swap);
4138  ADD_SEND_R(ret, line, ID2SYM(idASET),
4139  FIXNUM_INC(argc, 1), Qfalse, LONG2FIX(flag));
4140  }
4141  ADD_INSN(ret, line, pop);
4142  ADD_INSNL(ret, line, jump, lfin);
4143  ADD_LABEL(ret, label);
4144  if (!poped) {
4145  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff));
4146  }
4147  ADD_INSN1(ret, line, adjuststack, FIXNUM_INC(argc, 2+boff));
4148  ADD_LABEL(ret, lfin);
4149  }
4150  else {
4151  COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body);
4152  ADD_SEND(ret, line, ID2SYM(id), INT2FIX(1));
4153  if (!poped) {
4154  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff));
4155  }
4156  if (flag & VM_CALL_ARGS_SPLAT) {
4157  ADD_INSN1(ret, line, newarray, INT2FIX(1));
4158  if (boff > 0) {
4159  ADD_INSN1(ret, line, dupn, INT2FIX(3));
4160  ADD_INSN(ret, line, swap);
4161  ADD_INSN(ret, line, pop);
4162  }
4163  ADD_INSN(ret, line, concatarray);
4164  if (boff > 0) {
4165  ADD_INSN1(ret, line, setn, INT2FIX(3));
4166  ADD_INSN(ret, line, pop);
4167  ADD_INSN(ret, line, pop);
4168  }
4169  ADD_SEND_R(ret, line, ID2SYM(idASET),
4170  argc, Qfalse, LONG2FIX(flag));
4171  }
4172  else {
4173  if (boff > 0)
4174  ADD_INSN(ret, line, swap);
4175  ADD_SEND_R(ret, line, ID2SYM(idASET),
4176  FIXNUM_INC(argc, 1), Qfalse, LONG2FIX(flag));
4177  }
4178  ADD_INSN(ret, line, pop);
4179  }
4180 
4181  break;
4182  }
4183  case NODE_OP_ASGN2:{
4184  ID atype = node->nd_next->nd_mid;
4185  LABEL *lfin = NEW_LABEL(line);
4186  LABEL *lcfin = NEW_LABEL(line);
4187  /*
4188  class C; attr_accessor :c; end
4189  r = C.new
4190  r.a &&= v # asgn2
4191 
4192  eval r # r
4193  dup # r r
4194  eval r.a # r o
4195 
4196  # or
4197  dup # r o o
4198  if lcfin # r o
4199  pop # r
4200  eval v # r v
4201  swap # v r
4202  topn 1 # v r v
4203  send a= # v ?
4204  jump lfin # v ?
4205 
4206  lcfin: # r o
4207  swap # o r
4208 
4209  lfin: # o ?
4210  pop # o
4211 
4212  # and
4213  dup # r o o
4214  unless lcfin
4215  pop # r
4216  eval v # r v
4217  swap # v r
4218  topn 1 # v r v
4219  send a= # v ?
4220  jump lfin # v ?
4221 
4222  # others
4223  eval v # r o v
4224  send ?? # r w
4225  send a= # w
4226 
4227  */
4228 
4229  COMPILE(ret, "NODE_OP_ASGN2#recv", node->nd_recv);
4230  ADD_INSN(ret, line, dup);
4231  ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_vid),
4232  INT2FIX(0));
4233 
4234  if (atype == 0 || atype == 1) { /* 0: OR or 1: AND */
4235  ADD_INSN(ret, line, dup);
4236  if (atype == 0) {
4237  ADD_INSNL(ret, line, branchif, lcfin);
4238  }
4239  else {
4240  ADD_INSNL(ret, line, branchunless, lcfin);
4241  }
4242  ADD_INSN(ret, line, pop);
4243  COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value);
4244  ADD_INSN(ret, line, swap);
4245  ADD_INSN1(ret, line, topn, INT2FIX(1));
4246  ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_aid),
4247  INT2FIX(1));
4248  ADD_INSNL(ret, line, jump, lfin);
4249 
4250  ADD_LABEL(ret, lcfin);
4251  ADD_INSN(ret, line, swap);
4252 
4253  ADD_LABEL(ret, lfin);
4254  ADD_INSN(ret, line, pop);
4255  if (poped) {
4256  /* we can apply more optimize */
4257  ADD_INSN(ret, line, pop);
4258  }
4259  }
4260  else {
4261  COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value);
4262  ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_mid),
4263  INT2FIX(1));
4264  if (!poped) {
4265  ADD_INSN(ret, line, swap);
4266  ADD_INSN1(ret, line, topn, INT2FIX(1));
4267  }
4268  ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_aid),
4269  INT2FIX(1));
4270  ADD_INSN(ret, line, pop);
4271  }
4272  break;
4273  }
4274  case NODE_OP_CDECL: {
4275  LABEL *lfin = 0;
4276  LABEL *lassign = 0;
4277  ID mid;
4278 
4279  switch (nd_type(node->nd_head)) {
4280  case NODE_COLON3:
4281  ADD_INSN1(ret, line, putobject, rb_cObject);
4282  break;
4283  case NODE_COLON2:
4284  COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head);
4285  break;
4286  default:
4287  do {
4288  COMPILE_ERROR((ERROR_ARGS "%s: invalid node in NODE_OP_CDECL",
4289  ruby_node_name(nd_type(node->nd_head))));
4290  } while (0);
4291  return COMPILE_NG;
4292  }
4293  mid = node->nd_head->nd_mid;
4294  /* cref */
4295  if (node->nd_aid == 0) {
4296  lassign = NEW_LABEL(line);
4297  ADD_INSN(ret, line, dup); /* cref cref */
4298  ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_CONST),
4299  ID2SYM(mid), Qfalse); /* cref bool */
4300  ADD_INSNL(ret, line, branchunless, lassign); /* cref */
4301  }
4302  ADD_INSN(ret, line, dup); /* cref cref */
4303  ADD_INSN1(ret, line, getconstant, ID2SYM(mid)); /* cref obj */
4304 
4305  if (node->nd_aid == 0 || node->nd_aid == 1) {
4306  lfin = NEW_LABEL(line);
4307  if (!poped) ADD_INSN(ret, line, dup); /* cref [obj] obj */
4308  if (node->nd_aid == 0)
4309  ADD_INSNL(ret, line, branchif, lfin);
4310  else
4311  ADD_INSNL(ret, line, branchunless, lfin);
4312  /* cref [obj] */
4313  if (!poped) ADD_INSN(ret, line, pop); /* cref */
4314  if (lassign) ADD_LABEL(ret, lassign);
4315  COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value);
4316  /* cref value */
4317  if (poped)
4318  ADD_INSN1(ret, line, topn, INT2FIX(1)); /* cref value cref */
4319  else {
4320  ADD_INSN1(ret, line, dupn, INT2FIX(2)); /* cref value cref value */
4321  ADD_INSN(ret, line, swap); /* cref value value cref */
4322  }
4323  ADD_INSN1(ret, line, setconstant, ID2SYM(mid)); /* cref [value] */
4324  ADD_LABEL(ret, lfin); /* cref [value] */
4325  if (!poped) ADD_INSN(ret, line, swap); /* [value] cref */
4326  ADD_INSN(ret, line, pop); /* [value] */
4327  }
4328  else {
4329  COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value);
4330  /* cref obj value */
4331  ADD_CALL(ret, line, ID2SYM(node->nd_aid), INT2FIX(1));
4332  /* cref value */
4333  ADD_INSN(ret, line, swap); /* value cref */
4334  if (!poped) {
4335  ADD_INSN1(ret, line, topn, INT2FIX(1)); /* value cref value */
4336  ADD_INSN(ret, line, swap); /* value value cref */
4337  }
4338  ADD_INSN1(ret, line, setconstant, ID2SYM(mid));
4339  }
4340  break;
4341  }
4342  case NODE_OP_ASGN_AND:
4343  case NODE_OP_ASGN_OR:{
4344  LABEL *lfin = NEW_LABEL(line);
4345  LABEL *lassign;
4346 
4347  if (nd_type(node) == NODE_OP_ASGN_OR) {
4348  LABEL *lfinish[2];
4349  lfinish[0] = lfin;
4350  lfinish[1] = 0;
4351  defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
4352  lassign = lfinish[1];
4353  if (!lassign) {
4354  lassign = NEW_LABEL(line);
4355  }
4356  ADD_INSNL(ret, line, branchunless, lassign);
4357  }
4358  else {
4359  lassign = NEW_LABEL(line);
4360  }
4361 
4362  COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head);
4363  ADD_INSN(ret, line, dup);
4364 
4365  if (nd_type(node) == NODE_OP_ASGN_AND) {
4366  ADD_INSNL(ret, line, branchunless, lfin);
4367  }
4368  else {
4369  ADD_INSNL(ret, line, branchif, lfin);
4370  }
4371 
4372  ADD_INSN(ret, line, pop);
4373  ADD_LABEL(ret, lassign);
4374  COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value);
4375  ADD_LABEL(ret, lfin);
4376 
4377  if (poped) {
4378  /* we can apply more optimize */
4379  ADD_INSN(ret, line, pop);
4380  }
4381  break;
4382  }
4383  case NODE_CALL:
4384  if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR &&
4385  node->nd_mid == idFreeze && node->nd_args == NULL)
4386  {
4387  VALUE str = rb_fstring(node->nd_recv->nd_lit);
4388  iseq_add_mark_object(iseq, str);
4389  ADD_INSN1(ret, line, opt_str_freeze, str);
4390  if (poped) {
4391  ADD_INSN(ret, line, pop);
4392  }
4393  break;
4394  }
4395  case NODE_FCALL:
4396  case NODE_VCALL:{ /* VCALL: variable or call */
4397  /*
4398  call: obj.method(...)
4399  fcall: func(...)
4400  vcall: func
4401  */
4402  DECL_ANCHOR(recv);
4403  DECL_ANCHOR(args);
4404  ID mid = node->nd_mid;
4405  VALUE argc;
4406  VALUE flag = 0;
4407  VALUE parent_block = iseq->compile_data->current_block;
4409 
4410  INIT_ANCHOR(recv);
4411  INIT_ANCHOR(args);
4412 #if SUPPORT_JOKE
4413  if (nd_type(node) == NODE_VCALL) {
4414  ID id_bitblt;
4415  ID id_answer;
4416 
4417  CONST_ID(id_bitblt, "bitblt");
4418  CONST_ID(id_answer, "the_answer_to_life_the_universe_and_everything");
4419 
4420  if (mid == id_bitblt) {
4421  ADD_INSN(ret, line, bitblt);
4422  break;
4423  }
4424  else if (mid == id_answer) {
4425  ADD_INSN(ret, line, answer);
4426  break;
4427  }
4428  }
4429  /* only joke */
4430  {
4431  ID goto_id;
4432  ID label_id;
4433 
4434  CONST_ID(goto_id, "__goto__");
4435  CONST_ID(label_id, "__label__");
4436 
4437  if (nd_type(node) == NODE_FCALL &&
4438  (mid == goto_id || mid == label_id)) {
4439  LABEL *label;
4440  st_data_t data;
4441  st_table *labels_table = iseq->compile_data->labels_table;
4442  ID label_name;
4443 
4444  if (!labels_table) {
4445  labels_table = st_init_numtable();
4446  iseq->compile_data->labels_table = labels_table;
4447  }
4448  if (nd_type(node->nd_args->nd_head) == NODE_LIT &&
4449  SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
4450 
4451  label_name = SYM2ID(node->nd_args->nd_head->nd_lit);
4452  if (!st_lookup(labels_table, (st_data_t)label_name, &data)) {
4453  label = NEW_LABEL(line);
4454  label->position = line;
4455  st_insert(labels_table, (st_data_t)label_name, (st_data_t)label);
4456  }
4457  else {
4458  label = (LABEL *)data;
4459  }
4460  }
4461  else {
4462  COMPILE_ERROR((ERROR_ARGS "invalid goto/label format"));
4463  }
4464 
4465 
4466  if (mid == goto_id) {
4467  ADD_INSNL(ret, line, jump, label);
4468  }
4469  else {
4470  ADD_LABEL(ret, label);
4471  }
4472  break;
4473  }
4474  }
4475 #endif
4476  /* receiver */
4477  if (type == NODE_CALL) {
4478  COMPILE(recv, "recv", node->nd_recv);
4479  }
4480  else if (type == NODE_FCALL || type == NODE_VCALL) {
4481  ADD_CALL_RECEIVER(recv, line);
4482  }
4483 
4484  /* args */
4485  if (nd_type(node) != NODE_VCALL) {
4486  argc = setup_args(iseq, args, node->nd_args, &flag);
4487  }
4488  else {
4489  argc = INT2FIX(0);
4490  }
4491 
4492  ADD_SEQ(ret, recv);
4493  ADD_SEQ(ret, args);
4494 
4495  debugp_param("call args argc", argc);
4496  debugp_param("call method", ID2SYM(mid));
4497 
4498  switch (nd_type(node)) {
4499  case NODE_VCALL:
4500  flag |= VM_CALL_VCALL;
4501  /* VCALL is funcall, so fall through */
4502  case NODE_FCALL:
4503  flag |= VM_CALL_FCALL;
4504  }
4505 
4506  ADD_SEND_R(ret, line, ID2SYM(mid),
4507  argc, parent_block, LONG2FIX(flag));
4508 
4509  if (poped) {
4510  ADD_INSN(ret, line, pop);
4511  }
4512  break;
4513  }
4514  case NODE_SUPER:
4515  case NODE_ZSUPER:{
4516  DECL_ANCHOR(args);
4517  int argc;
4518  VALUE flag = 0;
4519  VALUE parent_block = iseq->compile_data->current_block;
4520 
4521  INIT_ANCHOR(args);
4523  if (nd_type(node) == NODE_SUPER) {
4524  VALUE vargc = setup_args(iseq, args, node->nd_args, &flag);
4525  argc = FIX2INT(vargc);
4526  }
4527  else {
4528  /* NODE_ZSUPER */
4529  int i;
4530  rb_iseq_t *liseq = iseq->local_iseq;
4531  int lvar_level = get_lvar_level(iseq);
4532 
4533  argc = liseq->argc;
4534 
4535  /* normal arguments */
4536  for (i = 0; i < liseq->argc; i++) {
4537  int idx = liseq->local_size - i;
4538  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4539  }
4540 
4541  if (!liseq->arg_simple) {
4542  if (liseq->arg_opts) {
4543  /* optional arguments */
4544  int j;
4545  for (j = 0; j < liseq->arg_opts - 1; j++) {
4546  int idx = liseq->local_size - (i + j);
4547  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4548  }
4549  i += j;
4550  argc = i;
4551  }
4552 
4553  if (liseq->arg_rest != -1) {
4554  /* rest argument */
4555  int idx = liseq->local_size - liseq->arg_rest;
4556  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4557  argc = liseq->arg_rest + 1;
4558  flag |= VM_CALL_ARGS_SPLAT;
4559  }
4560 
4561  if (liseq->arg_post_len) {
4562  /* post arguments */
4563  int post_len = liseq->arg_post_len;
4564  int post_start = liseq->arg_post_start;
4565 
4566  if (liseq->arg_rest != -1) {
4567  int j;
4568  for (j=0; j<post_len; j++) {
4569  int idx = liseq->local_size - (post_start + j);
4570  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4571  }
4572  ADD_INSN1(args, line, newarray, INT2FIX(j));
4573  ADD_INSN (args, line, concatarray);
4574  /* argc is settled at above */
4575  }
4576  else {
4577  int j;
4578  for (j=0; j<post_len; j++) {
4579  int idx = liseq->local_size - (post_start + j);
4580  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4581  }
4582  argc = post_len + post_start;
4583  }
4584  }
4585 
4586  if (liseq->arg_keyword >= 0) {
4587  int local_size = liseq->local_size;
4588  int idx = local_size - liseq->arg_keyword;
4589  argc++;
4590  ADD_INSN1(args, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
4591  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4592  ADD_SEND (args, line, ID2SYM(rb_intern("dup")), INT2FIX(0));
4593  for (i = 0; i < liseq->arg_keywords; ++i) {
4594  ID id = liseq->arg_keyword_table[i];
4595  idx = local_size - get_local_var_idx(liseq, id);
4596  ADD_INSN1(args, line, putobject, ID2SYM(id));
4597  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4598  }
4599  ADD_SEND(args, line, ID2SYM(id_core_hash_merge_ptr), INT2FIX(i * 2 + 1));
4600  if (liseq->arg_rest != -1) {
4601  ADD_INSN1(args, line, newarray, INT2FIX(1));
4602  ADD_INSN (args, line, concatarray);
4603  --argc;
4604  }
4605  }
4606  }
4607  }
4608 
4609  /* dummy receiver */
4610  ADD_INSN1(ret, line, putobject, nd_type(node) == NODE_ZSUPER ? Qfalse : Qtrue);
4611  ADD_SEQ(ret, args);
4612  ADD_INSN1(ret, line, invokesuper, new_callinfo(iseq, 0, argc, parent_block,
4613  flag | VM_CALL_SUPER | VM_CALL_FCALL));
4614 
4615  if (poped) {
4616  ADD_INSN(ret, line, pop);
4617  }
4618  break;
4619  }
4620  case NODE_ARRAY:{
4621  compile_array_(iseq, ret, node, COMPILE_ARRAY_TYPE_ARRAY, poped);
4622  break;
4623  }
4624  case NODE_ZARRAY:{
4625  if (!poped) {
4626  ADD_INSN1(ret, line, newarray, INT2FIX(0));
4627  }
4628  break;
4629  }
4630  case NODE_VALUES:{
4631  NODE *n = node;
4632  while (n) {
4633  COMPILE(ret, "values item", n->nd_head);
4634  n = n->nd_next;
4635  }
4636  ADD_INSN1(ret, line, newarray, INT2FIX(node->nd_alen));
4637  if (poped) {
4638  ADD_INSN(ret, line, pop);
4639  }
4640  break;
4641  }
4642  case NODE_HASH:{
4643  DECL_ANCHOR(list);
4644  int type = node->nd_head ? nd_type(node->nd_head) : NODE_ZARRAY;
4645 
4646  INIT_ANCHOR(list);
4647  switch (type) {
4648  case NODE_ARRAY:
4649  compile_array(iseq, list, node->nd_head, COMPILE_ARRAY_TYPE_HASH);
4650  ADD_SEQ(ret, list);
4651  break;
4652 
4653  case NODE_ZARRAY:
4654  ADD_INSN1(ret, line, newhash, INT2FIX(0));
4655  break;
4656 
4657  default:
4658  rb_bug("can't make hash with this node: %s", ruby_node_name(type));
4659  }
4660 
4661  if (poped) {
4662  ADD_INSN(ret, line, pop);
4663  }
4664  break;
4665  }
4666  case NODE_RETURN:{
4667  rb_iseq_t *is = iseq;
4668 
4669  if (is) {
4670  if (is->type == ISEQ_TYPE_TOP) {
4671  COMPILE_ERROR((ERROR_ARGS "Invalid return"));
4672  }
4673  else {
4674  LABEL *splabel = 0;
4675 
4676  if (is->type == ISEQ_TYPE_METHOD) {
4677  splabel = NEW_LABEL(0);
4678  ADD_LABEL(ret, splabel);
4679  ADD_ADJUST(ret, line, 0);
4680  }
4681 
4682  COMPILE(ret, "return nd_stts (return val)", node->nd_stts);
4683 
4684  if (is->type == ISEQ_TYPE_METHOD) {
4685  add_ensure_iseq(ret, iseq, 1);
4686  ADD_TRACE(ret, line, RUBY_EVENT_RETURN);
4687  ADD_INSN(ret, line, leave);
4688  ADD_ADJUST_RESTORE(ret, splabel);
4689 
4690  if (!poped) {
4691  ADD_INSN(ret, line, putnil);
4692  }
4693  }
4694  else {
4695  ADD_INSN1(ret, line, throw, INT2FIX(0x01) /* TAG_RETURN */ );
4696  if (poped) {
4697  ADD_INSN(ret, line, pop);
4698  }
4699  }
4700  }
4701  }
4702  break;
4703  }
4704  case NODE_YIELD:{
4705  DECL_ANCHOR(args);
4706  VALUE argc;
4707  VALUE flag = 0;
4708 
4709  INIT_ANCHOR(args);
4710  if (iseq->type == ISEQ_TYPE_TOP) {
4711  COMPILE_ERROR((ERROR_ARGS "Invalid yield"));
4712  }
4713 
4714  if (node->nd_head) {
4715  argc = setup_args(iseq, args, node->nd_head, &flag);
4716  }
4717  else {
4718  argc = INT2FIX(0);
4719  }
4720 
4721  ADD_SEQ(ret, args);
4722  ADD_INSN1(ret, line, invokeblock, new_callinfo(iseq, 0, FIX2INT(argc), 0, flag));
4723 
4724  if (poped) {
4725  ADD_INSN(ret, line, pop);
4726  }
4727  break;
4728  }
4729  case NODE_LVAR:{
4730  if (!poped) {
4731  ID id = node->nd_vid;
4732  int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id);
4733 
4734  debugs("id: %s idx: %d\n", rb_id2name(id), idx);
4735  ADD_INSN2(ret, line, getlocal, INT2FIX(idx), INT2FIX(get_lvar_level(iseq)));
4736  }
4737  break;
4738  }
4739  case NODE_DVAR:{
4740  int lv, idx, ls;
4741  debugi("nd_vid", node->nd_vid);
4742  if (!poped) {
4743  idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
4744  if (idx < 0) {
4745  rb_bug("unknown dvar (%s)", rb_id2name(node->nd_vid));
4746  }
4747  ADD_INSN2(ret, line, getlocal, INT2FIX(ls - idx), INT2FIX(lv));
4748  }
4749  break;
4750  }
4751  case NODE_GVAR:{
4752  ADD_INSN1(ret, line, getglobal,
4753  ((VALUE)node->nd_entry | 1));
4754  if (poped) {
4755  ADD_INSN(ret, line, pop);
4756  }
4757  break;
4758  }
4759  case NODE_IVAR:{
4760  debugi("nd_vid", node->nd_vid);
4761  if (!poped) {
4762  ADD_INSN2(ret, line, getinstancevariable,
4763  ID2SYM(node->nd_vid), INT2FIX(iseq->is_size++));
4764  }
4765  break;
4766  }
4767  case NODE_CONST:{
4768  debugi("nd_vid", node->nd_vid);
4769 
4770  if (iseq->compile_data->option->inline_const_cache) {
4771  LABEL *lend = NEW_LABEL(line);
4772  int ic_index = iseq->is_size++;
4773 
4774  ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index));
4775  ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid));
4776  ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index));
4777  ADD_LABEL(ret, lend);
4778  }
4779  else {
4780  ADD_INSN(ret, line, putnil);
4781  ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid));
4782  }
4783 
4784  if (poped) {
4785  ADD_INSN(ret, line, pop);
4786  }
4787  break;
4788  }
4789  case NODE_CVAR:{
4790  if (!poped) {
4791  ADD_INSN1(ret, line, getclassvariable,
4792  ID2SYM(node->nd_vid));
4793  }
4794  break;
4795  }
4796  case NODE_NTH_REF:{
4797  if (!poped) {
4798  ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */,
4799  INT2FIX(node->nd_nth << 1));
4800  }
4801  break;
4802  }
4803  case NODE_BACK_REF:{
4804  if (!poped) {
4805  ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */,
4806  INT2FIX(0x01 | (node->nd_nth << 1)));
4807  }
4808  break;
4809  }
4810  case NODE_MATCH:
4811  case NODE_MATCH2:
4812  case NODE_MATCH3:{
4813  DECL_ANCHOR(recv);
4814  DECL_ANCHOR(val);
4815 
4816  INIT_ANCHOR(recv);
4817  INIT_ANCHOR(val);
4818  switch (nd_type(node)) {
4819  case NODE_MATCH:
4820  ADD_INSN1(recv, line, putobject, node->nd_lit);
4821  ADD_INSN2(val, line, getspecial, INT2FIX(0),
4822  INT2FIX(0));
4823  break;
4824  case NODE_MATCH2:
4825  COMPILE(recv, "receiver", node->nd_recv);
4826  COMPILE(val, "value", node->nd_value);
4827  break;
4828  case NODE_MATCH3:
4829  COMPILE(recv, "receiver", node->nd_value);
4830  COMPILE(val, "value", node->nd_recv);
4831  break;
4832  }
4833 
4835  /* TODO: detect by node */
4836  if (recv->last == recv->anchor.next &&
4837  INSN_OF(recv->last) == BIN(putobject) &&
4838  nd_type(node) == NODE_MATCH2) {
4839  ADD_SEQ(ret, val);
4840  ADD_INSN1(ret, line, opt_regexpmatch1,
4841  OPERAND_AT(recv->last, 0));
4842  }
4843  else {
4844  ADD_SEQ(ret, recv);
4845  ADD_SEQ(ret, val);
4846  ADD_INSN1(ret, line, opt_regexpmatch2, new_callinfo(iseq, idEqTilde, 1, 0, 0));
4847  }
4848  }
4849  else {
4850  ADD_SEQ(ret, recv);
4851  ADD_SEQ(ret, val);
4852  ADD_SEND(ret, line, ID2SYM(idEqTilde), INT2FIX(1));
4853  }
4854 
4855  if (poped) {
4856  ADD_INSN(ret, line, pop);
4857  }
4858  break;
4859  }
4860  case NODE_LIT:{
4861  debugp_param("lit", node->nd_lit);
4862  if (!poped) {
4863  ADD_INSN1(ret, line, putobject, node->nd_lit);
4864  }
4865  break;
4866  }
4867  case NODE_STR:{
4868  node->nd_lit = rb_fstring(node->nd_lit);
4869  debugp_param("nd_lit", node->nd_lit);
4870  if (!poped) {
4871  ADD_INSN1(ret, line, putstring, node->nd_lit);
4872  }
4873  break;
4874  }
4875  case NODE_DSTR:{
4876  compile_dstr(iseq, ret, node);
4877 
4878  if (poped) {
4879  ADD_INSN(ret, line, pop);
4880  }
4881  break;
4882  }
4883  case NODE_XSTR:{
4884  node->nd_lit = rb_fstring(node->nd_lit);
4885  ADD_CALL_RECEIVER(ret, line);
4886  ADD_INSN1(ret, line, putobject, node->nd_lit);
4887  ADD_CALL(ret, line, ID2SYM(idBackquote), INT2FIX(1));
4888 
4889  if (poped) {
4890  ADD_INSN(ret, line, pop);
4891  }
4892  break;
4893  }
4894  case NODE_DXSTR:{
4895  ADD_CALL_RECEIVER(ret, line);
4896  compile_dstr(iseq, ret, node);
4897  ADD_CALL(ret, line, ID2SYM(idBackquote), INT2FIX(1));
4898 
4899  if (poped) {
4900  ADD_INSN(ret, line, pop);
4901  }
4902  break;
4903  }
4904  case NODE_EVSTR:{
4905  COMPILE(ret, "nd_body", node->nd_body);
4906 
4907  if (poped) {
4908  ADD_INSN(ret, line, pop);
4909  }
4910  else {
4911  ADD_INSN(ret, line, tostring);
4912  }
4913  break;
4914  }
4915  case NODE_DREGX:{
4916  compile_dregx(iseq, ret, node);
4917 
4918  if (poped) {
4919  ADD_INSN(ret, line, pop);
4920  }
4921  break;
4922  }
4923  case NODE_DREGX_ONCE:{
4924  int ic_index = iseq->is_size++;
4925  NODE *dregx_node = NEW_NODE(NODE_DREGX, node->u1.value, node->u2.value, node->u3.value);
4926  NODE *block_node = NEW_NODE(NODE_SCOPE, 0, dregx_node, 0);
4927  VALUE block_iseq = NEW_CHILD_ISEQVAL(block_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
4928 
4929  ADD_INSN2(ret, line, once, block_iseq, INT2FIX(ic_index));
4930 
4931  if (poped) {
4932  ADD_INSN(ret, line, pop);
4933  }
4934  break;
4935  }
4936  case NODE_ARGSCAT:{
4937  if (poped) {
4938  COMPILE(ret, "argscat head", node->nd_head);
4939  ADD_INSN1(ret, line, splatarray, Qfalse);
4940  ADD_INSN(ret, line, pop);
4941  COMPILE(ret, "argscat body", node->nd_body);
4942  ADD_INSN1(ret, line, splatarray, Qfalse);
4943  ADD_INSN(ret, line, pop);
4944  }
4945  else {
4946  COMPILE(ret, "argscat head", node->nd_head);
4947  COMPILE(ret, "argscat body", node->nd_body);
4948  ADD_INSN(ret, line, concatarray);
4949  }
4950  break;
4951  }
4952  case NODE_ARGSPUSH:{
4953  if (poped) {
4954  COMPILE(ret, "arsgpush head", node->nd_head);
4955  ADD_INSN1(ret, line, splatarray, Qfalse);
4956  ADD_INSN(ret, line, pop);
4957  COMPILE_(ret, "argspush body", node->nd_body, poped);
4958  }
4959  else {
4960  COMPILE(ret, "arsgpush head", node->nd_head);
4961  COMPILE_(ret, "argspush body", node->nd_body, poped);
4962  ADD_INSN1(ret, line, newarray, INT2FIX(1));
4963  ADD_INSN(ret, line, concatarray);
4964  }
4965  break;
4966  }
4967  case NODE_SPLAT:{
4968  COMPILE(ret, "splat", node->nd_head);
4969  ADD_INSN1(ret, line, splatarray, Qtrue);
4970 
4971  if (poped) {
4972  ADD_INSN(ret, line, pop);
4973  }
4974  break;
4975  }
4976  case NODE_DEFN:{
4977  VALUE iseqval = NEW_ISEQVAL(node->nd_defn,
4978  rb_id2str(node->nd_mid),
4979  ISEQ_TYPE_METHOD, line);
4980 
4981  debugp_param("defn/iseq", iseqval);
4982 
4983  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
4984  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
4985  ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid));
4986  ADD_INSN1(ret, line, putiseq, iseqval);
4987  ADD_SEND (ret, line, ID2SYM(id_core_define_method), INT2FIX(3));
4988 
4989  if (poped) {
4990  ADD_INSN(ret, line, pop);
4991  }
4992 
4993  debugp_param("defn", iseqval);
4994  break;
4995  }
4996  case NODE_DEFS:{
4997  VALUE iseqval = NEW_ISEQVAL(node->nd_defn,
4998  rb_id2str(node->nd_mid),
4999  ISEQ_TYPE_METHOD, line);
5000 
5001  debugp_param("defs/iseq", iseqval);
5002 
5003  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5004  COMPILE(ret, "defs: recv", node->nd_recv);
5005  ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid));
5006  ADD_INSN1(ret, line, putiseq, iseqval);
5008 
5009  if (poped) {
5010  ADD_INSN(ret, line, pop);
5011  }
5012  break;
5013  }
5014  case NODE_ALIAS:{
5015  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5016  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
5017  COMPILE(ret, "alias arg1", node->u1.node);
5018  COMPILE(ret, "alias arg2", node->u2.node);
5020 
5021  if (poped) {
5022  ADD_INSN(ret, line, pop);
5023  }
5024  break;
5025  }
5026  case NODE_VALIAS:{
5027  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5028  ADD_INSN1(ret, line, putobject, ID2SYM(node->u1.id));
5029  ADD_INSN1(ret, line, putobject, ID2SYM(node->u2.id));
5031 
5032  if (poped) {
5033  ADD_INSN(ret, line, pop);
5034  }
5035  break;
5036  }
5037  case NODE_UNDEF:{
5038  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5039  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
5040  COMPILE(ret, "undef arg", node->u2.node);
5041  ADD_SEND(ret, line, ID2SYM(id_core_undef_method), INT2FIX(2));
5042 
5043  if (poped) {
5044  ADD_INSN(ret, line, pop);
5045  }
5046  break;
5047  }
5048  case NODE_CLASS:{
5049  VALUE iseqval =
5051  node->nd_body,
5052  rb_sprintf("<class:%s>", rb_id2name(node->nd_cpath->nd_mid)),
5053  ISEQ_TYPE_CLASS, line);
5054  VALUE noscope = compile_cpath(ret, iseq, node->nd_cpath);
5056  if (!noscope) flags |= VM_DEFINECLASS_FLAG_SCOPED;
5057  if (node->nd_super) flags |= VM_DEFINECLASS_FLAG_HAS_SUPERCLASS;
5058  COMPILE(ret, "super", node->nd_super);
5059  ADD_INSN3(ret, line, defineclass,
5060  ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(flags));
5061 
5062  if (poped) {
5063  ADD_INSN(ret, line, pop);
5064  }
5065  break;
5066  }
5067  case NODE_MODULE:{
5068  VALUE iseqval = NEW_CHILD_ISEQVAL(
5069  node->nd_body,
5070  rb_sprintf("<module:%s>", rb_id2name(node->nd_cpath->nd_mid)),
5071  ISEQ_TYPE_CLASS, line);
5072 
5073  VALUE noscope = compile_cpath(ret, iseq, node->nd_cpath);
5075  if (!noscope) flags |= VM_DEFINECLASS_FLAG_SCOPED;
5076  ADD_INSN (ret, line, putnil); /* dummy */
5077  ADD_INSN3(ret, line, defineclass,
5078  ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(flags));
5079  if (poped) {
5080  ADD_INSN(ret, line, pop);
5081  }
5082  break;
5083  }
5084  case NODE_SCLASS:{
5085  ID singletonclass;
5086  VALUE iseqval =
5087  NEW_ISEQVAL(node->nd_body, rb_str_new2("singleton class"),
5088  ISEQ_TYPE_CLASS, line);
5089 
5090  COMPILE(ret, "sclass#recv", node->nd_recv);
5091  ADD_INSN (ret, line, putnil);
5092  CONST_ID(singletonclass, "singletonclass");
5093  ADD_INSN3(ret, line, defineclass,
5094  ID2SYM(singletonclass), iseqval,
5096 
5097  if (poped) {
5098  ADD_INSN(ret, line, pop);
5099  }
5100  break;
5101  }
5102  case NODE_COLON2:{
5103  if (rb_is_const_id(node->nd_mid)) {
5104  /* constant */
5105  LABEL *lend = NEW_LABEL(line);
5106  int ic_index = iseq->is_size++;
5107 
5108  DECL_ANCHOR(pref);
5109  DECL_ANCHOR(body);
5110 
5111  INIT_ANCHOR(pref);
5112  INIT_ANCHOR(body);
5113  compile_colon2(iseq, node, pref, body);
5114  if (LIST_SIZE_ZERO(pref)) {
5115  if (iseq->compile_data->option->inline_const_cache) {
5116  ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index));
5117  }
5118  else {
5119  ADD_INSN(ret, line, putnil);
5120  }
5121 
5122  ADD_SEQ(ret, body);
5123 
5124  if (iseq->compile_data->option->inline_const_cache) {
5125  ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index));
5126  ADD_LABEL(ret, lend);
5127  }
5128  }
5129  else {
5130  ADD_SEQ(ret, pref);
5131  ADD_SEQ(ret, body);
5132  }
5133  }
5134  else {
5135  /* function call */
5136  ADD_CALL_RECEIVER(ret, line);
5137  COMPILE(ret, "colon2#nd_head", node->nd_head);
5138  ADD_CALL(ret, line, ID2SYM(node->nd_mid),
5139  INT2FIX(1));
5140  }
5141  if (poped) {
5142  ADD_INSN(ret, line, pop);
5143  }
5144  break;
5145  }
5146  case NODE_COLON3:{
5147  LABEL *lend = NEW_LABEL(line);
5148  int ic_index = iseq->is_size++;
5149 
5150  debugi("colon3#nd_mid", node->nd_mid);
5151 
5152  /* add cache insn */
5153  if (iseq->compile_data->option->inline_const_cache) {
5154  ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index));
5155  ADD_INSN(ret, line, pop);
5156  }
5157 
5158  ADD_INSN1(ret, line, putobject, rb_cObject);
5159  ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_mid));
5160 
5161  if (iseq->compile_data->option->inline_const_cache) {
5162  ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index));
5163  ADD_LABEL(ret, lend);
5164  }
5165 
5166  if (poped) {
5167  ADD_INSN(ret, line, pop);
5168  }
5169  break;
5170  }
5171  case NODE_DOT2:
5172  case NODE_DOT3:{
5173  VALUE flag = type == NODE_DOT2 ? INT2FIX(0) : INT2FIX(1);
5174  COMPILE(ret, "min", (NODE *) node->nd_beg);
5175  COMPILE(ret, "max", (NODE *) node->nd_end);
5176  if (poped) {
5177  ADD_INSN(ret, line, pop);
5178  ADD_INSN(ret, line, pop);
5179  }
5180  else {
5181  ADD_INSN1(ret, line, newrange, flag);
5182  }
5183  break;
5184  }
5185  case NODE_FLIP2:
5186  case NODE_FLIP3:{
5187  LABEL *lend = NEW_LABEL(line);
5188  LABEL *lfin = NEW_LABEL(line);
5189  LABEL *ltrue = NEW_LABEL(line);
5190  rb_iseq_t *local_iseq = iseq->local_iseq;
5191  rb_num_t cnt;
5192  VALUE key;
5193 
5194  cnt = local_iseq->flip_cnt++ + DEFAULT_SPECIAL_VAR_COUNT;
5195  key = INT2FIX(cnt);
5196 
5197  ADD_INSN2(ret, line, getspecial, key, INT2FIX(0));
5198  ADD_INSNL(ret, line, branchif, lend);
5199 
5200  /* *flip == 0 */
5201  COMPILE(ret, "flip2 beg", node->nd_beg);
5202  ADD_INSN(ret, line, dup);
5203  ADD_INSNL(ret, line, branchunless, lfin);
5204  if (nd_type(node) == NODE_FLIP3) {
5205  ADD_INSN(ret, line, dup);
5206  ADD_INSN1(ret, line, setspecial, key);
5207  ADD_INSNL(ret, line, jump, lfin);
5208  }
5209  else {
5210  ADD_INSN1(ret, line, setspecial, key);
5211  }
5212 
5213  /* *flip == 1 */
5214  ADD_LABEL(ret, lend);
5215  COMPILE(ret, "flip2 end", node->nd_end);
5216  ADD_INSNL(ret, line, branchunless, ltrue);
5217  ADD_INSN1(ret, line, putobject, Qfalse);
5218  ADD_INSN1(ret, line, setspecial, key);
5219 
5220  ADD_LABEL(ret, ltrue);
5221  ADD_INSN1(ret, line, putobject, Qtrue);
5222 
5223  ADD_LABEL(ret, lfin);
5224  break;
5225  }
5226  case NODE_SELF:{
5227  if (!poped) {
5228  ADD_INSN(ret, line, putself);
5229  }
5230  break;
5231  }
5232  case NODE_NIL:{
5233  if (!poped) {
5234  ADD_INSN(ret, line, putnil);
5235  }
5236  break;
5237  }
5238  case NODE_TRUE:{
5239  if (!poped) {
5240  ADD_INSN1(ret, line, putobject, Qtrue);
5241  }
5242  break;
5243  }
5244  case NODE_FALSE:{
5245  if (!poped) {
5246  ADD_INSN1(ret, line, putobject, Qfalse);
5247  }
5248  break;
5249  }
5250  case NODE_ERRINFO:{
5251  if (!poped) {
5252  if (iseq->type == ISEQ_TYPE_RESCUE) {
5253  ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0));
5254  }
5255  else {
5256  rb_iseq_t *ip = iseq;
5257  int level = 0;
5258  while (ip) {
5259  if (ip->type == ISEQ_TYPE_RESCUE) {
5260  break;
5261  }
5262  ip = ip->parent_iseq;
5263  level++;
5264  }
5265  if (ip) {
5266  ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(level));
5267  }
5268  else {
5269  ADD_INSN(ret, line, putnil);
5270  }
5271  }
5272  }
5273  break;
5274  }
5275  case NODE_DEFINED:{
5276  if (poped) break;
5277  if (!node->nd_head) {
5279  ADD_INSN1(ret, nd_line(node), putobject, str);
5280  }
5281  else {
5282  LABEL *lfinish[2];
5283  lfinish[0] = NEW_LABEL(line);
5284  lfinish[1] = 0;
5285  ADD_INSN(ret, line, putnil);
5286  defined_expr(iseq, ret, node->nd_head, lfinish, Qtrue);
5287  ADD_INSN(ret, line, swap);
5288  ADD_INSN(ret, line, pop);
5289  if (lfinish[1]) {
5290  ADD_LABEL(ret, lfinish[1]);
5291  }
5292  ADD_LABEL(ret, lfinish[0]);
5293  }
5294  break;
5295  }
5296  case NODE_POSTEXE:{
5297  /* compiled to:
5298  * ONCE{ rb_mRubyVMFrozenCore::core#set_postexe{ ... } }
5299  */
5300  int is_index = iseq->is_size++;
5301  VALUE once_iseq = NEW_CHILD_ISEQVAL(
5302  NEW_IFUNC(build_postexe_iseq, node->nd_body),
5303  make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
5304 
5305  ADD_INSN2(ret, line, once, once_iseq, INT2FIX(is_index));
5306 
5307  if (poped) {
5308  ADD_INSN(ret, line, pop);
5309  }
5310  break;
5311  }
5312  case NODE_KW_ARG:{
5313  LABEL *default_label = NEW_LABEL(line);
5314  LABEL *end_label = 0;
5315  int idx, lv, ls;
5316  ID id = node->nd_body->nd_vid;
5317 
5318  ADD_INSN(ret, line, dup);
5319  ADD_INSN1(ret, line, putobject, ID2SYM(id));
5320  ADD_SEND(ret, line, ID2SYM(rb_intern("key?")), INT2FIX(1));
5321  ADD_INSNL(ret, line, branchunless, default_label);
5322  ADD_INSN(ret, line, dup);
5323  ADD_INSN1(ret, line, putobject, ID2SYM(id));
5324  ADD_SEND(ret, line, ID2SYM(rb_intern("delete")), INT2FIX(1));
5325  switch (nd_type(node->nd_body)) {
5326  case NODE_LASGN:
5327  idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id);
5328  ADD_INSN2(ret, line, setlocal, INT2FIX(idx), INT2FIX(get_lvar_level(iseq)));
5329  break;
5330  case NODE_DASGN:
5331  case NODE_DASGN_CURR:
5332  idx = get_dyna_var_idx(iseq, id, &lv, &ls);
5333  ADD_INSN2(ret, line, setlocal, INT2FIX(ls - idx), INT2FIX(lv));
5334  break;
5335  default:
5336  rb_bug("iseq_compile_each (NODE_KW_ARG): unknown node: %s", ruby_node_name(nd_type(node->nd_body)));
5337  }
5338  if (node->nd_body->nd_value != (NODE *)-1) {
5339  end_label = NEW_LABEL(nd_line(node));
5340  ADD_INSNL(ret, nd_line(node), jump, end_label);
5341  }
5342  ADD_LABEL(ret, default_label);
5343  if (node->nd_body->nd_value != (NODE *)-1) {
5344  COMPILE_POPED(ret, "keyword default argument", node->nd_body);
5345  ADD_LABEL(ret, end_label);
5346  }
5347  break;
5348  }
5349  case NODE_DSYM:{
5350  compile_dstr(iseq, ret, node);
5351  if (!poped) {
5352  ADD_SEND(ret, line, ID2SYM(idIntern), INT2FIX(0));
5353  }
5354  else {
5355  ADD_INSN(ret, line, pop);
5356  }
5357  break;
5358  }
5359  case NODE_ATTRASGN:{
5360  DECL_ANCHOR(recv);
5361  DECL_ANCHOR(args);
5362  VALUE flag = 0;
5363  VALUE argc;
5364 
5365  INIT_ANCHOR(recv);
5366  INIT_ANCHOR(args);
5367  argc = setup_args(iseq, args, node->nd_args, &flag);
5368 
5369  if (node->nd_recv == (NODE *) 1) {
5370  flag |= VM_CALL_FCALL;
5371  ADD_INSN(recv, line, putself);
5372  }
5373  else {
5374  COMPILE(recv, "recv", node->nd_recv);
5375  }
5376 
5377  debugp_param("argc", argc);
5378  debugp_param("nd_mid", ID2SYM(node->nd_mid));
5379 
5380  if (!poped) {
5381  ADD_INSN(ret, line, putnil);
5382  ADD_SEQ(ret, recv);
5383  ADD_SEQ(ret, args);
5384 
5385  if (flag & VM_CALL_ARGS_BLOCKARG) {
5386  ADD_INSN1(ret, line, topn, INT2FIX(1));
5387  if (flag & VM_CALL_ARGS_SPLAT) {
5388  ADD_INSN1(ret, line, putobject, INT2FIX(-1));
5389  ADD_SEND(ret, line, ID2SYM(idAREF), INT2FIX(1));
5390  }
5391  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 3));
5392  ADD_INSN (ret, line, pop);
5393  }
5394  else if (flag & VM_CALL_ARGS_SPLAT) {
5395  ADD_INSN(ret, line, dup);
5396  ADD_INSN1(ret, line, putobject, INT2FIX(-1));
5397  ADD_SEND(ret, line, ID2SYM(idAREF), INT2FIX(1));
5398  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2));
5399  ADD_INSN (ret, line, pop);
5400  }
5401  else {
5402  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 1));
5403  }
5404  }
5405  else {
5406  ADD_SEQ(ret, recv);
5407  ADD_SEQ(ret, args);
5408  }
5409  ADD_SEND_R(ret, line, ID2SYM(node->nd_mid), argc, 0, LONG2FIX(flag));
5410  ADD_INSN(ret, line, pop);
5411 
5412  break;
5413  }
5414  case NODE_PRELUDE:{
5415  COMPILE_POPED(ret, "prelude", node->nd_head);
5416  COMPILE_(ret, "body", node->nd_body, poped);
5417  break;
5418  }
5419  case NODE_LAMBDA:{
5420  /* compile same as lambda{...} */
5421  VALUE block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
5422  VALUE argc = INT2FIX(0);
5423  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5424  ADD_CALL_WITH_BLOCK(ret, line, ID2SYM(idLambda), argc, block);
5425 
5426  if (poped) {
5427  ADD_INSN(ret, line, pop);
5428  }
5429  break;
5430  }
5431  default:
5432  rb_bug("iseq_compile_each: unknown node: %s", ruby_node_name(type));
5433  return COMPILE_NG;
5434  }
5435 
5436  /* check & remove redundant trace(line) */
5437  if (saved_last_element && ret /* ret can be 0 when error */ &&
5438  ret->last == saved_last_element &&
5439  ((INSN *)saved_last_element)->insn_id == BIN(trace)) {
5440  POP_ELEMENT(ret);
5441  }
5442 
5443  debug_node_end();
5444  return COMPILE_OK;
5445 }
5446 
5447 /***************************/
5448 /* instruction information */
5449 /***************************/
5450 
5451 static int
5453 {
5454  return insn_len(iobj->insn_id);
5455 }
5456 
5457 static int
5459 {
5460  return insn_stack_increase(depth, insn->insn_id, insn->operands);
5461 }
5462 
5463 static VALUE
5465 {
5466  struct RBasic *r = (struct RBasic *) obj;
5467  if (!SPECIAL_CONST_P(r) && r->klass == 0) {
5468  switch (BUILTIN_TYPE(r)) {
5469  case T_STRING:
5470  obj = rb_str_new_cstr(RSTRING_PTR(obj));
5471  break;
5472  case T_ARRAY:
5473  obj = rb_ary_dup(obj);
5474  break;
5475  }
5476  }
5477  return rb_inspect(obj);
5478 }
5479 
5480 
5481 
5482 static VALUE
5484 {
5485  VALUE str = rb_sprintf("%-20s ", insn_name(iobj->insn_id));
5486 
5487  if (iobj->operands) {
5488  const char *types = insn_op_types(iobj->insn_id);
5489  int j;
5490 
5491  for (j = 0; types[j]; j++) {
5492  char type = types[j];
5493 
5494  switch (type) {
5495  case TS_OFFSET: /* label(destination position) */
5496  {
5497  LABEL *lobj = (LABEL *)OPERAND_AT(iobj, j);
5498  rb_str_catf(str, "<L%03d>", lobj->label_no);
5499  break;
5500  }
5501  break;
5502  case TS_ISEQ: /* iseq */
5503  {
5504  rb_iseq_t *iseq = (rb_iseq_t *)OPERAND_AT(iobj, j);
5505  VALUE val = Qnil;
5506  if (0 && iseq) { /* TODO: invalidate now */
5507  val = iseq->self;
5508  }
5509  rb_str_concat(str, opobj_inspect(val));
5510  }
5511  break;
5512  case TS_LINDEX:
5513  case TS_NUM: /* ulong */
5514  case TS_VALUE: /* VALUE */
5515  {
5516  VALUE v = OPERAND_AT(iobj, j);
5517  rb_str_concat(str, opobj_inspect(v));
5518  break;
5519  }
5520  case TS_ID: /* ID */
5521  rb_str_concat(str, opobj_inspect(OPERAND_AT(iobj, j)));
5522  break;
5523  case TS_GENTRY:
5524  {
5525  struct rb_global_entry *entry = (struct rb_global_entry *)
5526  (OPERAND_AT(iobj, j) & (~1));
5527  rb_str_cat2(str, rb_id2name(entry->id));
5528  break;
5529  }
5530  case TS_IC: /* inline cache */
5531  rb_str_catf(str, "<ic:%d>", FIX2INT(OPERAND_AT(iobj, j)));
5532  break;
5533  case TS_CALLINFO: /* call info */
5534  {
5535  rb_call_info_t *ci = (rb_call_info_t *)OPERAND_AT(iobj, j);
5536  rb_str_catf(str, "<callinfo:%s, %d>", ci->mid ? rb_id2name(ci->mid) : "", ci->orig_argc);
5537  break;
5538  }
5539  case TS_CDHASH: /* case/when condition cache */
5540  rb_str_cat2(str, "<ch>");
5541  break;
5542  default:{
5543  rb_raise(rb_eSyntaxError, "unknown operand type: %c", type);
5544  }
5545  }
5546  if (types[j + 1]) {
5547  rb_str_cat2(str, ", ");
5548  }
5549  }
5550  }
5551  return str;
5552 }
5553 
5554 static void
5556 {
5557  int pos = 0;
5558  INSN *iobj;
5559  LABEL *lobj;
5560  VALUE str;
5561 
5562  printf("-- raw disasm--------\n");
5563 
5564  while (link) {
5565  switch (link->type) {
5566  case ISEQ_ELEMENT_INSN:
5567  {
5568  iobj = (INSN *)link;
5569  str = insn_data_to_s_detail(iobj);
5570  printf("%04d %-65s(%4d)\n", pos, StringValueCStr(str), iobj->line_no);
5571  pos += insn_data_length(iobj);
5572  break;
5573  }
5574  case ISEQ_ELEMENT_LABEL:
5575  {
5576  lobj = (LABEL *)link;
5577  printf("<L%03d>\n", lobj->label_no);
5578  break;
5579  }
5580  case ISEQ_ELEMENT_NONE:
5581  {
5582  printf("[none]\n");
5583  break;
5584  }
5585  case ISEQ_ELEMENT_ADJUST:
5586  {
5587  ADJUST *adjust = (ADJUST *)link;
5588  printf("adjust: [label: %d]\n", adjust->label ? adjust->label->label_no : -1);
5589  break;
5590  }
5591  default:
5592  /* ignore */
5593  rb_raise(rb_eSyntaxError, "dump_disasm_list error: %ld\n", FIX2LONG(link->type));
5594  }
5595  link = link->next;
5596  }
5597  printf("---------------------\n");
5598 }
5599 
5600 const char *
5602 {
5603  return insn_name_info[i];
5604 }
5605 
5606 VALUE
5608 {
5609  VALUE ary = rb_ary_new();
5610  int i;
5611  for (i = 0; i < numberof(insn_name_info); i++) {
5612  rb_ary_push(ary, rb_fstring(rb_str_new2(insn_name_info[i])));
5613  }
5614  return rb_obj_freeze(ary);
5615 }
5616 
5617 static LABEL *
5618 register_label(rb_iseq_t *iseq, struct st_table *labels_table, VALUE obj)
5619 {
5620  LABEL *label = 0;
5621  st_data_t tmp;
5622  obj = rb_convert_type(obj, T_SYMBOL, "Symbol", "to_sym");
5623 
5624  if (st_lookup(labels_table, obj, &tmp) == 0) {
5625  label = NEW_LABEL(0);
5626  st_insert(labels_table, obj, (st_data_t)label);
5627  }
5628  else {
5629  label = (LABEL *)tmp;
5630  }
5631  return label;
5632 }
5633 
5634 static VALUE
5636 {
5637 #undef rb_intern
5638 #define rb_intern(str) rb_intern_const(str)
5640  static VALUE symRescue, symEnsure, symRetry;
5641  static VALUE symBreak, symRedo, symNext;
5642 
5643  if (symRescue == 0) {
5644  symRescue = ID2SYM(rb_intern("rescue"));
5645  symEnsure = ID2SYM(rb_intern("ensure"));
5646  symRetry = ID2SYM(rb_intern("retry"));
5647  symBreak = ID2SYM(rb_intern("break"));
5648  symRedo = ID2SYM(rb_intern("redo"));
5649  symNext = ID2SYM(rb_intern("next"));
5650  }
5651 
5652  if (sym == symRescue) return CATCH_TYPE_RESCUE;
5653  if (sym == symEnsure) return CATCH_TYPE_ENSURE;
5654  if (sym == symRetry) return CATCH_TYPE_RETRY;
5655  if (sym == symBreak) return CATCH_TYPE_BREAK;
5656  if (sym == symRedo) return CATCH_TYPE_REDO;
5657  if (sym == symNext) return CATCH_TYPE_NEXT;
5658  sym_inspect = rb_inspect(sym);
5659  rb_raise(rb_eSyntaxError, "invalid exception symbol: %s",
5660  StringValuePtr(sym_inspect));
5661  return 0;
5662 }
5663 
5664 static int
5666  VALUE exception)
5667 {
5668  int i;
5669 
5670  for (i=0; i<RARRAY_LEN(exception); i++) {
5671  VALUE v, type, eiseqval;
5672  const VALUE *ptr;
5673  LABEL *lstart, *lend, *lcont;
5674  int sp;
5675 
5676  RB_GC_GUARD(v) = rb_convert_type(RARRAY_AREF(exception, i), T_ARRAY,
5677  "Array", "to_ary");
5678  if (RARRAY_LEN(v) != 6) {
5679  rb_raise(rb_eSyntaxError, "wrong exception entry");
5680  }
5681  ptr = RARRAY_CONST_PTR(v);
5682  type = get_exception_sym2type(ptr[0]);
5683  if (ptr[1] == Qnil) {
5684  eiseqval = 0;
5685  }
5686  else {
5687  eiseqval = rb_iseq_load(ptr[1], iseq->self, Qnil);
5688  }
5689 
5690  lstart = register_label(iseq, labels_table, ptr[2]);
5691  lend = register_label(iseq, labels_table, ptr[3]);
5692  lcont = register_label(iseq, labels_table, ptr[4]);
5693  sp = NUM2INT(ptr[5]);
5694 
5695  (void)sp;
5696 
5697  ADD_CATCH_ENTRY(type, lstart, lend, eiseqval, lcont);
5698  }
5699  return COMPILE_OK;
5700 }
5701 
5702 static struct st_table *
5704 {
5705  struct st_table *table;
5706  int i;
5707  table = st_init_numtable();
5708 
5709  for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
5710  st_insert(table, ID2SYM(rb_intern(insn_name(i))), i);
5711  }
5712 
5713  return table;
5714 }
5715 
5716 static VALUE
5718 {
5719  VALUE iseqval;
5720  if (RB_TYPE_P(op, T_ARRAY)) {
5721  iseqval = rb_iseq_load(op, iseq->self, Qnil);
5722  }
5723  else if (CLASS_OF(op) == rb_cISeq) {
5724  iseqval = op;
5725  }
5726  else {
5727  rb_raise(rb_eSyntaxError, "ISEQ is required");
5728  }
5729  iseq_add_mark_object(iseq, iseqval);
5730  return iseqval;
5731 }
5732 
5733 static int
5735  VALUE body, struct st_table *labels_table)
5736 {
5737  /* TODO: body should be frozen */
5738  const VALUE *ptr = RARRAY_CONST_PTR(body);
5739  long i, len = RARRAY_LEN(body);
5740  int j;
5741  int line_no = 0;
5742 
5743  /*
5744  * index -> LABEL *label
5745  */
5746  static struct st_table *insn_table;
5747 
5748  if (insn_table == 0) {
5749  insn_table = insn_make_insn_table();
5750  }
5751 
5752  for (i=0; i<len; i++) {
5753  VALUE obj = ptr[i];
5754 
5755  if (SYMBOL_P(obj)) {
5756  LABEL *label = register_label(iseq, labels_table, obj);
5757  ADD_LABEL(anchor, label);
5758  }
5759  else if (FIXNUM_P(obj)) {
5760  line_no = NUM2INT(obj);
5761  }
5762  else if (RB_TYPE_P(obj, T_ARRAY)) {
5763  VALUE *argv = 0;
5764  int argc = RARRAY_LENINT(obj) - 1;
5765  st_data_t insn_id;
5766  VALUE insn;
5767 
5768  insn = (argc < 0) ? Qnil : RARRAY_AREF(obj, 0);
5769  if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) {
5770  /* TODO: exception */
5771  RB_GC_GUARD(insn) = rb_inspect(insn);
5772  rb_compile_error(RSTRING_PTR(iseq->location.path), line_no,
5773  "unknown instruction: %s", RSTRING_PTR(insn));
5774  }
5775 
5776  if (argc != insn_len((VALUE)insn_id)-1) {
5777  rb_compile_error(RSTRING_PTR(iseq->location.path), line_no,
5778  "operand size mismatch");
5779  }
5780 
5781  if (argc > 0) {
5782  argv = compile_data_alloc(iseq, sizeof(VALUE) * argc);
5783  for (j=0; j<argc; j++) {
5784  VALUE op = rb_ary_entry(obj, j+1);
5785  switch (insn_op_type((VALUE)insn_id, j)) {
5786  case TS_OFFSET: {
5787  LABEL *label = register_label(iseq, labels_table, op);
5788  argv[j] = (VALUE)label;
5789  break;
5790  }
5791  case TS_LINDEX:
5792  case TS_NUM:
5793  (void)NUM2INT(op);
5794  argv[j] = op;
5795  break;
5796  case TS_VALUE:
5797  argv[j] = op;
5798  iseq_add_mark_object(iseq, op);
5799  break;
5800  case TS_ISEQ:
5801  {
5802  if (op != Qnil) {
5803  argv[j] = iseq_build_load_iseq(iseq, op);
5804  }
5805  else {
5806  argv[j] = 0;
5807  }
5808  }
5809  break;
5810  case TS_GENTRY:
5811  op = rb_convert_type(op, T_SYMBOL, "Symbol", "to_sym");
5812  argv[j] = (VALUE)rb_global_entry(SYM2ID(op));
5813  break;
5814  case TS_IC:
5815  argv[j] = op;
5816  if (NUM2INT(op) >= iseq->is_size) {
5817  iseq->is_size = NUM2INT(op) + 1;
5818  }
5819  break;
5820  case TS_CALLINFO:
5821  {
5822  ID mid = 0;
5823  int orig_argc = 0;
5824  VALUE block = 0;
5825  unsigned long flag = 0;
5826 
5827  if (!NIL_P(op)) {
5828  VALUE vmid = rb_hash_aref(op, ID2SYM(rb_intern("mid")));
5829  VALUE vflag = rb_hash_aref(op, ID2SYM(rb_intern("flag")));
5830  VALUE vorig_argc = rb_hash_aref(op, ID2SYM(rb_intern("orig_argc")));
5831  VALUE vblock = rb_hash_aref(op, ID2SYM(rb_intern("blockptr")));
5832 
5833  if (!NIL_P(vmid)) mid = SYM2ID(vmid);
5834  if (!NIL_P(vflag)) flag = NUM2ULONG(vflag);
5835  if (!NIL_P(vorig_argc)) orig_argc = FIX2INT(vorig_argc);
5836  if (!NIL_P(vblock)) block = iseq_build_load_iseq(iseq, vblock);
5837  }
5838  argv[j] = (VALUE)new_callinfo(iseq, mid, orig_argc, block, flag);
5839  }
5840  break;
5841  case TS_ID:
5842  argv[j] = rb_convert_type(op, T_SYMBOL,
5843  "Symbol", "to_sym");
5844  break;
5845  case TS_CDHASH:
5846  {
5847  int i;
5848  op = rb_convert_type(op, T_ARRAY, "Array", "to_ary");
5849  op = rb_ary_dup(op);
5850  for (i=0; i<RARRAY_LEN(op); i+=2) {
5851  VALUE sym = rb_ary_entry(op, i+1);
5852  LABEL *label =
5853  register_label(iseq, labels_table, sym);
5854  rb_ary_store(op, i+1, (VALUE)label | 1);
5855  }
5856  argv[j] = op;
5858  }
5859  break;
5860  default:
5861  rb_raise(rb_eSyntaxError, "unknown operand: %c", insn_op_type((VALUE)insn_id, j));
5862  }
5863  }
5864  }
5865  ADD_ELEM(anchor,
5866  (LINK_ELEMENT*)new_insn_core(iseq, line_no,
5867  (enum ruby_vminsn_type)insn_id, argc, argv));
5868  }
5869  else {
5870  rb_raise(rb_eTypeError, "unexpected object for instruction");
5871  }
5872  }
5873  validate_labels(iseq, labels_table);
5874  st_free_table(labels_table);
5875  iseq_setup(iseq, anchor);
5876  return COMPILE_OK;
5877 }
5878 
5879 #define CHECK_ARRAY(v) rb_convert_type((v), T_ARRAY, "Array", "to_ary")
5880 #define CHECK_STRING(v) rb_convert_type((v), T_STRING, "String", "to_str")
5881 #define CHECK_SYMBOL(v) rb_convert_type((v), T_SYMBOL, "Symbol", "to_sym")
5882 static inline VALUE CHECK_INTEGER(VALUE v) {(void)NUM2LONG(v); return v;}
5883 
5884 VALUE
5886  VALUE exception, VALUE body)
5887 {
5888  int i;
5889  ID *tbl;
5890  struct st_table *labels_table = st_init_numtable();
5891  DECL_ANCHOR(anchor);
5892  INIT_ANCHOR(anchor);
5893 
5894  iseq->local_table_size = RARRAY_LENINT(locals);
5895  iseq->local_table = tbl = (ID *)ALLOC_N(ID, iseq->local_table_size);
5896  iseq->local_size = iseq->local_table_size + 1;
5897 
5898  for (i=0; i<RARRAY_LEN(locals); i++) {
5899  VALUE lv = RARRAY_AREF(locals, i);
5900  tbl[i] = FIXNUM_P(lv) ? (ID)FIX2LONG(lv) : SYM2ID(CHECK_SYMBOL(lv));
5901  }
5902 
5903  /* args */
5904  if (FIXNUM_P(args)) {
5905  iseq->arg_size = iseq->argc = FIX2INT(args);
5906  iseq->arg_simple = 1;
5907  }
5908  else {
5909  int i = 0;
5910  VALUE argc = CHECK_INTEGER(rb_ary_entry(args, i++));
5911  VALUE arg_opt_labels = CHECK_ARRAY(rb_ary_entry(args, i++));
5912  VALUE arg_post_len = CHECK_INTEGER(rb_ary_entry(args, i++));
5913  VALUE arg_post_start = CHECK_INTEGER(rb_ary_entry(args, i++));
5914  VALUE arg_rest = CHECK_INTEGER(rb_ary_entry(args, i++));
5915  VALUE arg_block = CHECK_INTEGER(rb_ary_entry(args, i++));
5916  VALUE arg_simple = CHECK_INTEGER(rb_ary_entry(args, i++));
5917 
5918  iseq->argc = FIX2INT(argc);
5919  iseq->arg_rest = FIX2INT(arg_rest);
5920  iseq->arg_post_len = FIX2INT(arg_post_len);
5921  iseq->arg_post_start = FIX2INT(arg_post_start);
5922  iseq->arg_block = FIX2INT(arg_block);
5923  iseq->arg_opts = RARRAY_LENINT(arg_opt_labels);
5924  iseq->arg_opt_table = (VALUE *)ALLOC_N(VALUE, iseq->arg_opts);
5925 
5926  if (iseq->arg_block != -1) {
5927  iseq->arg_size = iseq->arg_block + 1;
5928  }
5929  else if (iseq->arg_post_len) {
5930  iseq->arg_size = iseq->arg_post_start + iseq->arg_post_len;
5931  }
5932  else if (iseq->arg_rest != -1) {
5933  iseq->arg_size = iseq->arg_rest + 1;
5934  }
5935  else {
5936  iseq->arg_size = iseq->argc + (iseq->arg_opts ? iseq->arg_opts - 1 : 0);
5937  }
5938 
5939  for (i=0; i<RARRAY_LEN(arg_opt_labels); i++) {
5940  iseq->arg_opt_table[i] =
5941  (VALUE)register_label(iseq, labels_table,
5942  rb_ary_entry(arg_opt_labels, i));
5943  }
5944 
5945  iseq->arg_simple = NUM2INT(arg_simple);
5946  }
5947 
5948  /* exception */
5949  iseq_build_from_ary_exception(iseq, labels_table, exception);
5950 
5951  /* body */
5952  iseq_build_from_ary_body(iseq, anchor, body, labels_table);
5953  return iseq->self;
5954 }
5955 
5956 /* for parser */
5957 
5958 int
5960 {
5961  rb_thread_t *th = GET_THREAD();
5962  rb_iseq_t *iseq;
5963  if (th->base_block && (iseq = th->base_block->iseq)) {
5964  while (iseq->type == ISEQ_TYPE_BLOCK ||
5965  iseq->type == ISEQ_TYPE_RESCUE ||
5966  iseq->type == ISEQ_TYPE_ENSURE ||
5967  iseq->type == ISEQ_TYPE_EVAL ||
5968  iseq->type == ISEQ_TYPE_MAIN
5969  ) {
5970  int i;
5971 
5972  for (i = 0; i < iseq->local_table_size; i++) {
5973  if (iseq->local_table[i] == id) {
5974  return 1;
5975  }
5976  }
5977  iseq = iseq->parent_iseq;
5978  }
5979  }
5980  return 0;
5981 }
5982 
5983 int
5985 {
5986  rb_thread_t *th = GET_THREAD();
5987  rb_iseq_t *iseq;
5988 
5989  if (th->base_block && th->base_block->iseq) {
5990  int i;
5991  iseq = th->base_block->iseq->local_iseq;
5992 
5993  for (i=0; i<iseq->local_table_size; i++) {
5994  if (iseq->local_table[i] == id) {
5995  return 1;
5996  }
5997  }
5998  }
5999  return 0;
6000 }
6001 
6002 int
6004 {
6005  return GET_THREAD()->parse_in_eval > 0;
6006 }
6007 
6008 int
6010 {
6011  return GET_THREAD()->parse_in_eval < 0;
6012 }
VALUE data
Definition: tcltklib.c:3360
rb_serial_t class_serial
Definition: vm_core.h:164
#define RB_TYPE_P(obj, type)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: ripper.y:20
#define cond(node)
Definition: ripper.c:427
#define nd_type(n)
LINK_ELEMENT link
Definition: compile.c:42
#define NODE_DREGX_ONCE
#define VM_CALL_ARGS_BLOCKARG
Definition: vm_core.h:745
#define DEFAULT_SPECIAL_VAR_COUNT
Definition: iseq.h:132
struct rb_block_struct * blockptr
Definition: vm_core.h:173
VALUE rb_eStandardError
Definition: error.c:546
#define NODE_IF
#define NODE_RESCUE
#define NODE_RETRY
int arg_simple
Definition: vm_core.h:275
static int iseq_add_mark_object(rb_iseq_t *iseq, VALUE v)
Definition: compile.c:414
#define RUBY_EVENT_B_RETURN
static int iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
Definition: compile.c:1846
#define NODE_DEFN
int register char * block
Definition: crypt.c:949
VALUE sym
Definition: tkutil.c:1299
#define NODE_FALSE
VP_EXPORT int
Definition: bigdecimal.c:5179
#define NODE_OR
#define NODE_LAMBDA
static VALUE compile_array(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node_root, enum compile_array_type_t type)
Definition: compile.c:2563
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1171
int rb_eql(VALUE, VALUE)
Definition: object.c:100
void rb_bug(const char *fmt,...)
Definition: error.c:327
static void verify_list(ISEQ_ARG_DECLARE const char *info, LINK_ANCHOR *anchor)
Definition: compile.c:352
answer
Definition: dir.c:1286
void rb_compile_error(const char *file, int line, const char *fmt,...)
Definition: error.c:145
#define RB_OBJ_WRITE(a, slot, b)
#define FALSE
Definition: nkf.h:174
#define OPERAND_AT(insn, idx)
Definition: compile.c:268
static ADJUST * compile_data_alloc_adjust(rb_iseq_t *iseq)
Definition: compile.c:690
#define ADD_INSN2(seq, line, insn, op1, op2)
Definition: compile.c:195
#define rb_hash_lookup
Definition: tcltklib.c:269
memo u1 value
Definition: enum.c:587
static VALUE VALUE th
Definition: tcltklib.c:2944
unsigned long size
Definition: iseq.h:76
#define VM_CALL_FCALL
Definition: vm_core.h:746
#define RUBY_EVENT_CLASS
static int compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int poped)
Definition: compile.c:2745
VALUE rb_id2str(ID id)
Definition: ripper.c:17160
rb_serial_t method_state
Definition: vm_core.h:163
ID * arg_keyword_table
Definition: vm_core.h:287
#define NODE_DSYM
unsigned long end
Definition: iseq.h:66
static int insn_data_length(INSN *iobj)
Definition: compile.c:5452
#define NODE_DEFS
static void push_ensure_entry(rb_iseq_t *iseq, struct iseq_compile_data_ensure_node_stack *enl, struct ensure_range *er, NODE *node)
Definition: compile.c:3086
static int max(int a, int b)
Definition: strftime.c:141
int st_lookup(st_table *, st_data_t, st_data_t *)
#define NODE_HASH
#define CPDEBUG
debug function(macro) interface depend on CPDEBUG if it is less than 0, runtime option is in effect...
Definition: compile.c:91
struct ensure_range * next
Definition: compile.c:68
#define NODE_DOT3
#define COMPILE_NG
Definition: compile.c:291
st_table * st_init_numtable(void)
Definition: st.c:272
static int VALUE table
Definition: tcltklib.c:10086
VALUE * operands
Definition: compile.c:56
#define NODE_VCALL
#define NEW_LABEL(l)
Definition: compile.c:165
struct iseq_compile_data * compile_data
Definition: vm_core.h:323
#define NODE_NTH_REF
rb_iseq_t * iseq
Definition: vm_core.h:466
#define NODE_TRUE
Tcl_CmdInfo * info
Definition: tcltklib.c:1467
#define SP_INSN(opt)
VALUE rb_insns_name_array(void)
Definition: compile.c:5607
#define RUBY_EVENT_LINE
#define NODE_ITER
#define NODE_ARGS
#define NODE_MATCH3
const void ** rb_vm_get_insns_address_table(void)
Definition: vm_exec.c:118
#define RFLOAT_VALUE(v)
VALUE rb_str_new_cstr(const char *)
Definition: string.c:560
int ret
Definition: tcltklib.c:285
#define NODE_UNDEF
rb_call_info_t * callinfo_entries
Definition: vm_core.h:244
#define ADD_INSN(seq, line, insn)
Definition: compile.c:184
#define NEW_NIL()
Real * a
Definition: bigdecimal.c:1205
static INSN * compile_data_alloc_insn(rb_iseq_t *iseq)
Definition: compile.c:678
static int compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
Definition: compile.c:2346
VALUE rb_obj_freeze(VALUE)
Definition: object.c:1076
#define NODE_ENSURE
VALUE rb_eTypeError
Definition: error.c:548
static LABEL * compile_data_alloc_label(rb_iseq_t *iseq)
Definition: compile.c:684
#define OBJ_FREEZE(x)
int rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
Definition: compile.c:561
RB_GC_GUARD(args)
static INSN * new_insn_send(rb_iseq_t *iseq, int line_no, VALUE id, VALUE argc, VALUE block, VALUE flag)
Definition: compile.c:1036
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:896
NODE * kw_args
Definition: ripper.y:523
static int compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node_root, enum compile_array_type_t type, int poped)
Definition: compile.c:2415
static void validate_labels(rb_iseq_t *iseq, st_table *labels_table)
Definition: compile.c:450
#define debugi(header, id)
Definition: compile.c:146
#define NUM2ULONG(x)
static int iseq_build_from_ary_exception(rb_iseq_t *iseq, struct st_table *labels_table, VALUE exception)
Definition: compile.c:5665
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:534
VALUE rb_iseq_defined_string(enum defined_type type)
Definition: iseq.c:2039
* div
Definition: bigdecimal.c:1222
#define NODE_PRELUDE
VALUE(* call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_call_info_struct *ci)
Definition: vm_core.h:182
#define RSTRING_PTR(str)
#define CLASS_OF(v)
NIL_P(eventloop_thread)
Definition: tcltklib.c:4056
#define T_ARRAY
int local_table_size
Definition: vm_core.h:236
static int validate_label(st_data_t name, st_data_t label, st_data_t arg)
Definition: compile.c:434
#define NODE_SUPER
#define NODE_EVSTR
#define xfree
#define NODE_RESBODY
struct st_hash_type * type
Definition: ripper.y:70
LABEL * label
Definition: compile.c:61
struct rb_iseq_struct * local_iseq
Definition: vm_core.h:297
#define NODE_DXSTR
#define NODE_CASE
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
ID id
Definition: ripper.y:245
return Qtrue
Definition: tcltklib.c:9559
struct iseq_label_data * start_label
Definition: iseq.h:87
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3381
struct iseq_compile_data_storage * next
Definition: iseq.h:74
static int compile_colon2(rb_iseq_t *iseq, NODE *node, LINK_ANCHOR *pref, LINK_ANCHOR *body)
Definition: compile.c:2803
#define RUBY_EVENT_END
VALUE entry[3]
Definition: ossl_x509name.c:99
int pre_args_num
Definition: ripper.y:515
static LINK_ELEMENT * POP_ELEMENT(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor)
Definition: compile.c:765
#define VM_CALL_ARGS_SPLAT
Definition: vm_core.h:744
#define ADD_ADJUST(seq, line, label)
Definition: compile.c:241
NODE * kw_rest_arg
Definition: ripper.y:524
size_t stack_max
Definition: vm_core.h:289
int arg_keyword
Definition: vm_core.h:283
#define NODE_STR
#define VM_DEFINECLASS_FLAG_SCOPED
Definition: vm_core.h:666
Definition: ripper.y:83
#define NODE_REDO
#define NODE_NEXT
r
Definition: bigdecimal.c:1219
static int iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
Definition: compile.c:1059
tmp
Definition: enum.c:447
VALUE rb_iseq_compile_node(VALUE self, NODE *node)
Definition: compile.c:459
#define rb_str_new2
struct iseq_compile_data_ensure_node_stack * ensure_node_stack
Definition: iseq.h:93
ID id
Definition: ripper.y:502
#define ruby_sourcefile
Definition: compile.c:422
static ID r_id(ID id)
Definition: compile.c:135
#define NODE_XSTR
static void APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc1, LINK_ANCHOR *anc2)
Definition: compile.c:822
#define NODE_BLOCK_PASS
int size
Definition: encoding.c:49
struct st_table * rb_hash_tbl_raw(VALUE hash)
Definition: hash.c:351
ID block_arg
Definition: ripper.y:521
struct RNode * node
Definition: ripper.y:244
VALUE rb_eSyntaxError
Definition: error.c:563
#define NODE_MATCH2
#define ID2SYM(x)
#define NODE_FOR
#define debug_node_start(node)
Definition: compile.c:151
#define T_FLOAT
if(args--[1]==0)
Definition: array.c:3176
VALUE tbl
Definition: tkutil.c:1280
int arg_post_len
Definition: vm_core.h:279
static void REMOVE_ELEM(LINK_ELEMENT *elem)
Definition: compile.c:742
static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
Definition: compile.c:2036
memo state
Definition: enum.c:2432
Definition: ripper.y:80
static int get_dyna_var_idx(rb_iseq_t *iseq, ID id, int *level, int *ls)
Definition: compile.c:1160
struct iseq_label_data LABEL
#define NODE_UNTIL
#define VM_CALL_VCALL
Definition: vm_core.h:747
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:2340
#define NODE_GASGN
struct iseq_link_element LINK_ELEMENT
flag
Definition: tcltklib.c:2046
static int insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id)
Definition: compile.c:1965
static void INSERT_ELEM_NEXT(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
Definition: compile.c:699
VALUE current_block
Definition: iseq.h:90
void rb_hash_foreach(VALUE, int(*)(ANYARGS), VALUE)
Definition: hash.c:264
i
Definition: enum.c:446
VALUE ary
Definition: enum.c:674
#define head
Definition: st.c:107
const rb_compile_option_t * option
Definition: iseq.h:102
int sc_state
Definition: compile.c:55
#define NODE_POSTEXE
static int iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, VALUE body, struct st_table *labels_table)
Definition: compile.c:5734
#define NODE_OP_CDECL
const VALUE catch_table_ary
Definition: iseq.h:84
Definition: ripper.y:240
enum iseq_catch_table_entry::catch_type type
Definition: ripper.y:87
unsigned long pos
Definition: iseq.h:75
VALUE rb_cISeq
Definition: iseq.c:27
#define MEMZERO(p, type, n)
void rb_exc_raise(VALUE mesg)
Definition: eval.c:567
static VALUE sym_inspect(VALUE sym)
Definition: string.c:8436
VALUE * iseq
Definition: vm_core.h:225
LABEL * begin
Definition: compile.c:66
#define NODE_CLASS
int rb_is_const_id(ID id)
Definition: ripper.c:17271
#define ADD_SEQ(seq1, seq2)
Definition: compile.c:180
#define NODE_IFUNC
enum rb_iseq_struct::iseq_type type
#define NODE_WHILE
static VALUE iseq_build_load_iseq(rb_iseq_t *iseq, VALUE op)
Definition: compile.c:5717
Definition: ripper.y:78
*q done
Definition: tcltklib.c:2925
static int iseq_set_local_table(rb_iseq_t *iseq, ID *tbl)
Definition: compile.c:1360
#define FIXABLE(f)
#define NODE_LVAR
int arg_keyword_required
Definition: vm_core.h:286
#define le(x, y)
Definition: time.c:69
static void ADD_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor, LINK_ELEMENT *elem)
Definition: compile.c:387
#define NODE_LASGN
struct rb_global_entry * rb_global_entry(ID)
Definition: variable.c:450
static INSN * new_insn_body(rb_iseq_t *iseq, int line_no, int insn_id, int argc,...)
Definition: compile.c:989
int specialized_instruction
Definition: iseq.h:42
#define FIXNUM_INC(n, i)
Definition: compile.c:22
Definition: iseq.h:57
#define FIXNUM_P(f)
return Qfalse
Definition: tcltklib.c:6754
#define NODE_OP_ASGN_AND
static int compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *rhsn, NODE *orig_lhsn)
Definition: compile.c:2680
VALUE rb_dbl2big(double d)
Definition: bignum.c:5213
#define ADD_TRACE(seq, line, event)
Definition: compile.c:221
const char * rb_insns_name(int i)
Definition: compile.c:5601
static VALUE CHECK_INTEGER(VALUE v)
Definition: compile.c:5882
#define VM_CALL_ARGS_SKIP_SETUP
Definition: vm_core.h:751
#define RARRAY_LEN(a)
VALUE mark_ary
Definition: iseq.h:83
#define NEW_IFUNC(f, c)
#define NODE_WHEN
#define Qnil
Definition: enum.c:67
#define StringValuePtr(v)
volatile VALUE elem
Definition: tcltklib.c:9662
#define val
Definition: tcltklib.c:1935
Definition: ripper.y:500
int instructions_unification
Definition: iseq.h:44
static LABEL * new_label_body(rb_iseq_t *iseq, long line)
Definition: compile.c:947
#define ne(x, y)
Definition: time.c:66
int depth
Definition: tcltklib.c:2198
#define NEW_NODE(t, a0, a1, a2)
#define NODE_YIELD
static VALUE char * str
Definition: tcltklib.c:3539
#define NODE_FLIP2
#define NODE_BLOCK
#define NEW_ISEQVAL(node, name, type, line_no)
Definition: compile.c:173
static void Tcl_Interp * ip
Definition: stubs.c:43
#define RARRAY_CONST_PTR(a)
struct iseq_link_anchor LINK_ANCHOR
#define RARRAY_AREF(a, i)
#define NODE_DASGN_CURR
VALUE rb_ary_new(void)
Definition: array.c:495
#define StringValueCStr(v)
#define NODE_AND
int flags
Definition: tcltklib.c:3015
unsigned long ID
Definition: ripper.y:89
static ADJUST * new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line)
Definition: compile.c:961
va_end(args)
#define RUBY_EVENT_B_CALL
int argc
argument information
Definition: vm_core.h:274
static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
Definition: compile.c:2104
Definition: ripper.y:747
int last_line
Definition: iseq.h:98
#define ERROR_ARGS
Definition: compile.c:287
#define VM_DEFINECLASS_FLAG_HAS_SUPERCLASS
Definition: vm_core.h:667
static int cdhash_cmp(VALUE val, VALUE lit)
Definition: compile.c:1392
int arg_post_start
Definition: vm_core.h:280
#define ADD_SEND(seq, line, id, argc)
Definition: compile.c:204
#define ADD_INSNL(seq, line, insn, label)
Definition: compile.c:193
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:2159
#define UNLIKELY(x)
Definition: vm_core.h:109
static VALUE VALUE obj
Definition: tcltklib.c:3150
#define FIX2INT(x)
#define INT2FIX(i)
#define RUBY_EVENT_RETURN
#define CHECK_ARRAY(v)
Definition: compile.c:5879
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:790
VALUE value
Definition: ripper.y:246
VALUE * arg_opt_table
Definition: vm_core.h:282
#define FIX2LONG(x)
static int iseq_set_exception_local_table(rb_iseq_t *iseq)
Definition: compile.c:1111
#define T_STRING
int arg_keywords
Definition: vm_core.h:285
Definition: ripper.y:79
Definition: vm_core.h:141
static struct st_hash_type cdhash_type
Definition: compile.c:1418
#define ADD_CALL(seq, line, id, argc)
Definition: compile.c:210
#define NODE_ARGSCAT
#define NODE_COLON2
#define INIT_ANCHOR(name)
Definition: compile.c:298
rb_num_t flip_cnt
Definition: vm_core.h:320
static LINK_ELEMENT * get_destination_insn(INSN *iobj)
Definition: compile.c:1802
static VALUE case_when_optimizable_literal(NODE *node)
Definition: compile.c:2569
#define NODE_ZSUPER
rb_iseq_t * blockiseq
Definition: vm_core.h:160
rb_block_t * base_block
Definition: vm_core.h:555
#define COMPILE(anchor, desc, node)
Definition: compile.c:254
static int get_dyna_var_idx_at_raw(rb_iseq_t *iseq, ID id)
Definition: compile.c:1135
int rb_parse_in_main(void)
Definition: compile.c:6009
static int iseq_set_optargs_table(rb_iseq_t *iseq)
Definition: compile.c:1788
struct ensure_range * erange
Definition: compile.c:74
#define NODE_MODULE
int link(const char *, const char *)
Definition: win32.c:4595
ID * local_table
Definition: vm_core.h:235
static int VALUE key
Definition: tkutil.c:265
int len
Definition: enumerator.c:1332
struct iseq_compile_data_ensure_node_stack * prev
Definition: compile.c:73
Definition: ripper.y:82
unsigned long start
Definition: iseq.h:65
register int hval
Definition: lex.c:89
#define numberof(array)
Definition: etc.c:595
unsigned long rb_num_t
Definition: vm_core.h:124
VALUE arg
Definition: enum.c:2427
Definition: ripper.y:81
Definition: ripper.y:76
static int get_lvar_level(rb_iseq_t *iseq)
Definition: compile.c:1124
static int LIST_SIZE_ZERO(LINK_ANCHOR *anchor)
Definition: compile.c:804
#define VM_CALL_SUPER
Definition: vm_core.h:749
Definition: vm_core.h:133
node_type
Definition: ripper.y:23
gz level
Definition: zlib.c:2264
static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
ruby insn object list -&gt; raw instruction sequence
Definition: compile.c:1442
VALUE * argv
Definition: tcltklib.c:1969
static VALUE r_value(VALUE value)
Definition: compile.c:141
int rb_dvar_defined(ID id)
Definition: compile.c:5959
LABEL * end
Definition: compile.c:67
#define ADD_SEND_R(seq, line, id, argc, block, flag)
Definition: compile.c:216
#define ADD_LABEL(seq, label)
Definition: compile.c:235
const int id
Definition: nkf.c:209
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
Definition: st.c:1034
static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE *node)
Definition: compile.c:1183
ID rest_arg
Definition: ripper.y:520
Definition: iseq.h:62
#define defined_expr
Definition: compile.c:2850
LINK_ELEMENT link
Definition: compile.c:51
#define TRUE
Definition: nkf.h:175
#define NODE_NIL
defined_type
Definition: iseq.h:110
#define NODE_ATTRASGN
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1250
int operand_size
Definition: compile.c:54
#define NODE_COLON3
#define NODE_DEFINED
memo u3 cnt
Definition: enum.c:128
static int compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
Definition: compile.c:2355
struct iseq_insn_data INSN
static void REPLACE_ELEM(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
Definition: compile.c:729
VALUE v
Definition: enum.c:845
static VALUE build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *body)
Definition: compile.c:3234
#define NODE_MASGN
static LINK_ELEMENT * get_next_insn(INSN *iobj)
Definition: compile.c:1818
const VALUE klass
Definition: ripper.y:749
#define CONST_ID(var, str)
#define NODE_CONST
VALUE rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args, VALUE exception, VALUE body)
Definition: compile.c:5885
VP_EXPORT void
Definition: bigdecimal.c:5214
unsigned int line_no
Definition: compile.c:53
struct rb_iseq_struct * parent_iseq
Definition: vm_core.h:296
size_t length
Definition: tcltklib.c:4549
const VALUE path
Definition: vm_core.h:197
#define NODE_VALIAS
struct iseq_label_data * redo_label
Definition: iseq.h:89
#define NODE_GVAR
#define NODE_CDECL
#define DECL_ANCHOR(name)
Definition: compile.c:296
#define NEW_CHILD_ISEQVAL(node, name, type, line_no)
Definition: compile.c:176
union RNode::@114 u3
#define NODE_LIT
int type
Definition: tcltklib.c:112
compile_array_type_t
Definition: compile.c:2408
VALUE * iseq_encoded
Definition: vm_core.h:226
Definition: ripper.y:93
int argc
Definition: tcltklib.c:1968
NODE * post_init
Definition: ripper.y:513
static LINK_ELEMENT * get_prev_insn(INSN *iobj)
Definition: compile.c:1832
int catch_table_size
Definition: vm_core.h:293
Definition: iseq.h:55
static INSN * new_insn_core(rb_iseq_t *iseq, int line_no, int insn_id, int argc, VALUE *argv)
Definition: compile.c:972
static void * compile_data_alloc(rb_iseq_t *iseq, size_t size)
Definition: compile.c:636
int intptr_t
Definition: win32.h:87
Definition: ripper.y:75
rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1))
Definition: ripper.y:85
static VALUE new_child_iseq(rb_iseq_t *iseq, NODE *node, VALUE name, VALUE parent, enum iseq_type type, int line_no)
Definition: compile.c:1044
#define NODE_ERRINFO
#define ADD_CALL_RECEIVER(seq, line)
Definition: compile.c:207
int post_args_num
Definition: ripper.y:516
#define VM_CHECKMATCH_ARRAY
Definition: vm_core.h:742
VALUE rb_fstring(VALUE)
Definition: string.c:201
rb_iseq_location_t location
Definition: vm_core.h:223
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
Definition: iseq.c:583
static LABEL * register_label(rb_iseq_t *iseq, struct st_table *labels_table, VALUE obj)
Definition: compile.c:5618
#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc)
Definition: compile.c:247
#define NODE_ARGSPUSH
#define NODE_BACK_REF
void * ruby_xrealloc(void *ptr, size_t new_size)
Definition: gc.c:6206
#define NODE_MATCH
Definition: iseq.h:60
static int compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *cond, LABEL *then_label, LABEL *else_label)
Definition: compile.c:2364
VALUE flags
Definition: ripper.y:241
VALUE idx
Definition: enumerator.c:499
#define NODE_ALIAS
return ptr
Definition: tcltklib.c:789
#define NODE_CVDECL
#define ge(x, y)
Definition: time.c:70
#define NODE_DASGN
static VALUE compile_cpath(LINK_ANCHOR *ret, rb_iseq_t *iseq, NODE *cpath)
Definition: compile.c:2830
#define ADD_INSN3(seq, line, insn, op1, op2, op3)
Definition: compile.c:199
#define MEMCPY(p1, p2, type, n)
#define MEMORY(v)
gz end
Definition: zlib.c:2272
static VALUE get_exception_sym2type(VALUE sym)
Definition: compile.c:5635
void rb_iseq_add_mark_object(rb_iseq_t *iseq, VALUE obj)
Definition: iseq.c:245
static int calc_sp_depth(int depth, INSN *iobj)
Definition: compile.c:5458
static int cdhash_set_label_i(VALUE key, VALUE val, void *ptr)
Definition: compile.c:1430
#define COMPILE_OK
Definition: compile.c:290
static VALUE opobj_inspect(VALUE obj)
Definition: compile.c:5464
#define va_init_list(a, b)
Definition: tcltklib.c:62
LINK_ELEMENT link
Definition: compile.c:60
static int label_get_position(LABEL *lobj)
Definition: compile.c:1719
memo last
Definition: enum.c:1356
int callinfo_size
Definition: vm_core.h:245
#define T_SYMBOL
unsigned long sp
Definition: iseq.h:68
static void add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange, LABEL *lstart, LABEL *lend)
Definition: compile.c:3097
static int label_get_sp(LABEL *lobj)
Definition: compile.c:1725
#define COMPILE_POPED(anchor, desc, node)
Definition: compile.c:259
#define NUM2LONG(x)
static int compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
Definition: compile.c:2628
#define NODE_FCALL
int arg_keyword_check
Definition: vm_core.h:284
#define SYMBOL_P(x)
#define debugp_param(header, value)
Definition: compile.c:150
#define NODE_FLIP3
unsigned int position
Definition: iseq.h:51
#define Qundef
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:652
#define INSN_OF(insn)
Definition: compile.c:271
Definition: ripper.y:88
static VALUE insn_data_to_s_detail(INSN *iobj)
Definition: compile.c:5483
#define NODE_DVAR
VALUE name
Definition: enum.c:572
VALUE rb_hash(VALUE)
Definition: hash.c:106
static int iseq_set_exception_table(rb_iseq_t *iseq)
Definition: compile.c:1731
size_t line_info_size
Definition: vm_core.h:233
#define hide_obj(obj)
Definition: compile.c:301
#define NODE_ZARRAY
NODE * pre_init
Definition: ripper.y:512
#define NODE_CVAR
args[0]
Definition: enum.c:585
const char * ruby_node_name(int node)
Definition: iseq.c:1603
st_index_t rb_str_hash(VALUE)
Definition: string.c:2422
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1290
struct iseq_compile_data_storage * storage_current
Definition: iseq.h:97
#define NODE_BREAK
struct iseq_catch_table_entry * catch_table
Definition: vm_core.h:292
void rb_compile_warning(const char *file, int line, const char *fmt,...)
Definition: error.c:192
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1553
st_data_t st_index_t
Definition: ripper.y:48
#define ALLOC_N(type, n)
#define NODE_FL_NEWLINE
#define LONG2FIX(i)
#define gt(x, y)
Definition: time.c:68
#define RARRAY_LENINT(ary)
#define NODE_OP_ASGN2
int local_size
Definition: vm_core.h:239
#define NODE_DSTR
struct rb_encoding_entry * list
Definition: encoding.c:47
#define ADD_ADJUST_RESTORE(seq, label)
Definition: compile.c:244
struct iseq_inline_cache_entry * IC
Definition: vm_core.h:785
struct iseq_line_info_entry * line_info_table
Definition: vm_core.h:232
#define NODE_SCLASS
unsigned long iseq_size
Definition: vm_core.h:227
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1888
#define NODE_BEGIN
#define NODE_POSTARG
int st_insert(st_table *, st_data_t, st_data_t)
#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block)
Definition: compile.c:213
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:3542
#define VM_CALL_TAILCALL
Definition: vm_core.h:748
static VALUE setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, VALUE *flag)
Definition: compile.c:3150
#define ISEQ_ARG_DECLARE
Definition: compile.c:314
Definition: ripper.y:92
union RNode::@113 u2
#define compile_debug
Definition: compile.c:95
static rb_call_info_t * new_callinfo(rb_iseq_t *iseq, ID mid, int argc, VALUE block, unsigned long flag)
Definition: compile.c:1007
static const char * catch_type(int type)
Definition: iseq.c:1338
#define NODE_OP_ASGN1
#define NODE_CVASGN
data n
Definition: enum.c:860
#define PADDING_SIZE_MAX
Definition: compile.c:606
static st_index_t cdhash_hash(VALUE a)
Definition: compile.c:1408
static struct st_table * insn_make_insn_table(void)
Definition: compile.c:5703
static void add_ensure_iseq(LINK_ANCHOR *ret, rb_iseq_t *iseq, int is_return)
Definition: compile.c:3115
VALUE self
Definition: vm_core.h:303
#define GetISeqPtr(obj, ptr)
Definition: vm_core.h:193
unsigned long cont
Definition: iseq.h:67
#define NUM2INT(x)
VALUE rb_hash_new(void)
Definition: hash.c:298
#define COMPILE_ERROR(strs)
Definition: compile.c:275
const char * rb_id2name(ID id)
Definition: ripper.c:17230
#define NODE_CALL
struct iseq_label_data * end_label
Definition: iseq.h:88
static void INSERT_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc1, LINK_ANCHOR *anc2)
Definition: compile.c:843
int loopval_popped
Definition: iseq.h:94
#define BUILTIN_TYPE(x)
#define PRIsVALUE
#define NODE_OPT_N
#define CHECK_SYMBOL(v)
Definition: compile.c:5881
#define COMPILE_(anchor, desc, node, poped)
Definition: compile.c:264
BDIGIT e
Definition: bigdecimal.c:5216
static VALUE make_name_for_block(rb_iseq_t *iseq)
Definition: compile.c:3063
int rb_str_hash_cmp(VALUE, VALUE)
Definition: string.c:2432
VALUE iseq
Definition: iseq.h:64
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:697
#define lt(x, y)
Definition: time.c:67
unsigned long VALUE
Definition: ripper.y:88
static int iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
Definition: compile.c:1985
#define NODE_IVAR
#define debug_node_end()
Definition: compile.c:152
static void APPEND_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor, LINK_ELEMENT *before, LINK_ELEMENT *elem)
Definition: compile.c:399
union rb_call_info_struct::@189 aux
#define NODE_DOT2
#define NODE_KW_ARG
#define NODE_DREGX
#define NODE_OP_ASGN_OR
#define NODE_IASGN
#define NODE_RETURN
#define SPECIAL_CONST_P(x)
ID first_post_arg
Definition: ripper.y:518
Definition: iseq.h:50
static int iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
Definition: compile.c:2218
#define NODE_ARRAY
#define NODE_SPLAT
#define rb_intern(str)
int rb_parse_in_eval(void)
Definition: compile.c:6003
#define mod(x, y)
Definition: date_strftime.c:28
VALUE j
Definition: enum.c:1347
#define nd_line(n)
static int when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, int only_special_literals, VALUE literals)
Definition: compile.c:2591
#define NULL
Definition: _sdbm.c:103
unsigned int line_no
Definition: iseq.h:52
union RNode::@112 u1
#define APPEND_LABEL(seq, before, label)
Definition: compile.c:238
Definition: ripper.y:77
#define NODE_SCOPE
static LINK_ELEMENT * FIRST_ELEMENT(LINK_ANCHOR *anchor)
Definition: compile.c:751
static int get_local_var_idx(rb_iseq_t *iseq, ID id)
Definition: compile.c:1148
static int iseq_add_mark_object_compile_time(rb_iseq_t *iseq, VALUE v)
Definition: compile.c:425
int rb_local_defined(ID id)
Definition: compile.c:5984
const VALUE label
Definition: vm_core.h:200
Definition: ripper.y:84
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:927
struct iseq_adjust_data ADJUST
int retry
Definition: tcltklib.c:10099
static int eq(VALUE x, VALUE y)
Definition: time.c:45
VALUE rb_iseq_disasm(VALUE self)
Definition: iseq.c:1378
#define NODE_IASGN2
#define NODE_SELF
#define debugs
Definition: compile.c:159
#define SYM2ID(x)
static int compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int *cntp)
Definition: compile.c:2314
static void compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *lhsn)
Definition: compile.c:2671
RUBY_EXTERN VALUE rb_cNumeric
Definition: ripper.y:1575
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2616
#define iseq_path(iseq)
Definition: compile.c:167
#define iseq_absolute_path(iseq)
Definition: compile.c:170
void st_free_table(st_table *)
Definition: st.c:334
VALUE rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno, VALUE parent, enum iseq_type type, const rb_compile_option_t *option)
Definition: iseq.c:454
#define NODE_VALUES
static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE *n, int)
compile each node
Definition: compile.c:3253
enum ruby_vminsn_type insn_id
Definition: compile.c:52
static Bigint * mult(Bigint *a, Bigint *b)
Definition: util.c:1228
#define RUBY_EVENT_CALL
int parse_in_eval
Thread-local state of evaluation context.
Definition: vm_core.h:602
#define ADD_INSN1(seq, line, insn, op1)
Definition: compile.c:188
VALUE rb_inspect(VALUE)
Definition: object.c:470
union iseq_inline_storage_entry * is_entries
Definition: vm_core.h:241
NODE * opt_args
Definition: ripper.y:526
static void dump_disasm_list(LINK_ELEMENT *elem)
Definition: compile.c:5555