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