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