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)
29 VALUE
iseq_load(VALUE self
, VALUE data
, VALUE parent
, VALUE opt
);
33 typedef struct iseq_link_element
{
35 ISEQ_ELEMENT_NONE
= INT2FIX(0x00),
36 ISEQ_ELEMENT_LABEL
= INT2FIX(0x01),
37 ISEQ_ELEMENT_INSN
= INT2FIX(0x02),
38 ISEQ_ELEMENT_ADJUST
= INT2FIX(0x03)
40 struct iseq_link_element
*next
;
41 struct iseq_link_element
*prev
;
44 typedef struct iseq_link_anchor
{
49 typedef struct iseq_label_data
{
58 typedef struct iseq_insn_data
{
60 enum ruby_vminsn_type insn_id
;
67 typedef struct iseq_adjust_data
{
76 struct ensure_range
*next
;
79 struct iseq_compile_data_ensure_node_stack
{
81 struct iseq_compile_data_ensure_node_stack
*prev
;
82 struct ensure_range
*erange
;
85 #include "optinsn.inc"
86 #if OPT_INSTRUCTIONS_UNIFICATION
87 #include "optunifs.inc"
92 #define ISEQ_ARG iseq,
93 #define ISEQ_ARG_DECLARE rb_iseq_t *iseq,
96 #define ISEQ_ARG_DECLARE
100 #define gl_node_level iseq->compile_data->node_level
102 static void debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR
*anchor
);
106 static void dump_disasm_list(LINK_ELEMENT
*elem
);
108 static int insn_data_length(INSN
*iobj
);
109 static int insn_data_line_no(INSN
*iobj
);
110 static int calc_sp_depth(int depth
, INSN
*iobj
);
112 static void ADD_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR
*anchor
, LINK_ELEMENT
*elem
);
114 static INSN
*new_insn_body(rb_iseq_t
*iseq
, int line_no
, int insn_id
, int argc
, ...);
115 static LABEL
*new_label_body(rb_iseq_t
*iseq
, int line
);
116 static ADJUST
*new_adjust_body(rb_iseq_t
*iseq
, LABEL
*label
, int line
);
118 static int iseq_compile_each(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
, NODE
* n
, int);
119 static int iseq_setup(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
);
120 static int iseq_optimize(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
);
121 static int iseq_insns_unification(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
);
123 static int iseq_set_local_table(rb_iseq_t
*iseq
, ID
*tbl
);
124 static int iseq_set_exception_local_table(rb_iseq_t
*iseq
);
125 static int iseq_set_arguments(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
, NODE
* node
);
127 static int iseq_set_sequence_stackcaching(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
);
128 static int iseq_set_sequence(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
);
129 static int iseq_set_exception_table(rb_iseq_t
*iseq
);
130 static int iseq_set_optargs_table(rb_iseq_t
*iseq
);
133 * To make Array to LinkedList, use link_anchor
137 verify_list(ISEQ_ARG_DECLARE
const char *info
, LINK_ANCHOR
*anchor
)
141 LINK_ELEMENT
*list
, *plist
;
143 if (!compile_debug
) return;
145 list
= anchor
->anchor
.next
;
146 plist
= &anchor
->anchor
;
148 if (plist
!= list
->prev
) {
155 if (anchor
->last
!= plist
&& anchor
->last
!= 0) {
160 rb_bug("list verify error: %08x (%s)", flag
, info
);
165 #define verify_list(info, anchor) verify_list(iseq, info, anchor)
169 * elem1, elem2 => elem1, elem2, elem
172 ADD_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR
*anchor
, LINK_ELEMENT
*elem
)
174 elem
->prev
= anchor
->last
;
175 anchor
->last
->next
= elem
;
177 verify_list("add", anchor
);
180 #define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, anchor, elem)
184 iseq_add_mark_object(rb_iseq_t
*iseq
, VALUE v
)
186 if (!SPECIAL_CONST_P(v
)) {
187 rb_ary_push(iseq
->mark_ary
, v
);
192 #define ruby_sourcefile RSTRING_PTR(iseq->filename)
195 iseq_add_mark_object_compile_time(rb_iseq_t
*iseq
, VALUE v
)
197 if (!SPECIAL_CONST_P(v
)) {
198 rb_ary_push(iseq
->compile_data
->mark_ary
, v
);
204 iseq_compile(VALUE self
, NODE
*node
)
209 GetISeqPtr(self
, iseq
);
212 COMPILE(ret
, "nil", node
);
213 iseq_set_local_table(iseq
, 0);
215 else if (nd_type(node
) == NODE_SCOPE
) {
216 /* iseq type of top, method, class, block */
217 iseq_set_local_table(iseq
, node
->nd_tbl
);
218 iseq_set_arguments(iseq
, ret
, node
->nd_args
);
220 switch (iseq
->type
) {
221 case ISEQ_TYPE_BLOCK
: {
222 LABEL
*start
= iseq
->compile_data
->start_label
= NEW_LABEL(0);
223 LABEL
*end
= iseq
->compile_data
->end_label
= NEW_LABEL(0);
225 ADD_LABEL(ret
, start
);
226 COMPILE(ret
, "block body", node
->nd_body
);
229 /* wide range catch handler must put at last */
230 ADD_CATCH_ENTRY(CATCH_TYPE_REDO
, start
, end
, 0, start
);
231 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT
, start
, end
, 0, end
);
234 case ISEQ_TYPE_CLASS
: {
235 ADD_TRACE(ret
, nd_line(node
), RUBY_EVENT_CLASS
);
236 COMPILE(ret
, "scoped node", node
->nd_body
);
237 ADD_TRACE(ret
, nd_line(node
), RUBY_EVENT_END
);
240 case ISEQ_TYPE_METHOD
: {
241 ADD_TRACE(ret
, nd_line(node
), RUBY_EVENT_CALL
);
242 COMPILE(ret
, "scoped node", node
->nd_body
);
243 ADD_TRACE(ret
, nd_line(node
), RUBY_EVENT_RETURN
);
247 COMPILE(ret
, "scoped node", node
->nd_body
);
253 switch (iseq
->type
) {
254 case ISEQ_TYPE_METHOD
:
255 case ISEQ_TYPE_CLASS
:
256 case ISEQ_TYPE_BLOCK
:
259 rb_compile_error(ERROR_ARGS
"compile/should not be reached: %s:%d",
262 case ISEQ_TYPE_RESCUE
:
263 iseq_set_exception_local_table(iseq
);
264 COMPILE(ret
, "rescue", node
);
266 case ISEQ_TYPE_ENSURE
:
267 iseq_set_exception_local_table(iseq
);
268 COMPILE_POPED(ret
, "ensure", node
);
270 case ISEQ_TYPE_DEFINED_GUARD
:
271 iseq_set_local_table(iseq
, 0);
272 COMPILE(ret
, "defined guard", node
);
275 rb_bug("unknown scope");
279 if (iseq
->type
== ISEQ_TYPE_RESCUE
|| iseq
->type
== ISEQ_TYPE_ENSURE
) {
280 ADD_INSN2(ret
, 0, getdynamic
, INT2FIX(2), INT2FIX(0));
281 ADD_INSN1(ret
, 0, throw, INT2FIX(0) /* continue throw */ );
284 ADD_INSN(ret
, iseq
->compile_data
->last_line
, leave
);
287 return iseq_setup(iseq
, ret
);
291 iseq_translate_threaded_code(rb_iseq_t
*iseq
)
293 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
294 extern const void **vm_get_insns_address_table(void);
295 #if OPT_DIRECT_THREADED_CODE
296 const void * const *table
= vm_get_insns_address_table();
298 const void * const *table
= vm_get_insns_address_table();
302 iseq
->iseq_encoded
= ALLOC_N(VALUE
, iseq
->iseq_size
);
303 MEMCPY(iseq
->iseq_encoded
, iseq
->iseq
, VALUE
, iseq
->iseq_size
);
305 for (i
= 0; i
< iseq
->iseq_size
; /* */ ) {
306 int insn
= iseq
->iseq_encoded
[i
];
307 int len
= insn_len(insn
);
308 iseq
->iseq_encoded
[i
] = (VALUE
)table
[insn
];
312 iseq
->iseq_encoded
= iseq
->iseq
;
317 /*********************************************/
318 /* definition of data structure for compiler */
319 /*********************************************/
322 compile_data_alloc(rb_iseq_t
*iseq
, size_t size
)
325 struct iseq_compile_data_storage
*storage
=
326 iseq
->compile_data
->storage_current
;
328 if (storage
->pos
+ size
> storage
->size
) {
329 unsigned long alloc_size
= storage
->size
* 2;
332 if (alloc_size
< size
) {
336 storage
->next
= (void *)ALLOC_N(char, alloc_size
+
338 iseq_compile_data_storage
));
339 storage
= iseq
->compile_data
->storage_current
= storage
->next
;
342 storage
->size
= alloc_size
;
343 storage
->buff
= (char *)(&storage
->buff
+ 1);
346 ptr
= (void *)&storage
->buff
[storage
->pos
];
347 storage
->pos
+= size
;
352 compile_data_alloc_insn(rb_iseq_t
*iseq
)
354 return (INSN
*)compile_data_alloc(iseq
, sizeof(INSN
));
358 compile_data_alloc_label(rb_iseq_t
*iseq
)
360 return (LABEL
*)compile_data_alloc(iseq
, sizeof(LABEL
));
364 compile_data_alloc_adjust(rb_iseq_t
*iseq
)
366 return (ADJUST
*)compile_data_alloc(iseq
, sizeof(ADJUST
));
370 * elem1, elemX => elem1, elem2, elemX
373 INSERT_ELEM_NEXT(LINK_ELEMENT
*elem1
, LINK_ELEMENT
*elem2
)
375 elem2
->next
= elem1
->next
;
379 elem2
->next
->prev
= elem2
;
385 * elemX, elem1 => elemX, elem2, elem1
388 INSERT_ELEM_PREV(LINK_ELEMENT
*elem1
, LINK_ELEMENT
*elem2
)
390 elem2
->prev
= elem1
->prev
;
394 elem2
->prev
->next
= elem2
;
400 * elemX, elem1, elemY => elemX, elem2, elemY
403 REPLACE_ELEM(LINK_ELEMENT
*elem1
, LINK_ELEMENT
*elem2
)
405 elem2
->prev
= elem1
->prev
;
406 elem2
->next
= elem1
->next
;
408 elem1
->prev
->next
= elem2
;
411 elem1
->next
->prev
= elem2
;
416 REMOVE_ELEM(LINK_ELEMENT
*elem
)
418 elem
->prev
->next
= elem
->next
;
420 elem
->next
->prev
= elem
->prev
;
424 static LINK_ELEMENT
*
425 FIRST_ELEMENT(LINK_ANCHOR
*anchor
)
427 return anchor
->anchor
.next
;
431 static LINK_ELEMENT
*
432 LAST_ELEMENT(LINK_ANCHOR
*anchor
)
438 static LINK_ELEMENT
*
439 POP_ELEMENT(ISEQ_ARG_DECLARE LINK_ANCHOR
*anchor
)
441 LINK_ELEMENT
*elem
= anchor
->last
;
442 anchor
->last
= anchor
->last
->prev
;
443 anchor
->last
->next
= 0;
444 verify_list("pop", anchor
);
448 #define POP_ELEMENT(anchor) POP_ELEMENT(iseq, anchor)
452 static LINK_ELEMENT
*
453 SHIFT_ELEMENT(LINK_ANCHOR
*anchor
)
455 LINK_ELEMENT
*elem
= anchor
->anchor
.next
;
457 anchor
->anchor
.next
= elem
->next
;
465 LIST_SIZE(LINK_ANCHOR
*anchor
)
467 LINK_ELEMENT
*elem
= anchor
->anchor
.next
;
478 LIST_SIZE_ZERO(LINK_ANCHOR
*anchor
)
480 if (anchor
->anchor
.next
== 0) {
492 * anc1: e1, e2, e3, e4, e5
493 * anc2: e4, e5 (broken)
496 APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR
*anc1
, LINK_ANCHOR
*anc2
)
498 if (anc2
->anchor
.next
) {
499 anc1
->last
->next
= anc2
->anchor
.next
;
500 anc2
->anchor
.next
->prev
= anc1
->last
;
501 anc1
->last
= anc2
->last
;
503 verify_list("append", anc1
);
506 #define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, anc1, anc2)
513 * anc1: e4, e5, e1, e2, e3
514 * anc2: e4, e5 (broken)
517 INSERT_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR
*anc1
, LINK_ANCHOR
*anc2
)
519 if (anc2
->anchor
.next
) {
520 LINK_ELEMENT
*first
= anc1
->anchor
.next
;
521 anc1
->anchor
.next
= anc2
->anchor
.next
;
522 anc1
->anchor
.next
->prev
= &anc1
->anchor
;
523 anc2
->last
->next
= first
;
525 first
->prev
= anc2
->last
;
528 anc1
->last
= anc2
->last
;
532 verify_list("append", anc1
);
535 #define INSERT_LIST(anc1, anc2) INSERT_LIST(iseq, anc1, anc2)
547 SWAP_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR
*anc1
, LINK_ANCHOR
*anc2
)
549 LINK_ANCHOR tmp
= *anc2
;
555 verify_list("swap1", anc1
);
556 verify_list("swap2", anc2
);
559 #define SWAP_LIST(anc1, anc2) SWAP_LIST(iseq, anc1, anc2)
563 REVERSE_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR
*anc
)
565 LINK_ELEMENT
*first
, *last
, *elem
, *e
;
566 first
= &anc
->anchor
;
571 anc
->anchor
.next
= last
;
580 elem
->next
= elem
->prev
;
589 verify_list("reverse", anc
);
593 #define REVERSE_LIST(anc) REVERSE_LIST(iseq, anc)
599 debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR
*anchor
)
601 LINK_ELEMENT
*list
= FIRST_ELEMENT(anchor
);
603 printf("anch: %p, frst: %p, last: %p\n", &anchor
->anchor
,
604 anchor
->anchor
.next
, anchor
->last
);
606 printf("curr: %p, next: %p, prev: %p, type: %d\n", list
, list
->next
,
607 list
->prev
, FIX2INT(list
->type
));
612 dump_disasm_list(anchor
->anchor
.next
);
613 verify_list("debug list", anchor
);
616 #define debug_list(anc) debug_list(iseq, anc)
621 new_label_body(rb_iseq_t
*iseq
, int line
)
623 LABEL
*labelobj
= compile_data_alloc_label(iseq
);
625 labelobj
->link
.type
= ISEQ_ELEMENT_LABEL
;
626 labelobj
->link
.next
= 0;
628 labelobj
->label_no
= iseq
->compile_data
->label_no
++;
629 labelobj
->sc_state
= 0;
635 new_adjust_body(rb_iseq_t
*iseq
, LABEL
*label
, int line
)
637 ADJUST
*adjust
= compile_data_alloc_adjust(iseq
);
638 adjust
->link
.type
= ISEQ_ELEMENT_ADJUST
;
639 adjust
->link
.next
= 0;
640 adjust
->label
= label
;
641 adjust
->line_no
= line
;
646 new_insn_core(rb_iseq_t
*iseq
, int line_no
,
647 int insn_id
, int argc
, VALUE
*argv
)
649 INSN
*iobj
= compile_data_alloc_insn(iseq
);
651 iobj
->link
.type
= ISEQ_ELEMENT_INSN
;
653 iobj
->insn_id
= insn_id
;
654 iobj
->line_no
= line_no
;
655 iobj
->operands
= argv
;
656 iobj
->operand_size
= argc
;
662 new_insn_body(rb_iseq_t
*iseq
, int line_no
, int insn_id
, int argc
, ...)
668 va_init_list(argv
, argc
);
669 operands
= (VALUE
*)compile_data_alloc(iseq
, sizeof(VALUE
) * argc
);
670 for (i
= 0; i
< argc
; i
++) {
671 VALUE v
= va_arg(argv
, VALUE
);
676 return new_insn_core(iseq
, line_no
, insn_id
, argc
, operands
);
680 new_insn_send(rb_iseq_t
*iseq
, int line_no
,
681 VALUE id
, VALUE argc
, VALUE block
, VALUE flag
)
685 (VALUE
*)compile_data_alloc(iseq
, sizeof(VALUE
) * 5);
691 iobj
= new_insn_core(iseq
, line_no
, BIN(send
), 5, operands
);
696 new_child_iseq(rb_iseq_t
*iseq
, NODE
*node
,
697 VALUE name
, VALUE parent
, VALUE type
)
701 debugs("[new_child_iseq]> ---------------------------------------\n");
702 ret
= rb_iseq_new_with_opt(node
, name
, iseq_filename(iseq
->self
),
703 parent
, type
, iseq
->compile_data
->option
);
704 debugs("[new_child_iseq]< ---------------------------------------\n");
705 iseq_add_mark_object(iseq
, ret
);
710 iseq_setup(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
)
712 /* debugs("[compile step 2] (iseq_array_to_linkedlist)\n"); */
714 if (compile_debug
> 5)
715 dump_disasm_list(FIRST_ELEMENT(anchor
));
717 debugs("[compile step 3.1 (iseq_optimize)]\n");
718 iseq_optimize(iseq
, anchor
);
720 if (compile_debug
> 5)
721 dump_disasm_list(FIRST_ELEMENT(anchor
));
723 if (iseq
->compile_data
->option
->instructions_unification
) {
724 debugs("[compile step 3.2 (iseq_insns_unification)]\n");
725 iseq_insns_unification(iseq
, anchor
);
726 if (compile_debug
> 5)
727 dump_disasm_list(FIRST_ELEMENT(anchor
));
730 if (iseq
->compile_data
->option
->stack_caching
) {
731 debugs("[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
732 iseq_set_sequence_stackcaching(iseq
, anchor
);
733 if (compile_debug
> 5)
734 dump_disasm_list(FIRST_ELEMENT(anchor
));
737 debugs("[compile step 4.1 (iseq_set_sequence)]\n");
738 iseq_set_sequence(iseq
, anchor
);
739 if (compile_debug
> 5)
740 dump_disasm_list(FIRST_ELEMENT(anchor
));
742 debugs("[compile step 4.2 (iseq_set_exception_table)]\n");
743 iseq_set_exception_table(iseq
);
745 debugs("[compile step 4.3 (set_optargs_table)] \n");
746 iseq_set_optargs_table(iseq
);
748 debugs("[compile step 5 (iseq_translate_threaded_code)] \n");
749 iseq_translate_threaded_code(iseq
);
751 if (compile_debug
> 1) {
752 VALUE str
= ruby_iseq_disasm(iseq
->self
);
753 printf("%s\n", StringValueCStr(str
));
756 debugs("[compile step: finish]\n");
762 iseq_set_exception_local_table(rb_iseq_t
*iseq
)
766 CONST_ID(id_dollar_bang
, "#$!");
767 iseq
->local_table
= (ID
*)ALLOC_N(ID
*, 1);
768 iseq
->local_table_size
= 1;
769 iseq
->local_size
= iseq
->local_table_size
+ 1;
770 iseq
->local_table
[0] = id_dollar_bang
;
775 get_dyna_var_idx_at_raw(rb_iseq_t
*iseq
, ID id
)
779 for (i
= 0; i
< iseq
->local_table_size
; i
++) {
780 if (iseq
->local_table
[i
] == id
) {
788 get_local_var_idx(rb_iseq_t
*iseq
, ID id
)
790 int idx
= get_dyna_var_idx_at_raw(iseq
->local_iseq
, id
);
793 rb_bug("get_local_var_idx: %d", idx
);
800 get_dyna_var_idx(rb_iseq_t
*iseq
, ID id
, int *level
, int *ls
)
802 int lv
= 0, idx
= -1;
805 idx
= get_dyna_var_idx_at_raw(iseq
, id
);
809 iseq
= iseq
->parent_iseq
;
814 rb_bug("get_dyna_var_idx: -1");
818 *ls
= iseq
->local_size
;
823 iseq_set_arguments(rb_iseq_t
*iseq
, LINK_ANCHOR
*optargs
, NODE
*node_args
)
825 debugs("iseq_set_arguments: %s\n", node_args
? "" : "0");
828 NODE
*node_aux
= node_args
->nd_next
;
829 NODE
*node_opt
= node_args
->nd_opt
;
835 if (nd_type(node_args
) != NODE_ARGS
) {
836 rb_bug("iseq_set_arguments: NODE_ARGS is expected, but %s",
837 ruby_node_name(nd_type(node_args
)));
841 * new argument infromation:
842 * NODE_ARGS [m: int, o: NODE_OPT_ARG, ->]
843 * NODE_ARGS_AUX [r: ID, b: ID, ->]
844 * NODE_ARGS_AUX [Pst: id, Plen: int, init: NODE*]
845 * optarg information:
846 * NODE_OPT_ARGS [idx, expr, next ->]
848 * NODE_AND(m_init, p_init)
849 * if "r" is 1, it's means "{|x,|}" type block parameter.
852 iseq
->argc
= node_args
->nd_frml
;
853 debugs(" - argc: %d\n", iseq
->argc
);
856 rest_id
= node_aux
->nd_rest
;
861 block_id
= (ID
)node_aux
->nd_body
;
862 node_aux
= node_aux
->nd_next
;
865 ID post_start_id
= node_aux
->nd_pid
;
866 iseq
->arg_post_start
= get_dyna_var_idx_at_raw(iseq
, post_start_id
);
867 iseq
->arg_post_len
= node_aux
->nd_plen
;
868 node_init
= node_aux
->nd_next
;
873 NODE
*node
= node_opt
;
875 VALUE labels
= rb_ary_new();
879 label
= NEW_LABEL(nd_line(node
));
880 rb_ary_push(labels
, (VALUE
)label
| 1);
881 ADD_LABEL(optargs
, label
);
882 COMPILE_POPED(optargs
, "optarg", node
->nd_body
);
883 node
= node
->nd_next
;
888 label
= NEW_LABEL(nd_line(node_args
));
889 rb_ary_push(labels
, (VALUE
)label
| 1);
890 ADD_LABEL(optargs
, label
);
894 iseq
->arg_opt_table
= ALLOC_N(VALUE
, i
);
895 MEMCPY(iseq
->arg_opt_table
, RARRAY_PTR(labels
), VALUE
, i
);
896 for (j
= 0; j
< i
; j
++) {
897 iseq
->arg_opt_table
[j
] &= ~1;
905 if (node_init
->nd_1st
) { /* m_init */
906 COMPILE_POPED(optargs
, "init arguments (m)", node_init
->nd_1st
);
908 if (node_init
->nd_2nd
) { /* p_init */
909 COMPILE_POPED(optargs
, "init arguments (p)", node_init
->nd_2nd
);
914 iseq
->arg_rest
= get_dyna_var_idx_at_raw(iseq
, rest_id
);
916 if (iseq
->arg_rest
== -1) {
917 rb_bug("arg_rest: -1");
920 if (iseq
->arg_post_start
== 0) {
921 iseq
->arg_post_start
= iseq
->arg_rest
+ 1;
926 iseq
->arg_block
= get_dyna_var_idx_at_raw(iseq
, block_id
);
929 if (iseq
->arg_opts
!= 0 || iseq
->arg_post_len
!= 0 ||
930 iseq
->arg_rest
!= -1 || iseq
->arg_block
!= -1) {
931 iseq
->arg_simple
= 0;
933 /* set arg_size: size of arguments */
934 if (iseq
->arg_block
!= -1) {
935 iseq
->arg_size
= iseq
->arg_block
+ 1;
937 else if (iseq
->arg_post_len
) {
938 iseq
->arg_size
= iseq
->arg_post_start
+ iseq
->arg_post_len
;
940 else if (iseq
->arg_rest
!= -1) {
941 iseq
->arg_size
= iseq
->arg_rest
+ 1;
943 else if (iseq
->arg_opts
) {
944 iseq
->arg_size
= iseq
->argc
+ iseq
->arg_opts
- 1;
947 iseq
->arg_size
= iseq
->argc
;
951 iseq
->arg_simple
= 1;
952 iseq
->arg_size
= iseq
->argc
;
955 if (iseq
->type
== ISEQ_TYPE_BLOCK
) {
956 if (iseq
->arg_opts
== 0 && iseq
->arg_post_len
== 0 && iseq
->arg_rest
== -1) {
957 if (iseq
->argc
== 1 && last_comma
== 0) {
959 iseq
->arg_simple
|= 0x02;
965 iseq
->arg_simple
= 1;
972 iseq_set_local_table(rb_iseq_t
*iseq
, ID
*tbl
)
985 iseq
->local_table
= (ID
*)ALLOC_N(ID
*, size
);
986 MEMCPY(iseq
->local_table
, tbl
, ID
*, size
);
989 iseq
->local_size
= iseq
->local_table_size
= size
;
990 iseq
->local_size
+= 1;
992 if (lfp == dfp ) { // top, class, method
999 debugs("iseq_set_local_table: %d, %d\n", iseq
->local_size
, iseq
->local_table_size
);
1004 ruby insn object array -> raw instruction sequence
1007 iseq_set_sequence(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
)
1011 struct iseq_insn_info_entry
*insn_info_table
;
1013 VALUE
*generated_iseq
;
1015 int k
, pos
, sp
, stack_max
= 0, line
= 0;
1017 /* set label position */
1018 list
= FIRST_ELEMENT(anchor
);
1021 switch (list
->type
) {
1022 case ISEQ_ELEMENT_INSN
:
1024 iobj
= (INSN
*)list
;
1025 line
= iobj
->line_no
;
1026 pos
+= insn_data_length(iobj
);
1030 case ISEQ_ELEMENT_LABEL
:
1032 lobj
= (LABEL
*)list
;
1033 lobj
->position
= pos
;
1037 case ISEQ_ELEMENT_NONE
:
1042 case ISEQ_ELEMENT_ADJUST
:
1044 ADJUST
*adjust
= (ADJUST
*)list
;
1045 if (adjust
->line_no
!= -1) {
1046 pos
+= 2 /* insn + 1 operand */;
1052 dump_disasm_list(FIRST_ELEMENT(anchor
));
1053 dump_disasm_list(list
);
1054 rb_compile_error(RSTRING_PTR(iseq
->filename
), line
,
1055 "error: set_sequence");
1061 /* make instruction sequence */
1062 generated_iseq
= ALLOC_N(VALUE
, pos
);
1063 insn_info_table
= ALLOC_N(struct iseq_insn_info_entry
, k
);
1065 list
= FIRST_ELEMENT(anchor
);
1069 switch (list
->type
) {
1070 case ISEQ_ELEMENT_INSN
:
1076 iobj
= (INSN
*)list
;
1079 sp
= calc_sp_depth(sp
, iobj
);
1080 if (sp
> stack_max
) {
1084 /* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */
1086 operands
= iobj
->operands
;
1087 insn
= iobj
->insn_id
;
1088 generated_iseq
[pos
] = insn
;
1089 types
= insn_op_types(insn
);
1090 len
= insn_len(insn
);
1093 if (iobj
->operand_size
!= len
- 1) {
1094 dump_disasm_list(list
);
1095 rb_compile_error(RSTRING_PTR(iseq
->filename
), iobj
->line_no
,
1096 "operand size miss! (%d for %d)",
1097 iobj
->operand_size
, len
- 1);
1101 for (j
= 0; types
[j
]; j
++) {
1102 char type
= types
[j
];
1103 /* printf("--> [%c - (%d-%d)]\n", type, k, j); */
1107 /* label(destination position) */
1108 lobj
= (LABEL
*)operands
[j
];
1109 if (lobj
->set
!= Qtrue
) {
1110 rb_compile_error(RSTRING_PTR(iseq
->filename
), iobj
->line_no
,
1113 if (lobj
->sp
== -1) {
1116 generated_iseq
[pos
+ 1 + j
] =
1117 lobj
->position
- (pos
+ len
);
1126 VALUE lits
= operands
[j
];
1127 VALUE map
= rb_hash_new();
1129 for (i
=0; i
< RARRAY_LEN(lits
); i
+=2) {
1130 VALUE obj
= rb_ary_entry(lits
, i
);
1131 VALUE lv
= rb_ary_entry(lits
, i
+1);
1132 lobj
= (LABEL
*)(lv
& ~1);
1134 if (lobj
->set
!= Qtrue
) {
1135 rb_compile_error(RSTRING_PTR(iseq
->filename
), iobj
->line_no
,
1138 rb_hash_aset(map
, obj
, INT2FIX(lobj
->position
- (pos
+len
)));
1140 generated_iseq
[pos
+ 1 + j
] = map
;
1141 iseq_add_mark_object(iseq
, map
);
1146 case TS_NUM
: /* ulong */
1147 generated_iseq
[pos
+ 1 + j
] = FIX2INT(operands
[j
]);
1149 case TS_ISEQ
: /* iseq */
1151 VALUE v
= operands
[j
];
1152 rb_iseq_t
*block
= 0;
1154 GetISeqPtr(v
, block
);
1156 generated_iseq
[pos
+ 1 + j
] = (VALUE
)block
;
1159 case TS_VALUE
: /* VALUE */
1161 VALUE v
= operands
[j
];
1162 generated_iseq
[pos
+ 1 + j
] = v
;
1163 /* to mark ruby object */
1164 iseq_add_mark_object(iseq
, v
);
1167 case TS_IC
: /* inline cache */
1169 VALUE v
= (VALUE
)NEW_INLINE_CACHE_ENTRY();
1170 generated_iseq
[pos
+ 1 + j
] = v
;
1171 iseq_add_mark_object(iseq
, v
);
1174 case TS_ID
: /* ID */
1175 generated_iseq
[pos
+ 1 + j
] = SYM2ID(operands
[j
]);
1179 struct global_entry
*entry
=
1180 (struct global_entry
*)(operands
[j
] & (~1));
1181 generated_iseq
[pos
+ 1 + j
] = (VALUE
)entry
;
1185 rb_compile_error(RSTRING_PTR(iseq
->filename
), iobj
->line_no
,
1186 "unknown operand type: %c", type
);
1190 insn_info_table
[k
].line_no
= iobj
->line_no
;
1191 insn_info_table
[k
].position
= pos
;
1192 insn_info_table
[k
].sp
= sp
;
1197 case ISEQ_ELEMENT_LABEL
:
1199 lobj
= (LABEL
*)list
;
1200 if (lobj
->sp
== -1) {
1208 case ISEQ_ELEMENT_ADJUST
:
1210 ADJUST
*adjust
= (ADJUST
*)list
;
1213 if (adjust
->label
) {
1214 sp
= adjust
->label
->sp
;
1220 if (adjust
->line_no
!= -1) {
1221 if (orig_sp
- sp
> 0) {
1222 insn_info_table
[k
].line_no
= adjust
->line_no
;
1223 insn_info_table
[k
].position
= pos
;
1224 insn_info_table
[k
].sp
= sp
;
1226 generated_iseq
[pos
++] = BIN(adjuststack
);
1227 generated_iseq
[pos
++] = orig_sp
- sp
;
1229 else if (orig_sp
- sp
== 0) {
1230 /* jump to next insn */
1231 insn_info_table
[k
].line_no
= adjust
->line_no
;
1232 insn_info_table
[k
].position
= pos
;
1233 insn_info_table
[k
].sp
= sp
;
1235 generated_iseq
[pos
++] = BIN(jump
);
1236 generated_iseq
[pos
++] = 0;
1239 rb_bug("iseq_set_sequence: adjust bug");
1252 /* this check need dead code elimination */
1254 rb_bug("SP is not 0 on %s (%d)\n", RSTRING_PTR(iseq
->name
), sp
);
1258 iseq
->iseq
= (void *)generated_iseq
;
1259 iseq
->iseq_size
= pos
;
1260 iseq
->insn_info_table
= insn_info_table
;
1261 iseq
->insn_info_size
= k
;
1262 iseq
->stack_max
= stack_max
;
1268 label_get_position(LABEL
*lobj
)
1270 return lobj
->position
;
1274 label_get_sp(LABEL
*lobj
)
1280 iseq_set_exception_table(rb_iseq_t
*iseq
)
1284 struct iseq_catch_table_entry
*entry
;
1286 tlen
= RARRAY_LEN(iseq
->compile_data
->catch_table_ary
);
1287 tptr
= RARRAY_PTR(iseq
->compile_data
->catch_table_ary
);
1289 iseq
->catch_table
= tlen
? ALLOC_N(struct iseq_catch_table_entry
, tlen
) : 0;
1290 iseq
->catch_table_size
= tlen
;
1292 for (i
= 0; i
< tlen
; i
++) {
1293 ptr
= RARRAY_PTR(tptr
[i
]);
1294 entry
= &iseq
->catch_table
[i
];
1295 entry
->type
= ptr
[0] & 0xffff;
1296 entry
->start
= label_get_position((LABEL
*)(ptr
[1] & ~1));
1297 entry
->end
= label_get_position((LABEL
*)(ptr
[2] & ~1));
1298 entry
->iseq
= ptr
[3];
1300 /* register iseq as mark object */
1301 if (entry
->iseq
!= 0) {
1302 iseq_add_mark_object(iseq
, entry
->iseq
);
1307 LABEL
*lobj
= (LABEL
*)(ptr
[4] & ~1);
1308 entry
->cont
= label_get_position(lobj
);
1309 entry
->sp
= label_get_sp(lobj
);
1311 /* TODO: Dirty Hack! Fix me */
1312 if (entry
->type
== CATCH_TYPE_RESCUE
||
1313 entry
->type
== CATCH_TYPE_BREAK
||
1314 entry
->type
== CATCH_TYPE_NEXT
) {
1323 iseq
->compile_data
->catch_table_ary
= 0; /* free */
1328 * set optional argument table
1329 * def foo(a, b=expr1, c=expr2)
1337 iseq_set_optargs_table(rb_iseq_t
*iseq
)
1341 if (iseq
->arg_opts
!= 0) {
1342 for (i
= 0; i
< iseq
->arg_opts
; i
++) {
1343 iseq
->arg_opt_table
[i
] =
1344 label_get_position((LABEL
*)iseq
->arg_opt_table
[i
]);
1350 static LINK_ELEMENT
*
1351 get_destination_insn(INSN
*iobj
)
1353 LABEL
*lobj
= (LABEL
*)OPERAND_AT(iobj
, 0);
1356 list
= lobj
->link
.next
;
1358 if (list
->type
== ISEQ_ELEMENT_INSN
|| list
->type
== ISEQ_ELEMENT_ADJUST
) {
1366 static LINK_ELEMENT
*
1367 get_next_insn(INSN
*iobj
)
1369 LINK_ELEMENT
*list
= iobj
->link
.next
;
1372 if (list
->type
== ISEQ_ELEMENT_INSN
|| list
->type
== ISEQ_ELEMENT_ADJUST
) {
1380 static LINK_ELEMENT
*
1381 get_prev_insn(INSN
*iobj
)
1383 LINK_ELEMENT
*list
= iobj
->link
.prev
;
1386 if (list
->type
== ISEQ_ELEMENT_INSN
|| list
->type
== ISEQ_ELEMENT_ADJUST
) {
1395 iseq_peephole_optimize(rb_iseq_t
*iseq
, LINK_ELEMENT
*list
, const int do_tailcallopt
)
1397 INSN
*iobj
= (INSN
*)list
;
1399 if (iobj
->insn_id
== BIN(jump
)) {
1400 INSN
*niobj
, *diobj
, *piobj
;
1402 * useless jump elimination:
1408 * => in this case, first jump instruction should jump tp
1411 diobj
= (INSN
*)get_destination_insn(iobj
);
1412 niobj
= (INSN
*)get_next_insn(iobj
);
1414 if (diobj
== niobj
) {
1421 REMOVE_ELEM(&iobj
->link
);
1423 else if (iobj
!= diobj
&& diobj
->insn_id
== BIN(jump
)) {
1424 if (OPERAND_AT(iobj
, 0) != OPERAND_AT(diobj
, 0)) {
1425 OPERAND_AT(iobj
, 0) = OPERAND_AT(diobj
, 0);
1429 else if (diobj
->insn_id
== BIN(leave
)) {
1441 INSN
*eiobj
= new_insn_core(iseq
, iobj
->line_no
, BIN(leave
),
1442 diobj
->operand_size
, diobj
->operands
);
1443 INSN
*popiobj
= new_insn_core(iseq
, iobj
->line_no
,
1446 REPLACE_ELEM((LINK_ELEMENT
*)iobj
, (LINK_ELEMENT
*)eiobj
);
1447 INSERT_ELEM_NEXT((LINK_ELEMENT
*)eiobj
, (LINK_ELEMENT
*)popiobj
);
1451 * useless jump elimination (if/unless destination):
1464 else if ((piobj
= (INSN
*)get_prev_insn(iobj
)) != 0 &&
1465 (piobj
->insn_id
== BIN(branchif
) ||
1466 piobj
->insn_id
== BIN(branchunless
))) {
1467 if (niobj
== (INSN
*)get_destination_insn(piobj
)) {
1468 piobj
->insn_id
= (piobj
->insn_id
== BIN(branchif
))
1469 ? BIN(branchunless
) : BIN(branchif
);
1470 OPERAND_AT(piobj
, 0) = OPERAND_AT(iobj
, 0);
1471 REMOVE_ELEM(&iobj
->link
);
1476 if (iobj
->insn_id
== BIN(branchif
) ||
1477 iobj
->insn_id
== BIN(branchunless
)) {
1486 INSN
*nobj
= (INSN
*)get_destination_insn(iobj
);
1487 if (nobj
->insn_id
== BIN(jump
)) {
1488 OPERAND_AT(iobj
, 0) = OPERAND_AT(nobj
, 0);
1492 if (do_tailcallopt
&& iobj
->insn_id
== BIN(leave
)) {
1497 * send ..., ... | VM_CALL_TAILCALL_BIT, ...
1498 * leave # unreachable
1500 INSN
*piobj
= (INSN
*)get_prev_insn((INSN
*)list
);
1502 if (piobj
->insn_id
== BIN(send
) &&
1503 piobj
->operands
[2] == 0 /* block */
1505 piobj
->operands
[3] = INT2FIX(FIX2INT(piobj
->operands
[3]) | VM_CALL_TAILCALL_BIT
);
1512 insn_set_specialized_instruction(INSN
*iobj
, int insn_id
)
1514 iobj
->insn_id
= insn_id
;
1515 iobj
->operand_size
= 0;
1520 insn_set_specialized_instruction_with_ic(INSN
*iobj
, int insn_id
, int n
)
1523 iobj
->insn_id
= insn_id
;
1524 iobj
->operand_size
= n
;
1527 for (i
=0; i
<n
; i
++) {
1528 iobj
->operands
[i
] = Qnil
;
1536 iseq_specialized_instruction(rb_iseq_t
*iseq
, INSN
*iobj
)
1538 if (iobj
->insn_id
== BIN(send
)) {
1539 ID mid
= SYM2ID(OPERAND_AT(iobj
, 0));
1540 int argc
= FIX2INT(OPERAND_AT(iobj
, 1));
1541 VALUE block
= OPERAND_AT(iobj
, 2);
1542 VALUE flag
= OPERAND_AT(iobj
, 3);
1544 /* TODO: should be more sophisticated search */
1545 if (block
== 0 && flag
== INT2FIX(0)) {
1547 if (mid
== idLength
) {
1548 insn_set_specialized_instruction(iobj
, BIN(opt_length
));
1550 else if (mid
== idSucc
) {
1551 insn_set_specialized_instruction(iobj
, BIN(opt_succ
));
1553 else if (mid
== idNot
) {
1554 insn_set_specialized_instruction_with_ic(iobj
, BIN(opt_not
), 1);
1557 else if (argc
== 1) {
1560 else if (mid
== idPLUS
) {
1561 insn_set_specialized_instruction(iobj
, BIN(opt_plus
));
1563 else if (mid
== idMINUS
) {
1564 insn_set_specialized_instruction(iobj
, BIN(opt_minus
));
1566 else if (mid
== idMULT
) {
1567 insn_set_specialized_instruction(iobj
, BIN(opt_mult
));
1569 else if (mid
== idDIV
) {
1570 insn_set_specialized_instruction(iobj
, BIN(opt_div
));
1572 else if (mid
== idMOD
) {
1573 insn_set_specialized_instruction(iobj
, BIN(opt_mod
));
1575 else if (mid
== idEq
) {
1576 insn_set_specialized_instruction_with_ic(iobj
, BIN(opt_eq
), 1);
1578 else if (mid
== idNeq
) {
1579 insn_set_specialized_instruction_with_ic(iobj
, BIN(opt_neq
), 2);
1581 else if (mid
== idLT
) {
1582 insn_set_specialized_instruction(iobj
, BIN(opt_lt
));
1584 else if (mid
== idLE
) {
1585 insn_set_specialized_instruction(iobj
, BIN(opt_le
));
1587 else if (mid
== idGT
) {
1588 insn_set_specialized_instruction(iobj
, BIN(opt_gt
));
1590 else if (mid
== idGE
) {
1591 insn_set_specialized_instruction(iobj
, BIN(opt_ge
));
1593 else if (mid
== idLTLT
) {
1594 insn_set_specialized_instruction(iobj
, BIN(opt_ltlt
));
1596 else if (mid
== idAREF
) {
1597 insn_set_specialized_instruction(iobj
, BIN(opt_aref
));
1603 if (mid
== idSend
|| mid
== id__send__
) {
1604 OPERAND_AT(iobj
, 3) |= INT2FIX(VM_CALL_SEND_BIT
);
1612 iseq_optimize(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
)
1615 const int do_peepholeopt
= iseq
->compile_data
->option
->peephole_optimization
;
1616 const int do_tailcallopt
= iseq
->compile_data
->option
->tailcall_optimization
;
1617 const int do_si
= iseq
->compile_data
->option
->specialized_instruction
;
1618 const int do_ou
= iseq
->compile_data
->option
->operands_unification
;
1619 list
= FIRST_ELEMENT(anchor
);
1622 if (list
->type
== ISEQ_ELEMENT_INSN
) {
1623 if (do_peepholeopt
) {
1624 iseq_peephole_optimize(iseq
, list
, do_tailcallopt
);
1627 iseq_specialized_instruction(iseq
, (INSN
*)list
);
1630 insn_operands_unification((INSN
*)list
);
1638 #if OPT_INSTRUCTIONS_UNIFICATION
1640 new_unified_insn(rb_iseq_t
*iseq
,
1641 int insn_id
, int size
, LINK_ELEMENT
*seq_list
)
1644 LINK_ELEMENT
*list
= seq_list
;
1646 VALUE
*operands
= 0, *ptr
= 0;
1650 for (i
= 0; i
< size
; i
++) {
1651 iobj
= (INSN
*)list
;
1652 argc
+= iobj
->operand_size
;
1658 (VALUE
*)compile_data_alloc(iseq
, sizeof(VALUE
) * argc
);
1663 for (i
= 0; i
< size
; i
++) {
1664 iobj
= (INSN
*)list
;
1665 MEMCPY(ptr
, iobj
->operands
, VALUE
, iobj
->operand_size
);
1666 ptr
+= iobj
->operand_size
;
1670 return new_insn_core(iseq
, iobj
->line_no
, insn_id
, argc
, operands
);
1675 * This scheme can get more performance if do this optimize with
1676 * label address resolving.
1677 * It's future work (if compile time was bottle neck).
1680 iseq_insns_unification(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
)
1682 #if OPT_INSTRUCTIONS_UNIFICATION
1687 list
= FIRST_ELEMENT(anchor
);
1689 if (list
->type
== ISEQ_ELEMENT_INSN
) {
1690 iobj
= (INSN
*)list
;
1692 if (unified_insns_data
[id
] != 0) {
1693 const int *const *entry
= unified_insns_data
[id
];
1694 for (j
= 1; j
< (int)entry
[0]; j
++) {
1695 const int *unified
= entry
[j
];
1696 LINK_ELEMENT
*li
= list
->next
;
1697 for (k
= 2; k
< unified
[1]; k
++) {
1698 if (li
->type
!= ISEQ_ELEMENT_INSN
||
1699 ((INSN
*)li
)->insn_id
!= unified
[k
]) {
1706 new_unified_insn(iseq
, unified
[0], unified
[1] - 1,
1709 /* insert to list */
1710 niobj
->link
.prev
= (LINK_ELEMENT
*)iobj
->link
.prev
;
1711 niobj
->link
.next
= li
;
1713 li
->prev
= (LINK_ELEMENT
*)niobj
;
1716 list
->prev
->next
= (LINK_ELEMENT
*)niobj
;
1717 list
= (LINK_ELEMENT
*)niobj
;
1729 #if OPT_STACK_CACHING
1731 #define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)]
1732 #define SC_NEXT(insn) sc_insn_next[insn]
1734 #include "opt_sc.inc"
1737 insn_set_sc_state(rb_iseq_t
*iseq
, INSN
*iobj
, int state
)
1742 insn_id
= iobj
->insn_id
;
1743 iobj
->insn_id
= SC_INSN(insn_id
, state
);
1744 nstate
= SC_NEXT(iobj
->insn_id
);
1746 if (insn_id
== BIN(jump
) ||
1747 insn_id
== BIN(branchif
) || insn_id
== BIN(branchunless
)) {
1748 LABEL
*lobj
= (LABEL
*)OPERAND_AT(iobj
, 0);
1750 if (lobj
->sc_state
!= 0) {
1751 if (lobj
->sc_state
!= nstate
) {
1752 dump_disasm_list((LINK_ELEMENT
*)iobj
);
1753 dump_disasm_list((LINK_ELEMENT
*)lobj
);
1754 printf("\n-- %d, %d\n", lobj
->sc_state
, nstate
);
1755 rb_compile_error(RSTRING_PTR(iseq
->filename
), iobj
->lineno
,
1756 "insn_set_sc_state error\n");
1761 lobj
->sc_state
= nstate
;
1763 if (insn_id
== BIN(jump
)) {
1767 else if (insn_id
== BIN(leave
)) {
1775 label_set_sc_state(LABEL
*lobj
, int state
)
1777 if (lobj
->sc_state
!= 0) {
1778 if (lobj
->sc_state
!= state
) {
1779 state
= lobj
->sc_state
;
1783 lobj
->sc_state
= state
;
1793 iseq_set_sequence_stackcaching(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
)
1795 #if OPT_STACK_CACHING
1801 list
= FIRST_ELEMENT(anchor
);
1802 /* dump_disasm_list(list); */
1804 /* for each list element */
1807 switch (list
->type
) {
1808 case ISEQ_ELEMENT_INSN
:
1810 INSN
*iobj
= (INSN
*)list
;
1811 insn_id
= iobj
->insn_id
;
1813 /* dump_disasm_list(list); */
1818 /* exception merge point */
1819 if (state
!= SCS_AX
) {
1821 new_insn_body(iseq
, 0, BIN(reput
), 0);
1823 /* replace this insn */
1824 REPLACE_ELEM(list
, (LINK_ELEMENT
*)rpobj
);
1825 list
= (LINK_ELEMENT
*)rpobj
;
1832 if (state
== SCS_AB
|| state
== SCS_BA
) {
1833 state
= (state
== SCS_AB
? SCS_BA
: SCS_AB
);
1857 rb_compile_error(RSTRING_PTR(iseq
->filename
), iobj
->line_no
,
1860 /* remove useless pop */
1867 } /* end of switch */
1869 state
= insn_set_sc_state(iseq
, iobj
, state
);
1872 case ISEQ_ELEMENT_LABEL
:
1875 lobj
= (LABEL
*)list
;
1877 state
= label_set_sc_state(lobj
, state
);
1891 compile_dstr_fragments(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node
, int *cntp
)
1893 NODE
*list
= node
->nd_next
;
1894 VALUE lit
= node
->nd_lit
;
1897 debugp_param("nd_lit", lit
);
1898 ADD_INSN1(ret
, nd_line(node
), putobject
, node
->nd_lit
);
1901 COMPILE(ret
, "each string", list
->nd_head
);
1903 list
= list
->nd_next
;
1911 compile_dstr(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node
)
1914 compile_dstr_fragments(iseq
, ret
, node
, &cnt
);
1915 ADD_INSN1(ret
, nd_line(node
), concatstrings
, INT2FIX(cnt
));
1920 compile_dregx(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node
)
1923 compile_dstr_fragments(iseq
, ret
, node
, &cnt
);
1924 ADD_INSN2(ret
, nd_line(node
), toregexp
, INT2FIX(node
->nd_cflag
), INT2FIX(cnt
));
1929 compile_branch_condition(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* cond
,
1930 LABEL
*then_label
, LABEL
*else_label
)
1932 switch (nd_type(cond
)) {
1935 LABEL
*label
= NEW_LABEL(nd_line(cond
));
1936 compile_branch_condition(iseq
, ret
, cond
->nd_1st
, label
,
1938 ADD_LABEL(ret
, label
);
1939 compile_branch_condition(iseq
, ret
, cond
->nd_2nd
, then_label
,
1945 LABEL
*label
= NEW_LABEL(nd_line(cond
));
1946 compile_branch_condition(iseq
, ret
, cond
->nd_1st
, then_label
,
1948 ADD_LABEL(ret
, label
);
1949 compile_branch_condition(iseq
, ret
, cond
->nd_2nd
, then_label
,
1953 case NODE_LIT
: /* NODE_LIT is always not true */
1956 /* printf("useless conditon eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
1957 ADD_INSNL(ret
, nd_line(cond
), jump
, then_label
);
1961 /* printf("useless conditon eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
1962 ADD_INSNL(ret
, nd_line(cond
), jump
, else_label
);
1965 COMPILE(ret
, "branch condition", cond
);
1966 ADD_INSNL(ret
, nd_line(cond
), branchunless
, else_label
);
1967 ADD_INSNL(ret
, nd_line(cond
), jump
, then_label
);
1974 compile_array_(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node_root
,
1975 VALUE opt_p
, int poped
)
1977 NODE
*node
= node_root
;
1978 int len
= node
->nd_alen
, line
= nd_line(node
), i
=0;
1979 DECL_ANCHOR(anchor
);
1981 INIT_ANCHOR(anchor
);
1982 if (nd_type(node
) != NODE_ZARRAY
) {
1984 if (nd_type(node
) != NODE_ARRAY
) {
1985 rb_bug("compile_array: This node is not NODE_ARRAY, but %s",
1986 ruby_node_name(nd_type(node
)));
1990 if (opt_p
&& nd_type(node
->nd_head
) != NODE_LIT
) {
1993 COMPILE_(anchor
, "array element", node
->nd_head
, poped
);
1994 node
= node
->nd_next
;
2000 rb_bug("node error: compile_array (%d: %d-%d)",
2001 (int)nd_line(node_root
), len
, i
);
2006 if (opt_p
== Qtrue
) {
2008 VALUE ary
= rb_ary_new();
2011 rb_ary_push(ary
, node
->nd_head
->nd_lit
);
2012 node
= node
->nd_next
;
2015 iseq_add_mark_object_compile_time(iseq
, ary
);
2016 ADD_INSN1(ret
, nd_line(node_root
), duparray
, ary
);
2021 ADD_INSN1(anchor
, line
, newarray
, INT2FIX(len
));
2023 APPEND_LIST(ret
, anchor
);
2029 compile_array(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node_root
, VALUE opt_p
)
2031 return compile_array_(iseq
, ret
, node_root
, opt_p
, 0);
2035 case_when_optimizable_literal(NODE
* node
)
2037 switch (nd_type(node
)) {
2039 VALUE v
= node
->nd_lit
;
2040 if (SYMBOL_P(v
) || rb_obj_is_kind_of(v
, rb_cNumeric
)) {
2046 return node
->nd_lit
;
2052 when_vals(rb_iseq_t
*iseq
, LINK_ANCHOR
*cond_seq
, NODE
*vals
, LABEL
*l1
, VALUE special_literals
)
2058 val
= vals
->nd_head
;
2060 if (special_literals
&&
2061 (lit
= case_when_optimizable_literal(val
)) != Qfalse
) {
2062 rb_ary_push(special_literals
, lit
);
2063 rb_ary_push(special_literals
, (VALUE
)(l1
) | 1);
2066 special_literals
= Qfalse
;
2069 COMPILE(cond_seq
, "when cond", val
);
2070 ADD_INSN1(cond_seq
, nd_line(val
), topn
, INT2FIX(1));
2071 ADD_SEND(cond_seq
, nd_line(val
), ID2SYM(idEqq
), INT2FIX(1));
2072 ADD_INSNL(cond_seq
, nd_line(val
), branchif
, l1
);
2073 vals
= vals
->nd_next
;
2075 return special_literals
;
2079 compile_massign_lhs(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
*node
)
2081 switch (nd_type(node
)) {
2082 case NODE_ATTRASGN
: {
2086 COMPILE_POPED(ret
, "masgn lhs (NODE_ATTRASGN)", node
);
2087 POP_ELEMENT(ret
); /* pop pop insn */
2088 iobj
= (INSN
*)POP_ELEMENT(ret
); /* pop send insn */
2090 dupidx
= iobj
->operands
[1];
2091 dupidx
= INT2FIX(FIX2INT(dupidx
) + 1);
2092 iobj
->operands
[1] = dupidx
;
2094 ADD_INSN1(ret
, nd_line(node
), topn
, dupidx
);
2095 ADD_ELEM(ret
, (LINK_ELEMENT
*)iobj
);
2096 ADD_INSN(ret
, nd_line(node
), pop
); /* result */
2097 ADD_INSN(ret
, nd_line(node
), pop
); /* rhs */
2101 DECL_ANCHOR(anchor
);
2102 INIT_ANCHOR(anchor
);
2103 COMPILE_POPED(anchor
, "nest masgn lhs", node
);
2104 REMOVE_ELEM(FIRST_ELEMENT(anchor
));
2105 ADD_SEQ(ret
, anchor
);
2109 DECL_ANCHOR(anchor
);
2110 INIT_ANCHOR(anchor
);
2111 COMPILE_POPED(anchor
, "masgn lhs", node
);
2112 REMOVE_ELEM(FIRST_ELEMENT(anchor
));
2113 ADD_SEQ(ret
, anchor
);
2121 compile_massign_opt_lhs(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
*lhsn
)
2124 compile_massign_opt_lhs(iseq
, ret
, lhsn
->nd_next
);
2125 compile_massign_lhs(iseq
, ret
, lhsn
->nd_head
);
2130 compile_massign_opt(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
,
2131 NODE
*rhsn
, NODE
*orig_lhsn
)
2134 const int memsize
= sizeof(mem
) / sizeof(mem
[0]);
2136 int llen
= 0, rlen
= 0;
2138 NODE
*lhsn
= orig_lhsn
;
2140 #define MEMORY(v) { \
2142 if (memindex == memsize) return 0; \
2143 for (i=0; i<memindex; i++) { \
2144 if (mem[i] == (v)) return 0; \
2146 mem[memindex++] = (v); \
2149 if (rhsn
== 0 || nd_type(rhsn
) != NODE_ARRAY
) {
2154 NODE
*ln
= lhsn
->nd_head
;
2155 switch (nd_type(ln
)) {
2160 case NODE_DASGN_CURR
:
2169 lhsn
= lhsn
->nd_next
;
2175 COMPILE_POPED(ret
, "masgn val (poped)", rhsn
->nd_head
);
2178 COMPILE(ret
, "masgn val", rhsn
->nd_head
);
2180 rhsn
= rhsn
->nd_next
;
2185 for (i
=0; i
<llen
-rlen
; i
++) {
2186 ADD_INSN(ret
, nd_line(orig_lhsn
), putnil
);
2190 compile_massign_opt_lhs(iseq
, ret
, orig_lhsn
);
2195 compile_massign(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
*node
, int poped
)
2197 NODE
*rhsn
= node
->nd_value
;
2198 NODE
*splatn
= node
->nd_args
;
2199 NODE
*lhsn
= node
->nd_head
;
2200 int lhs_splat
= (splatn
&& (VALUE
)splatn
!= (VALUE
)-1) ? 1 : 0;
2202 if (!poped
|| splatn
|| !compile_massign_opt(iseq
, ret
, rhsn
, lhsn
)) {
2204 DECL_ANCHOR(lhsseq
);
2206 INIT_ANCHOR(lhsseq
);
2209 compile_massign_lhs(iseq
, lhsseq
, lhsn
->nd_head
);
2211 lhsn
= lhsn
->nd_next
;
2214 COMPILE(ret
, "normal masgn rhs", rhsn
);
2217 ADD_INSN(ret
, nd_line(node
), dup
);
2220 ADD_INSN2(ret
, nd_line(node
), expandarray
,
2221 INT2FIX(llen
), INT2FIX(lhs_splat
));
2222 ADD_SEQ(ret
, lhsseq
);
2225 if (nd_type(splatn
) == NODE_POSTARG
) {
2226 /*a, b, *r, p1, p2 */
2227 NODE
*postn
= splatn
->nd_2nd
;
2228 NODE
*restn
= splatn
->nd_1st
;
2229 int num
= postn
->nd_alen
;
2230 int flag
= 0x02 | (((VALUE
)restn
== (VALUE
)-1) ? 0x00 : 0x01);
2232 ADD_INSN2(ret
, nd_line(splatn
), expandarray
,
2233 INT2FIX(num
), INT2FIX(flag
));
2235 if ((VALUE
)restn
!= (VALUE
)-1) {
2236 compile_massign_lhs(iseq
, ret
, restn
);
2239 compile_massign_lhs(iseq
, ret
, postn
->nd_head
);
2240 postn
= postn
->nd_next
;
2245 compile_massign_lhs(iseq
, ret
, splatn
);
2253 compile_colon2(rb_iseq_t
*iseq
, NODE
* node
,
2254 LINK_ANCHOR
*pref
, LINK_ANCHOR
*body
)
2256 switch (nd_type(node
)) {
2258 debugi("compile_colon2 - colon", node
->nd_vid
);
2259 ADD_INSN1(body
, nd_line(node
), getconstant
, ID2SYM(node
->nd_vid
));
2262 debugi("compile_colon2 - colon3", node
->nd_mid
);
2263 ADD_INSN(body
, nd_line(node
), pop
);
2264 ADD_INSN1(body
, nd_line(node
), putobject
, rb_cObject
);
2265 ADD_INSN1(body
, nd_line(node
), getconstant
, ID2SYM(node
->nd_mid
));
2268 compile_colon2(iseq
, node
->nd_head
, pref
, body
);
2269 debugi("compile_colon2 - colon2", node
->nd_mid
);
2270 ADD_INSN1(body
, nd_line(node
), getconstant
, ID2SYM(node
->nd_mid
));
2273 COMPILE(pref
, "const colon2 prefix", node
);
2280 compile_cpath(LINK_ANCHOR
*ret
, rb_iseq_t
*iseq
, NODE
*cpath
)
2282 if (nd_type(cpath
) == NODE_COLON3
) {
2283 /* toplevel class ::Foo */
2284 ADD_INSN1(ret
, nd_line(cpath
), putobject
, rb_cObject
);
2287 else if (cpath
->nd_head
) {
2289 COMPILE(ret
, "nd_else->nd_head", cpath
->nd_head
);
2293 /* class at cbase Foo */
2294 ADD_INSN1(ret
, nd_line(cpath
), putspecialobject
, INT2FIX(VM_SPECIAL_OBJECT_CBASE
));
2300 defined_expr(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
,
2301 NODE
*node
, LABEL
**lfinish
, VALUE needstr
)
2303 const char *estr
= 0;
2304 enum node_type type
;
2306 switch (type
= nd_type(node
)) {
2326 defined_expr(iseq
, ret
, vals
->nd_head
, lfinish
, Qfalse
);
2329 lfinish
[1] = NEW_LABEL(nd_line(node
));
2331 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2332 } while ((vals
= vals
->nd_next
) != NULL
);
2337 estr
= "expression";
2343 estr
= "local-variable";
2347 ADD_INSN(ret
, nd_line(node
), putnil
);
2348 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_IVAR
),
2349 ID2SYM(node
->nd_vid
), needstr
);
2353 ADD_INSN(ret
, nd_line(node
), putnil
);
2354 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_GVAR
),
2355 ((VALUE
)node
->nd_entry
) | 1, needstr
);
2359 ADD_INSN(ret
, nd_line(node
), putnil
);
2360 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_CVAR
),
2361 ID2SYM(node
->nd_vid
), needstr
);
2365 ADD_INSN(ret
, nd_line(node
), putnil
);
2366 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_CONST
),
2367 ID2SYM(node
->nd_vid
), needstr
);
2371 lfinish
[1] = NEW_LABEL(nd_line(node
));
2373 defined_expr(iseq
, ret
, node
->nd_head
, lfinish
, Qfalse
);
2374 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2376 if (rb_is_const_id(node
->nd_mid
)) {
2377 COMPILE(ret
, "defined/colon2#nd_head", node
->nd_head
);
2378 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_CONST
),
2379 ID2SYM(node
->nd_mid
), needstr
);
2382 COMPILE(ret
, "defined/colon2#nd_head", node
->nd_head
);
2383 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_METHOD
),
2384 ID2SYM(node
->nd_mid
), needstr
);
2388 ADD_INSN1(ret
, nd_line(node
), putobject
, rb_cObject
);
2389 ADD_INSN3(ret
, nd_line(node
), defined
,
2390 INT2FIX(DEFINED_CONST
), ID2SYM(node
->nd_mid
), needstr
);
2393 /* method dispatch */
2397 case NODE_ATTRASGN
:{
2402 if (node
->nd_recv
== (NODE
*)1) break;
2410 lfinish
[1] = NEW_LABEL(nd_line(node
));
2412 if (node
->nd_args
) {
2413 defined_expr(iseq
, ret
, node
->nd_args
, lfinish
, Qfalse
);
2414 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2417 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
2418 LABEL
*lend
= NEW_LABEL(nd_line(node
));
2419 VALUE rescue
= NEW_CHILD_ISEQVAL(NEW_NIL(),
2420 rb_str_concat(rb_str_new2
2421 ("defined guard in "),
2423 ISEQ_TYPE_DEFINED_GUARD
);
2425 defined_expr(iseq
, ret
, node
->nd_recv
, lfinish
, Qfalse
);
2426 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2428 ADD_LABEL(ret
, lstart
);
2429 COMPILE(ret
, "defined/recv", node
->nd_recv
);
2430 ADD_LABEL(ret
, lend
);
2431 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE
, lstart
, lend
, rescue
, lfinish
[1]);
2432 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_METHOD
),
2433 ID2SYM(node
->nd_mid
), needstr
);
2436 ADD_INSN(ret
, nd_line(node
), putself
);
2437 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_FUNC
),
2438 ID2SYM(node
->nd_mid
), needstr
);
2444 ADD_INSN(ret
, nd_line(node
), putnil
);
2445 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_YIELD
), 0,
2451 ADD_INSN(ret
, nd_line(node
), putnil
);
2452 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_REF
),
2453 INT2FIX((node
->nd_nth
<< 1) | (type
== NODE_BACK_REF
)),
2459 ADD_INSN(ret
, nd_line(node
), putnil
);
2460 ADD_INSN3(ret
, nd_line(node
), defined
, INT2FIX(DEFINED_ZSUPER
), 0,
2466 case NODE_OP_ASGN_OR
:
2467 case NODE_OP_ASGN_AND
:
2471 case NODE_DASGN_CURR
:
2477 estr
= "assignment";
2481 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
2482 LABEL
*lend
= NEW_LABEL(nd_line(node
));
2483 VALUE ensure
= NEW_CHILD_ISEQVAL(NEW_NIL(),
2484 rb_str_concat(rb_str_new2
2485 ("defined guard in "),
2487 ISEQ_TYPE_DEFINED_GUARD
);
2489 ADD_LABEL(ret
, lstart
);
2490 COMPILE(ret
, "defined expr (others)", node
);
2492 lfinish
[1] = NEW_LABEL(nd_line(node
));
2494 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfinish
[1]);
2496 ADD_INSN1(ret
, nd_line(node
), putstring
, rb_str_new2("expression"));
2499 ADD_INSN1(ret
, nd_line(node
), putobject
, Qtrue
);
2501 ADD_LABEL(ret
, lend
);
2503 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE
, lstart
, lend
, ensure
, lfinish
[1]);
2505 } /* end of default */
2509 if (needstr
!= Qfalse
) {
2510 VALUE str
= rb_str_new2(estr
);
2511 ADD_INSN1(ret
, nd_line(node
), putstring
, str
);
2512 iseq_add_mark_object_compile_time(iseq
, str
);
2515 ADD_INSN1(ret
, nd_line(node
), putobject
, Qtrue
);
2522 #define BUFSIZE 0x100
2525 make_name_for_block(rb_iseq_t
*iseq
)
2527 if (iseq
->parent_iseq
== 0) {
2528 return rb_sprintf("block in %s", RSTRING_PTR(iseq
->name
));
2532 rb_iseq_t
*ip
= iseq
;
2533 while (ip
->local_iseq
!= ip
) {
2534 ip
= ip
->parent_iseq
;
2537 return rb_sprintf("block (%d levels) in %s", level
, RSTRING_PTR(ip
->name
));
2542 add_ensure_range(rb_iseq_t
*iseq
, struct ensure_range
*erange
,
2543 LABEL
*lstart
, LABEL
*lend
)
2545 struct ensure_range
*ne
=
2546 compile_data_alloc(iseq
, sizeof(struct ensure_range
));
2548 while (erange
->next
!= 0) {
2549 erange
= erange
->next
;
2553 ne
->end
= erange
->end
;
2554 erange
->end
= lstart
;
2560 add_ensure_iseq(LINK_ANCHOR
*ret
, rb_iseq_t
*iseq
)
2562 struct iseq_compile_data_ensure_node_stack
*enlp
=
2563 iseq
->compile_data
->ensure_node_stack
;
2564 struct iseq_compile_data_ensure_node_stack
*prev_enlp
= enlp
;
2565 DECL_ANCHOR(ensure
);
2567 INIT_ANCHOR(ensure
);
2569 DECL_ANCHOR(ensure_part
);
2570 LABEL
*lstart
= NEW_LABEL(0);
2571 LABEL
*lend
= NEW_LABEL(0);
2573 INIT_ANCHOR(ensure_part
);
2574 add_ensure_range(iseq
, enlp
->erange
, lstart
, lend
);
2576 iseq
->compile_data
->ensure_node_stack
= enlp
->prev
;
2577 ADD_LABEL(ensure_part
, lstart
);
2578 COMPILE_POPED(ensure_part
, "ensure part", enlp
->ensure_node
);
2579 ADD_LABEL(ensure_part
, lend
);
2581 ADD_SEQ(ensure
, ensure_part
);
2584 iseq
->compile_data
->ensure_node_stack
= prev_enlp
;
2585 ADD_SEQ(ret
, ensure
);
2589 setup_args(rb_iseq_t
*iseq
, LINK_ANCHOR
*args
, NODE
*argn
, unsigned long *flag
)
2591 VALUE argc
= INT2FIX(0);
2593 DECL_ANCHOR(arg_block
);
2594 DECL_ANCHOR(args_splat
);
2596 INIT_ANCHOR(arg_block
);
2597 INIT_ANCHOR(args_splat
);
2598 if (argn
&& nd_type(argn
) == NODE_BLOCK_PASS
) {
2599 COMPILE(arg_block
, "block", argn
->nd_body
);
2600 *flag
|= VM_CALL_ARGS_BLOCKARG_BIT
;
2601 argn
= argn
->nd_head
;
2606 switch (nd_type(argn
)) {
2608 COMPILE(args
, "args (splat)", argn
->nd_head
);
2611 *flag
|= VM_CALL_ARGS_SPLAT_BIT
;
2615 case NODE_ARGSPUSH
: {
2616 int next_is_array
= (nd_type(argn
->nd_head
) == NODE_ARRAY
);
2620 COMPILE(tmp
, "args (cat: splat)", argn
->nd_body
);
2621 if (next_is_array
&& nsplat
== 0) {
2625 if (nd_type(argn
) == NODE_ARGSCAT
) {
2626 ADD_INSN1(tmp
, nd_line(argn
), splatarray
, Qfalse
);
2629 ADD_INSN1(tmp
, nd_line(argn
), newarray
, INT2FIX(1));
2632 INSERT_LIST(args_splat
, tmp
);
2634 *flag
|= VM_CALL_ARGS_SPLAT_BIT
;
2636 if (next_is_array
) {
2637 argc
= INT2FIX(compile_array(iseq
, args
, argn
->nd_head
, Qfalse
) + 1);
2641 argn
= argn
->nd_head
;
2647 argc
= INT2FIX(compile_array(iseq
, args
, argn
, Qfalse
));
2652 rb_bug("setup_arg: unknown node: %s\n", ruby_node_name(nd_type(argn
)));
2659 for (i
=1; i
<nsplat
; i
++) {
2660 ADD_INSN(args_splat
, nd_line(args
), concatarray
);
2664 if (!LIST_SIZE_ZERO(args_splat
)) {
2665 ADD_SEQ(args
, args_splat
);
2668 if (*flag
& VM_CALL_ARGS_BLOCKARG_BIT
) {
2669 ADD_SEQ(args
, arg_block
);
2678 self: InstructionSequence
2679 node: Ruby compiled node
2680 poped: This node will be poped
2683 iseq_compile_each(rb_iseq_t
*iseq
, LINK_ANCHOR
*ret
, NODE
* node
, int poped
)
2685 enum node_type type
;
2689 debugs("node: NODE_NIL(implicit)\n");
2690 ADD_INSN(ret
, iseq
->compile_data
->last_line
, putnil
);
2695 iseq
->compile_data
->last_line
= nd_line(node
);
2696 debug_node_start(node
);
2698 type
= nd_type(node
);
2700 if (node
->flags
& NODE_FL_NEWLINE
) {
2701 ADD_TRACE(ret
, nd_line(node
), RUBY_EVENT_LINE
);
2706 while (node
&& nd_type(node
) == NODE_BLOCK
) {
2707 COMPILE_(ret
, "BLOCK body", node
->nd_head
,
2708 (node
->nd_next
== 0 && poped
== 0) ? 0 : 1);
2709 node
= node
->nd_next
;
2712 COMPILE_(ret
, "BLOCK next", node
->nd_next
, poped
);
2717 DECL_ANCHOR(cond_seq
);
2718 DECL_ANCHOR(then_seq
);
2719 DECL_ANCHOR(else_seq
);
2720 LABEL
*then_label
, *else_label
, *end_label
;
2722 INIT_ANCHOR(cond_seq
);
2723 INIT_ANCHOR(then_seq
);
2724 INIT_ANCHOR(else_seq
);
2725 then_label
= NEW_LABEL(nd_line(node
));
2726 else_label
= NEW_LABEL(nd_line(node
));
2727 end_label
= NEW_LABEL(nd_line(node
));
2729 compile_branch_condition(iseq
, cond_seq
, node
->nd_cond
,
2730 then_label
, else_label
);
2731 COMPILE_(then_seq
, "then", node
->nd_body
, poped
);
2732 COMPILE_(else_seq
, "else", node
->nd_else
, poped
);
2734 ADD_SEQ(ret
, cond_seq
);
2736 ADD_LABEL(ret
, then_label
);
2737 ADD_SEQ(ret
, then_seq
);
2738 ADD_INSNL(ret
, nd_line(node
), jump
, end_label
);
2740 ADD_LABEL(ret
, else_label
);
2741 ADD_SEQ(ret
, else_seq
);
2743 ADD_LABEL(ret
, end_label
);
2749 NODE
*tempnode
= node
;
2750 LABEL
*endlabel
, *elselabel
;
2752 DECL_ANCHOR(body_seq
);
2753 DECL_ANCHOR(cond_seq
);
2754 VALUE special_literals
= rb_ary_new();
2757 INIT_ANCHOR(body_seq
);
2758 INIT_ANCHOR(cond_seq
);
2759 if (node
->nd_head
== 0) {
2760 COMPILE_(ret
, "when", node
->nd_body
, poped
);
2763 COMPILE(head
, "case base", node
->nd_head
);
2765 node
= node
->nd_body
;
2766 type
= nd_type(node
);
2768 if (type
!= NODE_WHEN
) {
2769 COMPILE_ERROR((ERROR_ARGS
"NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type
)));
2772 endlabel
= NEW_LABEL(nd_line(node
));
2773 elselabel
= NEW_LABEL(nd_line(node
));
2775 ADD_SEQ(ret
, head
); /* case VAL */
2777 while (type
== NODE_WHEN
) {
2780 l1
= NEW_LABEL(nd_line(node
));
2781 ADD_LABEL(body_seq
, l1
);
2782 ADD_INSN(body_seq
, nd_line(node
), pop
);
2783 COMPILE_(body_seq
, "when body", node
->nd_body
, poped
);
2784 ADD_INSNL(body_seq
, nd_line(node
), jump
, endlabel
);
2786 vals
= node
->nd_head
;
2788 switch (nd_type(vals
)) {
2790 special_literals
= when_vals(iseq
, cond_seq
, vals
, l1
, special_literals
);
2795 special_literals
= 0;
2796 COMPILE(cond_seq
, "when/cond splat", vals
);
2797 ADD_INSN1(cond_seq
, nd_line(vals
), checkincludearray
, Qtrue
);
2798 ADD_INSNL(cond_seq
, nd_line(vals
), branchif
, l1
);
2801 rb_bug("NODE_CASE: unknown node (%s)",
2802 ruby_node_name(nd_type(vals
)));
2806 rb_bug("NODE_CASE: must be NODE_ARRAY, but 0");
2809 node
= node
->nd_next
;
2813 type
= nd_type(node
);
2817 ADD_LABEL(cond_seq
, elselabel
);
2818 ADD_INSN(cond_seq
, nd_line(node
), pop
);
2819 COMPILE_(cond_seq
, "else", node
, poped
);
2820 ADD_INSNL(cond_seq
, nd_line(node
), jump
, endlabel
);
2823 debugs("== else (implicit)\n");
2824 ADD_LABEL(cond_seq
, elselabel
);
2825 ADD_INSN(cond_seq
, nd_line(tempnode
), pop
);
2827 ADD_INSN(cond_seq
, nd_line(tempnode
), putnil
);
2829 ADD_INSNL(cond_seq
, nd_line(tempnode
), jump
, endlabel
);
2832 if (special_literals
) {
2833 ADD_INSN(ret
, nd_line(tempnode
), dup
);
2834 ADD_INSN2(ret
, nd_line(tempnode
), opt_case_dispatch
,
2835 special_literals
, elselabel
);
2836 iseq_add_mark_object_compile_time(iseq
, special_literals
);
2839 ADD_SEQ(ret
, cond_seq
);
2840 ADD_SEQ(ret
, body_seq
);
2841 ADD_LABEL(ret
, endlabel
);
2847 NODE
*orig_node
= node
;
2849 DECL_ANCHOR(body_seq
);
2851 INIT_ANCHOR(body_seq
);
2852 endlabel
= NEW_LABEL(nd_line(node
));
2854 while (node
&& nd_type(node
) == NODE_WHEN
) {
2855 LABEL
*l1
= NEW_LABEL(nd_line(node
));
2856 ADD_LABEL(body_seq
, l1
);
2857 COMPILE_(body_seq
, "when", node
->nd_body
, poped
);
2858 ADD_INSNL(body_seq
, nd_line(node
), jump
, endlabel
);
2860 vals
= node
->nd_head
;
2861 if (vals
&& nd_type(vals
) == NODE_ARRAY
) {
2863 val
= vals
->nd_head
;
2864 COMPILE(ret
, "when2", val
);
2865 ADD_INSNL(ret
, nd_line(val
), branchif
, l1
);
2866 vals
= vals
->nd_next
;
2869 else if (nd_type(vals
) == NODE_SPLAT
||
2870 nd_type(vals
) == NODE_ARGSCAT
||
2871 nd_type(vals
) == NODE_ARGSPUSH
) {
2873 NODE
*val
= vals
->nd_head
;
2875 if (nd_type(vals
) == NODE_ARGSCAT
|| nd_type(vals
) == NODE_ARGSPUSH
) {
2876 NODE
*vs
= vals
->nd_head
;
2877 val
= vals
->nd_body
;
2880 NODE
* val
= vs
->nd_head
;
2881 COMPILE(ret
, "when/argscat", val
);
2882 ADD_INSNL(ret
, nd_line(val
), branchif
, l1
);
2887 ADD_INSN(ret
, nd_line(val
), putnil
);
2888 COMPILE(ret
, "when2/splat", val
);
2889 ADD_INSN1(ret
, nd_line(val
), checkincludearray
, Qfalse
);
2890 ADD_INSN(ret
, nd_line(val
), pop
);
2891 ADD_INSNL(ret
, nd_line(val
), branchif
, l1
);
2896 node
= node
->nd_next
;
2899 COMPILE_(ret
, "else", node
, poped
);
2900 ADD_INSNL(ret
, nd_line(orig_node
), jump
, endlabel
);
2902 ADD_SEQ(ret
, body_seq
);
2903 ADD_LABEL(ret
, endlabel
);
2910 LABEL
*prev_start_label
= iseq
->compile_data
->start_label
;
2911 LABEL
*prev_end_label
= iseq
->compile_data
->end_label
;
2912 LABEL
*prev_redo_label
= iseq
->compile_data
->redo_label
;
2913 VALUE prev_loopval_popped
= iseq
->compile_data
->loopval_popped
;
2915 struct iseq_compile_data_ensure_node_stack
*enlp
=
2916 iseq
->compile_data
->ensure_node_stack
;
2918 LABEL
*next_label
= iseq
->compile_data
->start_label
= NEW_LABEL(nd_line(node
)); /* next */
2919 LABEL
*redo_label
= iseq
->compile_data
->redo_label
= NEW_LABEL(nd_line(node
)); /* redo */
2920 LABEL
*break_label
= iseq
->compile_data
->end_label
= NEW_LABEL(nd_line(node
)); /* break */
2921 LABEL
*end_label
= NEW_LABEL(nd_line(node
));
2923 LABEL
*next_catch_label
= NEW_LABEL(nd_line(node
));
2924 LABEL
*tmp_label
= NULL
;
2926 iseq
->compile_data
->loopval_popped
= 0;
2927 iseq
->compile_data
->ensure_node_stack
= 0;
2929 if (type
== NODE_OPT_N
|| node
->nd_state
== 1) {
2930 ADD_INSNL(ret
, nd_line(node
), jump
, next_label
);
2933 tmp_label
= NEW_LABEL(nd_line(node
));
2934 ADD_INSNL(ret
, nd_line(node
), jump
, tmp_label
);
2936 ADD_INSN(ret
, nd_line(node
), putnil
);
2937 ADD_LABEL(ret
, next_catch_label
);
2938 ADD_INSN(ret
, nd_line(node
), pop
);
2939 ADD_INSNL(ret
, nd_line(node
), jump
, next_label
);
2940 if (tmp_label
) ADD_LABEL(ret
, tmp_label
);
2942 ADD_LABEL(ret
, redo_label
);
2943 COMPILE_POPED(ret
, "while body", node
->nd_body
);
2944 ADD_LABEL(ret
, next_label
); /* next */
2946 if (type
== NODE_WHILE
) {
2947 compile_branch_condition(iseq
, ret
, node
->nd_cond
,
2948 redo_label
, end_label
);
2950 else if (type
== NODE_UNTIL
) {
2952 compile_branch_condition(iseq
, ret
, node
->nd_cond
,
2953 end_label
, redo_label
);
2956 ADD_CALL_RECEIVER(ret
, nd_line(node
));
2957 ADD_CALL(ret
, nd_line(node
), ID2SYM(idGets
), INT2FIX(0));
2958 ADD_INSNL(ret
, nd_line(node
), branchif
, redo_label
);
2962 ADD_LABEL(ret
, end_label
);
2964 if (node
->nd_state
== Qundef
) {
2965 /* ADD_INSN(ret, nd_line(node), putundef); */
2966 rb_bug("unsupported: putundef");
2969 ADD_INSN(ret
, nd_line(node
), putnil
);
2972 ADD_LABEL(ret
, break_label
); /* break */
2975 ADD_INSN(ret
, nd_line(node
), pop
);
2978 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK
, redo_label
, break_label
,
2980 ADD_CATCH_ENTRY(CATCH_TYPE_NEXT
, redo_label
, break_label
, 0,
2982 ADD_CATCH_ENTRY(CATCH_TYPE_REDO
, redo_label
, break_label
, 0,
2983 iseq
->compile_data
->redo_label
);
2985 iseq
->compile_data
->start_label
= prev_start_label
;
2986 iseq
->compile_data
->end_label
= prev_end_label
;
2987 iseq
->compile_data
->redo_label
= prev_redo_label
;
2988 iseq
->compile_data
->loopval_popped
= prev_loopval_popped
;
2989 iseq
->compile_data
->ensure_node_stack
= enlp
;
2994 VALUE prevblock
= iseq
->compile_data
->current_block
;
2995 LABEL
*retry_label
= NEW_LABEL(nd_line(node
));
2996 LABEL
*retry_end_l
= NEW_LABEL(nd_line(node
));
2999 ADD_LABEL(ret
, retry_label
);
3000 if (nd_type(node
) == NODE_FOR
) {
3001 COMPILE(ret
, "iter caller (for)", node
->nd_iter
);
3003 iseq
->compile_data
->current_block
=
3004 NEW_CHILD_ISEQVAL(node
->nd_body
, make_name_for_block(iseq
),
3008 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idEach
), INT2FIX(0),
3009 iseq
->compile_data
->current_block
, INT2FIX(0));
3012 iseq
->compile_data
->current_block
=
3013 NEW_CHILD_ISEQVAL(node
->nd_body
, make_name_for_block(iseq
),
3015 COMPILE(ret
, "iter caller", node
->nd_iter
);
3017 ADD_LABEL(ret
, retry_end_l
);
3020 ADD_INSN(ret
, nd_line(node
), pop
);
3023 iseq
->compile_data
->current_block
= prevblock
;
3025 ADD_CATCH_ENTRY(CATCH_TYPE_BREAK
, retry_label
, retry_end_l
, 0, retry_end_l
);
3030 unsigned long level
= 0;
3032 if (iseq
->compile_data
->redo_label
!= 0) {
3034 LABEL
*splabel
= NEW_LABEL(0);
3035 ADD_LABEL(ret
, splabel
);
3036 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->redo_label
);
3037 COMPILE_(ret
, "break val (while/until)", node
->nd_stts
, iseq
->compile_data
->loopval_popped
);
3038 add_ensure_iseq(ret
, iseq
);
3039 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->end_label
);
3040 ADD_ADJUST_RESTORE(ret
, splabel
);
3043 ADD_INSN(ret
, nd_line(node
), putnil
);
3046 else if (iseq
->type
== ISEQ_TYPE_BLOCK
) {
3048 /* escape from block */
3049 COMPILE(ret
, "break val (block)", node
->nd_stts
);
3050 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(level
| 0x02) /* TAG_BREAK */ );
3052 ADD_INSN(ret
, nd_line(node
), pop
);
3055 else if (iseq
->type
== ISEQ_TYPE_EVAL
) {
3057 COMPILE_ERROR((ERROR_ARGS
"Can't escape from eval with break"));
3060 rb_iseq_t
*ip
= iseq
->parent_iseq
;
3063 if (ip
->compile_data
->redo_label
!= 0) {
3065 if (ip
->compile_data
->loopval_popped
== 0) {
3071 else if (ip
->type
== ISEQ_TYPE_BLOCK
) {
3075 else if (ip
->type
== ISEQ_TYPE_EVAL
) {
3078 ip
= ip
->parent_iseq
;
3080 COMPILE_ERROR((ERROR_ARGS
"Invalid break"));
3085 unsigned long level
= 0;
3087 if (iseq
->compile_data
->redo_label
!= 0) {
3088 LABEL
*splabel
= NEW_LABEL(0);
3089 debugs("next in while loop\n");
3090 ADD_LABEL(ret
, splabel
);
3091 COMPILE(ret
, "next val/valid syntax?", node
->nd_stts
);
3092 add_ensure_iseq(ret
, iseq
);
3093 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->redo_label
);
3094 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->start_label
);
3095 ADD_ADJUST_RESTORE(ret
, splabel
);
3097 else if (iseq
->compile_data
->end_label
) {
3098 LABEL
*splabel
= NEW_LABEL(0);
3099 debugs("next in block\n");
3100 ADD_LABEL(ret
, splabel
);
3101 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->start_label
);
3102 COMPILE(ret
, "next val", node
->nd_stts
);
3103 add_ensure_iseq(ret
, iseq
);
3104 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->end_label
);
3105 ADD_ADJUST_RESTORE(ret
, splabel
);
3108 ADD_INSN(ret
, nd_line(node
), putnil
);
3111 else if (iseq
->type
== ISEQ_TYPE_EVAL
) {
3113 COMPILE_ERROR((ERROR_ARGS
"Can't escape from eval with next"));
3119 level
= 0x8000 | 0x4000;
3120 if (ip
->compile_data
->redo_label
!= 0) {
3124 else if (ip
->type
== ISEQ_TYPE_BLOCK
) {
3127 else if (ip
->type
== ISEQ_TYPE_EVAL
) {
3130 ip
= ip
->parent_iseq
;
3133 COMPILE(ret
, "next val", node
->nd_stts
);
3134 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(level
| 0x03) /* TAG_NEXT */ );
3137 ADD_INSN(ret
, nd_line(node
), pop
);
3141 COMPILE_ERROR((ERROR_ARGS
"Invalid next"));
3147 if (iseq
->compile_data
->redo_label
) {
3148 LABEL
*splabel
= NEW_LABEL(0);
3149 debugs("redo in while");
3150 ADD_LABEL(ret
, splabel
);
3151 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->redo_label
);
3152 add_ensure_iseq(ret
, iseq
);
3153 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->redo_label
);
3154 ADD_ADJUST_RESTORE(ret
, splabel
);
3156 else if (iseq
->type
== ISEQ_TYPE_EVAL
) {
3158 COMPILE_ERROR((ERROR_ARGS
"Can't escape from eval with redo"));
3160 else if (iseq
->compile_data
->start_label
) {
3161 LABEL
*splabel
= NEW_LABEL(0);
3163 debugs("redo in block");
3164 ADD_LABEL(ret
, splabel
);
3165 add_ensure_iseq(ret
, iseq
);
3166 ADD_ADJUST(ret
, nd_line(node
), iseq
->compile_data
->start_label
);
3167 ADD_INSNL(ret
, nd_line(node
), jump
, iseq
->compile_data
->start_label
);
3168 ADD_ADJUST_RESTORE(ret
, splabel
);
3171 ADD_INSN(ret
, nd_line(node
), putnil
);
3176 unsigned long level
;
3177 level
= 0x8000 | 0x4000;
3180 if (ip
->compile_data
->redo_label
!= 0) {
3183 else if (ip
->type
== ISEQ_TYPE_BLOCK
) {
3186 else if (ip
->type
== ISEQ_TYPE_EVAL
) {
3189 ip
= ip
->parent_iseq
;
3192 ADD_INSN(ret
, nd_line(node
), putnil
);
3193 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(level
| 0x05) /* TAG_REDO */ );
3196 ADD_INSN(ret
, nd_line(node
), pop
);
3200 COMPILE_ERROR((ERROR_ARGS
"Invalid redo"));
3206 if (iseq
->type
== ISEQ_TYPE_RESCUE
) {
3207 ADD_INSN(ret
, nd_line(node
), putnil
);
3208 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(0x04) /* TAG_RETRY */ );
3211 ADD_INSN(ret
, nd_line(node
), pop
);
3215 COMPILE_ERROR((ERROR_ARGS
"Invalid retry"));
3220 COMPILE_(ret
, "NODE_BEGIN", node
->nd_body
, poped
);
3224 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
3225 LABEL
*lend
= NEW_LABEL(nd_line(node
));
3226 LABEL
*lcont
= NEW_LABEL(nd_line(node
));
3227 VALUE rescue
= NEW_CHILD_ISEQVAL(
3229 rb_str_concat(rb_str_new2("rescue in "), iseq
->name
),
3232 ADD_LABEL(ret
, lstart
);
3233 COMPILE(ret
, "rescue head", node
->nd_head
);
3234 ADD_LABEL(ret
, lend
);
3235 if (node
->nd_else
) {
3236 ADD_INSN(ret
, nd_line(node
), pop
);
3237 COMPILE(ret
, "rescue else", node
->nd_else
);
3239 ADD_INSN(ret
, nd_line(node
), nop
);
3240 ADD_LABEL(ret
, lcont
);
3243 ADD_INSN(ret
, nd_line(node
), pop
);
3246 /* resgister catch entry */
3247 ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE
, lstart
, lend
, rescue
, lcont
);
3248 ADD_CATCH_ENTRY(CATCH_TYPE_RETRY
, lend
, lcont
, 0, lstart
);
3254 LABEL
*label_miss
, *label_hit
;
3257 label_miss
= NEW_LABEL(nd_line(node
));
3258 label_hit
= NEW_LABEL(nd_line(node
));
3260 narg
= resq
->nd_args
;
3262 switch (nd_type(narg
)) {
3265 COMPILE(ret
, "rescue arg", narg
->nd_head
);
3266 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(2), INT2FIX(0));
3267 ADD_SEND(ret
, nd_line(node
), ID2SYM(idEqq
), INT2FIX(1));
3268 ADD_INSNL(ret
, nd_line(node
), branchif
, label_hit
);
3269 narg
= narg
->nd_next
;
3275 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(2), INT2FIX(0));
3276 COMPILE(ret
, "rescue/cond splat", narg
);
3277 ADD_INSN1(ret
, nd_line(node
), checkincludearray
, Qtrue
);
3278 ADD_INSN(ret
, nd_line(node
), swap
);
3279 ADD_INSN(ret
, nd_line(node
), pop
);
3280 ADD_INSNL(ret
, nd_line(node
), branchif
, label_hit
);
3283 rb_bug("NODE_RESBODY: unknown node (%s)",
3284 ruby_node_name(nd_type(narg
)));
3288 ADD_INSN1(ret
, nd_line(node
), putobject
,
3290 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(2), INT2FIX(0));
3291 ADD_SEND(ret
, nd_line(node
), ID2SYM(idEqq
), INT2FIX(1));
3292 ADD_INSNL(ret
, nd_line(node
), branchif
, label_hit
);
3294 ADD_INSNL(ret
, nd_line(node
), jump
, label_miss
);
3295 ADD_LABEL(ret
, label_hit
);
3296 COMPILE(ret
, "resbody body", resq
->nd_body
);
3297 if (iseq
->compile_data
->option
->tailcall_optimization
) {
3298 ADD_INSN(ret
, nd_line(node
), nop
);
3300 ADD_INSN(ret
, nd_line(node
), leave
);
3301 ADD_LABEL(ret
, label_miss
);
3302 resq
= resq
->nd_head
;
3308 VALUE ensure
= NEW_CHILD_ISEQVAL(node
->nd_ensr
,
3309 rb_str_concat(rb_str_new2
3313 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
3314 LABEL
*lend
= NEW_LABEL(nd_line(node
));
3315 LABEL
*lcont
= NEW_LABEL(nd_line(node
));
3316 struct ensure_range er
= { 0 };
3317 struct iseq_compile_data_ensure_node_stack enl
;
3318 struct ensure_range
*erange
;
3323 enl
.ensure_node
= node
->nd_ensr
;
3324 enl
.prev
= iseq
->compile_data
->ensure_node_stack
; /* prev */
3326 COMPILE_POPED(ensr
, "ensure ensr", node
->nd_ensr
);
3328 iseq
->compile_data
->ensure_node_stack
= &enl
;
3330 ADD_LABEL(ret
, lstart
);
3331 COMPILE_(ret
, "ensure head", node
->nd_head
, poped
);
3332 ADD_LABEL(ret
, lend
);
3333 if (ensr
->anchor
.next
== 0) {
3334 ADD_INSN(ret
, nd_line(node
), nop
);
3339 ADD_LABEL(ret
, lcont
);
3341 erange
= iseq
->compile_data
->ensure_node_stack
->erange
;
3343 ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE
, erange
->begin
, erange
->end
,
3345 erange
= erange
->next
;
3347 iseq
->compile_data
->ensure_node_stack
= enl
.prev
;
3353 LABEL
*end_label
= NEW_LABEL(nd_line(node
));
3354 COMPILE(ret
, "nd_1st", node
->nd_1st
);
3356 ADD_INSN(ret
, nd_line(node
), dup
);
3358 if (type
== NODE_AND
) {
3359 ADD_INSNL(ret
, nd_line(node
), branchunless
, end_label
);
3362 ADD_INSNL(ret
, nd_line(node
), branchif
, end_label
);
3365 ADD_INSN(ret
, nd_line(node
), pop
);
3367 COMPILE_(ret
, "nd_2nd", node
->nd_2nd
, poped
);
3368 ADD_LABEL(ret
, end_label
);
3373 compile_massign(iseq
, ret
, node
, poped
);
3378 ID id
= node
->nd_vid
;
3379 int idx
= iseq
->local_iseq
->local_size
- get_local_var_idx(iseq
, id
);
3381 debugs("lvar: %s idx: %d\n", rb_id2name(id
), idx
);
3382 COMPILE(ret
, "rvalue", node
->nd_value
);
3385 ADD_INSN(ret
, nd_line(node
), dup
);
3387 ADD_INSN1(ret
, nd_line(node
), setlocal
, INT2FIX(idx
));
3392 case NODE_DASGN_CURR
:{
3394 COMPILE(ret
, "dvalue", node
->nd_value
);
3395 debugp_param("dassn id", rb_str_new2(rb_id2name(node
->nd_vid
) ? rb_id2name(node
->nd_vid
) : "*"));
3398 ADD_INSN(ret
, nd_line(node
), dup
);
3401 idx
= get_dyna_var_idx(iseq
, node
->nd_vid
, &lv
, &ls
);
3404 rb_bug("NODE_DASGN(_CURR): unknown id (%s)", rb_id2name(node
->nd_vid
));
3407 ADD_INSN2(ret
, nd_line(node
), setdynamic
,
3408 INT2FIX(ls
- idx
), INT2FIX(lv
));
3412 COMPILE(ret
, "lvalue", node
->nd_value
);
3415 ADD_INSN(ret
, nd_line(node
), dup
);
3417 ADD_INSN1(ret
, nd_line(node
), setglobal
,
3418 (((long)node
->nd_entry
) | 1));
3423 COMPILE(ret
, "lvalue", node
->nd_value
);
3425 ADD_INSN(ret
, nd_line(node
), dup
);
3427 ADD_INSN1(ret
, nd_line(node
), setinstancevariable
,
3428 ID2SYM(node
->nd_vid
));
3432 COMPILE(ret
, "lvalue", node
->nd_value
);
3435 ADD_INSN(ret
, nd_line(node
), dup
);
3439 ADD_INSN1(ret
, nd_line(node
), putspecialobject
, INT2FIX(VM_SPECIAL_OBJECT_CBASE
));
3440 ADD_INSN1(ret
, nd_line(node
), setconstant
, ID2SYM(node
->nd_vid
));
3443 compile_cpath(ret
, iseq
, node
->nd_else
);
3444 ADD_INSN1(ret
, nd_line(node
), setconstant
, ID2SYM(node
->nd_else
->nd_mid
));
3449 COMPILE(ret
, "cvasgn val", node
->nd_value
);
3451 ADD_INSN(ret
, nd_line(node
), dup
);
3453 ADD_INSN1(ret
, nd_line(node
), setclassvariable
,
3454 ID2SYM(node
->nd_vid
));
3457 case NODE_OP_ASGN1
: {
3460 unsigned long flag
= 0;
3461 ID id
= node
->nd_mid
;
3469 * send :[] # a x a[x]
3470 * eval y # a x a[x] y
3471 * send op # a x a[x]+y
3476 * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head;
3477 * NODE_OP_ASGN nd_recv
3483 COMPILE(ret
, "NODE_OP_ASGN1 recv", node
->nd_recv
);
3484 if (nd_type(node
->nd_args
->nd_body
) != NODE_ZARRAY
) {
3486 argc
= setup_args(iseq
, args
, node
->nd_args
->nd_body
, &flag
);
3492 ADD_INSN1(ret
, nd_line(node
), dupn
, INT2FIX(FIX2INT(argc
)+1));
3493 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idAREF
), argc
, Qfalse
, LONG2FIX(flag
));
3495 if (id
== 0 || id
== 1) {
3505 LABEL
*label
= NEW_LABEL(nd_line(node
));
3506 LABEL
*lfin
= NEW_LABEL(nd_line(node
));
3510 ADD_INSN(ret
, nd_line(node
), dup
);
3511 ADD_INSNL(ret
, nd_line(node
), branchif
, label
);
3512 ADD_INSN(ret
, nd_line(node
), pop
);
3516 ADD_INSN(ret
, nd_line(node
), dup
);
3517 ADD_INSNL(ret
, nd_line(node
), branchunless
, label
);
3518 ADD_INSN(ret
, nd_line(node
), pop
);
3521 COMPILE(ret
, "NODE_OP_ASGN1 args->head: ", node
->nd_args
->nd_head
);
3522 if (flag
& VM_CALL_ARGS_SPLAT_BIT
) {
3523 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(1));
3524 ADD_INSN(ret
, nd_line(node
), concatarray
);
3525 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idASET
),
3526 argc
, Qfalse
, LONG2FIX(flag
));
3529 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idASET
),
3530 INT2FIX(FIX2INT(argc
) + 1), Qfalse
, LONG2FIX(flag
));
3532 ADD_INSNL(ret
, nd_line(node
), jump
, lfin
);
3533 ADD_LABEL(ret
, label
);
3534 if (id
== 0 || id
== 1) { /* 0: or, 1: and */
3535 ADD_INSN(ret
, nd_line(node
), swap
);
3536 ADD_INSN(ret
, nd_line(node
), pop
);
3537 ADD_INSN(ret
, nd_line(node
), swap
);
3538 ADD_INSN(ret
, nd_line(node
), pop
);
3540 ADD_LABEL(ret
, lfin
);
3543 COMPILE(ret
, "NODE_OP_ASGN1 args->head: ", node
->nd_args
->nd_head
);
3544 ADD_SEND(ret
, nd_line(node
), ID2SYM(id
), INT2FIX(1));
3545 if (flag
& VM_CALL_ARGS_SPLAT_BIT
) {
3546 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(1));
3547 ADD_INSN(ret
, nd_line(node
), concatarray
);
3548 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idASET
),
3549 argc
, Qfalse
, LONG2FIX(flag
));
3552 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(idASET
),
3553 INT2FIX(FIX2INT(argc
) + 1), Qfalse
, LONG2FIX(flag
));
3558 ADD_INSN(ret
, nd_line(node
), pop
);
3563 case NODE_OP_ASGN2
:{
3564 ID atype
= node
->nd_next
->nd_mid
;
3565 LABEL
*lfin
= NEW_LABEL(nd_line(node
));
3566 LABEL
*lcfin
= NEW_LABEL(nd_line(node
));
3568 class C; attr_accessor :c; end
3605 COMPILE(ret
, "NODE_OP_ASGN2#recv", node
->nd_recv
);
3606 ADD_INSN(ret
, nd_line(node
), dup
);
3607 ADD_SEND(ret
, nd_line(node
), ID2SYM(node
->nd_next
->nd_vid
),
3610 if (atype
== 0 || atype
== 1) { /* 0: OR or 1: AND */
3611 ADD_INSN(ret
, nd_line(node
), dup
);
3613 ADD_INSNL(ret
, nd_line(node
), branchif
, lcfin
);
3616 ADD_INSNL(ret
, nd_line(node
), branchunless
, lcfin
);
3618 ADD_INSN(ret
, nd_line(node
), pop
);
3619 COMPILE(ret
, "NODE_OP_ASGN2 val", node
->nd_value
);
3620 ADD_SEND(ret
, nd_line(node
), ID2SYM(node
->nd_next
->nd_aid
),
3622 ADD_INSNL(ret
, nd_line(node
), jump
, lfin
);
3624 ADD_LABEL(ret
, lcfin
);
3625 ADD_INSN(ret
, nd_line(node
), swap
);
3626 ADD_INSN(ret
, nd_line(node
), pop
);
3628 ADD_LABEL(ret
, lfin
);
3631 COMPILE(ret
, "NODE_OP_ASGN2 val", node
->nd_value
);
3632 ADD_SEND(ret
, nd_line(node
), ID2SYM(node
->nd_next
->nd_mid
),
3634 ADD_SEND(ret
, nd_line(node
), ID2SYM(node
->nd_next
->nd_aid
),
3639 /* we can apply more optimize */
3640 ADD_INSN(ret
, nd_line(node
), pop
);
3644 case NODE_OP_ASGN_AND
:
3645 case NODE_OP_ASGN_OR
:{
3646 LABEL
*lfin
= NEW_LABEL(nd_line(node
));
3649 if (nd_type(node
) == NODE_OP_ASGN_OR
) {
3653 defined_expr(iseq
, ret
, node
->nd_head
, lfinish
, Qfalse
);
3654 lassign
= lfinish
[1];
3656 lassign
= NEW_LABEL(nd_line(node
));
3658 ADD_INSNL(ret
, nd_line(node
), branchunless
, lassign
);
3661 lassign
= NEW_LABEL(nd_line(node
));
3664 COMPILE(ret
, "NODE_OP_ASGN_AND/OR#nd_head", node
->nd_head
);
3665 ADD_INSN(ret
, nd_line(node
), dup
);
3667 if (nd_type(node
) == NODE_OP_ASGN_AND
) {
3668 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfin
);
3671 ADD_INSNL(ret
, nd_line(node
), branchif
, lfin
);
3674 ADD_INSN(ret
, nd_line(node
), pop
);
3675 ADD_LABEL(ret
, lassign
);
3676 COMPILE(ret
, "NODE_OP_ASGN_AND/OR#nd_value", node
->nd_value
);
3677 ADD_LABEL(ret
, lfin
);
3680 /* we can apply more optimize */
3681 ADD_INSN(ret
, nd_line(node
), pop
);
3687 case NODE_VCALL
:{ /* VCALL: variable or call */
3689 call: obj.method(...)
3695 ID mid
= node
->nd_mid
;
3697 unsigned long flag
= 0;
3698 VALUE parent_block
= iseq
->compile_data
->current_block
;
3699 iseq
->compile_data
->current_block
= Qfalse
;
3704 if (nd_type(node
) == NODE_VCALL
) {
3705 if (mid
== idBitblt
) {
3706 ADD_INSN(ret
, nd_line(node
), bitblt
);
3709 else if (mid
== idAnswer
) {
3710 ADD_INSN(ret
, nd_line(node
), answer
);
3722 CONST_ID(goto_id
, "__goto__");
3723 CONST_ID(label_id
, "__label__");
3725 if (nd_type(node
) == NODE_FCALL
&&
3726 (mid
== goto_id
|| mid
== label_id
)) {
3727 if (nd_type(node
->nd_args
->nd_head
) == NODE_LIT
&&
3728 SYMBOL_P(node
->nd_args
->nd_head
->nd_lit
)) {
3730 label_sym
= label
= node
->nd_args
->nd_head
->nd_lit
;
3732 rb_hash_aref(iseq
->compile_data
,
3733 label_sym
)) == Qnil
) {
3734 rb_hash_aset(iseq
->compile_data
, label_sym
,
3735 label
= NEW_LABEL(nd_line(node
)));
3739 rb_bug("invalid goto/label format");
3743 if (mid
== goto_id
) {
3744 ADD_INSNL(ret
, nd_line(node
), jump
, label
);
3747 ADD_LABEL(ret
, label
);
3754 if (type
== NODE_CALL
) {
3755 COMPILE(recv
, "recv", node
->nd_recv
);
3757 else if (type
== NODE_FCALL
|| type
== NODE_VCALL
) {
3758 ADD_CALL_RECEIVER(recv
, nd_line(node
));
3762 if (nd_type(node
) != NODE_VCALL
) {
3763 argc
= setup_args(iseq
, args
, node
->nd_args
, &flag
);
3772 debugp_param("call args argc", argc
);
3773 debugp_param("call method", ID2SYM(mid
));
3775 switch (nd_type(node
)) {
3777 flag
|= VM_CALL_VCALL_BIT
;
3778 /* VCALL is funcall, so fall through */
3780 flag
|= VM_CALL_FCALL_BIT
;
3783 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(mid
),
3784 argc
, parent_block
, LONG2FIX(flag
));
3787 ADD_INSN(ret
, nd_line(node
), pop
);
3795 unsigned long flag
= 0;
3796 VALUE parent_block
= iseq
->compile_data
->current_block
;
3799 iseq
->compile_data
->current_block
= Qfalse
;
3800 if (nd_type(node
) == NODE_SUPER
) {
3801 argc
= setup_args(iseq
, args
, node
->nd_args
, &flag
);
3806 rb_iseq_t
*liseq
= iseq
->local_iseq
;
3808 argc
= INT2FIX(liseq
->argc
);
3810 /* normal arguments */
3811 for (i
= 0; i
< liseq
->argc
; i
++) {
3812 int idx
= liseq
->local_size
- i
;
3813 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3816 if (!liseq
->arg_simple
) {
3817 if (liseq
->arg_opts
) {
3818 /* optional arguments */
3820 for (j
= 0; j
< liseq
->arg_opts
- 1; j
++) {
3821 int idx
= liseq
->local_size
- (i
+ j
);
3822 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3828 if (liseq
->arg_rest
!= -1) {
3830 int idx
= liseq
->local_size
- liseq
->arg_rest
;
3831 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3832 argc
= INT2FIX(liseq
->arg_rest
+ 1);
3833 flag
|= VM_CALL_ARGS_SPLAT_BIT
;
3836 if (liseq
->arg_post_len
) {
3837 /* post arguments */
3838 int post_len
= liseq
->arg_post_len
;
3839 int post_start
= liseq
->arg_post_start
;
3841 if (liseq
->arg_rest
!= -1) {
3843 for (j
=0; j
<post_len
; j
++) {
3844 int idx
= liseq
->local_size
- (post_start
+ j
);
3845 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3847 ADD_INSN1(args
, nd_line(node
), newarray
, INT2FIX(j
));
3848 ADD_INSN (args
, nd_line(node
), concatarray
);
3849 /* argc is setteled at above */
3853 for (j
=0; j
<post_len
; j
++) {
3854 int idx
= liseq
->local_size
- (post_start
+ j
);
3855 ADD_INSN1(args
, nd_line(node
), getlocal
, INT2FIX(idx
));
3857 argc
= INT2FIX(post_len
+ post_start
);
3863 /* dummy reciever */
3864 ADD_INSN1(ret
, nd_line(node
), putobject
,
3865 nd_type(node
) == NODE_ZSUPER
? Qfalse
: Qtrue
);
3867 ADD_INSN3(ret
, nd_line(node
), invokesuper
,
3868 argc
, parent_block
, LONG2FIX(flag
));
3871 ADD_INSN(ret
, nd_line(node
), pop
);
3876 compile_array_(iseq
, ret
, node
, Qtrue
, poped
);
3881 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(0));
3888 COMPILE(ret
, "values item", n
->nd_head
);
3891 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(node
->nd_alen
));
3893 ADD_INSN(ret
, nd_line(node
), pop
);
3900 int type
= node
->nd_head
? nd_type(node
->nd_head
) : NODE_ZARRAY
;
3905 compile_array(iseq
, list
, node
->nd_head
, Qfalse
);
3906 size
= OPERAND_AT(POP_ELEMENT(list
), 0);
3915 rb_bug("can't make hash with this node: %s", ruby_node_name(type
));
3918 ADD_INSN1(ret
, nd_line(node
), newhash
, size
);
3921 ADD_INSN(ret
, nd_line(node
), pop
);
3926 rb_iseq_t
*is
= iseq
;
3929 if (is
->type
== ISEQ_TYPE_TOP
|| is
->type
== ISEQ_TYPE_CLASS
) {
3930 COMPILE_ERROR((ERROR_ARGS
"Invalid return"));
3936 if (is
->type
== ISEQ_TYPE_METHOD
) {
3937 splabel
= NEW_LABEL(0);
3938 ADD_LABEL(ret
, splabel
);
3939 ADD_ADJUST(ret
, nd_line(node
), 0);
3942 COMPILE(ret
, "return nd_stts (return val)", node
->nd_stts
);
3944 if (is
->type
== ISEQ_TYPE_METHOD
) {
3945 add_ensure_iseq(ret
, iseq
);
3946 ADD_INSN(ret
, nd_line(node
), leave
);
3947 ADD_ADJUST_RESTORE(ret
, splabel
);
3950 ADD_INSN(ret
, nd_line(node
), putnil
);
3954 ADD_INSN1(ret
, nd_line(node
), throw, INT2FIX(0x01) /* TAG_RETURN */ );
3956 ADD_INSN(ret
, nd_line(node
), pop
);
3967 unsigned long flag
= 0;
3970 if (iseq
->type
== ISEQ_TYPE_TOP
|| iseq
->type
== ISEQ_TYPE_CLASS
) {
3971 COMPILE_ERROR((ERROR_ARGS
"Invalid yield"));
3974 if (node
->nd_head
) {
3975 argc
= setup_args(iseq
, args
, node
->nd_head
, &flag
);
3982 ADD_INSN2(ret
, nd_line(node
), invokeblock
, argc
, LONG2FIX(flag
));
3985 ADD_INSN(ret
, nd_line(node
), pop
);
3991 ID id
= node
->nd_vid
;
3992 int idx
= iseq
->local_iseq
->local_size
- get_local_var_idx(iseq
, id
);
3994 debugs("id: %s idx: %d\n", rb_id2name(id
), idx
);
3995 ADD_INSN1(ret
, nd_line(node
), getlocal
, INT2FIX(idx
));
4001 debugi("nd_vid", node
->nd_vid
);
4003 idx
= get_dyna_var_idx(iseq
, node
->nd_vid
, &lv
, &ls
);
4005 rb_bug("unknown dvar (%s)", rb_id2name(node
->nd_vid
));
4007 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(ls
- idx
), INT2FIX(lv
));
4012 ADD_INSN1(ret
, nd_line(node
), getglobal
,
4013 (((long)node
->nd_entry
) | 1));
4015 ADD_INSN(ret
, nd_line(node
), pop
);
4020 debugi("nd_vid", node
->nd_vid
);
4022 ADD_INSN1(ret
, nd_line(node
), getinstancevariable
,
4023 ID2SYM(node
->nd_vid
));
4028 debugi("nd_vid", node
->nd_vid
);
4030 if (iseq
->compile_data
->option
->inline_const_cache
) {
4031 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4032 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4034 ADD_LABEL(ret
, lstart
);
4035 ADD_INSN2(ret
, nd_line(node
), getinlinecache
, 0, lend
);
4036 ADD_INSN1(ret
, nd_line(node
), getconstant
, ID2SYM(node
->nd_vid
));
4037 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4038 ADD_LABEL(ret
, lend
);
4041 ADD_INSN(ret
, nd_line(node
), putnil
);
4042 ADD_INSN1(ret
, nd_line(node
), getconstant
, ID2SYM(node
->nd_vid
));
4046 ADD_INSN(ret
, nd_line(node
), pop
);
4052 ADD_INSN1(ret
, nd_line(node
), getclassvariable
,
4053 ID2SYM(node
->nd_vid
));
4059 ADD_INSN2(ret
, nd_line(node
), getspecial
, INT2FIX(1) /* '~' */,
4060 INT2FIX(node
->nd_nth
<< 1));
4064 case NODE_BACK_REF
:{
4066 ADD_INSN2(ret
, nd_line(node
), getspecial
, INT2FIX(1) /* '~' */,
4067 INT2FIX(0x01 | (node
->nd_nth
<< 1)));
4079 switch(nd_type(node
)) {
4081 ADD_INSN1(recv
, nd_line(node
), putobject
, node
->nd_lit
);
4082 ADD_INSN2(val
, nd_line(node
), getspecial
, INT2FIX(0),
4086 COMPILE(recv
, "reciever", node
->nd_recv
);
4087 COMPILE(val
, "value", node
->nd_value
);
4090 COMPILE(recv
, "reciever", node
->nd_value
);
4091 COMPILE(val
, "value", node
->nd_recv
);
4095 if (iseq
->compile_data
->option
->specialized_instruction
) {
4096 /* TODO: detect by node */
4097 if (recv
->last
== recv
->anchor
.next
&&
4098 INSN_OF(recv
->last
) == BIN(putobject
) &&
4099 nd_type(node
) == NODE_MATCH2
) {
4101 ADD_INSN1(ret
, nd_line(node
), opt_regexpmatch1
,
4102 OPERAND_AT(recv
->last
, 0));
4107 ADD_INSN(ret
, nd_line(node
), opt_regexpmatch2
);
4113 ADD_SEND(ret
, nd_line(node
), ID2SYM(idEqTilde
), INT2FIX(1));
4117 ADD_INSN(ret
, nd_line(node
), pop
);
4122 debugp_param("lit", node
->nd_lit
);
4124 ADD_INSN1(ret
, nd_line(node
), putobject
, node
->nd_lit
);
4129 debugp_param("nd_lit", node
->nd_lit
);
4131 ADD_INSN1(ret
, nd_line(node
), putstring
, node
->nd_lit
);
4136 compile_dstr(iseq
, ret
, node
);
4139 ADD_INSN(ret
, nd_line(node
), pop
);
4144 ADD_CALL_RECEIVER(ret
, nd_line(node
));
4145 ADD_INSN1(ret
, nd_line(node
), putobject
, node
->nd_lit
);
4146 ADD_CALL(ret
, nd_line(node
), ID2SYM(idBackquote
), INT2FIX(1));
4149 ADD_INSN(ret
, nd_line(node
), pop
);
4154 ADD_CALL_RECEIVER(ret
, nd_line(node
));
4155 compile_dstr(iseq
, ret
, node
);
4156 ADD_CALL(ret
, nd_line(node
), ID2SYM(idBackquote
), INT2FIX(1));
4159 ADD_INSN(ret
, nd_line(node
), pop
);
4164 COMPILE(ret
, "nd_body", node
->nd_body
);
4167 ADD_INSN(ret
, nd_line(node
), pop
);
4170 ADD_INSN(ret
, nd_line(node
), tostring
);
4175 compile_dregx(iseq
, ret
, node
);
4178 ADD_INSN(ret
, nd_line(node
), pop
);
4182 case NODE_DREGX_ONCE
:{
4184 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4185 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4187 ADD_LABEL(ret
, lstart
);
4188 ADD_INSN2(ret
, nd_line(node
), onceinlinecache
, 0, lend
);
4189 ADD_INSN(ret
, nd_line(node
), pop
);
4191 compile_dregx(iseq
, ret
, node
);
4193 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4194 ADD_LABEL(ret
, lend
);
4197 ADD_INSN(ret
, nd_line(node
), pop
);
4202 COMPILE(ret
, "argscat head", node
->nd_head
);
4203 COMPILE(ret
, "argscat body", node
->nd_body
);
4204 ADD_INSN(ret
, nd_line(node
), concatarray
);
4207 case NODE_ARGSPUSH
:{
4208 COMPILE(ret
, "arsgpush head", node
->nd_head
);
4209 COMPILE(ret
, "argspush body", node
->nd_body
);
4210 ADD_INSN1(ret
, nd_line(node
), newarray
, INT2FIX(1));
4211 ADD_INSN(ret
, nd_line(node
), concatarray
);
4215 COMPILE(ret
, "splat", node
->nd_head
);
4216 ADD_INSN1(ret
, nd_line(node
), splatarray
, Qfalse
);
4219 ADD_INSN(ret
, nd_line(node
), pop
);
4224 VALUE iseqval
= NEW_ISEQVAL(node
->nd_defn
,
4225 rb_str_dup(rb_id2str(node
->nd_mid
)),
4228 debugp_param("defn/iseq", iseqval
);
4230 ADD_INSN1(ret
, nd_line(node
), putspecialobject
, INT2FIX(VM_SPECIAL_OBJECT_VMCORE
));
4231 ADD_INSN1(ret
, nd_line(node
), putspecialobject
, INT2FIX(VM_SPECIAL_OBJECT_CBASE
));
4232 ADD_INSN1(ret
, nd_line(node
), putobject
, ID2SYM(node
->nd_mid
));
4233 ADD_INSN1(ret
, nd_line(node
), putiseq
, iseqval
);
4234 ADD_SEND (ret
, nd_line(node
), ID2SYM(id_core_define_method
), INT2FIX(3));
4237 ADD_INSN(ret
, nd_line(node
), pop
);
4240 debugp_param("defn", iseqval
);
4244 VALUE iseqval
= NEW_ISEQVAL(node
->nd_defn
,
4245 rb_str_dup(rb_id2str(node
->nd_mid
)),
4248 debugp_param("defs/iseq", iseqval
);
4250 ADD_INSN1(ret
, nd_line(node
), putspecialobject
, INT2FIX(VM_SPECIAL_OBJECT_VMCORE
));
4251 COMPILE(ret
, "defs: recv", node
->nd_recv
);
4252 ADD_INSN1(ret
, nd_line(node
), putobject
, ID2SYM(node
->nd_mid
));
4253 ADD_INSN1(ret
, nd_line(node
), putiseq
, iseqval
);
4254 ADD_SEND (ret
, nd_line(node
), ID2SYM(id_core_define_singleton_method
), INT2FIX(3));
4257 ADD_INSN(ret
, nd_line(node
), pop
);
4262 ADD_INSN1(ret
, nd_line(node
), putspecialobject
, INT2FIX(VM_SPECIAL_OBJECT_VMCORE
));
4263 ADD_INSN1(ret
, nd_line(node
), putspecialobject
, INT2FIX(VM_SPECIAL_OBJECT_CBASE
));
4264 COMPILE(ret
, "alias arg1", node
->u1
.node
);
4265 COMPILE(ret
, "alias arg2", node
->u2
.node
);
4266 ADD_SEND(ret
, nd_line(node
), ID2SYM(id_core_set_method_alias
), INT2FIX(3));
4269 ADD_INSN(ret
, nd_line(node
), pop
);
4274 ADD_INSN1(ret
, nd_line(node
), putspecialobject
, INT2FIX(VM_SPECIAL_OBJECT_VMCORE
));
4275 ADD_INSN1(ret
, nd_line(node
), putobject
, ID2SYM(node
->u1
.id
));
4276 ADD_INSN1(ret
, nd_line(node
), putobject
, ID2SYM(node
->u2
.id
));
4277 ADD_SEND(ret
, nd_line(node
), ID2SYM(id_core_set_variable_alias
), INT2FIX(2));
4280 ADD_INSN(ret
, nd_line(node
), pop
);
4285 ADD_INSN1(ret
, nd_line(node
), putspecialobject
, INT2FIX(VM_SPECIAL_OBJECT_VMCORE
));
4286 ADD_INSN1(ret
, nd_line(node
), putspecialobject
, INT2FIX(VM_SPECIAL_OBJECT_CBASE
));
4287 COMPILE(ret
, "undef arg", node
->u2
.node
);
4288 ADD_SEND(ret
, nd_line(node
), ID2SYM(id_core_undef_method
), INT2FIX(2));
4291 ADD_INSN(ret
, nd_line(node
), pop
);
4299 rb_sprintf("<class:%s>", rb_id2name(node
->nd_cpath
->nd_mid
)),
4301 compile_cpath(ret
, iseq
, node
->nd_cpath
);
4302 COMPILE(ret
, "super", node
->nd_super
);
4303 ADD_INSN3(ret
, nd_line(node
), defineclass
,
4304 ID2SYM(node
->nd_cpath
->nd_mid
), iseqval
, INT2FIX(0));
4307 ADD_INSN(ret
, nd_line(node
), pop
);
4312 VALUE iseqval
= NEW_CHILD_ISEQVAL(
4314 rb_sprintf("<module:%s>", rb_id2name(node
->nd_cpath
->nd_mid
)),
4317 compile_cpath(ret
, iseq
, node
->nd_cpath
);
4318 ADD_INSN (ret
, nd_line(node
), putnil
); /* dummy */
4319 ADD_INSN3(ret
, nd_line(node
), defineclass
,
4320 ID2SYM(node
->nd_cpath
->nd_mid
), iseqval
, INT2FIX(2));
4322 ADD_INSN(ret
, nd_line(node
), pop
);
4329 NEW_ISEQVAL(node
->nd_body
, rb_str_new2("singletonclass"),
4332 COMPILE(ret
, "sclass#recv", node
->nd_recv
);
4333 ADD_INSN (ret
, nd_line(node
), putnil
);
4334 CONST_ID(singletonclass
, "singletonclass");
4335 ADD_INSN3(ret
, nd_line(node
), defineclass
,
4336 ID2SYM(singletonclass
), iseqval
, INT2FIX(1));
4339 ADD_INSN(ret
, nd_line(node
), pop
);
4344 if (rb_is_const_id(node
->nd_mid
)) {
4346 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4347 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4353 compile_colon2(iseq
, node
, pref
, body
);
4354 if (LIST_SIZE_ZERO(pref
)) {
4355 if (iseq
->compile_data
->option
->inline_const_cache
) {
4356 ADD_LABEL(ret
, lstart
);
4357 ADD_INSN2(ret
, nd_line(node
), getinlinecache
, 0, lend
);
4360 ADD_INSN(ret
, nd_line(node
), putnil
);
4365 if (iseq
->compile_data
->option
->inline_const_cache
) {
4366 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4367 ADD_LABEL(ret
, lend
);
4377 ADD_CALL_RECEIVER(ret
, nd_line(node
));
4378 COMPILE(ret
, "colon2#nd_head", node
->nd_head
);
4379 ADD_CALL(ret
, nd_line(node
), ID2SYM(node
->nd_mid
),
4383 ADD_INSN(ret
, nd_line(node
), pop
);
4388 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4389 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4390 debugi("colon3#nd_mid", node
->nd_mid
);
4392 /* add cache insn */
4393 if (iseq
->compile_data
->option
->inline_const_cache
) {
4394 ADD_LABEL(ret
, lstart
);
4395 ADD_INSN2(ret
, nd_line(node
), getinlinecache
, 0, lend
);
4396 ADD_INSN(ret
, nd_line(node
), pop
);
4399 ADD_INSN1(ret
, nd_line(node
), putobject
, rb_cObject
);
4400 ADD_INSN1(ret
, nd_line(node
), getconstant
, ID2SYM(node
->nd_mid
));
4402 if (iseq
->compile_data
->option
->inline_const_cache
) {
4403 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4404 ADD_LABEL(ret
, lend
);
4408 ADD_INSN(ret
, nd_line(node
), pop
);
4414 int flag
= type
== NODE_DOT2
? INT2FIX(0) : INT2FIX(1);
4415 COMPILE(ret
, "min", (NODE
*) node
->nd_beg
);
4416 COMPILE(ret
, "max", (NODE
*) node
->nd_end
);
4418 ADD_INSN(ret
, nd_line(node
), pop
);
4419 ADD_INSN(ret
, nd_line(node
), pop
);
4422 ADD_INSN1(ret
, nd_line(node
), newrange
, flag
);
4428 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4429 LABEL
*lfin
= NEW_LABEL(nd_line(node
));
4430 LABEL
*ltrue
= NEW_LABEL(nd_line(node
));
4431 VALUE key
= rb_sprintf("flipflag/%s-%p-%d",
4432 RSTRING_PTR(iseq
->name
), iseq
,
4433 iseq
->compile_data
->flip_cnt
++);
4435 iseq_add_mark_object_compile_time(iseq
, key
);
4436 ADD_INSN2(ret
, nd_line(node
), getspecial
, key
, INT2FIX(0));
4437 ADD_INSNL(ret
, nd_line(node
), branchif
, lend
);
4440 COMPILE(ret
, "flip2 beg", node
->nd_beg
);
4441 ADD_INSN(ret
, nd_line(node
), dup
);
4442 ADD_INSNL(ret
, nd_line(node
), branchunless
, lfin
);
4443 if (nd_type(node
) == NODE_FLIP3
) {
4444 ADD_INSN(ret
, nd_line(node
), dup
);
4445 ADD_INSN1(ret
, nd_line(node
), setspecial
, key
);
4446 ADD_INSNL(ret
, nd_line(node
), jump
, lfin
);
4449 ADD_INSN1(ret
, nd_line(node
), setspecial
, key
);
4453 ADD_LABEL(ret
, lend
);
4454 COMPILE(ret
, "flip2 end", node
->nd_end
);
4455 ADD_INSNL(ret
, nd_line(node
), branchunless
, ltrue
);
4456 ADD_INSN1(ret
, nd_line(node
), putobject
, Qfalse
);
4457 ADD_INSN1(ret
, nd_line(node
), setspecial
, key
);
4459 ADD_LABEL(ret
, ltrue
);
4460 ADD_INSN1(ret
, nd_line(node
), putobject
, Qtrue
);
4462 ADD_LABEL(ret
, lfin
);
4467 ADD_INSN(ret
, nd_line(node
), putself
);
4473 ADD_INSN(ret
, nd_line(node
), putnil
);
4479 ADD_INSN1(ret
, nd_line(node
), putobject
, Qtrue
);
4485 ADD_INSN1(ret
, nd_line(node
), putobject
, Qfalse
);
4491 if (iseq
->type
== ISEQ_TYPE_RESCUE
) {
4492 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(2), INT2FIX(0));
4495 rb_iseq_t
*ip
= iseq
;
4498 if (ip
->type
== ISEQ_TYPE_RESCUE
) {
4501 ip
= ip
->parent_iseq
;
4505 ADD_INSN2(ret
, nd_line(node
), getdynamic
, INT2FIX(2), INT2FIX(level
));
4508 ADD_INSN(ret
, nd_line(node
), putnil
);
4517 lfinish
[0] = NEW_LABEL(nd_line(node
));
4519 defined_expr(iseq
, ret
, node
->nd_head
, lfinish
, Qtrue
);
4521 ADD_INSNL(ret
, nd_line(node
), jump
, lfinish
[0]);
4522 ADD_LABEL(ret
, lfinish
[1]);
4523 ADD_INSN(ret
, nd_line(node
), putnil
);
4525 ADD_LABEL(ret
, lfinish
[0]);
4530 LABEL
*lstart
= NEW_LABEL(nd_line(node
));
4531 LABEL
*lend
= NEW_LABEL(nd_line(node
));
4532 VALUE block
= NEW_CHILD_ISEQVAL(node
->nd_body
, make_name_for_block(iseq
), ISEQ_TYPE_BLOCK
);
4534 ADD_LABEL(ret
, lstart
);
4535 ADD_INSN2(ret
, nd_line(node
), onceinlinecache
, 0, lend
);
4536 ADD_INSN(ret
, nd_line(node
), pop
);
4538 ADD_INSN1(ret
, nd_line(node
), putspecialobject
, INT2FIX(VM_SPECIAL_OBJECT_VMCORE
));
4539 ADD_INSN1(ret
, nd_line(node
), putiseq
, block
);
4540 ADD_SEND (ret
, nd_line(node
), ID2SYM(id_core_set_postexe
), INT2FIX(1));
4542 ADD_INSN1(ret
, nd_line(node
), setinlinecache
, lstart
);
4543 ADD_LABEL(ret
, lend
);
4546 ADD_INSN(ret
, nd_line(node
), pop
);
4551 compile_dstr(iseq
, ret
, node
);
4553 ADD_SEND(ret
, nd_line(node
), ID2SYM(idIntern
), INT2FIX(0));
4556 ADD_INSN(ret
, nd_line(node
), pop
);
4560 case NODE_ATTRASGN
:{
4563 unsigned long flag
= 0;
4568 argc
= setup_args(iseq
, args
, node
->nd_args
, &flag
);
4570 if (node
->nd_recv
== (NODE
*) 1) {
4571 flag
|= VM_CALL_FCALL_BIT
;
4572 ADD_INSN(recv
, nd_line(node
), putself
);
4575 COMPILE(recv
, "recv", node
->nd_recv
);
4578 debugp_param("argc", argc
);
4579 debugp_param("nd_mid", ID2SYM(node
->nd_mid
));
4582 ADD_INSN(ret
, nd_line(node
), putnil
);
4586 if (flag
& VM_CALL_ARGS_BLOCKARG_BIT
) {
4587 ADD_INSN1(ret
, nd_line(node
), topn
, INT2FIX(1));
4588 ADD_INSN1(ret
, nd_line(node
), setn
, INT2FIX(FIX2INT(argc
) + 3));
4589 ADD_INSN (ret
, nd_line(node
), pop
);
4592 ADD_INSN1(ret
, nd_line(node
), setn
, INT2FIX(FIX2INT(argc
) + 1));
4599 ADD_SEND_R(ret
, nd_line(node
), ID2SYM(node
->nd_mid
), argc
, 0, LONG2FIX(flag
));
4600 ADD_INSN(ret
, nd_line(node
), pop
);
4604 case NODE_OPTBLOCK
:{
4606 LABEL
*redo_label
= NEW_LABEL(0);
4607 LABEL
*next_label
= NEW_LABEL(0);
4609 iseq
->compile_data
->start_label
= next_label
;
4610 iseq
->compile_data
->redo_label
= redo_label
;
4612 ADD_LABEL(ret
, redo_label
);
4613 COMPILE_(ret
, "optblock body", node
->nd_head
, 1 /* pop */ );
4614 ADD_LABEL(ret
, next_label
);
4615 ADD_INSN(ret
, 0, opt_checkenv
);
4619 COMPILE_POPED(ret
, "prelude", node
->nd_head
);
4620 COMPILE_(ret
, "body", node
->nd_body
, poped
);
4624 /* compile same as lambda{...} */
4625 VALUE block
= NEW_CHILD_ISEQVAL(node
->nd_body
, make_name_for_block(iseq
), ISEQ_TYPE_BLOCK
);
4626 VALUE argc
= INT2FIX(0);
4627 ADD_CALL_RECEIVER(ret
, nd_line(node
));
4628 ADD_CALL_WITH_BLOCK(ret
, nd_line(node
), ID2SYM(idLambda
), argc
, block
);
4631 ADD_INSN(ret
, nd_line(node
), pop
);
4636 rb_bug("iseq_compile_each: unknown node: %s", ruby_node_name(type
));
4644 /***************************/
4645 /* instruction information */
4646 /***************************/
4649 insn_data_length(INSN
*iobj
)
4651 return insn_len(iobj
->insn_id
);
4655 calc_sp_depth(int depth
, INSN
*insn
)
4657 return insn_stack_increase(depth
, insn
->insn_id
, insn
->operands
);
4661 insn_data_line_no(INSN
*iobj
)
4663 return insn_len(iobj
->line_no
);
4667 insn_data_to_s_detail(INSN
*iobj
)
4669 VALUE str
= rb_str_new(0, 0);
4671 str
= rb_sprintf("%-16s", insn_name(iobj
->insn_id
));
4672 if (iobj
->operands
) {
4673 const char *types
= insn_op_types(iobj
->insn_id
);
4676 for (j
= 0; types
[j
]; j
++) {
4677 char type
= types
[j
];
4680 case TS_OFFSET
: /* label(destination position) */
4682 LABEL
*lobj
= (LABEL
*)OPERAND_AT(iobj
, j
);
4683 rb_str_catf(str
, "<L%03d>", lobj
->label_no
);
4687 case TS_ISEQ
: /* iseq */
4689 rb_iseq_t
*iseq
= (rb_iseq_t
*)OPERAND_AT(iobj
, j
);
4694 rb_str_concat(str
, rb_inspect(val
));
4699 case TS_NUM
: /* ulong */
4700 case TS_VALUE
: /* VALUE */
4701 rb_str_concat(str
, rb_inspect(OPERAND_AT(iobj
, j
)));
4703 case TS_ID
: /* ID */
4704 rb_str_concat(str
, rb_inspect(OPERAND_AT(iobj
, j
)));
4708 struct global_entry
*entry
= (struct global_entry
*)
4709 (OPERAND_AT(iobj
, j
) & (~1));
4710 rb_str_cat2(str
, rb_id2name(entry
->id
));
4712 case TS_IC
: /* method cache */
4713 rb_str_cat2(str
, "<ic>");
4715 case TS_CDHASH
: /* case/when condition cache */
4716 rb_str_cat2(str
, "<ch>");
4719 rb_raise(rb_eSyntaxError
, "unknown operand type: %c", type
);
4723 rb_str_cat2(str
, ", ");
4731 dump_disasm_list(struct iseq_link_element
*link
)
4738 printf("-- raw disasm--------\n");
4741 switch (link
->type
) {
4742 case ISEQ_ELEMENT_INSN
:
4744 iobj
= (INSN
*)link
;
4745 str
= insn_data_to_s_detail(iobj
);
4746 printf("%04d %-65s(%4d)\n", pos
, StringValueCStr(str
),
4747 insn_data_line_no(iobj
));
4748 pos
+= insn_data_length(iobj
);
4751 case ISEQ_ELEMENT_LABEL
:
4753 lobj
= (LABEL
*)link
;
4754 printf("<L%03d>\n", lobj
->label_no
);
4757 case ISEQ_ELEMENT_NONE
:
4762 case ISEQ_ELEMENT_ADJUST
:
4764 ADJUST
*adjust
= (ADJUST
*)link
;
4765 printf("adjust: [label: %d]\n", adjust
->label
->label_no
);
4770 rb_raise(rb_eSyntaxError
, "dump_disasm_list error: %ld\n", FIX2LONG(link
->type
));
4774 printf("---------------------\n");
4778 insns_name_array(void)
4780 VALUE ary
= rb_ary_new();
4782 for (i
= 0; i
< sizeof(insn_name_info
) / sizeof(insn_name_info
[0]); i
++) {
4783 rb_ary_push(ary
, rb_str_new2(insn_name_info
[i
]));
4789 register_label(rb_iseq_t
*iseq
, struct st_table
*labels_table
, VALUE obj
)
4793 obj
= rb_convert_type(obj
, T_SYMBOL
, "Symbol", "to_sym");
4795 if (st_lookup(labels_table
, obj
, &tmp
) == 0) {
4796 label
= NEW_LABEL(0);
4797 st_insert(labels_table
, obj
, (st_data_t
)label
);
4800 label
= (LABEL
*)tmp
;
4806 get_exception_sym2type(VALUE sym
)
4809 static VALUE symRescue
, symEnsure
, symRetry
;
4810 static VALUE symBreak
, symRedo
, symNext
;
4812 if (symRescue
== 0) {
4813 symRescue
= ID2SYM(rb_intern("rescue"));
4814 symEnsure
= ID2SYM(rb_intern("ensure"));
4815 symRetry
= ID2SYM(rb_intern("retry"));
4816 symBreak
= ID2SYM(rb_intern("break"));
4817 symRedo
= ID2SYM(rb_intern("redo"));
4818 symNext
= ID2SYM(rb_intern("next"));
4821 if (sym
== symRescue
) return CATCH_TYPE_RESCUE
;
4822 if (sym
== symEnsure
) return CATCH_TYPE_ENSURE
;
4823 if (sym
== symRetry
) return CATCH_TYPE_RETRY
;
4824 if (sym
== symBreak
) return CATCH_TYPE_BREAK
;
4825 if (sym
== symRedo
) return CATCH_TYPE_REDO
;
4826 if (sym
== symNext
) return CATCH_TYPE_NEXT
;
4827 rb_raise(rb_eSyntaxError
, "invalid exception symbol: %s",
4828 RSTRING_PTR(rb_inspect(sym
)));
4833 iseq_build_exception(rb_iseq_t
*iseq
, struct st_table
*labels_table
,
4838 for (i
=0; i
<RARRAY_LEN(exception
); i
++) {
4839 VALUE v
, type
, *ptr
, eiseqval
;
4840 LABEL
*lstart
, *lend
, *lcont
;
4843 RB_GC_GUARD(v
) = rb_convert_type(RARRAY_PTR(exception
)[i
], T_ARRAY
,
4845 if (RARRAY_LEN(v
) != 6) {
4846 rb_raise(rb_eSyntaxError
, "wrong exception entry");
4848 ptr
= RARRAY_PTR(v
);
4849 type
= get_exception_sym2type(ptr
[0]);
4850 if (ptr
[1] == Qnil
) {
4854 eiseqval
= iseq_load(0, ptr
[1], iseq
->self
, Qnil
);
4857 lstart
= register_label(iseq
, labels_table
, ptr
[2]);
4858 lend
= register_label(iseq
, labels_table
, ptr
[3]);
4859 lcont
= register_label(iseq
, labels_table
, ptr
[4]);
4860 sp
= NUM2INT(ptr
[5]);
4862 ADD_CATCH_ENTRY(type
, lstart
, lend
, eiseqval
, lcont
);
4867 struct st_table
*insn_make_insn_table(void);
4870 iseq_build_body(rb_iseq_t
*iseq
, LINK_ANCHOR
*anchor
,
4871 VALUE body
, struct st_table
*labels_table
)
4873 /* TODO: body should be freezed */
4874 VALUE
*ptr
= RARRAY_PTR(body
);
4875 int len
= RARRAY_LEN(body
);
4879 * index -> LABEL *label
4881 static struct st_table
*insn_table
;
4883 if (insn_table
== 0) {
4884 insn_table
= insn_make_insn_table();
4887 for (i
=0; i
<len
; i
++) {
4890 if (SYMBOL_P(obj
)) {
4891 LABEL
*label
= register_label(iseq
, labels_table
, obj
);
4892 ADD_LABEL(anchor
, label
);
4894 else if (FIXNUM_P(obj
)) {
4895 line_no
= NUM2INT(obj
);
4897 else if (TYPE(obj
) == T_ARRAY
) {
4899 int argc
= RARRAY_LEN(obj
) - 1;
4903 insn
= (argc
< 0) ? Qnil
: RARRAY_PTR(obj
)[0];
4904 if (st_lookup(insn_table
, insn
, &insn_id
) == 0) {
4905 /* TODO: exception */
4906 RB_GC_GUARD(insn
) = rb_inspect(insn
);
4907 rb_compile_error(RSTRING_PTR(iseq
->filename
), line_no
,
4908 "unknown instruction: %s", RSTRING_PTR(insn
));
4911 if (argc
!= insn_len(insn_id
)-1) {
4912 rb_compile_error(RSTRING_PTR(iseq
->filename
), line_no
,
4913 "operand size mismatch");
4917 argv
= compile_data_alloc(iseq
, sizeof(VALUE
) * argc
);
4918 for (j
=0; j
<argc
; j
++) {
4919 VALUE op
= rb_ary_entry(obj
, j
+1);
4920 switch (insn_op_type(insn_id
, j
)) {
4922 LABEL
*label
= register_label(iseq
, labels_table
, op
);
4923 argv
[j
] = (VALUE
)label
;
4929 argv
[j
] = (NUM2INT(op
), op
);
4933 iseq_add_mark_object(iseq
, op
);
4938 if (TYPE(op
) == T_ARRAY
) {
4939 argv
[j
] = iseq_load(0, op
, iseq
->self
, Qnil
);
4941 else if (CLASS_OF(op
) == rb_cISeq
) {
4945 rb_raise(rb_eSyntaxError
, "ISEQ is required");
4947 iseq_add_mark_object(iseq
, argv
[j
]);
4955 op
= rb_convert_type(op
, T_SYMBOL
, "Symbol", "to_sym");
4956 argv
[j
] = (VALUE
)rb_global_entry(SYM2ID(op
));
4959 argv
[j
] = (VALUE
)NEW_INLINE_CACHE_ENTRY();
4960 iseq_add_mark_object(iseq
, argv
[j
]);
4963 argv
[j
] = rb_convert_type(op
, T_SYMBOL
,
4964 "Symbol", "to_sym");
4969 op
= rb_convert_type(op
, T_ARRAY
, "Array", "to_ary");
4970 op
= rb_ary_dup(op
);
4971 for (i
=0; i
<RARRAY_LEN(op
); i
+=2) {
4972 VALUE sym
= rb_ary_entry(op
, i
+1);
4974 register_label(iseq
, labels_table
, sym
);
4975 rb_ary_store(op
, i
+1, (VALUE
)label
| 1);
4981 rb_raise(rb_eSyntaxError
, "unknown operand: %c", insn_op_type(insn_id
, j
));
4986 (LINK_ELEMENT
*)new_insn_core(iseq
, line_no
,
4987 insn_id
, argc
, argv
));
4990 rb_raise(rb_eTypeError
, "unexpected object for instruction");
4993 st_free_table(labels_table
);
4994 iseq_setup(iseq
, anchor
);
4998 #define CHECK_ARRAY(v) rb_convert_type(v, T_ARRAY, "Array", "to_ary")
4999 #define CHECK_STRING(v) rb_convert_type(v, T_STRING, "String", "to_str")
5000 #define CHECK_SYMBOL(v) rb_convert_type(v, T_SYMBOL, "Symbol", "to_sym")
5001 static inline VALUE
CHECK_INTEGER(VALUE v
) {NUM2LONG(v
); return v
;}
5004 iseq_build_from_ary(rb_iseq_t
*iseq
, VALUE locals
, VALUE args
,
5005 VALUE exception
, VALUE body
)
5009 struct st_table
*labels_table
= st_init_numtable();
5011 DECL_ANCHOR(anchor
);
5013 INIT_ANCHOR(anchor
);
5015 iseq
->local_table_size
= RARRAY_LEN(locals
);
5016 iseq
->local_table
= tbl
= (ID
*)ALLOC_N(ID
*, iseq
->local_table_size
);
5017 iseq
->local_size
= iseq
->local_table_size
+ 1;
5019 for (i
=0; i
<RARRAY_LEN(locals
); i
++) {
5020 VALUE lv
= RARRAY_PTR(locals
)[i
];
5021 tbl
[i
] = FIXNUM_P(lv
) ? FIX2INT(lv
) : SYM2ID(CHECK_SYMBOL(lv
));
5025 if (FIXNUM_P(args
)) {
5026 iseq
->arg_size
= iseq
->argc
= FIX2INT(args
);
5027 iseq
->arg_simple
= 1;
5031 VALUE argc
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5032 VALUE arg_opt_labels
= CHECK_ARRAY(rb_ary_entry(args
, i
++));
5033 VALUE arg_post_len
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5034 VALUE arg_post_start
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5035 VALUE arg_rest
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5036 VALUE arg_block
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5037 VALUE arg_simple
= CHECK_INTEGER(rb_ary_entry(args
, i
++));
5039 iseq
->argc
= FIX2INT(argc
);
5040 iseq
->arg_rest
= FIX2INT(arg_rest
);
5041 iseq
->arg_post_len
= FIX2INT(arg_post_len
);
5042 iseq
->arg_post_start
= FIX2INT(arg_post_start
);
5043 iseq
->arg_block
= FIX2INT(arg_block
);
5044 iseq
->arg_opts
= RARRAY_LEN(arg_opt_labels
);
5045 iseq
->arg_opt_table
= (VALUE
*)ALLOC_N(VALUE
, iseq
->arg_opts
);
5047 if (iseq
->arg_block
!= -1) {
5048 iseq
->arg_size
= iseq
->arg_block
+ 1;
5050 else if (iseq
->arg_post_len
) {
5051 iseq
->arg_size
= iseq
->arg_post_start
+ iseq
->arg_post_len
;
5053 else if (iseq
->arg_rest
!= -1) {
5054 iseq
->arg_size
= iseq
->arg_rest
+ 1;
5057 iseq
->arg_size
= iseq
->argc
+ (iseq
->arg_opts
? iseq
->arg_opts
- 1 : 0);
5060 for (i
=0; i
<RARRAY_LEN(arg_opt_labels
); i
++) {
5061 iseq
->arg_opt_table
[i
] =
5062 (VALUE
)register_label(iseq
, labels_table
,
5063 rb_ary_entry(arg_opt_labels
, i
));
5066 iseq
->arg_simple
= NUM2INT(arg_simple
);
5070 iseq_build_exception(iseq
, labels_table
, exception
);
5073 iseq_build_body(iseq
, anchor
, body
, labels_table
);