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 (nd_type(cpath
) == NODE_COLON3
) {
2287 /* toplevel class ::Foo */
2288 ADD_INSN1(ret
, nd_line(cpath
), putobject
, rb_cObject
);
2290 else if (cpath
->nd_head
) {
2292 COMPILE(ret
, "nd_else->nd_head", cpath
->nd_head
);
2295 /* class at cbase Foo */
2296 ADD_INSN1(ret
, nd_line(cpath
), putobject
, Qundef
);
2302 defined_expr(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
,
2303 NODE
*node
, LABEL
**lfinish
, VALUE needstr
)
2306 enum node_type type
;
2308 switch (type
= nd_type(node
)) {
2328 defined_expr(iseq
, ret
, vals
->nd_head
, lfinish
, Qfalse
);
2331 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2334 LABEL
*lcont
= NEW_LABEL(nd_line(node
));
2335 lfinish
[1] = NEW_LABEL(nd_line(node
));
2336 ADD_INSNL(ret
, nd_line(node
), branchif
, lcont
);
2337 ADD_LABEL(ret
, lfinish
[1]);
2338 ADD_INSN(ret
, nd_line(node
), putnil
);
2339 ADD_INSNL(ret
, nd_line(node
), jump
, lfinish
[0]);
2340 ADD_LABEL(ret
, lcont
);
2342 } while ((vals
= vals
->nd_next
) != NULL
);
2347 estr
= "expression";
2353 estr
= "local-variable";
2357 ADD_INSN(ret
, nd_line(node
), putnil
);
2358 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_IVAR
),
2359 ID2SYM(node
->nd_vid
), needstr
);
2363 ADD_INSN(ret
, nd_line(node
), putnil
);
2364 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_GVAR
),
2365 ((VALUE
)node
->nd_entry
) | 1, needstr
);
2369 ADD_INSN(ret
, nd_line(node
), putnil
);
2370 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_CVAR
),
2371 ID2SYM(node
->nd_vid
), needstr
);
2375 ADD_INSN(ret
, nd_line(node
), putnil
);
2376 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_CONST
),
2377 ID2SYM(node
->nd_vid
), needstr
);
2381 lfinish
[1] = NEW_LABEL(nd_line(node
));
2383 defined_expr(iseq
, ret
, node
->nd_head
, lfinish
, Qfalse
);
2384 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2386 if (rb_is_const_id(node
->nd_mid
)) {
2387 COMPILE(ret
, "defined/colon2#nd_head", node
->nd_head
);
2388 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_CONST
),
2389 ID2SYM(node
->nd_mid
), needstr
);
2392 COMPILE(ret
, "defined/colon2#nd_head", node
->nd_head
);
2393 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_METHOD
),
2394 ID2SYM(node
->nd_mid
), needstr
);
2398 ADD_INSN1(ret
, nd_line(node
), putobject
, rb_cObject
);
2399 ADD_INSN3(ret
, nd_line(node
), defined
,
2400 INT2FIX(DEFINED_CONST
), ID2SYM(node
->nd_mid
), needstr
);
2403 /* method dispatch */
2407 case NODE_ATTRASGN
:{
2412 if (node
->nd_recv
== (NODE
*)1) break;
2420 lfinish
[1] = NEW_LABEL(nd_line(node
));
2422 if (node
->nd_args
) {
2423 defined_expr(iseq
, ret
, node
->nd_args
, lfinish
, Qfalse
);
2424 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2427 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
2428 LABEL
*lend
= NEW_LABEL(nd_line(node
));
2429 VALUE rescue
= NEW_CHILD_ISEQVAL(NEW_NIL(),
2430 rb_str_concat(rb_str_new2
2431 ("defined guard in "),
2433 ISEQ_TYPE_DEFINED_GUARD
);
2435 defined_expr(iseq
, ret
, node
->nd_recv
, lfinish
, Qfalse
);
2436 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2438 ADD_LABEL(ret
, lstart
);
2439 COMPILE(ret
, "defined/recv", node
->nd_recv
);
2440 ADD_LABEL(ret
, lend
);
2441 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE
, lstart
, lend
, rescue
, lfinish
[1]);
2442 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_METHOD
),
2443 ID2SYM(node
->nd_mid
), needstr
);
2446 ADD_INSN(ret
, nd_line(node
), putself
);
2447 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_FUNC
),
2448 ID2SYM(node
->nd_mid
), needstr
);
2454 ADD_INSN(ret
, nd_line(node
), putnil
);
2455 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_YIELD
), 0,
2461 ADD_INSN(ret
, nd_line(node
), putnil
);
2462 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_REF
),
2463 INT2FIX((node
->nd_nth
<< 1) | (type
== NODE_BACK_REF
)),
2468 ADD_INSN(ret
, nd_line(node
), putnil
);
2469 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_ZSUPER
), 0,
2478 case NODE_DASGN_CURR
:
2484 estr
= "assignment";
2488 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
2489 LABEL
*lend
= NEW_LABEL(nd_line(node
));
2490 VALUE ensure
= NEW_CHILD_ISEQVAL(NEW_NIL(),
2491 rb_str_concat(rb_str_new2
2492 ("defined guard in "),
2494 ISEQ_TYPE_DEFINED_GUARD
);
2496 ADD_LABEL(ret
, lstart
);
2497 COMPILE(ret
, "defined expr (others)", node
);
2499 lfinish
[1] = NEW_LABEL(nd_line(node
));
2501 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2503 ADD_INSN1(ret
, nd_line(node
), putstring
, rb_str_new2("expression"));
2506 ADD_INSN1(ret
, nd_line(node
), putobject
, Qtrue
);
2508 ADD_LABEL(ret
, lend
);
2510 ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE
, lstart
, lend
, ensure
, lfinish
[1]);
2512 } /* end of default */
2516 if (needstr
!= Qfalse
) {
2517 VALUE str
= rb_str_new2(estr
);
2518 ADD_INSN1(ret
, nd_line(node
), putstring
, str
);
2519 iseq_add_mark_object_compile_time(iseq
, str
);
2522 ADD_INSN1(ret
, nd_line(node
), putobject
, Qtrue
);
2529 #define BUFSIZE 0x100
2532 make_name_for_block(rb_iseq_t
*iseq
)
2534 if (iseq
->parent_iseq
== 0) {
2535 return rb_sprintf("block in %s", RSTRING_PTR(iseq
->name
));
2539 rb_iseq_t
*ip
= iseq
;
2540 while (ip
->local_iseq
!= ip
) {
2541 ip
= ip
->parent_iseq
;
2544 return rb_sprintf("block (%d levels) in %s", level
, RSTRING_PTR(ip
->name
));
2549 add_ensure_range(rb_iseq_t
*iseq
, struct ensure_range
*erange
,
2550 LABEL
*lstart
, LABEL
*lend
)
2552 struct ensure_range
*ne
=
2553 compile_data_alloc(iseq
, sizeof(struct ensure_range
));
2555 while (erange
->next
!= 0) {
2556 erange
= erange
->next
;
2560 ne
->end
= erange
->end
;
2561 erange
->end
= lstart
;
2567 add_ensure_iseq(LINK_ANCHOR
*ret
, rb_iseq_t
*iseq
)
2569 struct iseq_compile_data_ensure_node_stack
*enlp
=
2570 iseq
->compile_data
->ensure_node_stack
;
2571 struct iseq_compile_data_ensure_node_stack
*prev_enlp
= enlp
;
2572 DECL_ANCHOR(ensure
);
2574 INIT_ANCHOR(ensure
);
2576 DECL_ANCHOR(ensure_part
);
2577 LABEL
*lstart
= NEW_LABEL(0);
2578 LABEL
*lend
= NEW_LABEL(0);
2580 INIT_ANCHOR(ensure_part
);
2581 add_ensure_range(iseq
, enlp
->erange
, lstart
, lend
);
2583 iseq
->compile_data
->ensure_node_stack
= enlp
->prev
;
2584 ADD_LABEL(ensure_part
, lstart
);
2585 COMPILE_POPED(ensure_part
, "ensure part", enlp
->ensure_node
);
2586 ADD_LABEL(ensure_part
, lend
);
2588 ADD_SEQ(ensure
, ensure_part
);
2591 iseq
->compile_data
->ensure_node_stack
= prev_enlp
;
2592 ADD_SEQ(ret
, ensure
);
2596 setup_args(rb_iseq_t
*iseq
, LINK_ANCHOR
*args
, NODE
*argn
, unsigned long *flag
)
2598 VALUE argc
= INT2FIX(0);
2600 DECL_ANCHOR(arg_block
);
2601 DECL_ANCHOR(args_splat
);
2603 INIT_ANCHOR(arg_block
);
2604 INIT_ANCHOR(args_splat
);
2605 if (argn
&& nd_type(argn
) == NODE_BLOCK_PASS
) {
2606 COMPILE(arg_block
, "block", argn
->nd_body
);
2607 *flag
|= VM_CALL_ARGS_BLOCKARG_BIT
;
2608 argn
= argn
->nd_head
;
2613 switch (nd_type(argn
)) {
2615 COMPILE(args
, "args (splat)", argn
->nd_head
);
2618 *flag
|= VM_CALL_ARGS_SPLAT_BIT
;
2622 case NODE_ARGSPUSH
: {
2623 int next_is_array
= (nd_type(argn
->nd_head
) == NODE_ARRAY
);
2627 COMPILE(tmp
, "args (cat: splat)", argn
->nd_body
);
2628 if (next_is_array
&& nsplat
== 0) {
2632 if (nd_type(argn
) == NODE_ARGSCAT
) {
2633 ADD_INSN1(tmp
, nd_line(argn
), splatarray
, Qfalse
);
2636 ADD_INSN1(tmp
, nd_line(argn
), newarray
, INT2FIX(1));
2639 INSERT_LIST(args_splat
, tmp
);
2641 *flag
|= VM_CALL_ARGS_SPLAT_BIT
;
2643 if (next_is_array
) {
2644 argc
= INT2FIX(compile_array(iseq
, args
, argn
->nd_head
, Qfalse
) + 1);
2648 argn
= argn
->nd_head
;
2654 argc
= INT2FIX(compile_array(iseq
, args
, argn
, Qfalse
));
2659 rb_bug("setup_arg: unknown node: %s\n", ruby_node_name(nd_type(argn
)));
2666 for (i
=1; i
<nsplat
; i
++) {
2667 ADD_INSN(args_splat
, nd_line(args
), concatarray
);
2671 if (!LIST_SIZE_ZERO(args_splat
)) {
2672 ADD_SEQ(args
, args_splat
);
2675 if (*flag
& VM_CALL_ARGS_BLOCKARG_BIT
) {
2676 ADD_SEQ(args
, arg_block
);
2685 self: InstructionSequence
2686 node: Ruby compiled node
2687 poped: This node will be poped
2690 iseq_compile_each(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node
, int poped
)
2692 enum node_type type
;
2696 debugs("node: NODE_NIL(implicit)\n");
2697 ADD_INSN(ret
, iseq
->compile_data
->last_line
, putnil
);
2702 iseq
->compile_data
->last_line
= nd_line(node
);
2703 debug_node_start(node
);
2705 type
= nd_type(node
);
2707 if (node
->flags
& NODE_FL_NEWLINE
) {
2708 ADD_TRACE(ret
, nd_line(node
), RUBY_EVENT_LINE
);
2713 while (node
&& nd_type(node
) == NODE_BLOCK
) {
2714 COMPILE_(ret
, "BLOCK body", node
->nd_head
,
2715 (node
->nd_next
== 0 && poped
== 0) ? 0 : 1);
2716 node
= node
->nd_next
;
2719 COMPILE_(ret
, "BLOCK next", node
->nd_next
, poped
);
2724 DECL_ANCHOR(cond_seq
);
2725 DECL_ANCHOR(then_seq
);
2726 DECL_ANCHOR(else_seq
);
2727 LABEL
*then_label
, *else_label
, *end_label
;
2729 INIT_ANCHOR(cond_seq
);
2730 INIT_ANCHOR(then_seq
);
2731 INIT_ANCHOR(else_seq
);
2732 then_label
= NEW_LABEL(nd_line(node
));
2733 else_label
= NEW_LABEL(nd_line(node
));
2734 end_label
= NEW_LABEL(nd_line(node
));
2736 compile_branch_condition(iseq
, cond_seq
, node
->nd_cond
,
2737 then_label
, else_label
);
2738 COMPILE_(then_seq
, "then", node
->nd_body
, poped
);
2739 COMPILE_(else_seq
, "else", node
->nd_else
, poped
);
2741 ADD_SEQ(ret
, cond_seq
);
2743 ADD_LABEL(ret
, then_label
);
2744 ADD_SEQ(ret
, then_seq
);
2745 ADD_INSNL(ret
, nd_line(node
), jump
, end_label
);
2747 ADD_LABEL(ret
, else_label
);
2748 ADD_SEQ(ret
, else_seq
);
2750 ADD_LABEL(ret
, end_label
);
2756 NODE
*tempnode
= node
;
2757 LABEL
*endlabel
, *elselabel
;
2759 DECL_ANCHOR(body_seq
);
2760 DECL_ANCHOR(cond_seq
);
2761 VALUE special_literals
= rb_ary_new();
2764 INIT_ANCHOR(body_seq
);
2765 INIT_ANCHOR(cond_seq
);
2766 if (node
->nd_head
== 0) {
2767 COMPILE_(ret
, "when", node
->nd_body
, poped
);
2770 COMPILE(head
, "case base", node
->nd_head
);
2772 node
= node
->nd_body
;
2773 type
= nd_type(node
);
2775 if (type
!= NODE_WHEN
) {
2776 COMPILE_ERROR((ERROR_ARGS
"NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type
)));
2779 endlabel
= NEW_LABEL(nd_line(node
));
2780 elselabel
= NEW_LABEL(nd_line(node
));
2782 ADD_SEQ(ret
, head
); /* case VAL */
2784 while (type
== NODE_WHEN
) {
2787 l1
= NEW_LABEL(nd_line(node
));
2788 ADD_LABEL(body_seq
, l1
);
2789 ADD_INSN(body_seq
, nd_line(node
), pop
);
2790 COMPILE_(body_seq
, "when body", node
->nd_body
, poped
);
2791 ADD_INSNL(body_seq
, nd_line(node
), jump
, endlabel
);
2793 vals
= node
->nd_head
;
2795 switch (nd_type(vals
)) {
2797 special_literals
= when_vals(iseq
, cond_seq
, vals
, l1
, special_literals
);
2802 special_literals
= 0;
2803 COMPILE(cond_seq
, "when/cond splat", vals
);
2804 ADD_INSN1(cond_seq
, nd_line(vals
), checkincludearray
, Qtrue
);
2805 ADD_INSNL(cond_seq
, nd_line(vals
), branchif
, l1
);
2808 rb_bug("NODE_CASE: unknown node (%s)",
2809 ruby_node_name(nd_type(vals
)));
2813 rb_bug("NODE_CASE: must be NODE_ARRAY, but 0");
2816 node
= node
->nd_next
;
2820 type
= nd_type(node
);
2824 ADD_LABEL(cond_seq
, elselabel
);
2825 ADD_INSN(cond_seq
, nd_line(node
), pop
);
2826 COMPILE_(cond_seq
, "else", node
, poped
);
2827 ADD_INSNL(cond_seq
, nd_line(node
), jump
, endlabel
);
2830 debugs("== else (implicit)\n");
2831 ADD_LABEL(cond_seq
, elselabel
);
2832 ADD_INSN(cond_seq
, nd_line(tempnode
), pop
);
2834 ADD_INSN(cond_seq
, nd_line(tempnode
), putnil
);
2836 ADD_INSNL(cond_seq
, nd_line(tempnode
), jump
, endlabel
);
2839 if (special_literals
) {
2840 ADD_INSN(ret
, nd_line(tempnode
), dup
);
2841 ADD_INSN2(ret
, nd_line(tempnode
), opt_case_dispatch
,
2842 special_literals
, elselabel
);
2843 iseq_add_mark_object_compile_time(iseq
, special_literals
);
2846 ADD_SEQ(ret
, cond_seq
);
2847 ADD_SEQ(ret
, body_seq
);
2848 ADD_LABEL(ret
, endlabel
);
2854 NODE
*orig_node
= node
;
2856 DECL_ANCHOR(body_seq
);
2858 INIT_ANCHOR(body_seq
);
2859 endlabel
= NEW_LABEL(nd_line(node
));
2861 while (node
&& nd_type(node
) == NODE_WHEN
) {
2862 LABEL
*l1
= NEW_LABEL(nd_line(node
));
2863 ADD_LABEL(body_seq
, l1
);
2864 COMPILE_(body_seq
, "when", node
->nd_body
, poped
);
2865 ADD_INSNL(body_seq
, nd_line(node
), jump
, endlabel
);
2867 vals
= node
->nd_head
;
2868 if (vals
&& nd_type(vals
) == NODE_ARRAY
) {
2870 val
= vals
->nd_head
;
2871 COMPILE(ret
, "when2", val
);
2872 ADD_INSNL(ret
, nd_line(val
), branchif
, l1
);
2873 vals
= vals
->nd_next
;
2876 else if (nd_type(vals
) == NODE_SPLAT
||
2877 nd_type(vals
) == NODE_ARGSCAT
||
2878 nd_type(vals
) == NODE_ARGSPUSH
) {
2880 NODE
*val
= vals
->nd_head
;
2882 if (nd_type(vals
) == NODE_ARGSCAT
|| nd_type(vals
) == NODE_ARGSPUSH
) {
2883 NODE
*vs
= vals
->nd_head
;
2884 val
= vals
->nd_body
;
2887 NODE
* val
= vs
->nd_head
;
2888 COMPILE(ret
, "when/argscat", val
);
2889 ADD_INSNL(ret
, nd_line(val
), branchif
, l1
);
2894 ADD_INSN(ret
, nd_line(val
), putnil
);
2895 COMPILE(ret
, "when2/splat", val
);
2896 ADD_INSN1(ret
, nd_line(val
), checkincludearray
, Qfalse
);
2897 ADD_INSN(ret
, nd_line(val
), pop
);
2898 ADD_INSNL(ret
, nd_line(val
), branchif
, l1
);
2903 node
= node
->nd_next
;
2906 COMPILE_(ret
, "else", node
, poped
);
2907 ADD_INSNL(ret
, nd_line(orig_node
), jump
, endlabel
);
2909 ADD_SEQ(ret
, body_seq
);
2910 ADD_LABEL(ret
, endlabel
);
2917 LABEL
*prev_start_label
= iseq
->compile_data
->start_label
;
2918 LABEL
*prev_end_label
= iseq
->compile_data
->end_label
;
2919 LABEL
*prev_redo_label
= iseq
->compile_data
->redo_label
;
2920 VALUE prev_loopval_popped
= iseq
->compile_data
->loopval_popped
;
2922 struct iseq_compile_data_ensure_node_stack
*enlp
=
2923 iseq
->compile_data
->ensure_node_stack
;
2925 LABEL
*next_label
= iseq
->compile_data
->start_label
= NEW_LABEL(nd_line(node
)); /* next */
2926 LABEL
*redo_label
= iseq
->compile_data
->redo_label
= NEW_LABEL(nd_line(node
)); /* redo */
2927 LABEL
*break_label
= iseq
->compile_data
->end_label
= NEW_LABEL(nd_line(node
)); /* break */
2928 LABEL
*end_label
= NEW_LABEL(nd_line(node
));
2930 iseq
->compile_data
->loopval_popped
= 0;
2931 iseq
->compile_data
->ensure_node_stack
= 0;
2933 if (type
== NODE_OPT_N
|| node
->nd_state
== 1) {
2934 ADD_INSNL(ret
, nd_line(node
), jump
, next_label
);
2937 ADD_LABEL(ret
, redo_label
);
2938 COMPILE_POPED(ret
, "while body", node
->nd_body
);
2939 ADD_LABEL(ret
, next_label
); /* next */
2941 if (type
== NODE_WHILE
) {
2942 compile_branch_condition(iseq
, ret
, node
->nd_cond
,
2943 redo_label
, end_label
);
2945 else if (type
== NODE_UNTIL
) {
2947 compile_branch_condition(iseq
, ret
, node
->nd_cond
,
2948 end_label
, redo_label
);
2951 ADD_CALL_RECEIVER(ret
, nd_line(node
));
2952 ADD_CALL(ret
, nd_line(node
), ID2SYM(idGets
), INT2FIX(0));
2953 ADD_INSNL(ret
, nd_line(node
), branchif
, redo_label
);
2957 ADD_LABEL(ret
, end_label
);
2959 if (node
->nd_state
== Qundef
) {
2960 /* ADD_INSN(ret, nd_line(node), putundef); */
2961 rb_bug("unsupported: putundef");
2964 ADD_INSN(ret
, nd_line(node
), putnil
);
2967 ADD_LABEL(ret
, break_label
); /* braek */
2970 ADD_INSN(ret
, nd_line(node
), pop
);
2973 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK
, redo_label
, break_label
,
2975 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT
| 0x10000, redo_label
,
2976 break_label
, 0, iseq
->compile_data
->start_label
);
2977 ADD_CATCH_ENTRY(CATCH_TYPE_REDO
, redo_label
, break_label
, 0,
2978 iseq
->compile_data
->redo_label
);
2980 iseq
->compile_data
->start_label
= prev_start_label
;
2981 iseq
->compile_data
->end_label
= prev_end_label
;
2982 iseq
->compile_data
->redo_label
= prev_redo_label
;
2983 iseq
->compile_data
->loopval_popped
= prev_loopval_popped
;
2984 iseq
->compile_data
->ensure_node_stack
= enlp
;
2989 VALUE prevblock
= iseq
->compile_data
->current_block
;
2990 LABEL
*retry_label
= NEW_LABEL(nd_line(node
));
2991 LABEL
*retry_end_l
= NEW_LABEL(nd_line(node
));
2994 ADD_LABEL(ret
, retry_label
);
2995 if (nd_type(node
) == NODE_FOR
) {
2996 COMPILE(ret
, "iter caller (for)", node
->nd_iter
);
2998 iseq
->compile_data
->current_block
=
2999 NEW_CHILD_ISEQVAL(node
->nd_body
, make_name_for_block(iseq
),
3003 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idEach
), INT2FIX(0),
3004 iseq
->compile_data
->current_block
, INT2FIX(0));
3007 iseq
->compile_data
->current_block
=
3008 NEW_CHILD_ISEQVAL(node
->nd_body
, make_name_for_block(iseq
),
3010 COMPILE(ret
, "iter caller", node
->nd_iter
);
3012 ADD_LABEL(ret
, retry_end_l
);
3015 ADD_INSN(ret
, nd_line(node
), pop
);
3018 iseq
->compile_data
->current_block
= prevblock
;
3020 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK
, retry_label
, retry_end_l
, 0, retry_end_l
);
3025 unsigned long level
= 0;
3027 if (iseq
->compile_data
->redo_label
!= 0) {
3029 LABEL
*splabel
= NEW_LABEL(0);
3030 ADD_LABEL(ret
, splabel
);
3031 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->redo_label
);
3032 COMPILE_(ret
, "break val (while/until)", node
->nd_stts
, iseq
->compile_data
->loopval_popped
);
3033 add_ensure_iseq(ret
, iseq
);
3034 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->end_label
);
3035 ADD_ADJUST_RESTORE(ret
, splabel
);
3038 ADD_INSN(ret
, nd_line(node
), putnil
);
3041 else if (iseq
->type
== ISEQ_TYPE_BLOCK
) {
3043 /* escape from block */
3044 COMPILE(ret
, "break val (block)", node
->nd_stts
);
3045 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(level
| 0x02) /* TAG_BREAK */ );
3047 ADD_INSN(ret
, nd_line(node
), pop
);
3050 else if (iseq
->type
== ISEQ_TYPE_EVAL
) {
3052 COMPILE_ERROR((ERROR_ARGS
"Can't escape from eval with break"));
3055 rb_iseq_t
*ip
= iseq
->parent_iseq
;
3058 if (ip
->compile_data
->redo_label
!= 0) {
3060 if (ip
->compile_data
->loopval_popped
== 0) {
3066 else if (ip
->type
== ISEQ_TYPE_BLOCK
) {
3070 else if (ip
->type
== ISEQ_TYPE_EVAL
) {
3073 ip
= ip
->parent_iseq
;
3075 COMPILE_ERROR((ERROR_ARGS
"Invalid break"));
3080 unsigned long level
= 0;
3082 if (iseq
->compile_data
->redo_label
!= 0) {
3083 LABEL
*splabel
= NEW_LABEL(0);
3084 debugs("next in while loop\n");
3085 ADD_LABEL(ret
, splabel
);
3086 COMPILE(ret
, "next val/valid syntax?", node
->nd_stts
);
3087 add_ensure_iseq(ret
, iseq
);
3088 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->redo_label
);
3089 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->start_label
);
3090 ADD_ADJUST_RESTORE(ret
, splabel
);
3092 else if (iseq
->compile_data
->end_label
) {
3093 LABEL
*splabel
= NEW_LABEL(0);
3094 debugs("next in block\n");
3095 ADD_LABEL(ret
, splabel
);
3096 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->start_label
);
3097 COMPILE(ret
, "next val", node
->nd_stts
);
3098 add_ensure_iseq(ret
, iseq
);
3099 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->end_label
);
3100 ADD_ADJUST_RESTORE(ret
, splabel
);
3103 ADD_INSN(ret
, nd_line(node
), putnil
);
3106 else if (iseq
->type
== ISEQ_TYPE_EVAL
) {
3108 COMPILE_ERROR((ERROR_ARGS
"Can't escape from eval with next"));
3115 if (ip
->compile_data
->redo_label
!= 0) {
3119 else if (ip
->type
== ISEQ_TYPE_BLOCK
) {
3123 else if (ip
->type
== ISEQ_TYPE_EVAL
) {
3126 ip
= ip
->parent_iseq
;
3129 COMPILE(ret
, "next val", node
->nd_stts
);
3130 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(level
| 0x03) /* TAG_NEXT */ );
3133 ADD_INSN(ret
, nd_line(node
), pop
);
3137 COMPILE_ERROR((ERROR_ARGS
"Invalid next"));
3143 if (iseq
->compile_data
->redo_label
) {
3144 LABEL
*splabel
= NEW_LABEL(0);
3145 debugs("redo in while");
3146 ADD_LABEL(ret
, splabel
);
3147 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->redo_label
);
3148 add_ensure_iseq(ret
, iseq
);
3149 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->redo_label
);
3150 ADD_ADJUST_RESTORE(ret
, splabel
);
3152 else if (iseq
->type
== ISEQ_TYPE_EVAL
) {
3154 COMPILE_ERROR((ERROR_ARGS
"Can't escape from eval with redo"));
3156 else if (iseq
->compile_data
->start_label
) {
3157 LABEL
*splabel
= NEW_LABEL(0);
3159 debugs("redo in block");
3160 ADD_LABEL(ret
, splabel
);
3161 add_ensure_iseq(ret
, iseq
);
3162 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->start_label
);
3163 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->start_label
);
3164 ADD_ADJUST_RESTORE(ret
, splabel
);
3167 ADD_INSN(ret
, nd_line(node
), putnil
);
3172 unsigned long level
;
3173 level
= 0x8000 | 0x4000;
3176 if (ip
->compile_data
->redo_label
!= 0) {
3179 else if (ip
->type
== ISEQ_TYPE_BLOCK
) {
3182 else if (ip
->type
== ISEQ_TYPE_EVAL
) {
3185 ip
= ip
->parent_iseq
;
3188 ADD_INSN(ret
, nd_line(node
), putnil
);
3189 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(level
| 0x05) /* TAG_REDO */ );
3192 ADD_INSN(ret
, nd_line(node
), pop
);
3196 COMPILE_ERROR((ERROR_ARGS
"Invalid redo"));
3202 if (iseq
->type
== ISEQ_TYPE_RESCUE
) {
3203 ADD_INSN(ret
, nd_line(node
), putnil
);
3204 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(0x04) /* TAG_RETRY */ );
3207 ADD_INSN(ret
, nd_line(node
), pop
);
3211 COMPILE_ERROR((ERROR_ARGS
"Invalid retry"));
3216 COMPILE_(ret
, "NODE_BEGIN", node
->nd_body
, poped
);
3220 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
3221 LABEL
*lend
= NEW_LABEL(nd_line(node
));
3222 LABEL
*lcont
= NEW_LABEL(nd_line(node
));
3223 VALUE rescue
= NEW_CHILD_ISEQVAL(
3225 rb_str_concat(rb_str_new2("rescue in "), iseq
->name
),
3228 ADD_LABEL(ret
, lstart
);
3229 COMPILE(ret
, "rescue head", node
->nd_head
);
3230 ADD_LABEL(ret
, lend
);
3231 if (node
->nd_else
) {
3232 ADD_INSN(ret
, nd_line(node
), pop
);
3233 COMPILE(ret
, "rescue else", node
->nd_else
);
3235 ADD_INSN(ret
, nd_line(node
), nop
);
3236 ADD_LABEL(ret
, lcont
);
3239 ADD_INSN(ret
, nd_line(node
), pop
);
3242 /* resgister catch entry */
3243 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE
, lstart
, lend
, rescue
, lcont
);
3244 ADD_CATCH_ENTRY(CATCH_TYPE_RETRY
, lend
, lcont
, 0, lstart
);
3250 LABEL
*label_miss
, *label_hit
;
3253 label_miss
= NEW_LABEL(nd_line(node
));
3254 label_hit
= NEW_LABEL(nd_line(node
));
3256 narg
= resq
->nd_args
;
3258 switch (nd_type(narg
)) {
3261 COMPILE(ret
, "rescue arg", narg
->nd_head
);
3262 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(1),
3264 ADD_SEND(ret
, nd_line(node
), ID2SYM(idEqq
), INT2FIX(1));
3265 ADD_INSNL(ret
, nd_line(node
), branchif
, label_hit
);
3266 narg
= narg
->nd_next
;
3272 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(1),
3274 COMPILE(ret
, "rescue/cond splat", narg
);
3275 ADD_INSN1(ret
, nd_line(node
), checkincludearray
, Qtrue
);
3276 ADD_INSN(ret
, nd_line(node
), swap
);
3277 ADD_INSN(ret
, nd_line(node
), pop
);
3278 ADD_INSNL(ret
, nd_line(node
), branchif
, label_hit
);
3281 rb_bug("NODE_RESBODY: unknown node (%s)",
3282 ruby_node_name(nd_type(narg
)));
3286 ADD_INSN1(ret
, nd_line(node
), putobject
,
3288 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(1),
3290 ADD_SEND(ret
, nd_line(node
), ID2SYM(idEqq
), INT2FIX(1));
3291 ADD_INSNL(ret
, nd_line(node
), branchif
, label_hit
);
3293 ADD_INSNL(ret
, nd_line(node
), jump
, label_miss
);
3294 ADD_LABEL(ret
, label_hit
);
3295 COMPILE(ret
, "resbody body", resq
->nd_body
);
3296 if (iseq
->compile_data
->option
->tailcall_optimization
) {
3297 ADD_INSN(ret
, nd_line(node
), nop
);
3299 ADD_INSN(ret
, nd_line(node
), leave
);
3300 ADD_LABEL(ret
, label_miss
);
3301 resq
= resq
->nd_head
;
3307 VALUE ensure
= NEW_CHILD_ISEQVAL(node
->nd_ensr
,
3308 rb_str_concat(rb_str_new2
3312 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
3313 LABEL
*lend
= NEW_LABEL(nd_line(node
));
3314 LABEL
*lcont
= NEW_LABEL(nd_line(node
));
3315 struct ensure_range er
= { 0 };
3316 struct iseq_compile_data_ensure_node_stack enl
;
3317 struct ensure_range
*erange
;
3322 enl
.ensure_node
= node
->nd_ensr
;
3323 enl
.prev
= iseq
->compile_data
->ensure_node_stack
; /* prev */
3325 COMPILE_POPED(ensr
, "ensure ensr", node
->nd_ensr
);
3327 iseq
->compile_data
->ensure_node_stack
= &enl
;
3329 ADD_LABEL(ret
, lstart
);
3330 COMPILE_(ret
, "ensure head", node
->nd_head
, poped
);
3331 ADD_LABEL(ret
, lend
);
3332 if (ensr
->anchor
.next
== 0) {
3333 ADD_INSN(ret
, nd_line(node
), nop
);
3338 ADD_LABEL(ret
, lcont
);
3340 erange
= iseq
->compile_data
->ensure_node_stack
->erange
;
3342 ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE
, erange
->begin
, erange
->end
,
3344 erange
= erange
->next
;
3346 iseq
->compile_data
->ensure_node_stack
= enl
.prev
;
3352 LABEL
*end_label
= NEW_LABEL(nd_line(node
));
3353 COMPILE(ret
, "nd_1st", node
->nd_1st
);
3355 ADD_INSN(ret
, nd_line(node
), dup
);
3357 if (type
== NODE_AND
) {
3358 ADD_INSNL(ret
, nd_line(node
), branchunless
, end_label
);
3361 ADD_INSNL(ret
, nd_line(node
), branchif
, end_label
);
3364 ADD_INSN(ret
, nd_line(node
), pop
);
3366 COMPILE_(ret
, "nd_2nd", node
->nd_2nd
, poped
);
3367 ADD_LABEL(ret
, end_label
);
3372 compile_massign(iseq
, ret
, node
, poped
);
3377 ID id
= node
->nd_vid
;
3378 int idx
= iseq
->local_iseq
->local_size
- get_local_var_idx(iseq
, id
);
3380 debugs("lvar: %s idx: %d\n", rb_id2name(id
), idx
);
3381 COMPILE(ret
, "rvalue", node
->nd_value
);
3384 ADD_INSN(ret
, nd_line(node
), dup
);
3386 ADD_INSN1(ret
, nd_line(node
), setlocal
, INT2FIX(idx
));
3391 case NODE_DASGN_CURR
:{
3393 COMPILE(ret
, "dvalue", node
->nd_value
);
3394 debugp_param("dassn id", rb_str_new2(rb_id2name(node
->nd_vid
) ? rb_id2name(node
->nd_vid
) : "*"));
3397 ADD_INSN(ret
, nd_line(node
), dup
);
3400 idx
= get_dyna_var_idx(iseq
, node
->nd_vid
, &lv
, &ls
);
3403 rb_bug("NODE_DASGN(_CURR): unknown id (%s)", rb_id2name(node
->nd_vid
));
3406 ADD_INSN2(ret
, nd_line(node
), setdynamic
,
3407 INT2FIX(ls
- idx
), INT2FIX(lv
));
3411 COMPILE(ret
, "lvalue", node
->nd_value
);
3414 ADD_INSN(ret
, nd_line(node
), dup
);
3416 ADD_INSN1(ret
, nd_line(node
), setglobal
,
3417 (((long)node
->nd_entry
) | 1));
3422 COMPILE(ret
, "lvalue", node
->nd_value
);
3424 ADD_INSN(ret
, nd_line(node
), dup
);
3426 ADD_INSN1(ret
, nd_line(node
), setinstancevariable
,
3427 ID2SYM(node
->nd_vid
));
3431 COMPILE(ret
, "lvalue", node
->nd_value
);
3434 ADD_INSN(ret
, nd_line(node
), dup
);
3438 ADD_INSN1(ret
, nd_line(node
), putobject
, Qundef
);
3439 ADD_INSN1(ret
, nd_line(node
), setconstant
,
3440 ID2SYM(node
->nd_vid
));
3443 compile_cpath(ret
, iseq
, node
->nd_else
);
3444 ADD_INSN1(ret
, nd_line(node
), setconstant
,
3445 ID2SYM(node
->nd_else
->nd_mid
));
3450 COMPILE(ret
, "cvasgn val", node
->nd_value
);
3452 ADD_INSN(ret
, nd_line(node
), dup
);
3454 ADD_INSN1(ret
, nd_line(node
), setclassvariable
,
3455 ID2SYM(node
->nd_vid
));
3458 case NODE_OP_ASGN1
: {
3461 unsigned long flag
= 0;
3462 ID id
= node
->nd_mid
;
3470 * send :[] # a x a[x]
3471 * eval y # a x a[x] y
3472 * send op # a x a[x]+y
3477 * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head;
3478 * NODE_OP_ASGN nd_recv
3484 COMPILE(ret
, "NODE_OP_ASGN1 recv", node
->nd_recv
);
3485 if (nd_type(node
->nd_args
->nd_body
) != NODE_ZARRAY
) {
3487 argc
= setup_args(iseq
, args
, node
->nd_args
->nd_body
, &flag
);
3493 ADD_INSN1(ret
, nd_line(node
), dupn
, INT2FIX(FIX2INT(argc
)+1));
3494 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idAREF
), argc
, Qfalse
, LONG2FIX(flag
));
3496 if (id
== 0 || id
== 1) {
3506 LABEL
*label
= NEW_LABEL(nd_line(node
));
3507 LABEL
*lfin
= NEW_LABEL(nd_line(node
));
3511 ADD_INSN(ret
, nd_line(node
), dup
);
3512 ADD_INSNL(ret
, nd_line(node
), branchif
, label
);
3513 ADD_INSN(ret
, nd_line(node
), pop
);
3517 ADD_INSNL(ret
, nd_line(node
), branchunless
, label
);
3520 COMPILE(ret
, "NODE_OP_ASGN1 args->head: ", node
->nd_args
->nd_head
);
3521 if (flag
& VM_CALL_ARGS_SPLAT_BIT
) {
3522 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(1));
3523 ADD_INSN(ret
, nd_line(node
), concatarray
);
3524 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idASET
),
3525 argc
, Qfalse
, LONG2FIX(flag
));
3528 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idASET
),
3529 INT2FIX(FIX2INT(argc
) + 1), Qfalse
, LONG2FIX(flag
));
3531 ADD_INSNL(ret
, nd_line(node
), jump
, lfin
);
3532 ADD_LABEL(ret
, label
);
3533 if (id
== 0) { /* or */
3534 ADD_INSN(ret
, nd_line(node
), swap
);
3535 ADD_INSN(ret
, nd_line(node
), pop
);
3536 ADD_INSN(ret
, nd_line(node
), swap
);
3537 ADD_INSN(ret
, nd_line(node
), pop
);
3539 else if (id
== 1) { /* and */
3540 ADD_INSN(ret
, nd_line(node
), pop
);
3541 ADD_INSN(ret
, nd_line(node
), pop
);
3542 ADD_INSN(ret
, nd_line(node
), putnil
);
3544 ADD_LABEL(ret
, lfin
);
3547 COMPILE(ret
, "NODE_OP_ASGN1 args->head: ", node
->nd_args
->nd_head
);
3548 ADD_SEND(ret
, nd_line(node
), ID2SYM(id
), INT2FIX(1));
3549 if (flag
& VM_CALL_ARGS_SPLAT_BIT
) {
3550 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(1));
3551 ADD_INSN(ret
, nd_line(node
), concatarray
);
3552 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idASET
),
3553 argc
, Qfalse
, LONG2FIX(flag
));
3556 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idASET
),
3557 INT2FIX(FIX2INT(argc
) + 1), Qfalse
, LONG2FIX(flag
));
3562 ADD_INSN(ret
, nd_line(node
), pop
);
3567 case NODE_OP_ASGN2
:{
3568 ID atype
= node
->nd_next
->nd_mid
;
3569 LABEL
*lfin
= NEW_LABEL(nd_line(node
));
3570 LABEL
*lcfin
= NEW_LABEL(nd_line(node
));
3572 class C; attr_accessor :c; end
3609 COMPILE(ret
, "NODE_OP_ASGN2#recv", node
->nd_recv
);
3610 ADD_INSN(ret
, nd_line(node
), dup
);
3611 ADD_SEND(ret
, nd_line(node
), ID2SYM(node
->nd_next
->nd_vid
),
3614 if (atype
== 0 || atype
== 1) { /* 0: OR or 1: AND */
3615 ADD_INSN(ret
, nd_line(node
), dup
);
3617 ADD_INSNL(ret
, nd_line(node
), branchif
, lcfin
);
3620 ADD_INSNL(ret
, nd_line(node
), branchunless
, lcfin
);
3622 ADD_INSN(ret
, nd_line(node
), pop
);
3623 COMPILE(ret
, "NODE_OP_ASGN2 val", node
->nd_value
);
3624 ADD_SEND(ret
, nd_line(node
), ID2SYM(node
->nd_next
->nd_aid
),
3626 ADD_INSNL(ret
, nd_line(node
), jump
, lfin
);
3628 ADD_LABEL(ret
, lcfin
);
3629 ADD_INSN(ret
, nd_line(node
), swap
);
3630 ADD_INSN(ret
, nd_line(node
), pop
);
3632 ADD_LABEL(ret
, lfin
);
3635 COMPILE(ret
, "NODE_OP_ASGN2 val", node
->nd_value
);
3636 ADD_SEND(ret
, nd_line(node
), ID2SYM(node
->nd_next
->nd_mid
),
3638 ADD_SEND(ret
, nd_line(node
), ID2SYM(node
->nd_next
->nd_aid
),
3643 /* we can apply more optimize */
3644 ADD_INSN(ret
, nd_line(node
), pop
);
3648 case NODE_OP_ASGN_AND
:
3649 case NODE_OP_ASGN_OR
:{
3650 LABEL
*lfin
= NEW_LABEL(nd_line(node
));
3653 if (nd_type(node
) == NODE_OP_ASGN_OR
) {
3657 defined_expr(iseq
, ret
, node
->nd_head
, lfinish
, Qfalse
);
3658 lassign
= lfinish
[1];
3660 lassign
= NEW_LABEL(nd_line(node
));
3662 ADD_INSNL(ret
, nd_line(node
), branchunless
, lassign
);
3665 lassign
= NEW_LABEL(nd_line(node
));
3668 COMPILE(ret
, "NODE_OP_ASGN_AND/OR#nd_head", node
->nd_head
);
3669 ADD_INSN(ret
, nd_line(node
), dup
);
3671 if (nd_type(node
) == NODE_OP_ASGN_AND
) {
3672 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfin
);
3675 ADD_INSNL(ret
, nd_line(node
), branchif
, lfin
);
3678 ADD_INSN(ret
, nd_line(node
), pop
);
3679 ADD_LABEL(ret
, lassign
);
3680 COMPILE(ret
, "NODE_OP_ASGN_AND/OR#nd_value", node
->nd_value
);
3681 ADD_LABEL(ret
, lfin
);
3684 /* we can apply more optimize */
3685 ADD_INSN(ret
, nd_line(node
), pop
);
3691 case NODE_VCALL
:{ /* VCALL: variable or call */
3693 call: obj.method(...)
3699 ID mid
= node
->nd_mid
;
3701 unsigned long flag
= 0;
3702 VALUE parent_block
= iseq
->compile_data
->current_block
;
3703 iseq
->compile_data
->current_block
= Qfalse
;
3708 if (nd_type(node
) == NODE_VCALL
) {
3709 if (mid
== idBitblt
) {
3710 ADD_INSN(ret
, nd_line(node
), bitblt
);
3713 else if (mid
== idAnswer
) {
3714 ADD_INSN(ret
, nd_line(node
), answer
);
3726 goto_id
= rb_intern("__goto__");
3727 label_id
= rb_intern("__label__");
3730 if (nd_type(node
) == NODE_FCALL
&&
3731 (mid
== goto_id
|| mid
== label_id
)) {
3732 if (nd_type(node
->nd_args
->nd_head
) == NODE_LIT
&&
3733 SYMBOL_P(node
->nd_args
->nd_head
->nd_lit
)) {
3735 label_sym
= label
= node
->nd_args
->nd_head
->nd_lit
;
3737 rb_hash_aref(iseq
->compile_data
,
3738 label_sym
)) == Qnil
) {
3739 rb_hash_aset(iseq
->compile_data
, label_sym
,
3740 label
= NEW_LABEL(nd_line(node
)));
3744 rb_bug("invalid goto/label format");
3748 if (mid
== goto_id
) {
3749 ADD_INSNL(ret
, nd_line(node
), jump
, label
);
3752 ADD_LABEL(ret
, label
);
3759 if (type
== NODE_CALL
) {
3760 COMPILE(recv
, "recv", node
->nd_recv
);
3762 else if (type
== NODE_FCALL
|| type
== NODE_VCALL
) {
3763 ADD_CALL_RECEIVER(recv
, nd_line(node
));
3767 if (nd_type(node
) != NODE_VCALL
) {
3768 argc
= setup_args(iseq
, args
, node
->nd_args
, &flag
);
3777 debugp_param("call args argc", argc
);
3778 debugp_param("call method", ID2SYM(mid
));
3780 switch (nd_type(node
)) {
3782 flag
|= VM_CALL_VCALL_BIT
;
3783 /* VCALL is funcall, so fall through */
3785 flag
|= VM_CALL_FCALL_BIT
;
3788 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(mid
),
3789 argc
, parent_block
, LONG2FIX(flag
));
3792 ADD_INSN(ret
, nd_line(node
), pop
);
3800 unsigned long flag
= 0;
3801 VALUE parent_block
= iseq
->compile_data
->current_block
;
3804 iseq
->compile_data
->current_block
= Qfalse
;
3805 if (nd_type(node
) == NODE_SUPER
) {
3806 argc
= setup_args(iseq
, args
, node
->nd_args
, &flag
);
3811 rb_iseq_t
*liseq
= iseq
->local_iseq
;
3813 argc
= INT2FIX(liseq
->argc
);
3815 /* normal arguments */
3816 for (i
= 0; i
< liseq
->argc
; i
++) {
3817 int idx
= liseq
->local_size
- i
;
3818 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3821 if (!liseq
->arg_simple
) {
3822 if (liseq
->arg_opts
) {
3823 /* optional arguments */
3825 for (j
= 0; j
< liseq
->arg_opts
- 1; j
++) {
3826 int idx
= liseq
->local_size
- (i
+ j
);
3827 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3833 if (liseq
->arg_rest
!= -1) {
3835 int idx
= liseq
->local_size
- liseq
->arg_rest
;
3836 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3837 argc
= INT2FIX(liseq
->arg_rest
+ 1);
3838 flag
|= VM_CALL_ARGS_SPLAT_BIT
;
3841 if (liseq
->arg_post_len
) {
3842 /* post arguments */
3843 int post_len
= liseq
->arg_post_len
;
3844 int post_start
= liseq
->arg_post_start
;
3846 if (liseq
->arg_rest
!= -1) {
3848 for (j
=0; j
<post_len
; j
++) {
3849 int idx
= liseq
->local_size
- (post_start
+ j
);
3850 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3852 ADD_INSN1(args
, nd_line(node
), newarray
, INT2FIX(j
));
3853 ADD_INSN (args
, nd_line(node
), concatarray
);
3854 /* argc is setteled at above */
3858 for (j
=0; j
<post_len
; j
++) {
3859 int idx
= liseq
->local_size
- (post_start
+ j
);
3860 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3862 argc
= INT2FIX(post_len
+ post_start
);
3868 /* dummy reciever */
3869 ADD_INSN1(ret
, nd_line(node
), putobject
,
3870 nd_type(node
) == NODE_ZSUPER
? Qfalse
: Qtrue
);
3872 ADD_INSN3(ret
, nd_line(node
), invokesuper
,
3873 argc
, parent_block
, LONG2FIX(flag
));
3876 ADD_INSN(ret
, nd_line(node
), pop
);
3881 compile_array_(iseq
, ret
, node
, Qtrue
, poped
);
3886 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(0));
3893 COMPILE(ret
, "values item", n
->nd_head
);
3896 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(node
->nd_alen
));
3898 ADD_INSN(ret
, nd_line(node
), pop
);
3905 int type
= node
->nd_head
? nd_type(node
->nd_head
) : NODE_ZARRAY
;
3910 compile_array(iseq
, list
, node
->nd_head
, Qfalse
);
3911 size
= OPERAND_AT(POP_ELEMENT(list
), 0);
3920 rb_bug("can't make hash with this node: %s", ruby_node_name(type
));
3923 ADD_INSN1(ret
, nd_line(node
), newhash
, size
);
3926 ADD_INSN(ret
, nd_line(node
), pop
);
3931 rb_iseq_t
*is
= iseq
;
3934 if (is
->type
== ISEQ_TYPE_TOP
|| is
->type
== ISEQ_TYPE_CLASS
) {
3935 COMPILE_ERROR((ERROR_ARGS
"Invalid return"));
3941 if (is
->type
== ISEQ_TYPE_METHOD
) {
3942 splabel
= NEW_LABEL(0);
3943 ADD_LABEL(ret
, splabel
);
3944 ADD_ADJUST(ret
, nd_line(node
), 0);
3947 COMPILE(ret
, "return nd_stts (return val)", node
->nd_stts
);
3949 if (is
->type
== ISEQ_TYPE_METHOD
) {
3950 add_ensure_iseq(ret
, iseq
);
3951 ADD_INSN(ret
, nd_line(node
), leave
);
3952 ADD_ADJUST_RESTORE(ret
, splabel
);
3955 ADD_INSN(ret
, nd_line(node
), putnil
);
3959 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(0x01) /* TAG_RETURN */ );
3961 ADD_INSN(ret
, nd_line(node
), pop
);
3972 unsigned long flag
= 0;
3975 if (iseq
->type
== ISEQ_TYPE_TOP
|| iseq
->type
== ISEQ_TYPE_CLASS
) {
3976 COMPILE_ERROR((ERROR_ARGS
"Invalid yield"));
3979 if (node
->nd_head
) {
3980 argc
= setup_args(iseq
, args
, node
->nd_head
, &flag
);
3987 ADD_INSN2(ret
, nd_line(node
), invokeblock
, argc
, LONG2FIX(flag
));
3990 ADD_INSN(ret
, nd_line(node
), pop
);
3996 ID id
= node
->nd_vid
;
3997 int idx
= iseq
->local_iseq
->local_size
- get_local_var_idx(iseq
, id
);
3999 debugs("id: %s idx: %d\n", rb_id2name(id
), idx
);
4000 ADD_INSN1(ret
, nd_line(node
), getlocal
, INT2FIX(idx
));
4006 debugi("nd_vid", node
->nd_vid
);
4008 idx
= get_dyna_var_idx(iseq
, node
->nd_vid
, &lv
, &ls
);
4010 rb_bug("unknown dvar (%s)", rb_id2name(node
->nd_vid
));
4012 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(ls
- idx
),
4018 ADD_INSN1(ret
, nd_line(node
), getglobal
,
4019 (((long)node
->nd_entry
) | 1));
4021 ADD_INSN(ret
, nd_line(node
), pop
);
4026 debugi("nd_vid", node
->nd_vid
);
4028 ADD_INSN1(ret
, nd_line(node
), getinstancevariable
,
4029 ID2SYM(node
->nd_vid
));
4034 debugi("nd_vid", node
->nd_vid
);
4036 if (iseq
->compile_data
->option
->inline_const_cache
) {
4037 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4038 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4040 ADD_LABEL(ret
, lstart
);
4041 ADD_INSN2(ret
, nd_line(node
), getinlinecache
, 0, lend
);
4042 ADD_INSN1(ret
, nd_line(node
), getconstant
, ID2SYM(node
->nd_vid
));
4043 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4044 ADD_LABEL(ret
, lend
);
4047 ADD_INSN(ret
, nd_line(node
), putnil
);
4048 ADD_INSN1(ret
, nd_line(node
), getconstant
, ID2SYM(node
->nd_vid
));
4052 ADD_INSN(ret
, nd_line(node
), pop
);
4058 ADD_INSN1(ret
, nd_line(node
), getclassvariable
,
4059 ID2SYM(node
->nd_vid
));
4065 ADD_INSN2(ret
, nd_line(node
), getspecial
, INT2FIX(1) /* '~' */,
4066 INT2FIX(node
->nd_nth
<< 1));
4070 case NODE_BACK_REF
:{
4072 ADD_INSN2(ret
, nd_line(node
), getspecial
, INT2FIX(1) /* '~' */,
4073 INT2FIX(0x01 | (node
->nd_nth
<< 1)));
4085 switch(nd_type(node
)) {
4087 ADD_INSN1(recv
, nd_line(node
), putobject
, node
->nd_lit
);
4088 ADD_INSN2(val
, nd_line(node
), getspecial
, INT2FIX(0),
4092 COMPILE(recv
, "reciever", node
->nd_recv
);
4093 COMPILE(val
, "value", node
->nd_value
);
4096 COMPILE(recv
, "reciever", node
->nd_value
);
4097 COMPILE(val
, "value", node
->nd_recv
);
4101 if (iseq
->compile_data
->option
->specialized_instruction
) {
4102 /* TODO: detect by node */
4103 if (recv
->last
== recv
->anchor
.next
&&
4104 INSN_OF(recv
->last
) == BIN(putobject
) &&
4105 nd_type(node
) == NODE_MATCH2
) {
4107 ADD_INSN1(ret
, nd_line(node
), opt_regexpmatch1
,
4108 OPERAND_AT(recv
->last
, 0));
4113 ADD_INSN(ret
, nd_line(node
), opt_regexpmatch2
);
4119 ADD_SEND(ret
, nd_line(node
), ID2SYM(idEqTilde
), INT2FIX(1));
4123 ADD_INSN(ret
, nd_line(node
), pop
);
4128 debugp_param("lit", node
->nd_lit
);
4130 ADD_INSN1(ret
, nd_line(node
), putobject
, node
->nd_lit
);
4135 debugp_param("nd_lit", node
->nd_lit
);
4137 ADD_INSN1(ret
, nd_line(node
), putstring
, node
->nd_lit
);
4142 compile_dstr(iseq
, ret
, node
);
4145 ADD_INSN(ret
, nd_line(node
), pop
);
4150 ADD_CALL_RECEIVER(ret
, nd_line(node
));
4151 ADD_INSN1(ret
, nd_line(node
), putobject
, node
->nd_lit
);
4152 ADD_CALL(ret
, nd_line(node
), ID2SYM(idBackquote
), INT2FIX(1));
4155 ADD_INSN(ret
, nd_line(node
), pop
);
4160 ADD_CALL_RECEIVER(ret
, nd_line(node
));
4161 compile_dstr(iseq
, ret
, node
);
4162 ADD_CALL(ret
, nd_line(node
), ID2SYM(idBackquote
), INT2FIX(1));
4165 ADD_INSN(ret
, nd_line(node
), pop
);
4170 COMPILE(ret
, "nd_body", node
->nd_body
);
4173 ADD_INSN(ret
, nd_line(node
), pop
);
4176 ADD_INSN(ret
, nd_line(node
), tostring
);
4181 compile_dregx(iseq
, ret
, node
);
4184 ADD_INSN(ret
, nd_line(node
), pop
);
4188 case NODE_DREGX_ONCE
:{
4190 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4191 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4193 ADD_LABEL(ret
, lstart
);
4194 ADD_INSN2(ret
, nd_line(node
), onceinlinecache
, 0, lend
);
4195 ADD_INSN(ret
, nd_line(node
), pop
);
4197 compile_dregx(iseq
, ret
, node
);
4199 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4200 ADD_LABEL(ret
, lend
);
4203 ADD_INSN(ret
, nd_line(node
), pop
);
4208 COMPILE(ret
, "argscat head", node
->nd_head
);
4209 COMPILE(ret
, "argscat body", node
->nd_body
);
4210 ADD_INSN(ret
, nd_line(node
), concatarray
);
4213 case NODE_ARGSPUSH
:{
4214 COMPILE(ret
, "arsgpush head", node
->nd_head
);
4215 COMPILE(ret
, "argspush body", node
->nd_body
);
4216 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(1));
4217 ADD_INSN(ret
, nd_line(node
), concatarray
);
4221 COMPILE(ret
, "splat", node
->nd_head
);
4222 ADD_INSN1(ret
, nd_line(node
), splatarray
, Qfalse
);
4225 ADD_INSN(ret
, nd_line(node
), pop
);
4230 VALUE iseqval
= NEW_ISEQVAL(node
->nd_defn
,
4231 rb_str_dup(rb_id2str(node
->nd_mid
)),
4234 debugp_param("defn/iseq", iseqval
);
4236 ADD_INSN (ret
, nd_line(node
), putnil
);
4237 ADD_INSN3(ret
, nd_line(node
), definemethod
,
4238 ID2SYM(node
->nd_mid
), iseqval
, INT2FIX(0));
4240 ADD_INSN(ret
, nd_line(node
), putnil
);
4242 debugp_param("defn", iseqval
);
4246 VALUE iseqval
= NEW_ISEQVAL(node
->nd_defn
,
4247 rb_str_dup(rb_id2str(node
->nd_mid
)),
4250 debugp_param("defs/iseq", iseqval
);
4252 COMPILE(ret
, "defs: recv", node
->nd_recv
);
4253 ADD_INSN3(ret
, nd_line(node
), definemethod
,
4254 ID2SYM(node
->nd_mid
), iseqval
, INT2FIX(1));
4256 ADD_INSN(ret
, nd_line(node
), putnil
);
4261 COMPILE(ret
, "alias arg1", node
->u1
.node
);
4262 COMPILE(ret
, "alias arg2", node
->u2
.node
);
4264 ADD_INSN1(ret
, nd_line(node
), alias
, Qfalse
);
4267 ADD_INSN(ret
, nd_line(node
), putnil
);
4272 ADD_INSN1(ret
, nd_line(node
), putobject
, ID2SYM(node
->u1
.id
));
4273 ADD_INSN1(ret
, nd_line(node
), putobject
, ID2SYM(node
->u2
.id
));
4274 ADD_INSN1(ret
, nd_line(node
), alias
, Qtrue
);
4277 ADD_INSN(ret
, nd_line(node
), putnil
);
4282 COMPILE(ret
, "undef arg", node
->u2
.node
);
4283 ADD_INSN(ret
, nd_line(node
), undef
);
4286 ADD_INSN(ret
, nd_line(node
), putnil
);
4294 rb_sprintf("<class:%s>", rb_id2name(node
->nd_cpath
->nd_mid
)),
4296 compile_cpath(ret
, iseq
, node
->nd_cpath
);
4297 COMPILE(ret
, "super", node
->nd_super
);
4298 ADD_INSN3(ret
, nd_line(node
), defineclass
,
4299 ID2SYM(node
->nd_cpath
->nd_mid
), iseqval
, INT2FIX(0));
4302 ADD_INSN(ret
, nd_line(node
), pop
);
4307 VALUE iseqval
= NEW_CHILD_ISEQVAL(
4309 rb_sprintf("<module:%s>", rb_id2name(node
->nd_cpath
->nd_mid
)),
4312 COMPILE(ret
, "mbase", node
->nd_cpath
->nd_head
);
4313 ADD_INSN (ret
, nd_line(node
), putnil
); /* dummy */
4314 ADD_INSN3(ret
, nd_line(node
), defineclass
,
4315 ID2SYM(node
->nd_cpath
->nd_mid
), iseqval
, INT2FIX(2));
4317 ADD_INSN(ret
, nd_line(node
), pop
);
4323 NEW_ISEQVAL(node
->nd_body
, rb_str_new2("singletonclass"),
4326 COMPILE(ret
, "sclass#recv", node
->nd_recv
);
4327 ADD_INSN (ret
, nd_line(node
), putnil
);
4328 ADD_INSN3(ret
, nd_line(node
), defineclass
,
4329 ID2SYM(rb_intern("singletonclass")), iseqval
, INT2FIX(1));
4332 ADD_INSN(ret
, nd_line(node
), pop
);
4337 if (rb_is_const_id(node
->nd_mid
)) {
4339 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4340 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4346 compile_colon2(iseq
, node
, pref
, body
);
4347 if (LIST_SIZE_ZERO(pref
)) {
4348 if (iseq
->compile_data
->option
->inline_const_cache
) {
4349 ADD_LABEL(ret
, lstart
);
4350 ADD_INSN2(ret
, nd_line(node
), getinlinecache
, 0, lend
);
4353 ADD_INSN(ret
, nd_line(node
), putnil
);
4358 if (iseq
->compile_data
->option
->inline_const_cache
) {
4359 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4360 ADD_LABEL(ret
, lend
);
4370 ADD_CALL_RECEIVER(ret
, nd_line(node
));
4371 COMPILE(ret
, "colon2#nd_head", node
->nd_head
);
4372 ADD_CALL(ret
, nd_line(node
), ID2SYM(node
->nd_mid
),
4376 ADD_INSN(ret
, nd_line(node
), pop
);
4381 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4382 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4383 debugi("colon3#nd_mid", node
->nd_mid
);
4385 /* add cache insn */
4386 if (iseq
->compile_data
->option
->inline_const_cache
) {
4387 ADD_LABEL(ret
, lstart
);
4388 ADD_INSN2(ret
, nd_line(node
), getinlinecache
, 0, lend
);
4389 ADD_INSN(ret
, nd_line(node
), pop
);
4392 ADD_INSN1(ret
, nd_line(node
), putobject
, rb_cObject
);
4393 ADD_INSN1(ret
, nd_line(node
), getconstant
, ID2SYM(node
->nd_mid
));
4395 if (iseq
->compile_data
->option
->inline_const_cache
) {
4396 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4397 ADD_LABEL(ret
, lend
);
4401 ADD_INSN(ret
, nd_line(node
), pop
);
4407 int flag
= type
== NODE_DOT2
? INT2FIX(0) : INT2FIX(1);
4408 COMPILE(ret
, "min", (NODE
*) node
->nd_beg
);
4409 COMPILE(ret
, "max", (NODE
*) node
->nd_end
);
4411 ADD_INSN(ret
, nd_line(node
), pop
);
4412 ADD_INSN(ret
, nd_line(node
), pop
);
4415 ADD_INSN1(ret
, nd_line(node
), newrange
, flag
);
4421 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4422 LABEL
*lfin
= NEW_LABEL(nd_line(node
));
4423 LABEL
*ltrue
= NEW_LABEL(nd_line(node
));
4424 VALUE key
= rb_sprintf("flipflag/%s-%p-%d",
4425 RSTRING_PTR(iseq
->name
), iseq
,
4426 iseq
->compile_data
->flip_cnt
++);
4428 iseq_add_mark_object_compile_time(iseq
, key
);
4429 ADD_INSN2(ret
, nd_line(node
), getspecial
, key
, INT2FIX(0));
4430 ADD_INSNL(ret
, nd_line(node
), branchif
, lend
);
4433 COMPILE(ret
, "flip2 beg", node
->nd_beg
);
4434 ADD_INSN(ret
, nd_line(node
), dup
);
4435 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfin
);
4436 if (nd_type(node
) == NODE_FLIP3
) {
4437 ADD_INSN(ret
, nd_line(node
), dup
);
4438 ADD_INSN1(ret
, nd_line(node
), setspecial
, key
);
4439 ADD_INSNL(ret
, nd_line(node
), jump
, lfin
);
4442 ADD_INSN1(ret
, nd_line(node
), setspecial
, key
);
4446 ADD_LABEL(ret
, lend
);
4447 COMPILE(ret
, "flip2 end", node
->nd_end
);
4448 ADD_INSNL(ret
, nd_line(node
), branchunless
, ltrue
);
4449 ADD_INSN1(ret
, nd_line(node
), putobject
, Qfalse
);
4450 ADD_INSN1(ret
, nd_line(node
), setspecial
, key
);
4452 ADD_LABEL(ret
, ltrue
);
4453 ADD_INSN1(ret
, nd_line(node
), putobject
, Qtrue
);
4455 ADD_LABEL(ret
, lfin
);
4460 ADD_INSN(ret
, nd_line(node
), putself
);
4466 ADD_INSN(ret
, nd_line(node
), putnil
);
4472 ADD_INSN1(ret
, nd_line(node
), putobject
, Qtrue
);
4478 ADD_INSN1(ret
, nd_line(node
), putobject
, Qfalse
);
4484 if (iseq
->type
== ISEQ_TYPE_RESCUE
) {
4485 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(1),
4489 rb_iseq_t
*ip
= iseq
;
4492 if (ip
->type
== ISEQ_TYPE_RESCUE
) {
4495 ip
= ip
->parent_iseq
;
4499 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(1),
4503 ADD_INSN(ret
, nd_line(node
), putnil
);
4512 lfinish
[0] = NEW_LABEL(nd_line(node
));
4514 defined_expr(iseq
, ret
, node
->nd_head
, lfinish
, Qtrue
);
4516 ADD_INSNL(ret
, nd_line(node
), jump
, lfinish
[0]);
4517 ADD_LABEL(ret
, lfinish
[1]);
4518 ADD_INSN(ret
, nd_line(node
), putnil
);
4520 ADD_LABEL(ret
, lfinish
[0]);
4525 VALUE block
= NEW_CHILD_ISEQVAL(node
->nd_body
, make_name_for_block(iseq
), ISEQ_TYPE_BLOCK
);
4526 ADD_INSN1(ret
, nd_line(node
), postexe
, block
);
4528 ADD_INSN(ret
, nd_line(node
), putnil
);
4533 compile_dstr(iseq
, ret
, node
);
4535 ADD_SEND(ret
, nd_line(node
), ID2SYM(idIntern
), INT2FIX(0));
4538 ADD_INSN(ret
, nd_line(node
), pop
);
4542 case NODE_ATTRASGN
:{
4545 unsigned long flag
= 0;
4550 argc
= setup_args(iseq
, args
, node
->nd_args
, &flag
);
4552 if (node
->nd_recv
== (NODE
*) 1) {
4553 flag
|= VM_CALL_FCALL_BIT
;
4554 ADD_INSN(recv
, nd_line(node
), putself
);
4557 COMPILE(recv
, "recv", node
->nd_recv
);
4560 debugp_param("argc", argc
);
4561 debugp_param("nd_mid", ID2SYM(node
->nd_mid
));
4564 ADD_INSN(ret
, nd_line(node
), putnil
);
4568 if (flag
& VM_CALL_ARGS_BLOCKARG_BIT
) {
4569 ADD_INSN1(ret
, nd_line(node
), topn
, INT2FIX(1));
4570 ADD_INSN1(ret
, nd_line(node
), setn
, INT2FIX(FIX2INT(argc
) + 3));
4571 ADD_INSN (ret
, nd_line(node
), pop
);
4574 ADD_INSN1(ret
, nd_line(node
), setn
, INT2FIX(FIX2INT(argc
) + 1));
4581 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(node
->nd_mid
), argc
, 0, LONG2FIX(flag
));
4582 ADD_INSN(ret
, nd_line(node
), pop
);
4586 case NODE_OPTBLOCK
:{
4588 LABEL
*redo_label
= NEW_LABEL(0);
4589 LABEL
*next_label
= NEW_LABEL(0);
4591 iseq
->compile_data
->start_label
= next_label
;
4592 iseq
->compile_data
->redo_label
= redo_label
;
4594 ADD_LABEL(ret
, redo_label
);
4595 COMPILE_(ret
, "optblock body", node
->nd_head
, 1 /* pop */ );
4596 ADD_LABEL(ret
, next_label
);
4597 ADD_INSN(ret
, 0, opt_checkenv
);
4601 COMPILE_POPED(ret
, "prelude", node
->nd_head
);
4602 COMPILE_(ret
, "body", node
->nd_body
, poped
);
4606 /* compile same as lambda{...} */
4607 VALUE block
= NEW_CHILD_ISEQVAL(node
->nd_body
, make_name_for_block(iseq
), ISEQ_TYPE_BLOCK
);
4608 VALUE argc
= INT2FIX(0);
4609 ADD_CALL_RECEIVER(ret
, nd_line(node
));
4610 ADD_CALL_WITH_BLOCK(ret
, nd_line(node
), ID2SYM(idLambda
), argc
, block
);
4613 ADD_INSN(ret
, nd_line(node
), pop
);
4618 rb_bug("iseq_compile_each: unknown node: %s", ruby_node_name(type
));
4626 /***************************/
4627 /* instruction information */
4628 /***************************/
4631 insn_data_length(INSN
*iobj
)
4633 return insn_len(iobj
->insn_id
);
4637 calc_sp_depth(int depth
, INSN
*insn
)
4639 return insn_stack_increase(depth
, insn
->insn_id
, insn
->operands
);
4643 insn_data_line_no(INSN
*iobj
)
4645 return insn_len(iobj
->line_no
);
4649 insn_data_to_s_detail(INSN
*iobj
)
4651 VALUE str
= rb_str_new(0, 0);
4653 str
= rb_sprintf("%-16s", insn_name(iobj
->insn_id
));
4654 if (iobj
->operands
) {
4655 const char *types
= insn_op_types(iobj
->insn_id
);
4658 for (j
= 0; types
[j
]; j
++) {
4659 char type
= types
[j
];
4662 case TS_OFFSET
: /* label(destination position) */
4665 LABEL
*lobj
= (LABEL
*)OPERAND_AT(iobj
, j
);
4666 snprintf(buff
, sizeof(buff
), "<L%03d>", lobj
->label_no
);
4667 rb_str_concat(str
, rb_str_new2(buff
));
4671 case TS_ISEQ
: /* iseq */
4673 rb_iseq_t
*iseq
= (rb_iseq_t
*)OPERAND_AT(iobj
, j
);
4678 rb_str_concat(str
, rb_inspect(val
));
4683 case TS_NUM
: /* ulong */
4684 case TS_VALUE
: /* VALUE */
4685 rb_str_concat(str
, rb_inspect(OPERAND_AT(iobj
, j
)));
4687 case TS_ID
: /* ID */
4688 rb_str_concat(str
, rb_inspect(OPERAND_AT(iobj
, j
)));
4692 struct global_entry
*entry
= (struct global_entry
*)
4693 (OPERAND_AT(iobj
, j
) & (~1));
4694 rb_str_cat2(str
, rb_id2name(entry
->id
));
4696 case TS_IC
: /* method cache */
4697 rb_str_cat2(str
, "<ic>");
4699 case TS_CDHASH
: /* case/when condition cache */
4700 rb_str_cat2(str
, "<ch>");
4703 rb_raise(rb_eSyntaxError
, "unknown operand type: %c", type
);
4707 rb_str_cat2(str
, ", ");
4715 dump_disasm_list(struct iseq_link_element
*link
)
4722 printf("-- raw disasm--------\n");
4725 switch (link
->type
) {
4726 case ISEQ_ELEMENT_INSN
:
4728 iobj
= (INSN
*)link
;
4729 str
= insn_data_to_s_detail(iobj
);
4730 printf("%04d %-65s(%4d)\n", pos
, StringValueCStr(str
),
4731 insn_data_line_no(iobj
));
4732 pos
+= insn_data_length(iobj
);
4735 case ISEQ_ELEMENT_LABEL
:
4737 lobj
= (LABEL
*)link
;
4738 printf("<L%03d>\n", lobj
->label_no
);
4741 case ISEQ_ELEMENT_NONE
:
4746 case ISEQ_ELEMENT_ADJUST
:
4748 ADJUST
*adjust
= (ADJUST
*)link
;
4749 printf("adjust: [label: %d]\n", adjust
->label
->label_no
);
4754 rb_raise(rb_eSyntaxError
, "dump_disasm_list error: %ld\n", FIX2LONG(link
->type
));
4758 printf("---------------------\n");
4762 insns_name_array(void)
4764 VALUE ary
= rb_ary_new();
4766 for (i
= 0; i
< sizeof(insn_name_info
) / sizeof(insn_name_info
[0]); i
++) {
4767 rb_ary_push(ary
, rb_str_new2(insn_name_info
[i
]));
4773 register_label(rb_iseq_t
*iseq
, struct st_table
*labels_table
, VALUE obj
)
4777 obj
= rb_convert_type(obj
, T_SYMBOL
, "Symbol", "to_sym");
4779 if (st_lookup(labels_table
, obj
, &tmp
) == 0) {
4780 label
= NEW_LABEL(0);
4781 st_insert(labels_table
, obj
, (st_data_t
)label
);
4784 label
= (LABEL
*)tmp
;
4790 get_exception_sym2type(VALUE sym
)
4792 static VALUE symRescue
, symEnsure
, symRetry
;
4793 static VALUE symBreak
, symRedo
, symNext
;
4795 if (symRescue
== 0) {
4796 symRescue
= ID2SYM(rb_intern("rescue"));
4797 symEnsure
= ID2SYM(rb_intern("ensure"));
4798 symRetry
= ID2SYM(rb_intern("retry"));
4799 symBreak
= ID2SYM(rb_intern("break"));
4800 symRedo
= ID2SYM(rb_intern("redo"));
4801 symNext
= ID2SYM(rb_intern("next"));
4804 if (sym
== symRescue
) return CATCH_TYPE_RESCUE
;
4805 if (sym
== symEnsure
) return CATCH_TYPE_ENSURE
;
4806 if (sym
== symRetry
) return CATCH_TYPE_RETRY
;
4807 if (sym
== symBreak
) return CATCH_TYPE_BREAK
;
4808 if (sym
== symRedo
) return CATCH_TYPE_REDO
;
4809 if (sym
== symNext
) return CATCH_TYPE_NEXT
;
4810 rb_raise(rb_eSyntaxError
, "invalid exception symbol: %s",
4811 RSTRING_PTR(rb_inspect(sym
)));
4816 iseq_build_exception(rb_iseq_t
*iseq
, struct st_table
*labels_table
,
4821 for (i
=0; i
<RARRAY_LEN(exception
); i
++) {
4822 VALUE v
, type
, *ptr
, eiseqval
;
4823 LABEL
*lstart
, *lend
, *lcont
;
4826 RB_GC_GUARD(v
) = rb_convert_type(RARRAY_PTR(exception
)[i
], T_ARRAY
,
4828 if (RARRAY_LEN(v
) != 6) {
4829 rb_raise(rb_eSyntaxError
, "wrong exception entry");
4831 ptr
= RARRAY_PTR(v
);
4832 type
= get_exception_sym2type(ptr
[0]);
4833 if (ptr
[1] == Qnil
) {
4837 eiseqval
= iseq_load(0, ptr
[1], iseq
->self
, Qnil
);
4840 lstart
= register_label(iseq
, labels_table
, ptr
[2]);
4841 lend
= register_label(iseq
, labels_table
, ptr
[3]);
4842 lcont
= register_label(iseq
, labels_table
, ptr
[4]);
4843 sp
= NUM2INT(ptr
[5]);
4845 ADD_CATCH_ENTRY(type
, lstart
, lend
, eiseqval
, lcont
);
4850 struct st_table
*insn_make_insn_table(void);
4853 iseq_build_body(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
,
4854 VALUE body
, struct st_table
*labels_table
)
4856 /* TODO: body should be freezed */
4857 VALUE
*ptr
= RARRAY_PTR(body
);
4858 int len
= RARRAY_LEN(body
);
4862 * index -> LABEL *label
4864 static struct st_table
*insn_table
;
4866 if (insn_table
== 0) {
4867 insn_table
= insn_make_insn_table();
4870 for (i
=0; i
<len
; i
++) {
4873 if (SYMBOL_P(obj
)) {
4874 LABEL
*label
= register_label(iseq
, labels_table
, obj
);
4875 ADD_LABEL(anchor
, label
);
4877 else if (FIXNUM_P(obj
)) {
4878 line_no
= NUM2INT(obj
);
4880 else if (TYPE(obj
) == T_ARRAY
) {
4882 int argc
= RARRAY_LEN(obj
) - 1;
4886 insn
= (argc
< 0) ? Qnil
: RARRAY_PTR(obj
)[0];
4887 if (st_lookup(insn_table
, insn
, &insn_id
) == 0) {
4888 /* TODO: exception */
4889 RB_GC_GUARD(insn
) = rb_inspect(insn
);
4890 rb_compile_error(RSTRING_PTR(iseq
->filename
), line_no
,
4891 "unknown instruction: %s", RSTRING_PTR(insn
));
4894 if (argc
!= insn_len(insn_id
)-1) {
4895 rb_compile_error(RSTRING_PTR(iseq
->filename
), line_no
,
4896 "operand size mismatch");
4900 argv
= compile_data_alloc(iseq
, sizeof(VALUE
) * argc
);
4901 for (j
=0; j
<argc
; j
++) {
4902 VALUE op
= rb_ary_entry(obj
, j
+1);
4903 switch (insn_op_type(insn_id
, j
)) {
4905 LABEL
*label
= register_label(iseq
, labels_table
, op
);
4906 argv
[j
] = (VALUE
)label
;
4912 argv
[j
] = (NUM2INT(op
), op
);
4916 iseq_add_mark_object(iseq
, op
);
4921 if (TYPE(op
) == T_ARRAY
) {
4922 argv
[j
] = iseq_load(0, op
, iseq
->self
, Qnil
);
4924 else if (CLASS_OF(op
) == rb_cISeq
) {
4928 rb_raise(rb_eSyntaxError
, "ISEQ is required");
4930 iseq_add_mark_object(iseq
, argv
[j
]);
4938 op
= rb_convert_type(op
, T_SYMBOL
, "Symbol", "to_sym");
4939 argv
[j
] = (VALUE
)rb_global_entry(SYM2ID(op
));
4942 argv
[j
] = (VALUE
)NEW_INLINE_CACHE_ENTRY();
4943 iseq_add_mark_object(iseq
, argv
[j
]);
4946 argv
[j
] = rb_convert_type(op
, T_SYMBOL
,
4947 "Symbol", "to_sym");
4952 op
= rb_convert_type(op
, T_ARRAY
, "Array", "to_ary");
4953 for (i
=0; i
<RARRAY_LEN(op
); i
+=2) {
4954 VALUE sym
= rb_ary_entry(op
, i
+1);
4956 register_label(iseq
, labels_table
, sym
);
4957 rb_ary_store(op
, i
+1, (VALUE
)label
| 1);
4963 rb_raise(rb_eSyntaxError
, "unknown operand: %c", insn_op_type(insn_id
, j
));
4968 (LINK_ELEMENT
*)new_insn_core(iseq
, line_no
,
4969 insn_id
, argc
, argv
));
4972 rb_raise(rb_eTypeError
, "unexpected object for instruction");
4975 st_free_table(labels_table
);
4976 iseq_setup(iseq
, anchor
);
4980 #define CHECK_ARRAY(v) rb_convert_type(v, T_ARRAY, "Array", "to_ary")
4981 #define CHECK_STRING(v) rb_convert_type(v, T_STRING, "String", "to_str")
4982 #define CHECK_SYMBOL(v) rb_convert_type(v, T_SYMBOL, "Symbol", "to_sym")
4983 static inline VALUE
CHECK_INTEGER(VALUE v
) {NUM2LONG(v
); return v
;}
4986 iseq_build_from_ary(rb_iseq_t
*iseq
, VALUE locals
, VALUE args
,
4987 VALUE exception
, VALUE body
)
4992 struct st_table
*labels_table
= st_init_numtable();
4994 DECL_ANCHOR(anchor
);
4996 INIT_ANCHOR(anchor
);
4997 if (iseq
->type
== ISEQ_TYPE_METHOD
||
4998 iseq
->type
== ISEQ_TYPE_TOP
||
4999 iseq
->type
== ISEQ_TYPE_CLASS
) {
5003 iseq
->local_table_size
= opt
+ RARRAY_LEN(locals
);
5004 iseq
->local_table
= tbl
= (ID
*)ALLOC_N(ID
*, iseq
->local_table_size
);
5005 iseq
->local_size
= opt
+ iseq
->local_table_size
;
5007 for (i
=0; i
<RARRAY_LEN(locals
); i
++) {
5008 VALUE lv
= RARRAY_PTR(locals
)[i
];
5009 tbl
[i
] = FIXNUM_P(lv
) ? FIX2INT(lv
) : SYM2ID(CHECK_SYMBOL(lv
));
5013 if (FIXNUM_P(args
)) {
5014 iseq
->arg_size
= iseq
->argc
= FIX2INT(args
);
5015 iseq
->arg_simple
= 1;
5019 VALUE argc
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5020 VALUE arg_opt_labels
= CHECK_ARRAY(rb_ary_entry(args
, i
++));
5021 VALUE arg_post_len
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5022 VALUE arg_post_start
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5023 VALUE arg_rest
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5024 VALUE arg_block
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5025 VALUE arg_simple
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5027 iseq
->argc
= FIX2INT(argc
);
5028 iseq
->arg_rest
= FIX2INT(arg_rest
);
5029 iseq
->arg_post_len
= FIX2INT(arg_post_len
);
5030 iseq
->arg_post_start
= FIX2INT(arg_post_start
);
5031 iseq
->arg_block
= FIX2INT(arg_block
);
5032 iseq
->arg_opt_table
= (VALUE
*)ALLOC_N(VALUE
, RARRAY_LEN(arg_opt_labels
));
5034 if (iseq
->arg_block
!= -1) {
5035 iseq
->arg_size
= iseq
->arg_block
+ 1;
5037 else if (iseq
->arg_post_len
) {
5038 iseq
->arg_size
= iseq
->arg_post_start
+ iseq
->arg_post_len
;
5040 else if (iseq
->arg_rest
!= -1) {
5041 iseq
->arg_size
= iseq
->arg_rest
+ 1;
5044 iseq
->arg_size
= iseq
->argc
+ iseq
->arg_opts
;
5047 for (i
=0; i
<RARRAY_LEN(arg_opt_labels
); i
++) {
5048 iseq
->arg_opt_table
[i
] =
5049 (VALUE
)register_label(iseq
, labels_table
,
5050 rb_ary_entry(arg_opt_labels
, i
));
5053 iseq
->arg_simple
= NUM2INT(arg_simple
);
5057 iseq_build_exception(iseq
, labels_table
, exception
);
5060 iseq_build_body(iseq
, anchor
, body
, labels_table
);