Ruby  2.1.10p492(2016-04-01revision54464)
compile.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  compile.c - ruby node tree -> VM instruction sequence
4 
5  $Author: usa $
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  line = (int)nd_line(node);
3268 
3269  if (iseq->compile_data->last_line == line) {
3270  /* ignore */
3271  }
3272  else {
3273  if (node->flags & NODE_FL_NEWLINE) {
3274  iseq->compile_data->last_line = line;
3275  ADD_TRACE(ret, line, RUBY_EVENT_LINE);
3276  saved_last_element = ret->last;
3277  }
3278  }
3279 
3280  debug_node_start(node);
3281 
3282  type = nd_type(node);
3283 
3284  switch (type) {
3285  case NODE_BLOCK:{
3286  while (node && nd_type(node) == NODE_BLOCK) {
3287  COMPILE_(ret, "BLOCK body", node->nd_head,
3288  (node->nd_next == 0 && poped == 0) ? 0 : 1);
3289  node = node->nd_next;
3290  }
3291  if (node) {
3292  COMPILE_(ret, "BLOCK next", node->nd_next, poped);
3293  }
3294  break;
3295  }
3296  case NODE_IF:{
3297  DECL_ANCHOR(cond_seq);
3298  DECL_ANCHOR(then_seq);
3299  DECL_ANCHOR(else_seq);
3300  LABEL *then_label, *else_label, *end_label;
3301 
3302  INIT_ANCHOR(cond_seq);
3303  INIT_ANCHOR(then_seq);
3304  INIT_ANCHOR(else_seq);
3305  then_label = NEW_LABEL(line);
3306  else_label = NEW_LABEL(line);
3307  end_label = NEW_LABEL(line);
3308 
3309  compile_branch_condition(iseq, cond_seq, node->nd_cond,
3310  then_label, else_label);
3311  COMPILE_(then_seq, "then", node->nd_body, poped);
3312  COMPILE_(else_seq, "else", node->nd_else, poped);
3313 
3314  ADD_SEQ(ret, cond_seq);
3315 
3316  ADD_LABEL(ret, then_label);
3317  ADD_SEQ(ret, then_seq);
3318  ADD_INSNL(ret, line, jump, end_label);
3319 
3320  ADD_LABEL(ret, else_label);
3321  ADD_SEQ(ret, else_seq);
3322 
3323  ADD_LABEL(ret, end_label);
3324 
3325  break;
3326  }
3327  case NODE_CASE:{
3328  NODE *vals;
3329  NODE *tempnode = node;
3330  LABEL *endlabel, *elselabel;
3331  DECL_ANCHOR(head);
3332  DECL_ANCHOR(body_seq);
3333  DECL_ANCHOR(cond_seq);
3334  int only_special_literals = 1;
3335  VALUE literals = rb_hash_new();
3336 
3337  INIT_ANCHOR(head);
3338  INIT_ANCHOR(body_seq);
3339  INIT_ANCHOR(cond_seq);
3340 
3341  rb_hash_tbl_raw(literals)->type = &cdhash_type;
3342 
3343  if (node->nd_head == 0) {
3344  COMPILE_(ret, "when", node->nd_body, poped);
3345  break;
3346  }
3347  COMPILE(head, "case base", node->nd_head);
3348 
3349  node = node->nd_body;
3350  type = nd_type(node);
3351  line = nd_line(node);
3352 
3353  if (type != NODE_WHEN) {
3354  COMPILE_ERROR((ERROR_ARGS "NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type)));
3355  }
3356 
3357  endlabel = NEW_LABEL(line);
3358  elselabel = NEW_LABEL(line);
3359 
3360  ADD_SEQ(ret, head); /* case VAL */
3361 
3362  while (type == NODE_WHEN) {
3363  LABEL *l1;
3364 
3365  l1 = NEW_LABEL(line);
3366  ADD_LABEL(body_seq, l1);
3367  ADD_INSN(body_seq, line, pop);
3368  COMPILE_(body_seq, "when body", node->nd_body, poped);
3369  ADD_INSNL(body_seq, line, jump, endlabel);
3370 
3371  vals = node->nd_head;
3372  if (vals) {
3373  switch (nd_type(vals)) {
3374  case NODE_ARRAY:
3375  only_special_literals = when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals);
3376  break;
3377  case NODE_SPLAT:
3378  case NODE_ARGSCAT:
3379  case NODE_ARGSPUSH:
3380  only_special_literals = 0;
3381  ADD_INSN (cond_seq, nd_line(vals), dup);
3382  COMPILE(cond_seq, "when/cond splat", vals);
3383  ADD_INSN1(cond_seq, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
3384  ADD_INSNL(cond_seq, nd_line(vals), branchif, l1);
3385  break;
3386  default:
3387  rb_bug("NODE_CASE: unknown node (%s)",
3388  ruby_node_name(nd_type(vals)));
3389  }
3390  }
3391  else {
3392  rb_bug("NODE_CASE: must be NODE_ARRAY, but 0");
3393  }
3394 
3395  node = node->nd_next;
3396  if (!node) {
3397  break;
3398  }
3399  type = nd_type(node);
3400  line = nd_line(node);
3401  }
3402  /* else */
3403  if (node) {
3404  ADD_LABEL(cond_seq, elselabel);
3405  ADD_INSN(cond_seq, line, pop);
3406  COMPILE_(cond_seq, "else", node, poped);
3407  ADD_INSNL(cond_seq, line, jump, endlabel);
3408  }
3409  else {
3410  debugs("== else (implicit)\n");
3411  ADD_LABEL(cond_seq, elselabel);
3412  ADD_INSN(cond_seq, nd_line(tempnode), pop);
3413  if (!poped) {
3414  ADD_INSN(cond_seq, nd_line(tempnode), putnil);
3415  }
3416  ADD_INSNL(cond_seq, nd_line(tempnode), jump, endlabel);
3417  }
3418 
3419  if (only_special_literals) {
3420  iseq_add_mark_object(iseq, literals);
3421 
3422  ADD_INSN(ret, nd_line(tempnode), dup);
3423  ADD_INSN2(ret, nd_line(tempnode), opt_case_dispatch, literals, elselabel);
3424  }
3425 
3426  ADD_SEQ(ret, cond_seq);
3427  ADD_SEQ(ret, body_seq);
3428  ADD_LABEL(ret, endlabel);
3429  break;
3430  }
3431  case NODE_WHEN:{
3432  NODE *vals;
3433  NODE *val;
3434  NODE *orig_node = node;
3435  LABEL *endlabel;
3436  DECL_ANCHOR(body_seq);
3437 
3438  INIT_ANCHOR(body_seq);
3439  endlabel = NEW_LABEL(line);
3440 
3441  while (node && nd_type(node) == NODE_WHEN) {
3442  LABEL *l1 = NEW_LABEL(line = nd_line(node));
3443  ADD_LABEL(body_seq, l1);
3444  COMPILE_(body_seq, "when", node->nd_body, poped);
3445  ADD_INSNL(body_seq, line, jump, endlabel);
3446 
3447  vals = node->nd_head;
3448  if (!vals) {
3449  rb_bug("NODE_WHEN: must be NODE_ARRAY, but 0");
3450  }
3451  switch (nd_type(vals)) {
3452  case NODE_ARRAY:
3453  while (vals) {
3454  val = vals->nd_head;
3455  COMPILE(ret, "when2", val);
3456  ADD_INSNL(ret, nd_line(val), branchif, l1);
3457  vals = vals->nd_next;
3458  }
3459  break;
3460  case NODE_SPLAT:
3461  case NODE_ARGSCAT:
3462  case NODE_ARGSPUSH:
3463  ADD_INSN(ret, nd_line(vals), putnil);
3464  COMPILE(ret, "when2/cond splat", vals);
3466  ADD_INSNL(ret, nd_line(vals), branchif, l1);
3467  break;
3468  default:
3469  rb_bug("NODE_WHEN: unknown node (%s)",
3470  ruby_node_name(nd_type(vals)));
3471  }
3472  node = node->nd_next;
3473  }
3474  /* else */
3475  COMPILE_(ret, "else", node, poped);
3476  ADD_INSNL(ret, nd_line(orig_node), jump, endlabel);
3477 
3478  ADD_SEQ(ret, body_seq);
3479  ADD_LABEL(ret, endlabel);
3480 
3481  break;
3482  }
3483  case NODE_OPT_N:
3484  case NODE_WHILE:
3485  case NODE_UNTIL:{
3486  LABEL *prev_start_label = iseq->compile_data->start_label;
3487  LABEL *prev_end_label = iseq->compile_data->end_label;
3488  LABEL *prev_redo_label = iseq->compile_data->redo_label;
3489  int prev_loopval_popped = iseq->compile_data->loopval_popped;
3490 
3492 
3493  LABEL *next_label = iseq->compile_data->start_label = NEW_LABEL(line); /* next */
3494  LABEL *redo_label = iseq->compile_data->redo_label = NEW_LABEL(line); /* redo */
3495  LABEL *break_label = iseq->compile_data->end_label = NEW_LABEL(line); /* break */
3496  LABEL *end_label = NEW_LABEL(line);
3497 
3498  LABEL *next_catch_label = NEW_LABEL(line);
3499  LABEL *tmp_label = NULL;
3500 
3501  iseq->compile_data->loopval_popped = 0;
3502  push_ensure_entry(iseq, &enl, 0, 0);
3503 
3504  if (type == NODE_OPT_N || node->nd_state == 1) {
3505  ADD_INSNL(ret, line, jump, next_label);
3506  }
3507  else {
3508  tmp_label = NEW_LABEL(line);
3509  ADD_INSNL(ret, line, jump, tmp_label);
3510  }
3511  ADD_INSN(ret, line, putnil);
3512  ADD_LABEL(ret, next_catch_label);
3513  ADD_INSN(ret, line, pop);
3514  ADD_INSNL(ret, line, jump, next_label);
3515  if (tmp_label) ADD_LABEL(ret, tmp_label);
3516 
3517  ADD_LABEL(ret, redo_label);
3518  COMPILE_POPED(ret, "while body", node->nd_body);
3519  ADD_LABEL(ret, next_label); /* next */
3520 
3521  if (type == NODE_WHILE) {
3522  compile_branch_condition(iseq, ret, node->nd_cond,
3523  redo_label, end_label);
3524  }
3525  else if (type == NODE_UNTIL) {
3526  /* until */
3527  compile_branch_condition(iseq, ret, node->nd_cond,
3528  end_label, redo_label);
3529  }
3530  else {
3531  ADD_CALL_RECEIVER(ret, line);
3532  ADD_CALL(ret, line, ID2SYM(idGets), INT2FIX(0));
3533  ADD_INSNL(ret, line, branchif, redo_label);
3534  /* opt_n */
3535  }
3536 
3537  ADD_LABEL(ret, end_label);
3538 
3539  if (node->nd_state == Qundef) {
3540  /* ADD_INSN(ret, line, putundef); */
3541  rb_bug("unsupported: putundef");
3542  }
3543  else {
3544  ADD_INSN(ret, line, putnil);
3545  }
3546 
3547  ADD_LABEL(ret, break_label); /* break */
3548 
3549  if (poped) {
3550  ADD_INSN(ret, line, pop);
3551  }
3552 
3553  ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label,
3554  0, break_label);
3555  ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, redo_label, break_label, 0,
3556  next_catch_label);
3557  ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label, 0,
3558  iseq->compile_data->redo_label);
3559 
3560  iseq->compile_data->start_label = prev_start_label;
3561  iseq->compile_data->end_label = prev_end_label;
3562  iseq->compile_data->redo_label = prev_redo_label;
3563  iseq->compile_data->loopval_popped = prev_loopval_popped;
3565  break;
3566  }
3567  case NODE_ITER:
3568  case NODE_FOR:{
3569  VALUE prevblock = iseq->compile_data->current_block;
3570  LABEL *retry_label = NEW_LABEL(line);
3571  LABEL *retry_end_l = NEW_LABEL(line);
3572 
3573  ADD_LABEL(ret, retry_label);
3574  if (nd_type(node) == NODE_FOR) {
3575  COMPILE(ret, "iter caller (for)", node->nd_iter);
3576 
3577  iseq->compile_data->current_block =
3578  NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq),
3579  ISEQ_TYPE_BLOCK, line);
3580 
3581  ADD_SEND_R(ret, line, ID2SYM(idEach), INT2FIX(0),
3582  iseq->compile_data->current_block, INT2FIX(0));
3583  }
3584  else {
3585  iseq->compile_data->current_block =
3586  NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq),
3587  ISEQ_TYPE_BLOCK, line);
3588  COMPILE(ret, "iter caller", node->nd_iter);
3589  }
3590  ADD_LABEL(ret, retry_end_l);
3591 
3592  if (poped) {
3593  ADD_INSN(ret, line, pop);
3594  }
3595 
3596  iseq->compile_data->current_block = prevblock;
3597 
3598  ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, 0, retry_end_l);
3599 
3600  break;
3601  }
3602  case NODE_BREAK:{
3603  unsigned long level = 0;
3604 
3605  if (iseq->compile_data->redo_label != 0) {
3606  /* while/until */
3607  LABEL *splabel = NEW_LABEL(0);
3608  ADD_LABEL(ret, splabel);
3609  ADD_ADJUST(ret, line, iseq->compile_data->redo_label);
3610  COMPILE_(ret, "break val (while/until)", node->nd_stts, iseq->compile_data->loopval_popped);
3611  add_ensure_iseq(ret, iseq, 0);
3612  ADD_INSNL(ret, line, jump, iseq->compile_data->end_label);
3613  ADD_ADJUST_RESTORE(ret, splabel);
3614 
3615  if (!poped) {
3616  ADD_INSN(ret, line, putnil);
3617  }
3618  }
3619  else if (iseq->type == ISEQ_TYPE_BLOCK) {
3620  break_by_insn:
3621  /* escape from block */
3622  COMPILE(ret, "break val (block)", node->nd_stts);
3623  ADD_INSN1(ret, line, throw, INT2FIX(level | 0x02) /* TAG_BREAK */ );
3624  if (poped) {
3625  ADD_INSN(ret, line, pop);
3626  }
3627  }
3628  else if (iseq->type == ISEQ_TYPE_EVAL) {
3629  break_in_eval:
3630  COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with break"));
3631  }
3632  else {
3633  rb_iseq_t *ip = iseq->parent_iseq;
3634  while (ip) {
3635  if (!ip->compile_data) {
3636  ip = 0;
3637  break;
3638  }
3639 
3640  level++;
3641  if (ip->compile_data->redo_label != 0) {
3642  level = 0x8000;
3643  if (ip->compile_data->loopval_popped == 0) {
3644  /* need value */
3645  level |= 0x4000;
3646  }
3647  goto break_by_insn;
3648  }
3649  else if (ip->type == ISEQ_TYPE_BLOCK) {
3650  level <<= 16;
3651  goto break_by_insn;
3652  }
3653  else if (ip->type == ISEQ_TYPE_EVAL) {
3654  goto break_in_eval;
3655  }
3656 
3657  ip = ip->parent_iseq;
3658  }
3659  COMPILE_ERROR((ERROR_ARGS "Invalid break"));
3660  }
3661  break;
3662  }
3663  case NODE_NEXT:{
3664  unsigned long level = 0;
3665 
3666  if (iseq->compile_data->redo_label != 0) {
3667  LABEL *splabel = NEW_LABEL(0);
3668  debugs("next in while loop\n");
3669  ADD_LABEL(ret, splabel);
3670  COMPILE(ret, "next val/valid syntax?", node->nd_stts);
3671  add_ensure_iseq(ret, iseq, 0);
3672  ADD_ADJUST(ret, line, iseq->compile_data->redo_label);
3673  ADD_INSNL(ret, line, jump, iseq->compile_data->start_label);
3674  ADD_ADJUST_RESTORE(ret, splabel);
3675  if (!poped) {
3676  ADD_INSN(ret, line, putnil);
3677  }
3678  }
3679  else if (iseq->compile_data->end_label) {
3680  LABEL *splabel = NEW_LABEL(0);
3681  debugs("next in block\n");
3682  ADD_LABEL(ret, splabel);
3683  ADD_ADJUST(ret, line, iseq->compile_data->start_label);
3684  COMPILE(ret, "next val", node->nd_stts);
3685  add_ensure_iseq(ret, iseq, 0);
3686  ADD_INSNL(ret, line, jump, iseq->compile_data->end_label);
3687  ADD_ADJUST_RESTORE(ret, splabel);
3688 
3689  if (!poped) {
3690  ADD_INSN(ret, line, putnil);
3691  }
3692  }
3693  else if (iseq->type == ISEQ_TYPE_EVAL) {
3694  next_in_eval:
3695  COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with next"));
3696  }
3697  else {
3698  rb_iseq_t *ip;
3699  ip = iseq;
3700  while (ip) {
3701  if (!ip->compile_data) {
3702  ip = 0;
3703  break;
3704  }
3705 
3706  level = 0x8000 | 0x4000;
3707  if (ip->compile_data->redo_label != 0) {
3708  /* while loop */
3709  break;
3710  }
3711  else if (ip->type == ISEQ_TYPE_BLOCK) {
3712  break;
3713  }
3714  else if (ip->type == ISEQ_TYPE_EVAL) {
3715  goto next_in_eval;
3716  }
3717 
3718  ip = ip->parent_iseq;
3719  }
3720  if (ip != 0) {
3721  COMPILE(ret, "next val", node->nd_stts);
3722  ADD_INSN1(ret, line, throw, INT2FIX(level | 0x03) /* TAG_NEXT */ );
3723 
3724  if (poped) {
3725  ADD_INSN(ret, line, pop);
3726  }
3727  }
3728  else {
3729  COMPILE_ERROR((ERROR_ARGS "Invalid next"));
3730  }
3731  }
3732  break;
3733  }
3734  case NODE_REDO:{
3735  if (iseq->compile_data->redo_label) {
3736  LABEL *splabel = NEW_LABEL(0);
3737  debugs("redo in while");
3738  ADD_LABEL(ret, splabel);
3739  ADD_ADJUST(ret, line, iseq->compile_data->redo_label);
3740  add_ensure_iseq(ret, iseq, 0);
3741  ADD_INSNL(ret, line, jump, iseq->compile_data->redo_label);
3742  ADD_ADJUST_RESTORE(ret, splabel);
3743  if (!poped) {
3744  ADD_INSN(ret, line, putnil);
3745  }
3746  }
3747  else if (iseq->type == ISEQ_TYPE_EVAL) {
3748  redo_in_eval:
3749  COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with redo"));
3750  }
3751  else if (iseq->compile_data->start_label) {
3752  LABEL *splabel = NEW_LABEL(0);
3753 
3754  debugs("redo in block");
3755  ADD_LABEL(ret, splabel);
3756  add_ensure_iseq(ret, iseq, 0);
3757  ADD_ADJUST(ret, line, iseq->compile_data->start_label);
3758  ADD_INSNL(ret, line, jump, iseq->compile_data->start_label);
3759  ADD_ADJUST_RESTORE(ret, splabel);
3760 
3761  if (!poped) {
3762  ADD_INSN(ret, line, putnil);
3763  }
3764  }
3765  else {
3766  rb_iseq_t *ip;
3767  unsigned long level;
3768  level = 0x8000 | 0x4000;
3769  ip = iseq;
3770  while (ip) {
3771  if (!ip->compile_data) {
3772  ip = 0;
3773  break;
3774  }
3775 
3776  if (ip->compile_data->redo_label != 0) {
3777  break;
3778  }
3779  else if (ip->type == ISEQ_TYPE_BLOCK) {
3780  break;
3781  }
3782  else if (ip->type == ISEQ_TYPE_EVAL) {
3783  goto redo_in_eval;
3784  }
3785 
3786  ip = ip->parent_iseq;
3787  }
3788  if (ip != 0) {
3789  ADD_INSN(ret, line, putnil);
3790  ADD_INSN1(ret, line, throw, INT2FIX(level | 0x05) /* TAG_REDO */ );
3791 
3792  if (poped) {
3793  ADD_INSN(ret, line, pop);
3794  }
3795  }
3796  else {
3797  COMPILE_ERROR((ERROR_ARGS "Invalid redo"));
3798  }
3799  }
3800  break;
3801  }
3802  case NODE_RETRY:{
3803  if (iseq->type == ISEQ_TYPE_RESCUE) {
3804  ADD_INSN(ret, line, putnil);
3805  ADD_INSN1(ret, line, throw, INT2FIX(0x04) /* TAG_RETRY */ );
3806 
3807  if (poped) {
3808  ADD_INSN(ret, line, pop);
3809  }
3810  }
3811  else {
3812  COMPILE_ERROR((ERROR_ARGS "Invalid retry"));
3813  }
3814  break;
3815  }
3816  case NODE_BEGIN:{
3817  COMPILE_(ret, "NODE_BEGIN", node->nd_body, poped);
3818  break;
3819  }
3820  case NODE_RESCUE:{
3821  LABEL *lstart = NEW_LABEL(line);
3822  LABEL *lend = NEW_LABEL(line);
3823  LABEL *lcont = NEW_LABEL(line);
3824  VALUE rescue = NEW_CHILD_ISEQVAL(
3825  node->nd_resq,
3826  rb_str_concat(rb_str_new2("rescue in "), iseq->location.label),
3827  ISEQ_TYPE_RESCUE, line);
3828 
3829  ADD_LABEL(ret, lstart);
3830  COMPILE(ret, "rescue head", node->nd_head);
3831  ADD_LABEL(ret, lend);
3832  if (node->nd_else) {
3833  ADD_INSN(ret, line, pop);
3834  COMPILE(ret, "rescue else", node->nd_else);
3835  }
3836  ADD_INSN(ret, line, nop);
3837  ADD_LABEL(ret, lcont);
3838 
3839  if (poped) {
3840  ADD_INSN(ret, line, pop);
3841  }
3842 
3843  /* register catch entry */
3844  ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lcont);
3845  ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, 0, lstart);
3846  break;
3847  }
3848  case NODE_RESBODY:{
3849  NODE *resq = node;
3850  NODE *narg;
3851  LABEL *label_miss, *label_hit;
3852 
3853  while (resq) {
3854  label_miss = NEW_LABEL(line);
3855  label_hit = NEW_LABEL(line);
3856 
3857  narg = resq->nd_args;
3858  if (narg) {
3859  switch (nd_type(narg)) {
3860  case NODE_ARRAY:
3861  while (narg) {
3862  ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0));
3863  COMPILE(ret, "rescue arg", narg->nd_head);
3864  ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
3865  ADD_INSNL(ret, line, branchif, label_hit);
3866  narg = narg->nd_next;
3867  }
3868  break;
3869  case NODE_SPLAT:
3870  case NODE_ARGSCAT:
3871  case NODE_ARGSPUSH:
3872  ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0));
3873  COMPILE(ret, "rescue/cond splat", narg);
3875  ADD_INSNL(ret, line, branchif, label_hit);
3876  break;
3877  default:
3878  rb_bug("NODE_RESBODY: unknown node (%s)",
3879  ruby_node_name(nd_type(narg)));
3880  }
3881  }
3882  else {
3883  ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0));
3884  ADD_INSN1(ret, line, putobject, rb_eStandardError);
3885  ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
3886  ADD_INSNL(ret, line, branchif, label_hit);
3887  }
3888  ADD_INSNL(ret, line, jump, label_miss);
3889  ADD_LABEL(ret, label_hit);
3890  COMPILE(ret, "resbody body", resq->nd_body);
3892  ADD_INSN(ret, line, nop);
3893  }
3894  ADD_INSN(ret, line, leave);
3895  ADD_LABEL(ret, label_miss);
3896  resq = resq->nd_head;
3897  }
3898  break;
3899  }
3900  case NODE_ENSURE:{
3901  DECL_ANCHOR(ensr);
3902  VALUE ensure = NEW_CHILD_ISEQVAL(node->nd_ensr,
3904  ("ensure in "),
3905  iseq->location.label),
3906  ISEQ_TYPE_ENSURE, line);
3907  LABEL *lstart = NEW_LABEL(line);
3908  LABEL *lend = NEW_LABEL(line);
3909  LABEL *lcont = NEW_LABEL(line);
3910  struct ensure_range er;
3912  struct ensure_range *erange;
3913 
3914  INIT_ANCHOR(ensr);
3915  COMPILE_POPED(ensr, "ensure ensr", node->nd_ensr);
3916 
3917  er.begin = lstart;
3918  er.end = lend;
3919  er.next = 0;
3920  push_ensure_entry(iseq, &enl, &er, node->nd_ensr);
3921 
3922  ADD_LABEL(ret, lstart);
3923  COMPILE_(ret, "ensure head", node->nd_head, poped);
3924  ADD_LABEL(ret, lend);
3925  if (ensr->anchor.next == 0) {
3926  ADD_INSN(ret, line, nop);
3927  }
3928  else {
3929  ADD_SEQ(ret, ensr);
3930  }
3931  ADD_LABEL(ret, lcont);
3932 
3933  erange = iseq->compile_data->ensure_node_stack->erange;
3934  while (erange) {
3935  ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end,
3936  ensure, lcont);
3937  erange = erange->next;
3938  }
3939 
3940  iseq->compile_data->ensure_node_stack = enl.prev;
3941  break;
3942  }
3943 
3944  case NODE_AND:
3945  case NODE_OR:{
3946  LABEL *end_label = NEW_LABEL(line);
3947  COMPILE(ret, "nd_1st", node->nd_1st);
3948  if (!poped) {
3949  ADD_INSN(ret, line, dup);
3950  }
3951  if (type == NODE_AND) {
3952  ADD_INSNL(ret, line, branchunless, end_label);
3953  }
3954  else {
3955  ADD_INSNL(ret, line, branchif, end_label);
3956  }
3957  if (!poped) {
3958  ADD_INSN(ret, line, pop);
3959  }
3960  COMPILE_(ret, "nd_2nd", node->nd_2nd, poped);
3961  ADD_LABEL(ret, end_label);
3962  break;
3963  }
3964 
3965  case NODE_MASGN:{
3966  compile_massign(iseq, ret, node, poped);
3967  break;
3968  }
3969 
3970  case NODE_LASGN:{
3971  ID id = node->nd_vid;
3972  int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id);
3973 
3974  debugs("lvar: %s idx: %d\n", rb_id2name(id), idx);
3975  COMPILE(ret, "rvalue", node->nd_value);
3976 
3977  if (!poped) {
3978  ADD_INSN(ret, line, dup);
3979  }
3980  ADD_INSN2(ret, line, setlocal, INT2FIX(idx), INT2FIX(get_lvar_level(iseq)));
3981 
3982  break;
3983  }
3984  case NODE_DASGN:
3985  case NODE_DASGN_CURR:{
3986  int idx, lv, ls;
3987  COMPILE(ret, "dvalue", node->nd_value);
3988  debugp_param("dassn id", rb_str_new2(rb_id2name(node->nd_vid) ? rb_id2name(node->nd_vid) : "*"));
3989 
3990  if (!poped) {
3991  ADD_INSN(ret, line, dup);
3992  }
3993 
3994  idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
3995 
3996  if (idx < 0) {
3997  rb_bug("NODE_DASGN(_CURR): unknown id (%s)", rb_id2name(node->nd_vid));
3998  }
3999 
4000  ADD_INSN2(ret, line, setlocal, INT2FIX(ls - idx), INT2FIX(lv));
4001  break;
4002  }
4003  case NODE_GASGN:{
4004  COMPILE(ret, "lvalue", node->nd_value);
4005 
4006  if (!poped) {
4007  ADD_INSN(ret, line, dup);
4008  }
4009  ADD_INSN1(ret, line, setglobal,
4010  ((VALUE)node->nd_entry | 1));
4011  break;
4012  }
4013  case NODE_IASGN:
4014  case NODE_IASGN2:{
4015  COMPILE(ret, "lvalue", node->nd_value);
4016  if (!poped) {
4017  ADD_INSN(ret, line, dup);
4018  }
4019  ADD_INSN2(ret, line, setinstancevariable,
4020  ID2SYM(node->nd_vid), INT2FIX(iseq->is_size++));
4021  break;
4022  }
4023  case NODE_CDECL:{
4024  COMPILE(ret, "lvalue", node->nd_value);
4025 
4026  if (!poped) {
4027  ADD_INSN(ret, line, dup);
4028  }
4029 
4030  if (node->nd_vid) {
4031  ADD_INSN1(ret, line, putspecialobject,
4033  ADD_INSN1(ret, line, setconstant, ID2SYM(node->nd_vid));
4034  }
4035  else {
4036  compile_cpath(ret, iseq, node->nd_else);
4037  ADD_INSN1(ret, line, setconstant, ID2SYM(node->nd_else->nd_mid));
4038  }
4039  break;
4040  }
4041  case NODE_CVASGN:{
4042  COMPILE(ret, "cvasgn val", node->nd_value);
4043  if (!poped) {
4044  ADD_INSN(ret, line, dup);
4045  }
4046  ADD_INSN1(ret, line, setclassvariable,
4047  ID2SYM(node->nd_vid));
4048  break;
4049  }
4050  case NODE_OP_ASGN1: {
4051  DECL_ANCHOR(args);
4052  VALUE argc;
4053  VALUE flag = 0;
4054  ID id = node->nd_mid;
4055  int boff = 0;
4056 
4057  /*
4058  * a[x] (op)= y
4059  *
4060  * nil # nil
4061  * eval a # nil a
4062  * eval x # nil a x
4063  * dupn 2 # nil a x a x
4064  * send :[] # nil a x a[x]
4065  * eval y # nil a x a[x] y
4066  * send op # nil a x ret
4067  * setn 3 # ret a x ret
4068  * send []= # ret ?
4069  * pop # ret
4070  */
4071 
4072  /*
4073  * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head;
4074  * NODE_OP_ASGN nd_recv
4075  * nd_args->nd_head
4076  * nd_args->nd_body
4077  * nd_mid
4078  */
4079 
4080  if (!poped) {
4081  ADD_INSN(ret, line, putnil);
4082  }
4083  COMPILE(ret, "NODE_OP_ASGN1 recv", node->nd_recv);
4084  switch (nd_type(node->nd_args->nd_head)) {
4085  case NODE_ZARRAY:
4086  argc = INT2FIX(0);
4087  break;
4088  case NODE_BLOCK_PASS:
4089  boff = 1;
4090  default:
4091  INIT_ANCHOR(args);
4092  argc = setup_args(iseq, args, node->nd_args->nd_head, &flag);
4093  ADD_SEQ(ret, args);
4094  }
4095  ADD_INSN1(ret, line, dupn, FIXNUM_INC(argc, 1 + boff));
4096  ADD_SEND_R(ret, line, ID2SYM(idAREF), argc, Qfalse, LONG2FIX(flag));
4097 
4098  if (id == 0 || id == 1) {
4099  /* 0: or, 1: and
4100  a[x] ||= y
4101 
4102  unless/if a[x]
4103  a[x]= y
4104  else
4105  nil
4106  end
4107  */
4108  LABEL *label = NEW_LABEL(line);
4109  LABEL *lfin = NEW_LABEL(line);
4110 
4111  ADD_INSN(ret, line, dup);
4112  if (id == 0) {
4113  /* or */
4114  ADD_INSNL(ret, line, branchif, label);
4115  }
4116  else {
4117  /* and */
4118  ADD_INSNL(ret, line, branchunless, label);
4119  }
4120  ADD_INSN(ret, line, pop);
4121 
4122  COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body);
4123  if (!poped) {
4124  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff));
4125  }
4126  if (flag & VM_CALL_ARGS_SPLAT) {
4127  ADD_INSN1(ret, line, newarray, INT2FIX(1));
4128  if (boff > 0) {
4129  ADD_INSN1(ret, line, dupn, INT2FIX(3));
4130  ADD_INSN(ret, line, swap);
4131  ADD_INSN(ret, line, pop);
4132  }
4133  ADD_INSN(ret, line, concatarray);
4134  if (boff > 0) {
4135  ADD_INSN1(ret, line, setn, INT2FIX(3));
4136  ADD_INSN(ret, line, pop);
4137  ADD_INSN(ret, line, pop);
4138  }
4139  ADD_SEND_R(ret, line, ID2SYM(idASET),
4140  argc, Qfalse, LONG2FIX(flag));
4141  }
4142  else {
4143  if (boff > 0)
4144  ADD_INSN(ret, line, swap);
4145  ADD_SEND_R(ret, line, ID2SYM(idASET),
4146  FIXNUM_INC(argc, 1), Qfalse, LONG2FIX(flag));
4147  }
4148  ADD_INSN(ret, line, pop);
4149  ADD_INSNL(ret, line, jump, lfin);
4150  ADD_LABEL(ret, label);
4151  if (!poped) {
4152  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff));
4153  }
4154  ADD_INSN1(ret, line, adjuststack, FIXNUM_INC(argc, 2+boff));
4155  ADD_LABEL(ret, lfin);
4156  }
4157  else {
4158  COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body);
4159  ADD_SEND(ret, line, ID2SYM(id), INT2FIX(1));
4160  if (!poped) {
4161  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff));
4162  }
4163  if (flag & VM_CALL_ARGS_SPLAT) {
4164  ADD_INSN1(ret, line, newarray, INT2FIX(1));
4165  if (boff > 0) {
4166  ADD_INSN1(ret, line, dupn, INT2FIX(3));
4167  ADD_INSN(ret, line, swap);
4168  ADD_INSN(ret, line, pop);
4169  }
4170  ADD_INSN(ret, line, concatarray);
4171  if (boff > 0) {
4172  ADD_INSN1(ret, line, setn, INT2FIX(3));
4173  ADD_INSN(ret, line, pop);
4174  ADD_INSN(ret, line, pop);
4175  }
4176  ADD_SEND_R(ret, line, ID2SYM(idASET),
4177  argc, Qfalse, LONG2FIX(flag));
4178  }
4179  else {
4180  if (boff > 0)
4181  ADD_INSN(ret, line, swap);
4182  ADD_SEND_R(ret, line, ID2SYM(idASET),
4183  FIXNUM_INC(argc, 1), Qfalse, LONG2FIX(flag));
4184  }
4185  ADD_INSN(ret, line, pop);
4186  }
4187 
4188  break;
4189  }
4190  case NODE_OP_ASGN2:{
4191  ID atype = node->nd_next->nd_mid;
4192  LABEL *lfin = NEW_LABEL(line);
4193  LABEL *lcfin = NEW_LABEL(line);
4194  /*
4195  class C; attr_accessor :c; end
4196  r = C.new
4197  r.a &&= v # asgn2
4198 
4199  eval r # r
4200  dup # r r
4201  eval r.a # r o
4202 
4203  # or
4204  dup # r o o
4205  if lcfin # r o
4206  pop # r
4207  eval v # r v
4208  swap # v r
4209  topn 1 # v r v
4210  send a= # v ?
4211  jump lfin # v ?
4212 
4213  lcfin: # r o
4214  swap # o r
4215 
4216  lfin: # o ?
4217  pop # o
4218 
4219  # and
4220  dup # r o o
4221  unless lcfin
4222  pop # r
4223  eval v # r v
4224  swap # v r
4225  topn 1 # v r v
4226  send a= # v ?
4227  jump lfin # v ?
4228 
4229  # others
4230  eval v # r o v
4231  send ?? # r w
4232  send a= # w
4233 
4234  */
4235 
4236  COMPILE(ret, "NODE_OP_ASGN2#recv", node->nd_recv);
4237  ADD_INSN(ret, line, dup);
4238  ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_vid),
4239  INT2FIX(0));
4240 
4241  if (atype == 0 || atype == 1) { /* 0: OR or 1: AND */
4242  ADD_INSN(ret, line, dup);
4243  if (atype == 0) {
4244  ADD_INSNL(ret, line, branchif, lcfin);
4245  }
4246  else {
4247  ADD_INSNL(ret, line, branchunless, lcfin);
4248  }
4249  ADD_INSN(ret, line, pop);
4250  COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value);
4251  ADD_INSN(ret, line, swap);
4252  ADD_INSN1(ret, line, topn, INT2FIX(1));
4253  ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_aid),
4254  INT2FIX(1));
4255  ADD_INSNL(ret, line, jump, lfin);
4256 
4257  ADD_LABEL(ret, lcfin);
4258  ADD_INSN(ret, line, swap);
4259 
4260  ADD_LABEL(ret, lfin);
4261  ADD_INSN(ret, line, pop);
4262  if (poped) {
4263  /* we can apply more optimize */
4264  ADD_INSN(ret, line, pop);
4265  }
4266  }
4267  else {
4268  COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value);
4269  ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_mid),
4270  INT2FIX(1));
4271  if (!poped) {
4272  ADD_INSN(ret, line, swap);
4273  ADD_INSN1(ret, line, topn, INT2FIX(1));
4274  }
4275  ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_aid),
4276  INT2FIX(1));
4277  ADD_INSN(ret, line, pop);
4278  }
4279  break;
4280  }
4281  case NODE_OP_CDECL: {
4282  LABEL *lfin = 0;
4283  LABEL *lassign = 0;
4284  ID mid;
4285 
4286  switch (nd_type(node->nd_head)) {
4287  case NODE_COLON3:
4288  ADD_INSN1(ret, line, putobject, rb_cObject);
4289  break;
4290  case NODE_COLON2:
4291  COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head);
4292  break;
4293  default:
4294  do {
4295  COMPILE_ERROR((ERROR_ARGS "%s: invalid node in NODE_OP_CDECL",
4296  ruby_node_name(nd_type(node->nd_head))));
4297  } while (0);
4298  return COMPILE_NG;
4299  }
4300  mid = node->nd_head->nd_mid;
4301  /* cref */
4302  if (node->nd_aid == 0) {
4303  lassign = NEW_LABEL(line);
4304  ADD_INSN(ret, line, dup); /* cref cref */
4305  ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_CONST),
4306  ID2SYM(mid), Qfalse); /* cref bool */
4307  ADD_INSNL(ret, line, branchunless, lassign); /* cref */
4308  }
4309  ADD_INSN(ret, line, dup); /* cref cref */
4310  ADD_INSN1(ret, line, getconstant, ID2SYM(mid)); /* cref obj */
4311 
4312  if (node->nd_aid == 0 || node->nd_aid == 1) {
4313  lfin = NEW_LABEL(line);
4314  if (!poped) ADD_INSN(ret, line, dup); /* cref [obj] obj */
4315  if (node->nd_aid == 0)
4316  ADD_INSNL(ret, line, branchif, lfin);
4317  else
4318  ADD_INSNL(ret, line, branchunless, lfin);
4319  /* cref [obj] */
4320  if (!poped) ADD_INSN(ret, line, pop); /* cref */
4321  if (lassign) ADD_LABEL(ret, lassign);
4322  COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value);
4323  /* cref value */
4324  if (poped)
4325  ADD_INSN1(ret, line, topn, INT2FIX(1)); /* cref value cref */
4326  else {
4327  ADD_INSN1(ret, line, dupn, INT2FIX(2)); /* cref value cref value */
4328  ADD_INSN(ret, line, swap); /* cref value value cref */
4329  }
4330  ADD_INSN1(ret, line, setconstant, ID2SYM(mid)); /* cref [value] */
4331  ADD_LABEL(ret, lfin); /* cref [value] */
4332  if (!poped) ADD_INSN(ret, line, swap); /* [value] cref */
4333  ADD_INSN(ret, line, pop); /* [value] */
4334  }
4335  else {
4336  COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value);
4337  /* cref obj value */
4338  ADD_CALL(ret, line, ID2SYM(node->nd_aid), INT2FIX(1));
4339  /* cref value */
4340  ADD_INSN(ret, line, swap); /* value cref */
4341  if (!poped) {
4342  ADD_INSN1(ret, line, topn, INT2FIX(1)); /* value cref value */
4343  ADD_INSN(ret, line, swap); /* value value cref */
4344  }
4345  ADD_INSN1(ret, line, setconstant, ID2SYM(mid));
4346  }
4347  break;
4348  }
4349  case NODE_OP_ASGN_AND:
4350  case NODE_OP_ASGN_OR:{
4351  LABEL *lfin = NEW_LABEL(line);
4352  LABEL *lassign;
4353 
4354  if (nd_type(node) == NODE_OP_ASGN_OR) {
4355  LABEL *lfinish[2];
4356  lfinish[0] = lfin;
4357  lfinish[1] = 0;
4358  defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
4359  lassign = lfinish[1];
4360  if (!lassign) {
4361  lassign = NEW_LABEL(line);
4362  }
4363  ADD_INSNL(ret, line, branchunless, lassign);
4364  }
4365  else {
4366  lassign = NEW_LABEL(line);
4367  }
4368 
4369  COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head);
4370  ADD_INSN(ret, line, dup);
4371 
4372  if (nd_type(node) == NODE_OP_ASGN_AND) {
4373  ADD_INSNL(ret, line, branchunless, lfin);
4374  }
4375  else {
4376  ADD_INSNL(ret, line, branchif, lfin);
4377  }
4378 
4379  ADD_INSN(ret, line, pop);
4380  ADD_LABEL(ret, lassign);
4381  COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value);
4382  ADD_LABEL(ret, lfin);
4383 
4384  if (poped) {
4385  /* we can apply more optimize */
4386  ADD_INSN(ret, line, pop);
4387  }
4388  break;
4389  }
4390  case NODE_CALL:
4391  if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR &&
4392  node->nd_mid == idFreeze && node->nd_args == NULL)
4393  {
4394  VALUE str = rb_fstring(node->nd_recv->nd_lit);
4395  iseq_add_mark_object(iseq, str);
4396  ADD_INSN1(ret, line, opt_str_freeze, str);
4397  if (poped) {
4398  ADD_INSN(ret, line, pop);
4399  }
4400  break;
4401  }
4402  case NODE_FCALL:
4403  case NODE_VCALL:{ /* VCALL: variable or call */
4404  /*
4405  call: obj.method(...)
4406  fcall: func(...)
4407  vcall: func
4408  */
4409  DECL_ANCHOR(recv);
4410  DECL_ANCHOR(args);
4411  ID mid = node->nd_mid;
4412  VALUE argc;
4413  VALUE flag = 0;
4414  VALUE parent_block = iseq->compile_data->current_block;
4416 
4417  INIT_ANCHOR(recv);
4418  INIT_ANCHOR(args);
4419 #if SUPPORT_JOKE
4420  if (nd_type(node) == NODE_VCALL) {
4421  ID id_bitblt;
4422  ID id_answer;
4423 
4424  CONST_ID(id_bitblt, "bitblt");
4425  CONST_ID(id_answer, "the_answer_to_life_the_universe_and_everything");
4426 
4427  if (mid == id_bitblt) {
4428  ADD_INSN(ret, line, bitblt);
4429  break;
4430  }
4431  else if (mid == id_answer) {
4432  ADD_INSN(ret, line, answer);
4433  break;
4434  }
4435  }
4436  /* only joke */
4437  {
4438  ID goto_id;
4439  ID label_id;
4440 
4441  CONST_ID(goto_id, "__goto__");
4442  CONST_ID(label_id, "__label__");
4443 
4444  if (nd_type(node) == NODE_FCALL &&
4445  (mid == goto_id || mid == label_id)) {
4446  LABEL *label;
4447  st_data_t data;
4448  st_table *labels_table = iseq->compile_data->labels_table;
4449  ID label_name;
4450 
4451  if (!labels_table) {
4452  labels_table = st_init_numtable();
4453  iseq->compile_data->labels_table = labels_table;
4454  }
4455  if (nd_type(node->nd_args->nd_head) == NODE_LIT &&
4456  SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
4457 
4458  label_name = SYM2ID(node->nd_args->nd_head->nd_lit);
4459  if (!st_lookup(labels_table, (st_data_t)label_name, &data)) {
4460  label = NEW_LABEL(line);
4461  label->position = line;
4462  st_insert(labels_table, (st_data_t)label_name, (st_data_t)label);
4463  }
4464  else {
4465  label = (LABEL *)data;
4466  }
4467  }
4468  else {
4469  COMPILE_ERROR((ERROR_ARGS "invalid goto/label format"));
4470  }
4471 
4472 
4473  if (mid == goto_id) {
4474  ADD_INSNL(ret, line, jump, label);
4475  }
4476  else {
4477  ADD_LABEL(ret, label);
4478  }
4479  break;
4480  }
4481  }
4482 #endif
4483  /* receiver */
4484  if (type == NODE_CALL) {
4485  COMPILE(recv, "recv", node->nd_recv);
4486  }
4487  else if (type == NODE_FCALL || type == NODE_VCALL) {
4488  ADD_CALL_RECEIVER(recv, line);
4489  }
4490 
4491  /* args */
4492  if (nd_type(node) != NODE_VCALL) {
4493  argc = setup_args(iseq, args, node->nd_args, &flag);
4494  }
4495  else {
4496  argc = INT2FIX(0);
4497  }
4498 
4499  ADD_SEQ(ret, recv);
4500  ADD_SEQ(ret, args);
4501 
4502  debugp_param("call args argc", argc);
4503  debugp_param("call method", ID2SYM(mid));
4504 
4505  switch (nd_type(node)) {
4506  case NODE_VCALL:
4507  flag |= VM_CALL_VCALL;
4508  /* VCALL is funcall, so fall through */
4509  case NODE_FCALL:
4510  flag |= VM_CALL_FCALL;
4511  }
4512 
4513  ADD_SEND_R(ret, line, ID2SYM(mid),
4514  argc, parent_block, LONG2FIX(flag));
4515 
4516  if (poped) {
4517  ADD_INSN(ret, line, pop);
4518  }
4519  break;
4520  }
4521  case NODE_SUPER:
4522  case NODE_ZSUPER:{
4523  DECL_ANCHOR(args);
4524  int argc;
4525  VALUE flag = 0;
4526  VALUE parent_block = iseq->compile_data->current_block;
4527 
4528  INIT_ANCHOR(args);
4530  if (nd_type(node) == NODE_SUPER) {
4531  VALUE vargc = setup_args(iseq, args, node->nd_args, &flag);
4532  argc = FIX2INT(vargc);
4533  }
4534  else {
4535  /* NODE_ZSUPER */
4536  int i;
4537  rb_iseq_t *liseq = iseq->local_iseq;
4538  int lvar_level = get_lvar_level(iseq);
4539 
4540  argc = liseq->argc;
4541 
4542  /* normal arguments */
4543  for (i = 0; i < liseq->argc; i++) {
4544  int idx = liseq->local_size - i;
4545  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4546  }
4547 
4548  if (!liseq->arg_simple) {
4549  if (liseq->arg_opts) {
4550  /* optional arguments */
4551  int j;
4552  for (j = 0; j < liseq->arg_opts - 1; j++) {
4553  int idx = liseq->local_size - (i + j);
4554  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4555  }
4556  i += j;
4557  argc = i;
4558  }
4559 
4560  if (liseq->arg_rest != -1) {
4561  /* rest argument */
4562  int idx = liseq->local_size - liseq->arg_rest;
4563  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4564  argc = liseq->arg_rest + 1;
4565  flag |= VM_CALL_ARGS_SPLAT;
4566  }
4567 
4568  if (liseq->arg_post_len) {
4569  /* post arguments */
4570  int post_len = liseq->arg_post_len;
4571  int post_start = liseq->arg_post_start;
4572 
4573  if (liseq->arg_rest != -1) {
4574  int j;
4575  for (j=0; j<post_len; j++) {
4576  int idx = liseq->local_size - (post_start + j);
4577  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4578  }
4579  ADD_INSN1(args, line, newarray, INT2FIX(j));
4580  ADD_INSN (args, line, concatarray);
4581  /* argc is settled at above */
4582  }
4583  else {
4584  int j;
4585  for (j=0; j<post_len; j++) {
4586  int idx = liseq->local_size - (post_start + j);
4587  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4588  }
4589  argc = post_len + post_start;
4590  }
4591  }
4592 
4593  if (liseq->arg_keyword >= 0) {
4594  int local_size = liseq->local_size;
4595  int idx = local_size - liseq->arg_keyword;
4596  argc++;
4597  ADD_INSN1(args, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
4598  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4599  ADD_SEND (args, line, ID2SYM(rb_intern("dup")), INT2FIX(0));
4600  for (i = 0; i < liseq->arg_keywords; ++i) {
4601  ID id = liseq->arg_keyword_table[i];
4602  idx = local_size - get_local_var_idx(liseq, id);
4603  ADD_INSN1(args, line, putobject, ID2SYM(id));
4604  ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
4605  }
4606  ADD_SEND(args, line, ID2SYM(id_core_hash_merge_ptr), INT2FIX(i * 2 + 1));
4607  if (liseq->arg_rest != -1) {
4608  ADD_INSN1(args, line, newarray, INT2FIX(1));
4609  ADD_INSN (args, line, concatarray);
4610  --argc;
4611  }
4612  }
4613  }
4614  }
4615 
4616  /* dummy receiver */
4617  ADD_INSN1(ret, line, putobject, nd_type(node) == NODE_ZSUPER ? Qfalse : Qtrue);
4618  ADD_SEQ(ret, args);
4619  ADD_INSN1(ret, line, invokesuper, new_callinfo(iseq, 0, argc, parent_block,
4620  flag | VM_CALL_SUPER | VM_CALL_FCALL));
4621 
4622  if (poped) {
4623  ADD_INSN(ret, line, pop);
4624  }
4625  break;
4626  }
4627  case NODE_ARRAY:{
4628  compile_array_(iseq, ret, node, COMPILE_ARRAY_TYPE_ARRAY, poped);
4629  break;
4630  }
4631  case NODE_ZARRAY:{
4632  if (!poped) {
4633  ADD_INSN1(ret, line, newarray, INT2FIX(0));
4634  }
4635  break;
4636  }
4637  case NODE_VALUES:{
4638  NODE *n = node;
4639  while (n) {
4640  COMPILE(ret, "values item", n->nd_head);
4641  n = n->nd_next;
4642  }
4643  ADD_INSN1(ret, line, newarray, INT2FIX(node->nd_alen));
4644  if (poped) {
4645  ADD_INSN(ret, line, pop);
4646  }
4647  break;
4648  }
4649  case NODE_HASH:{
4650  DECL_ANCHOR(list);
4651  int type = node->nd_head ? nd_type(node->nd_head) : NODE_ZARRAY;
4652 
4653  INIT_ANCHOR(list);
4654  switch (type) {
4655  case NODE_ARRAY:
4656  compile_array(iseq, list, node->nd_head, COMPILE_ARRAY_TYPE_HASH);
4657  ADD_SEQ(ret, list);
4658  break;
4659 
4660  case NODE_ZARRAY:
4661  ADD_INSN1(ret, line, newhash, INT2FIX(0));
4662  break;
4663 
4664  default:
4665  rb_bug("can't make hash with this node: %s", ruby_node_name(type));
4666  }
4667 
4668  if (poped) {
4669  ADD_INSN(ret, line, pop);
4670  }
4671  break;
4672  }
4673  case NODE_RETURN:{
4674  rb_iseq_t *is = iseq;
4675 
4676  if (is) {
4677  if (is->type == ISEQ_TYPE_TOP) {
4678  COMPILE_ERROR((ERROR_ARGS "Invalid return"));
4679  }
4680  else {
4681  LABEL *splabel = 0;
4682 
4683  if (is->type == ISEQ_TYPE_METHOD) {
4684  splabel = NEW_LABEL(0);
4685  ADD_LABEL(ret, splabel);
4686  ADD_ADJUST(ret, line, 0);
4687  }
4688 
4689  COMPILE(ret, "return nd_stts (return val)", node->nd_stts);
4690 
4691  if (is->type == ISEQ_TYPE_METHOD) {
4692  add_ensure_iseq(ret, iseq, 1);
4693  ADD_TRACE(ret, line, RUBY_EVENT_RETURN);
4694  ADD_INSN(ret, line, leave);
4695  ADD_ADJUST_RESTORE(ret, splabel);
4696 
4697  if (!poped) {
4698  ADD_INSN(ret, line, putnil);
4699  }
4700  }
4701  else {
4702  ADD_INSN1(ret, line, throw, INT2FIX(0x01) /* TAG_RETURN */ );
4703  if (poped) {
4704  ADD_INSN(ret, line, pop);
4705  }
4706  }
4707  }
4708  }
4709  break;
4710  }
4711  case NODE_YIELD:{
4712  DECL_ANCHOR(args);
4713  VALUE argc;
4714  VALUE flag = 0;
4715 
4716  INIT_ANCHOR(args);
4717  if (iseq->type == ISEQ_TYPE_TOP) {
4718  COMPILE_ERROR((ERROR_ARGS "Invalid yield"));
4719  }
4720 
4721  if (node->nd_head) {
4722  argc = setup_args(iseq, args, node->nd_head, &flag);
4723  }
4724  else {
4725  argc = INT2FIX(0);
4726  }
4727 
4728  ADD_SEQ(ret, args);
4729  ADD_INSN1(ret, line, invokeblock, new_callinfo(iseq, 0, FIX2INT(argc), 0, flag));
4730 
4731  if (poped) {
4732  ADD_INSN(ret, line, pop);
4733  }
4734  break;
4735  }
4736  case NODE_LVAR:{
4737  if (!poped) {
4738  ID id = node->nd_vid;
4739  int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id);
4740 
4741  debugs("id: %s idx: %d\n", rb_id2name(id), idx);
4742  ADD_INSN2(ret, line, getlocal, INT2FIX(idx), INT2FIX(get_lvar_level(iseq)));
4743  }
4744  break;
4745  }
4746  case NODE_DVAR:{
4747  int lv, idx, ls;
4748  debugi("nd_vid", node->nd_vid);
4749  if (!poped) {
4750  idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
4751  if (idx < 0) {
4752  rb_bug("unknown dvar (%s)", rb_id2name(node->nd_vid));
4753  }
4754  ADD_INSN2(ret, line, getlocal, INT2FIX(ls - idx), INT2FIX(lv));
4755  }
4756  break;
4757  }
4758  case NODE_GVAR:{
4759  ADD_INSN1(ret, line, getglobal,
4760  ((VALUE)node->nd_entry | 1));
4761  if (poped) {
4762  ADD_INSN(ret, line, pop);
4763  }
4764  break;
4765  }
4766  case NODE_IVAR:{
4767  debugi("nd_vid", node->nd_vid);
4768  if (!poped) {
4769  ADD_INSN2(ret, line, getinstancevariable,
4770  ID2SYM(node->nd_vid), INT2FIX(iseq->is_size++));
4771  }
4772  break;
4773  }
4774  case NODE_CONST:{
4775  debugi("nd_vid", node->nd_vid);
4776 
4777  if (iseq->compile_data->option->inline_const_cache) {
4778  LABEL *lend = NEW_LABEL(line);
4779  int ic_index = iseq->is_size++;
4780 
4781  ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index));
4782  ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid));
4783  ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index));
4784  ADD_LABEL(ret, lend);
4785  }
4786  else {
4787  ADD_INSN(ret, line, putnil);
4788  ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid));
4789  }
4790 
4791  if (poped) {
4792  ADD_INSN(ret, line, pop);
4793  }
4794  break;
4795  }
4796  case NODE_CVAR:{
4797  if (!poped) {
4798  ADD_INSN1(ret, line, getclassvariable,
4799  ID2SYM(node->nd_vid));
4800  }
4801  break;
4802  }
4803  case NODE_NTH_REF:{
4804  if (!poped) {
4805  if (!node->nd_nth) {
4806  ADD_INSN(ret, line, putnil);
4807  break;
4808  }
4809  ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */,
4810  INT2FIX(node->nd_nth << 1));
4811  }
4812  break;
4813  }
4814  case NODE_BACK_REF:{
4815  if (!poped) {
4816  ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */,
4817  INT2FIX(0x01 | (node->nd_nth << 1)));
4818  }
4819  break;
4820  }
4821  case NODE_MATCH:
4822  case NODE_MATCH2:
4823  case NODE_MATCH3:{
4824  DECL_ANCHOR(recv);
4825  DECL_ANCHOR(val);
4826 
4827  INIT_ANCHOR(recv);
4828  INIT_ANCHOR(val);
4829  switch (nd_type(node)) {
4830  case NODE_MATCH:
4831  ADD_INSN1(recv, line, putobject, node->nd_lit);
4832  ADD_INSN2(val, line, getspecial, INT2FIX(0),
4833  INT2FIX(0));
4834  break;
4835  case NODE_MATCH2:
4836  COMPILE(recv, "receiver", node->nd_recv);
4837  COMPILE(val, "value", node->nd_value);
4838  break;
4839  case NODE_MATCH3:
4840  COMPILE(recv, "receiver", node->nd_value);
4841  COMPILE(val, "value", node->nd_recv);
4842  break;
4843  }
4844 
4846  /* TODO: detect by node */
4847  if (recv->last == recv->anchor.next &&
4848  INSN_OF(recv->last) == BIN(putobject) &&
4849  nd_type(node) == NODE_MATCH2) {
4850  ADD_SEQ(ret, val);
4851  ADD_INSN1(ret, line, opt_regexpmatch1,
4852  OPERAND_AT(recv->last, 0));
4853  }
4854  else {
4855  ADD_SEQ(ret, recv);
4856  ADD_SEQ(ret, val);
4857  ADD_INSN1(ret, line, opt_regexpmatch2, new_callinfo(iseq, idEqTilde, 1, 0, 0));
4858  }
4859  }
4860  else {
4861  ADD_SEQ(ret, recv);
4862  ADD_SEQ(ret, val);
4863  ADD_SEND(ret, line, ID2SYM(idEqTilde), INT2FIX(1));
4864  }
4865 
4866  if (poped) {
4867  ADD_INSN(ret, line, pop);
4868  }
4869  break;
4870  }
4871  case NODE_LIT:{
4872  debugp_param("lit", node->nd_lit);
4873  if (!poped) {
4874  ADD_INSN1(ret, line, putobject, node->nd_lit);
4875  }
4876  break;
4877  }
4878  case NODE_STR:{
4879  node->nd_lit = rb_fstring(node->nd_lit);
4880  debugp_param("nd_lit", node->nd_lit);
4881  if (!poped) {
4882  ADD_INSN1(ret, line, putstring, node->nd_lit);
4883  }
4884  break;
4885  }
4886  case NODE_DSTR:{
4887  compile_dstr(iseq, ret, node);
4888 
4889  if (poped) {
4890  ADD_INSN(ret, line, pop);
4891  }
4892  break;
4893  }
4894  case NODE_XSTR:{
4895  node->nd_lit = rb_fstring(node->nd_lit);
4896  ADD_CALL_RECEIVER(ret, line);
4897  ADD_INSN1(ret, line, putobject, node->nd_lit);
4898  ADD_CALL(ret, line, ID2SYM(idBackquote), INT2FIX(1));
4899 
4900  if (poped) {
4901  ADD_INSN(ret, line, pop);
4902  }
4903  break;
4904  }
4905  case NODE_DXSTR:{
4906  ADD_CALL_RECEIVER(ret, line);
4907  compile_dstr(iseq, ret, node);
4908  ADD_CALL(ret, line, ID2SYM(idBackquote), INT2FIX(1));
4909 
4910  if (poped) {
4911  ADD_INSN(ret, line, pop);
4912  }
4913  break;
4914  }
4915  case NODE_EVSTR:{
4916  COMPILE(ret, "nd_body", node->nd_body);
4917 
4918  if (poped) {
4919  ADD_INSN(ret, line, pop);
4920  }
4921  else {
4922  ADD_INSN(ret, line, tostring);
4923  }
4924  break;
4925  }
4926  case NODE_DREGX:{
4927  compile_dregx(iseq, ret, node);
4928 
4929  if (poped) {
4930  ADD_INSN(ret, line, pop);
4931  }
4932  break;
4933  }
4934  case NODE_DREGX_ONCE:{
4935  int ic_index = iseq->is_size++;
4936  NODE *dregx_node = NEW_NODE(NODE_DREGX, node->u1.value, node->u2.value, node->u3.value);
4937  NODE *block_node = NEW_NODE(NODE_SCOPE, 0, dregx_node, 0);
4938  VALUE block_iseq = NEW_CHILD_ISEQVAL(block_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
4939 
4940  ADD_INSN2(ret, line, once, block_iseq, INT2FIX(ic_index));
4941 
4942  if (poped) {
4943  ADD_INSN(ret, line, pop);
4944  }
4945  break;
4946  }
4947  case NODE_ARGSCAT:{
4948  if (poped) {
4949  COMPILE(ret, "argscat head", node->nd_head);
4950  ADD_INSN1(ret, line, splatarray, Qfalse);
4951  ADD_INSN(ret, line, pop);
4952  COMPILE(ret, "argscat body", node->nd_body);
4953  ADD_INSN1(ret, line, splatarray, Qfalse);
4954  ADD_INSN(ret, line, pop);
4955  }
4956  else {
4957  COMPILE(ret, "argscat head", node->nd_head);
4958  COMPILE(ret, "argscat body", node->nd_body);
4959  ADD_INSN(ret, line, concatarray);
4960  }
4961  break;
4962  }
4963  case NODE_ARGSPUSH:{
4964  if (poped) {
4965  COMPILE(ret, "arsgpush head", node->nd_head);
4966  ADD_INSN1(ret, line, splatarray, Qfalse);
4967  ADD_INSN(ret, line, pop);
4968  COMPILE_(ret, "argspush body", node->nd_body, poped);
4969  }
4970  else {
4971  COMPILE(ret, "arsgpush head", node->nd_head);
4972  COMPILE_(ret, "argspush body", node->nd_body, poped);
4973  ADD_INSN1(ret, line, newarray, INT2FIX(1));
4974  ADD_INSN(ret, line, concatarray);
4975  }
4976  break;
4977  }
4978  case NODE_SPLAT:{
4979  COMPILE(ret, "splat", node->nd_head);
4980  ADD_INSN1(ret, line, splatarray, Qtrue);
4981 
4982  if (poped) {
4983  ADD_INSN(ret, line, pop);
4984  }
4985  break;
4986  }
4987  case NODE_DEFN:{
4988  VALUE iseqval = NEW_ISEQVAL(node->nd_defn,
4989  rb_id2str(node->nd_mid),
4990  ISEQ_TYPE_METHOD, line);
4991 
4992  debugp_param("defn/iseq", iseqval);
4993 
4994  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
4995  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
4996  ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid));
4997  ADD_INSN1(ret, line, putiseq, iseqval);
4998  ADD_SEND (ret, line, ID2SYM(id_core_define_method), INT2FIX(3));
4999 
5000  if (poped) {
5001  ADD_INSN(ret, line, pop);
5002  }
5003 
5004  debugp_param("defn", iseqval);
5005  break;
5006  }
5007  case NODE_DEFS:{
5008  VALUE iseqval = NEW_ISEQVAL(node->nd_defn,
5009  rb_id2str(node->nd_mid),
5010  ISEQ_TYPE_METHOD, line);
5011 
5012  debugp_param("defs/iseq", iseqval);
5013 
5014  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5015  COMPILE(ret, "defs: recv", node->nd_recv);
5016  ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid));
5017  ADD_INSN1(ret, line, putiseq, iseqval);
5019 
5020  if (poped) {
5021  ADD_INSN(ret, line, pop);
5022  }
5023  break;
5024  }
5025  case NODE_ALIAS:{
5026  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5027  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
5028  COMPILE(ret, "alias arg1", node->u1.node);
5029  COMPILE(ret, "alias arg2", node->u2.node);
5031 
5032  if (poped) {
5033  ADD_INSN(ret, line, pop);
5034  }
5035  break;
5036  }
5037  case NODE_VALIAS:{
5038  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5039  ADD_INSN1(ret, line, putobject, ID2SYM(node->u1.id));
5040  ADD_INSN1(ret, line, putobject, ID2SYM(node->u2.id));
5042 
5043  if (poped) {
5044  ADD_INSN(ret, line, pop);
5045  }
5046  break;
5047  }
5048  case NODE_UNDEF:{
5049  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5050  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
5051  COMPILE(ret, "undef arg", node->u2.node);
5052  ADD_SEND(ret, line, ID2SYM(id_core_undef_method), INT2FIX(2));
5053 
5054  if (poped) {
5055  ADD_INSN(ret, line, pop);
5056  }
5057  break;
5058  }
5059  case NODE_CLASS:{
5060  VALUE iseqval =
5062  node->nd_body,
5063  rb_sprintf("<class:%s>", rb_id2name(node->nd_cpath->nd_mid)),
5064  ISEQ_TYPE_CLASS, line);
5065  VALUE noscope = compile_cpath(ret, iseq, node->nd_cpath);
5067  if (!noscope) flags |= VM_DEFINECLASS_FLAG_SCOPED;
5068  if (node->nd_super) flags |= VM_DEFINECLASS_FLAG_HAS_SUPERCLASS;
5069  COMPILE(ret, "super", node->nd_super);
5070  ADD_INSN3(ret, line, defineclass,
5071  ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(flags));
5072 
5073  if (poped) {
5074  ADD_INSN(ret, line, pop);
5075  }
5076  break;
5077  }
5078  case NODE_MODULE:{
5079  VALUE iseqval = NEW_CHILD_ISEQVAL(
5080  node->nd_body,
5081  rb_sprintf("<module:%s>", rb_id2name(node->nd_cpath->nd_mid)),
5082  ISEQ_TYPE_CLASS, line);
5083 
5084  VALUE noscope = compile_cpath(ret, iseq, node->nd_cpath);
5086  if (!noscope) flags |= VM_DEFINECLASS_FLAG_SCOPED;
5087  ADD_INSN (ret, line, putnil); /* dummy */
5088  ADD_INSN3(ret, line, defineclass,
5089  ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(flags));
5090  if (poped) {
5091  ADD_INSN(ret, line, pop);
5092  }
5093  break;
5094  }
5095  case NODE_SCLASS:{
5096  ID singletonclass;
5097  VALUE iseqval =
5098  NEW_ISEQVAL(node->nd_body, rb_str_new2("singleton class"),
5099  ISEQ_TYPE_CLASS, line);
5100 
5101  COMPILE(ret, "sclass#recv", node->nd_recv);
5102  ADD_INSN (ret, line, putnil);
5103  CONST_ID(singletonclass, "singletonclass");
5104  ADD_INSN3(ret, line, defineclass,
5105  ID2SYM(singletonclass), iseqval,
5107 
5108  if (poped) {
5109  ADD_INSN(ret, line, pop);
5110  }
5111  break;
5112  }
5113  case NODE_COLON2:{
5114  if (rb_is_const_id(node->nd_mid)) {
5115  /* constant */
5116  LABEL *lend = NEW_LABEL(line);
5117  int ic_index = iseq->is_size++;
5118 
5119  DECL_ANCHOR(pref);
5120  DECL_ANCHOR(body);
5121 
5122  INIT_ANCHOR(pref);
5123  INIT_ANCHOR(body);
5124  compile_colon2(iseq, node, pref, body);
5125  if (LIST_SIZE_ZERO(pref)) {
5126  if (iseq->compile_data->option->inline_const_cache) {
5127  ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index));
5128  }
5129  else {
5130  ADD_INSN(ret, line, putnil);
5131  }
5132 
5133  ADD_SEQ(ret, body);
5134 
5135  if (iseq->compile_data->option->inline_const_cache) {
5136  ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index));
5137  ADD_LABEL(ret, lend);
5138  }
5139  }
5140  else {
5141  ADD_SEQ(ret, pref);
5142  ADD_SEQ(ret, body);
5143  }
5144  }
5145  else {
5146  /* function call */
5147  ADD_CALL_RECEIVER(ret, line);
5148  COMPILE(ret, "colon2#nd_head", node->nd_head);
5149  ADD_CALL(ret, line, ID2SYM(node->nd_mid),
5150  INT2FIX(1));
5151  }
5152  if (poped) {
5153  ADD_INSN(ret, line, pop);
5154  }
5155  break;
5156  }
5157  case NODE_COLON3:{
5158  LABEL *lend = NEW_LABEL(line);
5159  int ic_index = iseq->is_size++;
5160 
5161  debugi("colon3#nd_mid", node->nd_mid);
5162 
5163  /* add cache insn */
5164  if (iseq->compile_data->option->inline_const_cache) {
5165  ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index));
5166  ADD_INSN(ret, line, pop);
5167  }
5168 
5169  ADD_INSN1(ret, line, putobject, rb_cObject);
5170  ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_mid));
5171 
5172  if (iseq->compile_data->option->inline_const_cache) {
5173  ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index));
5174  ADD_LABEL(ret, lend);
5175  }
5176 
5177  if (poped) {
5178  ADD_INSN(ret, line, pop);
5179  }
5180  break;
5181  }
5182  case NODE_DOT2:
5183  case NODE_DOT3:{
5184  VALUE flag = type == NODE_DOT2 ? INT2FIX(0) : INT2FIX(1);
5185  COMPILE(ret, "min", (NODE *) node->nd_beg);
5186  COMPILE(ret, "max", (NODE *) node->nd_end);
5187  if (poped) {
5188  ADD_INSN(ret, line, pop);
5189  ADD_INSN(ret, line, pop);
5190  }
5191  else {
5192  ADD_INSN1(ret, line, newrange, flag);
5193  }
5194  break;
5195  }
5196  case NODE_FLIP2:
5197  case NODE_FLIP3:{
5198  LABEL *lend = NEW_LABEL(line);
5199  LABEL *lfin = NEW_LABEL(line);
5200  LABEL *ltrue = NEW_LABEL(line);
5201  rb_iseq_t *local_iseq = iseq->local_iseq;
5202  rb_num_t cnt;
5203  VALUE key;
5204 
5205  cnt = local_iseq->flip_cnt++ + DEFAULT_SPECIAL_VAR_COUNT;
5206  key = INT2FIX(cnt);
5207 
5208  ADD_INSN2(ret, line, getspecial, key, INT2FIX(0));
5209  ADD_INSNL(ret, line, branchif, lend);
5210 
5211  /* *flip == 0 */
5212  COMPILE(ret, "flip2 beg", node->nd_beg);
5213  ADD_INSN(ret, line, dup);
5214  ADD_INSNL(ret, line, branchunless, lfin);
5215  if (nd_type(node) == NODE_FLIP3) {
5216  ADD_INSN(ret, line, dup);
5217  ADD_INSN1(ret, line, setspecial, key);
5218  ADD_INSNL(ret, line, jump, lfin);
5219  }
5220  else {
5221  ADD_INSN1(ret, line, setspecial, key);
5222  }
5223 
5224  /* *flip == 1 */
5225  ADD_LABEL(ret, lend);
5226  COMPILE(ret, "flip2 end", node->nd_end);
5227  ADD_INSNL(ret, line, branchunless, ltrue);
5228  ADD_INSN1(ret, line, putobject, Qfalse);
5229  ADD_INSN1(ret, line, setspecial, key);
5230 
5231  ADD_LABEL(ret, ltrue);
5232  ADD_INSN1(ret, line, putobject, Qtrue);
5233 
5234  ADD_LABEL(ret, lfin);
5235  break;
5236  }
5237  case NODE_SELF:{
5238  if (!poped) {
5239  ADD_INSN(ret, line, putself);
5240  }
5241  break;
5242  }
5243  case NODE_NIL:{
5244  if (!poped) {
5245  ADD_INSN(ret, line, putnil);
5246  }
5247  break;
5248  }
5249  case NODE_TRUE:{
5250  if (!poped) {
5251  ADD_INSN1(ret, line, putobject, Qtrue);
5252  }
5253  break;
5254  }
5255  case NODE_FALSE:{
5256  if (!poped) {
5257  ADD_INSN1(ret, line, putobject, Qfalse);
5258  }
5259  break;
5260  }
5261  case NODE_ERRINFO:{
5262  if (!poped) {
5263  if (iseq->type == ISEQ_TYPE_RESCUE) {
5264  ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0));
5265  }
5266  else {
5267  rb_iseq_t *ip = iseq;
5268  int level = 0;
5269  while (ip) {
5270  if (ip->type == ISEQ_TYPE_RESCUE) {
5271  break;
5272  }
5273  ip = ip->parent_iseq;
5274  level++;
5275  }
5276  if (ip) {
5277  ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(level));
5278  }
5279  else {
5280  ADD_INSN(ret, line, putnil);
5281  }
5282  }
5283  }
5284  break;
5285  }
5286  case NODE_DEFINED:{
5287  if (poped) break;
5288  if (!node->nd_head) {
5290  ADD_INSN1(ret, nd_line(node), putobject, str);
5291  }
5292  else {
5293  LABEL *lfinish[2];
5294  lfinish[0] = NEW_LABEL(line);
5295  lfinish[1] = 0;
5296  ADD_INSN(ret, line, putnil);
5297  defined_expr(iseq, ret, node->nd_head, lfinish, Qtrue);
5298  ADD_INSN(ret, line, swap);
5299  ADD_INSN(ret, line, pop);
5300  if (lfinish[1]) {
5301  ADD_LABEL(ret, lfinish[1]);
5302  }
5303  ADD_LABEL(ret, lfinish[0]);
5304  }
5305  break;
5306  }
5307  case NODE_POSTEXE:{
5308  /* compiled to:
5309  * ONCE{ rb_mRubyVMFrozenCore::core#set_postexe{ ... } }
5310  */
5311  int is_index = iseq->is_size++;
5312  VALUE once_iseq = NEW_CHILD_ISEQVAL(
5313  NEW_IFUNC(build_postexe_iseq, node->nd_body),
5314  make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
5315 
5316  ADD_INSN2(ret, line, once, once_iseq, INT2FIX(is_index));
5317 
5318  if (poped) {
5319  ADD_INSN(ret, line, pop);
5320  }
5321  break;
5322  }
5323  case NODE_KW_ARG:{
5324  LABEL *default_label = NEW_LABEL(line);
5325  LABEL *end_label = 0;
5326  int idx, lv, ls;
5327  ID id = node->nd_body->nd_vid;
5328 
5329  ADD_INSN(ret, line, dup);
5330  ADD_INSN1(ret, line, putobject, ID2SYM(id));
5331  ADD_SEND(ret, line, ID2SYM(rb_intern("key?")), INT2FIX(1));
5332  ADD_INSNL(ret, line, branchunless, default_label);
5333  ADD_INSN(ret, line, dup);
5334  ADD_INSN1(ret, line, putobject, ID2SYM(id));
5335  ADD_SEND(ret, line, ID2SYM(rb_intern("delete")), INT2FIX(1));
5336  switch (nd_type(node->nd_body)) {
5337  case NODE_LASGN:
5338  idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id);
5339  ADD_INSN2(ret, line, setlocal, INT2FIX(idx), INT2FIX(get_lvar_level(iseq)));
5340  break;
5341  case NODE_DASGN:
5342  case NODE_DASGN_CURR:
5343  idx = get_dyna_var_idx(iseq, id, &lv, &ls);
5344  ADD_INSN2(ret, line, setlocal, INT2FIX(ls - idx), INT2FIX(lv));
5345  break;
5346  default:
5347  rb_bug("iseq_compile_each (NODE_KW_ARG): unknown node: %s", ruby_node_name(nd_type(node->nd_body)));
5348  }
5349  if (node->nd_body->nd_value != (NODE *)-1) {
5350  end_label = NEW_LABEL(nd_line(node));
5351  ADD_INSNL(ret, nd_line(node), jump, end_label);
5352  }
5353  ADD_LABEL(ret, default_label);
5354  if (node->nd_body->nd_value != (NODE *)-1) {
5355  COMPILE_POPED(ret, "keyword default argument", node->nd_body);
5356  ADD_LABEL(ret, end_label);
5357  }
5358  break;
5359  }
5360  case NODE_DSYM:{
5361  compile_dstr(iseq, ret, node);
5362  if (!poped) {
5363  ADD_SEND(ret, line, ID2SYM(idIntern), INT2FIX(0));
5364  }
5365  else {
5366  ADD_INSN(ret, line, pop);
5367  }
5368  break;
5369  }
5370  case NODE_ATTRASGN:{
5371  DECL_ANCHOR(recv);
5372  DECL_ANCHOR(args);
5373  VALUE flag = 0;
5374  VALUE argc;
5375 
5376  INIT_ANCHOR(recv);
5377  INIT_ANCHOR(args);
5378  argc = setup_args(iseq, args, node->nd_args, &flag);
5379 
5380  if (node->nd_recv == (NODE *) 1) {
5381  flag |= VM_CALL_FCALL;
5382  ADD_INSN(recv, line, putself);
5383  }
5384  else {
5385  COMPILE(recv, "recv", node->nd_recv);
5386  }
5387 
5388  debugp_param("argc", argc);
5389  debugp_param("nd_mid", ID2SYM(node->nd_mid));
5390 
5391  if (!poped) {
5392  ADD_INSN(ret, line, putnil);
5393  ADD_SEQ(ret, recv);
5394  ADD_SEQ(ret, args);
5395 
5396  if (flag & VM_CALL_ARGS_BLOCKARG) {
5397  ADD_INSN1(ret, line, topn, INT2FIX(1));
5398  if (flag & VM_CALL_ARGS_SPLAT) {
5399  ADD_INSN1(ret, line, putobject, INT2FIX(-1));
5400  ADD_SEND(ret, line, ID2SYM(idAREF), INT2FIX(1));
5401  }
5402  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 3));
5403  ADD_INSN (ret, line, pop);
5404  }
5405  else if (flag & VM_CALL_ARGS_SPLAT) {
5406  ADD_INSN(ret, line, dup);
5407  ADD_INSN1(ret, line, putobject, INT2FIX(-1));
5408  ADD_SEND(ret, line, ID2SYM(idAREF), INT2FIX(1));
5409  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2));
5410  ADD_INSN (ret, line, pop);
5411  }
5412  else {
5413  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 1));
5414  }
5415  }
5416  else {
5417  ADD_SEQ(ret, recv);
5418  ADD_SEQ(ret, args);
5419  }
5420  ADD_SEND_R(ret, line, ID2SYM(node->nd_mid), argc, 0, LONG2FIX(flag));
5421  ADD_INSN(ret, line, pop);
5422 
5423  break;
5424  }
5425  case NODE_PRELUDE:{
5426  COMPILE_POPED(ret, "prelude", node->nd_head);
5427  COMPILE_(ret, "body", node->nd_body, poped);
5428  break;
5429  }
5430  case NODE_LAMBDA:{
5431  /* compile same as lambda{...} */
5432  VALUE block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
5433  VALUE argc = INT2FIX(0);
5434  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5435  ADD_CALL_WITH_BLOCK(ret, line, ID2SYM(idLambda), argc, block);
5436 
5437  if (poped) {
5438  ADD_INSN(ret, line, pop);
5439  }
5440  break;
5441  }
5442  default:
5443  rb_bug("iseq_compile_each: unknown node: %s", ruby_node_name(type));
5444  return COMPILE_NG;
5445  }
5446 
5447  /* check & remove redundant trace(line) */
5448  if (saved_last_element && ret /* ret can be 0 when error */ &&
5449  ret->last == saved_last_element &&
5450  ((INSN *)saved_last_element)->insn_id == BIN(trace)) {
5451  POP_ELEMENT(ret);
5452  }
5453 
5454  debug_node_end();
5455  return COMPILE_OK;
5456 }
5457 
5458 /***************************/
5459 /* instruction information */
5460 /***************************/
5461 
5462 static int
5464 {
5465  return insn_len(iobj->insn_id);
5466 }
5467 
5468 static int
5470 {
5471  return insn_stack_increase(depth, insn->insn_id, insn->operands);
5472 }
5473 
5474 static VALUE
5476 {
5477  struct RBasic *r = (struct RBasic *) obj;
5478  if (!SPECIAL_CONST_P(r) && r->klass == 0) {
5479  switch (BUILTIN_TYPE(r)) {
5480  case T_STRING:
5481  obj = rb_str_new_cstr(RSTRING_PTR(obj));
5482  break;
5483  case T_ARRAY:
5484  obj = rb_ary_dup(obj);
5485  break;
5486  }
5487  }
5488  return rb_inspect(obj);
5489 }
5490 
5491 
5492 
5493 static VALUE
5495 {
5496  VALUE str = rb_sprintf("%-20s ", insn_name(iobj->insn_id));
5497 
5498  if (iobj->operands) {
5499  const char *types = insn_op_types(iobj->insn_id);
5500  int j;
5501 
5502  for (j = 0; types[j]; j++) {
5503  char type = types[j];
5504 
5505  switch (type) {
5506  case TS_OFFSET: /* label(destination position) */
5507  {
5508  LABEL *lobj = (LABEL *)OPERAND_AT(iobj, j);
5509  rb_str_catf(str, "<L%03d>", lobj->label_no);
5510  break;
5511  }
5512  break;
5513  case TS_ISEQ: /* iseq */
5514  {
5515  rb_iseq_t *iseq = (rb_iseq_t *)OPERAND_AT(iobj, j);
5516  VALUE val = Qnil;
5517  if (0 && iseq) { /* TODO: invalidate now */
5518  val = iseq->self;
5519  }
5520  rb_str_concat(str, opobj_inspect(val));
5521  }
5522  break;
5523  case TS_LINDEX:
5524  case TS_NUM: /* ulong */
5525  case TS_VALUE: /* VALUE */
5526  {
5527  VALUE v = OPERAND_AT(iobj, j);
5528  rb_str_concat(str, opobj_inspect(v));
5529  break;
5530  }
5531  case TS_ID: /* ID */
5532  rb_str_concat(str, opobj_inspect(OPERAND_AT(iobj, j)));
5533  break;
5534  case TS_GENTRY:
5535  {
5536  struct rb_global_entry *entry = (struct rb_global_entry *)
5537  (OPERAND_AT(iobj, j) & (~1));
5538  rb_str_cat2(str, rb_id2name(entry->id));
5539  break;
5540  }
5541  case TS_IC: /* inline cache */
5542  rb_str_catf(str, "<ic:%d>", FIX2INT(OPERAND_AT(iobj, j)));
5543  break;
5544  case TS_CALLINFO: /* call info */
5545  {
5546  rb_call_info_t *ci = (rb_call_info_t *)OPERAND_AT(iobj, j);
5547  rb_str_catf(str, "<callinfo:%s, %d>", ci->mid ? rb_id2name(ci->mid) : "", ci->orig_argc);
5548  break;
5549  }
5550  case TS_CDHASH: /* case/when condition cache */
5551  rb_str_cat2(str, "<ch>");
5552  break;
5553  default:{
5554  rb_raise(rb_eSyntaxError, "unknown operand type: %c", type);
5555  }
5556  }
5557  if (types[j + 1]) {
5558  rb_str_cat2(str, ", ");
5559  }
5560  }
5561  }
5562  return str;
5563 }
5564 
5565 static void
5567 {
5568  int pos = 0;
5569  INSN *iobj;
5570  LABEL *lobj;
5571  VALUE str;
5572 
5573  printf("-- raw disasm--------\n");
5574 
5575  while (link) {
5576  switch (link->type) {
5577  case ISEQ_ELEMENT_INSN:
5578  {
5579  iobj = (INSN *)link;
5580  str = insn_data_to_s_detail(iobj);
5581  printf("%04d %-65s(%4d)\n", pos, StringValueCStr(str), iobj->line_no);
5582  pos += insn_data_length(iobj);
5583  break;
5584  }
5585  case ISEQ_ELEMENT_LABEL:
5586  {
5587  lobj = (LABEL *)link;
5588  printf("<L%03d>\n", lobj->label_no);
5589  break;
5590  }
5591  case ISEQ_ELEMENT_NONE:
5592  {
5593  printf("[none]\n");
5594  break;
5595  }
5596  case ISEQ_ELEMENT_ADJUST:
5597  {
5598  ADJUST *adjust = (ADJUST *)link;
5599  printf("adjust: [label: %d]\n", adjust->label ? adjust->label->label_no : -1);
5600  break;
5601  }
5602  default:
5603  /* ignore */
5604  rb_raise(rb_eSyntaxError, "dump_disasm_list error: %ld\n", FIX2LONG(link->type));
5605  }
5606  link = link->next;
5607  }
5608  printf("---------------------\n");
5609 }
5610 
5611 const char *
5613 {
5614  return insn_name_info[i];
5615 }
5616 
5617 VALUE
5619 {
5620  VALUE ary = rb_ary_new();
5621  int i;
5622  for (i = 0; i < numberof(insn_name_info); i++) {
5623  rb_ary_push(ary, rb_fstring(rb_str_new2(insn_name_info[i])));
5624  }
5625  return rb_obj_freeze(ary);
5626 }
5627 
5628 static LABEL *
5629 register_label(rb_iseq_t *iseq, struct st_table *labels_table, VALUE obj)
5630 {
5631  LABEL *label = 0;
5632  st_data_t tmp;
5633  obj = rb_convert_type(obj, T_SYMBOL, "Symbol", "to_sym");
5634 
5635  if (st_lookup(labels_table, obj, &tmp) == 0) {
5636  label = NEW_LABEL(0);
5637  st_insert(labels_table, obj, (st_data_t)label);
5638  }
5639  else {
5640  label = (LABEL *)tmp;
5641  }
5642  return label;
5643 }
5644 
5645 static VALUE
5647 {
5648 #undef rb_intern
5649 #define rb_intern(str) rb_intern_const(str)
5651  static VALUE symRescue, symEnsure, symRetry;
5652  static VALUE symBreak, symRedo, symNext;
5653 
5654  if (symRescue == 0) {
5655  symRescue = ID2SYM(rb_intern("rescue"));
5656  symEnsure = ID2SYM(rb_intern("ensure"));
5657  symRetry = ID2SYM(rb_intern("retry"));
5658  symBreak = ID2SYM(rb_intern("break"));
5659  symRedo = ID2SYM(rb_intern("redo"));
5660  symNext = ID2SYM(rb_intern("next"));
5661  }
5662 
5663  if (sym == symRescue) return CATCH_TYPE_RESCUE;
5664  if (sym == symEnsure) return CATCH_TYPE_ENSURE;
5665  if (sym == symRetry) return CATCH_TYPE_RETRY;
5666  if (sym == symBreak) return CATCH_TYPE_BREAK;
5667  if (sym == symRedo) return CATCH_TYPE_REDO;
5668  if (sym == symNext) return CATCH_TYPE_NEXT;
5669  sym_inspect = rb_inspect(sym);
5670  rb_raise(rb_eSyntaxError, "invalid exception symbol: %s",
5671  StringValuePtr(sym_inspect));
5672  return 0;
5673 }
5674 
5675 static int
5677  VALUE exception)
5678 {
5679  int i;
5680 
5681  for (i=0; i<RARRAY_LEN(exception); i++) {
5682  VALUE v, type, eiseqval;
5683  const VALUE *ptr;
5684  LABEL *lstart, *lend, *lcont;
5685  int sp;
5686 
5687  RB_GC_GUARD(v) = rb_convert_type(RARRAY_AREF(exception, i), T_ARRAY,
5688  "Array", "to_ary");
5689  if (RARRAY_LEN(v) != 6) {
5690  rb_raise(rb_eSyntaxError, "wrong exception entry");
5691  }
5692  ptr = RARRAY_CONST_PTR(v);
5693  type = get_exception_sym2type(ptr[0]);
5694  if (ptr[1] == Qnil) {
5695  eiseqval = 0;
5696  }
5697  else {
5698  eiseqval = rb_iseq_load(ptr[1], iseq->self, Qnil);
5699  }
5700 
5701  lstart = register_label(iseq, labels_table, ptr[2]);
5702  lend = register_label(iseq, labels_table, ptr[3]);
5703  lcont = register_label(iseq, labels_table, ptr[4]);
5704  sp = NUM2INT(ptr[5]);
5705 
5706  (void)sp;
5707 
5708  ADD_CATCH_ENTRY(type, lstart, lend, eiseqval, lcont);
5709  }
5710  return COMPILE_OK;
5711 }
5712 
5713 static struct st_table *
5715 {
5716  struct st_table *table;
5717  int i;
5718  table = st_init_numtable();
5719 
5720  for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
5721  st_insert(table, ID2SYM(rb_intern(insn_name(i))), i);
5722  }
5723 
5724  return table;
5725 }
5726 
5727 static VALUE
5729 {
5730  VALUE iseqval;
5731  if (RB_TYPE_P(op, T_ARRAY)) {
5732  iseqval = rb_iseq_load(op, iseq->self, Qnil);
5733  }
5734  else if (CLASS_OF(op) == rb_cISeq) {
5735  iseqval = op;
5736  }
5737  else {
5738  rb_raise(rb_eSyntaxError, "ISEQ is required");
5739  }
5740  iseq_add_mark_object(iseq, iseqval);
5741  return iseqval;
5742 }
5743 
5744 static int
5746  VALUE body, struct st_table *labels_table)
5747 {
5748  /* TODO: body should be frozen */
5749  const VALUE *ptr = RARRAY_CONST_PTR(body);
5750  long i, len = RARRAY_LEN(body);
5751  int j;
5752  int line_no = 0;
5753 
5754  /*
5755  * index -> LABEL *label
5756  */
5757  static struct st_table *insn_table;
5758 
5759  if (insn_table == 0) {
5760  insn_table = insn_make_insn_table();
5761  }
5762 
5763  for (i=0; i<len; i++) {
5764  VALUE obj = ptr[i];
5765 
5766  if (SYMBOL_P(obj)) {
5767  LABEL *label = register_label(iseq, labels_table, obj);
5768  ADD_LABEL(anchor, label);
5769  }
5770  else if (FIXNUM_P(obj)) {
5771  line_no = NUM2INT(obj);
5772  }
5773  else if (RB_TYPE_P(obj, T_ARRAY)) {
5774  VALUE *argv = 0;
5775  int argc = RARRAY_LENINT(obj) - 1;
5776  st_data_t insn_id;
5777  VALUE insn;
5778 
5779  insn = (argc < 0) ? Qnil : RARRAY_AREF(obj, 0);
5780  if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) {
5781  /* TODO: exception */
5782  RB_GC_GUARD(insn) = rb_inspect(insn);
5783  rb_compile_error(RSTRING_PTR(iseq->location.path), line_no,
5784  "unknown instruction: %s", RSTRING_PTR(insn));
5785  }
5786 
5787  if (argc != insn_len((VALUE)insn_id)-1) {
5788  rb_compile_error(RSTRING_PTR(iseq->location.path), line_no,
5789  "operand size mismatch");
5790  }
5791 
5792  if (argc > 0) {
5793  argv = compile_data_alloc(iseq, sizeof(VALUE) * argc);
5794  for (j=0; j<argc; j++) {
5795  VALUE op = rb_ary_entry(obj, j+1);
5796  switch (insn_op_type((VALUE)insn_id, j)) {
5797  case TS_OFFSET: {
5798  LABEL *label = register_label(iseq, labels_table, op);
5799  argv[j] = (VALUE)label;
5800  break;
5801  }
5802  case TS_LINDEX:
5803  case TS_NUM:
5804  (void)NUM2INT(op);
5805  argv[j] = op;
5806  break;
5807  case TS_VALUE:
5808  argv[j] = op;
5809  iseq_add_mark_object(iseq, op);
5810  break;
5811  case TS_ISEQ:
5812  {
5813  if (op != Qnil) {
5814  argv[j] = iseq_build_load_iseq(iseq, op);
5815  }
5816  else {
5817  argv[j] = 0;
5818  }
5819  }
5820  break;
5821  case TS_GENTRY:
5822  op = rb_convert_type(op, T_SYMBOL, "Symbol", "to_sym");
5823  argv[j] = (VALUE)rb_global_entry(SYM2ID(op));
5824  break;
5825  case TS_IC:
5826  argv[j] = op;
5827  if (NUM2INT(op) >= iseq->is_size) {
5828  iseq->is_size = NUM2INT(op) + 1;
5829  }
5830  break;
5831  case TS_CALLINFO:
5832  {
5833  ID mid = 0;
5834  int orig_argc = 0;
5835  VALUE block = 0;
5836  unsigned long flag = 0;
5837 
5838  if (!NIL_P(op)) {
5839  VALUE vmid = rb_hash_aref(op, ID2SYM(rb_intern("mid")));
5840  VALUE vflag = rb_hash_aref(op, ID2SYM(rb_intern("flag")));
5841  VALUE vorig_argc = rb_hash_aref(op, ID2SYM(rb_intern("orig_argc")));
5842  VALUE vblock = rb_hash_aref(op, ID2SYM(rb_intern("blockptr")));
5843 
5844  if (!NIL_P(vmid)) mid = SYM2ID(vmid);
5845  if (!NIL_P(vflag)) flag = NUM2ULONG(vflag);
5846  if (!NIL_P(vorig_argc)) orig_argc = FIX2INT(vorig_argc);
5847  if (!NIL_P(vblock)) block = iseq_build_load_iseq(iseq, vblock);
5848  }
5849  argv[j] = (VALUE)new_callinfo(iseq, mid, orig_argc, block, flag);
5850  }
5851  break;
5852  case TS_ID:
5853  argv[j] = rb_convert_type(op, T_SYMBOL,
5854  "Symbol", "to_sym");
5855  break;
5856  case TS_CDHASH:
5857  {
5858  int i;
5859  op = rb_convert_type(op, T_ARRAY, "Array", "to_ary");
5860  op = rb_ary_dup(op);
5861  for (i=0; i<RARRAY_LEN(op); i+=2) {
5862  VALUE sym = rb_ary_entry(op, i+1);
5863  LABEL *label =
5864  register_label(iseq, labels_table, sym);
5865  rb_ary_store(op, i+1, (VALUE)label | 1);
5866  }
5867  argv[j] = op;
5869  }
5870  break;
5871  default:
5872  rb_raise(rb_eSyntaxError, "unknown operand: %c", insn_op_type((VALUE)insn_id, j));
5873  }
5874  }
5875  }
5876  ADD_ELEM(anchor,
5877  (LINK_ELEMENT*)new_insn_core(iseq, line_no,
5878  (enum ruby_vminsn_type)insn_id, argc, argv));
5879  }
5880  else {
5881  rb_raise(rb_eTypeError, "unexpected object for instruction");
5882  }
5883  }
5884  validate_labels(iseq, labels_table);
5885  st_free_table(labels_table);
5886  iseq_setup(iseq, anchor);
5887  return COMPILE_OK;
5888 }
5889 
5890 #define CHECK_ARRAY(v) rb_convert_type((v), T_ARRAY, "Array", "to_ary")
5891 #define CHECK_STRING(v) rb_convert_type((v), T_STRING, "String", "to_str")
5892 #define CHECK_SYMBOL(v) rb_convert_type((v), T_SYMBOL, "Symbol", "to_sym")
5893 static inline VALUE CHECK_INTEGER(VALUE v) {(void)NUM2LONG(v); return v;}
5894 
5895 VALUE
5897  VALUE exception, VALUE body)
5898 {
5899  int i;
5900  ID *tbl;
5901  struct st_table *labels_table = st_init_numtable();
5902  DECL_ANCHOR(anchor);
5903  INIT_ANCHOR(anchor);
5904 
5905  iseq->local_table_size = RARRAY_LENINT(locals);
5906  iseq->local_table = tbl = (ID *)ALLOC_N(ID, iseq->local_table_size);
5907  iseq->local_size = iseq->local_table_size + 1;
5908 
5909  for (i=0; i<RARRAY_LEN(locals); i++) {
5910  VALUE lv = RARRAY_AREF(locals, i);
5911  tbl[i] = FIXNUM_P(lv) ? (ID)FIX2LONG(lv) : SYM2ID(CHECK_SYMBOL(lv));
5912  }
5913 
5914  /* args */
5915  if (FIXNUM_P(args)) {
5916  iseq->arg_size = iseq->argc = FIX2INT(args);
5917  iseq->arg_simple = 1;
5918  }
5919  else {
5920  int i = 0;
5921  VALUE argc = CHECK_INTEGER(rb_ary_entry(args, i++));
5922  VALUE arg_opt_labels = CHECK_ARRAY(rb_ary_entry(args, i++));
5923  VALUE arg_post_len = CHECK_INTEGER(rb_ary_entry(args, i++));
5924  VALUE arg_post_start = CHECK_INTEGER(rb_ary_entry(args, i++));
5925  VALUE arg_rest = CHECK_INTEGER(rb_ary_entry(args, i++));
5926  VALUE arg_block = CHECK_INTEGER(rb_ary_entry(args, i++));
5927  VALUE arg_simple = CHECK_INTEGER(rb_ary_entry(args, i++));
5928 
5929  iseq->argc = FIX2INT(argc);
5930  iseq->arg_rest = FIX2INT(arg_rest);
5931  iseq->arg_post_len = FIX2INT(arg_post_len);
5932  iseq->arg_post_start = FIX2INT(arg_post_start);
5933  iseq->arg_block = FIX2INT(arg_block);
5934  iseq->arg_opts = RARRAY_LENINT(arg_opt_labels);
5935  iseq->arg_opt_table = (VALUE *)ALLOC_N(VALUE, iseq->arg_opts);
5936 
5937  if (iseq->arg_block != -1) {
5938  iseq->arg_size = iseq->arg_block + 1;
5939  }
5940  else if (iseq->arg_post_len) {
5941  iseq->arg_size = iseq->arg_post_start + iseq->arg_post_len;
5942  }
5943  else if (iseq->arg_rest != -1) {
5944  iseq->arg_size = iseq->arg_rest + 1;
5945  }
5946  else {
5947  iseq->arg_size = iseq->argc + (iseq->arg_opts ? iseq->arg_opts - 1 : 0);
5948  }
5949 
5950  for (i=0; i<RARRAY_LEN(arg_opt_labels); i++) {
5951  iseq->arg_opt_table[i] =
5952  (VALUE)register_label(iseq, labels_table,
5953  rb_ary_entry(arg_opt_labels, i));
5954  }
5955 
5956  iseq->arg_simple = NUM2INT(arg_simple);
5957  }
5958 
5959  /* exception */
5960  iseq_build_from_ary_exception(iseq, labels_table, exception);
5961 
5962  /* body */
5963  iseq_build_from_ary_body(iseq, anchor, body, labels_table);
5964  return iseq->self;
5965 }
5966 
5967 /* for parser */
5968 
5969 int
5971 {
5972  rb_thread_t *th = GET_THREAD();
5973  rb_iseq_t *iseq;
5974  if (th->base_block && (iseq = th->base_block->iseq)) {
5975  while (iseq->type == ISEQ_TYPE_BLOCK ||
5976  iseq->type == ISEQ_TYPE_RESCUE ||
5977  iseq->type == ISEQ_TYPE_ENSURE ||
5978  iseq->type == ISEQ_TYPE_EVAL ||
5979  iseq->type == ISEQ_TYPE_MAIN
5980  ) {
5981  int i;
5982 
5983  for (i = 0; i < iseq->local_table_size; i++) {
5984  if (iseq->local_table[i] == id) {
5985  return 1;
5986  }
5987  }
5988  iseq = iseq->parent_iseq;
5989  }
5990  }
5991  return 0;
5992 }
5993 
5994 int
5996 {
5997  rb_thread_t *th = GET_THREAD();
5998  rb_iseq_t *iseq;
5999 
6000  if (th->base_block && th->base_block->iseq) {
6001  int i;
6002  iseq = th->base_block->iseq->local_iseq;
6003 
6004  for (i=0; i<iseq->local_table_size; i++) {
6005  if (iseq->local_table[i] == id) {
6006  return 1;
6007  }
6008  }
6009  }
6010  return 0;
6011 }
6012 
6013 int
6015 {
6016  return GET_THREAD()->parse_in_eval > 0;
6017 }
6018 
6019 int
6021 {
6022  return GET_THREAD()->parse_in_eval < 0;
6023 }
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:5172
#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:1179
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:17201
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:5463
#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:10145
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:5618
#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:1198
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:1070
#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:900
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:5676
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:538
VALUE rb_iseq_defined_string(enum defined_type type)
Definition: iseq.c:2040
* div
Definition: bigdecimal.c:1215
#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:9618
struct iseq_label_data * start_label
Definition: iseq.h:87
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3392
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:1212
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:360
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:3187
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:2339
#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:273
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:5745
#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:8439
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:17312
#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:5728
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:6790
#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:5612
static VALUE CHECK_INTEGER(VALUE v)
Definition: compile.c:5893
#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:9721
#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:499
#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:2158
#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:5890
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:794
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:6020
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:4601
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:602
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:5970
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:5896
VP_EXPORT void
Definition: bigdecimal.c:5207
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:5629
#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:6209
#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:5646
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:5469
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:5475
#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:646
#define INSN_OF(insn)
Definition: compile.c:271
Definition: ripper.y:88
static VALUE insn_data_to_s_detail(INSN *iobj)
Definition: compile.c:5494
#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:1604
st_index_t rb_str_hash(VALUE)
Definition: string.c:2421
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:1561
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:1899
#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:3553
#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:1339
#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:5714
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:307
#define COMPILE_ERROR(strs)
Definition: compile.c:275
const char * rb_id2name(ID id)
Definition: ripper.c:17271
#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:5892
#define COMPILE_(anchor, desc, node, poped)
Definition: compile.c:264
BDIGIT e
Definition: bigdecimal.c:5209
static VALUE make_name_for_block(rb_iseq_t *iseq)
Definition: compile.c:3063
int rb_str_hash_cmp(VALUE, VALUE)
Definition: string.c:2431
VALUE iseq
Definition: iseq.h:64
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:706
#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:6014
#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:102
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:5995
const VALUE label
Definition: vm_core.h:200
Definition: ripper.y:84
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:929
struct iseq_adjust_data ADJUST
int retry
Definition: tcltklib.c:10158
static int eq(VALUE x, VALUE y)
Definition: time.c:45
VALUE rb_iseq_disasm(VALUE self)
Definition: iseq.c:1379
#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:1583
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2637
#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:1232
#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:5566