Ruby 2.0.0p353(2013-11-22revision43784)

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