Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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