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