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