summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-09-28 04:05:36 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-09-28 04:05:36 +0000
commitd50483df23383caf098c23c25c133f4eefca5917 (patch)
treed2e94e5ec61e548687a0b67d06a0662063650a31 /vm_insnhelper.c
parent8124d67988ea5aa995f1721446c229a83a8b356d (diff)
* vm_core.h: remove rb_control_frame_t::bp (bp: base pointer).
`bp' can be calculate by `sp' (stack pointer) of previous frame. Now, `bp_check' field is remained for debug. You can eliminate this field by setting VM_DEBUG_BP_CHECK as 0. * vm_insnhelper.c (vm_base_ptr): add `vm_base_ptr(cfp). This function calculates base pointer from cfp. * vm_insnhelper.c (vm_setup_method): push `recv' value on top of value stack (before method parameters). This change is for keeping consistency with normal method dispatch. * insns.def: fix to use vm_base_ptr(). * vm.c (vm_exec): ditto. * vm_dump.c: remove `bp' related dumps. * cont.c (fiber_init): fix to check VM_DEBUG_BP_CHECK. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37043 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c63
1 files changed, 46 insertions, 17 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 46ef7e1a1c..808d73cb9f 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -57,7 +57,9 @@ vm_push_frame(rb_thread_t *th,
cfp->pc = (VALUE *)pc;
cfp->sp = sp + 1;
- cfp->bp = sp + 1;
+#if VM_DEBUG_BP_CHECK
+ cfp->bp_check = sp + 1;
+#endif
cfp->ep = sp;
cfp->iseq = (rb_iseq_t *) iseq;
cfp->flag = type;
@@ -494,19 +496,16 @@ vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
const rb_method_entry_t *me, VALUE defined_class)
{
int opt_pc, i;
- VALUE *sp, *rsp = cfp->sp - argc;
+ VALUE *sp, *argv = cfp->sp - argc;
rb_iseq_t *iseq = me->def->body.iseq;
- VM_CALLEE_SETUP_ARG(opt_pc, th, iseq, argc, rsp, &blockptr);
+ VM_CALLEE_SETUP_ARG(opt_pc, th, iseq, argc, argv, &blockptr);
/* stack overflow check */
CHECK_STACK_OVERFLOW(cfp, iseq->stack_max);
-
- sp = rsp + iseq->arg_size;
+ sp = argv + iseq->arg_size;
if (LIKELY(!(flag & VM_CALL_TAILCALL_BIT))) {
- if (0) printf("local_size: %d, arg_size: %d\n",
- iseq->local_size, iseq->arg_size);
/* clear local variables */
for (i = 0; i < iseq->local_size - iseq->arg_size; i++) {
@@ -517,30 +516,36 @@ vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
VM_ENVVAL_BLOCK_PTR(blockptr),
iseq->iseq_encoded + opt_pc, sp, 0, me);
- cfp->sp = rsp - 1 /* recv */;
+ cfp->sp = argv - 1 /* recv */;
}
else {
- VALUE *p_rsp;
- int is_finish_frame = VM_FRAME_TYPE_FINISH_P(cfp);
+ VALUE *src_argv = argv;
+ VALUE *sp_orig;
+ int src_argc = sp - src_argv;
+ VALUE finish_flag = VM_FRAME_TYPE_FINISH_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
+ cfp = th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); /* pop cf */
- th->cfp++; /* pop cf */
- p_rsp = th->cfp->sp;
+ sp = sp_orig = cfp->sp;
+
+ /* push self */
+ sp[0] = recv;
+ sp++;
/* copy arguments */
- for (i=0; i < (sp - rsp); i++) {
- p_rsp[i] = rsp[i];
+ for (i=0; i < src_argc; i++) {
+ *sp++ = src_argv[i];
}
- sp -= rsp - p_rsp;
-
/* clear local variables */
for (i = 0; i < iseq->local_size - iseq->arg_size; i++) {
*sp++ = Qnil;
}
- vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | (is_finish_frame ? VM_FRAME_FLAG_FINISH : 0),
+ vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag,
recv, defined_class, VM_ENVVAL_BLOCK_PTR(blockptr),
iseq->iseq_encoded + opt_pc, sp, 0, me);
+
+ cfp->sp = sp_orig;
}
}
@@ -1902,3 +1907,27 @@ double_cmp_ge(double a, double b)
CHECK_CMP_NAN(a, b);
return a >= b ? Qtrue : Qfalse;
}
+
+static VALUE *
+vm_base_ptr(rb_control_frame_t *cfp)
+{
+ rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+ VALUE *bp = prev_cfp->sp + cfp->iseq->local_size + 1;
+
+ if (cfp->iseq->type == ISEQ_TYPE_METHOD) {
+ /* adjust `self' */
+ bp += 1;
+ }
+
+#if VM_DEBUG_BP_CHECK
+ if (bp != cfp->bp_check) {
+ fprintf(stderr, "bp_check: %d, bp: %d\n",
+ cfp->bp_check - GET_THREAD()->stack,
+ bp - GET_THREAD()->stack);
+ rb_bug("vm_base_ptr: unreachable");
+ }
+#endif
+
+ return bp;
+}
+