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