1 /**********************************************************************
3 insnhelper.c - instruction helper functions.
7 Copyright (C) 2007 Koichi Sasada
9 **********************************************************************/
11 /* finish iseq array */
16 /* control stack frame */
23 static inline rb_control_frame_t
*
24 vm_push_frame(rb_thread_t
*th
, rb_iseq_t
*iseq
, VALUE type
,
25 VALUE self
, VALUE specval
, VALUE
*pc
,
26 VALUE
*sp
, VALUE
*lfp
, int local_size
)
29 rb_control_frame_t
*cfp
;
33 for (i
=0; i
< local_size
; i
++) {
39 *sp
= GC_GUARDED_PTR(specval
);
46 cfp
= th
->cfp
= th
->cfp
- 1;
57 #define COLLECT_PROFILE 0
59 cfp
->prof_time_self
= clock();
60 cfp
->prof_time_chld
= 0;
71 vm_pop_frame(rb_thread_t
*th
)
74 rb_control_frame_t
*cfp
= th
->cfp
;
76 if (RUBY_VM_NORMAL_ISEQ_P(cfp
->iseq
)) {
77 VALUE current_time
= clock();
78 rb_control_frame_t
*cfp
= th
->cfp
;
79 cfp
->prof_time_self
= current_time
- cfp
->prof_time_self
;
80 (cfp
+1)->prof_time_chld
+= cfp
->prof_time_self
;
82 cfp
->iseq
->profile
.count
++;
83 cfp
->iseq
->profile
.time_cumu
= cfp
->prof_time_self
;
84 cfp
->iseq
->profile
.time_self
= cfp
->prof_time_self
- cfp
->prof_time_chld
;
86 else if (0 /* c method? */) {
90 th
->cfp
= RUBY_VM_PREVIOUS_CONTROL_FRAME(th
->cfp
);
100 vm_callee_setup_arg(rb_thread_t
*th
, rb_iseq_t
*iseq
,
101 int argc
, VALUE
*argv
, rb_block_t
**block
)
103 const int m
= iseq
->argc
;
104 const int orig_argc
= argc
;
106 if (LIKELY(iseq
->arg_simple
& 0x01)) {
109 rb_raise(rb_eArgError
, "wrong number of arguments (%d for %d)",
115 VALUE
* const dst
= argv
;
117 th
->mark_stack_len
= argc
+ iseq
->arg_size
;
120 if (argc
< (m
+ iseq
->arg_post_len
)) { /* check with post arg */
121 rb_raise(rb_eArgError
, "wrong number of arguments (%d for %d)",
122 argc
, m
+ iseq
->arg_post_len
);
129 if (iseq
->arg_post_len
) {
130 if (!(orig_argc
< iseq
->arg_post_start
)) {
131 VALUE
*new_argv
= ALLOCA_N(VALUE
, argc
);
132 MEMCPY(new_argv
, argv
, VALUE
, argc
);
136 MEMCPY(&dst
[iseq
->arg_post_start
], &argv
[argc
-= iseq
->arg_post_len
],
137 VALUE
, iseq
->arg_post_len
);
141 if (iseq
->arg_opts
) {
142 const int opts
= iseq
->arg_opts
- 1 /* no opt */;
144 if (iseq
->arg_rest
== -1 && argc
> opts
) {
145 rb_raise(rb_eArgError
, "wrong number of arguments (%d for %d)",
146 orig_argc
, m
+ opts
+ iseq
->arg_post_len
);
152 opt_pc
= iseq
->arg_opt_table
[opts
]; /* no opt */
156 for (i
= argc
; i
<opts
; i
++) {
159 opt_pc
= iseq
->arg_opt_table
[argc
];
165 if (iseq
->arg_rest
!= -1) {
166 dst
[iseq
->arg_rest
] = rb_ary_new4(argc
, argv
);
170 /* block arguments */
171 if (block
&& iseq
->arg_block
!= -1) {
172 VALUE blockval
= Qnil
;
173 rb_block_t
* const blockptr
= *block
;
176 rb_raise(rb_eArgError
, "wrong number of arguments (%d for %d)",
177 orig_argc
, m
+ iseq
->arg_post_len
);
181 /* make Proc object */
182 if (blockptr
->proc
== 0) {
185 blockval
= vm_make_proc(th
, th
->cfp
, blockptr
);
187 GetProcPtr(blockval
, proc
);
188 *block
= &proc
->block
;
191 blockval
= blockptr
->proc
;
195 dst
[iseq
->arg_block
] = blockval
; /* Proc or nil */
198 th
->mark_stack_len
= 0;
204 caller_setup_args(rb_thread_t
*th
, rb_control_frame_t
*cfp
, VALUE flag
,
205 int argc
, rb_iseq_t
*blockiseq
, rb_block_t
**block
)
207 rb_block_t
*blockptr
= 0;
210 if (flag
& VM_CALL_ARGS_BLOCKARG_BIT
) {
217 if (!rb_obj_is_proc(proc
)) {
218 VALUE b
= rb_check_convert_type(proc
, T_DATA
, "Proc", "to_proc");
220 rb_raise(rb_eTypeError
,
221 "wrong argument type %s (expected Proc)",
222 rb_obj_classname(proc
));
226 GetProcPtr(proc
, po
);
227 blockptr
= &po
->block
;
228 RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp
)->proc
= proc
;
232 else if (blockiseq
) {
233 blockptr
= RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp
);
234 blockptr
->iseq
= blockiseq
;
240 /* expand top of stack? */
241 if (flag
& VM_CALL_ARGS_SPLAT_BIT
) {
242 VALUE ary
= *(cfp
->sp
- 1);
245 VALUE tmp
= rb_check_convert_type(ary
, T_ARRAY
, "Array", "to_a");
251 int len
= RARRAY_LEN(tmp
);
252 ptr
= RARRAY_PTR(tmp
);
255 CHECK_STACK_OVERFLOW(cfp
, len
);
257 for (i
= 0; i
< len
; i
++) {
268 call_cfunc(VALUE (*func
)(), VALUE recv
, int len
, int argc
, const VALUE
*argv
)
270 /* printf("len: %d, argc: %d\n", len, argc); */
272 if (len
>= 0 && argc
!= len
) {
273 rb_raise(rb_eArgError
, "wrong number of arguments(%d for %d)",
279 return (*func
) (recv
, rb_ary_new4(argc
, argv
));
282 return (*func
) (argc
, argv
, recv
);
285 return (*func
) (recv
);
288 return (*func
) (recv
, argv
[0]);
291 return (*func
) (recv
, argv
[0], argv
[1]);
294 return (*func
) (recv
, argv
[0], argv
[1], argv
[2]);
297 return (*func
) (recv
, argv
[0], argv
[1], argv
[2], argv
[3]);
300 return (*func
) (recv
, argv
[0], argv
[1], argv
[2], argv
[3], argv
[4]);
303 return (*func
) (recv
, argv
[0], argv
[1], argv
[2], argv
[3], argv
[4],
307 return (*func
) (recv
, argv
[0], argv
[1], argv
[2], argv
[3], argv
[4],
311 return (*func
) (recv
, argv
[0], argv
[1], argv
[2], argv
[3], argv
[4],
312 argv
[5], argv
[6], argv
[7]);
315 return (*func
) (recv
, argv
[0], argv
[1], argv
[2], argv
[3], argv
[4],
316 argv
[5], argv
[6], argv
[7], argv
[8]);
319 return (*func
) (recv
, argv
[0], argv
[1], argv
[2], argv
[3], argv
[4],
320 argv
[5], argv
[6], argv
[7], argv
[8], argv
[9]);
323 return (*func
) (recv
, argv
[0], argv
[1], argv
[2], argv
[3], argv
[4],
324 argv
[5], argv
[6], argv
[7], argv
[8], argv
[9],
328 return (*func
) (recv
, argv
[0], argv
[1], argv
[2], argv
[3], argv
[4],
329 argv
[5], argv
[6], argv
[7], argv
[8], argv
[9],
333 return (*func
) (recv
, argv
[0], argv
[1], argv
[2], argv
[3], argv
[4],
334 argv
[5], argv
[6], argv
[7], argv
[8], argv
[9], argv
[10],
338 return (*func
) (recv
, argv
[0], argv
[1], argv
[2], argv
[3], argv
[4],
339 argv
[5], argv
[6], argv
[7], argv
[8], argv
[9], argv
[10],
340 argv
[11], argv
[12], argv
[13]);
343 return (*func
) (recv
, argv
[0], argv
[1], argv
[2], argv
[3], argv
[4],
344 argv
[5], argv
[6], argv
[7], argv
[8], argv
[9], argv
[10],
345 argv
[11], argv
[12], argv
[13], argv
[14]);
348 rb_raise(rb_eArgError
, "too many arguments(%d)", len
);
351 return Qnil
; /* not reached */
355 vm_call_cfunc(rb_thread_t
*th
, rb_control_frame_t
*reg_cfp
, int num
,
356 ID id
, VALUE recv
, VALUE klass
, VALUE flag
,
357 NODE
*mn
, rb_block_t
*blockptr
)
361 EXEC_EVENT_HOOK(th
, RUBY_EVENT_C_CALL
, recv
, id
, klass
);
363 rb_control_frame_t
*cfp
=
364 vm_push_frame(th
, 0, FRAME_MAGIC_CFUNC
| (flag
<< FRAME_MAGIC_MASK_BITS
),
365 recv
, (VALUE
) blockptr
, 0, reg_cfp
->sp
, 0, 1);
368 cfp
->method_class
= klass
;
370 reg_cfp
->sp
-= num
+ 1;
372 val
= call_cfunc(mn
->nd_cfnc
, recv
, mn
->nd_argc
, num
, reg_cfp
->sp
+ 1);
374 if (reg_cfp
!= th
->cfp
+ 1) {
375 rb_bug("cfp consistency error - send");
379 EXEC_EVENT_HOOK(th
, RUBY_EVENT_C_RETURN
, recv
, id
, klass
);
385 vm_cfunc_flags(rb_control_frame_t
*cfp
)
387 if (RUBYVM_CFUNC_FRAME_P(cfp
))
388 return cfp
->flag
>> FRAME_MAGIC_MASK_BITS
;
393 vm_call_bmethod(rb_thread_t
*th
, ID id
, VALUE procval
, VALUE recv
,
394 VALUE klass
, int argc
, VALUE
*argv
, rb_block_t
*blockptr
)
396 rb_control_frame_t
*cfp
= th
->cfp
;
400 /* control block frame */
401 (cfp
-2)->method_id
= id
;
402 (cfp
-2)->method_class
= klass
;
404 GetProcPtr(procval
, proc
);
405 val
= vm_invoke_proc(th
, proc
, recv
, argc
, argv
, blockptr
);
410 vm_method_missing(rb_thread_t
*th
, ID id
, VALUE recv
, int num
,
411 rb_block_t
*blockptr
, int opt
)
413 rb_control_frame_t
*reg_cfp
= th
->cfp
;
414 VALUE
*argv
= STACK_ADDR_FROM_TOP(num
+ 1);
416 argv
[0] = ID2SYM(id
);
417 th
->method_missing_reason
= opt
;
418 th
->passed_block
= blockptr
;
419 val
= rb_funcall2(recv
, idMethodMissing
, num
+ 1, argv
);
425 vm_setup_method(rb_thread_t
*th
, rb_control_frame_t
*cfp
,
426 int argc
, rb_block_t
*blockptr
, VALUE flag
,
427 VALUE iseqval
, VALUE recv
, VALUE klass
)
431 VALUE
*sp
, *rsp
= cfp
->sp
- argc
;
433 /* TODO: eliminate it */
434 GetISeqPtr(iseqval
, iseq
);
435 opt_pc
= vm_callee_setup_arg(th
, iseq
, argc
, rsp
, &blockptr
);
437 /* stack overflow check */
438 CHECK_STACK_OVERFLOW(cfp
, iseq
->stack_max
);
440 sp
= rsp
+ iseq
->arg_size
;
442 if (LIKELY(!(flag
& VM_CALL_TAILCALL_BIT
))) {
443 if (0) printf("local_size: %d, arg_size: %d\n",
444 iseq
->local_size
, iseq
->arg_size
);
446 /* clear local variables */
447 for (i
= 0; i
< iseq
->local_size
- iseq
->arg_size
; i
++) {
451 vm_push_frame(th
, iseq
,
452 FRAME_MAGIC_METHOD
, recv
, (VALUE
) blockptr
,
453 iseq
->iseq_encoded
+ opt_pc
, sp
, 0, 0);
455 cfp
->sp
= rsp
- 1 /* recv */;
459 cfp
= ++th
->cfp
; /* pop cf */
463 for (i
=0; i
< (sp
- rsp
); i
++) {
469 /* clear local variables */
470 for (i
= 0; i
< iseq
->local_size
- iseq
->arg_size
; i
++) {
474 vm_push_frame(th
, iseq
,
475 FRAME_MAGIC_METHOD
, recv
, (VALUE
) blockptr
,
476 iseq
->iseq_encoded
+ opt_pc
, sp
, 0, 0);
481 vm_call_method(rb_thread_t
*th
, rb_control_frame_t
*cfp
,
482 int num
, rb_block_t
*blockptr
, VALUE flag
,
483 ID id
, NODE
*mn
, VALUE recv
, VALUE klass
)
487 start_method_dispatch
:
490 if ((mn
->nd_noex
== 0)) {
491 /* dispatch method */
494 normal_method_dispatch
:
498 switch (nd_type(node
)) {
499 case RUBY_VM_METHOD_NODE
:{
500 vm_setup_method(th
, cfp
, num
, blockptr
, flag
, (VALUE
)node
->nd_body
, recv
, klass
);
504 val
= vm_call_cfunc(th
, cfp
, num
, id
, recv
, mn
->nd_clss
, flag
, node
, blockptr
);
508 val
= rb_ivar_set(recv
, node
->nd_vid
, *(cfp
->sp
- 1));
514 rb_raise(rb_eArgError
, "wrong number of arguments (%d for 0)",
517 val
= rb_attr_get(recv
, node
->nd_vid
);
522 VALUE
*argv
= cfp
->sp
- num
;
523 val
= vm_call_bmethod(th
, id
, node
->nd_cval
, recv
, klass
, num
, argv
, blockptr
);
524 cfp
->sp
+= - num
- 1;
528 klass
= RCLASS_SUPER(mn
->nd_clss
);
529 mn
= rb_method_node(klass
, id
);
532 goto normal_method_dispatch
;
535 goto start_method_dispatch
;
539 printf("node: %s\n", ruby_node_name(nd_type(node
)));
540 rb_bug("eval_invoke_method: unreachable");
549 if (!(flag
& VM_CALL_FCALL_BIT
) &&
550 (mn
->nd_noex
& NOEX_MASK
) & NOEX_PRIVATE
) {
551 int stat
= NOEX_PRIVATE
;
553 if (flag
& VM_CALL_VCALL_BIT
) {
556 val
= vm_method_missing(th
, id
, recv
, num
, blockptr
, stat
);
558 else if (((mn
->nd_noex
& NOEX_MASK
) & NOEX_PROTECTED
) &&
559 !(flag
& VM_CALL_SEND_BIT
)) {
560 VALUE defined_class
= mn
->nd_clss
;
562 if (TYPE(defined_class
) == T_ICLASS
) {
563 defined_class
= RBASIC(defined_class
)->klass
;
566 if (!rb_obj_is_kind_of(cfp
->self
, rb_class_real(defined_class
))) {
567 val
= vm_method_missing(th
, id
, recv
, num
, blockptr
, NOEX_PROTECTED
);
570 goto normal_method_dispatch
;
573 else if ((noex_safe
= NOEX_SAFE(mn
->nd_noex
)) > th
->safe_level
&&
575 rb_raise(rb_eSecurityError
, "calling insecure method: %s", rb_id2name(id
));
578 goto normal_method_dispatch
;
584 if (id
== idMethodMissing
) {
585 rb_bug("method missing");
589 if (flag
& VM_CALL_VCALL_BIT
) {
592 if (flag
& VM_CALL_SUPER_BIT
) {
595 val
= vm_method_missing(th
, id
, recv
, num
, blockptr
, stat
);
599 RUBY_VM_CHECK_INTS();
604 vm_send_optimize(rb_control_frame_t
*reg_cfp
,
605 NODE
**mn
, rb_num_t
*flag
, rb_num_t
*num
, ID
*id
, VALUE klass
)
607 if (*mn
&& nd_type((*mn
)->nd_body
) == NODE_CFUNC
) {
608 NODE
*node
= (*mn
)->nd_body
;
609 extern VALUE
rb_f_send(int argc
, VALUE
*argv
, VALUE recv
);
611 if (node
->nd_cfnc
== rb_f_send
) {
614 *id
= SYMBOL_P(sym
) ? SYM2ID(sym
) : rb_to_id(sym
);
616 /* shift arguments */
618 MEMMOVE(&TOPN(i
), &TOPN(i
-1), VALUE
, i
);
621 *mn
= rb_method_node(klass
, *id
);
624 *flag
|= VM_CALL_FCALL_BIT
;
632 block_proc_is_lambda(VALUE procval
)
637 GetProcPtr(procval
, proc
);
638 return proc
->is_lambda
;
646 vm_yield_with_cfunc(rb_thread_t
*th
, rb_block_t
*block
,
647 VALUE self
, int argc
, VALUE
*argv
)
649 NODE
*ifunc
= (NODE
*) block
->iseq
;
652 int lambda
= block_proc_is_lambda(block
->proc
);
655 arg
= rb_ary_new4(argc
, argv
);
657 else if (argc
== 0) {
664 vm_push_frame(th
, 0, FRAME_MAGIC_IFUNC
,
665 self
, (VALUE
)block
->dfp
,
666 0, th
->cfp
->sp
, block
->lfp
, 1);
668 val
= (*ifunc
->nd_cfnc
) (arg
, ifunc
->nd_tval
, argc
, argv
);
675 vm_yield_setup_args(rb_thread_t
*th
, rb_iseq_t
*iseq
,
676 int argc
, VALUE
*argv
, rb_block_t
*blockptr
, int lambda
)
678 if (0) { /* for debug */
679 printf(" argc: %d\n", argc
);
680 printf("iseq argc: %d\n", iseq
->argc
);
681 printf("iseq opts: %d\n", iseq
->arg_opts
);
682 printf("iseq rest: %d\n", iseq
->arg_rest
);
683 printf("iseq post: %d\n", iseq
->arg_post_len
);
684 printf("iseq blck: %d\n", iseq
->arg_block
);
685 printf("iseq smpl: %d\n", iseq
->arg_simple
);
686 printf(" lambda: %s\n", lambda
? "true" : "false");
691 return vm_callee_setup_arg(th
, iseq
, argc
, argv
, &blockptr
);
695 const int m
= iseq
->argc
;
697 th
->mark_stack_len
= argc
;
701 * => {|a|} => a = [1, 2]
702 * => {|a, b|} => a, b = [1, 2]
704 if (!(iseq
->arg_simple
& 0x02) &&
705 (m
+ iseq
->arg_post_len
) > 0 &&
706 argc
== 1 && TYPE(argv
[0]) == T_ARRAY
) {
708 th
->mark_stack_len
= argc
= RARRAY_LEN(ary
);
710 CHECK_STACK_OVERFLOW(th
->cfp
, argc
);
712 MEMCPY(argv
, RARRAY_PTR(ary
), VALUE
, argc
);
715 for (i
=argc
; i
<m
; i
++) {
719 if (iseq
->arg_rest
== -1) {
723 * => {|a|} # truncate
725 th
->mark_stack_len
= argc
= m
;
729 int r
= iseq
->arg_rest
;
731 if (iseq
->arg_post_len
) {
732 int len
= iseq
->arg_post_len
;
733 int start
= iseq
->arg_post_start
;
734 int rsize
= argc
> m
? argc
- m
: 0;
738 if (psize
> len
) psize
= len
;
740 ary
= rb_ary_new4(rsize
- psize
, &argv
[r
]);
743 printf(" argc: %d\n", argc
);
744 printf(" len: %d\n", len
);
745 printf("start: %d\n", start
);
746 printf("rsize: %d\n", rsize
);
749 /* copy post argument */
750 MEMMOVE(&argv
[start
], &argv
[r
+ rsize
- psize
], VALUE
, psize
);
752 for (i
=psize
; i
<len
; i
++) {
753 argv
[start
+ i
] = Qnil
;
762 for (i
=argc
; i
<r
; i
++) {
765 argv
[r
] = rb_ary_new();
768 argv
[r
] = rb_ary_new4(argc
-r
, &argv
[r
]);
772 th
->mark_stack_len
= iseq
->arg_size
;
776 if (iseq
->arg_block
!= -1) {
777 VALUE procval
= Qnil
;
780 procval
= blockptr
->proc
;
783 argv
[iseq
->arg_block
] = procval
;
786 th
->mark_stack_len
= 0;
792 vm_invoke_block(rb_thread_t
*th
, rb_control_frame_t
*reg_cfp
, rb_num_t num
, rb_num_t flag
)
795 rb_block_t
*block
= GET_BLOCK_PTR();
799 if (GET_ISEQ()->local_iseq
->type
!= ISEQ_TYPE_METHOD
|| block
== 0) {
800 vm_localjump_error("no block given (yield)", Qnil
, 0);
804 argc
= caller_setup_args(th
, GET_CFP(), flag
, argc
, 0, 0);
806 if (BUILTIN_TYPE(iseq
) != T_NODE
) {
808 const int arg_size
= iseq
->arg_size
;
809 VALUE
*rsp
= GET_SP() - argc
;
812 CHECK_STACK_OVERFLOW(GET_CFP(), iseq
->stack_max
);
813 opt_pc
= vm_yield_setup_args(th
, iseq
, argc
, rsp
, 0,
814 block_proc_is_lambda(block
->proc
));
816 vm_push_frame(th
, iseq
,
817 FRAME_MAGIC_BLOCK
, block
->self
, (VALUE
) block
->dfp
,
818 iseq
->iseq_encoded
+ opt_pc
, rsp
+ arg_size
, block
->lfp
,
819 iseq
->local_size
- arg_size
);
824 val
= vm_yield_with_cfunc(th
, block
, block
->self
, argc
, STACK_ADDR_FROM_TOP(argc
));
825 POPN(argc
); /* TODO: should put before C/yield? */
833 lfp_get_special_cref(VALUE
*lfp
)
835 struct RValues
*values
;
836 if (((VALUE
)(values
= (void *)lfp
[-1])) != Qnil
&& values
->basic
.klass
) {
837 return (NODE
*)values
->basic
.klass
;
844 static struct RValues
*
847 struct RValues
*val
= RVALUES(rb_newobj());
848 OBJSETUP(val
, 0, T_VALUES
);
849 val
->v1
= val
->v2
= val
->v3
= Qnil
;
853 static struct RValues
*
854 lfp_svar_place(rb_thread_t
*th
, VALUE
*lfp
)
856 struct RValues
*svar
;
858 if (th
->local_lfp
!= lfp
) {
859 svar
= (struct RValues
*)lfp
[-1];
860 if ((VALUE
)svar
== Qnil
) {
862 lfp
[-1] = (VALUE
)svar
;
866 svar
= (struct RValues
*)th
->local_svar
;
867 if ((VALUE
)svar
== Qnil
) {
869 th
->local_svar
= (VALUE
)svar
;
876 lfp_svar_get(rb_thread_t
*th
, VALUE
*lfp
, VALUE key
)
878 struct RValues
*svar
= lfp_svar_place(th
, lfp
);
886 return svar
->basic
.klass
;
888 VALUE hash
= svar
->v3
;
894 return rb_hash_lookup(hash
, key
);
901 lfp_svar_set(rb_thread_t
*th
, VALUE
*lfp
, VALUE key
, VALUE val
)
903 struct RValues
*svar
= lfp_svar_place(th
, lfp
);
913 svar
->basic
.klass
= val
;
916 VALUE hash
= svar
->v3
;
919 svar
->v3
= hash
= rb_hash_new();
921 rb_hash_aset(hash
, key
, val
);
927 get_cref(rb_iseq_t
*iseq
, VALUE
*lfp
)
930 if ((cref
= lfp_get_special_cref(lfp
)) != 0) {
933 else if ((cref
= iseq
->cref_stack
) != 0) {
937 rb_bug("get_cref: unreachable");
943 vm_getspecial(rb_thread_t
*th
, VALUE
*lfp
, VALUE key
, rb_num_t type
)
948 if (FIXNUM_P(key
)) key
= FIX2INT(key
);
949 val
= lfp_svar_get(th
, lfp
, key
);
952 VALUE backref
= lfp_svar_get(th
, lfp
, 1);
957 val
= rb_reg_last_match(backref
);
960 val
= rb_reg_match_pre(backref
);
963 val
= rb_reg_match_post(backref
);
966 val
= rb_reg_match_last(backref
);
969 rb_bug("unexpected back-ref");
973 val
= rb_reg_nth_match(type
>> 1, backref
);
980 vm_check_if_namespace(VALUE klass
)
982 switch (TYPE(klass
)) {
987 rb_raise(rb_eTypeError
, "%s is not a class/module",
988 RSTRING_PTR(rb_obj_as_string(klass
)));
993 vm_get_ev_const(rb_thread_t
*th
, rb_iseq_t
*iseq
,
994 VALUE klass
, ID id
, int is_defined
)
999 /* in current lexical scope */
1000 NODE
*root_cref
= get_cref(iseq
, th
->cfp
->lfp
);
1001 NODE
*cref
= root_cref
;
1003 while (cref
&& cref
->nd_next
) {
1004 klass
= cref
->nd_clss
;
1005 cref
= cref
->nd_next
;
1016 klass
= CLASS_OF(th
->cfp
->self
);
1017 return rb_const_get(klass
, id
);
1021 if (RCLASS_IV_TBL(klass
) &&
1022 st_lookup(RCLASS_IV_TBL(klass
), id
, &val
)) {
1023 if (val
== Qundef
) {
1024 rb_autoload_load(klass
, id
);
1025 goto search_continue
;
1037 klass
= root_cref
->nd_clss
;
1039 return rb_const_defined(klass
, id
);
1042 return rb_const_get(klass
, id
);
1046 vm_check_if_namespace(klass
);
1048 return rb_const_defined_from(klass
, id
);
1051 return rb_const_get_from(klass
, id
);
1057 vm_get_cvar_base(rb_thread_t
*th
, rb_iseq_t
*iseq
)
1059 NODE
*cref
= get_cref(iseq
, th
->cfp
->lfp
);
1063 klass
= cref
->nd_clss
;
1064 if (!cref
->nd_next
) {
1065 rb_warn("class variable access from toplevel");
1069 rb_raise(rb_eTypeError
, "no class variables available");
1075 vm_define_method(rb_thread_t
*th
, VALUE obj
,
1076 ID id
, rb_iseq_t
*miseq
, rb_num_t is_singleton
, NODE
*cref
)
1079 int noex
= cref
->nd_visi
;
1080 VALUE klass
= cref
->nd_clss
;
1083 if (FIXNUM_P(obj
) || SYMBOL_P(obj
)) {
1084 rb_raise(rb_eTypeError
,
1085 "can't define singleton method \"%s\" for %s",
1086 rb_id2name(id
), rb_obj_classname(obj
));
1089 if (OBJ_FROZEN(obj
)) {
1090 rb_error_frozen("object");
1093 klass
= rb_singleton_class(obj
);
1098 COPY_CREF(miseq
->cref_stack
, cref
);
1099 miseq
->klass
= klass
;
1100 miseq
->defined_method_id
= id
;
1101 newbody
= NEW_NODE(RUBY_VM_METHOD_NODE
, 0, miseq
->self
, 0);
1102 rb_add_method(klass
, id
, newbody
, noex
);
1104 if (!is_singleton
&& noex
== NOEX_MODFUNC
) {
1105 rb_add_method(rb_singleton_class(klass
), id
, newbody
, NOEX_PUBLIC
);
1107 INC_VM_STATE_VERSION();
1110 static inline NODE
*
1111 vm_method_search(VALUE id
, VALUE klass
, IC ic
)
1115 #if OPT_INLINE_METHOD_CACHE
1117 if (LIKELY(klass
== ic
->ic_class
) &&
1118 LIKELY(GET_VM_STATE_VERSION() == ic
->ic_vmstat
)) {
1122 mn
= rb_method_node(klass
, id
);
1123 ic
->ic_class
= klass
;
1125 ic
->ic_vmstat
= GET_VM_STATE_VERSION();
1129 mn
= rb_method_node(klass
, id
);
1135 vm_search_normal_superclass(VALUE klass
, VALUE recv
)
1137 if (BUILTIN_TYPE(klass
) == T_CLASS
) {
1138 klass
= RCLASS_SUPER(klass
);
1140 else if (BUILTIN_TYPE(klass
) == T_MODULE
) {
1141 VALUE k
= CLASS_OF(recv
);
1143 if (BUILTIN_TYPE(k
) == T_ICLASS
&& RBASIC(k
)->klass
== klass
) {
1144 klass
= RCLASS_SUPER(k
);
1147 k
= RCLASS_SUPER(k
);
1154 vm_search_superclass(rb_control_frame_t
*reg_cfp
, rb_iseq_t
*ip
, VALUE recv
, VALUE sigval
, ID
*idp
, VALUE
*klassp
)
1159 while (ip
&& !ip
->klass
) {
1160 ip
= ip
->parent_iseq
;
1164 rb_raise(rb_eNoMethodError
, "super called outside of method");
1167 id
= ip
->defined_method_id
;
1169 if (ip
!= ip
->local_iseq
) {
1170 /* defined by Module#define_method() */
1171 rb_control_frame_t
*lcfp
= GET_CFP();
1173 while (lcfp
->iseq
!= ip
) {
1174 VALUE
*tdfp
= GET_PREV_DFP(lcfp
->dfp
);
1176 lcfp
= RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp
);
1177 if (lcfp
->dfp
== tdfp
) {
1183 id
= lcfp
->method_id
;
1184 klass
= vm_search_normal_superclass(lcfp
->method_class
, recv
);
1186 if (sigval
== Qfalse
) {
1188 rb_raise(rb_eRuntimeError
, "implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly.");
1192 klass
= vm_search_normal_superclass(ip
->klass
, recv
);
1200 vm_throw(rb_thread_t
*th
, rb_control_frame_t
*reg_cfp
, rb_num_t throw_state
, VALUE throwobj
)
1202 rb_num_t state
= throw_state
& 0xff;
1203 rb_num_t flag
= throw_state
& 0x8000;
1204 rb_num_t level
= throw_state
>> 16;
1210 if (throw_state
& 0x4000) {
1218 if (state
== TAG_BREAK
) {
1219 rb_control_frame_t
*cfp
= GET_CFP();
1220 VALUE
*dfp
= GET_DFP();
1222 rb_iseq_t
*base_iseq
= GET_ISEQ();
1225 if (cfp
->iseq
->type
!= ISEQ_TYPE_BLOCK
) {
1226 dfp
= GC_GUARDED_PTR_REF((VALUE
*) *dfp
);
1227 base_iseq
= base_iseq
->parent_iseq
;
1229 while ((VALUE
*) cfp
< th
->stack
+ th
->stack_size
) {
1230 if (cfp
->dfp
== dfp
) {
1235 rb_bug("VM (throw): can't find break base.");
1238 if (VM_FRAME_TYPE(cfp
) == FRAME_MAGIC_LAMBDA
) {
1239 /* lambda{... break ...} */
1244 dfp
= GC_GUARDED_PTR_REF((VALUE
*) *dfp
);
1246 while ((VALUE
*)cfp
< th
->stack
+ th
->stack_size
) {
1247 if (cfp
->dfp
== dfp
) {
1248 VALUE epc
= epc
= cfp
->pc
- cfp
->iseq
->iseq_encoded
;
1249 rb_iseq_t
*iseq
= cfp
->iseq
;
1252 for (i
=0; i
<iseq
->catch_table_size
; i
++) {
1253 struct iseq_catch_table_entry
*entry
= &iseq
->catch_table
[i
];
1255 if (entry
->type
== CATCH_TYPE_BREAK
&&
1256 entry
->start
< epc
&& entry
->end
>= epc
) {
1257 if (entry
->cont
== epc
) {
1277 vm_localjump_error("break from proc-closure", throwobj
, TAG_BREAK
);
1280 else if (state
== TAG_RETRY
) {
1281 pt
= GC_GUARDED_PTR_REF((VALUE
*) * GET_DFP());
1282 for (i
= 0; i
< level
; i
++) {
1283 pt
= GC_GUARDED_PTR_REF((VALUE
*) * pt
);
1286 else if (state
== TAG_RETURN
) {
1287 rb_control_frame_t
*cfp
= GET_CFP();
1288 VALUE
*dfp
= GET_DFP();
1294 while ((VALUE
*) cfp
< th
->stack
+ th
->stack_size
) {
1295 if (GET_DFP() == dfp
) {
1296 if (VM_FRAME_TYPE(cfp
) == FRAME_MAGIC_LAMBDA
) {
1302 if (GET_LFP() == cfp
->lfp
&&
1303 cfp
->iseq
->type
== ISEQ_TYPE_METHOD
) {
1311 vm_localjump_error("unexpected return", throwobj
, TAG_RETURN
);
1317 rb_bug("isns(throw): unsupport throw type");
1321 return (VALUE
)NEW_THROW_OBJECT(throwobj
, (VALUE
) pt
, state
);
1324 /* continue throw */
1325 VALUE err
= throwobj
;
1327 if (FIXNUM_P(err
)) {
1328 th
->state
= FIX2INT(err
);
1330 else if (SYMBOL_P(err
)) {
1331 th
->state
= TAG_THROW
;
1333 else if (BUILTIN_TYPE(err
) == T_NODE
) {
1334 th
->state
= GET_THROWOBJ_STATE(err
);
1337 th
->state
= TAG_RAISE
;
1338 /*th->state = FIX2INT(rb_ivar_get(err, idThrowState));*/
1345 vm_expandarray(rb_control_frame_t
*cfp
, VALUE ary
, int num
, int flag
)
1347 int is_splat
= flag
& 0x01;
1348 int space_size
= num
+ is_splat
;
1349 VALUE
*base
= cfp
->sp
, *ptr
;
1350 volatile VALUE tmp_ary
;
1353 if (TYPE(ary
) != T_ARRAY
) {
1354 ary
= rb_ary_to_ary(ary
);
1357 cfp
->sp
+= space_size
;
1360 ptr
= RARRAY_PTR(ary
);
1361 len
= RARRAY_LEN(ary
);
1364 /* post: ..., nil ,ary[-1], ..., ary[0..-num] # top */
1368 for (i
=0; i
<num
-len
; i
++) {
1372 for (j
=0; i
<num
; i
++, j
++) {
1373 VALUE v
= ptr
[len
- j
- 1];
1377 *base
= rb_ary_new4(len
- j
, ptr
);
1381 /* normal: ary[num..-1], ary[num-2], ary[num-3], ..., ary[0] # top */
1383 VALUE
*bptr
= &base
[space_size
- 1];
1385 for (i
=0; i
<num
; i
++) {
1387 for (; i
<num
; i
++) {
1396 *bptr
= rb_ary_new();
1399 *bptr
= rb_ary_new4(len
- num
, ptr
+ num
);
1406 check_cfunc(NODE
*mn
, void *func
)
1408 if (mn
&& nd_type(mn
->nd_body
) == NODE_CFUNC
&&
1409 mn
->nd_body
->nd_cfnc
== func
) {
1418 opt_eq_func(VALUE recv
, VALUE obj
, IC ic
)
1422 if (FIXNUM_2_P(recv
, obj
) &&
1423 BASIC_OP_UNREDEFINED_P(BOP_EQ
)) {
1424 long a
= FIX2LONG(recv
), b
= FIX2LONG(obj
);
1433 else if (!SPECIAL_CONST_P(recv
) && !SPECIAL_CONST_P(obj
)) {
1434 if (HEAP_CLASS_OF(recv
) == rb_cFloat
&&
1435 HEAP_CLASS_OF(obj
) == rb_cFloat
&&
1436 BASIC_OP_UNREDEFINED_P(BOP_EQ
)) {
1437 double a
= RFLOAT_VALUE(recv
);
1438 double b
= RFLOAT_VALUE(obj
);
1440 if (isnan(a
) || isnan(b
)) {
1450 else if (HEAP_CLASS_OF(recv
) == rb_cString
&&
1451 HEAP_CLASS_OF(obj
) == rb_cString
&&
1452 BASIC_OP_UNREDEFINED_P(BOP_EQ
)) {
1453 val
= rb_str_equal(recv
, obj
);
1456 NODE
*mn
= vm_method_search(idEq
, CLASS_OF(recv
), ic
);
1457 extern VALUE
rb_obj_equal(VALUE obj1
, VALUE obj2
);
1459 if (check_cfunc(mn
, rb_obj_equal
)) {
1460 return recv
== obj
? Qtrue
: Qfalse
;