Ruby  2.5.0dev(2017-10-22revision60238)
compile.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  compile.c - ruby node tree -> VM instruction sequence
4 
5  $Author$
6  created at: 04/01/01 03:42:15 JST
7 
8  Copyright (C) 2004-2007 Koichi Sasada
9 
10 **********************************************************************/
11 
12 #include "internal.h"
13 #include "ruby/re.h"
14 #include "encindex.h"
15 #include <math.h>
16 
17 #define USE_INSN_STACK_INCREASE 1
18 #include "vm_core.h"
19 #include "iseq.h"
20 #include "insns.inc"
21 #include "insns_info.inc"
22 #include "id_table.h"
23 #include "gc.h"
24 
25 #ifdef HAVE_DLADDR
26 # include <dlfcn.h>
27 #endif
28 
29 #undef RUBY_UNTYPED_DATA_WARNING
30 #define RUBY_UNTYPED_DATA_WARNING 0
31 
32 #define ISEQ_TYPE_ONCE_GUARD ISEQ_TYPE_DEFINED_GUARD
33 
34 #define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG))
35 #define FIXNUM_OR(n, i) ((n)|INT2FIX(i))
36 
37 typedef struct iseq_link_element {
38  enum {
43  } type;
46 } LINK_ELEMENT;
47 
48 typedef struct iseq_link_anchor {
51 } LINK_ANCHOR;
52 
53 typedef enum {
59 
60 typedef struct iseq_label_data {
62  int label_no;
63  int position;
64  int sc_state;
65  int sp;
66  int refcnt;
67  unsigned int set: 1;
68  unsigned int rescued: 2;
69  unsigned int unremovable: 1;
70 } LABEL;
71 
72 typedef struct iseq_insn_data {
74  enum ruby_vminsn_type insn_id;
75  unsigned int line_no;
77  int sc_state;
79 } INSN;
80 
81 typedef struct iseq_adjust_data {
84  int line_no;
85 } ADJUST;
86 
87 struct ensure_range {
90  struct ensure_range *next;
91 };
92 
97 };
98 
112 #ifndef CPDEBUG
113 #define CPDEBUG 0
114 #endif
115 
116 #if CPDEBUG >= 0
117 #define compile_debug CPDEBUG
118 #else
119 #define compile_debug ISEQ_COMPILE_DATA(iseq)->option->debug_level
120 #endif
121 
122 #if CPDEBUG
123 
124 #define compile_debug_print_indent(level) \
125  ruby_debug_print_indent((level), compile_debug, gl_node_level * 2)
126 
127 #define debugp(header, value) (void) \
128  (compile_debug_print_indent(1) && \
129  ruby_debug_print_value(1, compile_debug, (header), (value)))
130 
131 #define debugi(header, id) (void) \
132  (compile_debug_print_indent(1) && \
133  ruby_debug_print_id(1, compile_debug, (header), (id)))
134 
135 #define debugp_param(header, value) (void) \
136  (compile_debug_print_indent(1) && \
137  ruby_debug_print_value(1, compile_debug, (header), (value)))
138 
139 #define debugp_verbose(header, value) (void) \
140  (compile_debug_print_indent(2) && \
141  ruby_debug_print_value(2, compile_debug, (header), (value)))
142 
143 #define debugp_verbose_node(header, value) (void) \
144  (compile_debug_print_indent(10) && \
145  ruby_debug_print_value(10, compile_debug, (header), (value)))
146 
147 #define debug_node_start(node) ((void) \
148  (compile_debug_print_indent(1) && \
149  (ruby_debug_print_node(1, CPDEBUG, "", (NODE *)(node)), gl_node_level)), \
150  gl_node_level++)
151 
152 #define debug_node_end() gl_node_level --
153 
154 #else
155 
156 #define debugi(header, id) ((void)0)
157 #define debugp(header, value) ((void)0)
158 #define debugp_verbose(header, value) ((void)0)
159 #define debugp_verbose_node(header, value) ((void)0)
160 #define debugp_param(header, value) ((void)0)
161 #define debug_node_start(node) ((void)0)
162 #define debug_node_end() ((void)0)
163 #endif
164 
165 #if CPDEBUG > 1 || CPDEBUG < 0
166 #define printf ruby_debug_printf
167 #define debugs if (compile_debug_print_indent(1)) ruby_debug_printf
168 #define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs((msg), stderr)), (v))
169 #else
170 #define debugs if(0)printf
171 #define debug_compile(msg, v) (v)
172 #endif
173 
174 #define LVAR_ERRINFO (1)
175 
176 /* create new label */
177 #define NEW_LABEL(l) new_label_body(iseq, (l))
178 #define LABEL_FORMAT "<L%03d>"
179 
180 #define NEW_ISEQ(node, name, type, line_no) \
181  new_child_iseq(iseq, (node), rb_fstring(name), 0, (type), (line_no))
182 
183 #define NEW_CHILD_ISEQ(node, name, type, line_no) \
184  new_child_iseq(iseq, (node), rb_fstring(name), iseq, (type), (line_no))
185 
186 /* add instructions */
187 #define ADD_SEQ(seq1, seq2) \
188  APPEND_LIST((seq1), (seq2))
189 
190 /* add an instruction */
191 #define ADD_INSN(seq, line, insn) \
192  ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0))
193 
194 /* insert an instruction before prev */
195 #define INSERT_BEFORE_INSN(prev, line, insn) \
196  INSERT_ELEM_PREV(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0))
197 
198 /* add an instruction with some operands (1, 2, 3, 5) */
199 #define ADD_INSN1(seq, line, insn, op1) \
200  ADD_ELEM((seq), (LINK_ELEMENT *) \
201  new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1)))
202 
203 /* insert an instruction with some operands (1, 2, 3, 5) before prev */
204 #define INSERT_BEFORE_INSN1(prev, line, insn, op1) \
205  INSERT_ELEM_PREV(&(prev)->link, (LINK_ELEMENT *) \
206  new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1)))
207 
208 #define LABEL_REF(label) ((label)->refcnt++)
209 
210 /* add an instruction with label operand (alias of ADD_INSN1) */
211 #define ADD_INSNL(seq, line, insn, label) (ADD_INSN1(seq, line, insn, label), LABEL_REF(label))
212 
213 #define ADD_INSN2(seq, line, insn, op1, op2) \
214  ADD_ELEM((seq), (LINK_ELEMENT *) \
215  new_insn_body(iseq, (line), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2)))
216 
217 #define ADD_INSN3(seq, line, insn, op1, op2, op3) \
218  ADD_ELEM((seq), (LINK_ELEMENT *) \
219  new_insn_body(iseq, (line), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3)))
220 
221 /* Specific Insn factory */
222 #define ADD_SEND(seq, line, id, argc) \
223  ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)INT2FIX(0), NULL)
224 
225 #define ADD_SEND_WITH_FLAG(seq, line, id, argc, flag) \
226  ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)(flag), NULL)
227 
228 #define ADD_SEND_WITH_BLOCK(seq, line, id, argc, block) \
229  ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(0), NULL)
230 
231 #define ADD_CALL_RECEIVER(seq, line) \
232  ADD_INSN((seq), (line), putself)
233 
234 #define ADD_CALL(seq, line, id, argc) \
235  ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
236 
237 #define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \
238  ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL), NULL)
239 
240 #define ADD_SEND_R(seq, line, id, argc, block, flag, keywords) \
241  ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (line), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords)))
242 
243 #define ADD_TRACE_LINE_COVERAGE(seq, line) \
244  do { \
245  if (ISEQ_COVERAGE(iseq) && \
246  ISEQ_LINE_COVERAGE(iseq) && \
247  (line) > 0 && \
248  (line) != ISEQ_COMPILE_DATA(iseq)->last_coverable_line) { \
249  RARRAY_ASET(ISEQ_LINE_COVERAGE(iseq), (line) - 1, INT2FIX(0)); \
250  ISEQ_COMPILE_DATA(iseq)->last_coverable_line = (line); \
251  ADD_INSN2((seq), (line), trace2, INT2FIX(RUBY_EVENT_COVERAGE), INT2FIX(COVERAGE_INDEX_LINES)); \
252  } \
253  } while (0)
254 #define DECL_BRANCH_BASE(branches, line, type) \
255  do { \
256  if (ISEQ_COVERAGE(iseq) && \
257  ISEQ_BRANCH_COVERAGE(iseq) && \
258  (line) > 0) { \
259  VALUE structure = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 0); \
260  branches = rb_ary_tmp_new(0); \
261  rb_ary_push(structure, branches); \
262  rb_ary_push(branches, ID2SYM(rb_intern(type))); \
263  rb_ary_push(branches, INT2FIX(line)); \
264  } \
265  } while (0)
266 #define ADD_TRACE_BRANCH_COVERAGE(seq, line, type, branches) \
267  do { \
268  if (ISEQ_COVERAGE(iseq) && \
269  ISEQ_BRANCH_COVERAGE(iseq) && \
270  (line) > 0) { \
271  VALUE counters = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 1); \
272  long counter_idx = RARRAY_LEN(counters); \
273  rb_ary_push(counters, INT2FIX(0)); \
274  rb_ary_push(branches, ID2SYM(rb_intern(type))); \
275  rb_ary_push(branches, INT2FIX(line)); \
276  rb_ary_push(branches, INT2FIX(counter_idx)); \
277  ADD_INSN2((seq), (line), trace2, INT2FIX(RUBY_EVENT_COVERAGE), INT2FIX(counter_idx * 16 + COVERAGE_INDEX_BRANCHES)); \
278  } \
279  } while (0)
280 #define ADD_TRACE_METHOD_COVERAGE(seq, line, method_name) \
281  do { \
282  if (ISEQ_COVERAGE(iseq) && \
283  ISEQ_METHOD_COVERAGE(iseq) && \
284  (line) > 0) { \
285  VALUE methods = ISEQ_METHOD_COVERAGE(iseq); \
286  long counter_idx = RARRAY_LEN(methods) / 3; \
287  rb_ary_push(methods, ID2SYM(method_name)); \
288  rb_ary_push(methods, INT2FIX(line)); \
289  rb_ary_push(methods, INT2FIX(0)); \
290  ADD_INSN2((seq), (line), trace2, INT2FIX(RUBY_EVENT_COVERAGE), INT2FIX(counter_idx * 16 + COVERAGE_INDEX_METHODS)); \
291  } \
292  } while (0)
293 
294 #define ADD_TRACE(seq, line, event) \
295  do { \
296  if (ISEQ_COMPILE_DATA(iseq)->option->trace_instruction) { \
297  ADD_INSN1((seq), (line), trace, INT2FIX(event)); \
298  } \
299  } while (0)
300 
301 #define ADD_GETLOCAL(seq, line, idx, level) \
302  do { \
303  ADD_INSN2((seq), (line), getlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); \
304  } while (0)
305 
306 #define ADD_SETLOCAL(seq, line, idx, level) \
307  do { \
308  ADD_INSN2((seq), (line), setlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); \
309  } while (0)
310 
311 /* add label */
312 #define ADD_LABEL(seq, label) \
313  ADD_ELEM((seq), (LINK_ELEMENT *) (label))
314 
315 #define APPEND_LABEL(seq, before, label) \
316  APPEND_ELEM((seq), (before), (LINK_ELEMENT *) (label))
317 
318 #define ADD_ADJUST(seq, line, label) \
319  ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), (line)))
320 
321 #define ADD_ADJUST_RESTORE(seq, label) \
322  ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1))
323 
324 #define LABEL_UNREMOVABLE(label) \
325  ((label) ? (LABEL_REF(label), (label)->unremovable=1) : 0)
326 #define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) do { \
327  VALUE _e = rb_ary_new3(5, (type), \
328  (VALUE)(ls) | 1, (VALUE)(le) | 1, \
329  (VALUE)(iseqv), (VALUE)(lc) | 1); \
330  LABEL_UNREMOVABLE(ls); \
331  LABEL_UNREMOVABLE(le); \
332  LABEL_UNREMOVABLE(lc); \
333  rb_ary_push(ISEQ_COMPILE_DATA(iseq)->catch_table_ary, freeze_hide_obj(_e)); \
334 } while (0)
335 
336 /* compile node */
337 #define COMPILE(anchor, desc, node) \
338  (debug_compile("== " desc "\n", \
339  iseq_compile_each(iseq, (anchor), (node), 0)))
340 
341 /* compile node, this node's value will be popped */
342 #define COMPILE_POPPED(anchor, desc, node) \
343  (debug_compile("== " desc "\n", \
344  iseq_compile_each(iseq, (anchor), (node), 1)))
345 
346 /* compile node, which is popped when 'popped' is true */
347 #define COMPILE_(anchor, desc, node, popped) \
348  (debug_compile("== " desc "\n", \
349  iseq_compile_each(iseq, (anchor), (node), (popped))))
350 
351 #define COMPILE_RECV(anchor, desc, node) \
352  (private_recv_p(node) ? \
353  (ADD_INSN(anchor, nd_line(node), putself), VM_CALL_FCALL) : \
354  (COMPILE(anchor, desc, node->nd_recv), 0))
355 
356 #define OPERAND_AT(insn, idx) \
357  (((INSN*)(insn))->operands[(idx)])
358 
359 #define INSN_OF(insn) \
360  (((INSN*)(insn))->insn_id)
361 
362 #define IS_INSN(link) ((link)->type == ISEQ_ELEMENT_INSN)
363 #define IS_LABEL(link) ((link)->type == ISEQ_ELEMENT_LABEL)
364 #define IS_ADJUST(link) ((link)->type == ISEQ_ELEMENT_ADJUST)
365 #define IS_INSN_ID(iobj, insn) (INSN_OF(iobj) == BIN(insn))
366 #define IS_NEXT_INSN_ID(link, insn) \
367  ((link)->next && IS_INSN((link)->next) && IS_INSN_ID((link)->next, insn))
368 
369 /* error */
370 #if CPDEBUG > 0
371 NORETURN(static void append_compile_error(rb_iseq_t *iseq, int line, const char *fmt, ...));
372 #endif
373 
374 static void
375 append_compile_error(rb_iseq_t *iseq, int line, const char *fmt, ...)
376 {
377  VALUE err_info = ISEQ_COMPILE_DATA(iseq)->err_info;
378  VALUE file = rb_iseq_path(iseq);
379  VALUE err = err_info == Qtrue ? Qfalse : err_info;
380  va_list args;
381 
382  va_start(args, fmt);
383  err = rb_syntax_error_append(err, file, line, -1, NULL, fmt, args);
384  va_end(args);
385  if (NIL_P(err_info)) {
386  RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err);
387  rb_set_errinfo(err);
388  }
389  else if (!err_info) {
390  RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, Qtrue);
391  }
392  if (compile_debug) rb_exc_fatal(err);
393 }
394 
395 #if 0
396 static void
397 compile_bug(rb_iseq_t *iseq, int line, const char *fmt, ...)
398 {
399  va_list args;
400  va_start(args, fmt);
401  rb_report_bug_valist(rb_iseq_path(iseq), line, fmt, args);
402  va_end(args);
403  abort();
404 }
405 #endif
406 
407 #define COMPILE_ERROR append_compile_error
408 
409 #define ERROR_ARGS_AT(n) iseq, nd_line(n),
410 #define ERROR_ARGS ERROR_ARGS_AT(node)
411 
412 #define EXPECT_NODE(prefix, node, ndtype, errval) \
413 do { \
414  NODE *error_node = (node); \
415  enum node_type error_type = nd_type(error_node); \
416  if (error_type != (ndtype)) { \
417  COMPILE_ERROR(ERROR_ARGS_AT(error_node) \
418  prefix ": " #ndtype " is expected, but %s", \
419  ruby_node_name(error_type)); \
420  return errval; \
421  } \
422 } while (0)
423 
424 #define EXPECT_NODE_NONULL(prefix, parent, ndtype, errval) \
425 do { \
426  COMPILE_ERROR(ERROR_ARGS_AT(parent) \
427  prefix ": must be " #ndtype ", but 0"); \
428  return errval; \
429 } while (0)
430 
431 #define UNKNOWN_NODE(prefix, node, errval) \
432 do { \
433  NODE *error_node = (node); \
434  COMPILE_ERROR(ERROR_ARGS_AT(error_node) prefix ": unknown node (%s)", \
435  ruby_node_name(nd_type(error_node))); \
436  return errval; \
437 } while (0)
438 
439 #define COMPILE_OK 1
440 #define COMPILE_NG 0
441 
442 #define CHECK(sub) if (!(sub)) {BEFORE_RETURN;return COMPILE_NG;}
443 #define BEFORE_RETURN
444 
445 /* leave name uninitialized so that compiler warn if INIT_ANCHOR is
446  * missing */
447 #define DECL_ANCHOR(name) \
448  LINK_ANCHOR name[1] = {{{0,},}}
449 #define INIT_ANCHOR(name) \
450  (name->last = &name->anchor)
451 
452 static inline VALUE
453 freeze_hide_obj(VALUE obj)
454 {
455  OBJ_FREEZE(obj);
456  RBASIC_CLEAR_CLASS(obj);
457  return obj;
458 }
459 
460 #include "optinsn.inc"
461 #if OPT_INSTRUCTIONS_UNIFICATION
462 #include "optunifs.inc"
463 #endif
464 
465 /* for debug */
466 #if CPDEBUG < 0
467 #define ISEQ_ARG iseq,
468 #define ISEQ_ARG_DECLARE rb_iseq_t *iseq,
469 #else
470 #define ISEQ_ARG
471 #define ISEQ_ARG_DECLARE
472 #endif
473 
474 #if CPDEBUG
475 #define gl_node_level ISEQ_COMPILE_DATA(iseq)->node_level
476 #endif
477 
478 static void dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr, const LABEL *dest);
479 static void dump_disasm_list(const LINK_ELEMENT *elem);
480 
481 static int insn_data_length(INSN *iobj);
482 static int calc_sp_depth(int depth, INSN *iobj);
483 
484 static INSN *new_insn_body(rb_iseq_t *iseq, int line_no, enum ruby_vminsn_type insn_id, int argc, ...);
485 static LABEL *new_label_body(rb_iseq_t *iseq, long line);
486 static ADJUST *new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line);
487 
488 static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, NODE *n, int);
489 static int iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor);
490 static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor);
491 static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *const anchor);
492 
493 static int iseq_set_local_table(rb_iseq_t *iseq, const ID *tbl);
494 static int iseq_set_exception_local_table(rb_iseq_t *iseq);
495 static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, NODE *node);
496 
497 static int iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *const anchor);
498 static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor);
499 static int iseq_set_exception_table(rb_iseq_t *iseq);
500 static int iseq_set_optargs_table(rb_iseq_t *iseq);
501 
502 static int compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, VALUE needstr);
503 
504 /*
505  * To make Array to LinkedList, use link_anchor
506  */
507 
508 static void
509 verify_list(ISEQ_ARG_DECLARE const char *info, LINK_ANCHOR *const anchor)
510 {
511 #if CPDEBUG
512  int flag = 0;
513  LINK_ELEMENT *list, *plist;
514 
515  if (!compile_debug) return;
516 
517  list = anchor->anchor.next;
518  plist = &anchor->anchor;
519  while (list) {
520  if (plist != list->prev) {
521  flag += 1;
522  }
523  plist = list;
524  list = list->next;
525  }
526 
527  if (anchor->last != plist && anchor->last != 0) {
528  flag |= 0x70000;
529  }
530 
531  if (flag != 0) {
532  rb_bug("list verify error: %08x (%s)", flag, info);
533  }
534 #endif
535 }
536 #if CPDEBUG < 0
537 #define verify_list(info, anchor) verify_list(iseq, (info), (anchor))
538 #endif
539 
540 /*
541  * elem1, elem2 => elem1, elem2, elem
542  */
543 static void
544 ADD_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor, LINK_ELEMENT *elem)
545 {
546  elem->prev = anchor->last;
547  anchor->last->next = elem;
548  anchor->last = elem;
549  verify_list("add", anchor);
550 }
551 
552 /*
553  * elem1, before, elem2 => elem1, before, elem, elem2
554  */
555 static void
556 APPEND_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor, LINK_ELEMENT *before, LINK_ELEMENT *elem)
557 {
558  elem->prev = before;
559  elem->next = before->next;
560  elem->next->prev = elem;
561  before->next = elem;
562  if (before == anchor->last) anchor->last = elem;
563  verify_list("add", anchor);
564 }
565 #if CPDEBUG < 0
566 #define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, (anchor), (elem))
567 #define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem))
568 #endif
569 
570 static int
571 iseq_add_mark_object(const rb_iseq_t *iseq, VALUE v)
572 {
573  if (!SPECIAL_CONST_P(v)) {
574  rb_iseq_add_mark_object(iseq, v);
575  }
576  return COMPILE_OK;
577 }
578 
579 static int
580 iseq_add_mark_object_compile_time(const rb_iseq_t *iseq, VALUE v)
581 {
582  if (!SPECIAL_CONST_P(v)) {
583  rb_ary_push(ISEQ_COMPILE_DATA(iseq)->mark_ary, v);
584  }
585  return COMPILE_OK;
586 }
587 
588 static int
589 validate_label(st_data_t name, st_data_t label, st_data_t arg)
590 {
591  rb_iseq_t *iseq = (rb_iseq_t *)arg;
592  LABEL *lobj = (LABEL *)label;
593  if (!lobj->link.next) {
594  do {
595  COMPILE_ERROR(iseq, lobj->position,
596  "%"PRIsVALUE": undefined label",
597  rb_sym2str((VALUE)name));
598  } while (0);
599  }
600  return ST_CONTINUE;
601 }
602 
603 static void
604 validate_labels(rb_iseq_t *iseq, st_table *labels_table)
605 {
606  st_foreach(labels_table, validate_label, (st_data_t)iseq);
607  st_free_table(labels_table);
608 }
609 
610 VALUE
612 {
613  DECL_ANCHOR(ret);
614  INIT_ANCHOR(ret);
615 
616  if (node == 0) {
617  COMPILE(ret, "nil", node);
618  iseq_set_local_table(iseq, 0);
619  }
620  else if (nd_type(node) == NODE_SCOPE) {
621  /* iseq type of top, method, class, block */
622  iseq_set_local_table(iseq, node->nd_tbl);
623  iseq_set_arguments(iseq, ret, node->nd_args);
624 
625  switch (iseq->body->type) {
626  case ISEQ_TYPE_BLOCK:
627  {
628  LABEL *start = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(0);
629  LABEL *end = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(0);
630 
631  start->rescued = LABEL_RESCUE_BEG;
632  end->rescued = LABEL_RESCUE_END;
633 
635  ADD_LABEL(ret, start);
636  CHECK(COMPILE(ret, "block body", node->nd_body));
637  ADD_LABEL(ret, end);
639 
640  /* wide range catch handler must put at last */
641  ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, NULL, start);
642  ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, NULL, end);
643  break;
644  }
645  case ISEQ_TYPE_CLASS:
646  {
648  CHECK(COMPILE(ret, "scoped node", node->nd_body));
649  ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END);
650  break;
651  }
652  case ISEQ_TYPE_METHOD:
653  {
656  CHECK(COMPILE(ret, "scoped node", node->nd_body));
657  ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN);
658  break;
659  }
660  default: {
661  CHECK(COMPILE(ret, "scoped node", node->nd_body));
662  break;
663  }
664  }
665  }
666  else if (imemo_type_p((VALUE)node, imemo_ifunc)) {
667  const struct vm_ifunc *ifunc = (struct vm_ifunc *)node;
668  /* user callback */
669  (*ifunc->func)(iseq, ret, ifunc->data);
670  }
671  else {
672  switch (iseq->body->type) {
673  case ISEQ_TYPE_METHOD:
674  case ISEQ_TYPE_CLASS:
675  case ISEQ_TYPE_BLOCK:
676  case ISEQ_TYPE_EVAL:
677  case ISEQ_TYPE_MAIN:
678  case ISEQ_TYPE_TOP:
679  COMPILE_ERROR(ERROR_ARGS "compile/should not be reached: %s:%d",
680  __FILE__, __LINE__);
681  return COMPILE_NG;
682  case ISEQ_TYPE_RESCUE:
683  iseq_set_exception_local_table(iseq);
684  CHECK(COMPILE(ret, "rescue", node));
685  break;
686  case ISEQ_TYPE_ENSURE:
687  iseq_set_exception_local_table(iseq);
688  CHECK(COMPILE_POPPED(ret, "ensure", node));
689  break;
690  case ISEQ_TYPE_DEFINED_GUARD:
691  iseq_set_exception_local_table(iseq);
692  CHECK(COMPILE(ret, "defined guard", node));
693  break;
694  default:
695  COMPILE_ERROR(ERROR_ARGS "unknown scope");
696  return COMPILE_NG;
697  }
698  }
699 
700  if (iseq->body->type == ISEQ_TYPE_RESCUE || iseq->body->type == ISEQ_TYPE_ENSURE) {
701  ADD_GETLOCAL(ret, 0, LVAR_ERRINFO, 0);
702  ADD_INSN1(ret, 0, throw, INT2FIX(0) /* continue throw */ );
703  }
704  else {
705  ADD_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, leave);
706  }
707 
708 #if SUPPORT_JOKE
709  if (ISEQ_COMPILE_DATA(iseq)->labels_table) {
710  st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
711  ISEQ_COMPILE_DATA(iseq)->labels_table = 0;
712  validate_labels(iseq, labels_table);
713  }
714 #endif
715  return iseq_setup(iseq, ret);
716 }
717 
718 int
720 {
721 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
722  const void * const *table = rb_vm_get_insns_address_table();
723  unsigned int i;
724  VALUE *encoded = (VALUE *)iseq->body->iseq_encoded;
725 
726  for (i = 0; i < iseq->body->iseq_size; /* */ ) {
727  int insn = (int)iseq->body->iseq_encoded[i];
728  int len = insn_len(insn);
729  encoded[i] = (VALUE)table[insn];
730  i += len;
731  }
732 #endif
733  return COMPILE_OK;
734 }
735 
736 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
737 static int
738 rb_vm_insn_addr2insn(const void *addr) /* cold path */
739 {
740  int insn;
741  const void * const *table = rb_vm_get_insns_address_table();
742 
743  for (insn = 0; insn < VM_INSTRUCTION_SIZE; insn++) {
744  if (table[insn] == addr) {
745  return insn;
746  }
747  }
748  rb_bug("rb_vm_insn_addr2insn: invalid insn address: %p", addr);
749 }
750 #endif
751 
752 VALUE *
753 rb_iseq_original_iseq(const rb_iseq_t *iseq) /* cold path */
754 {
755  VALUE *original_code;
756 
757  if (ISEQ_ORIGINAL_ISEQ(iseq)) return ISEQ_ORIGINAL_ISEQ(iseq);
758  original_code = ISEQ_ORIGINAL_ISEQ_ALLOC(iseq, iseq->body->iseq_size);
759  MEMCPY(original_code, iseq->body->iseq_encoded, VALUE, iseq->body->iseq_size);
760 
761 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
762  {
763  unsigned int i;
764 
765  for (i = 0; i < iseq->body->iseq_size; /* */ ) {
766  const void *addr = (const void *)original_code[i];
767  const int insn = rb_vm_insn_addr2insn(addr);
768 
769  original_code[i] = insn;
770  i += insn_len(insn);
771  }
772  }
773 #endif
774  return original_code;
775 }
776 
777 /*********************************************/
778 /* definition of data structure for compiler */
779 /*********************************************/
780 
781 /*
782  * On 32-bit SPARC, GCC by default generates SPARC V7 code that may require
783  * 8-byte word alignment. On the other hand, Oracle Solaris Studio seems to
784  * generate SPARCV8PLUS code with unaligned memory access instructions.
785  * That is why the STRICT_ALIGNMENT is defined only with GCC.
786  */
787 #if defined(__sparc) && SIZEOF_VOIDP == 4 && defined(__GNUC__)
788  #define STRICT_ALIGNMENT
789 #endif
790 
791 #ifdef STRICT_ALIGNMENT
792  #if defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG > SIZEOF_VALUE
793  #define ALIGNMENT_SIZE SIZEOF_LONG_LONG
794  #else
795  #define ALIGNMENT_SIZE SIZEOF_VALUE
796  #endif
797  #define PADDING_SIZE_MAX ((size_t)((ALIGNMENT_SIZE) - 1))
798  #define ALIGNMENT_SIZE_MASK PADDING_SIZE_MAX
799  /* Note: ALIGNMENT_SIZE == (2 ** N) is expected. */
800 #else
801  #define PADDING_SIZE_MAX 0
802 #endif /* STRICT_ALIGNMENT */
803 
804 #ifdef STRICT_ALIGNMENT
805 /* calculate padding size for aligned memory access */
806 static size_t
807 calc_padding(void *ptr, size_t size)
808 {
809  size_t mis;
810  size_t padding = 0;
811 
812  mis = (size_t)ptr & ALIGNMENT_SIZE_MASK;
813  if (mis > 0) {
814  padding = ALIGNMENT_SIZE - mis;
815  }
816 /*
817  * On 32-bit sparc or equivalents, when a single VALUE is requested
818  * and padding == sizeof(VALUE), it is clear that no padding is needed.
819  */
820 #if ALIGNMENT_SIZE > SIZEOF_VALUE
821  if (size == sizeof(VALUE) && padding == sizeof(VALUE)) {
822  padding = 0;
823  }
824 #endif
825 
826  return padding;
827 }
828 #endif /* STRICT_ALIGNMENT */
829 
830 static void *
831 compile_data_alloc(rb_iseq_t *iseq, size_t size)
832 {
833  void *ptr = 0;
834  struct iseq_compile_data_storage *storage =
835  ISEQ_COMPILE_DATA(iseq)->storage_current;
836 #ifdef STRICT_ALIGNMENT
837  size_t padding = calc_padding((void *)&storage->buff[storage->pos], size);
838 #else
839  const size_t padding = 0; /* expected to be optimized by compiler */
840 #endif /* STRICT_ALIGNMENT */
841 
842  if (size >= INT_MAX - padding) rb_memerror();
843  if (storage->pos + size + padding > storage->size) {
844  unsigned int alloc_size = storage->size;
845 
846  while (alloc_size < size + PADDING_SIZE_MAX) {
847  if (alloc_size >= INT_MAX / 2) rb_memerror();
848  alloc_size *= 2;
849  }
850  storage->next = (void *)ALLOC_N(char, alloc_size +
852  storage = ISEQ_COMPILE_DATA(iseq)->storage_current = storage->next;
853  storage->next = 0;
854  storage->pos = 0;
855  storage->size = alloc_size;
856 #ifdef STRICT_ALIGNMENT
857  padding = calc_padding((void *)&storage->buff[storage->pos], size);
858 #endif /* STRICT_ALIGNMENT */
859  }
860 
861 #ifdef STRICT_ALIGNMENT
862  storage->pos += (int)padding;
863 #endif /* STRICT_ALIGNMENT */
864 
865  ptr = (void *)&storage->buff[storage->pos];
866  storage->pos += (int)size;
867  return ptr;
868 }
869 
870 static INSN *
871 compile_data_alloc_insn(rb_iseq_t *iseq)
872 {
873  return (INSN *)compile_data_alloc(iseq, sizeof(INSN));
874 }
875 
876 static LABEL *
877 compile_data_alloc_label(rb_iseq_t *iseq)
878 {
879  return (LABEL *)compile_data_alloc(iseq, sizeof(LABEL));
880 }
881 
882 static ADJUST *
883 compile_data_alloc_adjust(rb_iseq_t *iseq)
884 {
885  return (ADJUST *)compile_data_alloc(iseq, sizeof(ADJUST));
886 }
887 
888 /*
889  * elem1, elemX => elem1, elem2, elemX
890  */
891 static void
892 INSERT_ELEM_NEXT(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
893 {
894  elem2->next = elem1->next;
895  elem2->prev = elem1;
896  elem1->next = elem2;
897  if (elem2->next) {
898  elem2->next->prev = elem2;
899  }
900 }
901 
902 /*
903  * elem1, elemX => elemX, elem2, elem1
904  */
905 static void
906 INSERT_ELEM_PREV(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
907 {
908  elem2->prev = elem1->prev;
909  elem2->next = elem1;
910  elem1->prev = elem2;
911  if (elem2->prev) {
912  elem2->prev->next = elem2;
913  }
914 }
915 
916 /*
917  * elemX, elem1, elemY => elemX, elem2, elemY
918  */
919 static void
920 REPLACE_ELEM(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
921 {
922  elem2->prev = elem1->prev;
923  elem2->next = elem1->next;
924  if (elem1->prev) {
925  elem1->prev->next = elem2;
926  }
927  if (elem1->next) {
928  elem1->next->prev = elem2;
929  }
930 }
931 
932 static void
933 REMOVE_ELEM(LINK_ELEMENT *elem)
934 {
935  elem->prev->next = elem->next;
936  if (elem->next) {
937  elem->next->prev = elem->prev;
938  }
939 }
940 
941 static LINK_ELEMENT *
942 FIRST_ELEMENT(LINK_ANCHOR *const anchor)
943 {
944  return anchor->anchor.next;
945 }
946 
947 static LINK_ELEMENT *
948 LAST_ELEMENT(LINK_ANCHOR *const anchor)
949 {
950  return anchor->last;
951 }
952 
953 static LINK_ELEMENT *
954 POP_ELEMENT(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor)
955 {
956  LINK_ELEMENT *elem = anchor->last;
957  anchor->last = anchor->last->prev;
958  anchor->last->next = 0;
959  verify_list("pop", anchor);
960  return elem;
961 }
962 #if CPDEBUG < 0
963 #define POP_ELEMENT(anchor) POP_ELEMENT(iseq, (anchor))
964 #endif
965 
966 static int
967 LIST_SIZE_ZERO(LINK_ANCHOR *const anchor)
968 {
969  if (anchor->anchor.next == 0) {
970  return 1;
971  }
972  else {
973  return 0;
974  }
975 }
976 
977 /*
978  * anc1: e1, e2, e3
979  * anc2: e4, e5
980  *#=>
981  * anc1: e1, e2, e3, e4, e5
982  * anc2: e4, e5 (broken)
983  */
984 static void
985 APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *const anc1, LINK_ANCHOR *const anc2)
986 {
987  if (anc2->anchor.next) {
988  anc1->last->next = anc2->anchor.next;
989  anc2->anchor.next->prev = anc1->last;
990  anc1->last = anc2->last;
991  }
992  verify_list("append", anc1);
993 }
994 #if CPDEBUG < 0
995 #define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, (anc1), (anc2))
996 #endif
997 
998 /*
999  * anc1: e1, e2, e3
1000  * anc2: e4, e5
1001  *#=>
1002  * anc1: e4, e5, e1, e2, e3
1003  * anc2: e4, e5 (broken)
1004  */
1005 static void
1006 INSERT_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *const anc1, LINK_ANCHOR *const anc2)
1007 {
1008  if (anc2->anchor.next) {
1009  LINK_ELEMENT *first = anc1->anchor.next;
1010  anc1->anchor.next = anc2->anchor.next;
1011  anc1->anchor.next->prev = &anc1->anchor;
1012  anc2->last->next = first;
1013  if (first) {
1014  first->prev = anc2->last;
1015  }
1016  else {
1017  anc1->last = anc2->last;
1018  }
1019  }
1020 
1021  verify_list("append", anc1);
1022 }
1023 #if CPDEBUG < 0
1024 #define INSERT_LIST(anc1, anc2) INSERT_LIST(iseq, (anc1), (anc2))
1025 #endif
1026 
1027 #if CPDEBUG && 0
1028 static void
1030 {
1031  LINK_ELEMENT *list = FIRST_ELEMENT(anchor);
1032  printf("----\n");
1033  printf("anch: %p, frst: %p, last: %p\n", &anchor->anchor,
1034  anchor->anchor.next, anchor->last);
1035  while (list) {
1036  printf("curr: %p, next: %p, prev: %p, type: %d\n", list, list->next,
1037  list->prev, FIX2INT(list->type));
1038  list = list->next;
1039  }
1040  printf("----\n");
1041 
1042  dump_disasm_list(anchor->anchor.next);
1043  verify_list("debug list", anchor);
1044 }
1045 #if CPDEBUG < 0
1046 #define debug_list(anc) debug_list(iseq, (anc))
1047 #endif
1048 #else
1049 #define debug_list(anc) ((void)0)
1050 #endif
1051 
1052 static LABEL *
1053 new_label_body(rb_iseq_t *iseq, long line)
1054 {
1055  LABEL *labelobj = compile_data_alloc_label(iseq);
1056 
1057  labelobj->link.type = ISEQ_ELEMENT_LABEL;
1058  labelobj->link.next = 0;
1059 
1060  labelobj->label_no = ISEQ_COMPILE_DATA(iseq)->label_no++;
1061  labelobj->sc_state = 0;
1062  labelobj->sp = -1;
1063  labelobj->refcnt = 0;
1064  labelobj->set = 0;
1065  labelobj->rescued = LABEL_RESCUE_NONE;
1066  labelobj->unremovable = 0;
1067  return labelobj;
1068 }
1069 
1070 static ADJUST *
1071 new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line)
1072 {
1073  ADJUST *adjust = compile_data_alloc_adjust(iseq);
1074  adjust->link.type = ISEQ_ELEMENT_ADJUST;
1075  adjust->link.next = 0;
1076  adjust->label = label;
1077  adjust->line_no = line;
1078  LABEL_UNREMOVABLE(label);
1079  return adjust;
1080 }
1081 
1082 static INSN *
1083 new_insn_core(rb_iseq_t *iseq, int line_no,
1084  int insn_id, int argc, VALUE *argv)
1085 {
1086  INSN *iobj = compile_data_alloc_insn(iseq);
1087  /* printf("insn_id: %d, line: %d\n", insn_id, line_no); */
1088 
1089  iobj->link.type = ISEQ_ELEMENT_INSN;
1090  iobj->link.next = 0;
1091  iobj->insn_id = insn_id;
1092  iobj->line_no = line_no;
1093  iobj->operands = argv;
1094  iobj->operand_size = argc;
1095  iobj->sc_state = 0;
1096  return iobj;
1097 }
1098 
1099 static INSN *
1100 new_insn_body(rb_iseq_t *iseq, int line_no, enum ruby_vminsn_type insn_id, int argc, ...)
1101 {
1102  VALUE *operands = 0;
1103  va_list argv;
1104  if (argc > 0) {
1105  int i;
1106  va_init_list(argv, argc);
1107  operands = (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * argc);
1108  for (i = 0; i < argc; i++) {
1109  VALUE v = va_arg(argv, VALUE);
1110  operands[i] = v;
1111  }
1112  va_end(argv);
1113  }
1114  return new_insn_core(iseq, line_no, insn_id, argc, operands);
1115 }
1116 
1117 static struct rb_call_info *
1118 new_callinfo(rb_iseq_t *iseq, ID mid, int argc, unsigned int flag, struct rb_call_info_kw_arg *kw_arg, int has_blockiseq)
1119 {
1120  size_t size = kw_arg != NULL ? sizeof(struct rb_call_info_with_kwarg) : sizeof(struct rb_call_info);
1121  struct rb_call_info *ci = (struct rb_call_info *)compile_data_alloc(iseq, size);
1122  struct rb_call_info_with_kwarg *ci_kw = (struct rb_call_info_with_kwarg *)ci;
1123 
1124  ci->mid = mid;
1125  ci->flag = flag;
1126  ci->orig_argc = argc;
1127 
1128  if (kw_arg) {
1129  ci->flag |= VM_CALL_KWARG;
1130  ci_kw->kw_arg = kw_arg;
1131  ci->orig_argc += kw_arg->keyword_len;
1132  iseq->body->ci_kw_size++;
1133  }
1134  else {
1135  iseq->body->ci_size++;
1136  }
1137 
1138  if (!(ci->flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KW_SPLAT)) &&
1139  kw_arg == NULL && !has_blockiseq) {
1140  ci->flag |= VM_CALL_ARGS_SIMPLE;
1141  }
1142  return ci;
1143 }
1144 
1145 static INSN *
1146 new_insn_send(rb_iseq_t *iseq, int line_no, ID id, VALUE argc, const rb_iseq_t *blockiseq, VALUE flag, struct rb_call_info_kw_arg *keywords)
1147 {
1148  VALUE *operands = (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 3);
1149  operands[0] = (VALUE)new_callinfo(iseq, id, FIX2INT(argc), FIX2INT(flag), keywords, blockiseq != NULL);
1150  operands[1] = Qfalse; /* cache */
1151  operands[2] = (VALUE)blockiseq;
1152  return new_insn_core(iseq, line_no, BIN(send), 3, operands);
1153 }
1154 
1155 static rb_iseq_t *
1156 new_child_iseq(rb_iseq_t *iseq, NODE *node,
1157  VALUE name, const rb_iseq_t *parent, enum iseq_type type, int line_no)
1158 {
1159  rb_iseq_t *ret_iseq;
1160 
1161  debugs("[new_child_iseq]> ---------------------------------------\n");
1162  ret_iseq = rb_iseq_new_with_opt(node, name,
1163  rb_iseq_path(iseq), rb_iseq_realpath(iseq),
1164  INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option);
1165  debugs("[new_child_iseq]< ---------------------------------------\n");
1166  iseq_add_mark_object(iseq, (VALUE)ret_iseq);
1167  return ret_iseq;
1168 }
1169 
1170 static int
1171 iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
1172 {
1173  if (RTEST(ISEQ_COMPILE_DATA(iseq)->err_info))
1174  return COMPILE_NG;
1175 
1176  /* debugs("[compile step 2] (iseq_array_to_linkedlist)\n"); */
1177 
1178  if (compile_debug > 5)
1179  dump_disasm_list(FIRST_ELEMENT(anchor));
1180 
1181  debugs("[compile step 3.1 (iseq_optimize)]\n");
1182  iseq_optimize(iseq, anchor);
1183 
1184  if (compile_debug > 5)
1185  dump_disasm_list(FIRST_ELEMENT(anchor));
1186 
1187  if (ISEQ_COMPILE_DATA(iseq)->option->instructions_unification) {
1188  debugs("[compile step 3.2 (iseq_insns_unification)]\n");
1189  iseq_insns_unification(iseq, anchor);
1190  if (compile_debug > 5)
1191  dump_disasm_list(FIRST_ELEMENT(anchor));
1192  }
1193 
1194  if (ISEQ_COMPILE_DATA(iseq)->option->stack_caching) {
1195  debugs("[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
1196  iseq_set_sequence_stackcaching(iseq, anchor);
1197  if (compile_debug > 5)
1198  dump_disasm_list(FIRST_ELEMENT(anchor));
1199  }
1200 
1201  debugs("[compile step 4.1 (iseq_set_sequence)]\n");
1202  if (!iseq_set_sequence(iseq, anchor)) return COMPILE_NG;
1203  if (compile_debug > 5)
1204  dump_disasm_list(FIRST_ELEMENT(anchor));
1205 
1206  debugs("[compile step 4.2 (iseq_set_exception_table)]\n");
1207  if (!iseq_set_exception_table(iseq)) return COMPILE_NG;
1208 
1209  debugs("[compile step 4.3 (set_optargs_table)] \n");
1210  if (!iseq_set_optargs_table(iseq)) return COMPILE_NG;
1211 
1212  debugs("[compile step 5 (iseq_translate_threaded_code)] \n");
1213  if (!rb_iseq_translate_threaded_code(iseq)) return COMPILE_NG;
1214 
1215  if (compile_debug > 1) {
1216  VALUE str = rb_iseq_disasm(iseq);
1217  printf("%s\n", StringValueCStr(str));
1218  }
1219  debugs("[compile step: finish]\n");
1220 
1221  return COMPILE_OK;
1222 }
1223 
1224 static int
1225 iseq_set_exception_local_table(rb_iseq_t *iseq)
1226 {
1227  /* TODO: every id table is same -> share it.
1228  * Current problem is iseq_free().
1229  */
1230  ID id_dollar_bang;
1231  ID *ids = (ID *)ALLOC_N(ID, 1);
1232 
1233  CONST_ID(id_dollar_bang, "#$!");
1234  iseq->body->local_table_size = 1;
1235  ids[0] = id_dollar_bang;
1236  iseq->body->local_table = ids;
1237  return COMPILE_OK;
1238 }
1239 
1240 static int
1241 get_lvar_level(const rb_iseq_t *iseq)
1242 {
1243  int lev = 0;
1244  while (iseq != iseq->body->local_iseq) {
1245  lev++;
1246  iseq = iseq->body->parent_iseq;
1247  }
1248  return lev;
1249 }
1250 
1251 static int
1252 get_dyna_var_idx_at_raw(const rb_iseq_t *iseq, ID id)
1253 {
1254  unsigned int i;
1255 
1256  for (i = 0; i < iseq->body->local_table_size; i++) {
1257  if (iseq->body->local_table[i] == id) {
1258  return (int)i;
1259  }
1260  }
1261  return -1;
1262 }
1263 
1264 static int
1265 get_local_var_idx(const rb_iseq_t *iseq, ID id)
1266 {
1267  int idx = get_dyna_var_idx_at_raw(iseq->body->local_iseq, id);
1268 
1269  if (idx < 0) {
1270  rb_bug("get_local_var_idx: %d", idx);
1271  }
1272 
1273  return idx;
1274 }
1275 
1276 static int
1277 get_dyna_var_idx(const rb_iseq_t *iseq, ID id, int *level, int *ls)
1278 {
1279  int lv = 0, idx = -1;
1280 
1281  while (iseq) {
1282  idx = get_dyna_var_idx_at_raw(iseq, id);
1283  if (idx >= 0) {
1284  break;
1285  }
1286  iseq = iseq->body->parent_iseq;
1287  lv++;
1288  }
1289 
1290  if (idx < 0) {
1291  rb_bug("get_dyna_var_idx: -1");
1292  }
1293 
1294  *level = lv;
1295  *ls = iseq->body->local_table_size;
1296  return idx;
1297 }
1298 
1299 static void
1300 iseq_calc_param_size(rb_iseq_t *iseq)
1301 {
1302  if (iseq->body->param.flags.has_opt ||
1303  iseq->body->param.flags.has_post ||
1304  iseq->body->param.flags.has_rest ||
1305  iseq->body->param.flags.has_block ||
1306  iseq->body->param.flags.has_kw ||
1307  iseq->body->param.flags.has_kwrest) {
1308 
1309  if (iseq->body->param.flags.has_block) {
1310  iseq->body->param.size = iseq->body->param.block_start + 1;
1311  }
1312  else if (iseq->body->param.flags.has_kwrest) {
1313  iseq->body->param.size = iseq->body->param.keyword->rest_start + 1;
1314  }
1315  else if (iseq->body->param.flags.has_kw) {
1316  iseq->body->param.size = iseq->body->param.keyword->bits_start + 1;
1317  }
1318  else if (iseq->body->param.flags.has_post) {
1319  iseq->body->param.size = iseq->body->param.post_start + iseq->body->param.post_num;
1320  }
1321  else if (iseq->body->param.flags.has_rest) {
1322  iseq->body->param.size = iseq->body->param.rest_start + 1;
1323  }
1324  else if (iseq->body->param.flags.has_opt) {
1325  iseq->body->param.size = iseq->body->param.lead_num + iseq->body->param.opt_num;
1326  }
1327  else {
1328  rb_bug("unreachable");
1329  }
1330  }
1331  else {
1332  iseq->body->param.size = iseq->body->param.lead_num;
1333  }
1334 }
1335 
1336 static void
1337 iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
1338  const struct rb_args_info *args)
1339 {
1340  NODE *node = args->kw_args;
1341  struct rb_iseq_param_keyword *keyword;
1342  const VALUE default_values = rb_ary_tmp_new(1);
1343  const VALUE complex_mark = rb_str_tmp_new(0);
1344  int kw = 0, rkw = 0, di = 0, i;
1345 
1346  iseq->body->param.flags.has_kw = TRUE;
1347  iseq->body->param.keyword = keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
1348  keyword->bits_start = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_cflag);
1349 
1350  while (node) {
1351  NODE *val_node = node->nd_body->nd_value;
1352  VALUE dv;
1353 
1354  if (val_node == (NODE *)-1) {
1355  ++rkw;
1356  }
1357  else {
1358  switch (nd_type(val_node)) {
1359  case NODE_LIT:
1360  dv = val_node->nd_lit;
1361  iseq_add_mark_object(iseq, dv);
1362  break;
1363  case NODE_NIL:
1364  dv = Qnil;
1365  break;
1366  case NODE_TRUE:
1367  dv = Qtrue;
1368  break;
1369  case NODE_FALSE:
1370  dv = Qfalse;
1371  break;
1372  default:
1373  COMPILE_POPPED(optargs, "kwarg", node); /* nd_type(node) == NODE_KW_ARG */
1374  dv = complex_mark;
1375  }
1376 
1377  keyword->num = ++di;
1378  rb_ary_push(default_values, dv);
1379  }
1380 
1381  kw++;
1382  node = node->nd_next;
1383  }
1384 
1385  keyword->num = kw;
1386 
1387  if (args->kw_rest_arg->nd_vid != 0) {
1388  keyword->rest_start = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_vid);
1389  iseq->body->param.flags.has_kwrest = TRUE;
1390  }
1391  keyword->required_num = rkw;
1392  keyword->table = &iseq->body->local_table[keyword->bits_start - keyword->num];
1393 
1394  {
1395  VALUE *dvs = ALLOC_N(VALUE, RARRAY_LEN(default_values));
1396 
1397  for (i = 0; i < RARRAY_LEN(default_values); i++) {
1398  VALUE dv = RARRAY_AREF(default_values, i);
1399  if (dv == complex_mark) dv = Qundef;
1400  dvs[i] = dv;
1401  }
1402 
1403  keyword->default_values = dvs;
1404  }
1405 }
1406 
1407 static int
1408 iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, NODE *node_args)
1409 {
1410  debugs("iseq_set_arguments: %s\n", node_args ? "" : "0");
1411 
1412  if (node_args) {
1413  struct rb_args_info *args = node_args->nd_ainfo;
1414  ID rest_id = 0;
1415  int last_comma = 0;
1416  ID block_id = 0;
1417 
1418  EXPECT_NODE("iseq_set_arguments", node_args, NODE_ARGS, COMPILE_NG);
1419 
1420  iseq->body->param.lead_num = (int)args->pre_args_num;
1421  if (iseq->body->param.lead_num > 0) iseq->body->param.flags.has_lead = TRUE;
1422  debugs(" - argc: %d\n", iseq->body->param.lead_num);
1423 
1424  rest_id = args->rest_arg;
1425  if (rest_id == 1) {
1426  last_comma = 1;
1427  rest_id = 0;
1428  }
1429  block_id = args->block_arg;
1430 
1431  if (args->first_post_arg) {
1432  iseq->body->param.post_start = get_dyna_var_idx_at_raw(iseq, args->first_post_arg);
1433  iseq->body->param.post_num = args->post_args_num;
1434  iseq->body->param.flags.has_post = TRUE;
1435  }
1436 
1437  if (args->opt_args) {
1438  NODE *node = args->opt_args;
1439  LABEL *label;
1440  VALUE labels = rb_ary_tmp_new(1);
1441  VALUE *opt_table;
1442  int i = 0, j;
1443 
1444  while (node) {
1445  label = NEW_LABEL(nd_line(node));
1446  rb_ary_push(labels, (VALUE)label | 1);
1447  ADD_LABEL(optargs, label);
1448  COMPILE_POPPED(optargs, "optarg", node->nd_body);
1449  node = node->nd_next;
1450  i += 1;
1451  }
1452 
1453  /* last label */
1454  label = NEW_LABEL(nd_line(node_args));
1455  rb_ary_push(labels, (VALUE)label | 1);
1456  ADD_LABEL(optargs, label);
1457 
1458  opt_table = ALLOC_N(VALUE, i+1);
1459 
1460  MEMCPY(opt_table, RARRAY_CONST_PTR(labels), VALUE, i+1);
1461  for (j = 0; j < i+1; j++) {
1462  opt_table[j] &= ~1;
1463  }
1464  rb_ary_clear(labels);
1465 
1466  iseq->body->param.flags.has_opt = TRUE;
1467  iseq->body->param.opt_num = i;
1468  iseq->body->param.opt_table = opt_table;
1469  }
1470 
1471  if (args->kw_args) {
1472  iseq_set_arguments_keywords(iseq, optargs, args);
1473  }
1474  else if (args->kw_rest_arg) {
1475  struct rb_iseq_param_keyword *keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
1476  keyword->rest_start = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_vid);
1477  iseq->body->param.keyword = keyword;
1478  iseq->body->param.flags.has_kwrest = TRUE;
1479  }
1480 
1481  if (args->pre_init) { /* m_init */
1482  COMPILE_POPPED(optargs, "init arguments (m)", args->pre_init);
1483  }
1484  if (args->post_init) { /* p_init */
1485  COMPILE_POPPED(optargs, "init arguments (p)", args->post_init);
1486  }
1487 
1488  if (rest_id) {
1489  iseq->body->param.rest_start = get_dyna_var_idx_at_raw(iseq, rest_id);
1490  iseq->body->param.flags.has_rest = TRUE;
1491  assert(iseq->body->param.rest_start != -1);
1492 
1493  if (iseq->body->param.post_start == 0) { /* TODO: why that? */
1494  iseq->body->param.post_start = iseq->body->param.rest_start + 1;
1495  }
1496  }
1497 
1498  if (block_id) {
1499  iseq->body->param.block_start = get_dyna_var_idx_at_raw(iseq, block_id);
1500  iseq->body->param.flags.has_block = TRUE;
1501  }
1502 
1503  iseq_calc_param_size(iseq);
1504 
1505  if (iseq->body->type == ISEQ_TYPE_BLOCK) {
1506  if (iseq->body->param.flags.has_opt == FALSE &&
1507  iseq->body->param.flags.has_post == FALSE &&
1508  iseq->body->param.flags.has_rest == FALSE &&
1509  iseq->body->param.flags.has_kw == FALSE &&
1510  iseq->body->param.flags.has_kwrest == FALSE) {
1511 
1512  if (iseq->body->param.lead_num == 1 && last_comma == 0) {
1513  /* {|a|} */
1514  iseq->body->param.flags.ambiguous_param0 = TRUE;
1515  }
1516  }
1517  }
1518  }
1519 
1520  return COMPILE_OK;
1521 }
1522 
1523 static int
1524 iseq_set_local_table(rb_iseq_t *iseq, const ID *tbl)
1525 {
1526  unsigned int size;
1527 
1528  if (tbl) {
1529  size = (unsigned int)*tbl;
1530  tbl++;
1531  }
1532  else {
1533  size = 0;
1534  }
1535 
1536  if (size > 0) {
1537  ID *ids = (ID *)ALLOC_N(ID, size);
1538  MEMCPY(ids, tbl, ID, size);
1539  iseq->body->local_table = ids;
1540  }
1541  iseq->body->local_table_size = size;
1542 
1543  debugs("iseq_set_local_table: %u\n", iseq->body->local_table_size);
1544  return COMPILE_OK;
1545 }
1546 
1547 static int
1548 cdhash_cmp(VALUE val, VALUE lit)
1549 {
1550  if (val == lit) return 0;
1551  if (SPECIAL_CONST_P(lit)) {
1552  return val != lit;
1553  }
1554  if (SPECIAL_CONST_P(val) || BUILTIN_TYPE(val) != BUILTIN_TYPE(lit)) {
1555  return -1;
1556  }
1557  if (BUILTIN_TYPE(lit) == T_STRING) {
1558  return rb_str_hash_cmp(lit, val);
1559  }
1560  return !rb_eql(lit, val);
1561 }
1562 
1563 static st_index_t
1564 cdhash_hash(VALUE a)
1565 {
1566  if (SPECIAL_CONST_P(a)) return (st_index_t)a;
1567  if (RB_TYPE_P(a, T_STRING)) return rb_str_hash(a);
1568  {
1569  VALUE hval = rb_hash(a);
1570  return (st_index_t)FIX2LONG(hval);
1571  }
1572 }
1573 
1574 static const struct st_hash_type cdhash_type = {
1575  cdhash_cmp,
1576  cdhash_hash,
1577 };
1578 
1581  int pos;
1582  int len;
1583 };
1584 
1585 static int
1586 cdhash_set_label_i(VALUE key, VALUE val, void *ptr)
1587 {
1588  struct cdhash_set_label_struct *data = (struct cdhash_set_label_struct *)ptr;
1589  LABEL *lobj = (LABEL *)(val & ~1);
1590  rb_hash_aset(data->hash, key, INT2FIX(lobj->position - (data->pos+data->len)));
1591  return ST_CONTINUE;
1592 }
1593 
1594 
1595 static inline VALUE
1596 get_ivar_ic_value(rb_iseq_t *iseq,ID id)
1597 {
1598  VALUE val;
1599  struct rb_id_table *tbl = ISEQ_COMPILE_DATA(iseq)->ivar_cache_table;
1600  if (tbl) {
1601  if (rb_id_table_lookup(tbl,id,&val)) {
1602  return val;
1603  }
1604  }
1605  else {
1606  tbl = rb_id_table_create(1);
1607  ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = tbl;
1608  }
1609  val = INT2FIX(iseq->body->is_size++);
1610  rb_id_table_insert(tbl,id,val);
1611  return val;
1612 }
1613 
1614 #define BADINSN_DUMP(anchor, list, dest) \
1615  dump_disasm_list_with_cursor(&anchor->anchor, list, dest)
1616 
1617 #define BADINSN_ERROR \
1618  (xfree(generated_iseq), \
1619  xfree(line_info_table), \
1620  BADINSN_DUMP(anchor, list, NULL), \
1621  COMPILE_ERROR)
1622 
1623 static int
1624 fix_sp_depth(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
1625 {
1626  int stack_max = 0, sp = 0, line = 0;
1627  LINK_ELEMENT *list;
1628 
1629  for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
1630  if (list->type == ISEQ_ELEMENT_LABEL) {
1631  LABEL *lobj = (LABEL *)list;
1632  lobj->set = TRUE;
1633  }
1634  }
1635 
1636  for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
1637  switch (list->type) {
1638  case ISEQ_ELEMENT_INSN:
1639  {
1640  int j, len, insn;
1641  const char *types;
1642  VALUE *operands;
1643  INSN *iobj = (INSN *)list;
1644 
1645  /* update sp */
1646  sp = calc_sp_depth(sp, iobj);
1647  if (sp < 0) {
1648  BADINSN_DUMP(anchor, list, NULL);
1649  COMPILE_ERROR(iseq, iobj->line_no,
1650  "argument stack underflow (%d)", sp);
1651  return -1;
1652  }
1653  if (sp > stack_max) {
1654  stack_max = sp;
1655  }
1656 
1657  line = iobj->line_no;
1658  /* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */
1659  operands = iobj->operands;
1660  insn = iobj->insn_id;
1661  types = insn_op_types(insn);
1662  len = insn_len(insn);
1663 
1664  /* operand check */
1665  if (iobj->operand_size != len - 1) {
1666  /* printf("operand size miss! (%d, %d)\n", iobj->operand_size, len); */
1667  BADINSN_DUMP(anchor, list, NULL);
1668  COMPILE_ERROR(iseq, iobj->line_no,
1669  "operand size miss! (%d for %d)",
1670  iobj->operand_size, len - 1);
1671  return -1;
1672  }
1673 
1674  for (j = 0; types[j]; j++) {
1675  if (types[j] == TS_OFFSET) {
1676  /* label(destination position) */
1677  LABEL *lobj = (LABEL *)operands[j];
1678  if (!lobj->set) {
1679  BADINSN_DUMP(anchor, list, NULL);
1680  COMPILE_ERROR(iseq, iobj->line_no,
1681  "unknown label: "LABEL_FORMAT, lobj->label_no);
1682  return -1;
1683  }
1684  if (lobj->sp == -1) {
1685  lobj->sp = sp;
1686  }
1687  }
1688  }
1689  break;
1690  }
1691  case ISEQ_ELEMENT_LABEL:
1692  {
1693  LABEL *lobj = (LABEL *)list;
1694  if (lobj->sp == -1) {
1695  lobj->sp = sp;
1696  }
1697  else {
1698  sp = lobj->sp;
1699  }
1700  break;
1701  }
1702  case ISEQ_ELEMENT_NONE:
1703  {
1704  /* ignore */
1705  break;
1706  }
1707  case ISEQ_ELEMENT_ADJUST:
1708  {
1709  ADJUST *adjust = (ADJUST *)list;
1710  int orig_sp = sp;
1711 
1712  sp = adjust->label ? adjust->label->sp : 0;
1713  if (adjust->line_no != -1 && orig_sp - sp < 0) {
1714  BADINSN_DUMP(anchor, list, NULL);
1715  COMPILE_ERROR(iseq, adjust->line_no,
1716  "iseq_set_sequence: adjust bug %d < %d",
1717  orig_sp, sp);
1718  return -1;
1719  }
1720  break;
1721  }
1722  default:
1723  BADINSN_DUMP(anchor, list, NULL);
1724  COMPILE_ERROR(iseq, line, "unknown list type: %d", list->type);
1725  return -1;
1726  }
1727  }
1728  return stack_max;
1729 }
1730 
1734 static int
1735 iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
1736 {
1737  struct iseq_line_info_entry *line_info_table;
1738  unsigned int last_line = 0;
1739  LINK_ELEMENT *list;
1740  VALUE *generated_iseq;
1741 
1742  int insn_num, code_index, line_info_index, sp = 0;
1743  int stack_max = fix_sp_depth(iseq, anchor);
1744 
1745  if (stack_max < 0) return COMPILE_NG;
1746 
1747  /* fix label position */
1748  list = FIRST_ELEMENT(anchor);
1749  insn_num = code_index = 0;
1750  while (list) {
1751  switch (list->type) {
1752  case ISEQ_ELEMENT_INSN:
1753  {
1754  INSN *iobj = (INSN *)list;
1755  /* update sp */
1756  sp = calc_sp_depth(sp, iobj);
1757  code_index += insn_data_length(iobj);
1758  insn_num++;
1759  break;
1760  }
1761  case ISEQ_ELEMENT_LABEL:
1762  {
1763  LABEL *lobj = (LABEL *)list;
1764  lobj->position = code_index;
1765  sp = lobj->sp;
1766  break;
1767  }
1768  case ISEQ_ELEMENT_NONE:
1769  {
1770  /* ignore */
1771  break;
1772  }
1773  case ISEQ_ELEMENT_ADJUST:
1774  {
1775  ADJUST *adjust = (ADJUST *)list;
1776  if (adjust->line_no != -1) {
1777  int orig_sp = sp;
1778  sp = adjust->label ? adjust->label->sp : 0;
1779  if (orig_sp - sp > 0) {
1780  if (orig_sp - sp > 1) code_index++; /* 1 operand */
1781  code_index++; /* insn */
1782  insn_num++;
1783  }
1784  }
1785  break;
1786  }
1787  }
1788  list = list->next;
1789  }
1790 
1791  /* make instruction sequence */
1792  generated_iseq = ALLOC_N(VALUE, code_index);
1793  line_info_table = ALLOC_N(struct iseq_line_info_entry, insn_num);
1795  iseq->body->ci_entries = (struct rb_call_info *)ruby_xmalloc(sizeof(struct rb_call_info) * iseq->body->ci_size +
1796  sizeof(struct rb_call_info_with_kwarg) * iseq->body->ci_kw_size);
1797  iseq->body->cc_entries = ZALLOC_N(struct rb_call_cache, iseq->body->ci_size + iseq->body->ci_kw_size);
1798 
1799  ISEQ_COMPILE_DATA(iseq)->ci_index = ISEQ_COMPILE_DATA(iseq)->ci_kw_index = 0;
1800 
1801  list = FIRST_ELEMENT(anchor);
1802  line_info_index = code_index = sp = 0;
1803 
1804  while (list) {
1805  switch (list->type) {
1806  case ISEQ_ELEMENT_INSN:
1807  {
1808  int j, len, insn;
1809  const char *types;
1810  VALUE *operands;
1811  INSN *iobj = (INSN *)list;
1812 
1813  /* update sp */
1814  sp = calc_sp_depth(sp, iobj);
1815  /* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */
1816  operands = iobj->operands;
1817  insn = iobj->insn_id;
1818  generated_iseq[code_index] = insn;
1819  types = insn_op_types(insn);
1820  len = insn_len(insn);
1821 
1822  for (j = 0; types[j]; j++) {
1823  char type = types[j];
1824  /* printf("--> [%c - (%d-%d)]\n", type, k, j); */
1825  switch (type) {
1826  case TS_OFFSET:
1827  {
1828  /* label(destination position) */
1829  LABEL *lobj = (LABEL *)operands[j];
1830  generated_iseq[code_index + 1 + j] = lobj->position - (code_index + len);
1831  break;
1832  }
1833  case TS_CDHASH:
1834  {
1835  VALUE map = operands[j];
1836  struct cdhash_set_label_struct data;
1837  data.hash = map;
1838  data.pos = code_index;
1839  data.len = len;
1840  rb_hash_foreach(map, cdhash_set_label_i, (VALUE)&data);
1841 
1842  rb_hash_rehash(map);
1843  freeze_hide_obj(map);
1844  generated_iseq[code_index + 1 + j] = map;
1845  break;
1846  }
1847  case TS_LINDEX:
1848  case TS_NUM: /* ulong */
1849  generated_iseq[code_index + 1 + j] = FIX2INT(operands[j]);
1850  break;
1851  case TS_ISEQ: /* iseq */
1852  {
1853  VALUE v = operands[j];
1854  generated_iseq[code_index + 1 + j] = v;
1855  break;
1856  }
1857  case TS_VALUE: /* VALUE */
1858  {
1859  VALUE v = operands[j];
1860  generated_iseq[code_index + 1 + j] = v;
1861  /* to mark ruby object */
1862  iseq_add_mark_object(iseq, v);
1863  break;
1864  }
1865  case TS_IC: /* inline cache */
1866  {
1867  unsigned int ic_index = FIX2UINT(operands[j]);
1868  IC ic = (IC)&iseq->body->is_entries[ic_index];
1869  if (UNLIKELY(ic_index >= iseq->body->is_size)) {
1870  rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->body->is_size);
1871  }
1872  generated_iseq[code_index + 1 + j] = (VALUE)ic;
1873  break;
1874  }
1875  case TS_CALLINFO: /* call info */
1876  {
1877  struct rb_call_info *base_ci = (struct rb_call_info *)operands[j];
1878  struct rb_call_info *ci;
1879 
1880  if (base_ci->flag & VM_CALL_KWARG) {
1881  struct rb_call_info_with_kwarg *ci_kw_entries = (struct rb_call_info_with_kwarg *)&iseq->body->ci_entries[iseq->body->ci_size];
1882  struct rb_call_info_with_kwarg *ci_kw = &ci_kw_entries[ISEQ_COMPILE_DATA(iseq)->ci_kw_index++];
1883  *ci_kw = *((struct rb_call_info_with_kwarg *)base_ci);
1884  ci = (struct rb_call_info *)ci_kw;
1885  assert(ISEQ_COMPILE_DATA(iseq)->ci_kw_index <= iseq->body->ci_kw_size);
1886  }
1887  else {
1888  ci = &iseq->body->ci_entries[ISEQ_COMPILE_DATA(iseq)->ci_index++];
1889  *ci = *base_ci;
1890  assert(ISEQ_COMPILE_DATA(iseq)->ci_index <= iseq->body->ci_size);
1891  }
1892 
1893  generated_iseq[code_index + 1 + j] = (VALUE)ci;
1894  break;
1895  }
1896  case TS_CALLCACHE:
1897  {
1898  struct rb_call_cache *cc = &iseq->body->cc_entries[ISEQ_COMPILE_DATA(iseq)->ci_index + ISEQ_COMPILE_DATA(iseq)->ci_kw_index - 1];
1899  generated_iseq[code_index + 1 + j] = (VALUE)cc;
1900  break;
1901  }
1902  case TS_ID: /* ID */
1903  generated_iseq[code_index + 1 + j] = SYM2ID(operands[j]);
1904  break;
1905  case TS_GENTRY:
1906  {
1907  struct rb_global_entry *entry =
1908  (struct rb_global_entry *)(operands[j] & (~1));
1909  generated_iseq[code_index + 1 + j] = (VALUE)entry;
1910  }
1911  break;
1912  case TS_FUNCPTR:
1913  generated_iseq[code_index + 1 + j] = operands[j];
1914  break;
1915  default:
1916  BADINSN_ERROR(iseq, iobj->line_no,
1917  "unknown operand type: %c", type);
1918  return COMPILE_NG;
1919  }
1920  }
1921  if (last_line != iobj->line_no) {
1922  line_info_table[line_info_index].line_no = last_line = iobj->line_no;
1923  line_info_table[line_info_index].position = code_index;
1924  line_info_index++;
1925  }
1926  code_index += len;
1927  break;
1928  }
1929  case ISEQ_ELEMENT_LABEL:
1930  {
1931  LABEL *lobj = (LABEL *)list;
1932  sp = lobj->sp;
1933  break;
1934  }
1935  case ISEQ_ELEMENT_ADJUST:
1936  {
1937  ADJUST *adjust = (ADJUST *)list;
1938  int orig_sp = sp;
1939 
1940  if (adjust->label) {
1941  sp = adjust->label->sp;
1942  }
1943  else {
1944  sp = 0;
1945  }
1946 
1947  if (adjust->line_no != -1) {
1948  const int diff = orig_sp - sp;
1949  if (diff > 0) {
1950  if (last_line != (unsigned int)adjust->line_no) {
1951  line_info_table[line_info_index].line_no = last_line = adjust->line_no;
1952  line_info_table[line_info_index].position = code_index;
1953  line_info_index++;
1954  }
1955  }
1956  if (diff > 1) {
1957  generated_iseq[code_index++] = BIN(adjuststack);
1958  generated_iseq[code_index++] = orig_sp - sp;
1959  }
1960  else if (diff == 1) {
1961  generated_iseq[code_index++] = BIN(pop);
1962  }
1963  else if (diff < 0) {
1964  int label_no = adjust->label ? adjust->label->label_no : -1;
1965  xfree(generated_iseq);
1966  xfree(line_info_table);
1967  debug_list(anchor);
1968  COMPILE_ERROR(iseq, adjust->line_no,
1969  "iseq_set_sequence: adjust bug to %d %d < %d",
1970  label_no, orig_sp, sp);
1971  return COMPILE_NG;
1972  }
1973  }
1974  break;
1975  }
1976  default:
1977  /* ignore */
1978  break;
1979  }
1980  list = list->next;
1981  }
1982 
1983  iseq->body->iseq_encoded = (void *)generated_iseq;
1984  iseq->body->iseq_size = code_index;
1985  iseq->body->stack_max = stack_max;
1986 
1987  /* get rid of memory leak when REALLOC failed */
1988  iseq->body->line_info_table = line_info_table;
1989 
1990  REALLOC_N(line_info_table, struct iseq_line_info_entry, line_info_index);
1991  iseq->body->line_info_table = line_info_table;
1992  iseq->body->line_info_size = line_info_index;
1993 
1994  return COMPILE_OK;
1995 }
1996 
1997 static int
1998 label_get_position(LABEL *lobj)
1999 {
2000  return lobj->position;
2001 }
2002 
2003 static int
2004 label_get_sp(LABEL *lobj)
2005 {
2006  return lobj->sp;
2007 }
2008 
2009 static int
2010 iseq_set_exception_table(rb_iseq_t *iseq)
2011 {
2012  const VALUE *tptr, *ptr;
2013  unsigned int tlen, i;
2014  struct iseq_catch_table_entry *entry;
2015 
2016  tlen = (int)RARRAY_LEN(ISEQ_COMPILE_DATA(iseq)->catch_table_ary);
2017  tptr = RARRAY_CONST_PTR(ISEQ_COMPILE_DATA(iseq)->catch_table_ary);
2018 
2019  if (tlen > 0) {
2020  struct iseq_catch_table *table = xmalloc(iseq_catch_table_bytes(tlen));
2021  table->size = tlen;
2022 
2023  for (i = 0; i < table->size; i++) {
2024  ptr = RARRAY_CONST_PTR(tptr[i]);
2025  entry = &table->entries[i];
2026  entry->type = (enum catch_type)(ptr[0] & 0xffff);
2027  entry->start = label_get_position((LABEL *)(ptr[1] & ~1));
2028  entry->end = label_get_position((LABEL *)(ptr[2] & ~1));
2029  entry->iseq = (rb_iseq_t *)ptr[3];
2030 
2031  /* register iseq as mark object */
2032  if (entry->iseq != 0) {
2033  iseq_add_mark_object(iseq, (VALUE)entry->iseq);
2034  }
2035 
2036  /* stack depth */
2037  if (ptr[4]) {
2038  LABEL *lobj = (LABEL *)(ptr[4] & ~1);
2039  entry->cont = label_get_position(lobj);
2040  entry->sp = label_get_sp(lobj);
2041 
2042  /* TODO: Dirty Hack! Fix me */
2043  if (entry->type == CATCH_TYPE_RESCUE ||
2044  entry->type == CATCH_TYPE_BREAK ||
2045  entry->type == CATCH_TYPE_NEXT) {
2046  entry->sp--;
2047  }
2048  }
2049  else {
2050  entry->cont = 0;
2051  }
2052  }
2053  iseq->body->catch_table = table;
2054  RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, 0); /* free */
2055  }
2056  else {
2057  iseq->body->catch_table = NULL;
2058  }
2059 
2060  return COMPILE_OK;
2061 }
2062 
2063 /*
2064  * set optional argument table
2065  * def foo(a, b=expr1, c=expr2)
2066  * =>
2067  * b:
2068  * expr1
2069  * c:
2070  * expr2
2071  */
2072 static int
2073 iseq_set_optargs_table(rb_iseq_t *iseq)
2074 {
2075  int i;
2076  VALUE *opt_table = (VALUE *)iseq->body->param.opt_table;
2077 
2078  if (iseq->body->param.flags.has_opt) {
2079  for (i = 0; i < iseq->body->param.opt_num + 1; i++) {
2080  opt_table[i] = label_get_position((LABEL *)opt_table[i]);
2081  }
2082  }
2083  return COMPILE_OK;
2084 }
2085 
2086 static LINK_ELEMENT *
2087 get_destination_insn(INSN *iobj)
2088 {
2089  LABEL *lobj = (LABEL *)OPERAND_AT(iobj, 0);
2090  LINK_ELEMENT *list;
2091 
2092  list = lobj->link.next;
2093  while (list) {
2094  if (IS_INSN(list) || IS_ADJUST(list)) {
2095  break;
2096  }
2097  list = list->next;
2098  }
2099  return list;
2100 }
2101 
2102 static LINK_ELEMENT *
2103 get_next_insn(INSN *iobj)
2104 {
2105  LINK_ELEMENT *list = iobj->link.next;
2106 
2107  while (list) {
2108  if (IS_INSN(list) || IS_ADJUST(list)) {
2109  return list;
2110  }
2111  list = list->next;
2112  }
2113  return 0;
2114 }
2115 
2116 static LINK_ELEMENT *
2117 get_prev_insn(INSN *iobj)
2118 {
2119  LINK_ELEMENT *list = iobj->link.prev;
2120 
2121  while (list) {
2122  if (IS_INSN(list) || IS_ADJUST(list)) {
2123  return list;
2124  }
2125  list = list->prev;
2126  }
2127  return 0;
2128 }
2129 
2130 static void
2131 unref_destination(INSN *iobj, int pos)
2132 {
2133  LABEL *lobj = (LABEL *)OPERAND_AT(iobj, pos);
2134  --lobj->refcnt;
2135  if (!lobj->refcnt) REMOVE_ELEM(&lobj->link);
2136 }
2137 
2138 static void
2139 replace_destination(INSN *dobj, INSN *nobj)
2140 {
2141  VALUE n = OPERAND_AT(nobj, 0);
2142  LABEL *dl = (LABEL *)OPERAND_AT(dobj, 0);
2143  LABEL *nl = (LABEL *)n;
2144  --dl->refcnt;
2145  ++nl->refcnt;
2146  OPERAND_AT(dobj, 0) = n;
2147  if (!dl->refcnt) REMOVE_ELEM(&dl->link);
2148 }
2149 
2150 static int
2151 remove_unreachable_chunk(rb_iseq_t *iseq, LINK_ELEMENT *i)
2152 {
2153  LINK_ELEMENT *first = i, *end;
2154 
2155  if (!i) return 0;
2156  while (i) {
2157  if (IS_INSN(i)) {
2158  if (IS_INSN_ID(i, jump) || IS_INSN_ID(i, leave)) {
2159  break;
2160  }
2161  }
2162  else if (IS_LABEL(i)) {
2163  if (((LABEL *)i)->unremovable) return 0;
2164  if (((LABEL *)i)->refcnt > 0) {
2165  if (i == first) return 0;
2166  i = i->prev;
2167  break;
2168  }
2169  }
2170  else return 0;
2171  i = i->next;
2172  }
2173  end = i;
2174  i = first;
2175  do {
2176  if (IS_INSN(i)) {
2177  struct rb_iseq_constant_body *body = iseq->body;
2178  VALUE insn = INSN_OF(i);
2179  int pos, len = insn_len(insn);
2180  for (pos = 0; pos < len; ++pos) {
2181  switch (insn_op_types(insn)[pos]) {
2182  case TS_OFFSET:
2183  unref_destination((INSN *)i, pos);
2184  break;
2185  case TS_CALLINFO:
2186  if (((struct rb_call_info *)OPERAND_AT(i, pos))->flag & VM_CALL_KWARG)
2187  --(body->ci_kw_size);
2188  else
2189  --(body->ci_size);
2190  break;
2191  }
2192  }
2193  }
2194  REMOVE_ELEM(i);
2195  } while ((i != end) && (i = i->next) != 0);
2196  return 1;
2197 }
2198 
2199 static int
2200 iseq_pop_newarray(rb_iseq_t *iseq, INSN *iobj)
2201 {
2202  switch (OPERAND_AT(iobj, 0)) {
2203  case INT2FIX(0): /* empty array */
2204  REMOVE_ELEM(&iobj->link);
2205  return TRUE;
2206  case INT2FIX(1): /* single element array */
2207  REMOVE_ELEM(&iobj->link);
2208  return FALSE;
2209  default:
2210  iobj->insn_id = BIN(adjuststack);
2211  return TRUE;
2212  }
2213 }
2214 
2215 static int
2216 iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
2217 {
2218  INSN *const iobj = (INSN *)list;
2219  again:
2220  if (IS_INSN_ID(iobj, jump)) {
2221  INSN *niobj, *diobj, *piobj;
2222  diobj = (INSN *)get_destination_insn(iobj);
2223  niobj = (INSN *)get_next_insn(iobj);
2224 
2225  if (diobj == niobj) {
2226  /*
2227  * jump LABEL
2228  * LABEL:
2229  * =>
2230  * LABEL:
2231  */
2232  unref_destination(iobj, 0);
2233  REMOVE_ELEM(&iobj->link);
2234  return COMPILE_OK;
2235  }
2236  else if (iobj != diobj && IS_INSN_ID(diobj, jump) &&
2237  OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0)) {
2238  /*
2239  * useless jump elimination:
2240  * jump LABEL1
2241  * ...
2242  * LABEL1:
2243  * jump LABEL2
2244  *
2245  * => in this case, first jump instruction should jump to
2246  * LABEL2 directly
2247  */
2248  replace_destination(iobj, diobj);
2249  remove_unreachable_chunk(iseq, iobj->link.next);
2250  goto again;
2251  }
2252  else if (IS_INSN_ID(diobj, leave)) {
2253  /*
2254  * jump LABEL
2255  * ...
2256  * LABEL:
2257  * leave
2258  * =>
2259  * leave
2260  * ...
2261  * LABEL:
2262  * leave
2263  */
2264  INSN *popiobj = new_insn_core(iseq, iobj->line_no,
2265  BIN(pop), 0, 0);
2266  /* replace */
2267  unref_destination(iobj, 0);
2268  iobj->insn_id = BIN(leave);
2269  iobj->operand_size = 0;
2270  INSERT_ELEM_NEXT(&iobj->link, &popiobj->link);
2271  goto again;
2272  }
2273  else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 &&
2274  (IS_INSN_ID(piobj, branchif) ||
2275  IS_INSN_ID(piobj, branchunless))) {
2276  INSN *pdiobj = (INSN *)get_destination_insn(piobj);
2277  if (niobj == pdiobj) {
2278  /*
2279  * useless jump elimination (if/unless destination):
2280  * if L1
2281  * jump L2
2282  * L1:
2283  * ...
2284  * L2:
2285  *
2286  * ==>
2287  * unless L2
2288  * L1:
2289  * ...
2290  * L2:
2291  */
2292  piobj->insn_id = (IS_INSN_ID(piobj, branchif))
2293  ? BIN(branchunless) : BIN(branchif);
2294  replace_destination(piobj, iobj);
2295  REMOVE_ELEM(&iobj->link);
2296  return COMPILE_OK;
2297  }
2298  else if (diobj == pdiobj) {
2299  /*
2300  * useless jump elimination (if/unless before jump):
2301  * L1:
2302  * ...
2303  * if L1
2304  * jump L1
2305  *
2306  * ==>
2307  * L1:
2308  * ...
2309  * pop
2310  * jump L1
2311  */
2312  INSN *popiobj = new_insn_core(iseq, iobj->line_no,
2313  BIN(pop), 0, 0);
2314  REPLACE_ELEM(&piobj->link, &popiobj->link);
2315  }
2316  }
2317  if (remove_unreachable_chunk(iseq, iobj->link.next)) {
2318  goto again;
2319  }
2320  }
2321 
2322  /*
2323  * putstring "beg"
2324  * putstring "end"
2325  * newrange excl
2326  *
2327  * ==>
2328  *
2329  * putobject "beg".."end"
2330  */
2331  if (IS_INSN_ID(iobj, checkmatch)) {
2332  INSN *range = (INSN *)get_prev_insn(iobj);
2333  INSN *beg, *end;
2334 
2335  if (range && IS_INSN_ID(range, newrange) &&
2336  (end = (INSN *)get_prev_insn(range)) != 0 &&
2337  IS_INSN_ID(end, putstring) &&
2338  (beg = (INSN *)get_prev_insn(end)) != 0 &&
2339  IS_INSN_ID(beg, putstring)) {
2340  VALUE str_beg = OPERAND_AT(beg, 0);
2341  VALUE str_end = OPERAND_AT(end, 0);
2342  int excl = FIX2INT(OPERAND_AT(range, 0));
2343  VALUE lit_range = rb_range_new(str_beg, str_end, excl);
2344 
2345  iseq_add_mark_object_compile_time(iseq, lit_range);
2346  REMOVE_ELEM(&beg->link);
2347  REMOVE_ELEM(&end->link);
2348  range->insn_id = BIN(putobject);
2349  OPERAND_AT(range, 0) = lit_range;
2350  }
2351  }
2352 
2353  if (IS_INSN_ID(iobj, leave)) {
2354  remove_unreachable_chunk(iseq, iobj->link.next);
2355  }
2356 
2357  if (IS_INSN_ID(iobj, branchif) ||
2358  IS_INSN_ID(iobj, branchnil) ||
2359  IS_INSN_ID(iobj, branchunless)) {
2360  /*
2361  * if L1
2362  * ...
2363  * L1:
2364  * jump L2
2365  * =>
2366  * if L2
2367  */
2368  INSN *nobj = (INSN *)get_destination_insn(iobj);
2369  INSN *pobj = (INSN *)iobj->link.prev;
2370  int prev_dup = 0;
2371  if (pobj) {
2372  if (!IS_INSN(&pobj->link))
2373  pobj = 0;
2374  else if (IS_INSN_ID(pobj, dup))
2375  prev_dup = 1;
2376  }
2377 
2378  for (;;) {
2379  if (IS_INSN_ID(nobj, jump)) {
2380  replace_destination(iobj, nobj);
2381  }
2382  else if (prev_dup && IS_INSN_ID(nobj, dup) &&
2383  !!(nobj = (INSN *)nobj->link.next) &&
2384  /* basic blocks, with no labels in the middle */
2385  nobj->insn_id == iobj->insn_id) {
2386  /*
2387  * dup
2388  * if L1
2389  * ...
2390  * L1:
2391  * dup
2392  * if L2
2393  * =>
2394  * dup
2395  * if L2
2396  * ...
2397  * L1:
2398  * dup
2399  * if L2
2400  */
2401  replace_destination(iobj, nobj);
2402  }
2403  else if (pobj) {
2404  /*
2405  * putnil
2406  * if L1
2407  * =>
2408  * # nothing
2409  *
2410  * putobject true
2411  * if L1
2412  * =>
2413  * jump L1
2414  *
2415  * putstring ".."
2416  * if L1
2417  * =>
2418  * jump L1
2419  *
2420  * putstring ".."
2421  * dup
2422  * if L1
2423  * =>
2424  * putstring ".."
2425  * jump L1
2426  *
2427  */
2428  int cond;
2429  if (prev_dup && IS_INSN(pobj->link.prev)) {
2430  pobj = (INSN *)pobj->link.prev;
2431  }
2432  if (IS_INSN_ID(pobj, putobject)) {
2433  cond = (IS_INSN_ID(iobj, branchif) ?
2434  OPERAND_AT(pobj, 0) != Qfalse :
2435  IS_INSN_ID(iobj, branchunless) ?
2436  OPERAND_AT(pobj, 0) == Qfalse :
2437  FALSE);
2438  }
2439  else if (IS_INSN_ID(pobj, putstring) ||
2440  IS_INSN_ID(pobj, duparray) ||
2441  IS_INSN_ID(pobj, newarray)) {
2442  cond = IS_INSN_ID(iobj, branchif);
2443  }
2444  else if (IS_INSN_ID(pobj, putnil)) {
2445  cond = !IS_INSN_ID(iobj, branchif);
2446  }
2447  else break;
2448  if (prev_dup || !IS_INSN_ID(pobj, newarray)) {
2449  REMOVE_ELEM(iobj->link.prev);
2450  }
2451  else if (!iseq_pop_newarray(iseq, pobj)) {
2452  pobj = new_insn_core(iseq, pobj->line_no, BIN(pop), 0, NULL);
2453  INSERT_ELEM_NEXT(&iobj->link, &pobj->link);
2454  }
2455  if (cond) {
2456  iobj->insn_id = BIN(jump);
2457  goto again;
2458  }
2459  else {
2460  unref_destination(iobj, 0);
2461  REMOVE_ELEM(&iobj->link);
2462  }
2463  break;
2464  }
2465  else break;
2466  nobj = (INSN *)get_destination_insn(nobj);
2467  }
2468  }
2469 
2470  if (IS_INSN_ID(iobj, pop)) {
2471  /*
2472  * putself / putnil / putobject obj / putstring "..."
2473  * pop
2474  * =>
2475  * # do nothing
2476  */
2477  LINK_ELEMENT *prev = iobj->link.prev;
2478  if (IS_INSN(prev)) {
2479  enum ruby_vminsn_type previ = ((INSN *)prev)->insn_id;
2480  if (previ == BIN(putobject) || previ == BIN(putnil) ||
2481  previ == BIN(putself) || previ == BIN(putstring) ||
2482  previ == BIN(duparray)) {
2483  /* just push operand or static value and pop soon, no
2484  * side effects */
2485  REMOVE_ELEM(prev);
2486  REMOVE_ELEM(&iobj->link);
2487  }
2488  else if (previ == BIN(newarray) && iseq_pop_newarray(iseq, (INSN*)prev)) {
2489  REMOVE_ELEM(&iobj->link);
2490  }
2491  }
2492  }
2493 
2494  if (IS_INSN_ID(iobj, newarray) ||
2495  IS_INSN_ID(iobj, duparray) ||
2496  IS_INSN_ID(iobj, expandarray) ||
2497  IS_INSN_ID(iobj, concatarray) ||
2498  IS_INSN_ID(iobj, splatarray) ||
2499  0) {
2500  /*
2501  * newarray N
2502  * splatarray
2503  * =>
2504  * newarray N
2505  * newarray always puts an array
2506  */
2507  LINK_ELEMENT *next = iobj->link.next;
2508  if (IS_INSN(next) && IS_INSN_ID(next, splatarray)) {
2509  /* remove splatarray following always-array insn */
2510  REMOVE_ELEM(next);
2511  }
2512  }
2513 
2514  if (IS_INSN_ID(iobj, tostring)) {
2515  LINK_ELEMENT *next = iobj->link.next;
2516  if (IS_INSN(next) && IS_INSN_ID(next, concatstrings) &&
2517  OPERAND_AT(next, 0) == INT2FIX(1)) {
2518  REMOVE_ELEM(next);
2519  }
2520  }
2521 
2522  if (do_tailcallopt &&
2523  (IS_INSN_ID(iobj, send) ||
2524  IS_INSN_ID(iobj, opt_aref_with) ||
2525  IS_INSN_ID(iobj, opt_aset_with) ||
2526  IS_INSN_ID(iobj, invokesuper))) {
2527  /*
2528  * send ...
2529  * leave
2530  * =>
2531  * send ..., ... | VM_CALL_TAILCALL, ...
2532  * leave # unreachable
2533  */
2534  INSN *piobj = NULL;
2535  if (iobj->link.next) {
2536  LINK_ELEMENT *next = iobj->link.next;
2537  do {
2538  if (!IS_INSN(next)) {
2539  next = next->next;
2540  continue;
2541  }
2542  switch (INSN_OF(next)) {
2543  case BIN(nop):
2544  /*case BIN(trace):*/
2545  next = next->next;
2546  break;
2547  case BIN(jump):
2548  /* if cond
2549  * return tailcall
2550  * end
2551  */
2552  next = get_destination_insn((INSN *)next);
2553  break;
2554  case BIN(leave):
2555  piobj = iobj;
2556  default:
2557  next = NULL;
2558  break;
2559  }
2560  } while (next);
2561  }
2562 
2563  if (piobj) {
2564  struct rb_call_info *ci = (struct rb_call_info *)piobj->operands[0];
2565  if (IS_INSN_ID(piobj, send) || IS_INSN_ID(piobj, invokesuper)) {
2566  if (piobj->operands[2] == 0) { /* no blockiseq */
2567  ci->flag |= VM_CALL_TAILCALL;
2568  }
2569  }
2570  else {
2571  ci->flag |= VM_CALL_TAILCALL;
2572  }
2573  }
2574  }
2575 
2576  if (IS_INSN_ID(iobj, dup)) {
2577  if (IS_NEXT_INSN_ID(&iobj->link, setlocal)) {
2578  LINK_ELEMENT *set1 = iobj->link.next, *set2 = NULL;
2579  if (IS_NEXT_INSN_ID(set1, setlocal)) {
2580  set2 = set1->next;
2581  if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) &&
2582  OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) {
2583  REMOVE_ELEM(set1);
2584  REMOVE_ELEM(&iobj->link);
2585  }
2586  }
2587  else if (IS_NEXT_INSN_ID(set1, dup) &&
2588  IS_NEXT_INSN_ID(set1->next, setlocal)) {
2589  set2 = set1->next->next;
2590  if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) &&
2591  OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) {
2592  REMOVE_ELEM(set1->next);
2593  REMOVE_ELEM(set2);
2594  }
2595  }
2596  }
2597  }
2598 
2599  if (IS_INSN_ID(iobj, getlocal)) {
2600  if (IS_NEXT_INSN_ID(&iobj->link, setlocal)) {
2601  LINK_ELEMENT *set1 = iobj->link.next;
2602  if (OPERAND_AT(iobj, 0) == OPERAND_AT(set1, 0) &&
2603  OPERAND_AT(iobj, 1) == OPERAND_AT(set1, 1)) {
2604  REMOVE_ELEM(set1);
2605  REMOVE_ELEM(&iobj->link);
2606  }
2607  }
2608  }
2609 
2610  #define IS_TRACE_LINE(insn) \
2611  (IS_INSN_ID(insn, trace) && \
2612  OPERAND_AT(insn, 0) == INT2FIX(RUBY_EVENT_LINE))
2613  if (IS_TRACE_LINE(iobj) && iobj->link.prev && IS_INSN(iobj->link.prev)) {
2614  INSN *piobj = (INSN *)iobj->link.prev;
2615  if (IS_TRACE_LINE(piobj)) {
2616  REMOVE_ELEM(iobj->link.prev);
2617  }
2618  }
2619 
2620  return COMPILE_OK;
2621 }
2622 
2623 static int
2624 insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id)
2625 {
2626  iobj->insn_id = insn_id;
2627  iobj->operand_size = insn_len(insn_id) - 1;
2628 
2629  if (insn_id == BIN(opt_neq)) {
2630  VALUE *old_operands = iobj->operands;
2631  iobj->operand_size = 4;
2632  iobj->operands = (VALUE *)compile_data_alloc(iseq, iobj->operand_size * sizeof(VALUE));
2633  iobj->operands[0] = old_operands[0];
2634  iobj->operands[1] = Qfalse; /* CALL_CACHE */
2635  iobj->operands[2] = (VALUE)new_callinfo(iseq, idEq, 1, 0, NULL, FALSE);
2636  iobj->operands[3] = Qfalse; /* CALL_CACHE */
2637  }
2638 
2639  return COMPILE_OK;
2640 }
2641 
2642 static int
2643 iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
2644 {
2645  if (IS_INSN_ID(iobj, newarray) && iobj->link.next &&
2646  IS_INSN(iobj->link.next)) {
2647  /*
2648  * [a, b, ...].max/min -> a, b, c, opt_newarray_max/min
2649  */
2650  INSN *niobj = (INSN *)iobj->link.next;
2651  if (IS_INSN_ID(niobj, send)) {
2652  struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(niobj, 0);
2653  if ((ci->flag & VM_CALL_ARGS_SIMPLE) && ci->orig_argc == 0) {
2654  switch (ci->mid) {
2655  case idMax:
2656  iobj->insn_id = BIN(opt_newarray_max);
2657  REMOVE_ELEM(&niobj->link);
2658  return COMPILE_OK;
2659  case idMin:
2660  iobj->insn_id = BIN(opt_newarray_min);
2661  REMOVE_ELEM(&niobj->link);
2662  return COMPILE_OK;
2663  }
2664  }
2665  }
2666  }
2667 
2668  if (IS_INSN_ID(iobj, send)) {
2669  struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(iobj, 0);
2670  const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(iobj, 2);
2671 
2672 #define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
2673  if (ci->flag & VM_CALL_ARGS_SIMPLE) {
2674  switch (ci->orig_argc) {
2675  case 0:
2676  switch (ci->mid) {
2677  case idLength: SP_INSN(length); return COMPILE_OK;
2678  case idSize: SP_INSN(size); return COMPILE_OK;
2679  case idEmptyP: SP_INSN(empty_p);return COMPILE_OK;
2680  case idSucc: SP_INSN(succ); return COMPILE_OK;
2681  case idNot: SP_INSN(not); return COMPILE_OK;
2682  }
2683  break;
2684  case 1:
2685  switch (ci->mid) {
2686  case idPLUS: SP_INSN(plus); return COMPILE_OK;
2687  case idMINUS: SP_INSN(minus); return COMPILE_OK;
2688  case idMULT: SP_INSN(mult); return COMPILE_OK;
2689  case idDIV: SP_INSN(div); return COMPILE_OK;
2690  case idMOD: SP_INSN(mod); return COMPILE_OK;
2691  case idEq: SP_INSN(eq); return COMPILE_OK;
2692  case idNeq: SP_INSN(neq); return COMPILE_OK;
2693  case idLT: SP_INSN(lt); return COMPILE_OK;
2694  case idLE: SP_INSN(le); return COMPILE_OK;
2695  case idGT: SP_INSN(gt); return COMPILE_OK;
2696  case idGE: SP_INSN(ge); return COMPILE_OK;
2697  case idLTLT: SP_INSN(ltlt); return COMPILE_OK;
2698  case idAREF: SP_INSN(aref); return COMPILE_OK;
2699  }
2700  break;
2701  case 2:
2702  switch (ci->mid) {
2703  case idASET: SP_INSN(aset); return COMPILE_OK;
2704  }
2705  break;
2706  }
2707  }
2708 
2709  if ((ci->flag & VM_CALL_ARGS_BLOCKARG) == 0 && blockiseq == NULL) {
2710  iobj->insn_id = BIN(opt_send_without_block);
2711  iobj->operand_size = insn_len(iobj->insn_id) - 1;
2712  }
2713  }
2714 #undef SP_INSN
2715 
2716  return COMPILE_OK;
2717 }
2718 
2719 static inline int
2720 tailcallable_p(rb_iseq_t *iseq)
2721 {
2722  switch (iseq->body->type) {
2723  case ISEQ_TYPE_TOP:
2724  case ISEQ_TYPE_EVAL:
2725  case ISEQ_TYPE_MAIN:
2726  /* not tail callable because cfp will be over popped */
2727  case ISEQ_TYPE_RESCUE:
2728  case ISEQ_TYPE_ENSURE:
2729  /* rescue block can't tail call because of errinfo */
2730  return FALSE;
2731  default:
2732  return TRUE;
2733  }
2734 }
2735 
2736 static int
2737 iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
2738 {
2739  LINK_ELEMENT *list;
2740  const int do_peepholeopt = ISEQ_COMPILE_DATA(iseq)->option->peephole_optimization;
2741  const int do_tailcallopt = tailcallable_p(iseq) &&
2742  ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization;
2743  const int do_si = ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction;
2744  const int do_ou = ISEQ_COMPILE_DATA(iseq)->option->operands_unification;
2745  int rescue_level = 0;
2746  int tailcallopt = do_tailcallopt;
2747 
2748  list = FIRST_ELEMENT(anchor);
2749 
2750  while (list) {
2751  if (IS_INSN(list)) {
2752  if (do_peepholeopt) {
2753  iseq_peephole_optimize(iseq, list, tailcallopt);
2754  }
2755  if (do_si) {
2756  iseq_specialized_instruction(iseq, (INSN *)list);
2757  }
2758  if (do_ou) {
2759  insn_operands_unification((INSN *)list);
2760  }
2761  }
2762  if (IS_LABEL(list)) {
2763  switch (((LABEL *)list)->rescued) {
2764  case LABEL_RESCUE_BEG:
2765  rescue_level++;
2766  tailcallopt = FALSE;
2767  break;
2768  case LABEL_RESCUE_END:
2769  if (!--rescue_level) tailcallopt = do_tailcallopt;
2770  break;
2771  }
2772  }
2773  list = list->next;
2774  }
2775  return COMPILE_OK;
2776 }
2777 
2778 #if OPT_INSTRUCTIONS_UNIFICATION
2779 static INSN *
2780 new_unified_insn(rb_iseq_t *iseq,
2781  int insn_id, int size, LINK_ELEMENT *seq_list)
2782 {
2783  INSN *iobj = 0;
2784  LINK_ELEMENT *list = seq_list;
2785  int i, argc = 0;
2786  VALUE *operands = 0, *ptr = 0;
2787 
2788 
2789  /* count argc */
2790  for (i = 0; i < size; i++) {
2791  iobj = (INSN *)list;
2792  argc += iobj->operand_size;
2793  list = list->next;
2794  }
2795 
2796  if (argc > 0) {
2797  ptr = operands =
2798  (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * argc);
2799  }
2800 
2801  /* copy operands */
2802  list = seq_list;
2803  for (i = 0; i < size; i++) {
2804  iobj = (INSN *)list;
2805  MEMCPY(ptr, iobj->operands, VALUE, iobj->operand_size);
2806  ptr += iobj->operand_size;
2807  list = list->next;
2808  }
2809 
2810  return new_insn_core(iseq, iobj->line_no, insn_id, argc, operands);
2811 }
2812 #endif
2813 
2814 /*
2815  * This scheme can get more performance if do this optimize with
2816  * label address resolving.
2817  * It's future work (if compile time was bottle neck).
2818  */
2819 static int
2820 iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
2821 {
2822 #if OPT_INSTRUCTIONS_UNIFICATION
2823  LINK_ELEMENT *list;
2824  INSN *iobj, *niobj;
2825  int id, k;
2826  intptr_t j;
2827 
2828  list = FIRST_ELEMENT(anchor);
2829  while (list) {
2830  if (IS_INSN(list)) {
2831  iobj = (INSN *)list;
2832  id = iobj->insn_id;
2833  if (unified_insns_data[id] != 0) {
2834  const int *const *entry = unified_insns_data[id];
2835  for (j = 1; j < (intptr_t)entry[0]; j++) {
2836  const int *unified = entry[j];
2837  LINK_ELEMENT *li = list->next;
2838  for (k = 2; k < unified[1]; k++) {
2839  if (!IS_INSN(li) ||
2840  ((INSN *)li)->insn_id != unified[k]) {
2841  goto miss;
2842  }
2843  li = li->next;
2844  }
2845  /* matched */
2846  niobj =
2847  new_unified_insn(iseq, unified[0], unified[1] - 1,
2848  list);
2849 
2850  /* insert to list */
2851  niobj->link.prev = (LINK_ELEMENT *)iobj->link.prev;
2852  niobj->link.next = li;
2853  if (li) {
2854  li->prev = (LINK_ELEMENT *)niobj;
2855  }
2856 
2857  list->prev->next = (LINK_ELEMENT *)niobj;
2858  list = (LINK_ELEMENT *)niobj;
2859  break;
2860  miss:;
2861  }
2862  }
2863  }
2864  list = list->next;
2865  }
2866 #endif
2867  return COMPILE_OK;
2868 }
2869 
2870 #if OPT_STACK_CACHING
2871 
2872 #define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)]
2873 #define SC_NEXT(insn) sc_insn_next[(insn)]
2874 
2875 #include "opt_sc.inc"
2876 
2877 static int
2878 insn_set_sc_state(rb_iseq_t *iseq, const LINK_ELEMENT *anchor, INSN *iobj, int state)
2879 {
2880  int nstate;
2881  int insn_id;
2882 
2883  insn_id = iobj->insn_id;
2884  iobj->insn_id = SC_INSN(insn_id, state);
2885  nstate = SC_NEXT(iobj->insn_id);
2886 
2887  if (insn_id == BIN(jump) ||
2888  insn_id == BIN(branchif) || insn_id == BIN(branchunless)) {
2889  LABEL *lobj = (LABEL *)OPERAND_AT(iobj, 0);
2890 
2891  if (lobj->sc_state != 0) {
2892  if (lobj->sc_state != nstate) {
2893  BADINSN_DUMP(anchor, iobj, lobj);
2894  COMPILE_ERROR(iseq, iobj->line_no,
2895  "insn_set_sc_state error: %d at "LABEL_FORMAT
2896  ", %d expected\n",
2897  lobj->sc_state, lobj->label_no, nstate);
2898  return COMPILE_NG;
2899  }
2900  }
2901  else {
2902  lobj->sc_state = nstate;
2903  }
2904  if (insn_id == BIN(jump)) {
2905  nstate = SCS_XX;
2906  }
2907  }
2908  else if (insn_id == BIN(leave)) {
2909  nstate = SCS_XX;
2910  }
2911 
2912  return nstate;
2913 }
2914 
2915 static int
2916 label_set_sc_state(LABEL *lobj, int state)
2917 {
2918  if (lobj->sc_state != 0) {
2919  if (lobj->sc_state != state) {
2920  state = lobj->sc_state;
2921  }
2922  }
2923  else {
2924  lobj->sc_state = state;
2925  }
2926 
2927  return state;
2928 }
2929 
2930 
2931 #endif
2932 
2933 static int
2934 iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
2935 {
2936 #if OPT_STACK_CACHING
2937  LINK_ELEMENT *list;
2938  int state, insn_id;
2939 
2940  /* initialize */
2941  state = SCS_XX;
2942  list = FIRST_ELEMENT(anchor);
2943  /* dump_disasm_list(list); */
2944 
2945  /* for each list element */
2946  while (list) {
2947  redo_point:
2948  switch (list->type) {
2949  case ISEQ_ELEMENT_INSN:
2950  {
2951  INSN *iobj = (INSN *)list;
2952  insn_id = iobj->insn_id;
2953 
2954  /* dump_disasm_list(list); */
2955 
2956  switch (insn_id) {
2957  case BIN(nop):
2958  {
2959  /* exception merge point */
2960  if (state != SCS_AX) {
2961  INSN *rpobj =
2962  new_insn_body(iseq, 0, BIN(reput), 0);
2963 
2964  /* replace this insn */
2965  REPLACE_ELEM(list, (LINK_ELEMENT *)rpobj);
2966  list = (LINK_ELEMENT *)rpobj;
2967  goto redo_point;
2968  }
2969  break;
2970  }
2971  case BIN(swap):
2972  {
2973  if (state == SCS_AB || state == SCS_BA) {
2974  state = (state == SCS_AB ? SCS_BA : SCS_AB);
2975 
2976  REMOVE_ELEM(list);
2977  list = list->next;
2978  goto redo_point;
2979  }
2980  break;
2981  }
2982  case BIN(pop):
2983  {
2984  switch (state) {
2985  case SCS_AX:
2986  case SCS_BX:
2987  state = SCS_XX;
2988  break;
2989  case SCS_AB:
2990  state = SCS_AX;
2991  break;
2992  case SCS_BA:
2993  state = SCS_BX;
2994  break;
2995  case SCS_XX:
2996  goto normal_insn;
2997  default:
2998  COMPILE_ERROR(iseq, iobj->line_no,
2999  "unreachable");
3000  return COMPILE_NG;
3001  }
3002  /* remove useless pop */
3003  REMOVE_ELEM(list);
3004  list = list->next;
3005  goto redo_point;
3006  }
3007  default:;
3008  /* none */
3009  } /* end of switch */
3010  normal_insn:
3011  state = insn_set_sc_state(iseq, anchor, iobj, state);
3012  break;
3013  }
3014  case ISEQ_ELEMENT_LABEL:
3015  {
3016  LABEL *lobj;
3017  lobj = (LABEL *)list;
3018 
3019  state = label_set_sc_state(lobj, state);
3020  }
3021  default:
3022  break;
3023  }
3024  list = list->next;
3025  }
3026 #endif
3027  return COMPILE_OK;
3028 }
3029 
3030 static int
3031 compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int *cntp)
3032 {
3033  NODE *list = node->nd_next;
3034  VALUE lit = node->nd_lit;
3035  LINK_ELEMENT *first_lit = 0;
3036  int cnt = 0;
3037 
3038  debugp_param("nd_lit", lit);
3039  if (!NIL_P(lit)) {
3040  cnt++;
3041  if (!RB_TYPE_P(lit, T_STRING)) {
3042  COMPILE_ERROR(ERROR_ARGS "dstr: must be string: %s",
3043  rb_builtin_type_name(TYPE(lit)));
3044  return COMPILE_NG;
3045  }
3046  lit = node->nd_lit = rb_fstring(lit);
3047  ADD_INSN1(ret, nd_line(node), putobject, lit);
3048  if (RSTRING_LEN(lit) == 0) first_lit = LAST_ELEMENT(ret);
3049  }
3050 
3051  while (list) {
3052  node = list->nd_head;
3053  if (nd_type(node) == NODE_STR) {
3054  node->nd_lit = rb_fstring(node->nd_lit);
3055  ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit);
3056  lit = Qnil;
3057  }
3058  else {
3059  CHECK(COMPILE(ret, "each string", node));
3060  }
3061  cnt++;
3062  list = list->nd_next;
3063  }
3064  if (NIL_P(lit) && first_lit) {
3065  REMOVE_ELEM(first_lit);
3066  --cnt;
3067  }
3068  *cntp = cnt;
3069 
3070  return COMPILE_OK;
3071 }
3072 
3073 static int
3074 compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
3075 {
3076  int cnt;
3077  CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
3078  ADD_INSN1(ret, nd_line(node), concatstrings, INT2FIX(cnt));
3079  return COMPILE_OK;
3080 }
3081 
3082 static int
3083 compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
3084 {
3085  int cnt;
3086  CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
3087  ADD_INSN2(ret, nd_line(node), toregexp, INT2FIX(node->nd_cflag), INT2FIX(cnt));
3088  return COMPILE_OK;
3089 }
3090 
3091 static int
3092 compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int again,
3093  LABEL *then_label, LABEL *else_label)
3094 {
3095  const int line = nd_line(node);
3096  LABEL *lend = NEW_LABEL(line);
3097  rb_num_t cnt = ISEQ_FLIP_CNT_INCREMENT(iseq->body->local_iseq)
3099  VALUE key = INT2FIX(cnt);
3100 
3101  ADD_INSN2(ret, line, getspecial, key, INT2FIX(0));
3102  ADD_INSNL(ret, line, branchif, lend);
3103 
3104  /* *flip == 0 */
3105  CHECK(COMPILE(ret, "flip2 beg", node->nd_beg));
3106  ADD_INSNL(ret, line, branchunless, else_label);
3107  ADD_INSN1(ret, line, putobject, Qtrue);
3108  ADD_INSN1(ret, line, setspecial, key);
3109  if (!again) {
3110  ADD_INSNL(ret, line, jump, then_label);
3111  }
3112 
3113  /* *flip == 1 */
3114  ADD_LABEL(ret, lend);
3115  CHECK(COMPILE(ret, "flip2 end", node->nd_end));
3116  ADD_INSNL(ret, line, branchunless, then_label);
3117  ADD_INSN1(ret, line, putobject, Qfalse);
3118  ADD_INSN1(ret, line, setspecial, key);
3119  ADD_INSNL(ret, line, jump, then_label);
3120 
3121  return COMPILE_OK;
3122 }
3123 
3124 static int
3125 compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *cond,
3126  LABEL *then_label, LABEL *else_label)
3127 {
3128  again:
3129  switch (nd_type(cond)) {
3130  case NODE_AND:
3131  {
3132  LABEL *label = NEW_LABEL(nd_line(cond));
3133  CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, label,
3134  else_label));
3135  if (!label->refcnt) break;
3136  ADD_LABEL(ret, label);
3137  cond = cond->nd_2nd;
3138  goto again;
3139  }
3140  case NODE_OR:
3141  {
3142  LABEL *label = NEW_LABEL(nd_line(cond));
3143  CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, then_label,
3144  label));
3145  if (!label->refcnt) break;
3146  ADD_LABEL(ret, label);
3147  cond = cond->nd_2nd;
3148  goto again;
3149  }
3150  case NODE_LIT: /* NODE_LIT is always true */
3151  case NODE_TRUE:
3152  case NODE_STR:
3153  case NODE_ZARRAY:
3154  case NODE_LAMBDA:
3155  /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
3156  ADD_INSNL(ret, nd_line(cond), jump, then_label);
3157  break;
3158  case NODE_FALSE:
3159  case NODE_NIL:
3160  /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
3161  ADD_INSNL(ret, nd_line(cond), jump, else_label);
3162  break;
3163  case NODE_FLIP2:
3164  CHECK(compile_flip_flop(iseq, ret, cond, TRUE, then_label, else_label));
3165  break;
3166  case NODE_FLIP3:
3167  CHECK(compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label));
3168  break;
3169  case NODE_DEFINED:
3170  CHECK(compile_defined_expr(iseq, ret, cond, Qfalse));
3171  goto branch;
3172  default:
3173  CHECK(COMPILE(ret, "branch condition", cond));
3174  branch:
3175  ADD_INSNL(ret, nd_line(cond), branchunless, else_label);
3176  ADD_INSNL(ret, nd_line(cond), jump, then_label);
3177  break;
3178  }
3179  return COMPILE_OK;
3180 }
3181 
3182 static int
3183 compile_array_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
3184  const NODE *const root_node,
3185  struct rb_call_info_kw_arg **const kw_arg_ptr,
3186  unsigned int *flag)
3187 {
3188  if (kw_arg_ptr == NULL) return FALSE;
3189 
3190  if (nd_type(root_node) == NODE_HASH && root_node->nd_head && nd_type(root_node->nd_head) == NODE_ARRAY) {
3191  NODE *node = root_node->nd_head;
3192 
3193  while (node) {
3194  NODE *key_node = node->nd_head;
3195 
3196  assert(nd_type(node) == NODE_ARRAY);
3197  if (!key_node) {
3198  if (flag && !root_node->nd_alen) *flag |= VM_CALL_KW_SPLAT;
3199  return FALSE;
3200  }
3201  else if (nd_type(key_node) == NODE_LIT && RB_TYPE_P(key_node->nd_lit, T_SYMBOL)) {
3202  /* can be keywords */
3203  }
3204  else {
3205  return FALSE;
3206  }
3207  node = node->nd_next; /* skip value node */
3208  node = node->nd_next;
3209  }
3210 
3211  /* may be keywords */
3212  node = root_node->nd_head;
3213  {
3214  int len = (int)node->nd_alen / 2;
3215  struct rb_call_info_kw_arg *kw_arg = (struct rb_call_info_kw_arg *)ruby_xmalloc(sizeof(struct rb_call_info_kw_arg) + sizeof(VALUE) * (len - 1));
3216  VALUE *keywords = kw_arg->keywords;
3217  int i = 0;
3218  kw_arg->keyword_len = len;
3219 
3220  *kw_arg_ptr = kw_arg;
3221 
3222  for (i=0; node != NULL; i++, node = node->nd_next->nd_next) {
3223  NODE *key_node = node->nd_head;
3224  NODE *val_node = node->nd_next->nd_head;
3225  keywords[i] = key_node->nd_lit;
3226  COMPILE(ret, "keyword values", val_node);
3227  }
3228  assert(i == len);
3229  return TRUE;
3230  }
3231  }
3232  return FALSE;
3233 }
3234 
3239 };
3240 
3241 static inline int
3242 static_literal_node_p(NODE *node)
3243 {
3244  node = node->nd_head;
3245  switch (nd_type(node)) {
3246  case NODE_LIT:
3247  case NODE_NIL:
3248  case NODE_TRUE:
3249  case NODE_FALSE:
3250  return TRUE;
3251  default:
3252  return FALSE;
3253  }
3254 }
3255 
3256 static inline VALUE
3257 static_literal_value(NODE *node)
3258 {
3259  node = node->nd_head;
3260  switch (nd_type(node)) {
3261  case NODE_NIL:
3262  return Qnil;
3263  case NODE_TRUE:
3264  return Qtrue;
3265  case NODE_FALSE:
3266  return Qfalse;
3267  default:
3268  return node->nd_lit;
3269  }
3270 }
3271 
3272 static int
3273 compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE* node_root,
3274  enum compile_array_type_t type, struct rb_call_info_kw_arg **keywords_ptr,
3275  unsigned int *flag, int popped)
3276 {
3277  NODE *node = node_root;
3278  int line = (int)nd_line(node);
3279  int len = 0;
3280 
3281  if (nd_type(node) == NODE_ZARRAY) {
3282  if (!popped) {
3283  switch (type) {
3284  case COMPILE_ARRAY_TYPE_ARRAY: ADD_INSN1(ret, line, newarray, INT2FIX(0)); break;
3285  case COMPILE_ARRAY_TYPE_HASH: ADD_INSN1(ret, line, newhash, INT2FIX(0)); break;
3286  case COMPILE_ARRAY_TYPE_ARGS: /* do nothing */ break;
3287  }
3288  }
3289  }
3290  else {
3291  int opt_p = 1;
3292  int first = 1, i;
3293 
3294  while (node) {
3295  NODE *start_node = node, *end_node;
3296  NODE *kw = 0;
3297  const int max = 0x100;
3298  DECL_ANCHOR(anchor);
3299  INIT_ANCHOR(anchor);
3300 
3301  for (i=0; i<max && node; i++, len++, node = node->nd_next) {
3302  if (CPDEBUG > 0) {
3303  EXPECT_NODE("compile_array", node, NODE_ARRAY, -1);
3304  }
3305 
3306  if (type != COMPILE_ARRAY_TYPE_ARRAY && !node->nd_head) {
3307  kw = node->nd_next;
3308  node = 0;
3309  if (kw) {
3310  opt_p = 0;
3311  node = kw->nd_next;
3312  kw = kw->nd_head;
3313  }
3314  break;
3315  }
3316  if (opt_p && !static_literal_node_p(node)) {
3317  opt_p = 0;
3318  }
3319 
3320  if (type == COMPILE_ARRAY_TYPE_ARGS &&
3321  node->nd_next == NULL /* last node */ &&
3322  compile_array_keyword_arg(iseq, anchor, node->nd_head, keywords_ptr, flag)) {
3323  len--;
3324  }
3325  else {
3326  COMPILE_(anchor, "array element", node->nd_head, popped);
3327  }
3328  }
3329 
3330  if (opt_p && type != COMPILE_ARRAY_TYPE_ARGS) {
3331  if (!popped) {
3332  VALUE ary = rb_ary_tmp_new(i);
3333 
3334  end_node = node;
3335  node = start_node;
3336 
3337  while (node != end_node) {
3338  rb_ary_push(ary, static_literal_value(node));
3339  node = node->nd_next;
3340  }
3341  while (node && node->nd_next &&
3342  static_literal_node_p(node) &&
3343  static_literal_node_p(node->nd_next)) {
3344  VALUE elem[2];
3345  elem[0] = static_literal_value(node);
3346  elem[1] = static_literal_value(node->nd_next);
3347  rb_ary_cat(ary, elem, 2);
3348  node = node->nd_next->nd_next;
3349  len++;
3350  }
3351 
3352  OBJ_FREEZE(ary);
3353 
3354  iseq_add_mark_object_compile_time(iseq, ary);
3355 
3356  if (first) {
3357  first = 0;
3358  if (type == COMPILE_ARRAY_TYPE_ARRAY) {
3359  ADD_INSN1(ret, line, duparray, ary);
3360  }
3361  else { /* COMPILE_ARRAY_TYPE_HASH */
3362  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
3363  ADD_INSN1(ret, line, putobject, ary);
3364  ADD_SEND(ret, line, id_core_hash_from_ary, INT2FIX(1));
3365  }
3366  }
3367  else {
3368  if (type == COMPILE_ARRAY_TYPE_ARRAY) {
3369  ADD_INSN1(ret, line, putobject, ary);
3370  ADD_INSN(ret, line, concatarray);
3371  }
3372  else {
3373 #if 0
3374  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
3375  ADD_INSN1(ret, line, putobject, ary);
3376  ADD_SEND(ret, line, id_core_hash_merge_ary, INT2FIX(1));
3377  /* wrong number of arguments -----------------------^ */
3378 #else
3379  COMPILE_ERROR(ERROR_ARGS "core#hash_merge_ary");
3380  return -1;
3381 #endif
3382  }
3383  }
3384  }
3385  }
3386  else {
3387  if (!popped) {
3388  switch (type) {
3390  ADD_INSN1(anchor, line, newarray, INT2FIX(i));
3391 
3392  if (first) {
3393  first = 0;
3394  }
3395  else {
3396  ADD_INSN(anchor, line, concatarray);
3397  }
3398 
3399  APPEND_LIST(ret, anchor);
3400  break;
3402  if (i > 0) {
3403  if (first) {
3404  ADD_INSN1(anchor, line, newhash, INT2FIX(i));
3405  APPEND_LIST(ret, anchor);
3406  }
3407  else {
3408  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
3409  ADD_INSN(ret, line, swap);
3410  APPEND_LIST(ret, anchor);
3411  ADD_SEND(ret, line, id_core_hash_merge_ptr, INT2FIX(i + 1));
3412  }
3413  }
3414  if (kw) {
3415  VALUE nhash = (i > 0 || !first) ? INT2FIX(2) : INT2FIX(1);
3416  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
3417  if (i > 0 || !first) ADD_INSN(ret, line, swap);
3418  COMPILE(ret, "keyword splat", kw);
3419  ADD_SEND(ret, line, id_core_hash_merge_kwd, nhash);
3420  if (nhash == INT2FIX(1)) ADD_SEND(ret, line, rb_intern("dup"), INT2FIX(0));
3421  }
3422  first = 0;
3423  break;
3425  APPEND_LIST(ret, anchor);
3426  break;
3427  }
3428  }
3429  else {
3430  /* popped */
3431  APPEND_LIST(ret, anchor);
3432  }
3433  }
3434  }
3435  }
3436  return len;
3437 }
3438 
3439 static VALUE
3440 case_when_optimizable_literal(NODE *node)
3441 {
3442  switch (nd_type(node)) {
3443  case NODE_LIT: {
3444  VALUE v = node->nd_lit;
3445  double ival;
3446  if (RB_TYPE_P(v, T_FLOAT) &&
3447  modf(RFLOAT_VALUE(v), &ival) == 0.0) {
3448  return FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival);
3449  }
3450  if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) {
3451  return v;
3452  }
3453  break;
3454  }
3455  case NODE_NIL:
3456  return Qnil;
3457  case NODE_TRUE:
3458  return Qtrue;
3459  case NODE_FALSE:
3460  return Qfalse;
3461  case NODE_STR:
3462  return node->nd_lit = rb_fstring(node->nd_lit);
3463  }
3464  return Qundef;
3465 }
3466 
3467 static int
3468 when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, NODE *vals,
3469  LABEL *l1, int only_special_literals, VALUE literals)
3470 {
3471  while (vals) {
3472  NODE* val = vals->nd_head;
3473  VALUE lit = case_when_optimizable_literal(val);
3474 
3475  if (lit == Qundef) {
3476  only_special_literals = 0;
3477  }
3478  else {
3479  if (rb_hash_lookup(literals, lit) != Qnil) {
3480  VALUE file = rb_iseq_path(iseq);
3482  "duplicated when clause is ignored");
3483  }
3484  else {
3485  rb_hash_aset(literals, lit, (VALUE)(l1) | 1);
3486  }
3487  }
3488 
3489  ADD_INSN(cond_seq, nd_line(val), dup); /* dup target */
3490 
3491  if (nd_type(val) == NODE_STR) {
3492  val->nd_lit = rb_fstring(val->nd_lit);
3493  debugp_param("nd_lit", val->nd_lit);
3494  ADD_INSN1(cond_seq, nd_line(val), putobject, val->nd_lit);
3495  }
3496  else {
3497  COMPILE(cond_seq, "when cond", val);
3498  }
3499 
3500  ADD_INSN1(cond_seq, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
3501  ADD_INSNL(cond_seq, nd_line(val), branchif, l1);
3502  vals = vals->nd_next;
3503  }
3504  return only_special_literals;
3505 }
3506 
3507 static int
3508 compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
3509 {
3510  switch (nd_type(node)) {
3511  case NODE_ATTRASGN: {
3512  INSN *iobj;
3513  struct rb_call_info *ci;
3514  VALUE dupidx;
3515  int line = nd_line(node);
3516 
3517  CHECK(COMPILE_POPPED(ret, "masgn lhs (NODE_ATTRASGN)", node));
3518 
3519  iobj = (INSN *)get_prev_insn((INSN *)LAST_ELEMENT(ret)); /* send insn */
3520  ci = (struct rb_call_info *)iobj->operands[0];
3521  ci->orig_argc += 1;
3522  dupidx = INT2FIX(ci->orig_argc);
3523 
3524  INSERT_BEFORE_INSN1(iobj, line, topn, dupidx);
3525  if (ci->flag & VM_CALL_ARGS_SPLAT) {
3526  --ci->orig_argc;
3527  INSERT_BEFORE_INSN1(iobj, line, newarray, INT2FIX(1));
3528  INSERT_BEFORE_INSN(iobj, line, concatarray);
3529  }
3530  ADD_INSN(ret, line, pop); /* result */
3531  break;
3532  }
3533  case NODE_MASGN: {
3534  DECL_ANCHOR(anchor);
3535  INIT_ANCHOR(anchor);
3536  CHECK(COMPILE_POPPED(anchor, "nest masgn lhs", node));
3537  REMOVE_ELEM(FIRST_ELEMENT(anchor));
3538  ADD_SEQ(ret, anchor);
3539  break;
3540  }
3541  default: {
3542  DECL_ANCHOR(anchor);
3543  INIT_ANCHOR(anchor);
3544  CHECK(COMPILE_POPPED(anchor, "masgn lhs", node));
3545  REMOVE_ELEM(FIRST_ELEMENT(anchor));
3546  ADD_SEQ(ret, anchor);
3547  }
3548  }
3549 
3550  return COMPILE_OK;
3551 }
3552 
3553 static int
3554 compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *lhsn)
3555 {
3556  if (lhsn) {
3557  CHECK(compile_massign_opt_lhs(iseq, ret, lhsn->nd_next));
3558  CHECK(compile_massign_lhs(iseq, ret, lhsn->nd_head));
3559  }
3560  return COMPILE_OK;
3561 }
3562 
3563 static int
3564 compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
3565  NODE *rhsn, NODE *orig_lhsn)
3566 {
3567  VALUE mem[64];
3568  const int memsize = numberof(mem);
3569  int memindex = 0;
3570  int llen = 0, rlen = 0;
3571  int i;
3572  NODE *lhsn = orig_lhsn;
3573 
3574 #define MEMORY(v) { \
3575  int i; \
3576  if (memindex == memsize) return 0; \
3577  for (i=0; i<memindex; i++) { \
3578  if (mem[i] == (v)) return 0; \
3579  } \
3580  mem[memindex++] = (v); \
3581 }
3582 
3583  if (rhsn == 0 || nd_type(rhsn) != NODE_ARRAY) {
3584  return 0;
3585  }
3586 
3587  while (lhsn) {
3588  NODE *ln = lhsn->nd_head;
3589  switch (nd_type(ln)) {
3590  case NODE_LASGN:
3591  MEMORY(ln->nd_vid);
3592  break;
3593  case NODE_DASGN:
3594  case NODE_DASGN_CURR:
3595  case NODE_IASGN:
3596  case NODE_CVASGN:
3597  MEMORY(ln->nd_vid);
3598  break;
3599  default:
3600  return 0;
3601  }
3602  lhsn = lhsn->nd_next;
3603  llen++;
3604  }
3605 
3606  while (rhsn) {
3607  if (llen <= rlen) {
3608  COMPILE_POPPED(ret, "masgn val (popped)", rhsn->nd_head);
3609  }
3610  else {
3611  COMPILE(ret, "masgn val", rhsn->nd_head);
3612  }
3613  rhsn = rhsn->nd_next;
3614  rlen++;
3615  }
3616 
3617  if (llen > rlen) {
3618  for (i=0; i<llen-rlen; i++) {
3619  ADD_INSN(ret, nd_line(orig_lhsn), putnil);
3620  }
3621  }
3622 
3623  compile_massign_opt_lhs(iseq, ret, orig_lhsn);
3624  return 1;
3625 }
3626 
3627 static void
3628 adjust_stack(rb_iseq_t *iseq, LINK_ANCHOR *const ret, int line, int rlen, int llen)
3629 {
3630  if (rlen < llen) {
3631  do {ADD_INSN(ret, line, putnil);} while (++rlen < llen);
3632  }
3633  else if (rlen > llen) {
3634  do {ADD_INSN(ret, line, pop);} while (--rlen > llen);
3635  }
3636 }
3637 
3638 static int
3639 compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
3640 {
3641  NODE *rhsn = node->nd_value;
3642  NODE *splatn = node->nd_args;
3643  NODE *lhsn = node->nd_head;
3644  int lhs_splat = (splatn && (VALUE)splatn != (VALUE)-1) ? 1 : 0;
3645 
3646  if (!popped || splatn || !compile_massign_opt(iseq, ret, rhsn, lhsn)) {
3647  int llen = 0;
3648  int expand = 1;
3649  DECL_ANCHOR(lhsseq);
3650 
3651  INIT_ANCHOR(lhsseq);
3652 
3653  while (lhsn) {
3654  CHECK(compile_massign_lhs(iseq, lhsseq, lhsn->nd_head));
3655  llen += 1;
3656  lhsn = lhsn->nd_next;
3657  }
3658 
3659  COMPILE(ret, "normal masgn rhs", rhsn);
3660 
3661  if (!popped) {
3662  ADD_INSN(ret, nd_line(node), dup);
3663  }
3664  else if (!lhs_splat) {
3665  INSN *last = (INSN*)ret->last;
3666  if (IS_INSN(&last->link) &&
3667  IS_INSN_ID(last, newarray) &&
3668  last->operand_size == 1) {
3669  int rlen = FIX2INT(OPERAND_AT(last, 0));
3670  /* special case: assign to aset or attrset */
3671  if (llen == 2) {
3672  POP_ELEMENT(ret);
3673  adjust_stack(iseq, ret, nd_line(node), rlen, llen);
3674  ADD_INSN(ret, nd_line(node), swap);
3675  expand = 0;
3676  }
3677  else if (llen > 2 && llen != rlen) {
3678  POP_ELEMENT(ret);
3679  adjust_stack(iseq, ret, nd_line(node), rlen, llen);
3680  ADD_INSN1(ret, nd_line(node), reverse, INT2FIX(llen));
3681  expand = 0;
3682  }
3683  else if (llen > 2) {
3684  last->insn_id = BIN(reverse);
3685  expand = 0;
3686  }
3687  }
3688  }
3689  if (expand) {
3690  ADD_INSN2(ret, nd_line(node), expandarray,
3691  INT2FIX(llen), INT2FIX(lhs_splat));
3692  }
3693  ADD_SEQ(ret, lhsseq);
3694 
3695  if (lhs_splat) {
3696  if (nd_type(splatn) == NODE_POSTARG) {
3697  /*a, b, *r, p1, p2 */
3698  NODE *postn = splatn->nd_2nd;
3699  NODE *restn = splatn->nd_1st;
3700  int num = (int)postn->nd_alen;
3701  int flag = 0x02 | (((VALUE)restn == (VALUE)-1) ? 0x00 : 0x01);
3702 
3703  ADD_INSN2(ret, nd_line(splatn), expandarray,
3704  INT2FIX(num), INT2FIX(flag));
3705 
3706  if ((VALUE)restn != (VALUE)-1) {
3707  CHECK(compile_massign_lhs(iseq, ret, restn));
3708  }
3709  while (postn) {
3710  CHECK(compile_massign_lhs(iseq, ret, postn->nd_head));
3711  postn = postn->nd_next;
3712  }
3713  }
3714  else {
3715  /* a, b, *r */
3716  CHECK(compile_massign_lhs(iseq, ret, splatn));
3717  }
3718  }
3719  }
3720  return COMPILE_OK;
3721 }
3722 
3723 static int
3724 compile_const_prefix(rb_iseq_t *iseq, NODE *node,
3725  LINK_ANCHOR *const pref, LINK_ANCHOR *const body)
3726 {
3727  switch (nd_type(node)) {
3728  case NODE_CONST:
3729  debugi("compile_const_prefix - colon", node->nd_vid);
3730  ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_vid));
3731  break;
3732  case NODE_COLON3:
3733  debugi("compile_const_prefix - colon3", node->nd_mid);
3734  ADD_INSN(body, nd_line(node), pop);
3735  ADD_INSN1(body, nd_line(node), putobject, rb_cObject);
3736  ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid));
3737  break;
3738  case NODE_COLON2:
3739  CHECK(compile_const_prefix(iseq, node->nd_head, pref, body));
3740  debugi("compile_const_prefix - colon2", node->nd_mid);
3741  ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid));
3742  break;
3743  default:
3744  CHECK(COMPILE(pref, "const colon2 prefix", node));
3745  break;
3746  }
3747  return COMPILE_OK;
3748 }
3749 
3750 static int
3751 compile_cpath(LINK_ANCHOR *const ret, rb_iseq_t *iseq, NODE *cpath)
3752 {
3753  if (nd_type(cpath) == NODE_COLON3) {
3754  /* toplevel class ::Foo */
3755  ADD_INSN1(ret, nd_line(cpath), putobject, rb_cObject);
3757  }
3758  else if (cpath->nd_head) {
3759  /* Bar::Foo */
3760  COMPILE(ret, "nd_else->nd_head", cpath->nd_head);
3762  }
3763  else {
3764  /* class at cbase Foo */
3765  ADD_INSN1(ret, nd_line(cpath), putspecialobject,
3767  return 0;
3768  }
3769 }
3770 
3771 #define private_recv_p(node) (nd_type((node)->nd_recv) == NODE_SELF)
3772 static int
3773 defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
3774  NODE *node, LABEL **lfinish, VALUE needstr);
3775 
3776 static int
3777 defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
3778  NODE *node, LABEL **lfinish, VALUE needstr)
3779 {
3780  enum defined_type expr_type = 0;
3781  enum node_type type;
3782 
3783  switch (type = nd_type(node)) {
3784 
3785  /* easy literals */
3786  case NODE_NIL:
3787  expr_type = DEFINED_NIL;
3788  break;
3789  case NODE_SELF:
3790  expr_type = DEFINED_SELF;
3791  break;
3792  case NODE_TRUE:
3793  expr_type = DEFINED_TRUE;
3794  break;
3795  case NODE_FALSE:
3796  expr_type = DEFINED_FALSE;
3797  break;
3798 
3799  case NODE_ARRAY:{
3800  NODE *vals = node;
3801 
3802  do {
3803  defined_expr0(iseq, ret, vals->nd_head, lfinish, Qfalse);
3804 
3805  if (!lfinish[1]) {
3806  lfinish[1] = NEW_LABEL(nd_line(node));
3807  }
3808  ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
3809  } while ((vals = vals->nd_next) != NULL);
3810  }
3811  case NODE_STR:
3812  case NODE_LIT:
3813  case NODE_ZARRAY:
3814  case NODE_AND:
3815  case NODE_OR:
3816  default:
3817  expr_type = DEFINED_EXPR;
3818  break;
3819 
3820  /* variables */
3821  case NODE_LVAR:
3822  case NODE_DVAR:
3823  expr_type = DEFINED_LVAR;
3824  break;
3825 
3826  case NODE_IVAR:
3827  ADD_INSN(ret, nd_line(node), putnil);
3828  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_IVAR),
3829  ID2SYM(node->nd_vid), needstr);
3830  return 1;
3831 
3832  case NODE_GVAR:
3833  ADD_INSN(ret, nd_line(node), putnil);
3834  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_GVAR),
3835  ID2SYM(node->nd_entry->id), needstr);
3836  return 1;
3837 
3838  case NODE_CVAR:
3839  ADD_INSN(ret, nd_line(node), putnil);
3840  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CVAR),
3841  ID2SYM(node->nd_vid), needstr);
3842  return 1;
3843 
3844  case NODE_CONST:
3845  ADD_INSN(ret, nd_line(node), putnil);
3846  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CONST),
3847  ID2SYM(node->nd_vid), needstr);
3848  return 1;
3849  case NODE_COLON2:
3850  if (!lfinish[1]) {
3851  lfinish[1] = NEW_LABEL(nd_line(node));
3852  }
3853  defined_expr0(iseq, ret, node->nd_head, lfinish, Qfalse);
3854  ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
3855  COMPILE(ret, "defined/colon2#nd_head", node->nd_head);
3856 
3857  ADD_INSN3(ret, nd_line(node), defined,
3858  (rb_is_const_id(node->nd_mid) ?
3860  ID2SYM(node->nd_mid), needstr);
3861  return 1;
3862  case NODE_COLON3:
3863  ADD_INSN1(ret, nd_line(node), putobject, rb_cObject);
3864  ADD_INSN3(ret, nd_line(node), defined,
3865  INT2FIX(DEFINED_CONST), ID2SYM(node->nd_mid), needstr);
3866  return 1;
3867 
3868  /* method dispatch */
3869  case NODE_CALL:
3870  case NODE_OPCALL:
3871  case NODE_VCALL:
3872  case NODE_FCALL:
3873  case NODE_ATTRASGN:{
3874  const int explicit_receiver =
3875  (type == NODE_CALL || type == NODE_OPCALL ||
3876  (type == NODE_ATTRASGN && !private_recv_p(node)));
3877 
3878  if (!lfinish[1] && (node->nd_args || explicit_receiver)) {
3879  lfinish[1] = NEW_LABEL(nd_line(node));
3880  }
3881  if (node->nd_args) {
3882  defined_expr0(iseq, ret, node->nd_args, lfinish, Qfalse);
3883  ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
3884  }
3885  if (explicit_receiver) {
3886  defined_expr0(iseq, ret, node->nd_recv, lfinish, Qfalse);
3887  ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
3888  COMPILE(ret, "defined/recv", node->nd_recv);
3889  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_METHOD),
3890  ID2SYM(node->nd_mid), needstr);
3891  }
3892  else {
3893  ADD_INSN(ret, nd_line(node), putself);
3894  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_FUNC),
3895  ID2SYM(node->nd_mid), needstr);
3896  }
3897  return 1;
3898  }
3899 
3900  case NODE_YIELD:
3901  ADD_INSN(ret, nd_line(node), putnil);
3902  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_YIELD), 0,
3903  needstr);
3904  return 1;
3905 
3906  case NODE_BACK_REF:
3907  case NODE_NTH_REF:
3908  ADD_INSN(ret, nd_line(node), putnil);
3909  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_REF),
3910  INT2FIX((node->nd_nth << 1) | (type == NODE_BACK_REF)),
3911  needstr);
3912  return 1;
3913 
3914  case NODE_SUPER:
3915  case NODE_ZSUPER:
3916  ADD_INSN(ret, nd_line(node), putnil);
3917  ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_ZSUPER), 0,
3918  needstr);
3919  return 1;
3920 
3921  case NODE_OP_ASGN1:
3922  case NODE_OP_ASGN2:
3923  case NODE_OP_ASGN_OR:
3924  case NODE_OP_ASGN_AND:
3925  case NODE_MASGN:
3926  case NODE_LASGN:
3927  case NODE_DASGN:
3928  case NODE_DASGN_CURR:
3929  case NODE_GASGN:
3930  case NODE_IASGN:
3931  case NODE_CDECL:
3932  case NODE_CVASGN:
3933  expr_type = DEFINED_ASGN;
3934  break;
3935  }
3936 
3937  if (expr_type) {
3938  if (needstr != Qfalse) {
3939  VALUE str = rb_iseq_defined_string(expr_type);
3940  ADD_INSN1(ret, nd_line(node), putobject, str);
3941  }
3942  else {
3943  ADD_INSN1(ret, nd_line(node), putobject, Qtrue);
3944  }
3945  return 1;
3946  }
3947  return 0;
3948 }
3949 
3950 static int
3951 defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
3952  NODE *node, LABEL **lfinish, VALUE needstr)
3953 {
3954  LINK_ELEMENT *lcur = ret->last;
3955  int done = defined_expr0(iseq, ret, node, lfinish, needstr);
3956  if (lfinish[1]) {
3957  int line = nd_line(node);
3958  LABEL *lstart = NEW_LABEL(line);
3959  LABEL *lend = NEW_LABEL(line);
3960  const rb_iseq_t *rescue = NEW_CHILD_ISEQ(NEW_NIL(),
3962  ("defined guard in "),
3963  iseq->body->location.label),
3964  ISEQ_TYPE_DEFINED_GUARD, 0);
3965  lstart->rescued = LABEL_RESCUE_BEG;
3966  lend->rescued = LABEL_RESCUE_END;
3967  APPEND_LABEL(ret, lcur, lstart);
3968  ADD_LABEL(ret, lend);
3969  ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]);
3970  }
3971  return done;
3972 }
3973 
3974 static int
3975 compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, VALUE needstr)
3976 {
3977  const int line = nd_line(node);
3978  if (!node->nd_head) {
3980  ADD_INSN1(ret, line, putobject, str);
3981  }
3982  else {
3983  LABEL *lfinish[2];
3984  LINK_ELEMENT *last = ret->last;
3985  lfinish[0] = NEW_LABEL(line);
3986  lfinish[1] = 0;
3987  defined_expr(iseq, ret, node->nd_head, lfinish, needstr);
3988  if (lfinish[1]) {
3989  INSERT_ELEM_NEXT(last, &new_insn_body(iseq, line, BIN(putnil), 0)->link);
3990  ADD_INSN(ret, line, swap);
3991  ADD_INSN(ret, line, pop);
3992  ADD_LABEL(ret, lfinish[1]);
3993  }
3994  ADD_LABEL(ret, lfinish[0]);
3995  }
3996  return COMPILE_OK;
3997 }
3998 
3999 static VALUE
4000 make_name_for_block(const rb_iseq_t *orig_iseq)
4001 {
4002  int level = 1;
4003  const rb_iseq_t *iseq = orig_iseq;
4004 
4005  if (orig_iseq->body->parent_iseq != 0) {
4006  while (orig_iseq->body->local_iseq != iseq) {
4007  if (iseq->body->type == ISEQ_TYPE_BLOCK) {
4008  level++;
4009  }
4010  iseq = iseq->body->parent_iseq;
4011  }
4012  }
4013 
4014  if (level == 1) {
4015  return rb_sprintf("block in %"PRIsVALUE, iseq->body->location.label);
4016  }
4017  else {
4018  return rb_sprintf("block (%d levels) in %"PRIsVALUE, level, iseq->body->location.label);
4019  }
4020 }
4021 
4022 static void
4023 push_ensure_entry(rb_iseq_t *iseq,
4025  struct ensure_range *er, NODE *node)
4026 {
4027  enl->ensure_node = node;
4028  enl->prev = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack; /* prev */
4029  enl->erange = er;
4030  ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl;
4031 }
4032 
4033 static void
4034 add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange,
4035  LABEL *lstart, LABEL *lend)
4036 {
4037  struct ensure_range *ne =
4038  compile_data_alloc(iseq, sizeof(struct ensure_range));
4039 
4040  while (erange->next != 0) {
4041  erange = erange->next;
4042  }
4043  ne->next = 0;
4044  ne->begin = lend;
4045  ne->end = erange->end;
4046  erange->end = lstart;
4047 
4048  erange->next = ne;
4049 }
4050 
4051 static void
4052 add_ensure_iseq(LINK_ANCHOR *const ret, rb_iseq_t *iseq, int is_return)
4053 {
4055  ISEQ_COMPILE_DATA(iseq)->ensure_node_stack;
4056  struct iseq_compile_data_ensure_node_stack *prev_enlp = enlp;
4057  DECL_ANCHOR(ensure);
4058 
4059  INIT_ANCHOR(ensure);
4060  while (enlp) {
4061  if (enlp->erange != NULL) {
4062  DECL_ANCHOR(ensure_part);
4063  LABEL *lstart = NEW_LABEL(0);
4064  LABEL *lend = NEW_LABEL(0);
4065  INIT_ANCHOR(ensure_part);
4066 
4067  add_ensure_range(iseq, enlp->erange, lstart, lend);
4068 
4069  ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enlp->prev;
4070  ADD_LABEL(ensure_part, lstart);
4071  COMPILE_POPPED(ensure_part, "ensure part", enlp->ensure_node);
4072  ADD_LABEL(ensure_part, lend);
4073  ADD_SEQ(ensure, ensure_part);
4074  }
4075  else {
4076  if (!is_return) {
4077  break;
4078  }
4079  }
4080  enlp = enlp->prev;
4081  }
4082  ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = prev_enlp;
4083  ADD_SEQ(ret, ensure);
4084 }
4085 
4086 static VALUE
4087 setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, NODE *argn,
4088  unsigned int *flag, struct rb_call_info_kw_arg **keywords)
4089 {
4090  VALUE argc = INT2FIX(0);
4091  int nsplat = 0;
4092  DECL_ANCHOR(arg_block);
4093  DECL_ANCHOR(args_splat);
4094 
4095  INIT_ANCHOR(arg_block);
4096  INIT_ANCHOR(args_splat);
4097  if (argn && nd_type(argn) == NODE_BLOCK_PASS) {
4098  COMPILE(arg_block, "block", argn->nd_body);
4099  *flag |= VM_CALL_ARGS_BLOCKARG;
4100  argn = argn->nd_head;
4101  }
4102 
4103  setup_argn:
4104  if (argn) {
4105  switch (nd_type(argn)) {
4106  case NODE_SPLAT: {
4107  COMPILE(args, "args (splat)", argn->nd_head);
4108  ADD_INSN1(args, nd_line(argn), splatarray, nsplat ? Qtrue : Qfalse);
4109  argc = INT2FIX(1);
4110  nsplat++;
4111  *flag |= VM_CALL_ARGS_SPLAT;
4112  break;
4113  }
4114  case NODE_ARGSCAT:
4115  case NODE_ARGSPUSH: {
4116  int next_is_array = (nd_type(argn->nd_head) == NODE_ARRAY);
4117  DECL_ANCHOR(tmp);
4118 
4119  INIT_ANCHOR(tmp);
4120  COMPILE(tmp, "args (cat: splat)", argn->nd_body);
4121  if (nd_type(argn) == NODE_ARGSCAT) {
4122  ADD_INSN1(tmp, nd_line(argn), splatarray, nsplat ? Qtrue : Qfalse);
4123  }
4124  else {
4125  ADD_INSN1(tmp, nd_line(argn), newarray, INT2FIX(1));
4126  }
4127  INSERT_LIST(args_splat, tmp);
4128  nsplat++;
4129  *flag |= VM_CALL_ARGS_SPLAT;
4130 
4131  if (next_is_array) {
4132  int len = compile_array(iseq, args, argn->nd_head, COMPILE_ARRAY_TYPE_ARGS, NULL, flag, FALSE);
4133  if (len < 0) return Qnil;
4134  argc = INT2FIX(len + 1);
4135  }
4136  else {
4137  argn = argn->nd_head;
4138  goto setup_argn;
4139  }
4140  break;
4141  }
4142  case NODE_ARRAY:
4143  {
4144  int len = compile_array(iseq, args, argn, COMPILE_ARRAY_TYPE_ARGS, keywords, flag, FALSE);
4145  if (len < 0) return Qnil;
4146  argc = INT2FIX(len);
4147  break;
4148  }
4149  default: {
4150  UNKNOWN_NODE("setup_arg", argn, Qnil);
4151  }
4152  }
4153  }
4154 
4155  if (nsplat > 1) {
4156  int i;
4157  for (i=1; i<nsplat; i++) {
4158  ADD_INSN(args_splat, nd_line(args), concatarray);
4159  }
4160  }
4161 
4162  if (!LIST_SIZE_ZERO(args_splat)) {
4163  ADD_SEQ(args, args_splat);
4164  }
4165 
4166  if (*flag & VM_CALL_ARGS_BLOCKARG) {
4167  ADD_SEQ(args, arg_block);
4168  }
4169  return argc;
4170 }
4171 
4172 static VALUE
4173 build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *body)
4174 {
4175  int line = nd_line(body);
4176  VALUE argc = INT2FIX(0);
4177  const rb_iseq_t *block = NEW_CHILD_ISEQ(body, make_name_for_block(iseq->body->parent_iseq), ISEQ_TYPE_BLOCK, line);
4178 
4179  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
4180  ADD_CALL_WITH_BLOCK(ret, line, id_core_set_postexe, argc, block);
4181  iseq_set_local_table(iseq, 0);
4182  return Qnil;
4183 }
4184 
4185 static void
4186 compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node)
4187 {
4188  NODE *vars;
4189  LINK_ELEMENT *last;
4190  int line = nd_line(node);
4191  LABEL *fail_label = NEW_LABEL(line), *end_label = NEW_LABEL(line);
4192 
4193 #if !(defined(NAMED_CAPTURE_BY_SVAR) && NAMED_CAPTURE_BY_SVAR-0)
4194  ADD_INSN1(ret, line, getglobal, ((VALUE)rb_global_entry(idBACKREF) | 1));
4195 #else
4196  ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */, INT2FIX(0));
4197 #endif
4198  ADD_INSN(ret, line, dup);
4199  ADD_INSNL(ret, line, branchunless, fail_label);
4200 
4201  for (vars = node; vars; vars = vars->nd_next) {
4202  INSN *cap;
4203  if (vars->nd_next) {
4204  ADD_INSN(ret, line, dup);
4205  }
4206  last = ret->last;
4207  COMPILE_POPPED(ret, "capture", vars->nd_head);
4208  last = last->next; /* putobject :var */
4209  cap = new_insn_send(iseq, line, idAREF, INT2FIX(1),
4210  NULL, INT2FIX(0), NULL);
4211  INSERT_ELEM_PREV(last->next, (LINK_ELEMENT *)cap);
4212 #if !defined(NAMED_CAPTURE_SINGLE_OPT) || NAMED_CAPTURE_SINGLE_OPT-0
4213  if (!vars->nd_next && vars == node) {
4214  /* only one name */
4215  DECL_ANCHOR(nom);
4216 
4217  INIT_ANCHOR(nom);
4218  ADD_INSNL(nom, line, jump, end_label);
4219  ADD_LABEL(nom, fail_label);
4220 # if 0 /* $~ must be MatchData or nil */
4221  ADD_INSN(nom, line, pop);
4222  ADD_INSN(nom, line, putnil);
4223 # endif
4224  ADD_LABEL(nom, end_label);
4225  (nom->last->next = cap->link.next)->prev = nom->last;
4226  (cap->link.next = nom->anchor.next)->prev = &cap->link;
4227  return;
4228  }
4229 #endif
4230  }
4231  ADD_INSNL(ret, line, jump, end_label);
4232  ADD_LABEL(ret, fail_label);
4233  ADD_INSN(ret, line, pop);
4234  for (vars = node; vars; vars = vars->nd_next) {
4235  last = ret->last;
4236  COMPILE_POPPED(ret, "capture", vars->nd_head);
4237  last = last->next; /* putobject :var */
4238  ((INSN*)last)->insn_id = BIN(putnil);
4239  ((INSN*)last)->operand_size = 0;
4240  }
4241  ADD_LABEL(ret, end_label);
4242 }
4243 
4244 static int
4245 number_literal_p(NODE *n)
4246 {
4247  return (n && nd_type(n) == NODE_LIT && RB_INTEGER_TYPE_P(n->nd_lit));
4248 }
4249 
4250 static int
4251 compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped, const enum node_type type)
4252 {
4253  NODE *node_body = type == NODE_IF ? node->nd_body : node->nd_else;
4254  NODE *node_else = type == NODE_IF ? node->nd_else : node->nd_body;
4255 
4256  const int line = nd_line(node);
4257  DECL_ANCHOR(cond_seq);
4258  DECL_ANCHOR(then_seq);
4259  DECL_ANCHOR(else_seq);
4260  LABEL *then_label, *else_label, *end_label;
4261  VALUE branches = 0;
4262 
4263  INIT_ANCHOR(cond_seq);
4264  INIT_ANCHOR(then_seq);
4265  INIT_ANCHOR(else_seq);
4266  then_label = NEW_LABEL(line);
4267  else_label = NEW_LABEL(line);
4268  end_label = 0;
4269 
4270  compile_branch_condition(iseq, cond_seq, node->nd_cond,
4271  then_label, else_label);
4272  CHECK(COMPILE_(then_seq, "then", node_body, popped));
4273  CHECK(COMPILE_(else_seq, "else", node_else, popped));
4274 
4275  ADD_SEQ(ret, cond_seq);
4276 
4277  if (then_label->refcnt && else_label->refcnt) {
4278  DECL_BRANCH_BASE(branches, line, type == NODE_IF ? "if" : "unless");
4279  }
4280 
4281  if (then_label->refcnt) {
4282  ADD_LABEL(ret, then_label);
4283  if (else_label->refcnt) {
4284  ADD_TRACE_BRANCH_COVERAGE(ret, node_body ? nd_line(node_body) : line, type == NODE_IF ? "then" : "else", branches);
4285  }
4286  ADD_SEQ(ret, then_seq);
4287  end_label = NEW_LABEL(line);
4288  ADD_INSNL(ret, line, jump, end_label);
4289  }
4290 
4291  if (else_label->refcnt) {
4292  ADD_LABEL(ret, else_label);
4293  if (then_label->refcnt) {
4294  ADD_TRACE_BRANCH_COVERAGE(ret, node_else ? nd_line(node_else) : line, type == NODE_IF ? "else" : "then", branches);
4295  }
4296  ADD_SEQ(ret, else_seq);
4297  }
4298 
4299  if (end_label) {
4300  ADD_LABEL(ret, end_label);
4301  }
4302 
4303  return COMPILE_OK;
4304 }
4305 
4306 static int
4307 compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
4308 {
4309  NODE *vals;
4310  NODE *tempnode = node;
4311  LABEL *endlabel, *elselabel;
4312  DECL_ANCHOR(head);
4313  DECL_ANCHOR(body_seq);
4314  DECL_ANCHOR(cond_seq);
4315  int only_special_literals = 1;
4316  VALUE literals = rb_hash_new();
4317  int line;
4318  enum node_type type;
4319  VALUE branches = 0;
4320 
4321  INIT_ANCHOR(head);
4322  INIT_ANCHOR(body_seq);
4323  INIT_ANCHOR(cond_seq);
4324 
4325  rb_hash_tbl_raw(literals)->type = &cdhash_type;
4326 
4327  if (node->nd_head == 0) {
4328  CHECK(COMPILE_(ret, "when", node->nd_body, popped));
4329  return COMPILE_OK;
4330  }
4331  CHECK(COMPILE(head, "case base", node->nd_head));
4332 
4333  DECL_BRANCH_BASE(branches, nd_line(node), "case");
4334 
4335  node = node->nd_body;
4336  type = nd_type(node);
4337  line = nd_line(node);
4338 
4339  if (type != NODE_WHEN) {
4340  COMPILE_ERROR(ERROR_ARGS "NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type));
4341  return COMPILE_NG;
4342  }
4343 
4344  endlabel = NEW_LABEL(line);
4345  elselabel = NEW_LABEL(line);
4346 
4347  ADD_SEQ(ret, head); /* case VAL */
4348 
4349  while (type == NODE_WHEN) {
4350  LABEL *l1;
4351 
4352  l1 = NEW_LABEL(line);
4353  ADD_LABEL(body_seq, l1);
4354  ADD_INSN(body_seq, line, pop);
4355  ADD_TRACE_BRANCH_COVERAGE(body_seq, node->nd_body ? nd_line(node->nd_body) : line, "when", branches);
4356  CHECK(COMPILE_(body_seq, "when body", node->nd_body, popped));
4357  ADD_INSNL(body_seq, line, jump, endlabel);
4358 
4359  vals = node->nd_head;
4360  if (vals) {
4361  switch (nd_type(vals)) {
4362  case NODE_ARRAY:
4363  only_special_literals = when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals);
4364  break;
4365  case NODE_SPLAT:
4366  case NODE_ARGSCAT:
4367  case NODE_ARGSPUSH:
4368  only_special_literals = 0;
4369  ADD_INSN (cond_seq, nd_line(vals), dup);
4370  CHECK(COMPILE(cond_seq, "when/cond splat", vals));
4371  ADD_INSN1(cond_seq, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
4372  ADD_INSNL(cond_seq, nd_line(vals), branchif, l1);
4373  break;
4374  default:
4375  UNKNOWN_NODE("NODE_CASE", vals, COMPILE_NG);
4376  }
4377  }
4378  else {
4379  EXPECT_NODE_NONULL("NODE_CASE", node, NODE_ARRAY, COMPILE_NG);
4380  }
4381 
4382  node = node->nd_next;
4383  if (!node) {
4384  break;
4385  }
4386  type = nd_type(node);
4387  line = nd_line(node);
4388  }
4389  /* else */
4390  if (node) {
4391  ADD_LABEL(cond_seq, elselabel);
4392  ADD_INSN(cond_seq, line, pop);
4393  ADD_TRACE_BRANCH_COVERAGE(cond_seq, nd_line(node), "else", branches);
4394  CHECK(COMPILE_(cond_seq, "else", node, popped));
4395  ADD_INSNL(cond_seq, line, jump, endlabel);
4396  }
4397  else {
4398  debugs("== else (implicit)\n");
4399  ADD_LABEL(cond_seq, elselabel);
4400  ADD_INSN(cond_seq, nd_line(tempnode), pop);
4401  ADD_TRACE_BRANCH_COVERAGE(cond_seq, nd_line(tempnode), "else", branches);
4402  if (!popped) {
4403  ADD_INSN(cond_seq, nd_line(tempnode), putnil);
4404  }
4405  ADD_INSNL(cond_seq, nd_line(tempnode), jump, endlabel);
4406  }
4407 
4408  if (only_special_literals) {
4409  iseq_add_mark_object(iseq, literals);
4410 
4411  ADD_INSN(ret, nd_line(tempnode), dup);
4412  ADD_INSN2(ret, nd_line(tempnode), opt_case_dispatch, literals, elselabel);
4413  LABEL_REF(elselabel);
4414  }
4415 
4416  ADD_SEQ(ret, cond_seq);
4417  ADD_SEQ(ret, body_seq);
4418  ADD_LABEL(ret, endlabel);
4419  return COMPILE_OK;
4420 }
4421 
4422 static int
4423 compile_when(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
4424 {
4425  NODE *vals;
4426  NODE *val;
4427  NODE *orig_node = node;
4428  LABEL *endlabel;
4429  DECL_ANCHOR(body_seq);
4430  VALUE branches = 0;
4431 
4432  DECL_BRANCH_BASE(branches, nd_line(node), "case");
4433 
4434  INIT_ANCHOR(body_seq);
4435  endlabel = NEW_LABEL(nd_line(node));
4436 
4437  while (node && nd_type(node) == NODE_WHEN) {
4438  const int line = nd_line(node);
4439  LABEL *l1 = NEW_LABEL(line);
4440  ADD_LABEL(body_seq, l1);
4441  ADD_TRACE_BRANCH_COVERAGE(body_seq, node->nd_body ? nd_line(node->nd_body) : line, "when", branches);
4442  CHECK(COMPILE_(body_seq, "when", node->nd_body, popped));
4443  ADD_INSNL(body_seq, line, jump, endlabel);
4444 
4445  vals = node->nd_head;
4446  if (!vals) {
4447  COMPILE_ERROR(ERROR_ARGS "NODE_WHEN: must be NODE_ARRAY, but 0");
4448  return COMPILE_NG;
4449  }
4450  switch (nd_type(vals)) {
4451  case NODE_ARRAY:
4452  while (vals) {
4453  val = vals->nd_head;
4454  CHECK(COMPILE(ret, "when2", val));
4455  ADD_INSNL(ret, nd_line(val), branchif, l1);
4456  vals = vals->nd_next;
4457  }
4458  break;
4459  case NODE_SPLAT:
4460  case NODE_ARGSCAT:
4461  case NODE_ARGSPUSH:
4462  ADD_INSN(ret, nd_line(vals), putnil);
4463  CHECK(COMPILE(ret, "when2/cond splat", vals));
4465  ADD_INSNL(ret, nd_line(vals), branchif, l1);
4466  break;
4467  default:
4468  UNKNOWN_NODE("NODE_WHEN", vals, COMPILE_NG);
4469  }
4470  node = node->nd_next;
4471  }
4472  /* else */
4473  ADD_TRACE_BRANCH_COVERAGE(ret, node ? nd_line(node) : nd_line(orig_node), "else", branches);
4474  CHECK(COMPILE_(ret, "else", node, popped));
4475  ADD_INSNL(ret, nd_line(orig_node), jump, endlabel);
4476 
4477  ADD_SEQ(ret, body_seq);
4478  ADD_LABEL(ret, endlabel);
4479  return COMPILE_OK;
4480 }
4481 
4482 static int
4483 compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped, const enum node_type type)
4484 {
4485  const int line = (int)nd_line(node);
4486  LABEL *prev_start_label = ISEQ_COMPILE_DATA(iseq)->start_label;
4487  LABEL *prev_end_label = ISEQ_COMPILE_DATA(iseq)->end_label;
4488  LABEL *prev_redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label;
4489  int prev_loopval_popped = ISEQ_COMPILE_DATA(iseq)->loopval_popped;
4490  VALUE branches = 0;
4491 
4493 
4494  LABEL *next_label = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(line); /* next */
4495  LABEL *redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label = NEW_LABEL(line); /* redo */
4496  LABEL *break_label = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(line); /* break */
4497  LABEL *end_label = NEW_LABEL(line);
4498  LABEL *adjust_label = NEW_LABEL(line);
4499 
4500  LABEL *next_catch_label = NEW_LABEL(line);
4501  LABEL *tmp_label = NULL;
4502 
4503  ISEQ_COMPILE_DATA(iseq)->loopval_popped = 0;
4504  push_ensure_entry(iseq, &enl, NULL, NULL);
4505 
4506  if (type == NODE_OPT_N || node->nd_state == 1) {
4507  ADD_INSNL(ret, line, jump, next_label);
4508  }
4509  else {
4510  tmp_label = NEW_LABEL(line);
4511  ADD_INSNL(ret, line, jump, tmp_label);
4512  }
4513  ADD_LABEL(ret, adjust_label);
4514  ADD_INSN(ret, line, putnil);
4515  ADD_LABEL(ret, next_catch_label);
4516  ADD_INSN(ret, line, pop);
4517  ADD_INSNL(ret, line, jump, next_label);
4518  if (tmp_label) ADD_LABEL(ret, tmp_label);
4519 
4520  ADD_LABEL(ret, redo_label);
4521  DECL_BRANCH_BASE(branches, line, type == NODE_WHILE ? "while" : "until");
4522  ADD_TRACE_BRANCH_COVERAGE(ret, node->nd_body ? nd_line(node->nd_body) : line, "body", branches);
4523  CHECK(COMPILE_POPPED(ret, "while body", node->nd_body));
4524  ADD_LABEL(ret, next_label); /* next */
4525 
4526  if (type == NODE_WHILE) {
4527  compile_branch_condition(iseq, ret, node->nd_cond,
4528  redo_label, end_label);
4529  }
4530  else if (type == NODE_UNTIL) {
4531  /* until */
4532  compile_branch_condition(iseq, ret, node->nd_cond,
4533  end_label, redo_label);
4534  }
4535  else {
4536  ADD_CALL_RECEIVER(ret, line);
4537  ADD_CALL(ret, line, idGets, INT2FIX(0));
4538  ADD_INSNL(ret, line, branchif, redo_label);
4539  /* opt_n */
4540  }
4541 
4542  ADD_LABEL(ret, end_label);
4543  ADD_ADJUST_RESTORE(ret, adjust_label);
4544 
4545  if (node->nd_state == Qundef) {
4546  /* ADD_INSN(ret, line, putundef); */
4547  COMPILE_ERROR(ERROR_ARGS "unsupported: putundef");
4548  return COMPILE_NG;
4549  }
4550  else {
4551  ADD_INSN(ret, line, putnil);
4552  }
4553 
4554  ADD_LABEL(ret, break_label); /* break */
4555 
4556  if (popped) {
4557  ADD_INSN(ret, line, pop);
4558  }
4559 
4560  ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label, NULL,
4561  break_label);
4562  ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, redo_label, break_label, NULL,
4563  next_catch_label);
4564  ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label, NULL,
4565  ISEQ_COMPILE_DATA(iseq)->redo_label);
4566 
4567  ISEQ_COMPILE_DATA(iseq)->start_label = prev_start_label;
4568  ISEQ_COMPILE_DATA(iseq)->end_label = prev_end_label;
4569  ISEQ_COMPILE_DATA(iseq)->redo_label = prev_redo_label;
4570  ISEQ_COMPILE_DATA(iseq)->loopval_popped = prev_loopval_popped;
4571  ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->prev;
4572  return COMPILE_OK;
4573 }
4574 
4575 static int
4576 compile_iter(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
4577 {
4578  const int line = nd_line(node);
4579  const rb_iseq_t *prevblock = ISEQ_COMPILE_DATA(iseq)->current_block;
4580  LABEL *retry_label = NEW_LABEL(line);
4581  LABEL *retry_end_l = NEW_LABEL(line);
4582  const rb_iseq_t *child_iseq;
4583 
4584  ADD_LABEL(ret, retry_label);
4585  if (nd_type(node) == NODE_FOR) {
4586  CHECK(COMPILE(ret, "iter caller (for)", node->nd_iter));
4587 
4588  ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
4589  NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq),
4590  ISEQ_TYPE_BLOCK, line);
4591  ADD_SEND_WITH_BLOCK(ret, line, idEach, INT2FIX(0), child_iseq);
4592  }
4593  else {
4594  ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
4595  NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq),
4596  ISEQ_TYPE_BLOCK, line);
4597  CHECK(COMPILE(ret, "iter caller", node->nd_iter));
4598  }
4599  ADD_LABEL(ret, retry_end_l);
4600 
4601  if (popped) {
4602  ADD_INSN(ret, line, pop);
4603  }
4604 
4605  ISEQ_COMPILE_DATA(iseq)->current_block = prevblock;
4606 
4607  ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, child_iseq, retry_end_l);
4608  return COMPILE_OK;
4609 }
4610 
4611 static int
4612 compile_for(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
4613 {
4614  const int line = nd_line(node);
4615  if (node->nd_var) {
4616  /* massign to var in "for"
4617  * args.length == 1 && Array === (tmp = args[0]) ? tmp : args
4618  */
4619  NODE *var = node->nd_var;
4620  LABEL *not_single = NEW_LABEL(nd_line(var));
4621  LABEL *not_ary = NEW_LABEL(nd_line(var));
4622  CHECK(COMPILE(ret, "for var", var));
4623  ADD_INSN(ret, line, dup);
4624  ADD_CALL(ret, line, idLength, INT2FIX(0));
4625  ADD_INSN1(ret, line, putobject, INT2FIX(1));
4626  ADD_CALL(ret, line, idEq, INT2FIX(1));
4627  ADD_INSNL(ret, line, branchunless, not_single);
4628  ADD_INSN(ret, line, dup);
4629  ADD_INSN1(ret, line, putobject, INT2FIX(0));
4630  ADD_CALL(ret, line, idAREF, INT2FIX(1));
4631  ADD_INSN1(ret, line, putobject, rb_cArray);
4632  ADD_INSN1(ret, line, topn, INT2FIX(1));
4633  ADD_CALL(ret, line, idEqq, INT2FIX(1));
4634  ADD_INSNL(ret, line, branchunless, not_ary);
4635  ADD_INSN(ret, line, swap);
4636  ADD_LABEL(ret, not_ary);
4637  ADD_INSN(ret, line, pop);
4638  ADD_LABEL(ret, not_single);
4639  return COMPILE_OK;
4640  }
4641  else {
4642  return compile_iter(iseq, ret, node, popped);
4643  }
4644 }
4645 
4646 static int
4647 compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
4648 {
4649  const int line = nd_line(node);
4650  unsigned long level = 0;
4651 
4652  if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0) {
4653  /* while/until */
4654  LABEL *splabel = NEW_LABEL(0);
4655  ADD_LABEL(ret, splabel);
4656  ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label);
4657  CHECK(COMPILE_(ret, "break val (while/until)", node->nd_stts,
4658  ISEQ_COMPILE_DATA(iseq)->loopval_popped));
4659  add_ensure_iseq(ret, iseq, 0);
4660  ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
4661  ADD_ADJUST_RESTORE(ret, splabel);
4662 
4663  if (!popped) {
4664  ADD_INSN(ret, line, putnil);
4665  }
4666  }
4667  else if (iseq->body->type == ISEQ_TYPE_BLOCK) {
4668  break_by_insn:
4669  /* escape from block */
4670  CHECK(COMPILE(ret, "break val (block)", node->nd_stts));
4671  ADD_INSN1(ret, line, throw, INT2FIX(level | TAG_BREAK));
4672  if (popped) {
4673  ADD_INSN(ret, line, pop);
4674  }
4675  }
4676  else if (iseq->body->type == ISEQ_TYPE_EVAL) {
4677  break_in_eval:
4678  COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with break");
4679  return COMPILE_NG;
4680  }
4681  else {
4682  const rb_iseq_t *ip = iseq->body->parent_iseq;
4683 
4684  while (ip) {
4685  if (!ISEQ_COMPILE_DATA(ip)) {
4686  ip = 0;
4687  break;
4688  }
4689 
4690  level++;
4691  if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
4692  level = VM_THROW_NO_ESCAPE_FLAG;
4693  goto break_by_insn;
4694  }
4695  else if (ip->body->type == ISEQ_TYPE_BLOCK) {
4696  level <<= VM_THROW_LEVEL_SHIFT;
4697  goto break_by_insn;
4698  }
4699  else if (ip->body->type == ISEQ_TYPE_EVAL) {
4700  goto break_in_eval;
4701  }
4702 
4703  ip = ip->body->parent_iseq;
4704  }
4705  COMPILE_ERROR(ERROR_ARGS "Invalid break");
4706  return COMPILE_NG;
4707  }
4708  return COMPILE_OK;
4709 }
4710 
4711 static int
4712 compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
4713 {
4714  const int line = nd_line(node);
4715  unsigned long level = 0;
4716 
4717  if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0) {
4718  LABEL *splabel = NEW_LABEL(0);
4719  debugs("next in while loop\n");
4720  ADD_LABEL(ret, splabel);
4721  CHECK(COMPILE(ret, "next val/valid syntax?", node->nd_stts));
4722  add_ensure_iseq(ret, iseq, 0);
4723  ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label);
4724  ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
4725  ADD_ADJUST_RESTORE(ret, splabel);
4726  if (!popped) {
4727  ADD_INSN(ret, line, putnil);
4728  }
4729  }
4730  else if (ISEQ_COMPILE_DATA(iseq)->end_label) {
4731  LABEL *splabel = NEW_LABEL(0);
4732  debugs("next in block\n");
4733  ADD_LABEL(ret, splabel);
4734  ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->start_label);
4735  CHECK(COMPILE(ret, "next val", node->nd_stts));
4736  add_ensure_iseq(ret, iseq, 0);
4737  ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
4738  ADD_ADJUST_RESTORE(ret, splabel);
4739 
4740  if (!popped) {
4741  ADD_INSN(ret, line, putnil);
4742  }
4743  }
4744  else if (iseq->body->type == ISEQ_TYPE_EVAL) {
4745  next_in_eval:
4746  COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with next");
4747  return COMPILE_NG;
4748  }
4749  else {
4750  const rb_iseq_t *ip = iseq;
4751 
4752  while (ip) {
4753  if (!ISEQ_COMPILE_DATA(ip)) {
4754  ip = 0;
4755  break;
4756  }
4757 
4758  level = VM_THROW_NO_ESCAPE_FLAG;
4759  if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
4760  /* while loop */
4761  break;
4762  }
4763  else if (ip->body->type == ISEQ_TYPE_BLOCK) {
4764  break;
4765  }
4766  else if (ip->body->type == ISEQ_TYPE_EVAL) {
4767  goto next_in_eval;
4768  }
4769 
4770  ip = ip->body->parent_iseq;
4771  }
4772  if (ip != 0) {
4773  CHECK(COMPILE(ret, "next val", node->nd_stts));
4774  ADD_INSN1(ret, line, throw, INT2FIX(level | TAG_NEXT));
4775 
4776  if (popped) {
4777  ADD_INSN(ret, line, pop);
4778  }
4779  }
4780  else {
4781  COMPILE_ERROR(ERROR_ARGS "Invalid next");
4782  return COMPILE_NG;
4783  }
4784  }
4785  return COMPILE_OK;
4786 }
4787 
4788 static int
4789 compile_redo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
4790 {
4791  const int line = nd_line(node);
4792 
4793  if (ISEQ_COMPILE_DATA(iseq)->redo_label) {
4794  LABEL *splabel = NEW_LABEL(0);
4795  debugs("redo in while");
4796  ADD_LABEL(ret, splabel);
4797  ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->redo_label);
4798  add_ensure_iseq(ret, iseq, 0);
4799  ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->redo_label);
4800  ADD_ADJUST_RESTORE(ret, splabel);
4801  if (!popped) {
4802  ADD_INSN(ret, line, putnil);
4803  }
4804  }
4805  else if (iseq->body->type == ISEQ_TYPE_EVAL) {
4806  redo_in_eval:
4807  COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with redo");
4808  return COMPILE_NG;
4809  }
4810  else if (ISEQ_COMPILE_DATA(iseq)->start_label) {
4811  LABEL *splabel = NEW_LABEL(0);
4812 
4813  debugs("redo in block");
4814  ADD_LABEL(ret, splabel);
4815  add_ensure_iseq(ret, iseq, 0);
4816  ADD_ADJUST(ret, line, ISEQ_COMPILE_DATA(iseq)->start_label);
4817  ADD_INSNL(ret, line, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
4818  ADD_ADJUST_RESTORE(ret, splabel);
4819 
4820  if (!popped) {
4821  ADD_INSN(ret, line, putnil);
4822  }
4823  }
4824  else {
4825  const rb_iseq_t *ip = iseq;
4826  const unsigned long level = VM_THROW_NO_ESCAPE_FLAG;
4827 
4828  while (ip) {
4829  if (!ISEQ_COMPILE_DATA(ip)) {
4830  ip = 0;
4831  break;
4832  }
4833 
4834  if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
4835  break;
4836  }
4837  else if (ip->body->type == ISEQ_TYPE_BLOCK) {
4838  break;
4839  }
4840  else if (ip->body->type == ISEQ_TYPE_EVAL) {
4841  goto redo_in_eval;
4842  }
4843 
4844  ip = ip->body->parent_iseq;
4845  }
4846  if (ip != 0) {
4847  ADD_INSN(ret, line, putnil);
4848  ADD_INSN1(ret, line, throw, INT2FIX(level | TAG_REDO));
4849 
4850  if (popped) {
4851  ADD_INSN(ret, line, pop);
4852  }
4853  }
4854  else {
4855  COMPILE_ERROR(ERROR_ARGS "Invalid redo");
4856  return COMPILE_NG;
4857  }
4858  }
4859  return COMPILE_OK;
4860 }
4861 
4862 static int
4863 compile_retry(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
4864 {
4865  const int line = nd_line(node);
4866 
4867  if (iseq->body->type == ISEQ_TYPE_RESCUE) {
4868  ADD_INSN(ret, line, putnil);
4869  ADD_INSN1(ret, line, throw, INT2FIX(TAG_RETRY));
4870 
4871  if (popped) {
4872  ADD_INSN(ret, line, pop);
4873  }
4874  }
4875  else {
4876  COMPILE_ERROR(ERROR_ARGS "Invalid retry");
4877  return COMPILE_NG;
4878  }
4879  return COMPILE_OK;
4880 }
4881 
4882 static int
4883 compile_rescue(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
4884 {
4885  const int line = nd_line(node);
4886  LABEL *lstart = NEW_LABEL(line);
4887  LABEL *lend = NEW_LABEL(line);
4888  LABEL *lcont = NEW_LABEL(line);
4889  const rb_iseq_t *rescue = NEW_CHILD_ISEQ(node->nd_resq,
4890  rb_str_concat(rb_str_new2("rescue in "), iseq->body->location.label),
4891  ISEQ_TYPE_RESCUE, line);
4892 
4893  lstart->rescued = LABEL_RESCUE_BEG;
4894  lend->rescued = LABEL_RESCUE_END;
4895  ADD_LABEL(ret, lstart);
4896  CHECK(COMPILE(ret, "rescue head", node->nd_head));
4897  ADD_LABEL(ret, lend);
4898  if (node->nd_else) {
4899  ADD_INSN(ret, line, pop);
4900  CHECK(COMPILE(ret, "rescue else", node->nd_else));
4901  }
4902  ADD_INSN(ret, line, nop);
4903  ADD_LABEL(ret, lcont);
4904 
4905  if (popped) {
4906  ADD_INSN(ret, line, pop);
4907  }
4908 
4909  /* register catch entry */
4910  ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lcont);
4911  ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, NULL, lstart);
4912  return COMPILE_OK;
4913 }
4914 
4915 static int
4916 compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
4917 {
4918  const int line = nd_line(node);
4919  NODE *resq = node;
4920  NODE *narg;
4921  LABEL *label_miss, *label_hit;
4922 
4923  while (resq) {
4924  label_miss = NEW_LABEL(line);
4925  label_hit = NEW_LABEL(line);
4926 
4927  narg = resq->nd_args;
4928  if (narg) {
4929  switch (nd_type(narg)) {
4930  case NODE_ARRAY:
4931  while (narg) {
4932  ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0);
4933  CHECK(COMPILE(ret, "rescue arg", narg->nd_head));
4934  ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
4935  ADD_INSNL(ret, line, branchif, label_hit);
4936  narg = narg->nd_next;
4937  }
4938  break;
4939  case NODE_SPLAT:
4940  case NODE_ARGSCAT:
4941  case NODE_ARGSPUSH:
4942  ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0);
4943  CHECK(COMPILE(ret, "rescue/cond splat", narg));
4945  ADD_INSNL(ret, line, branchif, label_hit);
4946  break;
4947  default:
4948  UNKNOWN_NODE("NODE_RESBODY", narg, COMPILE_NG);
4949  }
4950  }
4951  else {
4952  ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0);
4953  ADD_INSN1(ret, line, putobject, rb_eStandardError);
4954  ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
4955  ADD_INSNL(ret, line, branchif, label_hit);
4956  }
4957  ADD_INSNL(ret, line, jump, label_miss);
4958  ADD_LABEL(ret, label_hit);
4959  CHECK(COMPILE(ret, "resbody body", resq->nd_body));
4960  if (ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization) {
4961  ADD_INSN(ret, line, nop);
4962  }
4963  ADD_INSN(ret, line, leave);
4964  ADD_LABEL(ret, label_miss);
4965  resq = resq->nd_head;
4966  }
4967  return COMPILE_OK;
4968 }
4969 
4970 static int
4971 compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
4972 {
4973  const int line = nd_line(node);
4974  DECL_ANCHOR(ensr);
4975  const rb_iseq_t *ensure = NEW_CHILD_ISEQ(node->nd_ensr,
4976  rb_str_concat(rb_str_new2 ("ensure in "), iseq->body->location.label),
4977  ISEQ_TYPE_ENSURE, line);
4978  LABEL *lstart = NEW_LABEL(line);
4979  LABEL *lend = NEW_LABEL(line);
4980  LABEL *lcont = NEW_LABEL(line);
4981  LINK_ELEMENT *last;
4982  int last_leave = 0;
4983  struct ensure_range er;
4985  struct ensure_range *erange;
4986 
4987  INIT_ANCHOR(ensr);
4988  CHECK(COMPILE_POPPED(ensr, "ensure ensr", node->nd_ensr));
4989  last = ensr->last;
4990  last_leave = last && IS_INSN(last) && IS_INSN_ID(last, leave);
4991 
4992  er.begin = lstart;
4993  er.end = lend;
4994  er.next = 0;
4995  push_ensure_entry(iseq, &enl, &er, node->nd_ensr);
4996 
4997  ADD_LABEL(ret, lstart);
4998  CHECK(COMPILE_(ret, "ensure head", node->nd_head, (popped | last_leave)));
4999  ADD_LABEL(ret, lend);
5000  if (ensr->anchor.next == NULL) {
5001  ADD_INSN(ret, line, nop);
5002  }
5003  else {
5004  ADD_SEQ(ret, ensr);
5005  if (!popped && last_leave) {
5006  ADD_INSN(ret, line, putnil);
5007  }
5008  }
5009  ADD_LABEL(ret, lcont);
5010  if (last_leave) ADD_INSN(ret, line, pop);
5011 
5012  erange = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->erange;
5013  if (lstart->link.next != &lend->link) {
5014  while (erange) {
5015  ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end,
5016  ensure, lcont);
5017  erange = erange->next;
5018  }
5019  }
5020 
5021  ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl.prev;
5022  return COMPILE_OK;
5023 }
5024 
5025 static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped);
5033 static int
5034 iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
5035 {
5036  if (node == 0) {
5037  if (!popped) {
5038  debugs("node: NODE_NIL(implicit)\n");
5039  ADD_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, putnil);
5040  }
5041  return COMPILE_OK;
5042  }
5043  return iseq_compile_each0(iseq, ret, node, popped);
5044 }
5045 
5046 
5047 static int
5048 iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped)
5049 {
5050  LINK_ELEMENT *saved_last_element = 0;
5051  const int line = (int)nd_line(node);
5052  const enum node_type type = nd_type(node);
5053 
5054  if (ISEQ_COMPILE_DATA(iseq)->last_line == line) {
5055  /* ignore */
5056  }
5057  else {
5058  if (node->flags & NODE_FL_NEWLINE) {
5059  ISEQ_COMPILE_DATA(iseq)->last_line = line;
5060  ADD_TRACE_LINE_COVERAGE(ret, line);
5061  ADD_TRACE(ret, line, RUBY_EVENT_LINE);
5062  saved_last_element = ret->last;
5063  }
5064  }
5065 
5066  debug_node_start(node);
5067 #undef BEFORE_RETURN
5068 #define BEFORE_RETURN debug_node_end()
5069 
5070  switch (type) {
5071  case NODE_BLOCK:{
5072  while (node && nd_type(node) == NODE_BLOCK) {
5073  CHECK(COMPILE_(ret, "BLOCK body", node->nd_head,
5074  (node->nd_next ? 1 : popped)));
5075  node = node->nd_next;
5076  }
5077  if (node) {
5078  CHECK(COMPILE_(ret, "BLOCK next", node->nd_next, popped));
5079  }
5080  break;
5081  }
5082  case NODE_IF:
5083  case NODE_UNLESS:
5084  CHECK(compile_if(iseq, ret, node, popped, type));
5085  break;
5086  case NODE_CASE:
5087  CHECK(compile_case(iseq, ret, node, popped));
5088  break;
5089  case NODE_WHEN:
5090  CHECK(compile_when(iseq, ret, node, popped));
5091  break;
5092  case NODE_OPT_N:
5093  case NODE_WHILE:
5094  case NODE_UNTIL:
5095  CHECK(compile_loop(iseq, ret, node, popped, type));
5096  break;
5097  case NODE_FOR:
5098  CHECK(compile_for(iseq, ret, node, popped));
5099  break;
5100  case NODE_ITER:
5101  CHECK(compile_iter(iseq, ret, node, popped));
5102  break;
5103  case NODE_BREAK:
5104  CHECK(compile_break(iseq, ret, node, popped));
5105  break;
5106  case NODE_NEXT:
5107  CHECK(compile_next(iseq, ret, node, popped));
5108  break;
5109  case NODE_REDO:
5110  CHECK(compile_redo(iseq, ret, node, popped));
5111  break;
5112  case NODE_RETRY:
5113  CHECK(compile_retry(iseq, ret, node, popped));
5114  break;
5115  case NODE_BEGIN:{
5116  CHECK(COMPILE_(ret, "NODE_BEGIN", node->nd_body, popped));
5117  break;
5118  }
5119  case NODE_RESCUE:
5120  CHECK(compile_rescue(iseq, ret, node, popped));
5121  break;
5122  case NODE_RESBODY:
5123  CHECK(compile_resbody(iseq, ret, node, popped));
5124  break;
5125  case NODE_ENSURE:
5126  CHECK(compile_ensure(iseq, ret, node, popped));
5127  break;
5128 
5129  case NODE_AND:
5130  case NODE_OR:{
5131  LABEL *end_label = NEW_LABEL(line);
5132  CHECK(COMPILE(ret, "nd_1st", node->nd_1st));
5133  if (!popped) {
5134  ADD_INSN(ret, line, dup);
5135  }
5136  if (type == NODE_AND) {
5137  ADD_INSNL(ret, line, branchunless, end_label);
5138  }
5139  else {
5140  ADD_INSNL(ret, line, branchif, end_label);
5141  }
5142  if (!popped) {
5143  ADD_INSN(ret, line, pop);
5144  }
5145  CHECK(COMPILE_(ret, "nd_2nd", node->nd_2nd, popped));
5146  ADD_LABEL(ret, end_label);
5147  break;
5148  }
5149 
5150  case NODE_MASGN:{
5151  compile_massign(iseq, ret, node, popped);
5152  break;
5153  }
5154 
5155  case NODE_LASGN:{
5156  ID id = node->nd_vid;
5157  int idx = iseq->body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id);
5158 
5159  debugs("lvar: %s idx: %d\n", rb_id2name(id), idx);
5160  CHECK(COMPILE(ret, "rvalue", node->nd_value));
5161 
5162  if (!popped) {
5163  ADD_INSN(ret, line, dup);
5164  }
5165  ADD_SETLOCAL(ret, line, idx, get_lvar_level(iseq));
5166  break;
5167  }
5168  case NODE_DASGN:
5169  case NODE_DASGN_CURR:{
5170  int idx, lv, ls;
5171  ID id = node->nd_vid;
5172  CHECK(COMPILE(ret, "dvalue", node->nd_value));
5173  debugi("dassn id", rb_id2str(id) ? id : '*');
5174 
5175  if (!popped) {
5176  ADD_INSN(ret, line, dup);
5177  }
5178 
5179  idx = get_dyna_var_idx(iseq, id, &lv, &ls);
5180 
5181  if (idx < 0) {
5182  COMPILE_ERROR(ERROR_ARGS "NODE_DASGN(_CURR): unknown id (%"PRIsVALUE")",
5183  rb_id2str(id));
5184  goto ng;
5185  }
5186  ADD_SETLOCAL(ret, line, ls - idx, lv);
5187  break;
5188  }
5189  case NODE_GASGN:{
5190  CHECK(COMPILE(ret, "lvalue", node->nd_value));
5191 
5192  if (!popped) {
5193  ADD_INSN(ret, line, dup);
5194  }
5195  ADD_INSN1(ret, line, setglobal,
5196  ((VALUE)node->nd_entry | 1));
5197  break;
5198  }
5199  case NODE_IASGN:{
5200  CHECK(COMPILE(ret, "lvalue", node->nd_value));
5201  if (!popped) {
5202  ADD_INSN(ret, line, dup);
5203  }
5204  ADD_INSN2(ret, line, setinstancevariable,
5205  ID2SYM(node->nd_vid),
5206  get_ivar_ic_value(iseq,node->nd_vid));
5207  break;
5208  }
5209  case NODE_CDECL:{
5210  CHECK(COMPILE(ret, "lvalue", node->nd_value));
5211 
5212  if (!popped) {
5213  ADD_INSN(ret, line, dup);
5214  }
5215 
5216  if (node->nd_vid) {
5217  ADD_INSN1(ret, line, putspecialobject,
5219  ADD_INSN1(ret, line, setconstant, ID2SYM(node->nd_vid));
5220  }
5221  else {
5222  compile_cpath(ret, iseq, node->nd_else);
5223  ADD_INSN1(ret, line, setconstant, ID2SYM(node->nd_else->nd_mid));
5224  }
5225  break;
5226  }
5227  case NODE_CVASGN:{
5228  CHECK(COMPILE(ret, "cvasgn val", node->nd_value));
5229  if (!popped) {
5230  ADD_INSN(ret, line, dup);
5231  }
5232  ADD_INSN1(ret, line, setclassvariable,
5233  ID2SYM(node->nd_vid));
5234  break;
5235  }
5236  case NODE_OP_ASGN1: {
5237  DECL_ANCHOR(args);
5238  VALUE argc;
5239  unsigned int flag = 0;
5240  unsigned int asgnflag = 0;
5241  ID id = node->nd_mid;
5242  int boff = 0;
5243 
5244  /*
5245  * a[x] (op)= y
5246  *
5247  * nil # nil
5248  * eval a # nil a
5249  * eval x # nil a x
5250  * dupn 2 # nil a x a x
5251  * send :[] # nil a x a[x]
5252  * eval y # nil a x a[x] y
5253  * send op # nil a x ret
5254  * setn 3 # ret a x ret
5255  * send []= # ret ?
5256  * pop # ret
5257  */
5258 
5259  /*
5260  * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head;
5261  * NODE_OP_ASGN nd_recv
5262  * nd_args->nd_head
5263  * nd_args->nd_body
5264  * nd_mid
5265  */
5266 
5267  if (!popped) {
5268  ADD_INSN(ret, line, putnil);
5269  }
5270  asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN1 recv", node);
5271  switch (nd_type(node->nd_args->nd_head)) {
5272  case NODE_ZARRAY:
5273  argc = INT2FIX(0);
5274  break;
5275  case NODE_BLOCK_PASS:
5276  boff = 1;
5277  default:
5278  INIT_ANCHOR(args);
5279  argc = setup_args(iseq, args, node->nd_args->nd_head, &flag, NULL);
5280  CHECK(!NIL_P(argc));
5281  ADD_SEQ(ret, args);
5282  }
5283  ADD_INSN1(ret, line, dupn, FIXNUM_INC(argc, 1 + boff));
5284  ADD_SEND_WITH_FLAG(ret, line, idAREF, argc, INT2FIX(flag));
5285  flag |= asgnflag;
5286 
5287  if (id == 0 || id == 1) {
5288  /* 0: or, 1: and
5289  a[x] ||= y
5290 
5291  unless/if a[x]
5292  a[x]= y
5293  else
5294  nil
5295  end
5296  */
5297  LABEL *label = NEW_LABEL(line);
5298  LABEL *lfin = NEW_LABEL(line);
5299 
5300  ADD_INSN(ret, line, dup);
5301  if (id == 0) {
5302  /* or */
5303  ADD_INSNL(ret, line, branchif, label);
5304  }
5305  else {
5306  /* and */
5307  ADD_INSNL(ret, line, branchunless, label);
5308  }
5309  ADD_INSN(ret, line, pop);
5310 
5311  CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
5312  if (!popped) {
5313  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff));
5314  }
5315  if (flag & VM_CALL_ARGS_SPLAT) {
5316  ADD_INSN1(ret, line, newarray, INT2FIX(1));
5317  if (boff > 0) {
5318  ADD_INSN1(ret, line, dupn, INT2FIX(3));
5319  ADD_INSN(ret, line, swap);
5320  ADD_INSN(ret, line, pop);
5321  }
5322  ADD_INSN(ret, line, concatarray);
5323  if (boff > 0) {
5324  ADD_INSN1(ret, line, setn, INT2FIX(3));
5325  ADD_INSN(ret, line, pop);
5326  ADD_INSN(ret, line, pop);
5327  }
5328  ADD_SEND_WITH_FLAG(ret, line, idASET, argc, INT2FIX(flag));
5329  }
5330  else {
5331  if (boff > 0)
5332  ADD_INSN(ret, line, swap);
5333  ADD_SEND_WITH_FLAG(ret, line, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag));
5334  }
5335  ADD_INSN(ret, line, pop);
5336  ADD_INSNL(ret, line, jump, lfin);
5337  ADD_LABEL(ret, label);
5338  if (!popped) {
5339  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff));
5340  }
5341  ADD_INSN1(ret, line, adjuststack, FIXNUM_INC(argc, 2+boff));
5342  ADD_LABEL(ret, lfin);
5343  }
5344  else {
5345  CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
5346  ADD_SEND(ret, line, id, INT2FIX(1));
5347  if (!popped) {
5348  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2+boff));
5349  }
5350  if (flag & VM_CALL_ARGS_SPLAT) {
5351  ADD_INSN1(ret, line, newarray, INT2FIX(1));
5352  if (boff > 0) {
5353  ADD_INSN1(ret, line, dupn, INT2FIX(3));
5354  ADD_INSN(ret, line, swap);
5355  ADD_INSN(ret, line, pop);
5356  }
5357  ADD_INSN(ret, line, concatarray);
5358  if (boff > 0) {
5359  ADD_INSN1(ret, line, setn, INT2FIX(3));
5360  ADD_INSN(ret, line, pop);
5361  ADD_INSN(ret, line, pop);
5362  }
5363  ADD_SEND_WITH_FLAG(ret, line, idASET, argc, INT2FIX(flag));
5364  }
5365  else {
5366  if (boff > 0)
5367  ADD_INSN(ret, line, swap);
5368  ADD_SEND_WITH_FLAG(ret, line, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag));
5369  }
5370  ADD_INSN(ret, line, pop);
5371  }
5372 
5373  break;
5374  }
5375  case NODE_OP_ASGN2:{
5376  ID atype = node->nd_next->nd_mid;
5377  ID vid = node->nd_next->nd_vid, aid = rb_id_attrset(vid);
5378  VALUE asgnflag;
5379  LABEL *lfin = NEW_LABEL(line);
5380  LABEL *lcfin = NEW_LABEL(line);
5381  LABEL *lskip = 0;
5382  /*
5383  class C; attr_accessor :c; end
5384  r = C.new
5385  r.a &&= v # asgn2
5386 
5387  eval r # r
5388  dup # r r
5389  eval r.a # r o
5390 
5391  # or
5392  dup # r o o
5393  if lcfin # r o
5394  pop # r
5395  eval v # r v
5396  swap # v r
5397  topn 1 # v r v
5398  send a= # v ?
5399  jump lfin # v ?
5400 
5401  lcfin: # r o
5402  swap # o r
5403 
5404  lfin: # o ?
5405  pop # o
5406 
5407  # and
5408  dup # r o o
5409  unless lcfin
5410  pop # r
5411  eval v # r v
5412  swap # v r
5413  topn 1 # v r v
5414  send a= # v ?
5415  jump lfin # v ?
5416 
5417  # others
5418  eval v # r o v
5419  send ?? # r w
5420  send a= # w
5421 
5422  */
5423 
5424  asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN2#recv", node);
5425  if (node->nd_next->nd_aid) {
5426  lskip = NEW_LABEL(line);
5427  ADD_INSN(ret, line, dup);
5428  ADD_INSNL(ret, line, branchnil, lskip);
5429  }
5430  ADD_INSN(ret, line, dup);
5431  ADD_SEND(ret, line, vid, INT2FIX(0));
5432 
5433  if (atype == 0 || atype == 1) { /* 0: OR or 1: AND */
5434  ADD_INSN(ret, line, dup);
5435  if (atype == 0) {
5436  ADD_INSNL(ret, line, branchif, lcfin);
5437  }
5438  else {
5439  ADD_INSNL(ret, line, branchunless, lcfin);
5440  }
5441  ADD_INSN(ret, line, pop);
5442  CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
5443  ADD_INSN(ret, line, swap);
5444  ADD_INSN1(ret, line, topn, INT2FIX(1));
5445  ADD_SEND_WITH_FLAG(ret, line, aid, INT2FIX(1), INT2FIX(asgnflag));
5446  ADD_INSNL(ret, line, jump, lfin);
5447 
5448  ADD_LABEL(ret, lcfin);
5449  ADD_INSN(ret, line, swap);
5450 
5451  ADD_LABEL(ret, lfin);
5452  ADD_INSN(ret, line, pop);
5453  if (lskip) {
5454  ADD_LABEL(ret, lskip);
5455  }
5456  if (popped) {
5457  /* we can apply more optimize */
5458  ADD_INSN(ret, line, pop);
5459  }
5460  }
5461  else {
5462  CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
5463  ADD_SEND(ret, line, atype, INT2FIX(1));
5464  if (!popped) {
5465  ADD_INSN(ret, line, swap);
5466  ADD_INSN1(ret, line, topn, INT2FIX(1));
5467  }
5468  ADD_SEND_WITH_FLAG(ret, line, aid, INT2FIX(1), INT2FIX(asgnflag));
5469  if (lskip && popped) {
5470  ADD_LABEL(ret, lskip);
5471  }
5472  ADD_INSN(ret, line, pop);
5473  if (lskip && !popped) {
5474  ADD_LABEL(ret, lskip);
5475  }
5476  }
5477  break;
5478  }
5479  case NODE_OP_CDECL: {
5480  LABEL *lfin = 0;
5481  LABEL *lassign = 0;
5482  ID mid;
5483 
5484  switch (nd_type(node->nd_head)) {
5485  case NODE_COLON3:
5486  ADD_INSN1(ret, line, putobject, rb_cObject);
5487  break;
5488  case NODE_COLON2:
5489  CHECK(COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head));
5490  break;
5491  default:
5492  COMPILE_ERROR(ERROR_ARGS "%s: invalid node in NODE_OP_CDECL",
5493  ruby_node_name(nd_type(node->nd_head)));
5494  goto ng;
5495  }
5496  mid = node->nd_head->nd_mid;
5497  /* cref */
5498  if (node->nd_aid == 0) {
5499  lassign = NEW_LABEL(line);
5500  ADD_INSN(ret, line, dup); /* cref cref */
5501  ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_CONST),
5502  ID2SYM(mid), Qfalse); /* cref bool */
5503  ADD_INSNL(ret, line, branchunless, lassign); /* cref */
5504  }
5505  ADD_INSN(ret, line, dup); /* cref cref */
5506  ADD_INSN1(ret, line, getconstant, ID2SYM(mid)); /* cref obj */
5507 
5508  if (node->nd_aid == 0 || node->nd_aid == 1) {
5509  lfin = NEW_LABEL(line);
5510  if (!popped) ADD_INSN(ret, line, dup); /* cref [obj] obj */
5511  if (node->nd_aid == 0)
5512  ADD_INSNL(ret, line, branchif, lfin);
5513  else
5514  ADD_INSNL(ret, line, branchunless, lfin);
5515  /* cref [obj] */
5516  if (!popped) ADD_INSN(ret, line, pop); /* cref */
5517  if (lassign) ADD_LABEL(ret, lassign);
5518  CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value));
5519  /* cref value */
5520  if (popped)
5521  ADD_INSN1(ret, line, topn, INT2FIX(1)); /* cref value cref */
5522  else {
5523  ADD_INSN1(ret, line, dupn, INT2FIX(2)); /* cref value cref value */
5524  ADD_INSN(ret, line, swap); /* cref value value cref */
5525  }
5526  ADD_INSN1(ret, line, setconstant, ID2SYM(mid)); /* cref [value] */
5527  ADD_LABEL(ret, lfin); /* cref [value] */
5528  if (!popped) ADD_INSN(ret, line, swap); /* [value] cref */
5529  ADD_INSN(ret, line, pop); /* [value] */
5530  }
5531  else {
5532  CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value));
5533  /* cref obj value */
5534  ADD_CALL(ret, line, node->nd_aid, INT2FIX(1));
5535  /* cref value */
5536  ADD_INSN(ret, line, swap); /* value cref */
5537  if (!popped) {
5538  ADD_INSN1(ret, line, topn, INT2FIX(1)); /* value cref value */
5539  ADD_INSN(ret, line, swap); /* value value cref */
5540  }
5541  ADD_INSN1(ret, line, setconstant, ID2SYM(mid));
5542  }
5543  break;
5544  }
5545  case NODE_OP_ASGN_AND:
5546  case NODE_OP_ASGN_OR:{
5547  LABEL *lfin = NEW_LABEL(line);
5548  LABEL *lassign;
5549 
5550  if (nd_type(node) == NODE_OP_ASGN_OR) {
5551  LABEL *lfinish[2];
5552  lfinish[0] = lfin;
5553  lfinish[1] = 0;
5554  defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
5555  lassign = lfinish[1];
5556  if (!lassign) {
5557  lassign = NEW_LABEL(line);
5558  }
5559  ADD_INSNL(ret, line, branchunless, lassign);
5560  }
5561  else {
5562  lassign = NEW_LABEL(line);
5563  }
5564 
5565  CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head));
5566  ADD_INSN(ret, line, dup);
5567 
5568  if (nd_type(node) == NODE_OP_ASGN_AND) {
5569  ADD_INSNL(ret, line, branchunless, lfin);
5570  }
5571  else {
5572  ADD_INSNL(ret, line, branchif, lfin);
5573  }
5574 
5575  ADD_INSN(ret, line, pop);
5576  ADD_LABEL(ret, lassign);
5577  CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value));
5578  ADD_LABEL(ret, lfin);
5579 
5580  if (popped) {
5581  /* we can apply more optimize */
5582  ADD_INSN(ret, line, pop);
5583  }
5584  break;
5585  }
5586  case NODE_CALL:
5587  case NODE_OPCALL:
5588  /* optimization shortcut
5589  * "literal".freeze -> opt_str_freeze("literal")
5590  */
5591  if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR &&
5592  (node->nd_mid == idFreeze || node->nd_mid == idUMinus) &&
5593  node->nd_args == NULL &&
5594  ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
5595  ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
5596  VALUE str = rb_fstring(node->nd_recv->nd_lit);
5597  iseq_add_mark_object(iseq, str);
5598  if (node->nd_mid == idUMinus) {
5599  ADD_INSN1(ret, line, opt_str_uminus, str);
5600  }
5601  else {
5602  ADD_INSN1(ret, line, opt_str_freeze, str);
5603  }
5604  if (popped) {
5605  ADD_INSN(ret, line, pop);
5606  }
5607  break;
5608  }
5609  /* optimization shortcut
5610  * obj["literal"] -> opt_aref_with(obj, "literal")
5611  */
5612  if (node->nd_mid == idAREF && !private_recv_p(node) && node->nd_args &&
5613  nd_type(node->nd_args) == NODE_ARRAY && node->nd_args->nd_alen == 1 &&
5614  nd_type(node->nd_args->nd_head) == NODE_STR &&
5615  ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
5616  ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
5617  VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
5618  node->nd_args->nd_head->nd_lit = str;
5619  CHECK(COMPILE(ret, "recv", node->nd_recv));
5620  ADD_INSN3(ret, line, opt_aref_with,
5621  new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE),
5622  NULL/* CALL_CACHE */, str);
5623  if (popped) {
5624  ADD_INSN(ret, line, pop);
5625  }
5626  break;
5627  }
5628  case NODE_QCALL:
5629  case NODE_FCALL:
5630  case NODE_VCALL:{ /* VCALL: variable or call */
5631  /*
5632  call: obj.method(...)
5633  fcall: func(...)
5634  vcall: func
5635  */
5636  DECL_ANCHOR(recv);
5637  DECL_ANCHOR(args);
5638  LABEL *else_label = 0;
5639  LABEL *end_label = 0;
5640  VALUE branches = 0;
5641  ID mid = node->nd_mid;
5642  VALUE argc;
5643  unsigned int flag = 0;
5644  struct rb_call_info_kw_arg *keywords = NULL;
5645  const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
5646  ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
5647 
5648  INIT_ANCHOR(recv);
5649  INIT_ANCHOR(args);
5650 #if SUPPORT_JOKE
5651  if (nd_type(node) == NODE_VCALL) {
5652  ID id_bitblt;
5653  ID id_answer;
5654 
5655  CONST_ID(id_bitblt, "bitblt");
5656  CONST_ID(id_answer, "the_answer_to_life_the_universe_and_everything");
5657 
5658  if (mid == id_bitblt) {
5659  ADD_INSN(ret, line, bitblt);
5660  break;
5661  }
5662  else if (mid == id_answer) {
5663  ADD_INSN(ret, line, answer);
5664  break;
5665  }
5666  }
5667  /* only joke */
5668  {
5669  ID goto_id;
5670  ID label_id;
5671 
5672  CONST_ID(goto_id, "__goto__");
5673  CONST_ID(label_id, "__label__");
5674 
5675  if (nd_type(node) == NODE_FCALL &&
5676  (mid == goto_id || mid == label_id)) {
5677  LABEL *label;
5678  st_data_t data;
5679  st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
5680  VALUE label_name;
5681 
5682  if (!labels_table) {
5683  labels_table = st_init_numtable();
5684  ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table;
5685  }
5686  if (nd_type(node->nd_args->nd_head) == NODE_LIT &&
5687  SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
5688 
5689  label_name = node->nd_args->nd_head->nd_lit;
5690  if (!st_lookup(labels_table, (st_data_t)label_name, &data)) {
5691  label = NEW_LABEL(line);
5692  label->position = line;
5693  st_insert(labels_table, (st_data_t)label_name, (st_data_t)label);
5694  }
5695  else {
5696  label = (LABEL *)data;
5697  }
5698  }
5699  else {
5700  COMPILE_ERROR(ERROR_ARGS "invalid goto/label format");
5701  goto ng;
5702  }
5703 
5704 
5705  if (mid == goto_id) {
5706  ADD_INSNL(ret, line, jump, label);
5707  }
5708  else {
5709  ADD_LABEL(ret, label);
5710  }
5711  break;
5712  }
5713  }
5714 #endif
5715  /* receiver */
5716  if (type == NODE_CALL || type == NODE_OPCALL || type == NODE_QCALL) {
5717  CHECK(COMPILE(recv, "recv", node->nd_recv));
5718  if (type == NODE_QCALL) {
5719  else_label = NEW_LABEL(line);
5720  end_label = NEW_LABEL(line);
5721 
5722  DECL_BRANCH_BASE(branches, nd_line(node), "&.");
5723  ADD_INSN(recv, line, dup);
5724  ADD_INSNL(recv, line, branchnil, else_label);
5725  ADD_TRACE_BRANCH_COVERAGE(recv, nd_line(node), "then", branches);
5726  }
5727  }
5728  else if (type == NODE_FCALL || type == NODE_VCALL) {
5729  ADD_CALL_RECEIVER(recv, line);
5730  }
5731 
5732  /* args */
5733  if (type != NODE_VCALL) {
5734  argc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
5735  CHECK(!NIL_P(argc));
5736  }
5737  else {
5738  argc = INT2FIX(0);
5739  }
5740 
5741  ADD_SEQ(ret, recv);
5742  ADD_SEQ(ret, args);
5743 
5744  debugp_param("call args argc", argc);
5745  debugp_param("call method", ID2SYM(mid));
5746 
5747  switch ((int)type) {
5748  case NODE_VCALL:
5749  flag |= VM_CALL_VCALL;
5750  /* VCALL is funcall, so fall through */
5751  case NODE_FCALL:
5752  flag |= VM_CALL_FCALL;
5753  }
5754 
5755  ADD_SEND_R(ret, line, mid, argc, parent_block, INT2FIX(flag), keywords);
5756 
5757  if (else_label && end_label) {
5758  ADD_INSNL(ret, line, jump, end_label);
5759  ADD_LABEL(ret, else_label);
5760  ADD_TRACE_BRANCH_COVERAGE(ret, nd_line(node), "else", branches);
5761  ADD_LABEL(ret, end_label);
5762  }
5763  if (popped) {
5764  ADD_INSN(ret, line, pop);
5765  }
5766  break;
5767  }
5768  case NODE_SUPER:
5769  case NODE_ZSUPER:{
5770  DECL_ANCHOR(args);
5771  int argc;
5772  unsigned int flag = 0;
5773  struct rb_call_info_kw_arg *keywords = NULL;
5774  const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
5775 
5776  INIT_ANCHOR(args);
5777  ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
5778  if (type == NODE_SUPER) {
5779  VALUE vargc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
5780  CHECK(!NIL_P(vargc));
5781  argc = FIX2INT(vargc);
5782  }
5783  else {
5784  /* NODE_ZSUPER */
5785  int i;
5786  const rb_iseq_t *liseq = iseq->body->local_iseq;
5787  int lvar_level = get_lvar_level(iseq);
5788 
5789  argc = liseq->body->param.lead_num;
5790 
5791  /* normal arguments */
5792  for (i = 0; i < liseq->body->param.lead_num; i++) {
5793  int idx = liseq->body->local_table_size - i;
5794  ADD_GETLOCAL(args, line, idx, lvar_level);
5795  }
5796 
5797  if (liseq->body->param.flags.has_opt) {
5798  /* optional arguments */
5799  int j;
5800  for (j = 0; j < liseq->body->param.opt_num; j++) {
5801  int idx = liseq->body->local_table_size - (i + j);
5802  ADD_GETLOCAL(args, line, idx, lvar_level);
5803  }
5804  i += j;
5805  argc = i;
5806  }
5807  if (liseq->body->param.flags.has_rest) {
5808  /* rest argument */
5809  int idx = liseq->body->local_table_size - liseq->body->param.rest_start;
5810  ADD_GETLOCAL(args, line, idx, lvar_level);
5811 
5812  argc = liseq->body->param.rest_start + 1;
5813  flag |= VM_CALL_ARGS_SPLAT;
5814  }
5815  if (liseq->body->param.flags.has_post) {
5816  /* post arguments */
5817  int post_len = liseq->body->param.post_num;
5818  int post_start = liseq->body->param.post_start;
5819 
5820  if (liseq->body->param.flags.has_rest) {
5821  int j;
5822  for (j=0; j<post_len; j++) {
5823  int idx = liseq->body->local_table_size - (post_start + j);
5824  ADD_GETLOCAL(args, line, idx, lvar_level);
5825  }
5826  ADD_INSN1(args, line, newarray, INT2FIX(j));
5827  ADD_INSN (args, line, concatarray);
5828  /* argc is settled at above */
5829  }
5830  else {
5831  int j;
5832  for (j=0; j<post_len; j++) {
5833  int idx = liseq->body->local_table_size - (post_start + j);
5834  ADD_GETLOCAL(args, line, idx, lvar_level);
5835  }
5836  argc = post_len + post_start;
5837  }
5838  }
5839 
5840  if (liseq->body->param.flags.has_kw) { /* TODO: support keywords */
5841  int local_size = liseq->body->local_table_size;
5842  argc++;
5843 
5844  ADD_INSN1(args, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
5845 
5846  if (liseq->body->param.flags.has_kwrest) {
5847  int idx = liseq->body->local_table_size - liseq->body->param.keyword->rest_start;
5848  ADD_GETLOCAL(args, line, idx, lvar_level);
5849  ADD_SEND (args, line, rb_intern("dup"), INT2FIX(0));
5850  }
5851  else {
5852  ADD_INSN1(args, line, newhash, INT2FIX(0));
5853  }
5854  for (i = 0; i < liseq->body->param.keyword->num; ++i) {
5855  ID id = liseq->body->param.keyword->table[i];
5856  int idx = local_size - get_local_var_idx(liseq, id);
5857  ADD_INSN1(args, line, putobject, ID2SYM(id));
5858  ADD_GETLOCAL(args, line, idx, lvar_level);
5859  }
5860  ADD_SEND(args, line, id_core_hash_merge_ptr, INT2FIX(i * 2 + 1));
5861  if (liseq->body->param.flags.has_rest) {
5862  ADD_INSN1(args, line, newarray, INT2FIX(1));
5863  ADD_INSN (args, line, concatarray);
5864  --argc;
5865  }
5866  }
5867  else if (liseq->body->param.flags.has_kwrest) {
5868  int idx = liseq->body->local_table_size - liseq->body->param.keyword->rest_start;
5869  ADD_GETLOCAL(args, line, idx, lvar_level);
5870 
5871  ADD_SEND (args, line, rb_intern("dup"), INT2FIX(0));
5872  if (liseq->body->param.flags.has_rest) {
5873  ADD_INSN1(args, line, newarray, INT2FIX(1));
5874  ADD_INSN (args, line, concatarray);
5875  }
5876  else {
5877  argc++;
5878  }
5879  }
5880  }
5881 
5882  /* dummy receiver */
5883  ADD_INSN1(ret, line, putobject, type == NODE_ZSUPER ? Qfalse : Qtrue);
5884  ADD_SEQ(ret, args);
5885  ADD_INSN3(ret, line, invokesuper,
5886  new_callinfo(iseq, 0, argc, flag | VM_CALL_SUPER | VM_CALL_FCALL, keywords, parent_block != NULL),
5887  Qnil, /* CALL_CACHE */
5888  parent_block);
5889 
5890  if (popped) {
5891  ADD_INSN(ret, line, pop);
5892  }
5893  break;
5894  }
5895  case NODE_ARRAY:{
5896  CHECK(compile_array(iseq, ret, node, COMPILE_ARRAY_TYPE_ARRAY, NULL, NULL, popped) >= 0);
5897  break;
5898  }
5899  case NODE_ZARRAY:{
5900  if (!popped) {
5901  ADD_INSN1(ret, line, newarray, INT2FIX(0));
5902  }
5903  break;
5904  }
5905  case NODE_VALUES:{
5906  NODE *n = node;
5907  if (popped) {
5908  COMPILE_ERROR(ERROR_ARGS "NODE_VALUES: must not be popped");
5909  }
5910  while (n) {
5911  CHECK(COMPILE(ret, "values item", n->nd_head));
5912  n = n->nd_next;
5913  }
5914  ADD_INSN1(ret, line, newarray, INT2FIX(node->nd_alen));
5915  break;
5916  }
5917  case NODE_HASH:{
5918  DECL_ANCHOR(list);
5919  int type = node->nd_head ? nd_type(node->nd_head) : NODE_ZARRAY;
5920 
5921  INIT_ANCHOR(list);
5922  switch (type) {
5923  case NODE_ARRAY:
5924  CHECK(compile_array(iseq, list, node->nd_head, COMPILE_ARRAY_TYPE_HASH, NULL, NULL, popped) >= 0);
5925  ADD_SEQ(ret, list);
5926  break;
5927 
5928  case NODE_ZARRAY:
5929  if (popped) break;
5930  ADD_INSN1(ret, line, newhash, INT2FIX(0));
5931  break;
5932 
5933  default:
5934  COMPILE_ERROR(ERROR_ARGS_AT(node->nd_head) "can't make hash with this node: %s",
5935  ruby_node_name(type));
5936  goto ng;
5937  }
5938  break;
5939  }
5940  case NODE_RETURN:{
5941  rb_iseq_t *is = iseq;
5942 
5943  if (is) {
5944  enum iseq_type type = is->body->type;
5945  const rb_iseq_t *parent_iseq = is->body->parent_iseq;
5946  enum iseq_type parent_type;
5947 
5948  if (type == ISEQ_TYPE_TOP) {
5949  LABEL *splabel = NEW_LABEL(line);
5950  ADD_LABEL(ret, splabel);
5951  ADD_ADJUST(ret, line, 0);
5952  ADD_INSN(ret, line, putnil);
5953  ADD_INSN(ret, line, leave);
5954  ADD_ADJUST_RESTORE(ret, splabel);
5955  }
5956  else if ((type == ISEQ_TYPE_RESCUE || type == ISEQ_TYPE_ENSURE || type == ISEQ_TYPE_MAIN) &&
5957  parent_iseq &&
5958  ((parent_type = parent_iseq->body->type) == ISEQ_TYPE_TOP ||
5959  parent_type == ISEQ_TYPE_MAIN)) {
5960  ADD_INSN(ret, line, putnil);
5961  ADD_INSN1(ret, line, throw, INT2FIX(TAG_RETURN));
5962  if (popped) {
5963  ADD_INSN(ret, line, pop);
5964  }
5965  }
5966  else {
5967  LABEL *splabel = 0;
5968 
5969  if (type == ISEQ_TYPE_METHOD) {
5970  splabel = NEW_LABEL(0);
5971  ADD_LABEL(ret, splabel);
5972  ADD_ADJUST(ret, line, 0);
5973  }
5974 
5975  CHECK(COMPILE(ret, "return nd_stts (return val)", node->nd_stts));
5976 
5977  if (type == ISEQ_TYPE_METHOD) {
5978  add_ensure_iseq(ret, iseq, 1);
5979  ADD_TRACE(ret, line, RUBY_EVENT_RETURN);
5980  ADD_INSN(ret, line, leave);
5981  ADD_ADJUST_RESTORE(ret, splabel);
5982 
5983  if (!popped) {
5984  ADD_INSN(ret, line, putnil);
5985  }
5986  }
5987  else {
5988  ADD_INSN1(ret, line, throw, INT2FIX(TAG_RETURN));
5989  if (popped) {
5990  ADD_INSN(ret, line, pop);
5991  }
5992  }
5993  }
5994  }
5995  break;
5996  }
5997  case NODE_YIELD:{
5998  DECL_ANCHOR(args);
5999  VALUE argc;
6000  unsigned int flag = 0;
6001  struct rb_call_info_kw_arg *keywords = NULL;
6002 
6003  INIT_ANCHOR(args);
6004  if (iseq->body->type == ISEQ_TYPE_TOP ||
6005  iseq->body->type == ISEQ_TYPE_MAIN) {
6006  COMPILE_ERROR(ERROR_ARGS "Invalid yield");
6007  goto ng;
6008  }
6009 
6010  if (node->nd_head) {
6011  argc = setup_args(iseq, args, node->nd_head, &flag, &keywords);
6012  CHECK(!NIL_P(argc));
6013  }
6014  else {
6015  argc = INT2FIX(0);
6016  }
6017 
6018  ADD_SEQ(ret, args);
6019  ADD_INSN1(ret, line, invokeblock, new_callinfo(iseq, 0, FIX2INT(argc), flag, keywords, FALSE));
6020 
6021  if (popped) {
6022  ADD_INSN(ret, line, pop);
6023  }
6024  break;
6025  }
6026  case NODE_LVAR:{
6027  if (!popped) {
6028  ID id = node->nd_vid;
6029  int idx = iseq->body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id);
6030 
6031  debugs("id: %s idx: %d\n", rb_id2name(id), idx);
6032  ADD_GETLOCAL(ret, line, idx, get_lvar_level(iseq));
6033  }
6034  break;
6035  }
6036  case NODE_DVAR:{
6037  int lv, idx, ls;
6038  debugi("nd_vid", node->nd_vid);
6039  if (!popped) {
6040  idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
6041  if (idx < 0) {
6042  COMPILE_ERROR(ERROR_ARGS "unknown dvar (%"PRIsVALUE")",
6043  rb_id2str(node->nd_vid));
6044  goto ng;
6045  }
6046  ADD_GETLOCAL(ret, line, ls - idx, lv);
6047  }
6048  break;
6049  }
6050  case NODE_GVAR:{
6051  ADD_INSN1(ret, line, getglobal,
6052  ((VALUE)node->nd_entry | 1));
6053  if (popped) {
6054  ADD_INSN(ret, line, pop);
6055  }
6056  break;
6057  }
6058  case NODE_IVAR:{
6059  debugi("nd_vid", node->nd_vid);
6060  if (!popped) {
6061  ADD_INSN2(ret, line, getinstancevariable,
6062  ID2SYM(node->nd_vid),
6063  get_ivar_ic_value(iseq,node->nd_vid));
6064  }
6065  break;
6066  }
6067  case NODE_CONST:{
6068  debugi("nd_vid", node->nd_vid);
6069 
6070  if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
6071  LABEL *lend = NEW_LABEL(line);
6072  int ic_index = iseq->body->is_size++;
6073 
6074  ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index));
6075  ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid));
6076  ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index));
6077  ADD_LABEL(ret, lend);
6078  }
6079  else {
6080  ADD_INSN(ret, line, putnil);
6081  ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid));
6082  }
6083 
6084  if (popped) {
6085  ADD_INSN(ret, line, pop);
6086  }
6087  break;
6088  }
6089  case NODE_CVAR:{
6090  if (!popped) {
6091  ADD_INSN1(ret, line, getclassvariable,
6092  ID2SYM(node->nd_vid));
6093  }
6094  break;
6095  }
6096  case NODE_NTH_REF:{
6097  if (!popped) {
6098  if (!node->nd_nth) {
6099  ADD_INSN(ret, line, putnil);
6100  break;
6101  }
6102  ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */,
6103  INT2FIX(node->nd_nth << 1));
6104  }
6105  break;
6106  }
6107  case NODE_BACK_REF:{
6108  if (!popped) {
6109  ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */,
6110  INT2FIX(0x01 | (node->nd_nth << 1)));
6111  }
6112  break;
6113  }
6114  case NODE_MATCH:
6115  case NODE_MATCH2:
6116  case NODE_MATCH3:{
6117  DECL_ANCHOR(recv);
6118  DECL_ANCHOR(val);
6119 
6120  INIT_ANCHOR(recv);
6121  INIT_ANCHOR(val);
6122  switch (nd_type(node)) {
6123  case NODE_MATCH:
6124  ADD_INSN1(recv, line, putobject, node->nd_lit);
6125  ADD_INSN2(val, line, getspecial, INT2FIX(0),
6126  INT2FIX(0));
6127  break;
6128  case NODE_MATCH2:
6129  CHECK(COMPILE(recv, "receiver", node->nd_recv));
6130  CHECK(COMPILE(val, "value", node->nd_value));
6131  break;
6132  case NODE_MATCH3:
6133  CHECK(COMPILE(recv, "receiver", node->nd_value));
6134  CHECK(COMPILE(val, "value", node->nd_recv));
6135  break;
6136  }
6137 
6138  if (ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
6139  /* TODO: detect by node */
6140  if (recv->last == recv->anchor.next &&
6141  INSN_OF(recv->last) == BIN(putobject) &&
6142  nd_type(node) == NODE_MATCH2) {
6143  ADD_SEQ(ret, val);
6144  ADD_INSN1(ret, line, opt_regexpmatch1,
6145  OPERAND_AT(recv->last, 0));
6146  }
6147  else {
6148  ADD_SEQ(ret, recv);
6149  ADD_SEQ(ret, val);
6150  ADD_INSN2(ret, line, opt_regexpmatch2, new_callinfo(iseq, idEqTilde, 1, 0, NULL, FALSE), Qnil);
6151  }
6152  }
6153  else {
6154  ADD_SEQ(ret, recv);
6155  ADD_SEQ(ret, val);
6156  ADD_SEND(ret, line, idEqTilde, INT2FIX(1));
6157  }
6158 
6159  if (node->nd_args) {
6160  compile_named_capture_assign(iseq, ret, node->nd_args);
6161  }
6162 
6163  if (popped) {
6164  ADD_INSN(ret, line, pop);
6165  }
6166  break;
6167  }
6168  case NODE_LIT:{
6169  debugp_param("lit", node->nd_lit);
6170  if (!popped) {
6171  ADD_INSN1(ret, line, putobject, node->nd_lit);
6172  }
6173  break;
6174  }
6175  case NODE_STR:{
6176  debugp_param("nd_lit", node->nd_lit);
6177  if (!popped) {
6178  node->nd_lit = rb_fstring(node->nd_lit);
6179  if (!ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
6180  ADD_INSN1(ret, line, putstring, node->nd_lit);
6181  }
6182  else {
6183  if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
6184  VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line));
6185  VALUE str = rb_str_dup(node->nd_lit);
6186  rb_ivar_set(str, id_debug_created_info, rb_obj_freeze(debug_info));
6187  ADD_INSN1(ret, line, putobject, rb_obj_freeze(str));
6188  iseq_add_mark_object_compile_time(iseq, str);
6189  }
6190  else {
6191  ADD_INSN1(ret, line, putobject, node->nd_lit);
6192  }
6193  }
6194  }
6195  break;
6196  }
6197  case NODE_DSTR:{
6198  compile_dstr(iseq, ret, node);
6199 
6200  if (popped) {
6201  ADD_INSN(ret, line, pop);
6202  }
6203  else {
6204  if (ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
6205  VALUE debug_info = Qnil;
6206  if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
6207  debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line));
6208  iseq_add_mark_object_compile_time(iseq, rb_obj_freeze(debug_info));
6209  }
6210  ADD_INSN1(ret, line, freezestring, debug_info);
6211  }
6212  }
6213  break;
6214  }
6215  case NODE_XSTR:{
6216  node->nd_lit = rb_fstring(node->nd_lit);
6217  ADD_CALL_RECEIVER(ret, line);
6218  ADD_INSN1(ret, line, putobject, node->nd_lit);
6219  ADD_CALL(ret, line, idBackquote, INT2FIX(1));
6220 
6221  if (popped) {
6222  ADD_INSN(ret, line, pop);
6223  }
6224  break;
6225  }
6226  case NODE_DXSTR:{
6227  ADD_CALL_RECEIVER(ret, line);
6228  compile_dstr(iseq, ret, node);
6229  ADD_CALL(ret, line, idBackquote, INT2FIX(1));
6230 
6231  if (popped) {
6232  ADD_INSN(ret, line, pop);
6233  }
6234  break;
6235  }
6236  case NODE_EVSTR:{
6237  CHECK(COMPILE(ret, "nd_body", node->nd_body));
6238 
6239  if (popped) {
6240  ADD_INSN(ret, line, pop);
6241  }
6242  else {
6243  const unsigned int flag = VM_CALL_FCALL;
6244  LABEL *isstr = NEW_LABEL(line);
6245  ADD_INSN(ret, line, dup);
6246  ADD_INSN2(ret, line, branchiftype, INT2FIX(T_STRING), isstr);
6247  LABEL_REF(isstr);
6248  ADD_INSN(ret, line, dup);
6249  ADD_SEND_R(ret, line, idTo_s, INT2FIX(0), NULL, INT2FIX(flag), NULL);
6250  ADD_INSN(ret, line, tostring);
6251  ADD_LABEL(ret, isstr);
6252  }
6253  break;
6254  }
6255  case NODE_DREGX:{
6256  compile_dregx(iseq, ret, node);
6257 
6258  if (popped) {
6259  ADD_INSN(ret, line, pop);
6260  }
6261  break;
6262  }
6263  case NODE_SCOPE:{
6264  int ic_index = iseq->body->is_size++;
6265  const rb_iseq_t *block_iseq = NEW_CHILD_ISEQ(node, make_name_for_block(iseq),
6266  ISEQ_TYPE_ONCE_GUARD, line);
6267 
6268  ADD_INSN2(ret, line, once, block_iseq, INT2FIX(ic_index));
6269 
6270  if (popped) {
6271  ADD_INSN(ret, line, pop);
6272  }
6273  break;
6274  }
6275  case NODE_ARGSCAT:{
6276  if (popped) {
6277  CHECK(COMPILE(ret, "argscat head", node->nd_head));
6278  ADD_INSN1(ret, line, splatarray, Qfalse);
6279  ADD_INSN(ret, line, pop);
6280  CHECK(COMPILE(ret, "argscat body", node->nd_body));
6281  ADD_INSN1(ret, line, splatarray, Qfalse);
6282  ADD_INSN(ret, line, pop);
6283  }
6284  else {
6285  CHECK(COMPILE(ret, "argscat head", node->nd_head));
6286  CHECK(COMPILE(ret, "argscat body", node->nd_body));
6287  ADD_INSN(ret, line, concatarray);
6288  }
6289  break;
6290  }
6291  case NODE_ARGSPUSH:{
6292  if (popped) {
6293  CHECK(COMPILE(ret, "arsgpush head", node->nd_head));
6294  ADD_INSN1(ret, line, splatarray, Qfalse);
6295  ADD_INSN(ret, line, pop);
6296  CHECK(COMPILE_(ret, "argspush body", node->nd_body, popped));
6297  }
6298  else {
6299  CHECK(COMPILE(ret, "arsgpush head", node->nd_head));
6300  CHECK(COMPILE_(ret, "argspush body", node->nd_body, popped));
6301  ADD_INSN1(ret, line, newarray, INT2FIX(1));
6302  ADD_INSN(ret, line, concatarray);
6303  }
6304  break;
6305  }
6306  case NODE_SPLAT:{
6307  CHECK(COMPILE(ret, "splat", node->nd_head));
6308  ADD_INSN1(ret, line, splatarray, Qtrue);
6309 
6310  if (popped) {
6311  ADD_INSN(ret, line, pop);
6312  }
6313  break;
6314  }
6315  case NODE_DEFN:{
6316  const rb_iseq_t *method_iseq = NEW_ISEQ(node->nd_defn,
6317  rb_id2str(node->nd_mid),
6318  ISEQ_TYPE_METHOD, line);
6319 
6320  debugp_param("defn/iseq", rb_iseqw_new(method_iseq));
6321 
6322  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6323  ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid));
6324  ADD_INSN1(ret, line, putiseq, method_iseq);
6325  ADD_SEND (ret, line, id_core_define_method, INT2FIX(2));
6326 
6327  if (popped) {
6328  ADD_INSN(ret, line, pop);
6329  }
6330 
6331  break;
6332  }
6333  case NODE_DEFS:{
6334  const rb_iseq_t * singleton_method = NEW_ISEQ(node->nd_defn,
6335  rb_id2str(node->nd_mid),
6336  ISEQ_TYPE_METHOD, line);
6337 
6338  debugp_param("defs/iseq", rb_iseqw_new(singleton_method));
6339 
6340  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6341  CHECK(COMPILE(ret, "defs: recv", node->nd_recv));
6342  ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid));
6343  ADD_INSN1(ret, line, putiseq, singleton_method);
6345 
6346  if (popped) {
6347  ADD_INSN(ret, line, pop);
6348  }
6349  break;
6350  }
6351  case NODE_ALIAS:{
6352  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6353  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
6354  CHECK(COMPILE(ret, "alias arg1", node->u1.node));
6355  CHECK(COMPILE(ret, "alias arg2", node->u2.node));
6356  ADD_SEND(ret, line, id_core_set_method_alias, INT2FIX(3));
6357 
6358  if (popped) {
6359  ADD_INSN(ret, line, pop);
6360  }
6361  break;
6362  }
6363  case NODE_VALIAS:{
6364  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6365  ADD_INSN1(ret, line, putobject, ID2SYM(node->u1.id));
6366  ADD_INSN1(ret, line, putobject, ID2SYM(node->u2.id));
6368 
6369  if (popped) {
6370  ADD_INSN(ret, line, pop);
6371  }
6372  break;
6373  }
6374  case NODE_UNDEF:{
6375  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6376  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
6377  CHECK(COMPILE(ret, "undef arg", node->u2.node));
6378  ADD_SEND(ret, line, id_core_undef_method, INT2FIX(2));
6379 
6380  if (popped) {
6381  ADD_INSN(ret, line, pop);
6382  }
6383  break;
6384  }
6385  case NODE_CLASS:{
6386  const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(node->nd_body,
6387  rb_sprintf("<class:%"PRIsVALUE">", rb_id2str(node->nd_cpath->nd_mid)),
6388  ISEQ_TYPE_CLASS, line);
6389  const int flags = VM_DEFINECLASS_TYPE_CLASS |
6390  (node->nd_super ? VM_DEFINECLASS_FLAG_HAS_SUPERCLASS : 0) |
6391  compile_cpath(ret, iseq, node->nd_cpath);
6392 
6393  CHECK(COMPILE(ret, "super", node->nd_super));
6394  ADD_INSN3(ret, line, defineclass, ID2SYM(node->nd_cpath->nd_mid), class_iseq, INT2FIX(flags));
6395 
6396  if (popped) {
6397  ADD_INSN(ret, line, pop);
6398  }
6399  break;
6400  }
6401  case NODE_MODULE:{
6402  const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(node->nd_body,
6403  rb_sprintf("<module:%"PRIsVALUE">", rb_id2str(node->nd_cpath->nd_mid)),
6404  ISEQ_TYPE_CLASS, line);
6405  const int flags = VM_DEFINECLASS_TYPE_MODULE |
6406  compile_cpath(ret, iseq, node->nd_cpath);
6407 
6408  ADD_INSN (ret, line, putnil); /* dummy */
6409  ADD_INSN3(ret, line, defineclass, ID2SYM(node->nd_cpath->nd_mid), module_iseq, INT2FIX(flags));
6410 
6411  if (popped) {
6412  ADD_INSN(ret, line, pop);
6413  }
6414  break;
6415  }
6416  case NODE_SCLASS:{
6417  ID singletonclass;
6418  const rb_iseq_t *singleton_class = NEW_ISEQ(node->nd_body, rb_fstring_cstr("singleton class"),
6419  ISEQ_TYPE_CLASS, line);
6420 
6421  CHECK(COMPILE(ret, "sclass#recv", node->nd_recv));
6422  ADD_INSN (ret, line, putnil);
6423  CONST_ID(singletonclass, "singletonclass");
6424  ADD_INSN3(ret, line, defineclass,
6425  ID2SYM(singletonclass), singleton_class,
6427 
6428  if (popped) {
6429  ADD_INSN(ret, line, pop);
6430  }
6431  break;
6432  }
6433  case NODE_COLON2:{
6434  if (rb_is_const_id(node->nd_mid)) {
6435  /* constant */
6436  LABEL *lend = NEW_LABEL(line);
6437  int ic_index = iseq->body->is_size++;
6438 
6439  DECL_ANCHOR(pref);
6440  DECL_ANCHOR(body);
6441 
6442  INIT_ANCHOR(pref);
6443  INIT_ANCHOR(body);
6444  CHECK(compile_const_prefix(iseq, node, pref, body));
6445  if (LIST_SIZE_ZERO(pref)) {
6446  if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
6447  ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index));
6448  }
6449  else {
6450  ADD_INSN(ret, line, putnil);
6451  }
6452 
6453  ADD_SEQ(ret, body);
6454 
6455  if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
6456  ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index));
6457  ADD_LABEL(ret, lend);
6458  }
6459  }
6460  else {
6461  ADD_SEQ(ret, pref);
6462  ADD_SEQ(ret, body);
6463  }
6464  }
6465  else {
6466  /* function call */
6467  ADD_CALL_RECEIVER(ret, line);
6468  CHECK(COMPILE(ret, "colon2#nd_head", node->nd_head));
6469  ADD_CALL(ret, line, node->nd_mid, INT2FIX(1));
6470  }
6471  if (popped) {
6472  ADD_INSN(ret, line, pop);
6473  }
6474  break;
6475  }
6476  case NODE_COLON3:{
6477  LABEL *lend = NEW_LABEL(line);
6478  int ic_index = iseq->body->is_size++;
6479 
6480  debugi("colon3#nd_mid", node->nd_mid);
6481 
6482  /* add cache insn */
6483  if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
6484  ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index));
6485  ADD_INSN(ret, line, pop);
6486  }
6487 
6488  ADD_INSN1(ret, line, putobject, rb_cObject);
6489  ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_mid));
6490 
6491  if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
6492  ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index));
6493  ADD_LABEL(ret, lend);
6494  }
6495 
6496  if (popped) {
6497  ADD_INSN(ret, line, pop);
6498  }
6499  break;
6500  }
6501  case NODE_DOT2:
6502  case NODE_DOT3:{
6503  int excl = type == NODE_DOT3;
6504  VALUE flag = INT2FIX(excl);
6505  NODE *b = node->nd_beg;
6506  NODE *e = node->nd_end;
6507  if (number_literal_p(b) && number_literal_p(e)) {
6508  if (!popped) {
6509  VALUE val = rb_range_new(b->nd_lit, e->nd_lit, excl);
6510  iseq_add_mark_object_compile_time(iseq, val);
6511  ADD_INSN1(ret, line, putobject, val);
6512  }
6513  }
6514  else {
6515  CHECK(COMPILE_(ret, "min", b, popped));
6516  CHECK(COMPILE_(ret, "max", e, popped));
6517  if (!popped) {
6518  ADD_INSN1(ret, line, newrange, flag);
6519  }
6520  }
6521  break;
6522  }
6523  case NODE_FLIP2:
6524  case NODE_FLIP3:{
6525  LABEL *lend = NEW_LABEL(line);
6526  LABEL *ltrue = NEW_LABEL(line);
6527  LABEL *lfalse = NEW_LABEL(line);
6528  CHECK(compile_flip_flop(iseq, ret, node, type == NODE_FLIP2,
6529  ltrue, lfalse));
6530  ADD_LABEL(ret, ltrue);
6531  ADD_INSN1(ret, line, putobject, Qtrue);
6532  ADD_INSNL(ret, line, jump, lend);
6533  ADD_LABEL(ret, lfalse);
6534  ADD_INSN1(ret, line, putobject, Qfalse);
6535  ADD_LABEL(ret, lend);
6536  break;
6537  }
6538  case NODE_SELF:{
6539  if (!popped) {
6540  ADD_INSN(ret, line, putself);
6541  }
6542  break;
6543  }
6544  case NODE_NIL:{
6545  if (!popped) {
6546  ADD_INSN(ret, line, putnil);
6547  }
6548  break;
6549  }
6550  case NODE_TRUE:{
6551  if (!popped) {
6552  ADD_INSN1(ret, line, putobject, Qtrue);
6553  }
6554  break;
6555  }
6556  case NODE_FALSE:{
6557  if (!popped) {
6558  ADD_INSN1(ret, line, putobject, Qfalse);
6559  }
6560  break;
6561  }
6562  case NODE_ERRINFO:{
6563  if (!popped) {
6564  if (iseq->body->type == ISEQ_TYPE_RESCUE) {
6565  ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0);
6566  }
6567  else {
6568  const rb_iseq_t *ip = iseq;
6569  int level = 0;
6570  while (ip) {
6571  if (ip->body->type == ISEQ_TYPE_RESCUE) {
6572  break;
6573  }
6574  ip = ip->body->parent_iseq;
6575  level++;
6576  }
6577  if (ip) {
6578  ADD_GETLOCAL(ret, line, LVAR_ERRINFO, level);
6579  }
6580  else {
6581  ADD_INSN(ret, line, putnil);
6582  }
6583  }
6584  }
6585  break;
6586  }
6587  case NODE_DEFINED:
6588  if (!popped) {
6589  CHECK(compile_defined_expr(iseq, ret, node, Qtrue));
6590  }
6591  break;
6592  case NODE_POSTEXE:{
6593  /* compiled to:
6594  * ONCE{ rb_mRubyVMFrozenCore::core#set_postexe{ ... } }
6595  */
6596  int is_index = iseq->body->is_size++;
6597  const rb_iseq_t *once_iseq = NEW_CHILD_ISEQ((NODE *)IFUNC_NEW(build_postexe_iseq, node->nd_body, 0),
6598  make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
6599 
6600  ADD_INSN2(ret, line, once, once_iseq, INT2FIX(is_index));
6601 
6602  if (popped) {
6603  ADD_INSN(ret, line, pop);
6604  }
6605  break;
6606  }
6607  case NODE_KW_ARG:
6608  {
6609  LABEL *end_label = NEW_LABEL(nd_line(node));
6610  NODE *default_value = node->nd_body->nd_value;
6611 
6612  if (default_value == (NODE *)-1) {
6613  /* required argument. do nothing */
6614  COMPILE_ERROR(ERROR_ARGS "unreachable");
6615  goto ng;
6616  }
6617  else if (nd_type(default_value) == NODE_LIT ||
6618  nd_type(default_value) == NODE_NIL ||
6619  nd_type(default_value) == NODE_TRUE ||
6620  nd_type(default_value) == NODE_FALSE) {
6621  COMPILE_ERROR(ERROR_ARGS "unreachable");
6622  goto ng;
6623  }
6624  else {
6625  /* if keywordcheck(_kw_bits, nth_keyword)
6626  * kw = default_value
6627  * end
6628  */
6629  int kw_bits_idx = iseq->body->local_table_size - iseq->body->param.keyword->bits_start;
6630  int keyword_idx = iseq->body->param.keyword->num;
6631 
6632  ADD_INSN2(ret, line, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(keyword_idx));
6633  ADD_INSNL(ret, line, branchif, end_label);
6634  CHECK(COMPILE_POPPED(ret, "keyword default argument", node->nd_body));
6635  ADD_LABEL(ret, end_label);
6636  }
6637 
6638  break;
6639  }
6640  case NODE_DSYM:{
6641  compile_dstr(iseq, ret, node);
6642  if (!popped) {
6643  ADD_INSN(ret, line, intern);
6644  }
6645  else {
6646  ADD_INSN(ret, line, pop);
6647  }
6648  break;
6649  }
6650  case NODE_ATTRASGN:{
6651  DECL_ANCHOR(recv);
6652  DECL_ANCHOR(args);
6653  unsigned int flag = 0;
6654  ID mid = node->nd_mid;
6655  LABEL *lskip = 0;
6656  VALUE argc;
6657 
6658  /* optimization shortcut
6659  * obj["literal"] = value -> opt_aset_with(obj, "literal", value)
6660  */
6661  if (mid == idASET && !private_recv_p(node) && node->nd_args &&
6662  nd_type(node->nd_args) == NODE_ARRAY && node->nd_args->nd_alen == 2 &&
6663  nd_type(node->nd_args->nd_head) == NODE_STR &&
6664  ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
6665  ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction)
6666  {
6667  VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
6668  node->nd_args->nd_head->nd_lit = str;
6669  iseq_add_mark_object(iseq, str);
6670  CHECK(COMPILE(ret, "recv", node->nd_recv));
6671  CHECK(COMPILE(ret, "value", node->nd_args->nd_next->nd_head));
6672  if (!popped) {
6673  ADD_INSN(ret, line, swap);
6674  ADD_INSN1(ret, line, topn, INT2FIX(1));
6675  }
6676  ADD_INSN3(ret, line, opt_aset_with,
6677  new_callinfo(iseq, idASET, 2, 0, NULL, FALSE),
6678  NULL/* CALL_CACHE */, str);
6679  ADD_INSN(ret, line, pop);
6680  break;
6681  }
6682 
6683  INIT_ANCHOR(recv);
6684  INIT_ANCHOR(args);
6685  argc = setup_args(iseq, args, node->nd_args, &flag, NULL);
6686  CHECK(!NIL_P(argc));
6687 
6688  flag |= COMPILE_RECV(recv, "recv", node);
6689 
6690  debugp_param("argc", argc);
6691  debugp_param("nd_mid", ID2SYM(mid));
6692 
6693  if (!rb_is_attrset_id(mid)) {
6694  /* safe nav attr */
6695  mid = rb_id_attrset(mid);
6696  ADD_INSN(recv, line, dup);
6697  lskip = NEW_LABEL(line);
6698  ADD_INSNL(recv, line, branchnil, lskip);
6699  }
6700  if (!popped) {
6701  ADD_INSN(ret, line, putnil);
6702  ADD_SEQ(ret, recv);
6703  ADD_SEQ(ret, args);
6704 
6705  if (flag & VM_CALL_ARGS_BLOCKARG) {
6706  ADD_INSN1(ret, line, topn, INT2FIX(1));
6707  if (flag & VM_CALL_ARGS_SPLAT) {
6708  ADD_INSN1(ret, line, putobject, INT2FIX(-1));
6709  ADD_SEND(ret, line, idAREF, INT2FIX(1));
6710  }
6711  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 3));
6712  ADD_INSN (ret, line, pop);
6713  }
6714  else if (flag & VM_CALL_ARGS_SPLAT) {
6715  ADD_INSN(ret, line, dup);
6716  ADD_INSN1(ret, line, putobject, INT2FIX(-1));
6717  ADD_SEND(ret, line, idAREF, INT2FIX(1));
6718  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 2));
6719  ADD_INSN (ret, line, pop);
6720  }
6721  else {
6722  ADD_INSN1(ret, line, setn, FIXNUM_INC(argc, 1));
6723  }
6724  }
6725  else {
6726  ADD_SEQ(ret, recv);
6727  ADD_SEQ(ret, args);
6728  }
6729  ADD_SEND_WITH_FLAG(ret, line, mid, argc, INT2FIX(flag));
6730  if (lskip) ADD_LABEL(ret, lskip);
6731  ADD_INSN(ret, line, pop);
6732 
6733  break;
6734  }
6735  case NODE_PRELUDE:{
6736  const rb_compile_option_t *orig_opt = ISEQ_COMPILE_DATA(iseq)->option;
6737  VALUE orig_cov = ISEQ_COVERAGE(iseq);
6738  rb_compile_option_t new_opt = *orig_opt;
6739  if (node->nd_orig) {
6740  rb_iseq_make_compile_option(&new_opt, node->nd_orig);
6741  ISEQ_COMPILE_DATA(iseq)->option = &new_opt;
6742  }
6743  if (!new_opt.coverage_enabled) ISEQ_COVERAGE_SET(iseq, Qfalse);
6744  CHECK(COMPILE_POPPED(ret, "prelude", node->nd_head));
6745  CHECK(COMPILE_(ret, "body", node->nd_body, popped));
6746  ISEQ_COMPILE_DATA(iseq)->option = orig_opt;
6747  ISEQ_COVERAGE_SET(iseq, orig_cov);
6748  break;
6749  }
6750  case NODE_LAMBDA:{
6751  /* compile same as lambda{...} */
6752  const rb_iseq_t *block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
6753  VALUE argc = INT2FIX(0);
6754 
6755  ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
6756  ADD_CALL_WITH_BLOCK(ret, line, idLambda, argc, block);
6757 
6758  if (popped) {
6759  ADD_INSN(ret, line, pop);
6760  }
6761  break;
6762  }
6763  default:
6764  UNKNOWN_NODE("iseq_compile_each", node, COMPILE_NG);
6765  ng:
6766  debug_node_end();
6767  return COMPILE_NG;
6768  }
6769 
6770  /* check & remove redundant trace(line) */
6771  if (saved_last_element &&
6772  ret->last == saved_last_element &&
6773  ((INSN *)saved_last_element)->insn_id == BIN(trace)) {
6774  POP_ELEMENT(ret);
6775  /* remove trace(coverage) */
6776  if (IS_INSN_ID(ret->last, trace2) &&
6777  (FIX2LONG(OPERAND_AT(ret->last, 0)) & RUBY_EVENT_COVERAGE) &&
6778  (FIX2LONG(OPERAND_AT(ret->last, 1)) == COVERAGE_INDEX_LINES)) {
6779  POP_ELEMENT(ret);
6780  RARRAY_ASET(ISEQ_LINE_COVERAGE(iseq), line - 1, Qnil);
6781  }
6782  }
6783 
6784  debug_node_end();
6785  return COMPILE_OK;
6786 }
6787 
6788 /***************************/
6789 /* instruction information */
6790 /***************************/
6791 
6792 static int
6793 insn_data_length(INSN *iobj)
6794 {
6795  return insn_len(iobj->insn_id);
6796 }
6797 
6798 static int
6799 calc_sp_depth(int depth, INSN *insn)
6800 {
6801  return insn_stack_increase(depth, insn->insn_id, insn->operands);
6802 }
6803 
6804 static VALUE
6805 opobj_inspect(VALUE obj)
6806 {
6807  struct RBasic *r = (struct RBasic *) obj;
6808  if (!SPECIAL_CONST_P(r) && r->klass == 0) {
6809  switch (BUILTIN_TYPE(r)) {
6810  case T_STRING:
6811  obj = rb_str_new_cstr(RSTRING_PTR(obj));
6812  break;
6813  case T_ARRAY:
6814  obj = rb_ary_dup(obj);
6815  break;
6816  }
6817  }
6818  return rb_inspect(obj);
6819 }
6820 
6821 
6822 
6823 static VALUE
6824 insn_data_to_s_detail(INSN *iobj)
6825 {
6826  VALUE str = rb_sprintf("%-20s ", insn_name(iobj->insn_id));
6827 
6828  if (iobj->operands) {
6829  const char *types = insn_op_types(iobj->insn_id);
6830  int j;
6831 
6832  for (j = 0; types[j]; j++) {
6833  char type = types[j];
6834 
6835  switch (type) {
6836  case TS_OFFSET: /* label(destination position) */
6837  {
6838  LABEL *lobj = (LABEL *)OPERAND_AT(iobj, j);
6839  rb_str_catf(str, LABEL_FORMAT, lobj->label_no);
6840  break;
6841  }
6842  break;
6843  case TS_ISEQ: /* iseq */
6844  {
6845  rb_iseq_t *iseq = (rb_iseq_t *)OPERAND_AT(iobj, j);
6846  VALUE val = Qnil;
6847  if (0 && iseq) { /* TODO: invalidate now */
6848  val = (VALUE)iseq;
6849  }
6850  rb_str_concat(str, opobj_inspect(val));
6851  }
6852  break;
6853  case TS_LINDEX:
6854  case TS_NUM: /* ulong */
6855  case TS_VALUE: /* VALUE */
6856  {
6857  VALUE v = OPERAND_AT(iobj, j);
6858  rb_str_concat(str, opobj_inspect(v));
6859  break;
6860  }
6861  case TS_ID: /* ID */
6862  rb_str_concat(str, opobj_inspect(OPERAND_AT(iobj, j)));
6863  break;
6864  case TS_GENTRY:
6865  {
6866  struct rb_global_entry *entry = (struct rb_global_entry *)
6867  (OPERAND_AT(iobj, j) & (~1));
6868  rb_str_append(str, rb_id2str(entry->id));
6869  break;
6870  }
6871  case TS_IC: /* inline cache */
6872  rb_str_catf(str, "<ic:%d>", FIX2INT(OPERAND_AT(iobj, j)));
6873  break;
6874  case TS_CALLINFO: /* call info */
6875  {
6876  struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(iobj, j);
6877  rb_str_cat2(str, "<callinfo:");
6878  if (ci->mid) rb_str_catf(str, "%"PRIsVALUE, rb_id2str(ci->mid));
6879  rb_str_catf(str, ", %d>", ci->orig_argc);
6880  break;
6881  }
6882  case TS_CALLCACHE: /* call cache */
6883  {
6884  rb_str_catf(str, "<call cache>");
6885  break;
6886  }
6887  case TS_CDHASH: /* case/when condition cache */
6888  rb_str_cat2(str, "<ch>");
6889  break;
6890  case TS_FUNCPTR:
6891  {
6892  rb_insn_func_t func = (rb_insn_func_t)OPERAND_AT(iobj, j);
6893 #ifdef HAVE_DLADDR
6894  Dl_info info;
6895  if (dladdr(func, &info) && info.dli_sname) {
6896  rb_str_cat2(str, info.dli_sname);
6897  break;
6898  }
6899 #endif
6900  rb_str_catf(str, "<%p>", func);
6901  }
6902  break;
6903  default:{
6904  rb_raise(rb_eSyntaxError, "unknown operand type: %c", type);
6905  }
6906  }
6907  if (types[j + 1]) {
6908  rb_str_cat2(str, ", ");
6909  }
6910  }
6911  }
6912  return str;
6913 }
6914 
6915 static void
6916 dump_disasm_list(const LINK_ELEMENT *link)
6917 {
6918  dump_disasm_list_with_cursor(link, NULL, NULL);
6919 }
6920 
6921 static void
6922 dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr, const LABEL *dest)
6923 {
6924  int pos = 0;
6925  INSN *iobj;
6926  LABEL *lobj;
6927  VALUE str;
6928 
6929  printf("-- raw disasm--------\n");
6930 
6931  while (link) {
6932  if (curr) printf(curr == link ? "*" : " ");
6933  switch (link->type) {
6934  case ISEQ_ELEMENT_INSN:
6935  {
6936  iobj = (INSN *)link;
6937  str = insn_data_to_s_detail(iobj);
6938  printf("%04d %-65s(%4u)\n", pos, StringValueCStr(str), iobj->line_no);
6939  pos += insn_data_length(iobj);
6940  break;
6941  }
6942  case ISEQ_ELEMENT_LABEL:
6943  {
6944  lobj = (LABEL *)link;
6945  printf(LABEL_FORMAT"%s\n", lobj->label_no, dest == lobj ? " <---" : "");
6946  break;
6947  }
6948  case ISEQ_ELEMENT_NONE:
6949  {
6950  printf("[none]\n");
6951  break;
6952  }
6953  case ISEQ_ELEMENT_ADJUST:
6954  {
6955  ADJUST *adjust = (ADJUST *)link;
6956  printf("adjust: [label: %d]\n", adjust->label ? adjust->label->label_no : -1);
6957  break;
6958  }
6959  default:
6960  /* ignore */
6961  rb_raise(rb_eSyntaxError, "dump_disasm_list error: %ld\n", FIX2LONG(link->type));
6962  }
6963  link = link->next;
6964  }
6965  printf("---------------------\n");
6966  fflush(stdout);
6967 }
6968 
6969 const char *
6971 {
6972  return insn_name_info[i];
6973 }
6974 
6975 VALUE
6977 {
6978  VALUE ary = rb_ary_new();
6979  int i;
6980  for (i = 0; i < VM_INSTRUCTION_SIZE; i++) {
6981  rb_ary_push(ary, rb_fstring_cstr(insn_name_info[i]));
6982  }
6983  return rb_obj_freeze(ary);
6984 }
6985 
6986 static LABEL *
6987 register_label(rb_iseq_t *iseq, struct st_table *labels_table, VALUE obj)
6988 {
6989  LABEL *label = 0;
6990  st_data_t tmp;
6991  obj = rb_convert_type_with_id(obj, T_SYMBOL, "Symbol", idTo_sym);
6992 
6993  if (st_lookup(labels_table, obj, &tmp) == 0) {
6994  label = NEW_LABEL(0);
6995  st_insert(labels_table, obj, (st_data_t)label);
6996  }
6997  else {
6998  label = (LABEL *)tmp;
6999  }
7000  LABEL_REF(label);
7001  return label;
7002 }
7003 
7004 static VALUE
7005 get_exception_sym2type(VALUE sym)
7006 {
7007 #undef rb_intern
7008 #define rb_intern(str) rb_intern_const(str)
7009  static VALUE symRescue, symEnsure, symRetry;
7010  static VALUE symBreak, symRedo, symNext;
7011 
7012  if (symRescue == 0) {
7013  symRescue = ID2SYM(rb_intern("rescue"));
7014  symEnsure = ID2SYM(rb_intern("ensure"));
7015  symRetry = ID2SYM(rb_intern("retry"));
7016  symBreak = ID2SYM(rb_intern("break"));
7017  symRedo = ID2SYM(rb_intern("redo"));
7018  symNext = ID2SYM(rb_intern("next"));
7019  }
7020 
7021  if (sym == symRescue) return CATCH_TYPE_RESCUE;
7022  if (sym == symEnsure) return CATCH_TYPE_ENSURE;
7023  if (sym == symRetry) return CATCH_TYPE_RETRY;
7024  if (sym == symBreak) return CATCH_TYPE_BREAK;
7025  if (sym == symRedo) return CATCH_TYPE_REDO;
7026  if (sym == symNext) return CATCH_TYPE_NEXT;
7027  rb_raise(rb_eSyntaxError, "invalid exception symbol: %+"PRIsVALUE, sym);
7028  return 0;
7029 }
7030 
7031 static int
7032 iseq_build_from_ary_exception(rb_iseq_t *iseq, struct st_table *labels_table,
7033  VALUE exception)
7034 {
7035  int i;
7036 
7037  for (i=0; i<RARRAY_LEN(exception); i++) {
7038  const rb_iseq_t *eiseq;
7039  VALUE v, type;
7040  const VALUE *ptr;
7041  LABEL *lstart, *lend, *lcont;
7042  unsigned int sp;
7043 
7044  v = rb_convert_type_with_id(RARRAY_AREF(exception, i), T_ARRAY,
7045  "Array", idTo_ary);
7046  if (RARRAY_LEN(v) != 6) {
7047  rb_raise(rb_eSyntaxError, "wrong exception entry");
7048  }
7049  ptr = RARRAY_CONST_PTR(v);
7050  type = get_exception_sym2type(ptr[0]);
7051  if (ptr[1] == Qnil) {
7052  eiseq = NULL;
7053  }
7054  else {
7055  eiseq = rb_iseqw_to_iseq(rb_iseq_load(ptr[1], (VALUE)iseq, Qnil));
7056  }
7057 
7058  lstart = register_label(iseq, labels_table, ptr[2]);
7059  lend = register_label(iseq, labels_table, ptr[3]);
7060  lcont = register_label(iseq, labels_table, ptr[4]);
7061  sp = NUM2UINT(ptr[5]);
7062 
7063  /* TODO: Dirty Hack! Fix me */
7064  if (type == CATCH_TYPE_RESCUE ||
7065  type == CATCH_TYPE_BREAK ||
7066  type == CATCH_TYPE_NEXT) {
7067  ++sp;
7068  }
7069 
7070  lcont->sp = sp;
7071 
7072  ADD_CATCH_ENTRY(type, lstart, lend, eiseq, lcont);
7073 
7074  RB_GC_GUARD(v);
7075  }
7076  return COMPILE_OK;
7077 }
7078 
7079 static struct st_table *
7080 insn_make_insn_table(void)
7081 {
7082  struct st_table *table;
7083  int i;
7084  table = st_init_numtable();
7085 
7086  for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
7087  st_insert(table, ID2SYM(rb_intern(insn_name(i))), i);
7088  }
7089 
7090  return table;
7091 }
7092 
7093 static const rb_iseq_t *
7094 iseq_build_load_iseq(const rb_iseq_t *iseq, VALUE op)
7095 {
7096  VALUE iseqw;
7097  const rb_iseq_t *loaded_iseq;
7098 
7099  if (RB_TYPE_P(op, T_ARRAY)) {
7100  iseqw = rb_iseq_load(op, (VALUE)iseq, Qnil);
7101  }
7102  else if (CLASS_OF(op) == rb_cISeq) {
7103  iseqw = op;
7104  }
7105  else {
7106  rb_raise(rb_eSyntaxError, "ISEQ is required");
7107  }
7108 
7109  loaded_iseq = rb_iseqw_to_iseq(iseqw);
7110  iseq_add_mark_object(iseq, (VALUE)loaded_iseq);
7111  return loaded_iseq;
7112 }
7113 
7114 static VALUE
7115 iseq_build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op)
7116 {
7117  ID mid = 0;
7118  int orig_argc = 0;
7119  unsigned int flag = 0;
7120  struct rb_call_info_kw_arg *kw_arg = 0;
7121 
7122  if (!NIL_P(op)) {
7123  VALUE vmid = rb_hash_aref(op, ID2SYM(rb_intern("mid")));
7124  VALUE vflag = rb_hash_aref(op, ID2SYM(rb_intern("flag")));
7125  VALUE vorig_argc = rb_hash_aref(op, ID2SYM(rb_intern("orig_argc")));
7126  VALUE vkw_arg = rb_hash_aref(op, ID2SYM(rb_intern("kw_arg")));
7127 
7128  if (!NIL_P(vmid)) mid = SYM2ID(vmid);
7129  if (!NIL_P(vflag)) flag = NUM2UINT(vflag);
7130  if (!NIL_P(vorig_argc)) orig_argc = FIX2INT(vorig_argc);
7131 
7132  if (!NIL_P(vkw_arg)) {
7133  int i;
7134  int len = RARRAY_LENINT(vkw_arg);
7135  size_t n = rb_call_info_kw_arg_bytes(len);
7136 
7137  kw_arg = xmalloc(n);
7138  kw_arg->keyword_len = len;
7139  for (i = 0; i < len; i++) {
7140  VALUE kw = RARRAY_AREF(vkw_arg, i);
7141  SYM2ID(kw); /* make immortal */
7142  kw_arg->keywords[i] = kw;
7143  }
7144  }
7145  }
7146 
7147  return (VALUE)new_callinfo(iseq, mid, orig_argc, flag, kw_arg, (flag & VM_CALL_ARGS_SIMPLE) == 0);
7148 }
7149 
7150 static int
7151 iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
7152  VALUE body, VALUE labels_wrapper)
7153 {
7154  /* TODO: body should be frozen */
7155  const VALUE *ptr = RARRAY_CONST_PTR(body);
7156  long i, len = RARRAY_LEN(body);
7157  struct st_table *labels_table = DATA_PTR(labels_wrapper);
7158  int j;
7159  int line_no = 0;
7160  int ret = COMPILE_OK;
7161 
7162  /*
7163  * index -> LABEL *label
7164  */
7165  static struct st_table *insn_table;
7166 
7167  if (insn_table == 0) {
7168  insn_table = insn_make_insn_table();
7169  }
7170 
7171  for (i=0; i<len; i++) {
7172  VALUE obj = ptr[i];
7173 
7174  if (SYMBOL_P(obj)) {
7175  LABEL *label = register_label(iseq, labels_table, obj);
7176  ADD_LABEL(anchor, label);
7177  }
7178  else if (FIXNUM_P(obj)) {
7179  line_no = NUM2INT(obj);
7180  }
7181  else if (RB_TYPE_P(obj, T_ARRAY)) {
7182  VALUE *argv = 0;
7183  int argc = RARRAY_LENINT(obj) - 1;
7184  st_data_t insn_id;
7185  VALUE insn;
7186 
7187  insn = (argc < 0) ? Qnil : RARRAY_AREF(obj, 0);
7188  if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) {
7189  /* TODO: exception */
7190  COMPILE_ERROR(iseq, line_no,
7191  "unknown instruction: %+"PRIsVALUE, insn);
7192  ret = COMPILE_NG;
7193  break;
7194  }
7195 
7196  if (argc != insn_len((VALUE)insn_id)-1) {
7197  COMPILE_ERROR(iseq, line_no,
7198  "operand size mismatch");
7199  ret = COMPILE_NG;
7200  break;
7201  }
7202 
7203  if (argc > 0) {
7204  argv = compile_data_alloc(iseq, sizeof(VALUE) * argc);
7205  for (j=0; j<argc; j++) {
7206  VALUE op = rb_ary_entry(obj, j+1);
7207  switch (insn_op_type((VALUE)insn_id, j)) {
7208  case TS_OFFSET: {
7209  LABEL *label = register_label(iseq, labels_table, op);
7210  argv[j] = (VALUE)label;
7211  break;
7212  }
7213  case TS_LINDEX:
7214  case TS_NUM:
7215  (void)NUM2INT(op);
7216  argv[j] = op;
7217  break;
7218  case TS_VALUE:
7219  argv[j] = op;
7220  iseq_add_mark_object(iseq, op);
7221  break;
7222  case TS_ISEQ:
7223  {
7224  if (op != Qnil) {
7225  argv[j] = (VALUE)iseq_build_load_iseq(iseq, op);
7226  }
7227  else {
7228  argv[j] = 0;
7229  }
7230  }
7231  break;
7232  case TS_GENTRY:
7233  op = rb_convert_type_with_id(op, T_SYMBOL, "Symbol", idTo_sym);
7234  argv[j] = (VALUE)rb_global_entry(SYM2ID(op));
7235  break;
7236  case TS_IC:
7237  argv[j] = op;
7238  if (NUM2UINT(op) >= iseq->body->is_size) {
7239  iseq->body->is_size = NUM2INT(op) + 1;
7240  }
7241  break;
7242  case TS_CALLINFO:
7243  argv[j] = iseq_build_callinfo_from_hash(iseq, op);
7244  break;
7245  case TS_CALLCACHE:
7246  argv[j] = Qfalse;
7247  break;
7248  case TS_ID:
7249  argv[j] = rb_convert_type_with_id(op, T_SYMBOL,
7250  "Symbol", idTo_sym);
7251  break;
7252  case TS_CDHASH:
7253  {
7254  int i;
7255  VALUE map = rb_hash_new_with_size(RARRAY_LEN(op)/2);
7256 
7257  rb_hash_tbl_raw(map)->type = &cdhash_type;
7258  op = rb_convert_type_with_id(op, T_ARRAY, "Array", idTo_ary);
7259  for (i=0; i<RARRAY_LEN(op); i+=2) {
7260  VALUE key = RARRAY_AREF(op, i);
7261  VALUE sym = RARRAY_AREF(op, i+1);
7262  LABEL *label =
7263  register_label(iseq, labels_table, sym);
7264  rb_hash_aset(map, key, (VALUE)label | 1);
7265  }
7266  RB_GC_GUARD(op);
7267  argv[j] = map;
7268  rb_iseq_add_mark_object(iseq, map);
7269  }
7270  break;
7271  case TS_FUNCPTR:
7272  {
7273 #if SIZEOF_VALUE <= SIZEOF_LONG
7274  long funcptr = NUM2LONG(op);
7275 #else
7276  LONG_LONG funcptr = NUM2LL(op);
7277 #endif
7278  argv[j] = (VALUE)funcptr;
7279  }
7280  break;
7281  default:
7282  rb_raise(rb_eSyntaxError, "unknown operand: %c", insn_op_type((VALUE)insn_id, j));
7283  }
7284  }
7285  }
7286  ADD_ELEM(anchor,
7287  (LINK_ELEMENT*)new_insn_core(iseq, line_no,
7288  (enum ruby_vminsn_type)insn_id, argc, argv));
7289  }
7290  else {
7291  rb_raise(rb_eTypeError, "unexpected object for instruction");
7292  }
7293  }
7294  DATA_PTR(labels_wrapper) = 0;
7295  validate_labels(iseq, labels_table);
7296  if (!ret) return ret;
7297  return iseq_setup(iseq, anchor);
7298 }
7299 
7300 #define CHECK_ARRAY(v) rb_convert_type_with_id((v), T_ARRAY, "Array", idTo_ary)
7301 #define CHECK_SYMBOL(v) rb_convert_type_with_id((v), T_SYMBOL, "Symbol", idTo_sym)
7302 
7303 static int
7304 int_param(int *dst, VALUE param, VALUE sym)
7305 {
7306  VALUE val = rb_hash_aref(param, sym);
7307  if (FIXNUM_P(val)) {
7308  *dst = FIX2INT(val);
7309  return TRUE;
7310  }
7311  else if (!NIL_P(val)) {
7312  rb_raise(rb_eTypeError, "invalid %+"PRIsVALUE" Fixnum: %+"PRIsVALUE,
7313  sym, val);
7314  }
7315  return FALSE;
7316 }
7317 
7318 static const struct rb_iseq_param_keyword *
7319 iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords)
7320 {
7321  int i, j;
7322  int len = RARRAY_LENINT(keywords);
7323  int default_len;
7324  VALUE key, sym, default_val;
7325  VALUE *dvs;
7326  ID *ids;
7327  struct rb_iseq_param_keyword *keyword = ZALLOC(struct rb_iseq_param_keyword);
7328 
7329  iseq->body->param.flags.has_kw = TRUE;
7330 
7331  keyword->num = len;
7332 #define SYM(s) ID2SYM(rb_intern(#s))
7333  (void)int_param(&keyword->bits_start, params, SYM(kwbits));
7334  i = keyword->bits_start - keyword->num;
7335  ids = (ID *)&iseq->body->local_table[i];
7336 #undef SYM
7337 
7338  /* required args */
7339  for (i = 0; i < len; i++) {
7340  VALUE val = RARRAY_AREF(keywords, i);
7341 
7342  if (!SYMBOL_P(val)) {
7343  goto default_values;
7344  }
7345  ids[i] = SYM2ID(val);
7346  keyword->required_num++;
7347  }
7348 
7349  default_values: /* note: we intentionally preserve `i' from previous loop */
7350  default_len = len - i;
7351  if (default_len == 0) {
7352  keyword->table = ids;
7353  return keyword;
7354  }
7355 
7356  dvs = ALLOC_N(VALUE, (unsigned int)default_len);
7357 
7358  for (j = 0; i < len; i++, j++) {
7359  key = RARRAY_AREF(keywords, i);
7360  CHECK_ARRAY(key);
7361 
7362  switch (RARRAY_LEN(key)) {
7363  case 1:
7364  sym = RARRAY_AREF(key, 0);
7365  default_val = Qundef;
7366  break;
7367  case 2:
7368  sym = RARRAY_AREF(key, 0);
7369  default_val = RARRAY_AREF(key, 1);
7370  break;
7371  default:
7372  rb_raise(rb_eTypeError, "keyword default has unsupported len %+"PRIsVALUE, key);
7373  }
7374  ids[i] = SYM2ID(sym);
7375  dvs[j] = default_val;
7376  }
7377 
7378  keyword->table = ids;
7379  keyword->default_values = dvs;
7380 
7381  return keyword;
7382 }
7383 
7384 void
7385 rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
7386  VALUE exception, VALUE body)
7387 {
7388 #define SYM(s) ID2SYM(rb_intern(#s))
7389  int i, len;
7390  unsigned int arg_size, local_size, stack_max;
7391  ID *tbl;
7392  struct st_table *labels_table = st_init_numtable();
7393  VALUE labels_wrapper = Data_Wrap_Struct(0, 0, st_free_table, labels_table);
7394  VALUE arg_opt_labels = rb_hash_aref(params, SYM(opt));
7395  VALUE keywords = rb_hash_aref(params, SYM(keyword));
7396  VALUE sym_arg_rest = ID2SYM(rb_intern("#arg_rest"));
7397  DECL_ANCHOR(anchor);
7398  INIT_ANCHOR(anchor);
7399 
7400  len = RARRAY_LENINT(locals);
7401  iseq->body->local_table_size = len;
7402  iseq->body->local_table = tbl = len > 0 ? (ID *)ALLOC_N(ID, iseq->body->local_table_size) : NULL;
7403 
7404  for (i = 0; i < len; i++) {
7405  VALUE lv = RARRAY_AREF(locals, i);
7406 
7407  if (sym_arg_rest == lv) {
7408  tbl[i] = 0;
7409  }
7410  else {
7411  tbl[i] = FIXNUM_P(lv) ? (ID)FIX2LONG(lv) : SYM2ID(CHECK_SYMBOL(lv));
7412  }
7413  }
7414 
7415 #define INT_PARAM(F) int_param(&iseq->body->param.F, params, SYM(F))
7416  if (INT_PARAM(lead_num)) {
7417  iseq->body->param.flags.has_lead = TRUE;
7418  }
7419  if (INT_PARAM(post_num)) iseq->body->param.flags.has_post = TRUE;
7420  if (INT_PARAM(post_start)) iseq->body->param.flags.has_post = TRUE;
7421  if (INT_PARAM(rest_start)) iseq->body->param.flags.has_rest = TRUE;
7422  if (INT_PARAM(block_start)) iseq->body->param.flags.has_block = TRUE;
7423 #undef INT_PARAM
7424  {
7425 #define INT_PARAM(F) F = (int_param(&x, misc, SYM(F)) ? (unsigned int)x : 0)
7426  int x;
7427  INT_PARAM(arg_size);
7428  INT_PARAM(local_size);
7429  INT_PARAM(stack_max);
7430 #undef INT_PARAM
7431  }
7432 
7433  if (RB_TYPE_P(arg_opt_labels, T_ARRAY)) {
7434  len = RARRAY_LENINT(arg_opt_labels);
7435  iseq->body->param.flags.has_opt = !!(len - 1 >= 0);
7436 
7437  if (iseq->body->param.flags.has_opt) {
7438  VALUE *opt_table = ALLOC_N(VALUE, len);
7439 
7440  for (i = 0; i < len; i++) {
7441  VALUE ent = RARRAY_AREF(arg_opt_labels, i);
7442  LABEL *label = register_label(iseq, labels_table, ent);
7443  opt_table[i] = (VALUE)label;
7444  }
7445 
7446  iseq->body->param.opt_num = len - 1;
7447  iseq->body->param.opt_table = opt_table;
7448  }
7449  }
7450  else if (!NIL_P(arg_opt_labels)) {
7451  rb_raise(rb_eTypeError, ":opt param is not an array: %+"PRIsVALUE,
7452  arg_opt_labels);
7453  }
7454 
7455  if (RB_TYPE_P(keywords, T_ARRAY)) {
7456  iseq->body->param.keyword = iseq_build_kw(iseq, params, keywords);
7457  }
7458  else if (!NIL_P(keywords)) {
7459  rb_raise(rb_eTypeError, ":keywords param is not an array: %+"PRIsVALUE,
7460  keywords);
7461  }
7462 
7463  if (Qtrue == rb_hash_aref(params, SYM(ambiguous_param0))) {
7464  iseq->body->param.flags.ambiguous_param0 = TRUE;
7465  }
7466 
7467  if (int_param(&i, params, SYM(kwrest))) {
7468  struct rb_iseq_param_keyword *keyword = (struct rb_iseq_param_keyword *)iseq->body->param.keyword;
7469  if (keyword == NULL) {
7470  iseq->body->param.keyword = keyword = ZALLOC(struct rb_iseq_param_keyword);
7471  }
7472  keyword->rest_start = i;
7473  iseq->body->param.flags.has_kwrest = TRUE;
7474  }
7475 #undef SYM
7476  iseq_calc_param_size(iseq);
7477 
7478  /* exception */
7479  iseq_build_from_ary_exception(iseq, labels_table, exception);
7480 
7481  /* body */
7482  iseq_build_from_ary_body(iseq, anchor, body, labels_wrapper);
7483 
7484  iseq->body->param.size = arg_size;
7485  iseq->body->local_table_size = local_size;
7486  iseq->body->stack_max = stack_max;
7487 }
7488 
7489 /* for parser */
7490 
7491 int
7492 rb_dvar_defined(ID id, const struct rb_block *base_block)
7493 {
7494  const rb_iseq_t *iseq;
7495 
7496  if (base_block && (iseq = vm_block_iseq(base_block)) != NULL) {
7497  while (iseq->body->type == ISEQ_TYPE_BLOCK ||
7498  iseq->body->type == ISEQ_TYPE_RESCUE ||
7499  iseq->body->type == ISEQ_TYPE_ENSURE ||
7500  iseq->body->type == ISEQ_TYPE_EVAL ||
7501  iseq->body->type == ISEQ_TYPE_MAIN
7502  ) {
7503  unsigned int i;
7504 
7505  for (i = 0; i < iseq->body->local_table_size; i++) {
7506  if (iseq->body->local_table[i] == id) {
7507  return 1;
7508  }
7509  }
7510  iseq = iseq->body->parent_iseq;
7511  }
7512  }
7513  return 0;
7514 }
7515 
7516 int
7517 rb_local_defined(ID id, const struct rb_block *base_block)
7518 {
7519  const rb_iseq_t *iseq;
7520 
7521  if (base_block && (iseq = vm_block_iseq(base_block)) != NULL) {
7522  unsigned int i;
7523  iseq = iseq->body->local_iseq;
7524 
7525  for (i=0; i<iseq->body->local_table_size; i++) {
7526  if (iseq->body->local_table[i] == id) {
7527  return 1;
7528  }
7529  }
7530  }
7531  return 0;
7532 }
7533 
7534 static int
7535 caller_location(VALUE *path, VALUE *realpath)
7536 {
7537  const rb_thread_t *const th = GET_THREAD();
7538  const rb_control_frame_t *const cfp =
7540 
7541  if (cfp) {
7542  int line = rb_vm_get_sourceline(cfp);
7543  *path = rb_iseq_path(cfp->iseq);
7544  *realpath = rb_iseq_realpath(cfp->iseq);
7545  return line;
7546  }
7547  else {
7548  *path = rb_fstring_cstr("<compiled>");
7549  *realpath = *path;
7550  return 1;
7551  }
7552 }
7553 
7554 typedef struct {
7557  int line;
7558 } accessor_args;
7559 
7560 static const rb_iseq_t *
7561 method_for_self(VALUE name, VALUE arg, rb_insn_func_t func,
7562  VALUE (*build)(rb_iseq_t *, LINK_ANCHOR *const, VALUE))
7563 {
7564  VALUE path, realpath;
7565  accessor_args acc;
7566 
7567  acc.arg = arg;
7568  acc.func = func;
7569  acc.line = caller_location(&path, &realpath);
7570  return rb_iseq_new_with_opt((NODE *)IFUNC_NEW(build, (VALUE)&acc, 0),
7571  rb_sym2str(name), path, realpath,
7572  INT2FIX(acc.line), 0, ISEQ_TYPE_METHOD, 0);
7573 }
7574 
7575 static VALUE
7576 for_self_aref(rb_iseq_t *iseq, LINK_ANCHOR *const ret, VALUE a)
7577 {
7578  const accessor_args *const args = (void *)a;
7579  const int line = args->line;
7580 
7581  iseq_set_local_table(iseq, 0);
7582  iseq->body->param.lead_num = 0;
7583  iseq->body->param.size = 0;
7584 
7585  ADD_INSN1(ret, line, putobject, args->arg);
7586  ADD_INSN1(ret, line, opt_call_c_function, (VALUE)args->func);
7587  return Qnil;
7588 }
7589 
7590 static VALUE
7591 for_self_aset(rb_iseq_t *iseq, LINK_ANCHOR *const ret, VALUE a)
7592 {
7593  const accessor_args *const args = (void *)a;
7594  const int line = args->line;
7595  static const ID vars[] = {1, idUScore};
7596 
7597  iseq_set_local_table(iseq, vars);
7598  iseq->body->param.lead_num = 1;
7599  iseq->body->param.size = 1;
7600 
7601  ADD_GETLOCAL(ret, line, numberof(vars)-1, 0);
7602  ADD_INSN1(ret, line, putobject, args->arg);
7603  ADD_INSN1(ret, line, opt_call_c_function, (VALUE)args->func);
7604  ADD_INSN(ret, line, pop);
7605  return Qnil;
7606 }
7607 
7608 /*
7609  * func (index) -> (value)
7610  */
7611 const rb_iseq_t *
7613 {
7614  return method_for_self(name, arg, func, for_self_aref);
7615 }
7616 
7617 /*
7618  * func (index, value) -> (index, value)
7619  */
7620 const rb_iseq_t *
7622 {
7623  return method_for_self(name, arg, func, for_self_aset);
7624 }
7625 
7626 /* ISeq binary format */
7627 
7628 typedef unsigned int ibf_offset_t;
7629 #define IBF_OFFSET(ptr) ((ibf_offset_t)(VALUE)(ptr))
7630 
7631 struct ibf_header {
7632  char magic[4]; /* YARB */
7633  unsigned int major_version;
7634  unsigned int minor_version;
7635  unsigned int size;
7636  unsigned int extra_size;
7637 
7638  unsigned int iseq_list_size;
7639  unsigned int id_list_size;
7640  unsigned int object_list_size;
7641 
7642  ibf_offset_t iseq_list_offset;
7643  ibf_offset_t id_list_offset;
7644  ibf_offset_t object_list_offset;
7645 };
7646 
7648  enum {
7651  ibf_id_enc_other
7652  } enc : 2;
7653  char body[1];
7654 };
7655 
7656 struct ibf_dump {
7658  VALUE iseq_list; /* [iseq0 offset, ...] */
7659  VALUE obj_list; /* [objs] */
7660  st_table *iseq_table; /* iseq -> iseq number */
7661  st_table *id_table; /* id -> id number */
7662 };
7663 
7664 rb_iseq_t * iseq_alloc(void);
7665 
7666 struct ibf_load {
7667  const char *buff;
7668  const struct ibf_header *header;
7669  ID *id_list; /* [id0, ...] */
7670  VALUE iseq_list; /* [iseq0, ...] */
7671  VALUE obj_list; /* [obj0, ...] */
7675 };
7676 
7677 static ibf_offset_t
7678 ibf_dump_pos(struct ibf_dump *dump)
7679 {
7680  return (unsigned int)rb_str_strlen(dump->str);
7681 }
7682 
7683 static ibf_offset_t
7684 ibf_dump_write(struct ibf_dump *dump, const void *buff, unsigned long size)
7685 {
7686  ibf_offset_t pos = ibf_dump_pos(dump);
7687  rb_str_cat(dump->str, (const char *)buff, size);
7688  /* TODO: overflow check */
7689  return pos;
7690 }
7691 
7692 static void
7693 ibf_dump_overwrite(struct ibf_dump *dump, void *buff, unsigned int size, long offset)
7694 {
7695  VALUE str = dump->str;
7696  char *ptr = RSTRING_PTR(str);
7697  if ((unsigned long)(size + offset) > (unsigned long)RSTRING_LEN(str))
7698  rb_bug("ibf_dump_overwrite: overflow");
7699  memcpy(ptr + offset, buff, size);
7700 }
7701 
7702 static void *
7703 ibf_load_alloc(const struct ibf_load *load, ibf_offset_t offset, int size)
7704 {
7705  void *buff = ruby_xmalloc(size);
7706  memcpy(buff, load->buff + offset, size);
7707  return buff;
7708 }
7709 
7710 #define IBF_W(b, type, n) (type *)(VALUE)ibf_dump_write(dump, (b), sizeof(type) * (n))
7711 #define IBF_WV(variable) ibf_dump_write(dump, &(variable), sizeof(variable))
7712 #define IBF_WP(b, type, n) ibf_dump_write(dump, (b), sizeof(type) * (n))
7713 #define IBF_R(val, type, n) (type *)ibf_load_alloc(load, IBF_OFFSET(val), sizeof(type) * (n))
7714 
7715 static int
7716 ibf_table_lookup(struct st_table *table, st_data_t key)
7717 {
7718  st_data_t val;
7719 
7720  if (st_lookup(table, key, &val)) {
7721  return (int)val;
7722  }
7723  else {
7724  return -1;
7725  }
7726 }
7727 
7728 static int
7729 ibf_table_index(struct st_table *table, st_data_t key)
7730 {
7731  int index = ibf_table_lookup(table, key);
7732 
7733  if (index < 0) { /* not found */
7734  index = (int)table->num_entries;
7735  st_insert(table, key, (st_data_t)index);
7736  }
7737 
7738  return index;
7739 }
7740 
7741 /* dump/load generic */
7742 
7743 static VALUE ibf_load_object(const struct ibf_load *load, VALUE object_index);
7744 static rb_iseq_t *ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq);
7745 
7746 static VALUE
7747 ibf_dump_object(struct ibf_dump *dump, VALUE obj)
7748 {
7749  long index = RARRAY_LEN(dump->obj_list);
7750  long i;
7751  for (i=0; i<index; i++) {
7752  if (RARRAY_AREF(dump->obj_list, i) == obj) return (VALUE)i; /* dedup */
7753  }
7754  rb_ary_push(dump->obj_list, obj);
7755  return (VALUE)index;
7756 }
7757 
7758 static VALUE
7759 ibf_dump_id(struct ibf_dump *dump, ID id)
7760 {
7761  return (VALUE)ibf_table_index(dump->id_table, (st_data_t)id);
7762 }
7763 
7764 static ID
7765 ibf_load_id(const struct ibf_load *load, const ID id_index)
7766 {
7767  ID id;
7768 
7769  if (id_index == 0) {
7770  id = 0;
7771  }
7772  else {
7773  id = load->id_list[(long)id_index];
7774 
7775  if (id == 0) {
7776  long *indices = (long *)(load->buff + load->header->id_list_offset);
7777  VALUE str = ibf_load_object(load, indices[id_index]);
7778  id = NIL_P(str) ? 0 : rb_intern_str(str); /* str == nil -> internal junk id */
7779  load->id_list[(long)id_index] = id;
7780  }
7781  }
7782 
7783  return id;
7784 }
7785 
7786 /* dump/load: code */
7787 
7788 static VALUE
7789 ibf_dump_callinfo(struct ibf_dump *dump, const struct rb_call_info *ci)
7790 {
7791  return (ci->flag & VM_CALL_KWARG) ? Qtrue : Qfalse;
7792 }
7793 
7794 static ibf_offset_t ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq);
7795 
7796 static rb_iseq_t *
7797 ibf_dump_iseq(struct ibf_dump *dump, const rb_iseq_t *iseq)
7798 {
7799  if (iseq == NULL) {
7800  return (rb_iseq_t *)-1;
7801  }
7802  else {
7803  int iseq_index = ibf_table_lookup(dump->iseq_table, (st_data_t)iseq);
7804  if (iseq_index < 0) {
7805  iseq_index = ibf_table_index(dump->iseq_table, (st_data_t)iseq);
7806  rb_ary_store(dump->iseq_list, iseq_index, LONG2NUM(ibf_dump_iseq_each(dump, rb_iseq_check(iseq))));
7807  }
7808  return (rb_iseq_t *)(VALUE)iseq_index;
7809  }
7810 }
7811 
7812 static VALUE
7813 ibf_dump_gentry(struct ibf_dump *dump, const struct rb_global_entry *entry)
7814 {
7815  return (VALUE)ibf_dump_id(dump, entry->id);
7816 }
7817 
7818 static VALUE
7819 ibf_load_gentry(const struct ibf_load *load, const struct rb_global_entry *entry)
7820 {
7821  ID gid = ibf_load_id(load, (ID)(VALUE)entry);
7822  return (VALUE)rb_global_entry(gid);
7823 }
7824 
7825 static VALUE *
7826 ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq)
7827 {
7828  const int iseq_size = iseq->body->iseq_size;
7829  int code_index;
7830  VALUE *code;
7831  const VALUE *orig_code = rb_iseq_original_iseq(iseq);
7832 
7833  code = ALLOCA_N(VALUE, iseq_size);
7834 
7835  for (code_index=0; code_index<iseq_size;) {
7836  const VALUE insn = orig_code[code_index];
7837  const char *types = insn_op_types(insn);
7838  int op_index;
7839 
7840  code[code_index++] = (VALUE)insn;
7841 
7842  for (op_index=0; types[op_index]; op_index++, code_index++) {
7843  VALUE op = orig_code[code_index];
7844  switch (types[op_index]) {
7845  case TS_CDHASH:
7846  case TS_VALUE:
7847  code[code_index] = ibf_dump_object(dump, op);
7848  break;
7849  case TS_ISEQ:
7850  code[code_index] = (VALUE)ibf_dump_iseq(dump, (const rb_iseq_t *)op);
7851  break;
7852  case TS_IC:
7853  {
7854  unsigned int i;
7855  for (i=0; i<iseq->body->is_size; i++) {
7856  if (op == (VALUE)&iseq->body->is_entries[i]) {
7857  break;
7858  }
7859  }
7860  code[code_index] = i;
7861  }
7862  break;
7863  case TS_CALLINFO:
7864  code[code_index] = ibf_dump_callinfo(dump, (const struct rb_call_info *)op);
7865  break;
7866  case TS_CALLCACHE:
7867  code[code_index] = 0;
7868  break;
7869  case TS_ID:
7870  code[code_index] = ibf_dump_id(dump, (ID)op);
7871  break;
7872  case TS_GENTRY:
7873  code[code_index] = ibf_dump_gentry(dump, (const struct rb_global_entry *)op);
7874  break;
7875  case TS_FUNCPTR:
7876  rb_raise(rb_eRuntimeError, "TS_FUNCPTR is not supported");
7877  break;
7878  default:
7879  code[code_index] = op;
7880  break;
7881  }
7882  }
7883  assert(insn_len(insn) == op_index+1);
7884  }
7885 
7886  return IBF_W(code, VALUE, iseq_size);
7887 }
7888 
7889 static VALUE *
7890 ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, const struct rb_iseq_constant_body *body)
7891 {
7892  const int iseq_size = body->iseq_size;
7893  int code_index;
7894  VALUE *code = IBF_R(body->iseq_encoded, VALUE, iseq_size);
7895 
7896  struct rb_call_info *ci_entries = iseq->body->ci_entries;
7897  struct rb_call_info_with_kwarg *ci_kw_entries = (struct rb_call_info_with_kwarg *)&iseq->body->ci_entries[iseq->body->ci_size];
7898  struct rb_call_cache *cc_entries = iseq->body->cc_entries;
7899  union iseq_inline_storage_entry *is_entries = iseq->body->is_entries;
7900 
7901  for (code_index=0; code_index<iseq_size;) {
7902  const VALUE insn = code[code_index++];
7903  const char *types = insn_op_types(insn);
7904  int op_index;
7905 
7906  for (op_index=0; types[op_index]; op_index++, code_index++) {
7907  VALUE op = code[code_index];
7908 
7909  switch (types[op_index]) {
7910  case TS_CDHASH:
7911  case TS_VALUE:
7912  code[code_index] = ibf_load_object(load, op);
7913  break;
7914  case TS_ISEQ:
7915  code[code_index] = (VALUE)ibf_load_iseq(load, (const rb_iseq_t *)op);
7916  break;
7917  case TS_IC:
7918  code[code_index] = (VALUE)&is_entries[(int)op];
7919  break;
7920  case TS_CALLINFO:
7921  code[code_index] = op ? (VALUE)ci_kw_entries++ : (VALUE)ci_entries++; /* op is Qtrue (kw) or Qfalse (!kw) */
7922  break;
7923  case TS_CALLCACHE:
7924  code[code_index] = (VALUE)cc_entries++;
7925  break;
7926  case TS_ID:
7927  code[code_index] = ibf_load_id(load, (ID)op);
7928  break;
7929  case TS_GENTRY:
7930  code[code_index] = ibf_load_gentry(load, (const struct rb_global_entry *)op);
7931  break;
7932  case TS_FUNCPTR:
7933  rb_raise(rb_eRuntimeError, "TS_FUNCPTR is not supported");
7934  break;
7935  default:
7936  /* code[code_index] = op; */
7937  break;
7938  }
7939  }
7940  if (insn_len(insn) != op_index+1) {
7941  rb_raise(rb_eRuntimeError, "operand size mismatch");
7942  }
7943  }
7944 
7945 
7946  return code;
7947 }
7948 
7949 static VALUE *
7950 ibf_dump_param_opt_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
7951 {
7952  int opt_num = iseq->body->param.opt_num;
7953 
7954  if (opt_num > 0) {
7955  return IBF_W(iseq->body->param.opt_table, VALUE, opt_num + 1);
7956  }
7957  else {
7958  return NULL;
7959  }
7960 }
7961 
7962 static VALUE *
7963 ibf_load_param_opt_table(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
7964 {
7965  int opt_num = body->param.opt_num;
7966 
7967  if (opt_num > 0) {
7968  ibf_offset_t offset = IBF_OFFSET(body->param.opt_table);
7969  VALUE *table = ALLOC_N(VALUE, opt_num+1);
7970  MEMCPY(table, load->buff + offset, VALUE, opt_num+1);
7971  return table;
7972  }
7973  else {
7974  return NULL;
7975  }
7976 }
7977 
7978 static struct rb_iseq_param_keyword *
7979 ibf_dump_param_keyword(struct ibf_dump *dump, const rb_iseq_t *iseq)
7980 {
7981  const struct rb_iseq_param_keyword *kw = iseq->body->param.keyword;
7982 
7983  if (kw) {
7984  struct rb_iseq_param_keyword dump_kw = *kw;
7985  int dv_num = kw->num - kw->required_num;
7986  ID *ids = kw->num > 0 ? ALLOCA_N(ID, kw->num) : NULL;
7987  VALUE *dvs = dv_num > 0 ? ALLOCA_N(VALUE, dv_num) : NULL;
7988  int i;
7989 
7990  for (i=0; i<kw->num; i++) ids[i] = (ID)ibf_dump_id(dump, kw->table[i]);
7991  for (i=0; i<dv_num; i++) dvs[i] = (VALUE)ibf_dump_object(dump, kw->default_values[i]);
7992 
7993  dump_kw.table = IBF_W(ids, ID, kw->num);
7994  dump_kw.default_values = IBF_W(dvs, VALUE, dv_num);
7995  return IBF_W(&dump_kw, struct rb_iseq_param_keyword, 1);
7996  }
7997  else {
7998  return NULL;
7999  }
8000 }
8001 
8002 static const struct rb_iseq_param_keyword *
8003 ibf_load_param_keyword(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
8004 {
8005  if (body->param.keyword) {
8006  struct rb_iseq_param_keyword *kw = IBF_R(body->param.keyword, struct rb_iseq_param_keyword, 1);
8007  ID *ids = IBF_R(kw->table, ID, kw->num);
8008  int dv_num = kw->num - kw->required_num;
8009  VALUE *dvs = IBF_R(kw->default_values, VALUE, dv_num);
8010  int i;
8011 
8012  for (i=0; i<kw->num; i++) {
8013  ids[i] = ibf_load_id(load, ids[i]);
8014  }
8015  for (i=0; i<dv_num; i++) {
8016  dvs[i] = ibf_load_object(load, dvs[i]);
8017  }
8018 
8019  kw->table = ids;
8020  kw->default_values = dvs;
8021  return kw;
8022  }
8023  else {
8024  return NULL;
8025  }
8026 }
8027 
8028 static struct iseq_line_info_entry *
8029 ibf_dump_line_info_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
8030 {
8031  return IBF_W(iseq->body->line_info_table, struct iseq_line_info_entry, iseq->body->line_info_size);
8032 }
8033 
8034 static struct iseq_line_info_entry *
8035 ibf_load_line_info_table(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
8036 {
8037  return IBF_R(body->line_info_table, struct iseq_line_info_entry, body->line_info_size);
8038 }
8039 
8040 static ID *
8041 ibf_dump_local_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
8042 {
8043  const int size = iseq->body->local_table_size;
8044  ID *table = ALLOCA_N(ID, size);
8045  int i;
8046 
8047  for (i=0; i<size; i++) {
8048  table[i] = ibf_dump_id(dump, iseq->body->local_table[i]);
8049  }
8050 
8051  return IBF_W(table, ID, size);
8052 }
8053 
8054 static ID *
8055 ibf_load_local_table(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
8056 {
8057  const int size = body->local_table_size;
8058 
8059  if (size > 0) {
8060  ID *table = IBF_R(body->local_table, ID, size);
8061  int i;
8062 
8063  for (i=0; i<size; i++) {
8064  table[i] = ibf_load_id(load, table[i]);
8065  }
8066  return table;
8067  }
8068  else {
8069  return NULL;
8070  }
8071 }
8072 
8073 static struct iseq_catch_table *
8074 ibf_dump_catch_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
8075 {
8076  const struct iseq_catch_table *table = iseq->body->catch_table;
8077 
8078  if (table) {
8079  int byte_size = iseq_catch_table_bytes(iseq->body->catch_table->size);
8080  struct iseq_catch_table *dump_table = (struct iseq_catch_table *)ALLOCA_N(char, byte_size);
8081  unsigned int i;
8082  dump_table->size = table->size;
8083  for (i=0; i<table->size; i++) {
8084  dump_table->entries[i] = table->entries[i];
8085  dump_table->entries[i].iseq = ibf_dump_iseq(dump, table->entries[i].iseq);
8086  }
8087  return (struct iseq_catch_table *)(VALUE)ibf_dump_write(dump, dump_table, byte_size);
8088  }
8089  else {
8090  return NULL;
8091  }
8092 }
8093 
8094 static struct iseq_catch_table *
8095 ibf_load_catch_table(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
8096 {
8097  if (body->catch_table) {
8098  struct iseq_catch_table *table;
8099  unsigned int i;
8100  unsigned int size;
8101  size = *(unsigned int *)(load->buff + IBF_OFFSET(body->catch_table));
8102  table = ibf_load_alloc(load, IBF_OFFSET(body->catch_table), iseq_catch_table_bytes(size));
8103  for (i=0; i<size; i++) {
8104  table->entries[i].iseq = ibf_load_iseq(load, table->entries[i].iseq);
8105  }
8106  return table;
8107  }
8108  else {
8109  return NULL;
8110  }
8111 }
8112 
8113 static struct rb_call_info *
8114 ibf_dump_ci_entries(struct ibf_dump *dump, const rb_iseq_t *iseq)
8115 {
8116  const unsigned int ci_size = iseq->body->ci_size;
8117  const unsigned int ci_kw_size = iseq->body->ci_kw_size;
8118  const struct rb_call_info *ci_entries = iseq->body->ci_entries;
8119  struct rb_call_info *dump_ci_entries;
8120  struct rb_call_info_with_kwarg *dump_ci_kw_entries;
8121  int byte_size = ci_size * sizeof(struct rb_call_info) +
8122  ci_kw_size * sizeof(struct rb_call_info_with_kwarg);
8123  unsigned int i;
8124 
8125  dump_ci_entries = (struct rb_call_info *)ALLOCA_N(char, byte_size);
8126  dump_ci_kw_entries = (struct rb_call_info_with_kwarg *)&dump_ci_entries[ci_size];
8127  memcpy(dump_ci_entries, ci_entries, byte_size);
8128 
8129  for (i=0; i<ci_size; i++) { /* conver ID for each ci */
8130  dump_ci_entries[i].mid = ibf_dump_id(dump, dump_ci_entries[i].mid);
8131  }
8132  for (i=0; i<ci_kw_size; i++) {
8133  const struct rb_call_info_kw_arg *kw_arg = dump_ci_kw_entries[i].kw_arg;
8134  int j;
8135  VALUE *keywords = ALLOCA_N(VALUE, kw_arg->keyword_len);
8136  for (j=0; j<kw_arg->keyword_len; j++) {
8137  keywords[j] = (VALUE)ibf_dump_object(dump, kw_arg->keywords[j]); /* kw_arg->keywords[n] is Symbol */
8138  }
8139  dump_ci_kw_entries[i].kw_arg = (struct rb_call_info_kw_arg *)(VALUE)ibf_dump_write(dump, &kw_arg->keyword_len, sizeof(int));
8140  ibf_dump_write(dump, keywords, sizeof(VALUE) * kw_arg->keyword_len);
8141 
8142  dump_ci_kw_entries[i].ci.mid = ibf_dump_id(dump, dump_ci_kw_entries[i].ci.mid);
8143  }
8144  return (struct rb_call_info *)(VALUE)ibf_dump_write(dump, dump_ci_entries, byte_size);
8145 }
8146 
8147 static struct rb_call_info *
8148 ibf_load_ci_entries(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
8149 {
8150  unsigned int i;
8151  const unsigned int ci_size = body->ci_size;
8152  const unsigned int ci_kw_size = body->ci_kw_size;
8153  struct rb_call_info *ci_entries = ibf_load_alloc(load, IBF_OFFSET(body->ci_entries),
8154  sizeof(struct rb_call_info) * body->ci_size +
8155  sizeof(struct rb_call_info_with_kwarg) * body->ci_kw_size);
8156  struct rb_call_info_with_kwarg *ci_kw_entries = (struct rb_call_info_with_kwarg *)&ci_entries[ci_size];
8157 
8158  for (i=0; i<ci_size; i++) {
8159  ci_entries[i].mid = ibf_load_id(load, ci_entries[i].mid);
8160  }
8161  for (i=0; i<ci_kw_size; i++) {
8162  int j;
8163  ibf_offset_t kw_arg_offset = IBF_OFFSET(ci_kw_entries[i].kw_arg);
8164  const int keyword_len = *(int *)(load->buff + kw_arg_offset);
8165  const VALUE *keywords = (VALUE *)(load->buff + kw_arg_offset + sizeof(int));
8166  struct rb_call_info_kw_arg *kw_arg = ruby_xmalloc(sizeof(struct rb_call_info_kw_arg) + sizeof(VALUE) * (keyword_len - 1));
8167  kw_arg->keyword_len = keyword_len;
8168  for (j=0; j<kw_arg->keyword_len; j++) {
8169  kw_arg->keywords[j] = (VALUE)ibf_load_object(load, keywords[j]);
8170  }
8171  ci_kw_entries[i].kw_arg = kw_arg;
8172  ci_kw_entries[i].ci.mid = ibf_load_id(load, ci_kw_entries[i].ci.mid);
8173  }
8174 
8175  return ci_entries;
8176 }
8177 
8178 static ibf_offset_t
8179 ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
8180 {
8181  struct rb_iseq_constant_body dump_body;
8182  dump_body = *iseq->body;
8183 
8184  dump_body.location.pathobj = ibf_dump_object(dump, dump_body.location.pathobj); /* TODO: freeze */
8185  dump_body.location.base_label = ibf_dump_object(dump, dump_body.location.base_label);
8186  dump_body.location.label = ibf_dump_object(dump, dump_body.location.label);
8187 
8188  dump_body.iseq_encoded = ibf_dump_code(dump, iseq);
8189  dump_body.param.opt_table = ibf_dump_param_opt_table(dump, iseq);
8190  dump_body.param.keyword = ibf_dump_param_keyword(dump, iseq);
8191  dump_body.line_info_table = ibf_dump_line_info_table(dump, iseq);
8192  dump_body.local_table = ibf_dump_local_table(dump, iseq);
8193  dump_body.catch_table = ibf_dump_catch_table(dump, iseq);
8194  dump_body.parent_iseq = ibf_dump_iseq(dump, iseq->body->parent_iseq);
8195  dump_body.local_iseq = ibf_dump_iseq(dump, iseq->body->local_iseq);
8196  dump_body.is_entries = NULL;
8197  dump_body.ci_entries = ibf_dump_ci_entries(dump, iseq);
8198  dump_body.cc_entries = NULL;
8199  dump_body.mark_ary = ISEQ_FLIP_CNT(iseq);
8200 
8201  return ibf_dump_write(dump, &dump_body, sizeof(dump_body));
8202 }
8203 
8204 static VALUE
8205 ibf_load_location_str(const struct ibf_load *load, VALUE str_index)
8206 {
8207  VALUE str = ibf_load_object(load, str_index);
8208  if (str != Qnil) {
8209  str = rb_fstring(str);
8210  }
8211  return str;
8212 }
8213 
8214 static void
8215 ibf_load_iseq_each(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
8216 {
8217  struct rb_iseq_constant_body *load_body = iseq->body = ZALLOC(struct rb_iseq_constant_body);
8218  const struct rb_iseq_constant_body *body = (struct rb_iseq_constant_body *)(load->buff + offset);
8219 
8220  /* memcpy(load_body, load->buff + offset, sizeof(*load_body)); */
8221  load_body->type = body->type;
8222  load_body->stack_max = body->stack_max;
8223  load_body->iseq_size = body->iseq_size;
8224  load_body->param = body->param;
8225  load_body->local_table_size = body->local_table_size;
8226  load_body->is_size = body->is_size;
8227  load_body->ci_size = body->ci_size;
8228  load_body->ci_kw_size = body->ci_kw_size;
8229  load_body->line_info_size = body->line_info_size;
8230 
8231  RB_OBJ_WRITE(iseq, &load_body->mark_ary, iseq_mark_ary_create((int)body->mark_ary));
8232 
8233  {
8234  VALUE realpath = Qnil, path = ibf_load_object(load, body->location.pathobj);
8235  if (RB_TYPE_P(path, T_STRING)) {
8236  realpath = path = rb_fstring(path);
8237  }
8238  else if (RB_TYPE_P(path, T_ARRAY)) {
8239  VALUE pathobj = path;
8240  if (RARRAY_LEN(pathobj) != 2) {
8241  rb_raise(rb_eRuntimeError, "path object size mismatch");
8242  }
8243  path = rb_fstring(RARRAY_AREF(pathobj, 0));
8244  realpath = rb_fstring(RARRAY_AREF(pathobj, 1));
8245  }
8246  else {
8247  rb_raise(rb_eRuntimeError, "unexpected path object");
8248  }
8249  rb_iseq_pathobj_set(iseq, path, realpath);
8250  }
8251 
8252  RB_OBJ_WRITE(iseq, &load_body->location.base_label, ibf_load_location_str(load, body->location.base_label));
8253  RB_OBJ_WRITE(iseq, &load_body->location.label, ibf_load_location_str(load, body->location.label));
8254  load_body->location.first_lineno = body->location.first_lineno;
8255 
8256  load_body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, body->is_size);
8257  load_body->ci_entries = ibf_load_ci_entries(load, body);
8258  load_body->cc_entries = ZALLOC_N(struct rb_call_cache, body->ci_size + body->ci_kw_size);
8259  load_body->param.opt_table = ibf_load_param_opt_table(load, body);
8260  load_body->param.keyword = ibf_load_param_keyword(load, body);
8261  load_body->line_info_table = ibf_load_line_info_table(load, body);
8262  load_body->local_table = ibf_load_local_table(load, body);
8263  load_body->catch_table = ibf_load_catch_table(load, body);
8264  load_body->parent_iseq = ibf_load_iseq(load, body->parent_iseq);
8265  load_body->local_iseq = ibf_load_iseq(load, body->local_iseq);
8266 
8267  load_body->iseq_encoded = ibf_load_code(load, iseq, body);
8268 
8270 }
8271 
8272 
8273 static void
8274 ibf_dump_iseq_list(struct ibf_dump *dump, struct ibf_header *header)
8275 {
8276  const long size = RARRAY_LEN(dump->iseq_list);
8277  ibf_offset_t *list = ALLOCA_N(ibf_offset_t, size);
8278  long i;
8279 
8280  for (i=0; i<size; i++) {
8281  list[i] = (ibf_offset_t)NUM2LONG(rb_ary_entry(dump->iseq_list, i));
8282  }
8283 
8284  header->iseq_list_offset = ibf_dump_write(dump, list, sizeof(ibf_offset_t) * size);
8285  header->iseq_list_size = (unsigned int)size;
8286 }
8287 
8289  struct ibf_dump *dump;
8290  long *list;
8292 };
8293 
8294 static int
8295 ibf_dump_id_list_i(st_data_t key, st_data_t val, st_data_t ptr)
8296 {
8297  struct ibf_dump_id_list_i_arg *arg = (struct ibf_dump_id_list_i_arg *)ptr;
8298  int i = (int)val;
8299  ID id = (ID)key;
8300  assert(arg->current_i == i);
8301  arg->current_i++;
8302 
8303  if (rb_id2name(id)) {
8304  arg->list[i] = (long)ibf_dump_object(arg->dump, rb_id2str(id));
8305  }
8306  else {
8307  arg->list[i] = 0;
8308  }
8309 
8310  return ST_CONTINUE;
8311 }
8312 
8313 static void
8314 ibf_dump_id_list(struct ibf_dump *dump, struct ibf_header *header)
8315 {
8316  const long size = dump->id_table->num_entries;
8317  struct ibf_dump_id_list_i_arg arg;
8318  arg.list = ALLOCA_N(long, size);
8319  arg.dump = dump;
8320  arg.current_i = 0;
8321 
8322  st_foreach(dump->id_table, ibf_dump_id_list_i, (st_data_t)&arg);
8323 
8324  header->id_list_offset = ibf_dump_write(dump, arg.list, sizeof(long) * size);
8325  header->id_list_size = (unsigned int)size;
8326 }
8327 
8328 #define IBF_OBJECT_INTERNAL FL_PROMOTED0
8329 
8330 /*
8331  * Binary format
8332  * - ibf_object_header
8333  * - ibf_object_xxx (xxx is type)
8334  */
8335 
8337  unsigned int type: 5;
8338  unsigned int special_const: 1;
8339  unsigned int frozen: 1;
8340  unsigned int internal: 1;
8341 };
8342 
8347 };
8348 
8350  long encindex;
8351  long len;
8352  char ptr[1];
8353 };
8354 
8356  long srcstr;
8357  char option;
8358 };
8359 
8361  long len;
8362  long ary[1];
8363 };
8364 
8366  long len;
8367  long keyval[1];
8368 };
8369 
8372  long len;
8373  long beg;
8374  long end;
8375  int excl;
8376 };
8377 
8379  ssize_t slen;
8380  BDIGIT digits[1];
8381 };
8382 
8385 };
8386 
8388  long a, b;
8389 };
8390 
8392  long str;
8393 };
8394 
8395 #define IBF_OBJHEADER(offset) (struct ibf_object_header *)(load->buff + (offset))
8396 #define IBF_OBJBODY(type, offset) (type *)(load->buff + sizeof(struct ibf_object_header) + (offset))
8397 
8398 static void
8399 ibf_dump_object_unsupported(struct ibf_dump *dump, VALUE obj)
8400 {
8401  rb_obj_info_dump(obj);
8402  rb_bug("ibf_dump_object_unsupported: unsupported");
8403 }
8404 
8405 static VALUE
8406 ibf_load_object_unsupported(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
8407 {
8408  rb_bug("unsupported");
8409  return Qnil;
8410 }
8411 
8412 static void
8413 ibf_dump_object_class(struct ibf_dump *dump, VALUE obj)
8414 {
8415  enum ibf_object_class_index cindex;
8416  if (obj == rb_cObject) {
8417  cindex = IBF_OBJECT_CLASS_OBJECT;
8418  }
8419  else if (obj == rb_cArray) {
8420  cindex = IBF_OBJECT_CLASS_ARRAY;
8421  }
8422  else if (obj == rb_eStandardError) {
8424  }
8425  else {
8426  rb_obj_info_dump(obj);
8427  rb_p(obj);
8428  rb_bug("unsupported class");
8429  }
8430  ibf_dump_write(dump, &cindex, sizeof(cindex));
8431 }
8432 
8433 static VALUE
8434 ibf_load_object_class(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
8435 {
8436  enum ibf_object_class_index *cindexp = IBF_OBJBODY(enum ibf_object_class_index, offset);
8437  enum ibf_object_class_index cindex = *cindexp;
8438 
8439  switch (cindex) {
8441  return rb_cObject;
8443  return rb_cArray;
8445  return rb_eStandardError;
8446  }
8447 
8448  rb_bug("ibf_load_object_class: unknown class (%d)", (int)cindex);
8449 }
8450 
8451 
8452 static void
8453 ibf_dump_object_float(struct ibf_dump *dump, VALUE obj)
8454 {
8455  double dbl = RFLOAT_VALUE(obj);
8456  ibf_dump_write(dump, &dbl, sizeof(dbl));
8457 }
8458 
8459 static VALUE
8460 ibf_load_object_float(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
8461 {
8462  double *dblp = IBF_OBJBODY(double, offset);
8463  return DBL2NUM(*dblp);
8464 }
8465 
8466 static void
8467 ibf_dump_object_string(struct ibf_dump *dump, VALUE obj)
8468 {
8469  long encindex = (long)rb_enc_get_index(obj);
8470  long len = RSTRING_LEN(obj);
8471  const char *ptr = RSTRING_PTR(obj);
8472 
8473  if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) {
8474  rb_encoding *enc = rb_enc_from_index((int)encindex);
8475  const char *enc_name = rb_enc_name(enc);
8476  encindex = RUBY_ENCINDEX_BUILTIN_MAX + ibf_dump_object(dump, rb_str_new2(enc_name));
8477  }
8478 
8479  IBF_WV(encindex);
8480  IBF_WV(len);
8481  IBF_WP(ptr, char, len);
8482 }
8483 
8484 static VALUE
8485 ibf_load_object_string(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
8486 {
8487  const struct ibf_object_string *string = IBF_OBJBODY(struct ibf_object_string, offset);
8488  VALUE str = rb_str_new(string->ptr, string->len);
8489  int encindex = (int)string->encindex;
8490 
8491  if (encindex > RUBY_ENCINDEX_BUILTIN_MAX) {
8492  VALUE enc_name_str = ibf_load_object(load, encindex - RUBY_ENCINDEX_BUILTIN_MAX);
8493  encindex = rb_enc_find_index(RSTRING_PTR(enc_name_str));
8494  }
8495  rb_enc_associate_index(str, encindex);
8496 
8497  if (header->internal) rb_obj_hide(str);
8498  if (header->frozen) str = rb_fstring(str);
8499 
8500  return str;
8501 }
8502 
8503 static void
8504 ibf_dump_object_regexp(struct ibf_dump *dump, VALUE obj)
8505 {
8506  struct ibf_object_regexp regexp;
8507  regexp.srcstr = RREGEXP_SRC(obj);
8508  regexp.option = (char)rb_reg_options(obj);
8509  regexp.srcstr = (long)ibf_dump_object(dump, regexp.srcstr);
8510  IBF_WV(regexp);
8511 }
8512 
8513 static VALUE
8514 ibf_load_object_regexp(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
8515 {
8516  const struct ibf_object_regexp *regexp = IBF_OBJBODY(struct ibf_object_regexp, offset);
8517  VALUE srcstr = ibf_load_object(load, regexp->srcstr);
8518  VALUE reg = rb_reg_compile(srcstr, (int)regexp->option, NULL, 0);
8519 
8520  if (header->internal) rb_obj_hide(reg);
8521  if (header->frozen) rb_obj_freeze(reg);
8522 
8523  return reg;
8524 }
8525 
8526 static void
8527 ibf_dump_object_array(struct ibf_dump *dump, VALUE obj)
8528 {
8529  long i, len = (int)RARRAY_LEN(obj);
8530  IBF_WV(len);
8531  for (i=0; i<len; i++) {
8532  long index = (long)ibf_dump_object(dump, RARRAY_AREF(obj, i));
8533  IBF_WV(index);
8534  }
8535 }
8536 
8537 static VALUE
8538 ibf_load_object_array(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
8539 {
8540  const struct ibf_object_array *array = IBF_OBJBODY(struct ibf_object_array, offset);
8541  VALUE ary = rb_ary_new_capa(array->len);
8542  int i;
8543 
8544  for (i=0; i<array->len; i++) {
8545  rb_ary_push(ary, ibf_load_object(load, array->ary[i]));
8546  }
8547 
8548  if (header->internal) rb_obj_hide(ary);
8549  if (header->frozen) rb_obj_freeze(ary);
8550 
8551  return ary;
8552 }
8553 
8554 static int
8555 ibf_dump_object_hash_i(st_data_t key, st_data_t val, st_data_t ptr)
8556 {
8557  struct ibf_dump *dump = (struct ibf_dump *)ptr;
8558  long key_index = (long)ibf_dump_object(dump, (VALUE)key);
8559  long val_index = (long)ibf_dump_object(dump, (VALUE)val);
8560  IBF_WV(key_index);
8561  IBF_WV(val_index);
8562  return ST_CONTINUE;
8563 }
8564 
8565 static void
8566 ibf_dump_object_hash(struct ibf_dump *dump, VALUE obj)
8567 {
8568  long len = RHASH_SIZE(obj);
8569  IBF_WV(len);
8570  if (len > 0) st_foreach(RHASH(obj)->ntbl, ibf_dump_object_hash_i, (st_data_t)dump);
8571 }
8572 
8573 static VALUE
8574 ibf_load_object_hash(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
8575 {
8576  const struct ibf_object_hash *hash = IBF_OBJBODY(struct ibf_object_hash, offset);
8577  VALUE obj = rb_hash_new_with_size(hash->len);
8578  int i;
8579 
8580  for (i=0; i<hash->len; i++) {
8581  VALUE key = ibf_load_object(load, hash->keyval[i*2 ]);
8582  VALUE val = ibf_load_object(load, hash->keyval[i*2+1]);
8583  rb_hash_aset(obj, key, val);
8584  }
8585  rb_hash_rehash(obj);
8586 
8587  if (header->internal) rb_obj_hide(obj);
8588  if (header->frozen) rb_obj_freeze(obj);
8589 
8590  return obj;
8591 }
8592 
8593 static void
8594 ibf_dump_object_struct(struct ibf_dump *dump, VALUE obj)
8595 {
8596  if (rb_obj_is_kind_of(obj, rb_cRange)) {
8597  struct ibf_object_struct_range range;
8598  VALUE beg, end;
8599  range.len = 3;
8600  range.class_index = 0;
8601 
8602  rb_range_values(obj, &beg, &end, &range.excl);
8603  range.beg = (long)ibf_dump_object(dump, beg);
8604  range.end = (long)ibf_dump_object(dump, end);
8605 
8606  IBF_WV(range);
8607  }
8608  else {
8609  rb_bug("ibf_dump_object_struct: unsupported class");
8610  }
8611 }
8612 
8613 static VALUE
8614 ibf_load_object_struct(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
8615 {
8616  const struct ibf_object_struct_range *range = IBF_OBJBODY(struct ibf_object_struct_range, offset);
8617  VALUE beg = ibf_load_object(load, range->beg);
8618  VALUE end = ibf_load_object(load, range->end);
8619  VALUE obj = rb_range_new(beg, end, range->excl);
8620  if (header->internal) rb_obj_hide(obj);
8621  if (header->frozen) rb_obj_freeze(obj);
8622  return obj;
8623 }
8624 
8625 static void
8626 ibf_dump_object_bignum(struct ibf_dump *dump, VALUE obj)
8627 {
8628  ssize_t len = BIGNUM_LEN(obj);
8629  ssize_t slen = BIGNUM_SIGN(obj) > 0 ? len : len * -1;
8630  BDIGIT *d = BIGNUM_DIGITS(obj);
8631 
8632  IBF_WV(slen);
8633  IBF_WP(d, BDIGIT, len);
8634 }
8635 
8636 static VALUE
8637 ibf_load_object_bignum(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
8638 {
8639  const struct ibf_object_bignum *bignum = IBF_OBJBODY(struct ibf_object_bignum, offset);
8640  int sign = bignum->slen > 0;
8641  ssize_t len = sign > 0 ? bignum->slen : -1 * bignum->slen;
8642  VALUE obj = rb_integer_unpack(bignum->digits, len * 2, 2, 0,
8644  if (header->internal) rb_obj_hide(obj);
8645  if (header->frozen) rb_obj_freeze(obj);
8646  return obj;
8647 }
8648 
8649 static void
8650 ibf_dump_object_data(struct ibf_dump *dump, VALUE obj)
8651 {
8652  if (rb_data_is_encoding(obj)) {
8653  rb_encoding *enc = rb_to_encoding(obj);
8654  const char *name = rb_enc_name(enc);
8656  long len = strlen(name) + 1;
8657  IBF_WV(type);
8658  IBF_WV(len);
8659  IBF_WP(name, char, strlen(name) + 1);
8660  }
8661  else {
8662  ibf_dump_object_unsupported(dump, obj);
8663  }
8664 }
8665 
8666 static VALUE
8667 ibf_load_object_data(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
8668 {
8669  const enum ibf_object_data_type *typep = IBF_OBJBODY(enum ibf_object_data_type, offset);
8670  /* const long *lenp = IBF_OBJBODY(long, offset + sizeof(enum ibf_object_data_type)); */
8671  const char *data = IBF_OBJBODY(char, offset + sizeof(enum ibf_object_data_type) + sizeof(long));
8672 
8673  switch (*typep) {
8675  {
8676  VALUE encobj = rb_enc_from_encoding(rb_enc_find(data));
8677  return encobj;
8678  }
8679  }
8680 
8681  return ibf_load_object_unsupported(load, header, offset);
8682 }
8683 
8684 static void
8685 ibf_dump_object_complex_rational(struct ibf_dump *dump, VALUE obj)
8686 {
8687  long real = (long)ibf_dump_object(dump, RCOMPLEX(obj)->real);
8688  long imag = (long)ibf_dump_object(dump, RCOMPLEX(obj)->imag);
8689 
8690  IBF_WV(real);
8691  IBF_WV(imag);
8692 }
8693 
8694 static VALUE
8695 ibf_load_object_complex_rational(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
8696 {
8697  const struct ibf_object_complex_rational *nums = IBF_OBJBODY(struct ibf_object_complex_rational, offset);
8698  VALUE a = ibf_load_object(load, nums->a);
8699  VALUE b = ibf_load_object(load, nums->b);
8700  VALUE obj = header->type == T_COMPLEX ?
8701  rb_complex_new(a, b) : rb_rational_new(a, b);
8702 
8703  if (header->internal) rb_obj_hide(obj);
8704  if (header->frozen) rb_obj_freeze(obj);
8705  return obj;
8706 }
8707 
8708 static void
8709 ibf_dump_object_symbol(struct ibf_dump *dump, VALUE obj)
8710 {
8711  VALUE str = rb_sym2str(obj);
8712  long str_index = (long)ibf_dump_object(dump, str);
8713  IBF_WV(str_index);
8714 }
8715 
8716 static VALUE
8717 ibf_load_object_symbol(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
8718 {
8719  /* const struct ibf_object_header *header = IBF_OBJHEADER(offset); */
8720  const struct ibf_object_symbol *symbol = IBF_OBJBODY(struct ibf_object_symbol, offset);
8721  VALUE str = ibf_load_object(load, symbol->str);
8722  ID id = rb_intern_str(str);
8723  return ID2SYM(id);
8724 }
8725 
8726 typedef void (*ibf_dump_object_function)(struct ibf_dump *dump, VALUE obj);
8727 static ibf_dump_object_function dump_object_functions[RUBY_T_MASK+1] = {
8728  ibf_dump_object_unsupported, /* T_NONE */
8729  ibf_dump_object_unsupported, /* T_OBJECT */
8730  ibf_dump_object_class, /* T_CLASS */
8731  ibf_dump_object_unsupported, /* T_MODULE */
8732  ibf_dump_object_float, /* T_FLOAT */
8733  ibf_dump_object_string, /* T_STRING */
8734  ibf_dump_object_regexp, /* T_REGEXP */
8735  ibf_dump_object_array, /* T_ARRAY */
8736  ibf_dump_object_hash, /* T_HASH */
8737  ibf_dump_object_struct, /* T_STRUCT */
8738  ibf_dump_object_bignum, /* T_BIGNUM */
8739  ibf_dump_object_unsupported, /* T_FILE */
8740  ibf_dump_object_data, /* T_DATA */
8741  ibf_dump_object_unsupported, /* T_MATCH */
8742  ibf_dump_object_complex_rational, /* T_COMPLEX */
8743  ibf_dump_object_complex_rational, /* T_RATIONAL */
8744  ibf_dump_object_unsupported, /* 0x10 */
8745  ibf_dump_object_unsupported, /* 0x11 T_NIL */
8746  ibf_dump_object_unsupported, /* 0x12 T_TRUE */
8747  ibf_dump_object_unsupported, /* 0x13 T_FALSE */
8748  ibf_dump_object_symbol, /* 0x14 T_SYMBOL */
8749  ibf_dump_object_unsupported, /* T_FIXNUM */
8750  ibf_dump_object_unsupported, /* T_UNDEF */
8751  ibf_dump_object_unsupported, /* 0x17 */
8752  ibf_dump_object_unsupported, /* 0x18 */
8753  ibf_dump_object_unsupported, /* 0x19 */
8754  ibf_dump_object_unsupported, /* T_IMEMO 0x1a */
8755  ibf_dump_object_unsupported, /* T_NODE 0x1b */
8756  ibf_dump_object_unsupported, /* T_ICLASS 0x1c */
8757  ibf_dump_object_unsupported, /* T_ZOMBIE 0x1d */
8758  ibf_dump_object_unsupported, /* 0x1e */
8759  ibf_dump_object_unsupported /* 0x1f */
8760 };
8761 
8762 static ibf_offset_t
8763 lbf_dump_object_object(struct ibf_dump *dump, VALUE obj)
8764 {
8765  struct ibf_object_header obj_header;
8766  ibf_offset_t current_offset = ibf_dump_pos(dump);
8767  obj_header.type = TYPE(obj);
8768 
8769  if (SPECIAL_CONST_P(obj)) {
8770  if (RB_TYPE_P(obj, T_SYMBOL) ||
8771  RB_TYPE_P(obj, T_FLOAT)) {
8772  obj_header.internal = FALSE;
8773  goto dump_object;
8774  }
8775  obj_header.special_const = TRUE;
8776  obj_header.frozen = TRUE;
8777  obj_header.internal = TRUE;
8778  IBF_WV(obj_header);
8779  IBF_WV(obj);
8780  }
8781  else {
8782  obj_header.internal = (RBASIC_CLASS(obj) == 0) ? TRUE : FALSE;
8783  dump_object:
8784  obj_header.special_const = FALSE;
8785  obj_header.frozen = FL_TEST(obj, FL_FREEZE) ? TRUE : FALSE;
8786  IBF_WV(obj_header);
8787  (*dump_object_functions[obj_header.type])(dump, obj);
8788  }
8789 
8790  return current_offset;
8791 }
8792 
8793 typedef VALUE (*ibf_load_object_function)(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t);
8794 static ibf_load_object_function load_object_functions[RUBY_T_MASK+1] = {
8795  ibf_load_object_unsupported, /* T_NONE */
8796  ibf_load_object_unsupported, /* T_OBJECT */
8797  ibf_load_object_class, /* T_CLASS */
8798  ibf_load_object_unsupported, /* T_MODULE */
8799  ibf_load_object_float, /* T_FLOAT */
8800  ibf_load_object_string, /* T_STRING */
8801  ibf_load_object_regexp, /* T_REGEXP */
8802  ibf_load_object_array, /* T_ARRAY */
8803  ibf_load_object_hash, /* T_HASH */
8804  ibf_load_object_struct, /* T_STRUCT */
8805  ibf_load_object_bignum, /* T_BIGNUM */
8806  ibf_load_object_unsupported, /* T_FILE */
8807  ibf_load_object_data, /* T_DATA */
8808  ibf_load_object_unsupported, /* T_MATCH */
8809  ibf_load_object_complex_rational, /* T_COMPLEX */
8810  ibf_load_object_complex_rational, /* T_RATIONAL */
8811  ibf_load_object_unsupported, /* 0x10 */
8812  ibf_load_object_unsupported, /* T_NIL */
8813  ibf_load_object_unsupported, /* T_TRUE */
8814  ibf_load_object_unsupported, /* T_FALSE */
8815  ibf_load_object_symbol,
8816  ibf_load_object_unsupported, /* T_FIXNUM */
8817  ibf_load_object_unsupported, /* T_UNDEF */
8818  ibf_load_object_unsupported, /* 0x17 */
8819  ibf_load_object_unsupported, /* 0x18 */
8820  ibf_load_object_unsupported, /* 0x19 */
8821  ibf_load_object_unsupported, /* T_IMEMO 0x1a */
8822  ibf_load_object_unsupported, /* T_NODE 0x1b */
8823  ibf_load_object_unsupported, /* T_ICLASS 0x1c */
8824  ibf_load_object_unsupported, /* T_ZOMBIE 0x1d */
8825  ibf_load_object_unsupported, /* 0x1e */
8826  ibf_load_object_unsupported /* 0x1f */
8827 };
8828 
8829 static VALUE
8830 ibf_load_object(const struct ibf_load *load, VALUE object_index)
8831 {
8832  if (object_index == 0) {
8833  return Qnil;
8834  }
8835  else if (object_index >= load->header->object_list_size) {
8836  rb_raise(rb_eIndexError, "object index out of range: %"PRIdVALUE, object_index);
8837  }
8838  else {
8839  VALUE obj = rb_ary_entry(load->obj_list, (long)object_index);
8840  if (obj == Qnil) { /* TODO: avoid multiple Qnil load */
8841  ibf_offset_t *offsets = (ibf_offset_t *)(load->header->object_list_offset + load->buff);
8842  ibf_offset_t offset = offsets[object_index];
8843  const struct ibf_object_header *header = IBF_OBJHEADER(offset);
8844 
8845  if (header->special_const) {
8846  VALUE *vp = IBF_OBJBODY(VALUE, offset);
8847  obj = *vp;
8848  }
8849  else {
8850  obj = (*load_object_functions[header->type])(load, header, offset);
8851  }
8852 
8853  rb_ary_store(load->obj_list, (long)object_index, obj);
8854  }
8855  iseq_add_mark_object(load->iseq, obj);
8856  return obj;
8857  }
8858 }
8859 
8860 static void
8861 ibf_dump_object_list(struct ibf_dump *dump, struct ibf_header *header)
8862 {
8863  VALUE list = rb_ary_tmp_new(RARRAY_LEN(dump->obj_list));
8864  int i, size;
8865 
8866  for (i=0; i<RARRAY_LEN(dump->obj_list); i++) {
8867  VALUE obj = RARRAY_AREF(dump->obj_list, i);
8868  ibf_offset_t offset = lbf_dump_object_object(dump, obj);
8869  rb_ary_push(list, UINT2NUM(offset));
8870  }
8871  size = i;
8872  header->object_list_offset = ibf_dump_pos(dump);
8873 
8874  for (i=0; i<size; i++) {
8875  ibf_offset_t offset = NUM2UINT(RARRAY_AREF(list, i));
8876  IBF_WV(offset);
8877  }
8878 
8879  header->object_list_size = size;
8880 }
8881 
8882 static void
8883 ibf_dump_mark(void *ptr)
8884 {
8885  struct ibf_dump *dump = (struct ibf_dump *)ptr;
8886  rb_gc_mark(dump->str);
8887  rb_gc_mark(dump->iseq_list);
8888  rb_gc_mark(dump->obj_list);
8889 }
8890 
8891 static void
8892 ibf_dump_free(void *ptr)
8893 {
8894  struct ibf_dump *dump = (struct ibf_dump *)ptr;
8895  if (dump->iseq_table) {
8896  st_free_table(dump->iseq_table);
8897  dump->iseq_table = 0;
8898  }
8899  if (dump->id_table) {
8900  st_free_table(dump->id_table);
8901  dump->id_table = 0;
8902  }
8903  ruby_xfree(dump);
8904 }
8905 
8906 static size_t
8907 ibf_dump_memsize(const void *ptr)
8908 {
8909  struct ibf_dump *dump = (struct ibf_dump *)ptr;
8910  size_t size = sizeof(*dump);
8911  if (dump->iseq_table) size += st_memsize(dump->iseq_table);
8912  if (dump->id_table) size += st_memsize(dump->id_table);
8913  return size;
8914 }
8915 
8916 static const rb_data_type_t ibf_dump_type = {
8917  "ibf_dump",
8918  {ibf_dump_mark, ibf_dump_free, ibf_dump_memsize,},
8920 };
8921 
8922 static void
8923 ibf_dump_setup(struct ibf_dump *dump, VALUE dumper_obj)
8924 {
8925  RB_OBJ_WRITE(dumper_obj, &dump->str, rb_str_new(0, 0));
8926  RB_OBJ_WRITE(dumper_obj, &dump->iseq_list, rb_ary_tmp_new(0));
8927  RB_OBJ_WRITE(dumper_obj, &dump->obj_list, rb_ary_tmp_new(1));
8928  rb_ary_push(dump->obj_list, Qnil); /* 0th is nil */
8929  dump->iseq_table = st_init_numtable(); /* need free */
8930  dump->id_table = st_init_numtable(); /* need free */
8931 
8932  ibf_table_index(dump->id_table, 0); /* id_index:0 is 0 */
8933 }
8934 
8935 VALUE
8936 iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt)
8937 {
8938  struct ibf_dump *dump;
8939  struct ibf_header header = {{0}};
8940  VALUE dump_obj;
8941  VALUE str;
8942 
8943  if (iseq->body->parent_iseq != NULL ||
8944  iseq->body->local_iseq != iseq) {
8945  rb_raise(rb_eRuntimeError, "should be top of iseq");
8946  }
8947  if (RTEST(ISEQ_COVERAGE(iseq))) {
8948  rb_raise(rb_eRuntimeError, "should not compile with coverage");
8949  }
8950 
8951  dump_obj = TypedData_Make_Struct(0, struct ibf_dump, &ibf_dump_type, dump);
8952  ibf_dump_setup(dump, dump_obj);
8953 
8954  ibf_dump_write(dump, &header, sizeof(header));
8955  ibf_dump_write(dump, RUBY_PLATFORM, strlen(RUBY_PLATFORM) + 1);
8956  ibf_dump_iseq(dump, iseq);
8957 
8958  header.magic[0] = 'Y'; /* YARB */
8959  header.magic[1] = 'A';
8960  header.magic[2] = 'R';
8961  header.magic[3] = 'B';
8964  ibf_dump_iseq_list(dump, &header);
8965  ibf_dump_id_list(dump, &header);
8966  ibf_dump_object_list(dump, &header);
8967  header.size = ibf_dump_pos(dump);
8968 
8969  if (RTEST(opt)) {
8970  VALUE opt_str = opt;
8971  const char *ptr = StringValuePtr(opt_str);
8972  header.extra_size = RSTRING_LENINT(opt_str);
8973  ibf_dump_write(dump, ptr, header.extra_size);
8974  }
8975  else {
8976  header.extra_size = 0;
8977  }
8978 
8979  ibf_dump_overwrite(dump, &header, sizeof(header), 0);
8980 
8981  str = dump->str;
8982  ibf_dump_free(dump);
8983  DATA_PTR(dump_obj) = NULL;
8984  RB_GC_GUARD(dump_obj);
8985  return str;
8986 }
8987 
8988 static const ibf_offset_t *
8989 ibf_iseq_list(const struct ibf_load *load)
8990 {
8991  return (ibf_offset_t *)(load->buff + load->header->iseq_list_offset);
8992 }
8993 
8994 void
8996 {
8997  struct ibf_load *load = RTYPEDDATA_DATA(iseq->aux.loader.obj);
8998  rb_iseq_t *prev_src_iseq = load->iseq;
8999  load->iseq = iseq;
9000  ibf_load_iseq_each(load, iseq, ibf_iseq_list(load)[iseq->aux.loader.index]);
9001  ISEQ_COMPILE_DATA(iseq) = NULL;
9003  load->iseq = prev_src_iseq;
9004 }
9005 
9006 #if USE_LAZY_LOAD
9007 const rb_iseq_t *
9008 rb_iseq_complete(const rb_iseq_t *iseq)
9009 {
9011  return iseq;
9012 }
9013 #endif
9014 
9015 static rb_iseq_t *
9016 ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq)
9017 {
9018  int iseq_index = (int)(VALUE)index_iseq;
9019 
9020  if (iseq_index == -1) {
9021  return NULL;
9022  }
9023  else {
9024  VALUE iseqv = rb_ary_entry(load->iseq_list, iseq_index);
9025 
9026  if (iseqv != Qnil) {
9027  return (rb_iseq_t *)iseqv;
9028  }
9029  else {
9030  rb_iseq_t *iseq = iseq_imemo_alloc();
9031  FL_SET(iseq, ISEQ_NOT_LOADED_YET);
9032  iseq->aux.loader.obj = load->loader_obj;
9033  iseq->aux.loader.index = iseq_index;
9034  rb_ary_store(load->iseq_list, iseq_index, (VALUE)iseq);
9035 
9036 #if !USE_LAZY_LOAD
9037  ibf_load_iseq_complete(iseq);
9038 #endif /* !USE_LAZY_LOAD */
9039 
9040  if (load->iseq) {
9041  iseq_add_mark_object(load->iseq, (VALUE)iseq);
9042  }
9043  return iseq;
9044  }
9045  }
9046 }
9047 
9048 static void
9049 ibf_load_setup(struct ibf_load *load, VALUE loader_obj, VALUE str)
9050 {
9051  rb_check_safe_obj(str);
9052 
9053  if (RSTRING_LENINT(str) < (int)sizeof(struct ibf_header)) {
9054  rb_raise(rb_eRuntimeError, "broken binary format");
9055  }
9056  RB_OBJ_WRITE(loader_obj, &load->str, str);
9057  load->loader_obj = loader_obj;
9058  load->buff = StringValuePtr(str);
9059  load->header = (struct ibf_header *)load->buff;
9060  RB_OBJ_WRITE(loader_obj, &load->iseq_list, rb_ary_tmp_new(0));
9061  RB_OBJ_WRITE(loader_obj, &load->obj_list, rb_ary_tmp_new(0));
9062  load->id_list = ZALLOC_N(ID, load->header->id_list_size);
9063  load->iseq = NULL;
9064 
9065  if (RSTRING_LENINT(str) < (int)load->header->size) {
9066  rb_raise(rb_eRuntimeError, "broken binary format");
9067  }
9068  if (strncmp(load->header->magic, "YARB", 4) != 0) {
9069  rb_raise(rb_eRuntimeError, "unknown binary format");
9070  }
9071  if (load->header->major_version != ISEQ_MAJOR_VERSION ||
9073  rb_raise(rb_eRuntimeError, "unmatched version file (%u.%u for %u.%u)",
9075  }
9076  if (strcmp(load->buff + sizeof(struct ibf_header), RUBY_PLATFORM) != 0) {
9077  rb_raise(rb_eRuntimeError, "unmatched platform");
9078  }
9079 }
9080 
9081 static void
9082 ibf_loader_mark(void *ptr)
9083 {
9084  struct ibf_load *load = (struct ibf_load *)ptr;
9085  rb_gc_mark(load->str);
9086  rb_gc_mark(load->iseq_list);
9087  rb_gc_mark(load->obj_list);
9088 }
9089 
9090 static void
9091 ibf_loader_free(void *ptr)
9092 {
9093  struct ibf_load *load = (struct ibf_load *)ptr;
9094  ruby_xfree(load->id_list);
9095  ruby_xfree(load);
9096 }
9097 
9098 static size_t
9099 ibf_loader_memsize(const void *ptr)
9100 {
9101  struct ibf_load *load = (struct ibf_load *)ptr;
9102  return sizeof(struct ibf_load) + load->header->id_list_size * sizeof(ID);
9103 }
9104 
9105 static const rb_data_type_t ibf_load_type = {
9106  "ibf_loader",
9107  {ibf_loader_mark, ibf_loader_free, ibf_loader_memsize,},
9109 };
9110 
9111 const rb_iseq_t *
9113 {
9114  struct ibf_load *load;
9115  const rb_iseq_t *iseq;
9116  VALUE loader_obj = TypedData_Make_Struct(0, struct ibf_load, &ibf_load_type, load);
9117 
9118  ibf_load_setup(load, loader_obj, str);
9119  iseq = ibf_load_iseq(load, 0);
9120 
9121  RB_GC_GUARD(loader_obj);
9122  return iseq;
9123 }
9124 
9125 VALUE
9127 {
9128  struct ibf_load *load;
9129  VALUE loader_obj = TypedData_Make_Struct(0, struct ibf_load, &ibf_load_type, load);
9130  VALUE extra_str;
9131 
9132  ibf_load_setup(load, loader_obj, str);
9133  extra_str = rb_str_new(load->buff + load->header->size, load->header->extra_size);
9134  RB_GC_GUARD(loader_obj);
9135  return extra_str;
9136 }
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:1469
LINK_ELEMENT link
Definition: compile.c:61
#define RUBY_EVENT_B_RETURN
Definition: ruby.h:2092
unsigned int stack_max
Definition: vm_core.h:415
#define VM_CALL_ARGS_BLOCKARG
Definition: vm_core.h:963
#define T_SYMBOL
Definition: ruby.h:508
VALUE rb_hash(VALUE obj)
Definition: hash.c:121
Definition: node.h:91
union iseq_inline_storage_entry * is_entries
Definition: vm_core.h:400
Definition: node.h:31
rb_control_frame_t * rb_vm_get_ruby_level_next_cfp(const rb_thread_t *th, const rb_control_frame_t *cfp)
Definition: vm.c:498
Definition: id.h:84
VALUE iseq_ibf_load_extra_data(VALUE str)
Definition: compile.c:9126
int rb_enc_get_index(VALUE obj)
Definition: encoding.c:773
const rb_iseq_t * iseq
Definition: iseq.h:170
Definition: id.h:90
#define EXPECT_NODE(prefix, node, ndtype, errval)
Definition: compile.c:412
VALUE iseq_list
Definition: compile.c:7658
void rb_bug(const char *fmt,...)
Definition: error.c:521
unsigned int id_list_size
Definition: compile.c:7639
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1215
#define RARRAY_LEN(a)
Definition: ruby.h:1019
VALUE rb_ary_new_capa(long capa)
Definition: array.c:493
int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
Definition: id_table.c:226
void ibf_load_iseq_complete(rb_iseq_t *iseq)
Definition: compile.c:8995
#define FALSE
Definition: nkf.h:174
#define OPERAND_AT(insn, idx)
Definition: compile.c:356
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, VALUE exception, VALUE body)
Definition: compile.c:7385
#define ADD_INSN2(seq, line, insn, op1, op2)
Definition: compile.c:213
unsigned int major_version
Definition: compile.c:7633
#define va_init_list(a, b)
Definition: win32ole.h:34
Definition: id.h:86
size_t strlen(const char *)
#define INT_PARAM(F)
VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline)
Definition: re.c:2919
#define VM_CALL_FCALL
Definition: vm_core.h:964
iterator function
Definition: internal.h:843
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:38
#define RUBY_EVENT_RETURN
Definition: ruby.h:2084
Definition: st.h:79
void rb_iseq_make_compile_option(rb_compile_option_t *option, VALUE opt)
Definition: iseq.c:401
#define BIGNUM_DIGITS(b)
Definition: internal.h:616
Definition: node.h:49
#define INSERT_BEFORE_INSN(prev, line, insn)
Definition: compile.c:195
VALUE rb_range_new(VALUE, VALUE, int)
Definition: range.c:54
#define NUM2INT(x)
Definition: ruby.h:684
ibf_offset_t id_list_offset
Definition: compile.c:7643
#define NUM2UINT(x)
Definition: ruby.h:685
rb_iseq_t * iseq
Definition: compile.c:7674
rb_control_frame_t * cfp
Definition: vm_core.h:744
#define ADD_SEND_WITH_FLAG(seq, line, id, argc, flag)
Definition: compile.c:225
#define CPDEBUG
debug function(macro) interface depend on CPDEBUG if it is less than 0, runtime option is in effect...
Definition: compile.c:113
unsigned int is_size
Definition: vm_core.h:411
struct ensure_range * next
Definition: compile.c:90
#define DECL_BRANCH_BASE(branches, line, type)
Definition: compile.c:254
Definition: id.h:85
#define COMPILE_NG
Definition: compile.c:440
#define CLASS_OF(v)
Definition: ruby.h:453
VALUE rb_fstring_cstr(const char *str)
Definition: string.c:388
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2746
#define ADD_SEND_WITH_BLOCK(seq, line, id, argc, block)
Definition: compile.c:228
#define IS_ADJUST(link)
Definition: compile.c:364
#define st_foreach
Definition: regint.h:186
#define IBF_R(val, type, n)
Definition: compile.c:7713
#define nd_line(n)
Definition: node.h:278
Definition: id.h:97
Definition: id.h:88
#define Qtrue
Definition: ruby.h:437
VALUE * operands
Definition: compile.c:78
struct ibf_dump * dump
Definition: compile.c:8289
#define NEW_LABEL(l)
Definition: compile.c:177
Definition: id.h:101
#define ISEQ_MAJOR_VERSION
Definition: iseq.h:15
#define BIGNUM_LEN(b)
Definition: internal.h:610
VALUE(* ibf_load_object_function)(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t)
Definition: compile.c:8793
#define rb_id2str(id)
Definition: vm_backtrace.c:29
Definition: id.h:91
Definition: st.h:99
Definition: id.h:96
#define OBJ_FREEZE(x)
Definition: ruby.h:1306
#define SP_INSN(opt)
VALUE rb_insns_name_array(void)
Definition: compile.c:6976
const int id
Definition: nkf.c:209
unsigned int end
Definition: iseq.h:173
Definition: compile.c:7647
#define ZALLOC_N(type, n)
Definition: ruby.h:1589
struct rb_iseq_struct::@137::@138 loader
struct rb_iseq_constant_body::@135::@136 flags
node_type
Definition: node.h:22
st_table * id_table
Definition: compile.c:7661
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:246
int rb_is_const_id(ID id)
Definition: symbol.c:820
#define ADD_INSN(seq, line, insn)
Definition: compile.c:191
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:117
#define IBF_OBJHEADER(offset)
Definition: compile.c:8395
#define RUBY_EVENT_CALL
Definition: ruby.h:2083
int rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
Definition: compile.c:719
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Definition: range.c:979
Definition: node.h:41
const ID * local_table
Definition: vm_core.h:391
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:924
if(len<=MAX_WORD_LENGTH &&len >=MIN_WORD_LENGTH)
Definition: zonetab.h:883
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:2999
#define debugi(header, id)
Definition: compile.c:156
#define SYM2ID(x)
Definition: ruby.h:384
struct st_table * rb_hash_tbl_raw(VALUE hash)
Definition: hash.c:482
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:544
VALUE rb_iseq_defined_string(enum defined_type type)
Definition: iseq.c:2211
#define ADD_GETLOCAL(seq, line, idx, level)
Definition: compile.c:301
struct rb_iseq_constant_body * body
Definition: vm_core.h:423
int rb_local_defined(ID id, const struct rb_block *base_block)
Definition: compile.c:7517
struct rb_call_info_kw_arg * kw_arg
Definition: vm_core.h:230
int rb_reg_options(VALUE)
Definition: re.c:3543
LABEL * label
Definition: compile.c:83
ID id
Definition: node.h:238
#define LVAR_ERRINFO
Definition: compile.c:174
#define NEW_NIL()
Definition: node.h:443
unsigned int flag
Definition: vm_core.h:219
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3501
struct iseq_compile_data_storage * next
Definition: iseq.h:197
#define RB_GC_GUARD(v)
Definition: ruby.h:552
int pre_args_num
Definition: node.h:486
Definition: id.h:83
const void ** rb_vm_get_insns_address_table(void)
Definition: vm_exec.c:130
#define VM_CALL_ARGS_SPLAT
Definition: vm_core.h:962
#define ADD_ADJUST(seq, line, label)
Definition: compile.c:318
st_index_t rb_str_hash(VALUE)
Definition: string.c:3094
BDIGIT digits[1]
Definition: compile.c:8380
#define DATA_PTR(dta)
Definition: ruby.h:1106
#define VM_DEFINECLASS_FLAG_SCOPED
Definition: vm_core.h:875
#define cond(node, column)
Definition: ripper.c:653
#define TAG_NEXT
Definition: vm_core.h:167
void rb_gc_mark(VALUE ptr)
Definition: gc.c:4464
void(* ibf_dump_object_function)(struct ibf_dump *dump, VALUE obj)
Definition: compile.c:8726
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:853
#define FL_UNSET(x, f)
Definition: ruby.h:1290
#define T_ARRAY
Definition: ruby.h:498
st_data_t st_index_t
Definition: st.h:50
#define st_lookup
Definition: regint.h:185
#define VM_CALL_KWARG
Definition: vm_core.h:968
ID id
Definition: internal.h:1019
Definition: id.h:92
Definition: id.h:80
VALUE loader_obj
Definition: compile.c:7672
#define RCOMPLEX(obj)
Definition: internal.h:647
NODE * pre_init
Definition: node.h:483
unsigned int last
Definition: nkf.c:4311
ID block_arg
Definition: node.h:492
void rb_p(VALUE)
Definition: io.c:7448
#define ADD_TRACE_LINE_COVERAGE(seq, line)
Definition: compile.c:243
void rb_obj_info_dump(VALUE obj)
Definition: gc.c:9453
struct RNode * node
Definition: node.h:237
#define FIXNUM_P(f)
Definition: ruby.h:365
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:656
VALUE rb_hash_new_with_size(st_index_t size)
Definition: hash.c:430
#define debug_node_start(node)
Definition: compile.c:161
#define COMPILE_POPPED(anchor, desc, node)
Definition: compile.c:342
#define FL_TEST(x, f)
Definition: ruby.h:1282
#define nd_type(n)
Definition: node.h:272
VALUE rb_str_tmp_new(long)
Definition: string.c:1310
Definition: id.h:102
VALUE rb_ary_cat(VALUE ary, const VALUE *argv, long len)
Definition: array.c:936
unsigned int cont
Definition: iseq.h:174
#define IBF_OFFSET(ptr)
Definition: compile.c:7629
struct iseq_label_data LABEL
#define IS_NEXT_INSN_ID(link, insn)
Definition: compile.c:366
#define IBF_WP(b, type, n)
Definition: compile.c:7712
#define VM_CALL_VCALL
Definition: vm_core.h:965
#define LABEL_FORMAT
Definition: compile.c:178
struct iseq_link_element LINK_ELEMENT
#define NORETURN(x)
Definition: defines.h:34
int sc_state
Definition: compile.c:77
VALUE iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt)
Definition: compile.c:8936
Definition: node.h:27
#define GET_THREAD()
Definition: vm_core.h:1583
#define sym(x)
Definition: date_core.c:3721
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:22
Definition: node.h:233
enum iseq_catch_table_entry::catch_type type
#define RUBY_EVENT_CLASS
Definition: ruby.h:2081
#define Data_Wrap_Struct(klass, mark, free, sval)
Definition: ruby.h:1142
const VALUE * iseq_encoded
Definition: vm_core.h:314
rb_iseq_t * iseq_alloc(void)
VALUE rb_cISeq
Definition: iseq.c:29
void rb_hash_foreach(VALUE hash, int(*func)(ANYARGS), VALUE farg)
Definition: hash.c:385
#define ISEQ_MINOR_VERSION
Definition: iseq.h:16
VALUE rb_iseqw_new(const rb_iseq_t *)
Definition: iseq.c:782
int orig_argc
Definition: vm_core.h:220
VALUE str
Definition: compile.c:7657
#define ISEQ_NOT_LOADED_YET
Definition: iseq.h:88
#define RHASH(obj)
Definition: internal.h:663
LABEL * begin
Definition: compile.c:88
unsigned int iseq_size
Definition: vm_core.h:313
#define ADD_SEQ(seq1, seq2)
Definition: compile.c:187
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
VALUE rb_obj_is_kind_of(VALUE, VALUE)
call-seq: obj.is_a?(class) -> true or false obj.kind_of?(class) -> true or false
Definition: object.c:842
#define COMPILE_RECV(anchor, desc, node)
Definition: compile.c:351
VALUE rb_hash_rehash(VALUE hash)
Definition: hash.c:779
#define UNLIKELY(x)
Definition: internal.h:43
#define le(x, y)
Definition: time.c:75
#define RUBY_TYPED_WB_PROTECTED
Definition: ruby.h:1139
long keyval[1]
Definition: compile.c:8367
const rb_iseq_t * iseq
Definition: vm_core.h:665
#define FIXNUM_INC(n, i)
Definition: compile.c:34
unsigned int special_const
Definition: compile.c:8338
#define div(x, y)
Definition: date_strftime.c:27
int rb_data_is_encoding(VALUE obj)
Definition: encoding.c:90
#define ADD_SETLOCAL(seq, line, idx, level)
Definition: compile.c:306
#define rb_intern_str(string)
Definition: generator.h:16
Definition: compile.c:7650
VALUE rb_dbl2big(double d)
Definition: bignum.c:5214
#define ADD_TRACE(seq, line, event)
Definition: compile.c:294
const char * rb_insns_name(int i)
Definition: compile.c:6970
#define ALLOC_N(type, n)
Definition: ruby.h:1587
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1616
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2979
ibf_offset_t object_list_offset
Definition: compile.c:7644
unsigned int local_table_size
Definition: vm_core.h:410
#define level
#define ISEQ_TYPE_ONCE_GUARD
Definition: compile.c:32
ibf_object_class_index
Definition: compile.c:8343
Definition: internal.h:1017
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
#define ne(x, y)
Definition: time.c:72
size_t st_memsize(const st_table *tab)
Definition: st.c:676
#define PRIdVALUE
Definition: ruby.h:130
struct rb_call_info * ci_entries
Definition: vm_core.h:401
#define INSERT_BEFORE_INSN1(prev, line, insn, op1)
Definition: compile.c:204
VALUE rb_str_cat2(VALUE, const char *)
struct iseq_link_anchor LINK_ANCHOR
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
Definition: eval.c:1792
#define FL_SET(x, f)
Definition: ruby.h:1288
VALUE rb_ary_new(void)
Definition: array.c:499
#define UINT2NUM(x)
Definition: ruby.h:1539
#define SIZEOF_ISEQ_COMPILE_DATA_STORAGE
Definition: iseq.h:204
VALUE keywords[1]
Definition: vm_core.h:225
Definition: ruby.h:854
RUBY_EXTERN VALUE rb_cRange
Definition: ruby.h:1922
#define ERROR_ARGS
Definition: compile.c:410
VALUE rb_eIndexError
Definition: error.c:803
#define VM_DEFINECLASS_FLAG_HAS_SUPERCLASS
Definition: vm_core.h:876
VALUE obj_list
Definition: compile.c:7671
#define ADD_SEND(seq, line, id, argc)
Definition: compile.c:222
const rb_iseq_t * rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func)
Definition: compile.c:7621
#define ADD_INSNL(seq, line, insn, label)
Definition: compile.c:211
#define NIL_P(v)
Definition: ruby.h:451
void rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath)
Definition: iseq.c:236
NODE * opt_args
Definition: node.h:497
#define CHECK_ARRAY(v)
Definition: compile.c:7300
#define VM_CALL_ARGS_SIMPLE
Definition: vm_core.h:966
#define debug_list(anc)
Definition: compile.c:1049
struct rb_id_table * rb_id_table_create(size_t capa)
Definition: id_table.c:95
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:815
register int hval
Definition: zonetab.h:82
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:525
Definition: vm_core.h:197
#define ADD_CALL(seq, line, id, argc)
Definition: compile.c:234
ibf_object_data_type
Definition: compile.c:8383
#define T_FLOAT
Definition: ruby.h:495
#define INIT_ANCHOR(name)
Definition: compile.c:449
#define TYPE(x)
Definition: ruby.h:521
int argc
Definition: ruby.c:187
Definition: node.h:61
VALUE * rb_iseq_original_iseq(const rb_iseq_t *iseq)
Definition: compile.c:753
VALUE rb_eSyntaxError
Definition: error.c:816
#define Qfalse
Definition: ruby.h:436
#define COMPILE_(anchor, desc, node, popped)
Definition: compile.c:347
const char * rb_builtin_type_name(int t)
Definition: error.c:648
VALUE rb_rational_new(VALUE, VALUE)
Definition: rational.c:1973
#define ALLOCA_N(type, n)
Definition: ruby.h:1593
#define range(low, item, hi)
Definition: date_strftime.c:21
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1661
#define COMPILE(anchor, desc, node)
Definition: compile.c:337
VALUE rb_enc_associate_index(VALUE obj, int idx)
Definition: encoding.c:826
struct ensure_range * erange
Definition: compile.c:96
#define rb_str_new2
Definition: intern.h:835
int err
Definition: win32.c:135
#define ADD_SEND_R(seq, line, id, argc, block, flag, keywords)
Definition: compile.c:240
#define ISEQ_COVERAGE_SET(iseq, cov)
Definition: iseq.h:49
#define T_COMPLEX
Definition: ruby.h:510
int link(const char *, const char *)
Definition: win32.c:4925
struct iseq_compile_data_ensure_node_stack * prev
Definition: compile.c:95
#define numberof(array)
Definition: etc.c:618
unsigned long rb_num_t
Definition: vm_core.h:149
VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
Definition: bignum.c:3615
#define IS_TRACE_LINE(insn)
#define LABEL_UNREMOVABLE(label)
Definition: compile.c:324
#define VM_CALL_SUPER
Definition: vm_core.h:971
Definition: vm_core.h:188
int rb_str_hash_cmp(VALUE, VALUE)
Definition: string.c:3104
#define ZALLOC(type)
Definition: ruby.h:1590
#define TAG_REDO
Definition: vm_core.h:169
LABEL * end
Definition: compile.c:89
struct rb_call_cache * cc_entries
Definition: vm_core.h:406
#define RSTRING_LEN(str)
Definition: ruby.h:971
#define ADD_LABEL(seq, label)
Definition: compile.c:312
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:1021
ID rest_arg
Definition: node.h:491
int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val)
Definition: id_table.c:256
#define REALLOC_N(var, type, n)
Definition: ruby.h:1591
unsigned int size
Definition: iseq.h:199
LINK_ELEMENT link
Definition: compile.c:73
#define TRUE
Definition: nkf.h:175
struct rb_iseq_constant_body::@135 param
parameter information
VALUE rb_obj_freeze(VALUE)
call-seq: obj.freeze -> obj
Definition: object.c:1331
int rb_dvar_defined(ID id, const struct rb_block *base_block)
Definition: compile.c:7492
defined_type
Definition: iseq.h:240
unsigned int coverage_enabled
Definition: iseq.h:139
rb_insn_func_t func
Definition: compile.c:7556
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1452
int operand_size
Definition: compile.c:76
struct iseq_insn_data INSN
#define IS_INSN_ID(iobj, insn)
Definition: compile.c:365
#define rb_enc_name(enc)
Definition: encoding.h:171
#define SYM(s)
const char * buff
Definition: compile.c:7667
const VALUE klass
Definition: ruby.h:856
#define private_recv_p(node)
Definition: compile.c:3771
const rb_iseq_t * rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func)
Definition: compile.c:7612
#define RHASH_SIZE(hsh)
Definition: fbuffer.h:8
VALUE rb_hash_new(void)
Definition: hash.c:424
void ruby_xfree(void *x)
Definition: gc.c:8085
void rb_compile_warning(const char *file, int line, const char *fmt,...)
Definition: error.c:215
unsigned int line_no
Definition: compile.c:75
ID * id_list
Definition: compile.c:7669
#define VM_ENV_DATA_SIZE
Definition: vm_core.h:1047
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1315
unsigned int set
Definition: compile.c:67
#define RUBY_EVENT_LINE
Definition: ruby.h:2080
#define PRIsVALUE
Definition: ruby.h:135
unsigned long ID
Definition: ruby.h:86
#define DECL_ANCHOR(name)
Definition: compile.c:447
#define Qnil
Definition: ruby.h:438
st_table * iseq_table
Definition: compile.c:7660
VALUE rb_eStandardError
Definition: error.c:799
#define NODE_FL_NEWLINE
Definition: node.h:267
compile_array_type_t
Definition: compile.c:3235
#define ISEQ_COVERAGE(iseq)
Definition: iseq.h:48
IFUNC (Internal FUNCtion)
Definition: internal.h:917
#define LABEL_REF(label)
Definition: compile.c:208
#define BUILTIN_TYPE(x)
Definition: ruby.h:518
unsigned long VALUE
Definition: ruby.h:85
VALUE iseq_list
Definition: compile.c:7670
NODE * post_init
Definition: node.h:484
Definition: iseq.h:148
void rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args)
Definition: error.c:597
Definition: id.h:87
int intptr_t
Definition: win32.h:90
VALUE rb_iseq_compile_node(rb_iseq_t *iseq, NODE *node)
Definition: compile.c:611
VALUE rb_eTypeError
Definition: error.c:801
#define FIX2INT(x)
Definition: ruby.h:686
Definition: id.h:93
#define COVERAGE_INDEX_LINES
Definition: internal.h:1694
#define ADD_CALL_RECEIVER(seq, line)
Definition: compile.c:231
unsigned int ci_kw_size
Definition: vm_core.h:413
unsigned int ci_size
Definition: vm_core.h:412
int post_args_num
Definition: node.h:487
#define VM_CHECKMATCH_ARRAY
Definition: vm_core.h:945
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt)
Definition: iseq.c:626
VALUE rb_syntax_error_append(VALUE exc, VALUE file, int line, int column, rb_encoding *enc, const char *fmt, va_list args)
Definition: error.c:111
const char * rb_id2name(ID)
Definition: symbol.c:751
#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc)
Definition: compile.c:326
VALUE rb_str_new_cstr(const char *)
Definition: string.c:771
#define INTEGER_PACK_LITTLE_ENDIAN
Definition: intern.h:149
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition: object.c:72
Definition: id.h:98
#define RARRAY_LENINT(ary)
Definition: ruby.h:1020
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:1919
unsigned int unremovable
Definition: compile.c:69
VALUE flags
Definition: node.h:234
VALUE rb_fstring(VALUE)
Definition: string.c:306
VALUE rb_complex_new(VALUE x, VALUE y)
Definition: complex.c:1448
enum rb_iseq_constant_body::iseq_type type
VALUE rb_str_dup(VALUE)
Definition: string.c:1488
const struct rb_iseq_constant_body::@135::rb_iseq_param_keyword * keyword
#define FIXABLE(f)
Definition: ruby.h:368
#define ge(x, y)
Definition: time.c:76
#define LONG2NUM(x)
Definition: ruby.h:1573
#define ADD_INSN3(seq, line, insn, op1, op2, op3)
Definition: compile.c:217
void rb_memerror(void)
Definition: gc.c:7700
register unsigned int len
Definition: zonetab.h:51
unsigned int rescued
Definition: compile.c:68
#define StringValueCStr(v)
Definition: ruby.h:571
unsigned int type
Definition: compile.c:8337
#define MEMORY(v)
unsigned int internal
Definition: compile.c:8340
void * ruby_xmalloc(size_t size)
Definition: gc.c:7997
#define COMPILE_OK
Definition: compile.c:439
LABEL_RESCUE_TYPE
Definition: compile.c:53
unsigned int pos
Definition: iseq.h:198
#define RSTRING_PTR(str)
Definition: ruby.h:975
VALUE rb_iseq_realpath(const rb_iseq_t *iseq)
Definition: iseq.c:698
LINK_ELEMENT link
Definition: compile.c:82
const rb_iseq_t * rb_iseqw_to_iseq(VALUE iseqw)
Definition: iseq.c:958
unsigned int minor_version
Definition: compile.c:7634
#define ADD_TRACE_METHOD_COVERAGE(seq, line, method_name)
Definition: compile.c:280
#define INTEGER_PACK_NEGATIVE
Definition: intern.h:147
#define RB_OBJ_WRITE(a, slot, b)
Definition: eval_intern.h:175
#define RARRAY_ASET(a, i, v)
Definition: ruby.h:1034
#define RUBY_PLATFORM
Definition: defines.h:325
VALUE rb_iseq_disasm(const rb_iseq_t *iseq)
Definition: iseq.c:1515
#define ISEQ_LINE_COVERAGE(iseq)
Definition: iseq.h:50
#define BIGNUM_SIGN(b)
Definition: internal.h:599
#define rb_intern(str)
#define RFLOAT_VALUE(v)
Definition: ruby.h:933
int size
Definition: encoding.c:57
#define TAG_RETRY
Definition: vm_core.h:168
#define IBF_OBJBODY(type, offset)
Definition: compile.c:8396
#define INT2FIX(i)
Definition: ruby.h:232
unsigned int start
Definition: iseq.h:172
#define debugp_param(header, value)
Definition: compile.c:160
const struct iseq_catch_table * catch_table
Definition: vm_core.h:394
unsigned int position
Definition: iseq.h:144
#define RARRAY_AREF(a, i)
Definition: ruby.h:1033
unsigned int iseq_list_size
Definition: compile.c:7638
#define INSN_OF(insn)
Definition: compile.c:359
#define IS_INSN(link)
Definition: compile.c:362
Definition: node.h:47
#define xmalloc
Definition: defines.h:183
#define UNKNOWN_NODE(prefix, node, errval)
Definition: compile.c:431
#define st_init_numtable
Definition: regint.h:178
#define RBASIC_CLASS(obj)
Definition: ruby.h:878
struct rb_call_info ci
Definition: vm_core.h:229
VALUE rb_eRuntimeError
Definition: error.c:800
#define IBF_WV(variable)
Definition: compile.c:7711
Definition: node.h:207
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:831
struct rb_iseq_struct * local_iseq
Definition: vm_core.h:398
Definition: compile.c:7649
unsigned int ibf_offset_t
Definition: compile.c:7628
const char * ruby_node_name(int node)
Definition: iseq.c:1767
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1492
#define IBF_W(b, type, n)
Definition: compile.c:7710
#define ISEQ_FLIP_CNT(iseq)
Definition: iseq.h:54
void rb_iseq_add_mark_object(const rb_iseq_t *iseq, VALUE obj)
Definition: iseq.c:280
rb_control_frame_t *FUNC_FASTCALL rb_insn_func_t(rb_thread_t *, rb_control_frame_t *)
Definition: vm_core.h:1002
#define gt(x, y)
Definition: time.c:74
#define LONG2FIX(i)
Definition: ruby.h:234
Definition: id.h:109
#define RTEST(v)
Definition: ruby.h:450
#define ERROR_ARGS_AT(n)
Definition: compile.c:409
Definition: node.h:141
#define T_STRING
Definition: ruby.h:496
void rb_check_safe_obj(VALUE)
Definition: safe.c:117
struct rb_encoding_entry * list
Definition: encoding.c:55
union RNode::@88 u1
#define ADD_ADJUST_RESTORE(seq, label)
Definition: compile.c:321
struct iseq_inline_cache_entry * IC
Definition: vm_core.h:989
#define BADINSN_DUMP(anchor, list, dest)
Definition: compile.c:1614
Definition: id.h:95
#define RUBY_EVENT_END
Definition: ruby.h:2082
#define NEW_ISEQ(node, name, type, line_no)
Definition: compile.c:180
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1175
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1930
#define CHECK(sub)
Definition: compile.c:442
VALUE rb_iseq_path(const rb_iseq_t *iseq)
Definition: iseq.c:692
#define assert
Definition: ruby_assert.h:37
const struct st_hash_type * type
Definition: st.h:84
#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block)
Definition: compile.c:237
VALUE(* func)(ANYARGS)
Definition: internal.h:920
VALUE rb_cArray
Definition: array.c:26
#define VM_CALL_TAILCALL
Definition: vm_core.h:970
union RNode::@89 u2
#define ISEQ_ARG_DECLARE
Definition: compile.c:471
#define st_insert
Definition: regint.h:184
const void * data
Definition: internal.h:921
#define compile_debug
Definition: compile.c:117
const struct rb_iseq_struct * parent_iseq
Definition: vm_core.h:397
#define NEW_CHILD_ISEQ(node, name, type, line_no)
Definition: compile.c:183
#define PADDING_SIZE_MAX
Definition: compile.c:801
#define TAG_RETURN
Definition: vm_core.h:165
rb_execution_context_t ec
Definition: vm_core.h:790
#define VM_CALL_KW_SPLAT
Definition: vm_core.h:969
const struct iseq_line_info_entry * line_info_table
Definition: vm_core.h:389
#define ruby_debug
Definition: ruby.h:1814
#define RUBY_EVENT_COVERAGE
Definition: ruby.h:2100
const char * name
Definition: nkf.c:208
long rb_str_strlen(VALUE)
Definition: string.c:1789
const VALUE * opt_table
Definition: vm_core.h:361
#define ID2SYM(x)
Definition: ruby.h:383
Definition: node.h:63
int rb_eql(VALUE, VALUE)
Determines if obj1 and obj2 are equal in terms of Object::eql?.
Definition: object.c:149
int rb_is_attrset_id(ID id)
Definition: symbol.c:844
#define StringValuePtr(v)
Definition: ruby.h:570
VALUE() rb_ary_new_from_args(long n,...)
Definition: array.c:505
unsigned int line_info_size
Definition: vm_core.h:414
#define FL_FREEZE
Definition: ruby.h:1216
rb_iseq_t * rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, enum iseq_type type, const rb_compile_option_t *option)
Definition: iseq.c:495
void rb_exc_fatal(VALUE mesg)
Raises a fatal error in the current thread.
Definition: eval.c:631
#define CHECK_SYMBOL(v)
Definition: compile.c:7301
#define st_free_table
Definition: regint.h:188
Definition: id.h:99
#define lt(x, y)
Definition: time.c:73
#define RTYPEDDATA_DATA(v)
Definition: ruby.h:1110
#define FIX2UINT(x)
Definition: ruby.h:687
#define debug_node_end()
Definition: compile.c:162
int rb_enc_find_index(const char *name)
Definition: encoding.c:704
#define RSTRING_LENINT(str)
Definition: ruby.h:983
Definition: node.h:33
#define CONST_ID(var, str)
Definition: ruby.h:1743
VALUE str
Definition: compile.c:7673
#define TAG_BREAK
Definition: vm_core.h:166
char magic[4]
Definition: compile.c:7632
ID rb_id_attrset(ID)
Definition: symbol.c:100
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1242
unsigned int object_list_size
Definition: compile.c:7640
#define ISEQ_COMPILE_DATA(iseq)
Definition: iseq.h:80
void void xfree(void *)
Definition: node.h:43
ID first_post_arg
Definition: node.h:489
Definition: iseq.h:143
ibf_offset_t iseq_list_offset
Definition: compile.c:7642
#define IS_LABEL(link)
Definition: compile.c:363
#define ADD_TRACE_BRANCH_COVERAGE(seq, line, type, branches)
Definition: compile.c:266
Definition: id.h:94
union rb_iseq_struct::@137 aux
unsigned int size
Definition: vm_core.h:352
#define SYMBOL_P(x)
Definition: ruby.h:382
#define mod(x, y)
Definition: date_strftime.c:28
NODE * kw_args
Definition: node.h:494
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
#define NULL
Definition: _sdbm.c:102
struct rb_global_entry * rb_global_entry(ID)
Definition: variable.c:482
unsigned int line_no
Definition: iseq.h:145
#define RREGEXP_SRC(r)
Definition: ruby.h:1050
VALUE obj_list
Definition: compile.c:7659
#define FIX2LONG(x)
Definition: ruby.h:363
#define Qundef
Definition: ruby.h:439
unsigned int sp
Definition: iseq.h:175
#define APPEND_LABEL(seq, before, label)
Definition: compile.c:315
unsigned int size
Definition: compile.c:7635
const rb_iseq_t * iseq_ibf_load(VALUE str)
Definition: compile.c:9112
NODE * kw_rest_arg
Definition: node.h:495
st_index_t num_entries
Definition: st.h:86
struct iseq_adjust_data ADJUST
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2900
unsigned int frozen
Definition: compile.c:8339
#define debugs
Definition: compile.c:170
#define EXPECT_NODE_NONULL(prefix, parent, ndtype, errval)
Definition: compile.c:424
#define BADINSN_ERROR
Definition: compile.c:1617
rb_encoding * rb_enc_find(const char *name)
Definition: encoding.c:728
const struct ibf_header * header
Definition: compile.c:7668
#define NUM2LONG(x)
Definition: ruby.h:648
Definition: node.h:139
#define BDIGIT
Definition: bigdecimal.h:48
#define RUBY_EVENT_B_CALL
Definition: ruby.h:2091
enum ruby_vminsn_type insn_id
Definition: compile.c:74
char ** argv
Definition: ruby.c:188
#define DBL2NUM(dbl)
Definition: ruby.h:934
rb_iseq_location_t location
Definition: vm_core.h:386
#define ADD_INSN1(seq, line, insn, op1)
Definition: compile.c:199
#define COMPILE_ERROR
Definition: compile.c:407
#define IFUNC_NEW(a, b, c)
Definition: internal.h:925
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:616
#define rb_sym2str(sym)
Definition: console.c:107
unsigned int extra_size
Definition: compile.c:7636
VALUE rb_str_new(const char *, long)
Definition: string.c:737