1 /**********************************************************************
3 compile.c - ruby node tree -> VM instruction sequence
6 created at: 04/01/01 03:42:15 JST
8 Copyright (C) 2004-2007 Koichi Sasada
10 **********************************************************************/
12 #include "ruby/ruby.h"
13 #include "ruby/node.h"
15 #define USE_INSN_STACK_INCREASE 1
19 #include "insns_info.inc"
21 #ifdef HAVE_STDARG_PROTOTYPES
23 #define va_init_list(a,b) va_start(a,b)
26 #define va_init_list(a,b) va_start(a)
30 VALUE
iseq_load(VALUE self
, VALUE data
, VALUE parent
, VALUE opt
);
33 VALUE
vm_eval(void *);
37 typedef struct iseq_link_element
{
39 ISEQ_ELEMENT_NONE
= INT2FIX(0x00),
40 ISEQ_ELEMENT_LABEL
= INT2FIX(0x01),
41 ISEQ_ELEMENT_INSN
= INT2FIX(0x02),
42 ISEQ_ELEMENT_ADJUST
= INT2FIX(0x03),
44 struct iseq_link_element
*next
;
45 struct iseq_link_element
*prev
;
48 typedef struct iseq_link_anchor
{
53 typedef struct iseq_label_data
{
62 typedef struct iseq_insn_data
{
64 enum ruby_vminsn_type insn_id
;
71 typedef struct iseq_adjust_data
{
80 struct ensure_range
*next
;
83 struct iseq_compile_data_ensure_node_stack
{
85 struct iseq_compile_data_ensure_node_stack
*prev
;
86 struct ensure_range
*erange
;
89 #include "optinsn.inc"
90 #if OPT_INSTRUCTIONS_UNIFICATION
91 #include "optunifs.inc"
96 #define ISEQ_ARG iseq,
97 #define ISEQ_ARG_DECLARE rb_iseq_t *iseq,
100 #define ISEQ_ARG_DECLARE
104 #define gl_node_level iseq->compile_data->node_level
106 static void debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR
*anchor
);
110 static void dump_disasm_list(LINK_ELEMENT
*elem
);
112 static int insn_data_length(INSN
*iobj
);
113 static int insn_data_line_no(INSN
*iobj
);
114 static int calc_sp_depth(int depth
, INSN
*iobj
);
116 static void ADD_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR
*anchor
, LINK_ELEMENT
*elem
);
118 static INSN
*new_insn_body(rb_iseq_t
*iseq
, int line_no
, int insn_id
, int argc
, ...);
119 static LABEL
*new_label_body(rb_iseq_t
*iseq
, int line
);
120 static ADJUST
*new_adjust_body(rb_iseq_t
*iseq
, LABEL
*label
, int line
);
122 static int iseq_compile_each(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
, NODE
* n
, int);
123 static int iseq_setup(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
);
124 static int iseq_optimize(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
);
125 static int iseq_insns_unification(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
);
127 static int iseq_set_local_table(rb_iseq_t
*iseq
, ID
*tbl
);
128 static int iseq_set_exception_local_table(rb_iseq_t
*iseq
);
129 static int iseq_set_arguments(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
, NODE
* node
);
131 static int iseq_set_sequence_stackcaching(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
);
132 static int iseq_set_sequence(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
);
133 static int iseq_set_exception_table(rb_iseq_t
*iseq
);
134 static int iseq_set_optargs_table(rb_iseq_t
*iseq
);
137 * To make Array to LinkedList, use link_anchor
141 verify_list(ISEQ_ARG_DECLARE
char *info
, LINK_ANCHOR
*anchor
)
145 LINK_ELEMENT
*list
, *plist
;
147 if (!compile_debug
) return;
149 list
= anchor
->anchor
.next
;
150 plist
= &anchor
->anchor
;
152 if (plist
!= list
->prev
) {
159 if (anchor
->last
!= plist
&& anchor
->last
!= 0) {
164 rb_bug("list verify error: %08x (%s)", flag
, info
);
169 #define verify_list(info, anchor) verify_list(iseq, info, anchor)
173 * elem1, elem2 => elem1, elem2, elem
176 ADD_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR
*anchor
, LINK_ELEMENT
*elem
)
178 elem
->prev
= anchor
->last
;
179 anchor
->last
->next
= elem
;
181 verify_list("add", anchor
);
184 #define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, anchor, elem)
188 iseq_add_mark_object(rb_iseq_t
*iseq
, VALUE v
)
190 if (!SPECIAL_CONST_P(v
)) {
191 rb_ary_push(iseq
->mark_ary
, v
);
196 #define ruby_sourcefile RSTRING_PTR(iseq->filename)
199 iseq_add_mark_object_compile_time(rb_iseq_t
*iseq
, VALUE v
)
201 if (!SPECIAL_CONST_P(v
)) {
202 rb_ary_push(iseq
->compile_data
->mark_ary
, v
);
208 iseq_compile(VALUE self
, NODE
*node
)
213 GetISeqPtr(self
, iseq
);
216 COMPILE(ret
, "nil", node
);
217 iseq_set_local_table(iseq
, 0);
219 else if (nd_type(node
) == NODE_SCOPE
) {
220 /* iseq type of top, method, class, block */
221 iseq_set_local_table(iseq
, node
->nd_tbl
);
222 iseq_set_arguments(iseq
, ret
, node
->nd_args
);
224 switch (iseq
->type
) {
225 case ISEQ_TYPE_BLOCK
: {
226 LABEL
*start
= iseq
->compile_data
->start_label
= NEW_LABEL(0);
227 LABEL
*end
= iseq
->compile_data
->end_label
= NEW_LABEL(0);
229 ADD_LABEL(ret
, start
);
230 COMPILE(ret
, "block body", node
->nd_body
);
233 /* wide range catch handler must put at last */
234 ADD_CATCH_ENTRY(CATCH_TYPE_REDO
, start
, end
, 0, start
);
235 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT
, start
, end
, 0, end
);
238 case ISEQ_TYPE_CLASS
: {
239 ADD_TRACE(ret
, nd_line(node
), RUBY_EVENT_CLASS
);
240 COMPILE(ret
, "scoped node", node
->nd_body
);
241 ADD_TRACE(ret
, nd_line(node
), RUBY_EVENT_END
);
244 case ISEQ_TYPE_METHOD
: {
245 ADD_TRACE(ret
, nd_line(node
), RUBY_EVENT_CALL
);
246 COMPILE(ret
, "scoped node", node
->nd_body
);
247 ADD_TRACE(ret
, nd_line(node
), RUBY_EVENT_RETURN
);
251 COMPILE(ret
, "scoped node", node
->nd_body
);
257 switch (iseq
->type
) {
258 case ISEQ_TYPE_METHOD
:
259 case ISEQ_TYPE_CLASS
:
260 case ISEQ_TYPE_BLOCK
:
263 rb_compile_error(ERROR_ARGS
"compile/should not be reached: %s:%d",
266 case ISEQ_TYPE_RESCUE
:
267 iseq_set_exception_local_table(iseq
);
268 COMPILE(ret
, "rescue", node
);
270 case ISEQ_TYPE_ENSURE
:
271 iseq_set_exception_local_table(iseq
);
272 COMPILE_POPED(ret
, "ensure", node
);
274 case ISEQ_TYPE_DEFINED_GUARD
:
275 COMPILE(ret
, "defined guard", node
);
278 rb_bug("unknown scope");
282 if (iseq
->type
== ISEQ_TYPE_RESCUE
|| iseq
->type
== ISEQ_TYPE_ENSURE
) {
283 ADD_INSN2(ret
, 0, getdynamic
, INT2FIX(1), INT2FIX(0));
284 ADD_INSN1(ret
, 0, throw, INT2FIX(0) /* continue throw */ );
287 ADD_INSN(ret
, iseq
->compile_data
->last_line
, leave
);
290 return iseq_setup(iseq
, ret
);
294 iseq_translate_threaded_code(rb_iseq_t
*iseq
)
296 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
298 #if OPT_DIRECT_THREADED_CODE
299 const void *const *table
= (const void **)vm_eval(0);
301 extern const void *const *get_insns_address_table();
302 const void *const *table
= get_insns_address_table();
306 iseq
->iseq_encoded
= ALLOC_N(VALUE
, iseq
->iseq_size
);
307 MEMCPY(iseq
->iseq_encoded
, iseq
->iseq
, VALUE
, iseq
->iseq_size
);
309 for (i
= 0; i
< iseq
->iseq_size
; /* */ ) {
310 int insn
= iseq
->iseq_encoded
[i
];
311 int len
= insn_len(insn
);
312 iseq
->iseq_encoded
[i
] = (VALUE
)table
[insn
];
316 iseq
->iseq_encoded
= iseq
->iseq
;
321 /*********************************************/
322 /* definition of data structure for compiler */
323 /*********************************************/
326 compile_data_alloc(rb_iseq_t
*iseq
, size_t size
)
329 struct iseq_compile_data_storage
*storage
=
330 iseq
->compile_data
->storage_current
;
332 if (storage
->pos
+ size
> storage
->size
) {
333 unsigned long alloc_size
= storage
->size
* 2;
336 if (alloc_size
< size
) {
340 storage
->next
= (void *)ALLOC_N(char, alloc_size
+
342 iseq_compile_data_storage
));
343 storage
= iseq
->compile_data
->storage_current
= storage
->next
;
346 storage
->size
= alloc_size
;
347 storage
->buff
= (char *)(&storage
->buff
+ 1);
350 ptr
= (void *)&storage
->buff
[storage
->pos
];
351 storage
->pos
+= size
;
356 compile_data_alloc_insn(rb_iseq_t
*iseq
)
358 return (INSN
*)compile_data_alloc(iseq
, sizeof(INSN
));
362 compile_data_alloc_label(rb_iseq_t
*iseq
)
364 return (LABEL
*)compile_data_alloc(iseq
, sizeof(LABEL
));
368 compile_data_alloc_adjust(rb_iseq_t
*iseq
)
370 return (ADJUST
*)compile_data_alloc(iseq
, sizeof(ADJUST
));
374 * elem1, elemX => elem1, elem2, elemX
377 INSERT_ELEM_NEXT(LINK_ELEMENT
*elem1
, LINK_ELEMENT
*elem2
)
379 elem2
->next
= elem1
->next
;
383 elem2
->next
->prev
= elem2
;
389 * elemX, elem1 => elemX, elem2, elem1
392 INSERT_ELEM_PREV(LINK_ELEMENT
*elem1
, LINK_ELEMENT
*elem2
)
394 elem2
->prev
= elem1
->prev
;
398 elem2
->prev
->next
= elem2
;
404 * elemX, elem1, elemY => elemX, elem2, elemY
407 REPLACE_ELEM(LINK_ELEMENT
*elem1
, LINK_ELEMENT
*elem2
)
409 elem2
->prev
= elem1
->prev
;
410 elem2
->next
= elem1
->next
;
412 elem1
->prev
->next
= elem2
;
415 elem1
->next
->prev
= elem2
;
420 REMOVE_ELEM(LINK_ELEMENT
*elem
)
422 elem
->prev
->next
= elem
->next
;
424 elem
->next
->prev
= elem
->prev
;
428 static LINK_ELEMENT
*
429 FIRST_ELEMENT(LINK_ANCHOR
*anchor
)
431 return anchor
->anchor
.next
;
435 static LINK_ELEMENT
*
436 LAST_ELEMENT(LINK_ANCHOR
*anchor
)
442 static LINK_ELEMENT
*
443 POP_ELEMENT(ISEQ_ARG_DECLARE LINK_ANCHOR
*anchor
)
445 LINK_ELEMENT
*elem
= anchor
->last
;
446 anchor
->last
= anchor
->last
->prev
;
447 anchor
->last
->next
= 0;
448 verify_list("pop", anchor
);
452 #define POP_ELEMENT(anchor) POP_ELEMENT(iseq, anchor)
456 static LINK_ELEMENT
*
457 SHIFT_ELEMENT(LINK_ANCHOR
*anchor
)
459 LINK_ELEMENT
*elem
= anchor
->anchor
.next
;
461 anchor
->anchor
.next
= elem
->next
;
469 LIST_SIZE(LINK_ANCHOR
*anchor
)
471 LINK_ELEMENT
*elem
= anchor
->anchor
.next
;
482 LIST_SIZE_ZERO(LINK_ANCHOR
*anchor
)
484 if (anchor
->anchor
.next
== 0) {
496 * anc1: e1, e2, e3, e4, e5
497 * anc2: e4, e5 (broken)
500 APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR
*anc1
, LINK_ANCHOR
*anc2
)
502 if (anc2
->anchor
.next
) {
503 anc1
->last
->next
= anc2
->anchor
.next
;
504 anc2
->anchor
.next
->prev
= anc1
->last
;
505 anc1
->last
= anc2
->last
;
507 verify_list("append", anc1
);
510 #define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, anc1, anc2)
517 * anc1: e4, e5, e1, e2, e3
518 * anc2: e4, e5 (broken)
521 INSERT_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR
*anc1
, LINK_ANCHOR
*anc2
)
523 if (anc2
->anchor
.next
) {
524 LINK_ELEMENT
*first
= anc1
->anchor
.next
;
525 anc1
->anchor
.next
= anc2
->anchor
.next
;
526 anc1
->anchor
.next
->prev
= &anc1
->anchor
;
527 anc2
->last
->next
= first
;
529 first
->prev
= anc2
->last
;
532 anc1
->last
= anc2
->last
;
536 verify_list("append", anc1
);
539 #define INSERT_LIST(anc1, anc2) INSERT_LIST(iseq, anc1, anc2)
551 SWAP_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR
*anc1
, LINK_ANCHOR
*anc2
)
553 LINK_ANCHOR tmp
= *anc2
;
559 verify_list("swap1", anc1
);
560 verify_list("swap2", anc2
);
563 #define SWAP_LIST(anc1, anc2) SWAP_LIST(iseq, anc1, anc2)
567 REVERSE_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR
*anc
)
569 LINK_ELEMENT
*first
, *last
, *elem
, *e
;
570 first
= &anc
->anchor
;
575 anc
->anchor
.next
= last
;
584 elem
->next
= elem
->prev
;
593 verify_list("reverse", anc
);
597 #define REVERSE_LIST(anc) REVERSE_LIST(iseq, anc)
603 debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR
*anchor
)
605 LINK_ELEMENT
*list
= FIRST_ELEMENT(anchor
);
607 printf("anch: %p, frst: %p, last: %p\n", &anchor
->anchor
,
608 anchor
->anchor
.next
, anchor
->last
);
610 printf("curr: %p, next: %p, prev: %p, type: %d\n", list
, list
->next
,
611 list
->prev
, FIX2INT(list
->type
));
616 dump_disasm_list(anchor
->anchor
.next
);
617 verify_list("debug list", anchor
);
620 #define debug_list(anc) debug_list(iseq, anc)
625 new_label_body(rb_iseq_t
*iseq
, int line
)
627 LABEL
*labelobj
= compile_data_alloc_label(iseq
);
629 labelobj
->link
.type
= ISEQ_ELEMENT_LABEL
;
630 labelobj
->link
.next
= 0;
632 labelobj
->label_no
= iseq
->compile_data
->label_no
++;
633 labelobj
->sc_state
= 0;
639 new_adjust_body(rb_iseq_t
*iseq
, LABEL
*label
, int line
)
641 ADJUST
*adjust
= compile_data_alloc_adjust(iseq
);
642 adjust
->link
.type
= ISEQ_ELEMENT_ADJUST
;
643 adjust
->link
.next
= 0;
644 adjust
->label
= label
;
645 adjust
->line_no
= line
;
650 new_insn_core(rb_iseq_t
*iseq
, int line_no
,
651 int insn_id
, int argc
, VALUE
*argv
)
653 INSN
*iobj
= compile_data_alloc_insn(iseq
);
655 iobj
->link
.type
= ISEQ_ELEMENT_INSN
;
657 iobj
->insn_id
= insn_id
;
658 iobj
->line_no
= line_no
;
659 iobj
->operands
= argv
;
660 iobj
->operand_size
= argc
;
666 new_insn_body(rb_iseq_t
*iseq
, int line_no
, int insn_id
, int argc
, ...)
672 va_init_list(argv
, argc
);
673 operands
= (VALUE
*)compile_data_alloc(iseq
, sizeof(VALUE
) * argc
);
674 for (i
= 0; i
< argc
; i
++) {
675 VALUE v
= va_arg(argv
, VALUE
);
680 return new_insn_core(iseq
, line_no
, insn_id
, argc
, operands
);
684 new_insn_send(rb_iseq_t
*iseq
, int line_no
,
685 VALUE id
, VALUE argc
, VALUE block
, VALUE flag
)
689 (VALUE
*)compile_data_alloc(iseq
, sizeof(VALUE
) * 5);
695 iobj
= new_insn_core(iseq
, line_no
, BIN(send
), 5, operands
);
700 new_child_iseq(rb_iseq_t
*iseq
, NODE
*node
,
701 VALUE name
, VALUE parent
, VALUE type
)
705 debugs("[new_child_iseq]> ---------------------------------------\n");
706 ret
= rb_iseq_new_with_opt(node
, name
, iseq_filename(iseq
->self
),
707 parent
, type
, iseq
->compile_data
->option
);
708 debugs("[new_child_iseq]< ---------------------------------------\n");
709 iseq_add_mark_object(iseq
, ret
);
714 iseq_setup(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
)
716 /* debugs("[compile step 2] (iseq_array_to_linkedlist)\n"); */
718 if (compile_debug
> 5)
719 dump_disasm_list(FIRST_ELEMENT(anchor
));
721 debugs("[compile step 3.1 (iseq_optimize)]\n");
722 iseq_optimize(iseq
, anchor
);
724 if (compile_debug
> 5)
725 dump_disasm_list(FIRST_ELEMENT(anchor
));
727 if (iseq
->compile_data
->option
->instructions_unification
) {
728 debugs("[compile step 3.2 (iseq_insns_unification)]\n");
729 iseq_insns_unification(iseq
, anchor
);
730 if (compile_debug
> 5)
731 dump_disasm_list(FIRST_ELEMENT(anchor
));
734 if (iseq
->compile_data
->option
->stack_caching
) {
735 debugs("[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
736 iseq_set_sequence_stackcaching(iseq
, anchor
);
737 if (compile_debug
> 5)
738 dump_disasm_list(FIRST_ELEMENT(anchor
));
741 debugs("[compile step 4.1 (iseq_set_sequence)]\n");
742 iseq_set_sequence(iseq
, anchor
);
743 if (compile_debug
> 5)
744 dump_disasm_list(FIRST_ELEMENT(anchor
));
746 debugs("[compile step 4.2 (iseq_set_exception_table)]\n");
747 iseq_set_exception_table(iseq
);
749 debugs("[compile step 4.3 (set_optargs_table)] \n");
750 iseq_set_optargs_table(iseq
);
752 debugs("[compile step 5 (iseq_translate_threaded_code)] \n");
753 iseq_translate_threaded_code(iseq
);
755 if (compile_debug
> 1) {
756 VALUE str
= ruby_iseq_disasm(iseq
->self
);
757 printf("%s\n", StringValueCStr(str
));
760 debugs("[compile step: finish]\n");
766 iseq_set_exception_local_table(rb_iseq_t
*iseq
)
768 static ID id_dollar_bang
;
770 if (!id_dollar_bang
) {
771 id_dollar_bang
= rb_intern("#$!");
773 iseq
->local_table
= (ID
*)ALLOC_N(ID
*, 1);
774 iseq
->local_table_size
= iseq
->local_size
= 1;
775 iseq
->local_table
[0] = id_dollar_bang
;
780 get_dyna_var_idx_at_raw(rb_iseq_t
*iseq
, ID id
)
784 for (i
= 0; i
< iseq
->local_table_size
; i
++) {
785 if (iseq
->local_table
[i
] == id
) {
793 get_local_var_idx(rb_iseq_t
*iseq
, ID id
)
795 int idx
= get_dyna_var_idx_at_raw(iseq
->local_iseq
, id
);
798 rb_bug("get_local_var_idx: %d", idx
);
805 get_dyna_var_idx(rb_iseq_t
*iseq
, ID id
, int *level
, int *ls
)
807 int lv
= 0, idx
= -1;
810 idx
= get_dyna_var_idx_at_raw(iseq
, id
);
814 iseq
= iseq
->parent_iseq
;
819 rb_bug("get_dyna_var_idx: -1");
823 *ls
= iseq
->local_size
;
828 iseq_set_arguments(rb_iseq_t
*iseq
, LINK_ANCHOR
*optargs
, NODE
*node_args
)
830 debugs("iseq_set_arguments: %s\n", node_args
? "" : "0");
833 NODE
*node_aux
= node_args
->nd_next
;
834 NODE
*node_opt
= node_args
->nd_opt
;
840 if (nd_type(node_args
) != NODE_ARGS
) {
841 rb_bug("iseq_set_arguments: NODE_ARGS is expected, but %s",
842 ruby_node_name(nd_type(node_args
)));
846 * new argument infromation:
847 * NODE_ARGS [m: int, o: NODE_OPT_ARG, ->]
848 * NODE_ARGS_AUX [r: ID, b: ID, ->]
849 * NODE_ARGS_AUX [Pst: id, Plen: int, init: NODE*]
850 * optarg information:
851 * NODE_OPT_ARGS [idx, expr, next ->]
853 * NODE_AND(m_init, p_init)
854 * if "r" is 1, it's means "{|x,|}" type block parameter.
857 iseq
->argc
= node_args
->nd_frml
;
858 debugs(" - argc: %d\n", iseq
->argc
);
861 rest_id
= node_aux
->nd_rest
;
866 block_id
= (ID
)node_aux
->nd_body
;
867 node_aux
= node_aux
->nd_next
;
870 ID post_start_id
= node_aux
->nd_pid
;
871 iseq
->arg_post_start
= get_dyna_var_idx_at_raw(iseq
, post_start_id
);
872 iseq
->arg_post_len
= node_aux
->nd_plen
;
873 node_init
= node_aux
->nd_next
;
878 NODE
*node
= node_opt
;
880 VALUE labels
= rb_ary_new();
884 label
= NEW_LABEL(nd_line(node
));
885 rb_ary_push(labels
, (VALUE
)label
| 1);
886 ADD_LABEL(optargs
, label
);
887 COMPILE_POPED(optargs
, "optarg", node
->nd_body
);
888 node
= node
->nd_next
;
893 label
= NEW_LABEL(nd_line(node_args
));
894 rb_ary_push(labels
, (VALUE
)label
| 1);
895 ADD_LABEL(optargs
, label
);
899 iseq
->arg_opt_table
= ALLOC_N(VALUE
, i
);
900 MEMCPY(iseq
->arg_opt_table
, RARRAY_PTR(labels
), VALUE
, i
);
901 for (j
= 0; j
< i
; j
++) {
902 iseq
->arg_opt_table
[j
] &= ~1;
910 if (node_init
->nd_1st
) { /* m_init */
911 COMPILE_POPED(optargs
, "init arguments (m)", node_init
->nd_1st
);
913 if (node_init
->nd_2nd
) { /* p_init */
914 COMPILE_POPED(optargs
, "init arguments (p)", node_init
->nd_2nd
);
919 iseq
->arg_rest
= get_dyna_var_idx_at_raw(iseq
, rest_id
);
921 if (iseq
->arg_rest
== -1) {
922 rb_bug("arg_rest: -1");
925 if (iseq
->arg_post_start
== 0) {
926 iseq
->arg_post_start
= iseq
->arg_rest
+ 1;
931 iseq
->arg_block
= get_dyna_var_idx_at_raw(iseq
, block_id
);
934 if (iseq
->arg_opts
!= 0 || iseq
->arg_post_len
!= 0 ||
935 iseq
->arg_rest
!= -1 || iseq
->arg_block
!= -1) {
936 iseq
->arg_simple
= 0;
938 /* set arg_size: size of arguments */
939 if (iseq
->arg_block
!= -1) {
940 iseq
->arg_size
= iseq
->arg_block
+ 1;
942 else if (iseq
->arg_post_len
) {
943 iseq
->arg_size
= iseq
->arg_post_start
+ iseq
->arg_post_len
;
945 else if (iseq
->arg_rest
!= -1) {
946 iseq
->arg_size
= iseq
->arg_rest
+ 1;
948 else if (iseq
->arg_opts
) {
949 iseq
->arg_size
= iseq
->argc
+ iseq
->arg_opts
- 1;
952 iseq
->arg_size
= iseq
->argc
;
956 iseq
->arg_simple
= 1;
957 iseq
->arg_size
= iseq
->argc
;
960 if (iseq
->type
== ISEQ_TYPE_BLOCK
) {
961 if (iseq
->arg_opts
== 0 && iseq
->arg_post_len
== 0 && iseq
->arg_rest
== -1) {
962 if (iseq
->argc
== 1 && last_comma
== 0) {
964 iseq
->arg_simple
|= 0x02;
970 iseq
->arg_simple
= 1;
977 iseq_set_local_table(rb_iseq_t
*iseq
, ID
*tbl
)
990 iseq
->local_table
= (ID
*)ALLOC_N(ID
*, size
);
991 MEMCPY(iseq
->local_table
, tbl
, ID
*, size
);
994 iseq
->local_size
= iseq
->local_table_size
= size
;
996 if (iseq
->type
== ISEQ_TYPE_METHOD
||
997 iseq
->type
== ISEQ_TYPE_CLASS
||
998 iseq
->type
== ISEQ_TYPE_TOP
) {
999 iseq
->local_size
+= 1 /* svar */;
1002 debugs("iseq_set_local_table: %d, %d\n", iseq
->local_size
, iseq
->local_table_size
);
1007 ruby insn object array -> raw instruction sequence
1010 iseq_set_sequence(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
)
1014 struct iseq_insn_info_entry
*insn_info_table
;
1016 VALUE
*generated_iseq
;
1018 int k
, pos
, sp
, stack_max
= 0, line
= 0;
1020 /* set label position */
1021 list
= FIRST_ELEMENT(anchor
);
1024 switch (list
->type
) {
1025 case ISEQ_ELEMENT_INSN
:
1027 iobj
= (INSN
*)list
;
1028 line
= iobj
->line_no
;
1029 pos
+= insn_data_length(iobj
);
1033 case ISEQ_ELEMENT_LABEL
:
1035 lobj
= (LABEL
*)list
;
1036 lobj
->position
= pos
;
1040 case ISEQ_ELEMENT_NONE
:
1045 case ISEQ_ELEMENT_ADJUST
:
1047 ADJUST
*adjust
= (ADJUST
*)list
;
1048 if (adjust
->line_no
!= -1) {
1049 pos
+= 2 /* insn + 1 operand */;
1055 dump_disasm_list(FIRST_ELEMENT(anchor
));
1056 dump_disasm_list(list
);
1057 rb_compile_error(RSTRING_PTR(iseq
->filename
), line
,
1058 "error: set_sequence");
1064 /* make instruction sequence */
1065 generated_iseq
= ALLOC_N(VALUE
, pos
);
1066 insn_info_table
= ALLOC_N(struct iseq_insn_info_entry
, k
);
1068 list
= FIRST_ELEMENT(anchor
);
1072 switch (list
->type
) {
1073 case ISEQ_ELEMENT_INSN
:
1079 iobj
= (INSN
*)list
;
1082 sp
= calc_sp_depth(sp
, iobj
);
1083 if (sp
> stack_max
) {
1087 /* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */
1089 operands
= iobj
->operands
;
1090 insn
= iobj
->insn_id
;
1091 generated_iseq
[pos
] = insn
;
1092 types
= insn_op_types(insn
);
1093 len
= insn_len(insn
);
1096 if (iobj
->operand_size
!= len
- 1) {
1097 dump_disasm_list(list
);
1098 rb_compile_error(RSTRING_PTR(iseq
->filename
), iobj
->line_no
,
1099 "operand size miss! (%d for %d)",
1100 iobj
->operand_size
, len
- 1);
1104 for (j
= 0; types
[j
]; j
++) {
1105 char type
= types
[j
];
1106 /* printf("--> [%c - (%d-%d)]\n", type, k, j); */
1110 /* label(destination position) */
1111 lobj
= (LABEL
*)operands
[j
];
1112 if (lobj
->set
!= Qtrue
) {
1113 rb_compile_error(RSTRING_PTR(iseq
->filename
), iobj
->line_no
,
1116 if (lobj
->sp
== -1) {
1119 generated_iseq
[pos
+ 1 + j
] =
1120 lobj
->position
- (pos
+ len
);
1129 VALUE lits
= operands
[j
];
1130 VALUE map
= rb_hash_new();
1132 for (i
=0; i
< RARRAY_LEN(lits
); i
+=2) {
1133 VALUE obj
= rb_ary_entry(lits
, i
);
1134 VALUE lv
= rb_ary_entry(lits
, i
+1);
1135 lobj
= (LABEL
*)(lv
& ~1);
1137 if (lobj
->set
!= Qtrue
) {
1138 rb_compile_error(RSTRING_PTR(iseq
->filename
), iobj
->line_no
,
1141 rb_hash_aset(map
, obj
, INT2FIX(lobj
->position
- (pos
+len
)));
1143 generated_iseq
[pos
+ 1 + j
] = map
;
1144 iseq_add_mark_object(iseq
, map
);
1149 case TS_NUM
: /* ulong */
1150 generated_iseq
[pos
+ 1 + j
] = FIX2INT(operands
[j
]);
1152 case TS_ISEQ
: /* iseq */
1154 VALUE v
= operands
[j
];
1155 rb_iseq_t
*block
= 0;
1157 GetISeqPtr(v
, block
);
1159 generated_iseq
[pos
+ 1 + j
] = (VALUE
)block
;
1162 case TS_VALUE
: /* VALUE */
1164 VALUE v
= operands
[j
];
1165 generated_iseq
[pos
+ 1 + j
] = v
;
1166 /* to mark ruby object */
1167 iseq_add_mark_object(iseq
, v
);
1170 case TS_IC
: /* inline cache */
1172 VALUE v
= (VALUE
)NEW_INLINE_CACHE_ENTRY();
1173 generated_iseq
[pos
+ 1 + j
] = v
;
1174 iseq_add_mark_object(iseq
, v
);
1177 case TS_ID
: /* ID */
1178 generated_iseq
[pos
+ 1 + j
] = SYM2ID(operands
[j
]);
1182 struct global_entry
*entry
=
1183 (struct global_entry
*)(operands
[j
] & (~1));
1184 generated_iseq
[pos
+ 1 + j
] = (VALUE
)entry
;
1188 rb_compile_error(RSTRING_PTR(iseq
->filename
), iobj
->line_no
,
1189 "unknown operand type: %c", type
);
1193 insn_info_table
[k
].line_no
= iobj
->line_no
;
1194 insn_info_table
[k
].position
= pos
;
1195 insn_info_table
[k
].sp
= sp
;
1200 case ISEQ_ELEMENT_LABEL
:
1202 lobj
= (LABEL
*)list
;
1203 if (lobj
->sp
== -1) {
1211 case ISEQ_ELEMENT_ADJUST
:
1213 ADJUST
*adjust
= (ADJUST
*)list
;
1216 if (adjust
->label
) {
1217 sp
= adjust
->label
->sp
;
1223 if (adjust
->line_no
!= -1) {
1224 if (orig_sp
- sp
> 0) {
1225 insn_info_table
[k
].line_no
= adjust
->line_no
;
1226 insn_info_table
[k
].position
= pos
;
1227 insn_info_table
[k
].sp
= sp
;
1229 generated_iseq
[pos
++] = BIN(adjuststack
);
1230 generated_iseq
[pos
++] = orig_sp
- sp
;
1232 else if (orig_sp
- sp
== 0) {
1233 /* jump to next insn */
1234 insn_info_table
[k
].line_no
= adjust
->line_no
;
1235 insn_info_table
[k
].position
= pos
;
1236 insn_info_table
[k
].sp
= sp
;
1238 generated_iseq
[pos
++] = BIN(jump
);
1239 generated_iseq
[pos
++] = 0;
1242 rb_bug("iseq_set_sequence: adjust bug");
1255 /* this check need dead code elimination */
1257 rb_bug("SP is not 0 on %s (%d)\n", RSTRING_PTR(iseq
->name
), sp
);
1261 iseq
->iseq
= (void *)generated_iseq
;
1262 iseq
->iseq_size
= pos
;
1263 iseq
->insn_info_table
= insn_info_table
;
1264 iseq
->insn_info_size
= k
;
1265 iseq
->stack_max
= stack_max
;
1271 label_get_position(LABEL
*lobj
)
1273 return lobj
->position
;
1277 label_get_sp(LABEL
*lobj
)
1283 iseq_set_exception_table(rb_iseq_t
*iseq
)
1287 struct iseq_catch_table_entry
*entry
;
1289 tlen
= RARRAY_LEN(iseq
->compile_data
->catch_table_ary
);
1290 tptr
= RARRAY_PTR(iseq
->compile_data
->catch_table_ary
);
1292 iseq
->catch_table
= tlen
? ALLOC_N(struct iseq_catch_table_entry
, tlen
) : 0;
1293 iseq
->catch_table_size
= tlen
;
1295 for (i
= 0; i
< tlen
; i
++) {
1296 ptr
= RARRAY_PTR(tptr
[i
]);
1297 entry
= &iseq
->catch_table
[i
];
1298 entry
->type
= ptr
[0] & 0xffff;
1299 entry
->start
= label_get_position((LABEL
*)(ptr
[1] & ~1));
1300 entry
->end
= label_get_position((LABEL
*)(ptr
[2] & ~1));
1301 entry
->iseq
= ptr
[3];
1303 /* register iseq as mark object */
1304 if (entry
->iseq
!= 0) {
1305 iseq_add_mark_object(iseq
, entry
->iseq
);
1310 LABEL
*lobj
= (LABEL
*)(ptr
[4] & ~1);
1311 entry
->cont
= label_get_position(lobj
);
1312 entry
->sp
= label_get_sp(lobj
);
1314 /* TODO: Dirty Hack! Fix me */
1315 if (entry
->type
== CATCH_TYPE_RESCUE
||
1316 entry
->type
== CATCH_TYPE_BREAK
||
1317 (((ptr
[0] & 0x10000) == 0)
1318 && entry
->type
== CATCH_TYPE_NEXT
)) {
1327 iseq
->compile_data
->catch_table_ary
= 0; /* free */
1332 * set optional argument table
1333 * def foo(a, b=expr1, c=expr2)
1341 iseq_set_optargs_table(rb_iseq_t
*iseq
)
1345 if (iseq
->arg_opts
!= 0) {
1346 for (i
= 0; i
< iseq
->arg_opts
; i
++) {
1347 iseq
->arg_opt_table
[i
] =
1348 label_get_position((LABEL
*)iseq
->arg_opt_table
[i
]);
1354 static LINK_ELEMENT
*
1355 get_destination_insn(INSN
*iobj
)
1357 LABEL
*lobj
= (LABEL
*)OPERAND_AT(iobj
, 0);
1360 list
= lobj
->link
.next
;
1362 if (list
->type
== ISEQ_ELEMENT_INSN
) {
1370 static LINK_ELEMENT
*
1371 get_next_insn(INSN
*iobj
)
1373 LINK_ELEMENT
*list
= iobj
->link
.next
;
1376 if (list
->type
== ISEQ_ELEMENT_INSN
) {
1384 static LINK_ELEMENT
*
1385 get_prev_insn(INSN
*iobj
)
1387 LINK_ELEMENT
*list
= iobj
->link
.prev
;
1390 if (list
->type
== ISEQ_ELEMENT_INSN
) {
1399 iseq_peephole_optimize(rb_iseq_t
*iseq
, LINK_ELEMENT
*list
, const int do_tailcallopt
)
1401 INSN
*iobj
= (INSN
*)list
;
1403 if (iobj
->insn_id
== BIN(jump
)) {
1404 INSN
*niobj
, *diobj
, *piobj
;
1406 * useless jump elimination:
1412 * => in this case, first jump instruction should jump tp
1415 diobj
= (INSN
*)get_destination_insn(iobj
);
1416 niobj
= (INSN
*)get_next_insn(iobj
);
1418 if (diobj
== niobj
) {
1425 REMOVE_ELEM(&iobj
->link
);
1427 else if (iobj
!= diobj
&& diobj
->insn_id
== BIN(jump
)) {
1428 if (OPERAND_AT(iobj
, 0) != OPERAND_AT(diobj
, 0)) {
1429 OPERAND_AT(iobj
, 0) = OPERAND_AT(diobj
, 0);
1433 else if (diobj
->insn_id
== BIN(leave
)) {
1445 INSN
*eiobj
= new_insn_core(iseq
, iobj
->line_no
, BIN(leave
),
1446 diobj
->operand_size
, diobj
->operands
);
1447 INSN
*popiobj
= new_insn_core(iseq
, iobj
->line_no
,
1450 REPLACE_ELEM((LINK_ELEMENT
*)iobj
, (LINK_ELEMENT
*)eiobj
);
1451 INSERT_ELEM_NEXT((LINK_ELEMENT
*)eiobj
, (LINK_ELEMENT
*)popiobj
);
1455 * useless jump elimination (if/unless destination):
1468 else if ((piobj
= (INSN
*)get_prev_insn(iobj
)) != 0 &&
1469 (piobj
->insn_id
== BIN(branchif
) ||
1470 piobj
->insn_id
== BIN(branchunless
))) {
1471 if (niobj
== (INSN
*)get_destination_insn(piobj
)) {
1472 piobj
->insn_id
= (piobj
->insn_id
== BIN(branchif
))
1473 ? BIN(branchunless
) : BIN(branchif
);
1474 OPERAND_AT(piobj
, 0) = OPERAND_AT(iobj
, 0);
1475 REMOVE_ELEM(&iobj
->link
);
1480 if (iobj
->insn_id
== BIN(branchif
) ||
1481 iobj
->insn_id
== BIN(branchunless
)) {
1490 INSN
*nobj
= (INSN
*)get_destination_insn(iobj
);
1491 if (nobj
->insn_id
== BIN(jump
)) {
1492 OPERAND_AT(iobj
, 0) = OPERAND_AT(nobj
, 0);
1496 if (do_tailcallopt
&& iobj
->insn_id
== BIN(leave
)) {
1501 * send ..., ... | VM_CALL_TAILCALL_BIT, ...
1502 * leave # unreachable
1504 INSN
*piobj
= (INSN
*)get_prev_insn((INSN
*)list
);
1506 if (piobj
->insn_id
== BIN(send
) &&
1507 piobj
->operands
[2] == 0 /* block */
1509 piobj
->operands
[3] = INT2FIX(FIX2INT(piobj
->operands
[3]) | VM_CALL_TAILCALL_BIT
);
1516 insn_set_specialized_instruction(INSN
*iobj
, int insn_id
)
1518 iobj
->insn_id
= insn_id
;
1519 iobj
->operand_size
= 0;
1524 insn_set_specialized_instruction_with_ic(INSN
*iobj
, int insn_id
, int n
)
1527 iobj
->insn_id
= insn_id
;
1528 iobj
->operand_size
= n
;
1531 for (i
=0; i
<n
; i
++) {
1532 iobj
->operands
[i
] = Qnil
;
1540 iseq_specialized_instruction(rb_iseq_t
*iseq
, INSN
*iobj
)
1542 if (iobj
->insn_id
== BIN(send
)) {
1543 ID mid
= SYM2ID(OPERAND_AT(iobj
, 0));
1544 int argc
= FIX2INT(OPERAND_AT(iobj
, 1));
1545 VALUE block
= OPERAND_AT(iobj
, 2);
1546 VALUE flag
= OPERAND_AT(iobj
, 3);
1548 /* TODO: should be more sophisticated search */
1549 if (block
== 0 && flag
== INT2FIX(0)) {
1551 if (mid
== idLength
) {
1552 insn_set_specialized_instruction(iobj
, BIN(opt_length
));
1554 else if (mid
== idSucc
) {
1555 insn_set_specialized_instruction(iobj
, BIN(opt_succ
));
1557 else if (mid
== idNot
) {
1558 insn_set_specialized_instruction_with_ic(iobj
, BIN(opt_not
), 1);
1561 else if (argc
== 1) {
1564 else if (mid
== idPLUS
) {
1565 insn_set_specialized_instruction(iobj
, BIN(opt_plus
));
1567 else if (mid
== idMINUS
) {
1568 insn_set_specialized_instruction(iobj
, BIN(opt_minus
));
1570 else if (mid
== idMULT
) {
1571 insn_set_specialized_instruction(iobj
, BIN(opt_mult
));
1573 else if (mid
== idDIV
) {
1574 insn_set_specialized_instruction(iobj
, BIN(opt_div
));
1576 else if (mid
== idMOD
) {
1577 insn_set_specialized_instruction(iobj
, BIN(opt_mod
));
1579 else if (mid
== idEq
) {
1580 insn_set_specialized_instruction_with_ic(iobj
, BIN(opt_eq
), 1);
1582 else if (mid
== idNeq
) {
1583 insn_set_specialized_instruction_with_ic(iobj
, BIN(opt_neq
), 2);
1585 else if (mid
== idLT
) {
1586 insn_set_specialized_instruction(iobj
, BIN(opt_lt
));
1588 else if (mid
== idLE
) {
1589 insn_set_specialized_instruction(iobj
, BIN(opt_le
));
1591 else if (mid
== idGT
) {
1592 insn_set_specialized_instruction(iobj
, BIN(opt_gt
));
1594 else if (mid
== idGE
) {
1595 insn_set_specialized_instruction(iobj
, BIN(opt_ge
));
1597 else if (mid
== idLTLT
) {
1598 insn_set_specialized_instruction(iobj
, BIN(opt_ltlt
));
1600 else if (mid
== idAREF
) {
1601 insn_set_specialized_instruction(iobj
, BIN(opt_aref
));
1607 if (mid
== idSend
|| mid
== id__send__
) {
1608 OPERAND_AT(iobj
, 3) |= INT2FIX(VM_CALL_SEND_BIT
);
1616 iseq_optimize(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
)
1619 const int do_peepholeopt
= iseq
->compile_data
->option
->peephole_optimization
;
1620 const int do_tailcallopt
= iseq
->compile_data
->option
->tailcall_optimization
;
1621 const int do_si
= iseq
->compile_data
->option
->specialized_instruction
;
1622 const int do_ou
= iseq
->compile_data
->option
->operands_unification
;
1623 list
= FIRST_ELEMENT(anchor
);
1626 if (list
->type
== ISEQ_ELEMENT_INSN
) {
1627 if (do_peepholeopt
) {
1628 iseq_peephole_optimize(iseq
, list
, do_tailcallopt
);
1631 iseq_specialized_instruction(iseq
, (INSN
*)list
);
1634 insn_operands_unification((INSN
*)list
);
1642 #if OPT_INSTRUCTIONS_UNIFICATION
1644 new_unified_insn(rb_iseq_t
*iseq
,
1645 int insn_id
, int size
, LINK_ELEMENT
*seq_list
)
1648 LINK_ELEMENT
*list
= seq_list
;
1650 VALUE
*operands
= 0, *ptr
= 0;
1654 for (i
= 0; i
< size
; i
++) {
1655 iobj
= (INSN
*)list
;
1656 argc
+= iobj
->operand_size
;
1662 (VALUE
*)compile_data_alloc(iseq
, sizeof(VALUE
) * argc
);
1667 for (i
= 0; i
< size
; i
++) {
1668 iobj
= (INSN
*)list
;
1669 MEMCPY(ptr
, iobj
->operands
, VALUE
, iobj
->operand_size
);
1670 ptr
+= iobj
->operand_size
;
1674 return new_insn_core(iseq
, iobj
->line_no
, insn_id
, argc
, operands
);
1679 * This scheme can get more performance if do this optimize with
1680 * label address resolving.
1681 * It's future work (if compile time was bottle neck).
1684 iseq_insns_unification(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
)
1686 #if OPT_INSTRUCTIONS_UNIFICATION
1691 list
= FIRST_ELEMENT(anchor
);
1693 if (list
->type
== ISEQ_ELEMENT_INSN
) {
1694 iobj
= (INSN
*)list
;
1696 if (unified_insns_data
[id
] != 0) {
1697 const int *const *entry
= unified_insns_data
[id
];
1698 for (j
= 1; j
< (int)entry
[0]; j
++) {
1699 const int *unified
= entry
[j
];
1700 LINK_ELEMENT
*li
= list
->next
;
1701 for (k
= 2; k
< unified
[1]; k
++) {
1702 if (li
->type
!= ISEQ_ELEMENT_INSN
||
1703 ((INSN
*)li
)->insn_id
!= unified
[k
]) {
1710 new_unified_insn(iseq
, unified
[0], unified
[1] - 1,
1713 /* insert to list */
1714 niobj
->link
.prev
= (LINK_ELEMENT
*)iobj
->link
.prev
;
1715 niobj
->link
.next
= li
;
1717 li
->prev
= (LINK_ELEMENT
*)niobj
;
1720 list
->prev
->next
= (LINK_ELEMENT
*)niobj
;
1721 list
= (LINK_ELEMENT
*)niobj
;
1733 #if OPT_STACK_CACHING
1735 #define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)]
1736 #define SC_NEXT(insn) sc_insn_next[insn]
1738 #include "opt_sc.inc"
1741 insn_set_sc_state(rb_iseq_t
*iseq
, INSN
*iobj
, int state
)
1746 insn_id
= iobj
->insn_id
;
1747 iobj
->insn_id
= SC_INSN(insn_id
, state
);
1748 nstate
= SC_NEXT(iobj
->insn_id
);
1750 if (insn_id
== BIN(jump
) ||
1751 insn_id
== BIN(branchif
) || insn_id
== BIN(branchunless
)) {
1752 LABEL
*lobj
= (LABEL
*)OPERAND_AT(iobj
, 0);
1754 if (lobj
->sc_state
!= 0) {
1755 if (lobj
->sc_state
!= nstate
) {
1756 dump_disasm_list((LINK_ELEMENT
*)iobj
);
1757 dump_disasm_list((LINK_ELEMENT
*)lobj
);
1758 printf("\n-- %d, %d\n", lobj
->sc_state
, nstate
);
1759 rb_compile_error(RSTRING_PTR(iseq
->filename
), iobj
->lineno
,
1760 "insn_set_sc_state error\n");
1765 lobj
->sc_state
= nstate
;
1767 if (insn_id
== BIN(jump
)) {
1771 else if (insn_id
== BIN(leave
)) {
1779 label_set_sc_state(LABEL
*lobj
, int state
)
1781 if (lobj
->sc_state
!= 0) {
1782 if (lobj
->sc_state
!= state
) {
1783 state
= lobj
->sc_state
;
1787 lobj
->sc_state
= state
;
1797 iseq_set_sequence_stackcaching(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
)
1799 #if OPT_STACK_CACHING
1805 list
= FIRST_ELEMENT(anchor
);
1806 /* dump_disasm_list(list); */
1808 /* for each list element */
1811 switch (list
->type
) {
1812 case ISEQ_ELEMENT_INSN
:
1814 INSN
*iobj
= (INSN
*)list
;
1815 insn_id
= iobj
->insn_id
;
1817 /* dump_disasm_list(list); */
1822 /* exception merge point */
1823 if (state
!= SCS_AX
) {
1825 new_insn_body(iseq
, 0, BIN(reput
), 0);
1827 /* replace this insn */
1828 REPLACE_ELEM(list
, (LINK_ELEMENT
*)rpobj
);
1829 list
= (LINK_ELEMENT
*)rpobj
;
1836 if (state
== SCS_AB
|| state
== SCS_BA
) {
1837 state
= (state
== SCS_AB
? SCS_BA
: SCS_AB
);
1861 rb_compile_error(RSTRING_PTR(iseq
->filename
), iobj
->line_no
,
1864 /* remove useless pop */
1871 } /* end of switch */
1873 state
= insn_set_sc_state(iseq
, iobj
, state
);
1876 case ISEQ_ELEMENT_LABEL
:
1879 lobj
= (LABEL
*)list
;
1881 state
= label_set_sc_state(lobj
, state
);
1895 compile_dstr_fragments(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node
, int *cntp
)
1897 NODE
*list
= node
->nd_next
;
1898 VALUE lit
= node
->nd_lit
;
1901 debugp_param("nd_lit", lit
);
1902 ADD_INSN1(ret
, nd_line(node
), putobject
, node
->nd_lit
);
1905 COMPILE(ret
, "each string", list
->nd_head
);
1907 list
= list
->nd_next
;
1915 compile_dstr(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node
)
1918 compile_dstr_fragments(iseq
, ret
, node
, &cnt
);
1919 ADD_INSN1(ret
, nd_line(node
), concatstrings
, INT2FIX(cnt
));
1924 compile_dregx(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node
)
1927 compile_dstr_fragments(iseq
, ret
, node
, &cnt
);
1928 ADD_INSN2(ret
, nd_line(node
), toregexp
, INT2FIX(node
->nd_cflag
), INT2FIX(cnt
));
1933 compile_branch_condition(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* cond
,
1934 LABEL
*then_label
, LABEL
*else_label
)
1936 switch (nd_type(cond
)) {
1939 LABEL
*label
= NEW_LABEL(nd_line(cond
));
1940 compile_branch_condition(iseq
, ret
, cond
->nd_1st
, label
,
1942 ADD_LABEL(ret
, label
);
1943 compile_branch_condition(iseq
, ret
, cond
->nd_2nd
, then_label
,
1949 LABEL
*label
= NEW_LABEL(nd_line(cond
));
1950 compile_branch_condition(iseq
, ret
, cond
->nd_1st
, then_label
,
1952 ADD_LABEL(ret
, label
);
1953 compile_branch_condition(iseq
, ret
, cond
->nd_2nd
, then_label
,
1957 case NODE_LIT
: /* NODE_LIT is always not true */
1960 /* printf("useless conditon eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
1961 ADD_INSNL(ret
, nd_line(cond
), jump
, then_label
);
1965 /* printf("useless conditon eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
1966 ADD_INSNL(ret
, nd_line(cond
), jump
, else_label
);
1969 COMPILE(ret
, "branch condition", cond
);
1970 ADD_INSNL(ret
, nd_line(cond
), branchunless
, else_label
);
1971 ADD_INSNL(ret
, nd_line(cond
), jump
, then_label
);
1978 compile_array_(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node_root
,
1979 VALUE opt_p
, int poped
)
1981 NODE
*node
= node_root
;
1982 int len
= node
->nd_alen
, line
= nd_line(node
), i
=0;
1983 DECL_ANCHOR(anchor
);
1985 INIT_ANCHOR(anchor
);
1986 if (nd_type(node
) != NODE_ZARRAY
) {
1988 if (nd_type(node
) != NODE_ARRAY
) {
1989 rb_bug("compile_array: This node is not NODE_ARRAY, but %s",
1990 ruby_node_name(nd_type(node
)));
1994 if (opt_p
&& nd_type(node
->nd_head
) != NODE_LIT
) {
1997 COMPILE_(anchor
, "array element", node
->nd_head
, poped
);
1998 node
= node
->nd_next
;
2004 rb_bug("node error: compile_array (%d: %d-%d)",
2005 (int)nd_line(node_root
), len
, i
);
2010 if (opt_p
== Qtrue
) {
2012 VALUE ary
= rb_ary_new();
2015 rb_ary_push(ary
, node
->nd_head
->nd_lit
);
2016 node
= node
->nd_next
;
2019 iseq_add_mark_object_compile_time(iseq
, ary
);
2020 ADD_INSN1(ret
, nd_line(node_root
), duparray
, ary
);
2025 ADD_INSN1(anchor
, line
, newarray
, INT2FIX(len
));
2027 APPEND_LIST(ret
, anchor
);
2033 compile_array(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node_root
, VALUE opt_p
)
2035 return compile_array_(iseq
, ret
, node_root
, opt_p
, 0);
2039 case_when_optimizable_literal(NODE
* node
)
2041 switch (nd_type(node
)) {
2043 VALUE v
= node
->nd_lit
;
2044 if (SYMBOL_P(v
) || rb_obj_is_kind_of(v
, rb_cNumeric
)) {
2050 return node
->nd_lit
;
2056 when_vals(rb_iseq_t
*iseq
, LINK_ANCHOR
*cond_seq
, NODE
*vals
, LABEL
*l1
, VALUE special_literals
)
2062 val
= vals
->nd_head
;
2064 if (special_literals
&&
2065 (lit
= case_when_optimizable_literal(val
)) != Qfalse
) {
2066 rb_ary_push(special_literals
, lit
);
2067 rb_ary_push(special_literals
, (VALUE
)(l1
) | 1);
2070 special_literals
= Qfalse
;
2073 COMPILE(cond_seq
, "when cond", val
);
2074 ADD_INSN1(cond_seq
, nd_line(val
), topn
, INT2FIX(1));
2075 ADD_SEND(cond_seq
, nd_line(val
), ID2SYM(idEqq
), INT2FIX(1));
2076 ADD_INSNL(cond_seq
, nd_line(val
), branchif
, l1
);
2077 vals
= vals
->nd_next
;
2079 return special_literals
;
2083 compile_massign_lhs(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
*node
)
2085 switch (nd_type(node
)) {
2086 case NODE_ATTRASGN
: {
2090 COMPILE_POPED(ret
, "masgn lhs (NODE_ATTRASGN)", node
);
2091 POP_ELEMENT(ret
); /* pop pop insn */
2092 iobj
= (INSN
*)POP_ELEMENT(ret
); /* pop send insn */
2094 dupidx
= iobj
->operands
[1];
2095 dupidx
= INT2FIX(FIX2INT(dupidx
) + 1);
2096 iobj
->operands
[1] = dupidx
;
2098 ADD_INSN1(ret
, nd_line(node
), topn
, dupidx
);
2099 ADD_ELEM(ret
, (LINK_ELEMENT
*)iobj
);
2100 ADD_INSN(ret
, nd_line(node
), pop
); /* result */
2101 ADD_INSN(ret
, nd_line(node
), pop
); /* rhs */
2105 DECL_ANCHOR(anchor
);
2106 INIT_ANCHOR(anchor
);
2107 COMPILE_POPED(anchor
, "nest masgn lhs", node
);
2108 REMOVE_ELEM(FIRST_ELEMENT(anchor
));
2109 ADD_SEQ(ret
, anchor
);
2113 DECL_ANCHOR(anchor
);
2114 INIT_ANCHOR(anchor
);
2115 COMPILE_POPED(anchor
, "masgn lhs", node
);
2116 REMOVE_ELEM(FIRST_ELEMENT(anchor
));
2117 ADD_SEQ(ret
, anchor
);
2125 compile_massign_opt_lhs(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
*lhsn
)
2128 compile_massign_opt_lhs(iseq
, ret
, lhsn
->nd_next
);
2129 compile_massign_lhs(iseq
, ret
, lhsn
->nd_head
);
2134 compile_massign_opt(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
,
2135 NODE
*rhsn
, NODE
*orig_lhsn
)
2138 const int memsize
= sizeof(mem
) / sizeof(mem
[0]);
2140 int llen
= 0, rlen
= 0;
2142 NODE
*lhsn
= orig_lhsn
;
2144 #define MEMORY(v) { \
2146 if (memindex == memsize) return 0; \
2147 for (i=0; i<memindex; i++) { \
2148 if (mem[i] == (v)) return 0; \
2150 mem[memindex++] = (v); \
2153 if (rhsn
== 0 || nd_type(rhsn
) != NODE_ARRAY
) {
2158 NODE
*ln
= lhsn
->nd_head
;
2159 switch (nd_type(ln
)) {
2164 case NODE_DASGN_CURR
:
2173 lhsn
= lhsn
->nd_next
;
2179 COMPILE_POPED(ret
, "masgn val (poped)", rhsn
->nd_head
);
2182 COMPILE(ret
, "masgn val", rhsn
->nd_head
);
2184 rhsn
= rhsn
->nd_next
;
2189 for (i
=0; i
<llen
-rlen
; i
++) {
2190 ADD_INSN(ret
, nd_line(orig_lhsn
), putnil
);
2194 compile_massign_opt_lhs(iseq
, ret
, orig_lhsn
);
2199 compile_massign(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
*node
, int poped
)
2201 NODE
*rhsn
= node
->nd_value
;
2202 NODE
*splatn
= node
->nd_args
;
2203 NODE
*lhsn
= node
->nd_head
;
2204 int lhs_splat
= (splatn
&& (VALUE
)splatn
!= (VALUE
)-1) ? 1 : 0;
2206 if (!poped
|| splatn
|| !compile_massign_opt(iseq
, ret
, rhsn
, lhsn
)) {
2208 DECL_ANCHOR(lhsseq
);
2210 INIT_ANCHOR(lhsseq
);
2213 compile_massign_lhs(iseq
, lhsseq
, lhsn
->nd_head
);
2215 lhsn
= lhsn
->nd_next
;
2218 COMPILE(ret
, "normal masgn rhs", rhsn
);
2221 ADD_INSN(ret
, nd_line(node
), dup
);
2224 ADD_INSN2(ret
, nd_line(node
), expandarray
,
2225 INT2FIX(llen
), INT2FIX(lhs_splat
));
2226 ADD_SEQ(ret
, lhsseq
);
2229 if (nd_type(splatn
) == NODE_POSTARG
) {
2230 /*a, b, *r, p1, p2 */
2231 NODE
*postn
= splatn
->nd_2nd
;
2232 NODE
*restn
= splatn
->nd_1st
;
2233 int num
= postn
->nd_alen
;
2234 int flag
= 0x02 | (((VALUE
)restn
== (VALUE
)-1) ? 0x00 : 0x01);
2236 ADD_INSN2(ret
, nd_line(splatn
), expandarray
,
2237 INT2FIX(num
), INT2FIX(flag
));
2239 if ((VALUE
)restn
!= (VALUE
)-1) {
2240 compile_massign_lhs(iseq
, ret
, restn
);
2243 compile_massign_lhs(iseq
, ret
, postn
->nd_head
);
2244 postn
= postn
->nd_next
;
2249 compile_massign_lhs(iseq
, ret
, splatn
);
2257 compile_colon2(rb_iseq_t
*iseq
, NODE
* node
,
2258 LINK_ANCHOR
*pref
, LINK_ANCHOR
*body
)
2260 switch (nd_type(node
)) {
2262 debugi("compile_colon2 - colon", node
->nd_vid
);
2263 ADD_INSN1(body
, nd_line(node
), getconstant
, ID2SYM(node
->nd_vid
));
2266 debugi("compile_colon2 - colon3", node
->nd_mid
);
2267 ADD_INSN(body
, nd_line(node
), pop
);
2268 ADD_INSN1(body
, nd_line(node
), putobject
, rb_cObject
);
2269 ADD_INSN1(body
, nd_line(node
), getconstant
, ID2SYM(node
->nd_mid
));
2272 compile_colon2(iseq
, node
->nd_head
, pref
, body
);
2273 debugi("compile_colon2 - colon2", node
->nd_mid
);
2274 ADD_INSN1(body
, nd_line(node
), getconstant
, ID2SYM(node
->nd_mid
));
2277 COMPILE(pref
, "const colon2 prefix", node
);
2284 compile_cpath(LINK_ANCHOR
*ret
, rb_iseq_t
*iseq
, NODE
*cpath
)
2286 if (cpath
->nd_head
) {
2287 COMPILE(ret
, "nd_else->nd_head", cpath
->nd_head
);
2289 else if (nd_type(cpath
) == NODE_COLON2
) {
2290 COMPILE(ret
, "cpath (NODE_COLON2)", cpath
->nd_head
);
2293 ADD_INSN1(ret
, nd_line(cpath
), putobject
, rb_cObject
);
2299 defined_expr(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
,
2300 NODE
*node
, LABEL
**lfinish
, VALUE needstr
)
2303 enum node_type type
;
2305 switch (type
= nd_type(node
)) {
2325 defined_expr(iseq
, ret
, vals
->nd_head
, lfinish
, Qfalse
);
2328 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2331 LABEL
*lcont
= NEW_LABEL(nd_line(node
));
2332 lfinish
[1] = NEW_LABEL(nd_line(node
));
2333 ADD_INSNL(ret
, nd_line(node
), branchif
, lcont
);
2334 ADD_LABEL(ret
, lfinish
[1]);
2335 ADD_INSN(ret
, nd_line(node
), putnil
);
2336 ADD_INSNL(ret
, nd_line(node
), jump
, lfinish
[0]);
2337 ADD_LABEL(ret
, lcont
);
2339 } while ((vals
= vals
->nd_next
) != NULL
);
2344 estr
= "expression";
2350 estr
= "local-variable";
2354 ADD_INSN(ret
, nd_line(node
), putnil
);
2355 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_IVAR
),
2356 ID2SYM(node
->nd_vid
), needstr
);
2360 ADD_INSN(ret
, nd_line(node
), putnil
);
2361 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_GVAR
),
2362 ((VALUE
)node
->nd_entry
) | 1, needstr
);
2366 ADD_INSN(ret
, nd_line(node
), putnil
);
2367 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_CVAR
),
2368 ID2SYM(node
->nd_vid
), needstr
);
2372 ADD_INSN(ret
, nd_line(node
), putnil
);
2373 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_CONST
),
2374 ID2SYM(node
->nd_vid
), needstr
);
2378 lfinish
[1] = NEW_LABEL(nd_line(node
));
2380 defined_expr(iseq
, ret
, node
->nd_head
, lfinish
, Qfalse
);
2381 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2383 if (rb_is_const_id(node
->nd_mid
)) {
2384 COMPILE(ret
, "defined/colon2#nd_head", node
->nd_head
);
2385 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_CONST
),
2386 ID2SYM(node
->nd_mid
), needstr
);
2389 COMPILE(ret
, "defined/colon2#nd_head", node
->nd_head
);
2390 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_METHOD
),
2391 ID2SYM(node
->nd_mid
), needstr
);
2395 ADD_INSN1(ret
, nd_line(node
), putobject
, rb_cObject
);
2396 ADD_INSN3(ret
, nd_line(node
), defined
,
2397 INT2FIX(DEFINED_CONST
), ID2SYM(node
->nd_mid
), needstr
);
2400 /* method dispatch */
2404 case NODE_ATTRASGN
:{
2409 if (node
->nd_recv
== (NODE
*)1) break;
2417 lfinish
[1] = NEW_LABEL(nd_line(node
));
2419 if (node
->nd_args
) {
2420 defined_expr(iseq
, ret
, node
->nd_args
, lfinish
, Qfalse
);
2421 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2424 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
2425 LABEL
*lend
= NEW_LABEL(nd_line(node
));
2426 VALUE rescue
= NEW_CHILD_ISEQVAL(NEW_NIL(),
2427 rb_str_concat(rb_str_new2
2428 ("defined guard in "),
2430 ISEQ_TYPE_DEFINED_GUARD
);
2432 defined_expr(iseq
, ret
, node
->nd_recv
, lfinish
, Qfalse
);
2433 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2435 ADD_LABEL(ret
, lstart
);
2436 COMPILE(ret
, "defined/recv", node
->nd_recv
);
2437 ADD_LABEL(ret
, lend
);
2438 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE
, lstart
, lend
, rescue
, lfinish
[1]);
2439 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_METHOD
),
2440 ID2SYM(node
->nd_mid
), needstr
);
2443 ADD_INSN(ret
, nd_line(node
), putself
);
2444 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_FUNC
),
2445 ID2SYM(node
->nd_mid
), needstr
);
2451 ADD_INSN(ret
, nd_line(node
), putnil
);
2452 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_YIELD
), 0,
2458 ADD_INSN(ret
, nd_line(node
), putnil
);
2459 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_REF
),
2460 INT2FIX((node
->nd_nth
<< 1) | (type
== NODE_BACK_REF
)),
2465 ADD_INSN(ret
, nd_line(node
), putnil
);
2466 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_ZSUPER
), 0,
2475 case NODE_DASGN_CURR
:
2481 estr
= "assignment";
2485 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
2486 LABEL
*lend
= NEW_LABEL(nd_line(node
));
2487 VALUE ensure
= NEW_CHILD_ISEQVAL(NEW_NIL(),
2488 rb_str_concat(rb_str_new2
2489 ("defined guard in "),
2491 ISEQ_TYPE_DEFINED_GUARD
);
2493 ADD_LABEL(ret
, lstart
);
2494 COMPILE(ret
, "defined expr (others)", node
);
2496 lfinish
[1] = NEW_LABEL(nd_line(node
));
2498 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2500 ADD_INSN1(ret
, nd_line(node
), putstring
, rb_str_new2("expression"));
2503 ADD_INSN1(ret
, nd_line(node
), putobject
, Qtrue
);
2505 ADD_LABEL(ret
, lend
);
2507 ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE
, lstart
, lend
, ensure
, lfinish
[1]);
2509 } /* end of default */
2513 if (needstr
!= Qfalse
) {
2514 VALUE str
= rb_str_new2(estr
);
2515 ADD_INSN1(ret
, nd_line(node
), putstring
, str
);
2516 iseq_add_mark_object_compile_time(iseq
, str
);
2519 ADD_INSN1(ret
, nd_line(node
), putobject
, Qtrue
);
2526 #define BUFSIZE 0x100
2529 make_name_for_block(rb_iseq_t
*iseq
)
2531 if (iseq
->parent_iseq
== 0) {
2532 return rb_sprintf("block in %s", RSTRING_PTR(iseq
->name
));
2536 rb_iseq_t
*ip
= iseq
;
2537 while (ip
->local_iseq
!= ip
) {
2538 ip
= ip
->parent_iseq
;
2541 return rb_sprintf("block (%d levels) in %s", level
, RSTRING_PTR(ip
->name
));
2546 add_ensure_range(rb_iseq_t
*iseq
, struct ensure_range
*erange
,
2547 LABEL
*lstart
, LABEL
*lend
)
2549 struct ensure_range
*ne
=
2550 compile_data_alloc(iseq
, sizeof(struct ensure_range
));
2552 while (erange
->next
!= 0) {
2553 erange
= erange
->next
;
2557 ne
->end
= erange
->end
;
2558 erange
->end
= lstart
;
2564 add_ensure_iseq(LINK_ANCHOR
*ret
, rb_iseq_t
*iseq
)
2566 struct iseq_compile_data_ensure_node_stack
*enlp
=
2567 iseq
->compile_data
->ensure_node_stack
;
2568 struct iseq_compile_data_ensure_node_stack
*prev_enlp
= enlp
;
2569 DECL_ANCHOR(ensure
);
2571 INIT_ANCHOR(ensure
);
2573 DECL_ANCHOR(ensure_part
);
2574 LABEL
*lstart
= NEW_LABEL(0);
2575 LABEL
*lend
= NEW_LABEL(0);
2577 INIT_ANCHOR(ensure_part
);
2578 add_ensure_range(iseq
, enlp
->erange
, lstart
, lend
);
2580 iseq
->compile_data
->ensure_node_stack
= enlp
->prev
;
2581 ADD_LABEL(ensure_part
, lstart
);
2582 COMPILE_POPED(ensure_part
, "ensure part", enlp
->ensure_node
);
2583 ADD_LABEL(ensure_part
, lend
);
2585 ADD_SEQ(ensure
, ensure_part
);
2588 iseq
->compile_data
->ensure_node_stack
= prev_enlp
;
2589 ADD_SEQ(ret
, ensure
);
2593 setup_args(rb_iseq_t
*iseq
, LINK_ANCHOR
*args
, NODE
*argn
, unsigned long *flag
)
2595 VALUE argc
= INT2FIX(0);
2597 DECL_ANCHOR(arg_block
);
2598 DECL_ANCHOR(args_splat
);
2600 INIT_ANCHOR(arg_block
);
2601 INIT_ANCHOR(args_splat
);
2602 if (argn
&& nd_type(argn
) == NODE_BLOCK_PASS
) {
2603 COMPILE(arg_block
, "block", argn
->nd_body
);
2604 *flag
|= VM_CALL_ARGS_BLOCKARG_BIT
;
2605 argn
= argn
->nd_head
;
2610 switch (nd_type(argn
)) {
2612 COMPILE(args
, "args (splat)", argn
->nd_head
);
2615 *flag
|= VM_CALL_ARGS_SPLAT_BIT
;
2619 case NODE_ARGSPUSH
: {
2620 int next_is_array
= (nd_type(argn
->nd_head
) == NODE_ARRAY
);
2624 COMPILE(tmp
, "args (cat: splat)", argn
->nd_body
);
2625 if (next_is_array
&& nsplat
== 0) {
2629 if (nd_type(argn
) == NODE_ARGSCAT
) {
2630 ADD_INSN1(tmp
, nd_line(argn
), splatarray
, Qfalse
);
2633 ADD_INSN1(tmp
, nd_line(argn
), newarray
, INT2FIX(1));
2636 INSERT_LIST(args_splat
, tmp
);
2638 *flag
|= VM_CALL_ARGS_SPLAT_BIT
;
2640 if (next_is_array
) {
2641 argc
= INT2FIX(compile_array(iseq
, args
, argn
->nd_head
, Qfalse
) + 1);
2645 argn
= argn
->nd_head
;
2651 argc
= INT2FIX(compile_array(iseq
, args
, argn
, Qfalse
));
2656 rb_bug("setup_arg: unknown node: %s\n", ruby_node_name(nd_type(argn
)));
2663 for (i
=1; i
<nsplat
; i
++) {
2664 ADD_INSN(args_splat
, nd_line(args
), concatarray
);
2668 if (!LIST_SIZE_ZERO(args_splat
)) {
2669 ADD_SEQ(args
, args_splat
);
2672 if (*flag
& VM_CALL_ARGS_BLOCKARG_BIT
) {
2673 ADD_SEQ(args
, arg_block
);
2682 self: InstructionSequence
2683 node: Ruby compiled node
2684 poped: This node will be poped
2687 iseq_compile_each(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node
, int poped
)
2689 enum node_type type
;
2693 debugs("node: NODE_NIL(implicit)\n");
2694 ADD_INSN(ret
, iseq
->compile_data
->last_line
, putnil
);
2699 iseq
->compile_data
->last_line
= nd_line(node
);
2700 debug_node_start(node
);
2702 type
= nd_type(node
);
2704 if (node
->flags
& NODE_FL_NEWLINE
) {
2705 ADD_TRACE(ret
, nd_line(node
), RUBY_EVENT_LINE
);
2710 while (node
&& nd_type(node
) == NODE_BLOCK
) {
2711 COMPILE_(ret
, "BLOCK body", node
->nd_head
,
2712 (node
->nd_next
== 0 && poped
== 0) ? 0 : 1);
2713 node
= node
->nd_next
;
2716 COMPILE_(ret
, "BLOCK next", node
->nd_next
, poped
);
2721 DECL_ANCHOR(cond_seq
);
2722 DECL_ANCHOR(then_seq
);
2723 DECL_ANCHOR(else_seq
);
2724 LABEL
*then_label
, *else_label
, *end_label
;
2726 INIT_ANCHOR(cond_seq
);
2727 INIT_ANCHOR(then_seq
);
2728 INIT_ANCHOR(else_seq
);
2729 then_label
= NEW_LABEL(nd_line(node
));
2730 else_label
= NEW_LABEL(nd_line(node
));
2731 end_label
= NEW_LABEL(nd_line(node
));
2733 compile_branch_condition(iseq
, cond_seq
, node
->nd_cond
,
2734 then_label
, else_label
);
2735 COMPILE_(then_seq
, "then", node
->nd_body
, poped
);
2736 COMPILE_(else_seq
, "else", node
->nd_else
, poped
);
2738 ADD_SEQ(ret
, cond_seq
);
2740 ADD_LABEL(ret
, then_label
);
2741 ADD_SEQ(ret
, then_seq
);
2742 ADD_INSNL(ret
, nd_line(node
), jump
, end_label
);
2744 ADD_LABEL(ret
, else_label
);
2745 ADD_SEQ(ret
, else_seq
);
2747 ADD_LABEL(ret
, end_label
);
2753 NODE
*tempnode
= node
;
2754 LABEL
*endlabel
, *elselabel
;
2756 DECL_ANCHOR(body_seq
);
2757 DECL_ANCHOR(cond_seq
);
2758 VALUE special_literals
= rb_ary_new();
2761 INIT_ANCHOR(body_seq
);
2762 INIT_ANCHOR(cond_seq
);
2763 if (node
->nd_head
== 0) {
2764 COMPILE_(ret
, "when", node
->nd_body
, poped
);
2767 COMPILE(head
, "case base", node
->nd_head
);
2769 node
= node
->nd_body
;
2770 type
= nd_type(node
);
2772 if (type
!= NODE_WHEN
) {
2773 COMPILE_ERROR((ERROR_ARGS
"NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type
)));
2776 endlabel
= NEW_LABEL(nd_line(node
));
2777 elselabel
= NEW_LABEL(nd_line(node
));
2779 ADD_SEQ(ret
, head
); /* case VAL */
2781 while (type
== NODE_WHEN
) {
2784 l1
= NEW_LABEL(nd_line(node
));
2785 ADD_LABEL(body_seq
, l1
);
2786 ADD_INSN(body_seq
, nd_line(node
), pop
);
2787 COMPILE_(body_seq
, "when body", node
->nd_body
, poped
);
2788 ADD_INSNL(body_seq
, nd_line(node
), jump
, endlabel
);
2790 vals
= node
->nd_head
;
2792 switch (nd_type(vals
)) {
2794 special_literals
= when_vals(iseq
, cond_seq
, vals
, l1
, special_literals
);
2799 special_literals
= 0;
2800 COMPILE(cond_seq
, "when/cond splat", vals
);
2801 ADD_INSN1(cond_seq
, nd_line(vals
), checkincludearray
, Qtrue
);
2802 ADD_INSNL(cond_seq
, nd_line(vals
), branchif
, l1
);
2805 rb_bug("NODE_CASE: unknown node (%s)",
2806 ruby_node_name(nd_type(vals
)));
2810 rb_bug("NODE_CASE: must be NODE_ARRAY, but 0");
2813 node
= node
->nd_next
;
2817 type
= nd_type(node
);
2821 ADD_LABEL(cond_seq
, elselabel
);
2822 ADD_INSN(cond_seq
, nd_line(node
), pop
);
2823 COMPILE_(cond_seq
, "else", node
, poped
);
2824 ADD_INSNL(cond_seq
, nd_line(node
), jump
, endlabel
);
2827 debugs("== else (implicit)\n");
2828 ADD_LABEL(cond_seq
, elselabel
);
2829 ADD_INSN(cond_seq
, nd_line(tempnode
), pop
);
2831 ADD_INSN(cond_seq
, nd_line(tempnode
), putnil
);
2833 ADD_INSNL(cond_seq
, nd_line(tempnode
), jump
, endlabel
);
2836 if (special_literals
) {
2837 ADD_INSN(ret
, nd_line(tempnode
), dup
);
2838 ADD_INSN2(ret
, nd_line(tempnode
), opt_case_dispatch
,
2839 special_literals
, elselabel
);
2840 iseq_add_mark_object_compile_time(iseq
, special_literals
);
2843 ADD_SEQ(ret
, cond_seq
);
2844 ADD_SEQ(ret
, body_seq
);
2845 ADD_LABEL(ret
, endlabel
);
2851 NODE
*orig_node
= node
;
2853 DECL_ANCHOR(body_seq
);
2855 INIT_ANCHOR(body_seq
);
2856 endlabel
= NEW_LABEL(nd_line(node
));
2858 while (node
&& nd_type(node
) == NODE_WHEN
) {
2859 LABEL
*l1
= NEW_LABEL(nd_line(node
));
2860 ADD_LABEL(body_seq
, l1
);
2861 COMPILE_(body_seq
, "when", node
->nd_body
, poped
);
2862 ADD_INSNL(body_seq
, nd_line(node
), jump
, endlabel
);
2864 vals
= node
->nd_head
;
2865 if (vals
&& nd_type(vals
) == NODE_ARRAY
) {
2867 val
= vals
->nd_head
;
2868 COMPILE(ret
, "when2", val
);
2869 ADD_INSNL(ret
, nd_line(val
), branchif
, l1
);
2870 vals
= vals
->nd_next
;
2873 else if (nd_type(vals
) == NODE_SPLAT
||
2874 nd_type(vals
) == NODE_ARGSCAT
||
2875 nd_type(vals
) == NODE_ARGSPUSH
) {
2877 NODE
*val
= vals
->nd_head
;
2879 if (nd_type(vals
) == NODE_ARGSCAT
|| nd_type(vals
) == NODE_ARGSPUSH
) {
2880 NODE
*vs
= vals
->nd_head
;
2881 val
= vals
->nd_body
;
2884 NODE
* val
= vs
->nd_head
;
2885 COMPILE(ret
, "when/argscat", val
);
2886 ADD_INSNL(ret
, nd_line(val
), branchif
, l1
);
2891 ADD_INSN(ret
, nd_line(val
), putnil
);
2892 COMPILE(ret
, "when2/splat", val
);
2893 ADD_INSN1(ret
, nd_line(val
), checkincludearray
, Qfalse
);
2894 ADD_INSN(ret
, nd_line(val
), pop
);
2895 ADD_INSNL(ret
, nd_line(val
), branchif
, l1
);
2900 node
= node
->nd_next
;
2903 COMPILE_(ret
, "else", node
, poped
);
2904 ADD_INSNL(ret
, nd_line(orig_node
), jump
, endlabel
);
2906 ADD_SEQ(ret
, body_seq
);
2907 ADD_LABEL(ret
, endlabel
);
2914 LABEL
*prev_start_label
= iseq
->compile_data
->start_label
;
2915 LABEL
*prev_end_label
= iseq
->compile_data
->end_label
;
2916 LABEL
*prev_redo_label
= iseq
->compile_data
->redo_label
;
2917 VALUE prev_loopval_popped
= iseq
->compile_data
->loopval_popped
;
2919 struct iseq_compile_data_ensure_node_stack
*enlp
=
2920 iseq
->compile_data
->ensure_node_stack
;
2922 LABEL
*next_label
= iseq
->compile_data
->start_label
= NEW_LABEL(nd_line(node
)); /* next */
2923 LABEL
*redo_label
= iseq
->compile_data
->redo_label
= NEW_LABEL(nd_line(node
)); /* redo */
2924 LABEL
*break_label
= iseq
->compile_data
->end_label
= NEW_LABEL(nd_line(node
)); /* break */
2925 LABEL
*end_label
= NEW_LABEL(nd_line(node
));
2927 iseq
->compile_data
->loopval_popped
= 0;
2928 iseq
->compile_data
->ensure_node_stack
= 0;
2930 if (type
== NODE_OPT_N
|| node
->nd_state
== 1) {
2931 ADD_INSNL(ret
, nd_line(node
), jump
, next_label
);
2934 ADD_LABEL(ret
, redo_label
);
2935 COMPILE_POPED(ret
, "while body", node
->nd_body
);
2936 ADD_LABEL(ret
, next_label
); /* next */
2938 if (type
== NODE_WHILE
) {
2939 compile_branch_condition(iseq
, ret
, node
->nd_cond
,
2940 redo_label
, end_label
);
2942 else if (type
== NODE_UNTIL
) {
2944 compile_branch_condition(iseq
, ret
, node
->nd_cond
,
2945 end_label
, redo_label
);
2948 ADD_CALL_RECEIVER(ret
, nd_line(node
));
2949 ADD_CALL(ret
, nd_line(node
), ID2SYM(idGets
), INT2FIX(0));
2950 ADD_INSNL(ret
, nd_line(node
), branchif
, redo_label
);
2954 ADD_LABEL(ret
, end_label
);
2956 if (node
->nd_state
== Qundef
) {
2957 /* ADD_INSN(ret, nd_line(node), putundef); */
2958 rb_bug("unsupported: putundef");
2961 ADD_INSN(ret
, nd_line(node
), putnil
);
2964 ADD_LABEL(ret
, break_label
); /* braek */
2967 ADD_INSN(ret
, nd_line(node
), pop
);
2970 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK
, redo_label
, break_label
,
2972 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT
| 0x10000, redo_label
,
2973 break_label
, 0, iseq
->compile_data
->start_label
);
2974 ADD_CATCH_ENTRY(CATCH_TYPE_REDO
, redo_label
, break_label
, 0,
2975 iseq
->compile_data
->redo_label
);
2977 iseq
->compile_data
->start_label
= prev_start_label
;
2978 iseq
->compile_data
->end_label
= prev_end_label
;
2979 iseq
->compile_data
->redo_label
= prev_redo_label
;
2980 iseq
->compile_data
->loopval_popped
= prev_loopval_popped
;
2981 iseq
->compile_data
->ensure_node_stack
= enlp
;
2986 VALUE prevblock
= iseq
->compile_data
->current_block
;
2987 LABEL
*retry_label
= NEW_LABEL(nd_line(node
));
2988 LABEL
*retry_end_l
= NEW_LABEL(nd_line(node
));
2991 ADD_LABEL(ret
, retry_label
);
2992 if (nd_type(node
) == NODE_FOR
) {
2993 COMPILE(ret
, "iter caller (for)", node
->nd_iter
);
2995 iseq
->compile_data
->current_block
=
2996 NEW_CHILD_ISEQVAL(node
->nd_body
, make_name_for_block(iseq
),
3000 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idEach
), INT2FIX(0),
3001 iseq
->compile_data
->current_block
, INT2FIX(0));
3004 iseq
->compile_data
->current_block
=
3005 NEW_CHILD_ISEQVAL(node
->nd_body
, make_name_for_block(iseq
),
3007 COMPILE(ret
, "iter caller", node
->nd_iter
);
3009 ADD_LABEL(ret
, retry_end_l
);
3012 ADD_INSN(ret
, nd_line(node
), pop
);
3015 iseq
->compile_data
->current_block
= prevblock
;
3017 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK
, retry_label
, retry_end_l
, 0, retry_end_l
);
3022 unsigned long level
= 0;
3024 if (iseq
->compile_data
->redo_label
!= 0) {
3026 LABEL
*splabel
= NEW_LABEL(0);
3027 ADD_LABEL(ret
, splabel
);
3028 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->redo_label
);
3029 COMPILE_(ret
, "break val (while/until)", node
->nd_stts
, iseq
->compile_data
->loopval_popped
);
3030 add_ensure_iseq(ret
, iseq
);
3031 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->end_label
);
3032 ADD_ADJUST_RESTORE(ret
, splabel
);
3035 ADD_INSN(ret
, nd_line(node
), putnil
);
3038 else if (iseq
->type
== ISEQ_TYPE_BLOCK
) {
3040 /* escape from block */
3041 COMPILE(ret
, "break val (block)", node
->nd_stts
);
3042 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(level
| 0x02) /* TAG_BREAK */ );
3044 ADD_INSN(ret
, nd_line(node
), pop
);
3047 else if (iseq
->type
== ISEQ_TYPE_EVAL
) {
3049 COMPILE_ERROR((ERROR_ARGS
"Can't escape from eval with break"));
3052 rb_iseq_t
*ip
= iseq
->parent_iseq
;
3055 if (ip
->compile_data
->redo_label
!= 0) {
3057 if (ip
->compile_data
->loopval_popped
== 0) {
3063 else if (ip
->type
== ISEQ_TYPE_BLOCK
) {
3067 else if (ip
->type
== ISEQ_TYPE_EVAL
) {
3070 ip
= ip
->parent_iseq
;
3072 COMPILE_ERROR((ERROR_ARGS
"Invalid break"));
3077 unsigned long level
= 0;
3079 if (iseq
->compile_data
->redo_label
!= 0) {
3080 LABEL
*splabel
= NEW_LABEL(0);
3081 debugs("next in while loop\n");
3082 ADD_LABEL(ret
, splabel
);
3083 COMPILE(ret
, "next val/valid syntax?", node
->nd_stts
);
3084 add_ensure_iseq(ret
, iseq
);
3085 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->redo_label
);
3086 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->start_label
);
3087 ADD_ADJUST_RESTORE(ret
, splabel
);
3089 else if (iseq
->compile_data
->end_label
) {
3090 LABEL
*splabel
= NEW_LABEL(0);
3091 debugs("next in block\n");
3092 ADD_LABEL(ret
, splabel
);
3093 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->start_label
);
3094 COMPILE(ret
, "next val", node
->nd_stts
);
3095 add_ensure_iseq(ret
, iseq
);
3096 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->end_label
);
3097 ADD_ADJUST_RESTORE(ret
, splabel
);
3100 ADD_INSN(ret
, nd_line(node
), putnil
);
3103 else if (iseq
->type
== ISEQ_TYPE_EVAL
) {
3105 COMPILE_ERROR((ERROR_ARGS
"Can't escape from eval with next"));
3112 if (ip
->compile_data
->redo_label
!= 0) {
3116 else if (ip
->type
== ISEQ_TYPE_BLOCK
) {
3120 else if (ip
->type
== ISEQ_TYPE_EVAL
) {
3123 ip
= ip
->parent_iseq
;
3126 COMPILE(ret
, "next val", node
->nd_stts
);
3127 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(level
| 0x03) /* TAG_NEXT */ );
3130 ADD_INSN(ret
, nd_line(node
), pop
);
3134 COMPILE_ERROR((ERROR_ARGS
"Invalid next"));
3140 if (iseq
->compile_data
->redo_label
) {
3141 LABEL
*splabel
= NEW_LABEL(0);
3142 debugs("redo in while");
3143 ADD_LABEL(ret
, splabel
);
3144 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->redo_label
);
3145 add_ensure_iseq(ret
, iseq
);
3146 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->redo_label
);
3147 ADD_ADJUST_RESTORE(ret
, splabel
);
3149 else if (iseq
->type
== ISEQ_TYPE_EVAL
) {
3151 COMPILE_ERROR((ERROR_ARGS
"Can't escape from eval with redo"));
3153 else if (iseq
->compile_data
->start_label
) {
3154 LABEL
*splabel
= NEW_LABEL(0);
3156 debugs("redo in block");
3157 ADD_LABEL(ret
, splabel
);
3158 add_ensure_iseq(ret
, iseq
);
3159 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->start_label
);
3160 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->start_label
);
3161 ADD_ADJUST_RESTORE(ret
, splabel
);
3164 ADD_INSN(ret
, nd_line(node
), putnil
);
3169 unsigned long level
;
3170 level
= 0x8000 | 0x4000;
3173 if (ip
->compile_data
->redo_label
!= 0) {
3176 else if (ip
->type
== ISEQ_TYPE_BLOCK
) {
3179 else if (ip
->type
== ISEQ_TYPE_EVAL
) {
3182 ip
= ip
->parent_iseq
;
3185 ADD_INSN(ret
, nd_line(node
), putnil
);
3186 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(level
| 0x05) /* TAG_REDO */ );
3189 ADD_INSN(ret
, nd_line(node
), pop
);
3193 COMPILE_ERROR((ERROR_ARGS
"Invalid redo"));
3199 if (iseq
->type
== ISEQ_TYPE_RESCUE
) {
3200 ADD_INSN(ret
, nd_line(node
), putnil
);
3201 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(0x04) /* TAG_RETRY */ );
3204 ADD_INSN(ret
, nd_line(node
), pop
);
3208 COMPILE_ERROR((ERROR_ARGS
"Invalid retry"));
3213 COMPILE_(ret
, "NODE_BEGIN", node
->nd_body
, poped
);
3217 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
3218 LABEL
*lend
= NEW_LABEL(nd_line(node
));
3219 LABEL
*lcont
= NEW_LABEL(nd_line(node
));
3220 VALUE rescue
= NEW_CHILD_ISEQVAL(
3222 rb_str_concat(rb_str_new2("rescue in "), iseq
->name
),
3225 ADD_LABEL(ret
, lstart
);
3226 COMPILE(ret
, "rescue head", node
->nd_head
);
3227 ADD_LABEL(ret
, lend
);
3228 if (node
->nd_else
) {
3229 ADD_INSN(ret
, nd_line(node
), pop
);
3230 COMPILE(ret
, "rescue else", node
->nd_else
);
3232 ADD_INSN(ret
, nd_line(node
), nop
);
3233 ADD_LABEL(ret
, lcont
);
3236 ADD_INSN(ret
, nd_line(node
), pop
);
3239 /* resgister catch entry */
3240 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE
, lstart
, lend
, rescue
, lcont
);
3241 ADD_CATCH_ENTRY(CATCH_TYPE_RETRY
, lend
, lcont
, 0, lstart
);
3247 LABEL
*label_miss
, *label_hit
;
3250 label_miss
= NEW_LABEL(nd_line(node
));
3251 label_hit
= NEW_LABEL(nd_line(node
));
3253 narg
= resq
->nd_args
;
3255 switch (nd_type(narg
)) {
3258 COMPILE(ret
, "rescue arg", narg
->nd_head
);
3259 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(1),
3261 ADD_SEND(ret
, nd_line(node
), ID2SYM(idEqq
), INT2FIX(1));
3262 ADD_INSNL(ret
, nd_line(node
), branchif
, label_hit
);
3263 narg
= narg
->nd_next
;
3269 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(1),
3271 COMPILE(ret
, "rescue/cond splat", narg
);
3272 ADD_INSN1(ret
, nd_line(node
), checkincludearray
, Qtrue
);
3273 ADD_INSN(ret
, nd_line(node
), swap
);
3274 ADD_INSN(ret
, nd_line(node
), pop
);
3275 ADD_INSNL(ret
, nd_line(node
), branchif
, label_hit
);
3278 rb_bug("NODE_RESBODY: unknown node (%s)",
3279 ruby_node_name(nd_type(narg
)));
3283 ADD_INSN1(ret
, nd_line(node
), putobject
,
3285 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(1),
3287 ADD_SEND(ret
, nd_line(node
), ID2SYM(idEqq
), INT2FIX(1));
3288 ADD_INSNL(ret
, nd_line(node
), branchif
, label_hit
);
3290 ADD_INSNL(ret
, nd_line(node
), jump
, label_miss
);
3291 ADD_LABEL(ret
, label_hit
);
3292 COMPILE(ret
, "resbody body", resq
->nd_body
);
3293 if (iseq
->compile_data
->option
->tailcall_optimization
) {
3294 ADD_INSN(ret
, nd_line(node
), nop
);
3296 ADD_INSN(ret
, nd_line(node
), leave
);
3297 ADD_LABEL(ret
, label_miss
);
3298 resq
= resq
->nd_head
;
3304 VALUE ensure
= NEW_CHILD_ISEQVAL(node
->nd_ensr
,
3305 rb_str_concat(rb_str_new2
3309 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
3310 LABEL
*lend
= NEW_LABEL(nd_line(node
));
3311 LABEL
*lcont
= NEW_LABEL(nd_line(node
));
3312 struct ensure_range er
= { 0 };
3313 struct iseq_compile_data_ensure_node_stack enl
;
3314 struct ensure_range
*erange
;
3319 enl
.ensure_node
= node
->nd_ensr
;
3320 enl
.prev
= iseq
->compile_data
->ensure_node_stack
; /* prev */
3322 COMPILE_POPED(ensr
, "ensure ensr", node
->nd_ensr
);
3324 iseq
->compile_data
->ensure_node_stack
= &enl
;
3326 ADD_LABEL(ret
, lstart
);
3327 COMPILE_(ret
, "ensure head", node
->nd_head
, poped
);
3328 ADD_LABEL(ret
, lend
);
3329 if (ensr
->anchor
.next
== 0) {
3330 ADD_INSN(ret
, nd_line(node
), nop
);
3335 ADD_LABEL(ret
, lcont
);
3337 erange
= iseq
->compile_data
->ensure_node_stack
->erange
;
3339 ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE
, erange
->begin
, erange
->end
,
3341 erange
= erange
->next
;
3343 iseq
->compile_data
->ensure_node_stack
= enl
.prev
;
3349 LABEL
*end_label
= NEW_LABEL(nd_line(node
));
3350 COMPILE(ret
, "nd_1st", node
->nd_1st
);
3352 ADD_INSN(ret
, nd_line(node
), dup
);
3354 if (type
== NODE_AND
) {
3355 ADD_INSNL(ret
, nd_line(node
), branchunless
, end_label
);
3358 ADD_INSNL(ret
, nd_line(node
), branchif
, end_label
);
3361 ADD_INSN(ret
, nd_line(node
), pop
);
3363 COMPILE_(ret
, "nd_2nd", node
->nd_2nd
, poped
);
3364 ADD_LABEL(ret
, end_label
);
3369 compile_massign(iseq
, ret
, node
, poped
);
3374 ID id
= node
->nd_vid
;
3375 int idx
= iseq
->local_iseq
->local_size
- get_local_var_idx(iseq
, id
);
3377 debugs("lvar: %s idx: %d\n", rb_id2name(id
), idx
);
3378 COMPILE(ret
, "rvalue", node
->nd_value
);
3381 ADD_INSN(ret
, nd_line(node
), dup
);
3383 ADD_INSN1(ret
, nd_line(node
), setlocal
, INT2FIX(idx
));
3388 case NODE_DASGN_CURR
:{
3390 COMPILE(ret
, "dvalue", node
->nd_value
);
3391 debugp_param("dassn id", rb_str_new2(rb_id2name(node
->nd_vid
) ? rb_id2name(node
->nd_vid
) : "*"));
3394 ADD_INSN(ret
, nd_line(node
), dup
);
3397 idx
= get_dyna_var_idx(iseq
, node
->nd_vid
, &lv
, &ls
);
3400 rb_bug("NODE_DASGN(_CURR): unknown id (%s)", rb_id2name(node
->nd_vid
));
3403 ADD_INSN2(ret
, nd_line(node
), setdynamic
,
3404 INT2FIX(ls
- idx
), INT2FIX(lv
));
3408 COMPILE(ret
, "lvalue", node
->nd_value
);
3411 ADD_INSN(ret
, nd_line(node
), dup
);
3413 ADD_INSN1(ret
, nd_line(node
), setglobal
,
3414 (((long)node
->nd_entry
) | 1));
3419 COMPILE(ret
, "lvalue", node
->nd_value
);
3421 ADD_INSN(ret
, nd_line(node
), dup
);
3423 ADD_INSN1(ret
, nd_line(node
), setinstancevariable
,
3424 ID2SYM(node
->nd_vid
));
3428 COMPILE(ret
, "lvalue", node
->nd_value
);
3431 ADD_INSN(ret
, nd_line(node
), dup
);
3435 ADD_INSN(ret
, nd_line(node
), putnil
);
3436 ADD_INSN1(ret
, nd_line(node
), setconstant
,
3437 ID2SYM(node
->nd_vid
));
3440 compile_cpath(ret
, iseq
, node
->nd_else
);
3441 ADD_INSN1(ret
, nd_line(node
), setconstant
,
3442 ID2SYM(node
->nd_else
->nd_mid
));
3447 COMPILE(ret
, "cvasgn val", node
->nd_value
);
3449 ADD_INSN(ret
, nd_line(node
), dup
);
3451 ADD_INSN1(ret
, nd_line(node
), setclassvariable
,
3452 ID2SYM(node
->nd_vid
));
3455 case NODE_OP_ASGN1
: {
3458 unsigned long flag
= 0;
3459 ID id
= node
->nd_mid
;
3467 * send :[] # a x a[x]
3468 * eval y # a x a[x] y
3469 * send op # a x a[x]+y
3474 * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head;
3475 * NODE_OP_ASGN nd_recv
3481 COMPILE(ret
, "NODE_OP_ASGN1 recv", node
->nd_recv
);
3482 if (nd_type(node
->nd_args
->nd_body
) != NODE_ZARRAY
) {
3484 argc
= setup_args(iseq
, args
, node
->nd_args
->nd_body
, &flag
);
3490 ADD_INSN1(ret
, nd_line(node
), dupn
, INT2FIX(FIX2INT(argc
)+1));
3491 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idAREF
), argc
, Qfalse
, LONG2FIX(flag
));
3493 if (id
== 0 || id
== 1) {
3503 LABEL
*label
= NEW_LABEL(nd_line(node
));
3504 LABEL
*lfin
= NEW_LABEL(nd_line(node
));
3508 ADD_INSN(ret
, nd_line(node
), dup
);
3509 ADD_INSNL(ret
, nd_line(node
), branchif
, label
);
3510 ADD_INSN(ret
, nd_line(node
), pop
);
3514 ADD_INSNL(ret
, nd_line(node
), branchunless
, label
);
3517 COMPILE(ret
, "NODE_OP_ASGN1 args->head: ", node
->nd_args
->nd_head
);
3518 if (flag
& VM_CALL_ARGS_SPLAT_BIT
) {
3519 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(1));
3520 ADD_INSN(ret
, nd_line(node
), concatarray
);
3521 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idASET
),
3522 argc
, Qfalse
, LONG2FIX(flag
));
3525 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idASET
),
3526 INT2FIX(FIX2INT(argc
) + 1), Qfalse
, LONG2FIX(flag
));
3528 ADD_INSNL(ret
, nd_line(node
), jump
, lfin
);
3529 ADD_LABEL(ret
, label
);
3530 if (id
== 0) { /* or */
3531 ADD_INSN(ret
, nd_line(node
), swap
);
3532 ADD_INSN(ret
, nd_line(node
), pop
);
3533 ADD_INSN(ret
, nd_line(node
), swap
);
3534 ADD_INSN(ret
, nd_line(node
), pop
);
3536 else if (id
== 1) { /* and */
3537 ADD_INSN(ret
, nd_line(node
), pop
);
3538 ADD_INSN(ret
, nd_line(node
), pop
);
3539 ADD_INSN(ret
, nd_line(node
), putnil
);
3541 ADD_LABEL(ret
, lfin
);
3544 COMPILE(ret
, "NODE_OP_ASGN1 args->head: ", node
->nd_args
->nd_head
);
3545 ADD_SEND(ret
, nd_line(node
), ID2SYM(id
), INT2FIX(1));
3546 if (flag
& VM_CALL_ARGS_SPLAT_BIT
) {
3547 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(1));
3548 ADD_INSN(ret
, nd_line(node
), concatarray
);
3549 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idASET
),
3550 argc
, Qfalse
, LONG2FIX(flag
));
3553 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idASET
),
3554 INT2FIX(FIX2INT(argc
) + 1), Qfalse
, LONG2FIX(flag
));
3559 ADD_INSN(ret
, nd_line(node
), pop
);
3564 case NODE_OP_ASGN2
:{
3565 ID atype
= node
->nd_next
->nd_mid
;
3566 LABEL
*lfin
= NEW_LABEL(nd_line(node
));
3567 LABEL
*lcfin
= NEW_LABEL(nd_line(node
));
3569 class C; attr_accessor :c; end
3606 COMPILE(ret
, "NODE_OP_ASGN2#recv", node
->nd_recv
);
3607 ADD_INSN(ret
, nd_line(node
), dup
);
3608 ADD_SEND(ret
, nd_line(node
), ID2SYM(node
->nd_next
->nd_vid
),
3611 if (atype
== 0 || atype
== 1) { /* 0: OR or 1: AND */
3612 ADD_INSN(ret
, nd_line(node
), dup
);
3614 ADD_INSNL(ret
, nd_line(node
), branchif
, lcfin
);
3617 ADD_INSNL(ret
, nd_line(node
), branchunless
, lcfin
);
3619 ADD_INSN(ret
, nd_line(node
), pop
);
3620 COMPILE(ret
, "NODE_OP_ASGN2 val", node
->nd_value
);
3621 ADD_SEND(ret
, nd_line(node
), ID2SYM(node
->nd_next
->nd_aid
),
3623 ADD_INSNL(ret
, nd_line(node
), jump
, lfin
);
3625 ADD_LABEL(ret
, lcfin
);
3626 ADD_INSN(ret
, nd_line(node
), swap
);
3627 ADD_INSN(ret
, nd_line(node
), pop
);
3629 ADD_LABEL(ret
, lfin
);
3632 COMPILE(ret
, "NODE_OP_ASGN2 val", node
->nd_value
);
3633 ADD_SEND(ret
, nd_line(node
), ID2SYM(node
->nd_next
->nd_mid
),
3635 ADD_SEND(ret
, nd_line(node
), ID2SYM(node
->nd_next
->nd_aid
),
3640 /* we can apply more optimize */
3641 ADD_INSN(ret
, nd_line(node
), pop
);
3645 case NODE_OP_ASGN_AND
:
3646 case NODE_OP_ASGN_OR
:{
3647 LABEL
*lfin
= NEW_LABEL(nd_line(node
));
3650 if (nd_type(node
) == NODE_OP_ASGN_OR
) {
3654 defined_expr(iseq
, ret
, node
->nd_head
, lfinish
, Qfalse
);
3655 lassign
= lfinish
[1];
3657 lassign
= NEW_LABEL(nd_line(node
));
3659 ADD_INSNL(ret
, nd_line(node
), branchunless
, lassign
);
3662 lassign
= NEW_LABEL(nd_line(node
));
3665 COMPILE(ret
, "NODE_OP_ASGN_AND/OR#nd_head", node
->nd_head
);
3666 ADD_INSN(ret
, nd_line(node
), dup
);
3668 if (nd_type(node
) == NODE_OP_ASGN_AND
) {
3669 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfin
);
3672 ADD_INSNL(ret
, nd_line(node
), branchif
, lfin
);
3675 ADD_INSN(ret
, nd_line(node
), pop
);
3676 ADD_LABEL(ret
, lassign
);
3677 COMPILE(ret
, "NODE_OP_ASGN_AND/OR#nd_value", node
->nd_value
);
3678 ADD_LABEL(ret
, lfin
);
3681 /* we can apply more optimize */
3682 ADD_INSN(ret
, nd_line(node
), pop
);
3688 case NODE_VCALL
:{ /* VCALL: variable or call */
3690 call: obj.method(...)
3696 ID mid
= node
->nd_mid
;
3698 unsigned long flag
= 0;
3699 VALUE parent_block
= iseq
->compile_data
->current_block
;
3700 iseq
->compile_data
->current_block
= Qfalse
;
3705 if (nd_type(node
) == NODE_VCALL
) {
3706 if (mid
== idBitblt
) {
3707 ADD_INSN(ret
, nd_line(node
), bitblt
);
3710 else if (mid
== idAnswer
) {
3711 ADD_INSN(ret
, nd_line(node
), answer
);
3723 goto_id
= rb_intern("__goto__");
3724 label_id
= rb_intern("__label__");
3727 if (nd_type(node
) == NODE_FCALL
&&
3728 (mid
== goto_id
|| mid
== label_id
)) {
3729 if (nd_type(node
->nd_args
->nd_head
) == NODE_LIT
&&
3730 SYMBOL_P(node
->nd_args
->nd_head
->nd_lit
)) {
3732 label_sym
= label
= node
->nd_args
->nd_head
->nd_lit
;
3734 rb_hash_aref(iseq
->compile_data
,
3735 label_sym
)) == Qnil
) {
3736 rb_hash_aset(iseq
->compile_data
, label_sym
,
3737 label
= NEW_LABEL(nd_line(node
)));
3741 rb_bug("invalid goto/label format");
3745 if (mid
== goto_id
) {
3746 ADD_INSNL(ret
, nd_line(node
), jump
, label
);
3749 ADD_LABEL(ret
, label
);
3756 if (type
== NODE_CALL
) {
3757 COMPILE(recv
, "recv", node
->nd_recv
);
3759 else if (type
== NODE_FCALL
|| type
== NODE_VCALL
) {
3760 ADD_CALL_RECEIVER(recv
, nd_line(node
));
3764 if (nd_type(node
) != NODE_VCALL
) {
3765 argc
= setup_args(iseq
, args
, node
->nd_args
, &flag
);
3774 debugp_param("call args argc", argc
);
3775 debugp_param("call method", ID2SYM(mid
));
3777 switch (nd_type(node
)) {
3779 flag
|= VM_CALL_VCALL_BIT
;
3780 /* VCALL is funcall, so fall through */
3782 flag
|= VM_CALL_FCALL_BIT
;
3785 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(mid
),
3786 argc
, parent_block
, LONG2FIX(flag
));
3789 ADD_INSN(ret
, nd_line(node
), pop
);
3797 unsigned long flag
= 0;
3798 VALUE parent_block
= iseq
->compile_data
->current_block
;
3801 iseq
->compile_data
->current_block
= Qfalse
;
3802 if (nd_type(node
) == NODE_SUPER
) {
3803 argc
= setup_args(iseq
, args
, node
->nd_args
, &flag
);
3808 rb_iseq_t
*liseq
= iseq
->local_iseq
;
3810 argc
= INT2FIX(liseq
->argc
);
3812 /* normal arguments */
3813 for (i
= 0; i
< liseq
->argc
; i
++) {
3814 int idx
= liseq
->local_size
- i
;
3815 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3818 if (!liseq
->arg_simple
) {
3819 if (liseq
->arg_opts
) {
3820 /* optional arguments */
3822 for (j
= 0; j
< liseq
->arg_opts
- 1; j
++) {
3823 int idx
= liseq
->local_size
- (i
+ j
);
3824 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3830 if (liseq
->arg_rest
!= -1) {
3832 int idx
= liseq
->local_size
- liseq
->arg_rest
;
3833 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3834 argc
= INT2FIX(liseq
->arg_rest
+ 1);
3835 flag
|= VM_CALL_ARGS_SPLAT_BIT
;
3838 if (liseq
->arg_post_len
) {
3839 /* post arguments */
3840 int post_len
= liseq
->arg_post_len
;
3841 int post_start
= liseq
->arg_post_start
;
3843 if (liseq
->arg_rest
!= -1) {
3845 for (j
=0; j
<post_len
; j
++) {
3846 int idx
= liseq
->local_size
- (post_start
+ j
);
3847 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3849 ADD_INSN1(args
, nd_line(node
), newarray
, INT2FIX(j
));
3850 ADD_INSN (args
, nd_line(node
), concatarray
);
3851 /* argc is setteled at above */
3855 for (j
=0; j
<post_len
; j
++) {
3856 int idx
= liseq
->local_size
- (post_start
+ j
);
3857 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3859 argc
= INT2FIX(post_len
+ post_start
);
3865 /* dummy reciever */
3866 ADD_INSN1(ret
, nd_line(node
), putobject
,
3867 nd_type(node
) == NODE_ZSUPER
? Qfalse
: Qtrue
);
3869 ADD_INSN3(ret
, nd_line(node
), invokesuper
,
3870 argc
, parent_block
, LONG2FIX(flag
));
3873 ADD_INSN(ret
, nd_line(node
), pop
);
3878 compile_array_(iseq
, ret
, node
, Qtrue
, poped
);
3883 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(0));
3890 COMPILE(ret
, "values item", n
->nd_head
);
3893 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(node
->nd_alen
));
3895 ADD_INSN(ret
, nd_line(node
), pop
);
3902 int type
= node
->nd_head
? nd_type(node
->nd_head
) : NODE_ZARRAY
;
3907 compile_array(iseq
, list
, node
->nd_head
, Qfalse
);
3908 size
= OPERAND_AT(POP_ELEMENT(list
), 0);
3917 rb_bug("can't make hash with this node: %s", ruby_node_name(type
));
3920 ADD_INSN1(ret
, nd_line(node
), newhash
, size
);
3923 ADD_INSN(ret
, nd_line(node
), pop
);
3928 rb_iseq_t
*is
= iseq
;
3931 if (is
->type
== ISEQ_TYPE_TOP
|| is
->type
== ISEQ_TYPE_CLASS
) {
3932 COMPILE_ERROR((ERROR_ARGS
"Invalid return"));
3938 if (is
->type
== ISEQ_TYPE_METHOD
) {
3939 splabel
= NEW_LABEL(0);
3940 ADD_LABEL(ret
, splabel
);
3941 ADD_ADJUST(ret
, nd_line(node
), 0);
3944 COMPILE(ret
, "return nd_stts (return val)", node
->nd_stts
);
3946 if (is
->type
== ISEQ_TYPE_METHOD
) {
3947 add_ensure_iseq(ret
, iseq
);
3948 ADD_INSN(ret
, nd_line(node
), leave
);
3949 ADD_ADJUST_RESTORE(ret
, splabel
);
3952 ADD_INSN(ret
, nd_line(node
), putnil
);
3956 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(0x01) /* TAG_RETURN */ );
3958 ADD_INSN(ret
, nd_line(node
), pop
);
3969 unsigned long flag
= 0;
3972 if (iseq
->type
== ISEQ_TYPE_TOP
|| iseq
->type
== ISEQ_TYPE_CLASS
) {
3973 COMPILE_ERROR((ERROR_ARGS
"Invalid yield"));
3976 if (node
->nd_head
) {
3977 argc
= setup_args(iseq
, args
, node
->nd_head
, &flag
);
3984 ADD_INSN2(ret
, nd_line(node
), invokeblock
, argc
, LONG2FIX(flag
));
3987 ADD_INSN(ret
, nd_line(node
), pop
);
3993 ID id
= node
->nd_vid
;
3994 int idx
= iseq
->local_iseq
->local_size
- get_local_var_idx(iseq
, id
);
3996 debugs("id: %s idx: %d\n", rb_id2name(id
), idx
);
3997 ADD_INSN1(ret
, nd_line(node
), getlocal
, INT2FIX(idx
));
4003 debugi("nd_vid", node
->nd_vid
);
4005 idx
= get_dyna_var_idx(iseq
, node
->nd_vid
, &lv
, &ls
);
4007 rb_bug("unknown dvar (%s)", rb_id2name(node
->nd_vid
));
4009 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(ls
- idx
),
4015 ADD_INSN1(ret
, nd_line(node
), getglobal
,
4016 (((long)node
->nd_entry
) | 1));
4018 ADD_INSN(ret
, nd_line(node
), pop
);
4023 debugi("nd_vid", node
->nd_vid
);
4025 ADD_INSN1(ret
, nd_line(node
), getinstancevariable
,
4026 ID2SYM(node
->nd_vid
));
4031 debugi("nd_vid", node
->nd_vid
);
4033 if (iseq
->compile_data
->option
->inline_const_cache
) {
4034 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4035 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4037 ADD_LABEL(ret
, lstart
);
4038 ADD_INSN2(ret
, nd_line(node
), getinlinecache
, 0, lend
);
4039 ADD_INSN1(ret
, nd_line(node
), getconstant
, ID2SYM(node
->nd_vid
));
4040 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4041 ADD_LABEL(ret
, lend
);
4044 ADD_INSN(ret
, nd_line(node
), putnil
);
4045 ADD_INSN1(ret
, nd_line(node
), getconstant
, ID2SYM(node
->nd_vid
));
4049 ADD_INSN(ret
, nd_line(node
), pop
);
4055 ADD_INSN1(ret
, nd_line(node
), getclassvariable
,
4056 ID2SYM(node
->nd_vid
));
4062 ADD_INSN2(ret
, nd_line(node
), getspecial
, INT2FIX(1) /* '~' */,
4063 INT2FIX(node
->nd_nth
<< 1));
4067 case NODE_BACK_REF
:{
4069 ADD_INSN2(ret
, nd_line(node
), getspecial
, INT2FIX(1) /* '~' */,
4070 INT2FIX(0x01 | (node
->nd_nth
<< 1)));
4082 switch(nd_type(node
)) {
4084 ADD_INSN1(recv
, nd_line(node
), putobject
, node
->nd_lit
);
4085 ADD_INSN2(val
, nd_line(node
), getspecial
, INT2FIX(0),
4089 COMPILE(recv
, "reciever", node
->nd_recv
);
4090 COMPILE(val
, "value", node
->nd_value
);
4093 COMPILE(recv
, "reciever", node
->nd_value
);
4094 COMPILE(val
, "value", node
->nd_recv
);
4098 if (iseq
->compile_data
->option
->specialized_instruction
) {
4099 /* TODO: detect by node */
4100 if (recv
->last
== recv
->anchor
.next
&&
4101 INSN_OF(recv
->last
) == BIN(putobject
) &&
4102 nd_type(node
) == NODE_MATCH2
) {
4104 ADD_INSN1(ret
, nd_line(node
), opt_regexpmatch1
,
4105 OPERAND_AT(recv
->last
, 0));
4110 ADD_INSN(ret
, nd_line(node
), opt_regexpmatch2
);
4116 ADD_SEND(ret
, nd_line(node
), ID2SYM(idEqTilde
), INT2FIX(1));
4120 ADD_INSN(ret
, nd_line(node
), pop
);
4125 debugp_param("lit", node
->nd_lit
);
4127 ADD_INSN1(ret
, nd_line(node
), putobject
, node
->nd_lit
);
4132 debugp_param("nd_lit", node
->nd_lit
);
4134 ADD_INSN1(ret
, nd_line(node
), putstring
, node
->nd_lit
);
4139 compile_dstr(iseq
, ret
, node
);
4142 ADD_INSN(ret
, nd_line(node
), pop
);
4147 ADD_CALL_RECEIVER(ret
, nd_line(node
));
4148 ADD_INSN1(ret
, nd_line(node
), putobject
, node
->nd_lit
);
4149 ADD_CALL(ret
, nd_line(node
), ID2SYM(idBackquote
), INT2FIX(1));
4152 ADD_INSN(ret
, nd_line(node
), pop
);
4157 ADD_CALL_RECEIVER(ret
, nd_line(node
));
4158 compile_dstr(iseq
, ret
, node
);
4159 ADD_CALL(ret
, nd_line(node
), ID2SYM(idBackquote
), INT2FIX(1));
4162 ADD_INSN(ret
, nd_line(node
), pop
);
4167 COMPILE(ret
, "nd_body", node
->nd_body
);
4170 ADD_INSN(ret
, nd_line(node
), pop
);
4173 ADD_INSN(ret
, nd_line(node
), tostring
);
4178 compile_dregx(iseq
, ret
, node
);
4181 ADD_INSN(ret
, nd_line(node
), pop
);
4185 case NODE_DREGX_ONCE
:{
4187 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4188 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4190 ADD_LABEL(ret
, lstart
);
4191 ADD_INSN2(ret
, nd_line(node
), onceinlinecache
, 0, lend
);
4192 ADD_INSN(ret
, nd_line(node
), pop
);
4194 compile_dregx(iseq
, ret
, node
);
4196 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4197 ADD_LABEL(ret
, lend
);
4200 ADD_INSN(ret
, nd_line(node
), pop
);
4205 COMPILE(ret
, "argscat head", node
->nd_head
);
4206 COMPILE(ret
, "argscat body", node
->nd_body
);
4207 ADD_INSN(ret
, nd_line(node
), concatarray
);
4210 case NODE_ARGSPUSH
:{
4211 COMPILE(ret
, "arsgpush head", node
->nd_head
);
4212 COMPILE(ret
, "argspush body", node
->nd_body
);
4213 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(1));
4214 ADD_INSN(ret
, nd_line(node
), concatarray
);
4218 COMPILE(ret
, "splat", node
->nd_head
);
4219 ADD_INSN1(ret
, nd_line(node
), splatarray
, Qfalse
);
4222 ADD_INSN(ret
, nd_line(node
), pop
);
4227 VALUE iseqval
= NEW_ISEQVAL(node
->nd_defn
,
4228 rb_str_dup(rb_id2str(node
->nd_mid
)),
4231 debugp_param("defn/iseq", iseqval
);
4233 ADD_INSN (ret
, nd_line(node
), putnil
);
4234 ADD_INSN3(ret
, nd_line(node
), definemethod
,
4235 ID2SYM(node
->nd_mid
), iseqval
, INT2FIX(0));
4237 ADD_INSN(ret
, nd_line(node
), putnil
);
4239 debugp_param("defn", iseqval
);
4243 VALUE iseqval
= NEW_ISEQVAL(node
->nd_defn
,
4244 rb_str_dup(rb_id2str(node
->nd_mid
)),
4247 debugp_param("defs/iseq", iseqval
);
4249 COMPILE(ret
, "defs: recv", node
->nd_recv
);
4250 ADD_INSN3(ret
, nd_line(node
), definemethod
,
4251 ID2SYM(node
->nd_mid
), iseqval
, INT2FIX(1));
4253 ADD_INSN(ret
, nd_line(node
), putnil
);
4258 COMPILE(ret
, "alias arg1", node
->u1
.node
);
4259 COMPILE(ret
, "alias arg2", node
->u2
.node
);
4261 ADD_INSN1(ret
, nd_line(node
), alias
, Qfalse
);
4264 ADD_INSN(ret
, nd_line(node
), putnil
);
4269 ADD_INSN1(ret
, nd_line(node
), putobject
, ID2SYM(node
->u1
.id
));
4270 ADD_INSN1(ret
, nd_line(node
), putobject
, ID2SYM(node
->u2
.id
));
4271 ADD_INSN1(ret
, nd_line(node
), alias
, Qtrue
);
4274 ADD_INSN(ret
, nd_line(node
), putnil
);
4279 COMPILE(ret
, "undef arg", node
->u2
.node
);
4280 ADD_INSN(ret
, nd_line(node
), undef
);
4283 ADD_INSN(ret
, nd_line(node
), putnil
);
4291 rb_sprintf("<class:%s>", rb_id2name(node
->nd_cpath
->nd_mid
)),
4293 compile_cpath(ret
, iseq
, node
->nd_cpath
);
4294 COMPILE(ret
, "super", node
->nd_super
);
4295 ADD_INSN3(ret
, nd_line(node
), defineclass
,
4296 ID2SYM(node
->nd_cpath
->nd_mid
), iseqval
, INT2FIX(0));
4299 ADD_INSN(ret
, nd_line(node
), pop
);
4304 VALUE iseqval
= NEW_CHILD_ISEQVAL(
4306 rb_sprintf("<module:%s>", rb_id2name(node
->nd_cpath
->nd_mid
)),
4309 COMPILE(ret
, "mbase", node
->nd_cpath
->nd_head
);
4310 ADD_INSN (ret
, nd_line(node
), putnil
); /* dummy */
4311 ADD_INSN3(ret
, nd_line(node
), defineclass
,
4312 ID2SYM(node
->nd_cpath
->nd_mid
), iseqval
, INT2FIX(2));
4314 ADD_INSN(ret
, nd_line(node
), pop
);
4320 NEW_ISEQVAL(node
->nd_body
, rb_str_new2("singletonclass"),
4323 COMPILE(ret
, "sclass#recv", node
->nd_recv
);
4324 ADD_INSN (ret
, nd_line(node
), putnil
);
4325 ADD_INSN3(ret
, nd_line(node
), defineclass
,
4326 ID2SYM(rb_intern("singletonclass")), iseqval
, INT2FIX(1));
4329 ADD_INSN(ret
, nd_line(node
), pop
);
4334 if (rb_is_const_id(node
->nd_mid
)) {
4336 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4337 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4343 compile_colon2(iseq
, node
, pref
, body
);
4344 if (LIST_SIZE_ZERO(pref
)) {
4345 if (iseq
->compile_data
->option
->inline_const_cache
) {
4346 ADD_LABEL(ret
, lstart
);
4347 ADD_INSN2(ret
, nd_line(node
), getinlinecache
, 0, lend
);
4350 ADD_INSN(ret
, nd_line(node
), putnil
);
4355 if (iseq
->compile_data
->option
->inline_const_cache
) {
4356 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4357 ADD_LABEL(ret
, lend
);
4367 ADD_CALL_RECEIVER(ret
, nd_line(node
));
4368 COMPILE(ret
, "colon2#nd_head", node
->nd_head
);
4369 ADD_CALL(ret
, nd_line(node
), ID2SYM(node
->nd_mid
),
4373 ADD_INSN(ret
, nd_line(node
), pop
);
4378 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4379 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4380 debugi("colon3#nd_mid", node
->nd_mid
);
4382 /* add cache insn */
4383 if (iseq
->compile_data
->option
->inline_const_cache
) {
4384 ADD_LABEL(ret
, lstart
);
4385 ADD_INSN2(ret
, nd_line(node
), getinlinecache
, 0, lend
);
4386 ADD_INSN(ret
, nd_line(node
), pop
);
4389 ADD_INSN1(ret
, nd_line(node
), putobject
, rb_cObject
);
4390 ADD_INSN1(ret
, nd_line(node
), getconstant
, ID2SYM(node
->nd_mid
));
4392 if (iseq
->compile_data
->option
->inline_const_cache
) {
4393 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4394 ADD_LABEL(ret
, lend
);
4398 ADD_INSN(ret
, nd_line(node
), pop
);
4404 int flag
= type
== NODE_DOT2
? INT2FIX(0) : INT2FIX(1);
4405 COMPILE(ret
, "min", (NODE
*) node
->nd_beg
);
4406 COMPILE(ret
, "max", (NODE
*) node
->nd_end
);
4408 ADD_INSN(ret
, nd_line(node
), pop
);
4409 ADD_INSN(ret
, nd_line(node
), pop
);
4412 ADD_INSN1(ret
, nd_line(node
), newrange
, flag
);
4418 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4419 LABEL
*lfin
= NEW_LABEL(nd_line(node
));
4420 LABEL
*ltrue
= NEW_LABEL(nd_line(node
));
4421 VALUE key
= rb_sprintf("flipflag/%s-%p-%d",
4422 RSTRING_PTR(iseq
->name
), iseq
,
4423 iseq
->compile_data
->flip_cnt
++);
4425 iseq_add_mark_object_compile_time(iseq
, key
);
4426 ADD_INSN2(ret
, nd_line(node
), getspecial
, key
, INT2FIX(0));
4427 ADD_INSNL(ret
, nd_line(node
), branchif
, lend
);
4430 COMPILE(ret
, "flip2 beg", node
->nd_beg
);
4431 ADD_INSN(ret
, nd_line(node
), dup
);
4432 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfin
);
4433 if (nd_type(node
) == NODE_FLIP3
) {
4434 ADD_INSN(ret
, nd_line(node
), dup
);
4435 ADD_INSN1(ret
, nd_line(node
), setspecial
, key
);
4436 ADD_INSNL(ret
, nd_line(node
), jump
, lfin
);
4439 ADD_INSN1(ret
, nd_line(node
), setspecial
, key
);
4443 ADD_LABEL(ret
, lend
);
4444 COMPILE(ret
, "flip2 end", node
->nd_end
);
4445 ADD_INSNL(ret
, nd_line(node
), branchunless
, ltrue
);
4446 ADD_INSN1(ret
, nd_line(node
), putobject
, Qfalse
);
4447 ADD_INSN1(ret
, nd_line(node
), setspecial
, key
);
4449 ADD_LABEL(ret
, ltrue
);
4450 ADD_INSN1(ret
, nd_line(node
), putobject
, Qtrue
);
4452 ADD_LABEL(ret
, lfin
);
4457 ADD_INSN(ret
, nd_line(node
), putself
);
4463 ADD_INSN(ret
, nd_line(node
), putnil
);
4469 ADD_INSN1(ret
, nd_line(node
), putobject
, Qtrue
);
4475 ADD_INSN1(ret
, nd_line(node
), putobject
, Qfalse
);
4481 if (iseq
->type
== ISEQ_TYPE_RESCUE
) {
4482 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(1),
4486 rb_iseq_t
*ip
= iseq
;
4489 if (ip
->type
== ISEQ_TYPE_RESCUE
) {
4492 ip
= ip
->parent_iseq
;
4496 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(1),
4500 ADD_INSN(ret
, nd_line(node
), putnil
);
4509 lfinish
[0] = NEW_LABEL(nd_line(node
));
4511 defined_expr(iseq
, ret
, node
->nd_head
, lfinish
, Qtrue
);
4513 ADD_INSNL(ret
, nd_line(node
), jump
, lfinish
[0]);
4514 ADD_LABEL(ret
, lfinish
[1]);
4515 ADD_INSN(ret
, nd_line(node
), putnil
);
4517 ADD_LABEL(ret
, lfinish
[0]);
4522 VALUE block
= NEW_CHILD_ISEQVAL(node
->nd_body
, make_name_for_block(iseq
), ISEQ_TYPE_BLOCK
);
4523 ADD_INSN1(ret
, nd_line(node
), postexe
, block
);
4525 ADD_INSN(ret
, nd_line(node
), putnil
);
4530 compile_dstr(iseq
, ret
, node
);
4532 ADD_SEND(ret
, nd_line(node
), ID2SYM(idIntern
), INT2FIX(0));
4535 ADD_INSN(ret
, nd_line(node
), pop
);
4539 case NODE_ATTRASGN
:{
4542 unsigned long flag
= 0;
4547 argc
= setup_args(iseq
, args
, node
->nd_args
, &flag
);
4549 if (node
->nd_recv
== (NODE
*) 1) {
4550 flag
|= VM_CALL_FCALL_BIT
;
4551 ADD_INSN(recv
, nd_line(node
), putself
);
4554 COMPILE(recv
, "recv", node
->nd_recv
);
4557 debugp_param("argc", argc
);
4558 debugp_param("nd_mid", ID2SYM(node
->nd_mid
));
4561 ADD_INSN(ret
, nd_line(node
), putnil
);
4565 if (flag
& VM_CALL_ARGS_BLOCKARG_BIT
) {
4566 ADD_INSN1(ret
, nd_line(node
), topn
, INT2FIX(1));
4567 ADD_INSN1(ret
, nd_line(node
), setn
, INT2FIX(FIX2INT(argc
) + 3));
4568 ADD_INSN (ret
, nd_line(node
), pop
);
4571 ADD_INSN1(ret
, nd_line(node
), setn
, INT2FIX(FIX2INT(argc
) + 1));
4578 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(node
->nd_mid
), argc
, 0, LONG2FIX(flag
));
4579 ADD_INSN(ret
, nd_line(node
), pop
);
4583 case NODE_OPTBLOCK
:{
4585 LABEL
*redo_label
= NEW_LABEL(0);
4586 LABEL
*next_label
= NEW_LABEL(0);
4588 iseq
->compile_data
->start_label
= next_label
;
4589 iseq
->compile_data
->redo_label
= redo_label
;
4591 ADD_LABEL(ret
, redo_label
);
4592 COMPILE_(ret
, "optblock body", node
->nd_head
, 1 /* pop */ );
4593 ADD_LABEL(ret
, next_label
);
4594 ADD_INSN(ret
, 0, opt_checkenv
);
4598 COMPILE_POPED(ret
, "prelude", node
->nd_head
);
4599 COMPILE_(ret
, "body", node
->nd_body
, poped
);
4603 /* compile same as lambda{...} */
4604 VALUE block
= NEW_CHILD_ISEQVAL(node
->nd_body
, make_name_for_block(iseq
), ISEQ_TYPE_BLOCK
);
4605 VALUE argc
= INT2FIX(0);
4606 ADD_CALL_RECEIVER(ret
, nd_line(node
));
4607 ADD_CALL_WITH_BLOCK(ret
, nd_line(node
), ID2SYM(idLambda
), argc
, block
);
4610 ADD_INSN(ret
, nd_line(node
), pop
);
4615 rb_bug("iseq_compile_each: unknown node: %s", ruby_node_name(type
));
4623 /***************************/
4624 /* instruction information */
4625 /***************************/
4628 insn_data_length(INSN
*iobj
)
4630 return insn_len(iobj
->insn_id
);
4634 calc_sp_depth(int depth
, INSN
*insn
)
4636 return insn_stack_increase(depth
, insn
->insn_id
, insn
->operands
);
4640 insn_data_line_no(INSN
*iobj
)
4642 return insn_len(iobj
->line_no
);
4646 insn_data_to_s_detail(INSN
*iobj
)
4648 VALUE str
= rb_str_new(0, 0);
4650 str
= rb_sprintf("%-16s", insn_name(iobj
->insn_id
));
4651 if (iobj
->operands
) {
4652 const char *types
= insn_op_types(iobj
->insn_id
);
4655 for (j
= 0; types
[j
]; j
++) {
4656 char type
= types
[j
];
4659 case TS_OFFSET
: /* label(destination position) */
4662 LABEL
*lobj
= (LABEL
*)OPERAND_AT(iobj
, j
);
4663 snprintf(buff
, sizeof(buff
), "<L%03d>", lobj
->label_no
);
4664 rb_str_concat(str
, rb_str_new2(buff
));
4668 case TS_ISEQ
: /* iseq */
4670 rb_iseq_t
*iseq
= (rb_iseq_t
*)OPERAND_AT(iobj
, j
);
4675 rb_str_concat(str
, rb_inspect(val
));
4680 case TS_NUM
: /* ulong */
4681 case TS_VALUE
: /* VALUE */
4682 rb_str_concat(str
, rb_inspect(OPERAND_AT(iobj
, j
)));
4684 case TS_ID
: /* ID */
4685 rb_str_concat(str
, rb_inspect(OPERAND_AT(iobj
, j
)));
4689 struct global_entry
*entry
= (struct global_entry
*)
4690 (OPERAND_AT(iobj
, j
) & (~1));
4691 rb_str_cat2(str
, rb_id2name(entry
->id
));
4693 case TS_IC
: /* method cache */
4694 rb_str_cat2(str
, "<ic>");
4696 case TS_CDHASH
: /* case/when condition cache */
4697 rb_str_cat2(str
, "<ch>");
4700 rb_raise(rb_eSyntaxError
, "unknown operand type: %c", type
);
4704 rb_str_cat2(str
, ", ");
4712 dump_disasm_list(struct iseq_link_element
*link
)
4719 printf("-- raw disasm--------\n");
4722 switch (link
->type
) {
4723 case ISEQ_ELEMENT_INSN
:
4725 iobj
= (INSN
*)link
;
4726 str
= insn_data_to_s_detail(iobj
);
4727 printf("%04d %-65s(%4d)\n", pos
, StringValueCStr(str
),
4728 insn_data_line_no(iobj
));
4729 pos
+= insn_data_length(iobj
);
4732 case ISEQ_ELEMENT_LABEL
:
4734 lobj
= (LABEL
*)link
;
4735 printf("<L%03d>\n", lobj
->label_no
);
4738 case ISEQ_ELEMENT_NONE
:
4743 case ISEQ_ELEMENT_ADJUST
:
4745 ADJUST
*adjust
= (ADJUST
*)link
;
4746 printf("adjust: [label: %d]\n", adjust
->label
->label_no
);
4751 rb_raise(rb_eSyntaxError
, "dump_disasm_list error: %ld\n", FIX2LONG(link
->type
));
4755 printf("---------------------\n");
4759 insns_name_array(void)
4761 VALUE ary
= rb_ary_new();
4763 for (i
= 0; i
< sizeof(insn_name_info
) / sizeof(insn_name_info
[0]); i
++) {
4764 rb_ary_push(ary
, rb_str_new2(insn_name_info
[i
]));
4770 register_label(rb_iseq_t
*iseq
, struct st_table
*labels_table
, VALUE obj
)
4774 obj
= rb_convert_type(obj
, T_SYMBOL
, "Symbol", "to_sym");
4776 if (st_lookup(labels_table
, obj
, &tmp
) == 0) {
4777 label
= NEW_LABEL(0);
4778 st_insert(labels_table
, obj
, (st_data_t
)label
);
4781 label
= (LABEL
*)tmp
;
4787 get_exception_sym2type(VALUE sym
)
4789 static VALUE symRescue
, symEnsure
, symRetry
;
4790 static VALUE symBreak
, symRedo
, symNext
;
4792 if (symRescue
== 0) {
4793 symRescue
= ID2SYM(rb_intern("rescue"));
4794 symEnsure
= ID2SYM(rb_intern("ensure"));
4795 symRetry
= ID2SYM(rb_intern("retry"));
4796 symBreak
= ID2SYM(rb_intern("break"));
4797 symRedo
= ID2SYM(rb_intern("redo"));
4798 symNext
= ID2SYM(rb_intern("next"));
4801 if (sym
== symRescue
) return CATCH_TYPE_RESCUE
;
4802 if (sym
== symEnsure
) return CATCH_TYPE_ENSURE
;
4803 if (sym
== symRetry
) return CATCH_TYPE_RETRY
;
4804 if (sym
== symBreak
) return CATCH_TYPE_BREAK
;
4805 if (sym
== symRedo
) return CATCH_TYPE_REDO
;
4806 if (sym
== symNext
) return CATCH_TYPE_NEXT
;
4807 rb_raise(rb_eSyntaxError
, "invalid exception symbol: %s",
4808 RSTRING_PTR(rb_inspect(sym
)));
4813 iseq_build_exception(rb_iseq_t
*iseq
, struct st_table
*labels_table
,
4818 for (i
=0; i
<RARRAY_LEN(exception
); i
++) {
4819 VALUE v
, type
, *ptr
, eiseqval
;
4820 LABEL
*lstart
, *lend
, *lcont
;
4823 RB_GC_GUARD(v
) = rb_convert_type(RARRAY_PTR(exception
)[i
], T_ARRAY
,
4825 if (RARRAY_LEN(v
) != 6) {
4826 rb_raise(rb_eSyntaxError
, "wrong exception entry");
4828 ptr
= RARRAY_PTR(v
);
4829 type
= get_exception_sym2type(ptr
[0]);
4830 if (ptr
[1] == Qnil
) {
4834 eiseqval
= iseq_load(0, ptr
[1], iseq
->self
, Qnil
);
4837 lstart
= register_label(iseq
, labels_table
, ptr
[2]);
4838 lend
= register_label(iseq
, labels_table
, ptr
[3]);
4839 lcont
= register_label(iseq
, labels_table
, ptr
[4]);
4840 sp
= NUM2INT(ptr
[5]);
4842 ADD_CATCH_ENTRY(type
, lstart
, lend
, eiseqval
, lcont
);
4847 struct st_table
*insn_make_insn_table(void);
4850 iseq_build_body(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
,
4851 VALUE body
, struct st_table
*labels_table
)
4853 /* TODO: body should be freezed */
4854 VALUE
*ptr
= RARRAY_PTR(body
);
4855 int len
= RARRAY_LEN(body
);
4859 * index -> LABEL *label
4861 static struct st_table
*insn_table
;
4863 if (insn_table
== 0) {
4864 insn_table
= insn_make_insn_table();
4867 for (i
=0; i
<len
; i
++) {
4870 if (SYMBOL_P(obj
)) {
4871 LABEL
*label
= register_label(iseq
, labels_table
, obj
);
4872 ADD_LABEL(anchor
, label
);
4874 else if (FIXNUM_P(obj
)) {
4875 line_no
= NUM2INT(obj
);
4877 else if (TYPE(obj
) == T_ARRAY
) {
4879 int argc
= RARRAY_LEN(obj
) - 1;
4883 insn
= (argc
< 0) ? Qnil
: RARRAY_PTR(obj
)[0];
4884 if (st_lookup(insn_table
, insn
, &insn_id
) == 0) {
4885 /* TODO: exception */
4886 RB_GC_GUARD(insn
) = rb_inspect(insn
);
4887 rb_compile_error(RSTRING_PTR(iseq
->filename
), line_no
,
4888 "unknown instruction: %s", RSTRING_PTR(insn
));
4891 if (argc
!= insn_len(insn_id
)-1) {
4892 rb_compile_error(RSTRING_PTR(iseq
->filename
), line_no
,
4893 "operand size mismatch");
4897 argv
= compile_data_alloc(iseq
, sizeof(VALUE
) * argc
);
4898 for (j
=0; j
<argc
; j
++) {
4899 VALUE op
= rb_ary_entry(obj
, j
+1);
4900 switch (insn_op_type(insn_id
, j
)) {
4902 LABEL
*label
= register_label(iseq
, labels_table
, op
);
4903 argv
[j
] = (VALUE
)label
;
4909 argv
[j
] = (NUM2INT(op
), op
);
4913 iseq_add_mark_object(iseq
, op
);
4918 if (TYPE(op
) == T_ARRAY
) {
4919 argv
[j
] = iseq_load(0, op
, iseq
->self
, Qnil
);
4921 else if (CLASS_OF(op
) == rb_cISeq
) {
4925 rb_raise(rb_eSyntaxError
, "ISEQ is required");
4927 iseq_add_mark_object(iseq
, argv
[j
]);
4935 op
= rb_convert_type(op
, T_SYMBOL
, "Symbol", "to_sym");
4936 argv
[j
] = (VALUE
)rb_global_entry(SYM2ID(op
));
4939 argv
[j
] = (VALUE
)NEW_INLINE_CACHE_ENTRY();
4940 iseq_add_mark_object(iseq
, argv
[j
]);
4943 argv
[j
] = rb_convert_type(op
, T_SYMBOL
,
4944 "Symbol", "to_sym");
4949 op
= rb_convert_type(op
, T_ARRAY
, "Array", "to_ary");
4950 for (i
=0; i
<RARRAY_LEN(op
); i
+=2) {
4951 VALUE sym
= rb_ary_entry(op
, i
+1);
4953 register_label(iseq
, labels_table
, sym
);
4954 rb_ary_store(op
, i
+1, (VALUE
)label
| 1);
4960 rb_raise(rb_eSyntaxError
, "unknown operand: %c", insn_op_type(insn_id
, j
));
4965 (LINK_ELEMENT
*)new_insn_core(iseq
, line_no
,
4966 insn_id
, argc
, argv
));
4969 rb_raise(rb_eTypeError
, "unexpected object for instruction");
4972 st_free_table(labels_table
);
4973 iseq_setup(iseq
, anchor
);
4977 #define CHECK_ARRAY(v) rb_convert_type(v, T_ARRAY, "Array", "to_ary")
4978 #define CHECK_STRING(v) rb_convert_type(v, T_STRING, "String", "to_str")
4979 #define CHECK_SYMBOL(v) rb_convert_type(v, T_SYMBOL, "Symbol", "to_sym")
4980 static inline VALUE
CHECK_INTEGER(VALUE v
) {NUM2LONG(v
); return v
;}
4983 iseq_build_from_ary(rb_iseq_t
*iseq
, VALUE locals
, VALUE args
,
4984 VALUE exception
, VALUE body
)
4989 struct st_table
*labels_table
= st_init_numtable();
4991 DECL_ANCHOR(anchor
);
4993 INIT_ANCHOR(anchor
);
4994 if (iseq
->type
== ISEQ_TYPE_METHOD
||
4995 iseq
->type
== ISEQ_TYPE_TOP
||
4996 iseq
->type
== ISEQ_TYPE_CLASS
) {
5000 iseq
->local_table_size
= opt
+ RARRAY_LEN(locals
);
5001 iseq
->local_table
= tbl
= (ID
*)ALLOC_N(ID
*, iseq
->local_table_size
);
5002 iseq
->local_size
= opt
+ iseq
->local_table_size
;
5004 for (i
=0; i
<RARRAY_LEN(locals
); i
++) {
5005 VALUE lv
= RARRAY_PTR(locals
)[i
];
5006 tbl
[i
] = FIXNUM_P(lv
) ? FIX2INT(lv
) : SYM2ID(CHECK_SYMBOL(lv
));
5010 if (FIXNUM_P(args
)) {
5011 iseq
->arg_size
= iseq
->argc
= FIX2INT(args
);
5012 iseq
->arg_simple
= 1;
5016 VALUE argc
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5017 VALUE arg_opt_labels
= CHECK_ARRAY(rb_ary_entry(args
, i
++));
5018 VALUE arg_post_len
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5019 VALUE arg_post_start
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5020 VALUE arg_rest
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5021 VALUE arg_block
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5022 VALUE arg_simple
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5024 iseq
->argc
= FIX2INT(argc
);
5025 iseq
->arg_rest
= FIX2INT(arg_rest
);
5026 iseq
->arg_post_len
= FIX2INT(arg_post_len
);
5027 iseq
->arg_post_start
= FIX2INT(arg_post_start
);
5028 iseq
->arg_block
= FIX2INT(arg_block
);
5029 iseq
->arg_opt_table
= (VALUE
*)ALLOC_N(VALUE
, RARRAY_LEN(arg_opt_labels
));
5031 if (iseq
->arg_block
!= -1) {
5032 iseq
->arg_size
= iseq
->arg_block
+ 1;
5034 else if (iseq
->arg_post_len
) {
5035 iseq
->arg_size
= iseq
->arg_post_start
+ iseq
->arg_post_len
;
5037 else if (iseq
->arg_rest
!= -1) {
5038 iseq
->arg_size
= iseq
->arg_rest
+ 1;
5041 iseq
->arg_size
= iseq
->argc
+ iseq
->arg_opts
;
5044 for (i
=0; i
<RARRAY_LEN(arg_opt_labels
); i
++) {
5045 iseq
->arg_opt_table
[i
] =
5046 (VALUE
)register_label(iseq
, labels_table
,
5047 rb_ary_entry(arg_opt_labels
, i
));
5050 iseq
->arg_simple
= NUM2INT(arg_simple
);
5054 iseq_build_exception(iseq
, labels_table
, exception
);
5057 iseq_build_body(iseq
, anchor
, body
, labels_table
);