mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* vm_core.h: remove lfp (local frame pointer) and rename
dfp (dynamic frame pointer) to ep (environment pointer). This change make VM `normal' (similar to other interpreters). Before this commit: Each frame has two env pointers lfp and dfp. lfp points local environment which is method/class/toplevel frame. lfp[0] is block pointer. dfp is block local frame. dfp[0] points previous (parent) environment pointer. lfp == dfp when frame is method/class/toplevel. You can get lfp from dfp by traversing previous environment pointers. After this commit: Each frame has only `ep' to point respective enviornoment. If there is parent environment, then ep[0] points parent envioenment (as dfp). If there are no more environment, then ep[0] points block pointer (as lfp). We call such ep as `LEP' (local EP). We add some macros to get LEP and to detect LEP or not. In short, we replace dfp and lfp with ep and LEP. rb_block_t and rb_binding_t member `lfp' and `dfp' are removed and member `ep' is added. rename rb_thread_t's member `local_lfp' and `local_svar' to `root_lep' and `root_svar'. (VM_EP_PREV_EP(ep)): get previous environment pointer. This macro assume that ep is not LEP. (VM_EP_BLOCK_PTR(ep)): get block pointer. This macro assume that ep is LEP. (VM_EP_LEP_P(ep)): detect ep is LEP or not. (VM_ENVVAL_BLOCK_PTR(ptr)): make block pointer. (VM_ENVVAL_BLOCK_PTR_P(v)): detect v is block pointer. (VM_ENVVAL_PREV_EP_PTR(ptr)): make prev environment pointer. (VM_ENVVAL_PREV_EP_PTR_P(v)): detect v is prev env pointer. * vm.c: apply above changes. (VM_EP_LEP(ep)): get LEP. (VM_CF_LEP(cfp)): get LEP of cfp->ep. (VM_CF_PREV_EP(cfp)): utility function VM_EP_PREV_EP(cfp->ep). (VM_CF_BLOCK_PTR(cfp)): utility function VM_EP_BLOCK_PTR(cfp->ep). * vm.c, vm_eval.c, vm_insnhelper.c, vm_insnhelper.h, insns.def: apply above changes. * cont.c: ditto. * eval.c, eval_intern.h: ditto. * proc.c: ditto. * thread.c: ditto. * vm_dump.c: ditto. * vm_exec.h: fix function name (on vm debug mode). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
9b29e5f7e1
commit
0a71db8a74
14 changed files with 415 additions and 336 deletions
57
ChangeLog
57
ChangeLog
|
@ -1,3 +1,60 @@
|
|||
Mon Jun 11 12:14:37 2012 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* vm_core.h: remove lfp (local frame pointer) and rename
|
||||
dfp (dynamic frame pointer) to ep (environment pointer).
|
||||
This change make VM `normal' (similar to other interpreters).
|
||||
Before this commit:
|
||||
Each frame has two env pointers lfp and dfp. lfp points
|
||||
local environment which is method/class/toplevel frame.
|
||||
lfp[0] is block pointer.
|
||||
dfp is block local frame. dfp[0] points previous (parent)
|
||||
environment pointer.
|
||||
lfp == dfp when frame is method/class/toplevel.
|
||||
You can get lfp from dfp by traversing previous environment
|
||||
pointers.
|
||||
After this commit:
|
||||
Each frame has only `ep' to point respective enviornoment.
|
||||
If there is parent environment, then ep[0] points parent
|
||||
envioenment (as dfp). If there are no more environment,
|
||||
then ep[0] points block pointer (as lfp). We call such ep
|
||||
as `LEP' (local EP). We add some macros to get LEP and to
|
||||
detect LEP or not.
|
||||
In short, we replace dfp and lfp with ep and LEP.
|
||||
rb_block_t and rb_binding_t member `lfp' and `dfp' are removed
|
||||
and member `ep' is added.
|
||||
rename rb_thread_t's member `local_lfp' and `local_svar' to
|
||||
`root_lep' and `root_svar'.
|
||||
(VM_EP_PREV_EP(ep)): get previous environment pointer. This macro
|
||||
assume that ep is not LEP.
|
||||
(VM_EP_BLOCK_PTR(ep)): get block pointer. This macro assume
|
||||
that ep is LEP.
|
||||
(VM_EP_LEP_P(ep)): detect ep is LEP or not.
|
||||
(VM_ENVVAL_BLOCK_PTR(ptr)): make block pointer.
|
||||
(VM_ENVVAL_BLOCK_PTR_P(v)): detect v is block pointer.
|
||||
(VM_ENVVAL_PREV_EP_PTR(ptr)): make prev environment pointer.
|
||||
(VM_ENVVAL_PREV_EP_PTR_P(v)): detect v is prev env pointer.
|
||||
|
||||
* vm.c: apply above changes.
|
||||
(VM_EP_LEP(ep)): get LEP.
|
||||
(VM_CF_LEP(cfp)): get LEP of cfp->ep.
|
||||
(VM_CF_PREV_EP(cfp)): utility function VM_EP_PREV_EP(cfp->ep).
|
||||
(VM_CF_BLOCK_PTR(cfp)): utility function VM_EP_BLOCK_PTR(cfp->ep).
|
||||
|
||||
* vm.c, vm_eval.c, vm_insnhelper.c, vm_insnhelper.h, insns.def:
|
||||
apply above changes.
|
||||
|
||||
* cont.c: ditto.
|
||||
|
||||
* eval.c, eval_intern.h: ditto.
|
||||
|
||||
* proc.c: ditto.
|
||||
|
||||
* thread.c: ditto.
|
||||
|
||||
* vm_dump.c: ditto.
|
||||
|
||||
* vm_exec.h: fix function name (on vm debug mode).
|
||||
|
||||
Mon Jun 11 11:52:18 2012 URABE Shyouhei <shyouhei@ruby-lang.org>
|
||||
|
||||
* compile.c (iseq_set_sequence): nonstatic initializer of an
|
||||
|
|
9
cont.c
9
cont.c
|
@ -1059,9 +1059,8 @@ fiber_init(VALUE fibval, VALUE proc)
|
|||
th->cfp->pc = 0;
|
||||
th->cfp->sp = th->stack + 1;
|
||||
th->cfp->bp = 0;
|
||||
th->cfp->lfp = th->stack;
|
||||
*th->cfp->lfp = 0;
|
||||
th->cfp->dfp = th->stack;
|
||||
th->cfp->ep = th->stack;
|
||||
*th->cfp->ep = VM_ENVVAL_BLOCK_PTR(0);
|
||||
th->cfp->self = Qnil;
|
||||
th->cfp->flag = 0;
|
||||
th->cfp->iseq = 0;
|
||||
|
@ -1155,8 +1154,8 @@ rb_fiber_start(void)
|
|||
argv = (argc = cont->argc) > 1 ? RARRAY_PTR(args) : &args;
|
||||
cont->value = Qnil;
|
||||
th->errinfo = Qnil;
|
||||
th->local_lfp = proc->block.lfp;
|
||||
th->local_svar = Qnil;
|
||||
th->root_lep = rb_vm_ep_local_ep(proc->block.ep);
|
||||
th->root_svar = Qnil;
|
||||
|
||||
fib->status = RUNNING;
|
||||
cont->value = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, 0);
|
||||
|
|
10
eval.c
10
eval.c
|
@ -604,7 +604,7 @@ rb_block_given_p(void)
|
|||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
|
||||
if (RUBY_VM_GET_BLOCK_PTR(th->cfp)) {
|
||||
if (rb_vm_control_frame_block_ptr(th->cfp)) {
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
|
@ -1054,12 +1054,12 @@ errinfo_place(rb_thread_t *th)
|
|||
while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
|
||||
if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
||||
if (cfp->iseq->type == ISEQ_TYPE_RESCUE) {
|
||||
return &cfp->dfp[-2];
|
||||
return &cfp->ep[-2];
|
||||
}
|
||||
else if (cfp->iseq->type == ISEQ_TYPE_ENSURE &&
|
||||
!RB_TYPE_P(cfp->dfp[-2], T_NODE) &&
|
||||
!FIXNUM_P(cfp->dfp[-2])) {
|
||||
return &cfp->dfp[-2];
|
||||
!RB_TYPE_P(cfp->ep[-2], T_NODE) &&
|
||||
!FIXNUM_P(cfp->ep[-2])) {
|
||||
return &cfp->ep[-2];
|
||||
}
|
||||
}
|
||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "vm_core.h"
|
||||
|
||||
#define PASS_PASSED_BLOCK_TH(th) do { \
|
||||
(th)->passed_block = GC_GUARDED_PTR_REF((rb_block_t *)(th)->cfp->lfp[0]); \
|
||||
(th)->passed_block = rb_vm_control_frame_block_ptr(th->cfp); \
|
||||
(th)->cfp->flag |= VM_FRAME_FLAG_PASSED; \
|
||||
} while (0)
|
||||
|
||||
|
|
48
insns.def
48
insns.def
|
@ -55,7 +55,7 @@ getlocal
|
|||
()
|
||||
(VALUE val)
|
||||
{
|
||||
val = *(GET_LFP() - idx);
|
||||
val = *(GET_LEP() - idx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,7 +69,7 @@ setlocal
|
|||
(VALUE val)
|
||||
()
|
||||
{
|
||||
(*(GET_LFP() - idx)) = val;
|
||||
*(GET_LEP() - idx) = val;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,7 +83,7 @@ getspecial
|
|||
()
|
||||
(VALUE val)
|
||||
{
|
||||
val = vm_getspecial(th, GET_LFP(), key, type);
|
||||
val = vm_getspecial(th, GET_LEP(), key, type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,7 +97,7 @@ setspecial
|
|||
(VALUE obj)
|
||||
()
|
||||
{
|
||||
lfp_svar_set(th, GET_LFP(), key, obj);
|
||||
lep_svar_set(th, GET_LEP(), key, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,11 +114,11 @@ getdynamic
|
|||
(VALUE val)
|
||||
{
|
||||
rb_num_t i;
|
||||
VALUE *dfp2 = GET_DFP();
|
||||
VALUE *ep = GET_EP();
|
||||
for (i = 0; i < level; i++) {
|
||||
dfp2 = GET_PREV_DFP(dfp2);
|
||||
ep = GET_PREV_EP(ep);
|
||||
}
|
||||
val = *(dfp2 - idx);
|
||||
val = *(ep - idx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,11 +135,11 @@ setdynamic
|
|||
()
|
||||
{
|
||||
rb_num_t i;
|
||||
VALUE *dfp2 = GET_DFP();
|
||||
VALUE *ep = GET_EP();
|
||||
for (i = 0; i < level; i++) {
|
||||
dfp2 = GET_PREV_DFP(dfp2);
|
||||
ep = GET_PREV_EP(ep);
|
||||
}
|
||||
*(dfp2 - idx) = val;
|
||||
*(ep - idx) = val;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,7 +183,7 @@ getclassvariable
|
|||
()
|
||||
(VALUE val)
|
||||
{
|
||||
NODE * const cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||
NODE *cref = vm_get_cref(GET_ISEQ(), GET_EP());
|
||||
val = rb_cvar_get(vm_get_cvar_base(cref), id);
|
||||
}
|
||||
|
||||
|
@ -198,7 +198,7 @@ setclassvariable
|
|||
(VALUE val)
|
||||
()
|
||||
{
|
||||
NODE * const cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||
NODE *cref = vm_get_cref(GET_ISEQ(), GET_EP());
|
||||
rb_cvar_set(vm_get_cvar_base(cref), id, val);
|
||||
}
|
||||
|
||||
|
@ -343,10 +343,10 @@ putspecialobject
|
|||
val = rb_mRubyVMFrozenCore;
|
||||
break;
|
||||
case VM_SPECIAL_OBJECT_CBASE:
|
||||
val = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||
val = vm_get_cbase(GET_ISEQ(), GET_EP());
|
||||
break;
|
||||
case VM_SPECIAL_OBJECT_CONST_BASE:
|
||||
val = vm_get_const_base(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||
val = vm_get_const_base(GET_ISEQ(), GET_EP());
|
||||
break;
|
||||
default:
|
||||
rb_bug("putspecialobject insn: unknown value_type");
|
||||
|
@ -768,7 +768,7 @@ defined
|
|||
}
|
||||
break;
|
||||
case DEFINED_IVAR2:
|
||||
klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||
klass = vm_get_cbase(GET_ISEQ(), GET_EP());
|
||||
break;
|
||||
case DEFINED_GVAR:
|
||||
if (rb_gvar_defined(rb_global_entry(SYM2ID(obj)))) {
|
||||
|
@ -777,7 +777,7 @@ defined
|
|||
break;
|
||||
case DEFINED_CVAR:
|
||||
{
|
||||
NODE *cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||
NODE *cref = vm_get_cref(GET_ISEQ(), GET_EP());
|
||||
klass = vm_get_cvar_base(cref);
|
||||
if (rb_cvar_defined(klass, SYM2ID(obj))) {
|
||||
expr_type = "class variable";
|
||||
|
@ -842,7 +842,7 @@ defined
|
|||
break;
|
||||
}
|
||||
case DEFINED_REF:{
|
||||
val = vm_getspecial(th, GET_LFP(), Qfalse, FIX2INT(obj));
|
||||
val = vm_getspecial(th, GET_LEP(), Qfalse, FIX2INT(obj));
|
||||
if (val != Qnil) {
|
||||
expr_type = "global-variable";
|
||||
}
|
||||
|
@ -971,9 +971,9 @@ defineclass
|
|||
COPY_CREF(class_iseq->cref_stack, vm_cref_push(th, klass, NOEX_PUBLIC, NULL));
|
||||
|
||||
/* enter scope */
|
||||
vm_push_frame(th, class_iseq,
|
||||
VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_BLOCK_PTR(),
|
||||
class_iseq->iseq_encoded, GET_SP(), 0,
|
||||
vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS,
|
||||
klass, VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()),
|
||||
class_iseq->iseq_encoded, GET_SP(),
|
||||
class_iseq->local_size);
|
||||
RESTORE_REGS();
|
||||
|
||||
|
@ -1315,11 +1315,11 @@ opt_checkenv
|
|||
()
|
||||
()
|
||||
{
|
||||
if (GET_CFP()->bp != GET_DFP() + 1) {
|
||||
VALUE *new_dfp = GET_CFP()->bp - 1;
|
||||
if (GET_CFP()->bp != GET_EP() + 1) {
|
||||
VALUE *ep = GET_CFP()->bp - 1;
|
||||
/* TODO: copy env and clean stack at creating env? */
|
||||
*new_dfp = *GET_DFP();
|
||||
SET_DFP(new_dfp);
|
||||
*ep = *GET_EP();
|
||||
SET_EP(ep);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
14
proc.c
14
proc.c
|
@ -383,17 +383,13 @@ proc_new(VALUE klass, int is_lambda)
|
|||
rb_control_frame_t *cfp = th->cfp;
|
||||
rb_block_t *block;
|
||||
|
||||
if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0) {
|
||||
|
||||
block = GC_GUARDED_PTR_REF(cfp->lfp[0]);
|
||||
if ((block = rb_vm_control_frame_block_ptr(cfp)) != 0) {
|
||||
/* block found */
|
||||
}
|
||||
else {
|
||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||
|
||||
if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0) {
|
||||
|
||||
block = GC_GUARDED_PTR_REF(cfp->lfp[0]);
|
||||
|
||||
if ((block = rb_vm_control_frame_block_ptr(cfp)) != 0) {
|
||||
if (is_lambda) {
|
||||
rb_warn("tried to create Proc object without a block");
|
||||
}
|
||||
|
@ -418,7 +414,7 @@ proc_new(VALUE klass, int is_lambda)
|
|||
}
|
||||
|
||||
procval = rb_vm_make_proc(th, block, klass);
|
||||
rb_vm_rewrite_dfp_in_errinfo(th, cfp);
|
||||
rb_vm_rewrite_ep_in_errinfo(th, cfp);
|
||||
|
||||
if (is_lambda) {
|
||||
rb_proc_t *proc;
|
||||
|
@ -801,7 +797,7 @@ rb_hash_proc(st_index_t hash, VALUE prc)
|
|||
GetProcPtr(prc, proc);
|
||||
hash = rb_hash_uint(hash, (st_index_t)proc->block.iseq);
|
||||
hash = rb_hash_uint(hash, (st_index_t)proc->envval);
|
||||
return rb_hash_uint(hash, (st_index_t)proc->block.lfp >> 16);
|
||||
return rb_hash_uint(hash, (st_index_t)proc->block.ep >> 16);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
4
thread.c
4
thread.c
|
@ -454,8 +454,8 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s
|
|||
if (!th->first_func) {
|
||||
GetProcPtr(th->first_proc, proc);
|
||||
th->errinfo = Qnil;
|
||||
th->local_lfp = proc->block.lfp;
|
||||
th->local_svar = Qnil;
|
||||
th->root_lep = rb_vm_ep_local_ep(proc->block.ep);
|
||||
th->root_svar = Qnil;
|
||||
th->value = rb_vm_invoke_proc(th, proc, proc->block.self,
|
||||
(int)RARRAY_LEN(args), RARRAY_PTR(args), 0);
|
||||
}
|
||||
|
|
211
vm.c
211
vm.c
|
@ -19,6 +19,48 @@
|
|||
#include "iseq.h"
|
||||
#include "eval_intern.h"
|
||||
|
||||
static inline VALUE *
|
||||
VM_EP_LEP(VALUE *ep)
|
||||
{
|
||||
while (1) {
|
||||
if (VM_EP_LEP_P(ep)) {
|
||||
return ep;
|
||||
}
|
||||
ep = VM_EP_PREV_EP(ep);
|
||||
}
|
||||
}
|
||||
|
||||
VALUE *
|
||||
rb_vm_ep_local_ep(VALUE *ep)
|
||||
{
|
||||
return VM_EP_LEP(ep);
|
||||
}
|
||||
|
||||
static inline VALUE *
|
||||
VM_CF_LEP(rb_control_frame_t *cfp)
|
||||
{
|
||||
return VM_EP_LEP(cfp->ep);
|
||||
}
|
||||
|
||||
static inline VALUE *
|
||||
VM_CF_PREV_EP(rb_control_frame_t * cfp)
|
||||
{
|
||||
return VM_EP_PREV_EP((cfp)->ep);
|
||||
}
|
||||
|
||||
static inline rb_block_t *
|
||||
VM_CF_BLOCK_PTR(rb_control_frame_t *cfp)
|
||||
{
|
||||
VALUE *ep = VM_CF_LEP(cfp);
|
||||
return VM_EP_BLOCK_PTR(ep);
|
||||
}
|
||||
|
||||
rb_block_t *
|
||||
rb_vm_control_frame_block_ptr(rb_control_frame_t *cfp)
|
||||
{
|
||||
return VM_CF_BLOCK_PTR(cfp);
|
||||
}
|
||||
|
||||
#include "vm_insnhelper.h"
|
||||
#include "vm_insnhelper.c"
|
||||
#include "vm_exec.h"
|
||||
|
@ -85,8 +127,8 @@ static inline VALUE
|
|||
rb_vm_set_finish_env(rb_thread_t * th)
|
||||
{
|
||||
vm_push_frame(th, 0, VM_FRAME_MAGIC_FINISH,
|
||||
Qnil, th->cfp->lfp[0], 0,
|
||||
th->cfp->sp, 0, 1);
|
||||
Qnil, VM_ENVVAL_BLOCK_PTR(VM_CF_BLOCK_PTR(th->cfp)), 0,
|
||||
th->cfp->sp, 1);
|
||||
th->cfp->pc = (VALUE *)&finish_insn_seq[0];
|
||||
return Qtrue;
|
||||
}
|
||||
|
@ -106,8 +148,8 @@ vm_set_top_stack(rb_thread_t * th, VALUE iseqval)
|
|||
|
||||
CHECK_STACK_OVERFLOW(th->cfp, iseq->local_size + iseq->stack_max);
|
||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP,
|
||||
th->top_self, 0, iseq->iseq_encoded,
|
||||
th->cfp->sp, 0, iseq->local_size);
|
||||
th->top_self, VM_ENVVAL_BLOCK_PTR(0), iseq->iseq_encoded,
|
||||
th->cfp->sp, iseq->local_size);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -122,11 +164,11 @@ vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref)
|
|||
|
||||
CHECK_STACK_OVERFLOW(th->cfp, iseq->local_size + iseq->stack_max);
|
||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL, block->self,
|
||||
GC_GUARDED_PTR(block->dfp), iseq->iseq_encoded,
|
||||
th->cfp->sp, block->lfp, iseq->local_size);
|
||||
VM_ENVVAL_PREV_EP_PTR(block->ep), iseq->iseq_encoded,
|
||||
th->cfp->sp, iseq->local_size);
|
||||
|
||||
if (cref) {
|
||||
th->cfp->dfp[-1] = (VALUE)cref;
|
||||
th->cfp->ep[-1] = (VALUE)cref;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,11 +340,10 @@ static int
|
|||
check_env(rb_env_t * const env)
|
||||
{
|
||||
fprintf(stderr, "---\n");
|
||||
fprintf(stderr, "envptr: %p\n", (void *)&env->block.dfp[0]);
|
||||
fprintf(stderr, "envval: %10p ", (void *)env->block.dfp[1]);
|
||||
dp(env->block.dfp[1]);
|
||||
fprintf(stderr, "lfp: %10p\n", (void *)env->block.lfp);
|
||||
fprintf(stderr, "dfp: %10p\n", (void *)env->block.dfp);
|
||||
fprintf(stderr, "envptr: %p\n", (void *)&env->block.ep[0]);
|
||||
fprintf(stderr, "envval: %10p ", (void *)env->block.ep[1]);
|
||||
dp(env->block.ep[1]);
|
||||
fprintf(stderr, "ep: %10p\n", (void *)env->block.ep);
|
||||
if (env->prev_envval) {
|
||||
fprintf(stderr, ">>\n");
|
||||
check_env_value(env->prev_envval);
|
||||
|
@ -345,16 +386,15 @@ vm_make_env_each(rb_thread_t * const th, rb_control_frame_t * const cfp,
|
|||
penvval = ENV_VAL(penvptr);
|
||||
}
|
||||
else {
|
||||
while (pcfp->dfp != penvptr) {
|
||||
while (pcfp->ep != penvptr) {
|
||||
pcfp++;
|
||||
if (pcfp->dfp == 0) {
|
||||
if (pcfp->ep == 0) {
|
||||
SDR();
|
||||
rb_bug("invalid dfp");
|
||||
rb_bug("invalid ep");
|
||||
}
|
||||
}
|
||||
penvval = vm_make_env_each(th, pcfp, penvptr, endptr);
|
||||
cfp->lfp = pcfp->lfp;
|
||||
*envptr = GC_GUARDED_PTR(pcfp->dfp);
|
||||
*envptr = VM_ENVVAL_PREV_EP_PTR(pcfp->ep);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -389,23 +429,19 @@ vm_make_env_each(rb_thread_t * const th, rb_control_frame_t * const cfp,
|
|||
nenvptr = &env->env[i - 1];
|
||||
nenvptr[1] = envval; /* frame self */
|
||||
|
||||
/* reset lfp/dfp in cfp */
|
||||
cfp->dfp = nenvptr;
|
||||
if (envptr == endptr) {
|
||||
cfp->lfp = nenvptr;
|
||||
}
|
||||
/* reset ep in cfp */
|
||||
cfp->ep = nenvptr;
|
||||
|
||||
/* as Binding */
|
||||
env->block.self = cfp->self;
|
||||
env->block.lfp = cfp->lfp;
|
||||
env->block.dfp = cfp->dfp;
|
||||
env->block.ep = cfp->ep;
|
||||
env->block.iseq = cfp->iseq;
|
||||
|
||||
if (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
||||
/* TODO */
|
||||
env->block.iseq = 0;
|
||||
} else {
|
||||
rb_vm_rewrite_dfp_in_errinfo(th, cfp);
|
||||
rb_vm_rewrite_ep_in_errinfo(th, cfp);
|
||||
}
|
||||
return envval;
|
||||
}
|
||||
|
@ -436,11 +472,11 @@ collect_local_variables_in_env(rb_env_t * env, const VALUE ary)
|
|||
}
|
||||
|
||||
static int
|
||||
vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary)
|
||||
vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *ep, VALUE ary)
|
||||
{
|
||||
if (ENV_IN_HEAP_P(th, dfp)) {
|
||||
if (ENV_IN_HEAP_P(th, ep)) {
|
||||
rb_env_t *env;
|
||||
GetEnvPtr(ENV_VAL(dfp), env);
|
||||
GetEnvPtr(ENV_VAL(ep), env);
|
||||
collect_local_variables_in_env(env, ary);
|
||||
return 1;
|
||||
}
|
||||
|
@ -459,7 +495,7 @@ rb_vm_make_env_object(rb_thread_t * th, rb_control_frame_t *cfp)
|
|||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||
}
|
||||
|
||||
envval = vm_make_env_each(th, cfp, cfp->dfp, cfp->lfp);
|
||||
envval = vm_make_env_each(th, cfp, cfp->ep, VM_CF_LEP(cfp));
|
||||
|
||||
if (PROCDEBUG) {
|
||||
check_env_value(envval);
|
||||
|
@ -469,21 +505,21 @@ rb_vm_make_env_object(rb_thread_t * th, rb_control_frame_t *cfp)
|
|||
}
|
||||
|
||||
void
|
||||
rb_vm_rewrite_dfp_in_errinfo(rb_thread_t *th, rb_control_frame_t *cfp)
|
||||
rb_vm_rewrite_ep_in_errinfo(rb_thread_t *th, rb_control_frame_t *cfp)
|
||||
{
|
||||
/* rewrite dfp in errinfo to point to heap */
|
||||
/* rewrite ep in errinfo to point to heap */
|
||||
if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq) &&
|
||||
(cfp->iseq->type == ISEQ_TYPE_RESCUE ||
|
||||
cfp->iseq->type == ISEQ_TYPE_ENSURE)) {
|
||||
VALUE errinfo = cfp->dfp[-2]; /* #$! */
|
||||
VALUE errinfo = cfp->ep[-2]; /* #$! */
|
||||
if (RB_TYPE_P(errinfo, T_NODE)) {
|
||||
VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(errinfo);
|
||||
if (! ENV_IN_HEAP_P(th, escape_dfp)) {
|
||||
VALUE dfpval = *escape_dfp;
|
||||
if (CLASS_OF(dfpval) == rb_cEnv) {
|
||||
rb_env_t *dfpenv;
|
||||
GetEnvPtr(dfpval, dfpenv);
|
||||
SET_THROWOBJ_CATCH_POINT(errinfo, (VALUE)(dfpenv->env + dfpenv->local_size));
|
||||
VALUE *escape_ep = GET_THROWOBJ_CATCH_POINT(errinfo);
|
||||
if (! ENV_IN_HEAP_P(th, escape_ep)) {
|
||||
VALUE epval = *escape_ep;
|
||||
if (CLASS_OF(epval) == rb_cEnv) {
|
||||
rb_env_t *epenv;
|
||||
GetEnvPtr(epval, epenv);
|
||||
SET_THROWOBJ_CATCH_POINT(errinfo, (VALUE)(epenv->env + epenv->local_size));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -517,19 +553,19 @@ rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass)
|
|||
VALUE procval, envval, blockprocval = 0;
|
||||
rb_proc_t *proc;
|
||||
rb_control_frame_t *cfp = RUBY_VM_GET_CFP_FROM_BLOCK_PTR(block);
|
||||
rb_block_t *block2;
|
||||
|
||||
if (block->proc) {
|
||||
rb_bug("rb_vm_make_proc: Proc value is already created.");
|
||||
}
|
||||
|
||||
if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
|
||||
if ((block2 = VM_CF_BLOCK_PTR(cfp)) != 0) {
|
||||
rb_proc_t *p;
|
||||
|
||||
blockprocval = vm_make_proc_from_block(
|
||||
th, (rb_block_t *)GC_GUARDED_PTR_REF(*cfp->lfp));
|
||||
blockprocval = vm_make_proc_from_block(th, block2);
|
||||
|
||||
GetProcPtr(blockprocval, p);
|
||||
*cfp->lfp = GC_GUARDED_PTR(&p->block);
|
||||
*VM_CF_LEP(cfp) = VM_ENVVAL_BLOCK_PTR(&p->block);
|
||||
}
|
||||
|
||||
envval = rb_vm_make_env_object(th, cfp);
|
||||
|
@ -541,19 +577,15 @@ rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass)
|
|||
GetProcPtr(procval, proc);
|
||||
proc->blockprocval = blockprocval;
|
||||
proc->block.self = block->self;
|
||||
proc->block.lfp = block->lfp;
|
||||
proc->block.dfp = block->dfp;
|
||||
proc->block.ep = block->ep;
|
||||
proc->block.iseq = block->iseq;
|
||||
proc->block.proc = procval;
|
||||
proc->envval = envval;
|
||||
proc->safe_level = th->safe_level;
|
||||
|
||||
if (VMDEBUG) {
|
||||
if (th->stack < block->dfp && block->dfp < th->stack + th->stack_size) {
|
||||
rb_bug("invalid ptr: block->dfp");
|
||||
}
|
||||
if (th->stack < block->lfp && block->lfp < th->stack + th->stack_size) {
|
||||
rb_bug("invalid ptr: block->lfp");
|
||||
if (th->stack < block->ep && block->ep < th->stack + th->stack_size) {
|
||||
rb_bug("invalid ptr: block->ep");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -590,15 +622,14 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
|
|||
type == VM_FRAME_MAGIC_LAMBDA);
|
||||
|
||||
ncfp = vm_push_frame(th, iseq, type,
|
||||
self, GC_GUARDED_PTR(block->dfp),
|
||||
iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, block->lfp,
|
||||
iseq->local_size - arg_size);
|
||||
self, VM_ENVVAL_PREV_EP_PTR(block->ep),
|
||||
iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, iseq->local_size - arg_size);
|
||||
ncfp->me = th->passed_me;
|
||||
th->passed_me = 0;
|
||||
th->passed_block = blockptr;
|
||||
|
||||
if (cref) {
|
||||
th->cfp->dfp[-1] = (VALUE)cref;
|
||||
th->cfp->ep[-1] = (VALUE)cref;
|
||||
}
|
||||
|
||||
return vm_exec(th);
|
||||
|
@ -611,7 +642,7 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
|
|||
static inline const rb_block_t *
|
||||
check_block(rb_thread_t *th)
|
||||
{
|
||||
const rb_block_t *blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
|
||||
const rb_block_t *blockptr = VM_CF_BLOCK_PTR(th->cfp);
|
||||
|
||||
if (blockptr == 0) {
|
||||
rb_vm_localjump_error("no block given", Qnil, 0);
|
||||
|
@ -679,14 +710,14 @@ static VALUE
|
|||
vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key)
|
||||
{
|
||||
cfp = vm_normal_frame(th, cfp);
|
||||
return lfp_svar_get(th, cfp ? cfp->lfp : 0, key);
|
||||
return lep_svar_get(th, cfp ? VM_CF_LEP(cfp) : 0, key);
|
||||
}
|
||||
|
||||
static void
|
||||
vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, const VALUE val)
|
||||
{
|
||||
cfp = vm_normal_frame(th, cfp);
|
||||
lfp_svar_set(th, cfp ? cfp->lfp : 0, key, val);
|
||||
lep_svar_set(th, cfp ? VM_CF_LEP(cfp) : 0, key, val);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -780,7 +811,7 @@ rb_vm_cref(void)
|
|||
if (cfp == 0) {
|
||||
rb_raise(rb_eRuntimeError, "Can't call on top of Fiber or Thread");
|
||||
}
|
||||
return vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
|
||||
return vm_get_cref(cfp->iseq, cfp->ep);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -804,7 +835,7 @@ rb_vm_cbase(void)
|
|||
if (cfp == 0) {
|
||||
rb_raise(rb_eRuntimeError, "Can't call on top of Fiber or Thread");
|
||||
}
|
||||
return vm_get_cbase(cfp->iseq, cfp->lfp, cfp->dfp);
|
||||
return vm_get_cbase(cfp->iseq, cfp->ep);
|
||||
}
|
||||
|
||||
/* jump */
|
||||
|
@ -896,10 +927,10 @@ static void
|
|||
vm_iter_break(rb_thread_t *th, VALUE val)
|
||||
{
|
||||
rb_control_frame_t *cfp = th->cfp;
|
||||
VALUE *dfp = GC_GUARDED_PTR_REF(*cfp->dfp);
|
||||
VALUE *ep = VM_CF_PREV_EP(cfp);
|
||||
|
||||
th->state = TAG_BREAK;
|
||||
th->errinfo = (VALUE)NEW_THROW_OBJECT(val, (VALUE)dfp, TAG_BREAK);
|
||||
th->errinfo = (VALUE)NEW_THROW_OBJECT(val, (VALUE)ep, TAG_BREAK);
|
||||
TH_JUMP_TAG(th, TAG_BREAK);
|
||||
}
|
||||
|
||||
|
@ -1028,16 +1059,14 @@ vm_frametype_name(const rb_control_frame_t *cfp)
|
|||
rb_iseq_t *iseq; // cfp[3], iseq
|
||||
VALUE flag; // cfp[4], magic
|
||||
VALUE self; // cfp[5], self
|
||||
VALUE *lfp; // cfp[6], local frame pointer
|
||||
VALUE *dfp; // cfp[7], dynamic frame pointer
|
||||
rb_iseq_t * block_iseq; // cfp[8], block iseq
|
||||
VALUE proc; // cfp[9], always 0
|
||||
VALUE *ep; // cfp[6], env pointer
|
||||
rb_iseq_t * block_iseq; // cfp[7], block iseq
|
||||
VALUE proc; // cfp[8], always 0
|
||||
};
|
||||
|
||||
struct BLOCK {
|
||||
VALUE self;
|
||||
VALUE *lfp;
|
||||
VALUE *dfp;
|
||||
VALUE *ep;
|
||||
rb_iseq_t *block_iseq;
|
||||
VALUE proc;
|
||||
};
|
||||
|
@ -1054,8 +1083,8 @@ vm_frametype_name(const rb_control_frame_t *cfp)
|
|||
...
|
||||
VALUE paramN;
|
||||
VALUE cref;
|
||||
VALUE special; // lfp [1]
|
||||
struct block_object *block_ptr | 0x01; // lfp [0]
|
||||
VALUE special; // lep [1]
|
||||
struct block_object *block_ptr | 0x01; // lep [0]
|
||||
};
|
||||
|
||||
struct BLOCK_CONTROL_FRAME {
|
||||
|
@ -1070,7 +1099,7 @@ vm_frametype_name(const rb_control_frame_t *cfp)
|
|||
...
|
||||
VALUE paramN;
|
||||
VALUE cref;
|
||||
VALUE *(prev_ptr | 0x01); // DFP[0]
|
||||
VALUE *(prev_ptr | 0x01); // ep[0]
|
||||
};
|
||||
|
||||
struct CLASS_CONTROL_FRAME {
|
||||
|
@ -1082,30 +1111,28 @@ vm_frametype_name(const rb_control_frame_t *cfp)
|
|||
...
|
||||
VALUE paramN;
|
||||
VALUE cref;
|
||||
VALUE prev_dfp; // for frame jump
|
||||
VALUE prev_ep; // for frame jump
|
||||
};
|
||||
|
||||
struct C_METHOD_CONTROL_FRAME {
|
||||
VALUE *pc; // 0
|
||||
VALUE *sp; // stack pointer
|
||||
VALUE *bp; // base pointer (used in exception)
|
||||
rb_iseq_t *iseq; // cmi
|
||||
rb_iseq_t *iseq; // cmi
|
||||
VALUE magic; // C_METHOD_FRAME
|
||||
VALUE self; // ?
|
||||
VALUE *lfp; // lfp
|
||||
VALUE *dfp; // == lfp
|
||||
rb_iseq_t * block_iseq; //
|
||||
VALUE *ep; // ep == lep
|
||||
rb_iseq_t * block_iseq; //
|
||||
VALUE proc; // always 0
|
||||
};
|
||||
|
||||
struct C_BLOCK_CONTROL_FRAME {
|
||||
VALUE *pc; // point only "finish" insn
|
||||
VALUE *sp; // sp
|
||||
rb_iseq_t *iseq; // ?
|
||||
rb_iseq_t *iseq; // ?
|
||||
VALUE magic; // C_METHOD_FRAME
|
||||
VALUE self; // needed?
|
||||
VALUE *lfp; // lfp
|
||||
VALUE *dfp; // lfp
|
||||
VALUE *ep; // ep
|
||||
rb_iseq_t * block_iseq; // 0
|
||||
};
|
||||
*/
|
||||
|
@ -1117,7 +1144,7 @@ vm_exec(rb_thread_t *th)
|
|||
int state;
|
||||
VALUE result, err;
|
||||
VALUE initial = 0;
|
||||
VALUE *escape_dfp = NULL;
|
||||
VALUE *escape_ep = NULL;
|
||||
|
||||
TH_PUSH_TAG(th);
|
||||
_tag.retval = Qnil;
|
||||
|
@ -1155,12 +1182,12 @@ vm_exec(rb_thread_t *th)
|
|||
epc = cfp->pc - cfp->iseq->iseq_encoded;
|
||||
|
||||
if (state == TAG_BREAK || state == TAG_RETURN) {
|
||||
escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
|
||||
escape_ep = GET_THROWOBJ_CATCH_POINT(err);
|
||||
|
||||
if (cfp->dfp == escape_dfp) {
|
||||
if (cfp->ep == escape_ep) {
|
||||
if (state == TAG_RETURN) {
|
||||
if ((cfp + 1)->pc != &finish_insn_seq[0]) {
|
||||
SET_THROWOBJ_CATCH_POINT(err, (VALUE)(cfp + 1)->dfp);
|
||||
SET_THROWOBJ_CATCH_POINT(err, (VALUE)(cfp + 1)->ep);
|
||||
SET_THROWOBJ_STATE(err, state = TAG_BREAK);
|
||||
}
|
||||
else {
|
||||
|
@ -1224,9 +1251,9 @@ vm_exec(rb_thread_t *th)
|
|||
break;
|
||||
}
|
||||
else if (entry->type == CATCH_TYPE_RETRY) {
|
||||
VALUE *escape_dfp;
|
||||
escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
|
||||
if (cfp->dfp == escape_dfp) {
|
||||
VALUE *escape_ep;
|
||||
escape_ep = GET_THROWOBJ_CATCH_POINT(err);
|
||||
if (cfp->ep == escape_ep) {
|
||||
cfp->pc = cfp->iseq->iseq_encoded + entry->cont;
|
||||
th->errinfo = Qnil;
|
||||
goto vm_loop_start;
|
||||
|
@ -1235,7 +1262,7 @@ vm_exec(rb_thread_t *th)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (state == TAG_BREAK && ((VALUE)escape_dfp & ~0x03) == 0) {
|
||||
else if (state == TAG_BREAK && ((VALUE)escape_ep & ~0x03) == 0) {
|
||||
type = CATCH_TYPE_BREAK;
|
||||
|
||||
search_restart_point:
|
||||
|
@ -1302,8 +1329,8 @@ vm_exec(rb_thread_t *th)
|
|||
/* push block frame */
|
||||
cfp->sp[0] = err;
|
||||
vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_BLOCK,
|
||||
cfp->self, (VALUE)cfp->dfp, catch_iseq->iseq_encoded,
|
||||
cfp->sp + 1 /* push value */, cfp->lfp, catch_iseq->local_size - 1);
|
||||
cfp->self, VM_ENVVAL_PREV_EP_PTR(cfp->ep), catch_iseq->iseq_encoded,
|
||||
cfp->sp + 1 /* push value */, catch_iseq->local_size - 1);
|
||||
|
||||
state = 0;
|
||||
th->state = 0;
|
||||
|
@ -1438,7 +1465,7 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg,
|
|||
VALUE val;
|
||||
|
||||
vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP,
|
||||
recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
|
||||
recv, VM_ENVVAL_BLOCK_PTR(blockptr), 0, reg_cfp->sp, 1);
|
||||
|
||||
val = (*func)(arg);
|
||||
|
||||
|
@ -1645,7 +1672,7 @@ rb_thread_mark(void *ptr)
|
|||
RUBY_MARK_UNLESS_NULL(th->value);
|
||||
RUBY_MARK_UNLESS_NULL(th->errinfo);
|
||||
RUBY_MARK_UNLESS_NULL(th->thrown_errinfo);
|
||||
RUBY_MARK_UNLESS_NULL(th->local_svar);
|
||||
RUBY_MARK_UNLESS_NULL(th->root_svar);
|
||||
RUBY_MARK_UNLESS_NULL(th->top_self);
|
||||
RUBY_MARK_UNLESS_NULL(th->top_wrapper);
|
||||
RUBY_MARK_UNLESS_NULL(th->fiber);
|
||||
|
@ -1781,8 +1808,8 @@ th_init(rb_thread_t *th, VALUE self)
|
|||
|
||||
th->cfp = (void *)(th->stack + th->stack_size);
|
||||
|
||||
vm_push_frame(th, 0, VM_FRAME_MAGIC_TOP, Qnil, 0, 0,
|
||||
th->stack, 0, 1);
|
||||
vm_push_frame(th, 0 /* dummy iseq */, VM_FRAME_MAGIC_TOP, Qnil /* dummy self */,
|
||||
VM_ENVVAL_BLOCK_PTR(0), 0 /* dummy pc */, th->stack, 1);
|
||||
|
||||
th->status = THREAD_RUNNABLE;
|
||||
th->errinfo = Qnil;
|
||||
|
|
43
vm_core.h
43
vm_core.h
|
@ -349,17 +349,15 @@ typedef struct {
|
|||
rb_iseq_t *iseq; /* cfp[3] */
|
||||
VALUE flag; /* cfp[4] */
|
||||
VALUE self; /* cfp[5] / block[0] */
|
||||
VALUE *lfp; /* cfp[6] / block[1] */
|
||||
VALUE *dfp; /* cfp[7] / block[2] */
|
||||
rb_iseq_t *block_iseq; /* cfp[8] / block[3] */
|
||||
VALUE proc; /* cfp[9] / block[4] */
|
||||
const rb_method_entry_t *me;/* cfp[10] */
|
||||
VALUE *ep; /* cfp[6] / block[1] */
|
||||
rb_iseq_t *block_iseq; /* cfp[7] / block[2] */
|
||||
VALUE proc; /* cfp[8] / block[3] */
|
||||
const rb_method_entry_t *me;/* cfp[9] */
|
||||
} rb_control_frame_t;
|
||||
|
||||
typedef struct rb_block_struct {
|
||||
VALUE self; /* share with method frame if it's only block */
|
||||
VALUE *lfp; /* share with method frame if it's only block */
|
||||
VALUE *dfp; /* share with method frame if it's only block */
|
||||
VALUE *ep; /* share with method frame if it's only block */
|
||||
rb_iseq_t *iseq;
|
||||
VALUE proc;
|
||||
} rb_block_t;
|
||||
|
@ -434,8 +432,8 @@ typedef struct rb_thread_struct {
|
|||
/* eval env */
|
||||
rb_block_t *base_block;
|
||||
|
||||
VALUE *local_lfp;
|
||||
VALUE local_svar;
|
||||
VALUE *root_lep;
|
||||
VALUE root_svar;
|
||||
|
||||
/* thread control */
|
||||
rb_thread_id_t thread_id;
|
||||
|
@ -622,7 +620,27 @@ typedef rb_control_frame_t *
|
|||
#define GC_GUARDED_PTR_REF(p) ((void *)(((VALUE)(p)) & ~0x03))
|
||||
#define GC_GUARDED_PTR_P(p) (((VALUE)(p)) & 0x01)
|
||||
|
||||
#define RUBY_VM_GET_BLOCK_PTR(cfp) ((rb_block_t *)(GC_GUARDED_PTR_REF((cfp)->lfp[0])))
|
||||
/*
|
||||
* block frame:
|
||||
* ep[ 0]: prev frame
|
||||
* ep[-1]: CREF (for *_eval)
|
||||
*
|
||||
* method frame:
|
||||
* ep[ 0]: block pointer (ptr | VM_ENVVAL_BLOCK_PTR_FLAG)
|
||||
*/
|
||||
|
||||
#define VM_ENVVAL_BLOCK_PTR_FLAG 0x02
|
||||
#define VM_ENVVAL_BLOCK_PTR(v) (GC_GUARDED_PTR(v) | VM_ENVVAL_BLOCK_PTR_FLAG)
|
||||
#define VM_ENVVAL_BLOCK_PTR_P(v) ((v) & VM_ENVVAL_BLOCK_PTR_FLAG)
|
||||
#define VM_ENVVAL_PREV_EP_PTR(v) ((VALUE)GC_GUARDED_PTR(v))
|
||||
#define VM_ENVVAL_PREV_EP_PTR_P(v) (!(VM_ENVVAL_BLOCK_PTR_P(v)))
|
||||
|
||||
#define VM_EP_PREV_EP(ep) ((VALUE *)GC_GUARDED_PTR_REF((ep)[0]))
|
||||
#define VM_EP_BLOCK_PTR(ep) ((rb_block_t *)GC_GUARDED_PTR_REF((ep)[0]))
|
||||
#define VM_EP_LEP_P(ep) VM_ENVVAL_BLOCK_PTR_P((ep)[0])
|
||||
|
||||
VALUE *rb_vm_ep_local_ep(VALUE *ep);
|
||||
rb_block_t *rb_vm_control_frame_block_ptr(rb_control_frame_t *cfp);
|
||||
|
||||
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp) ((cfp)+1)
|
||||
#define RUBY_VM_NEXT_CONTROL_FRAME(cfp) ((cfp)-1)
|
||||
|
@ -647,6 +665,9 @@ VALUE rb_proc_alloc(VALUE klass);
|
|||
|
||||
/* for debug */
|
||||
extern void rb_vmdebug_stack_dump_raw(rb_thread_t *, rb_control_frame_t *);
|
||||
extern void rb_vmdebug_debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp);
|
||||
extern void rb_vmdebug_debug_print_post(rb_thread_t *th, rb_control_frame_t *cfp);
|
||||
|
||||
#define SDR() rb_vmdebug_stack_dump_raw(GET_THREAD(), GET_THREAD()->cfp)
|
||||
#define SDR2(cfp) rb_vmdebug_stack_dump_raw(GET_THREAD(), (cfp))
|
||||
void rb_vm_bugreport(void);
|
||||
|
@ -666,7 +687,7 @@ VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
|
|||
int argc, const VALUE *argv, const rb_block_t *blockptr);
|
||||
VALUE rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass);
|
||||
VALUE rb_vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp);
|
||||
void rb_vm_rewrite_dfp_in_errinfo(rb_thread_t *th, rb_control_frame_t *cfp);
|
||||
void rb_vm_rewrite_ep_in_errinfo(rb_thread_t *th, rb_control_frame_t *cfp);
|
||||
void rb_vm_inc_const_missing_count(void);
|
||||
void rb_vm_gvl_destroy(rb_vm_t *vm);
|
||||
VALUE rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc,
|
||||
|
|
78
vm_dump.c
78
vm_dump.c
|
@ -28,9 +28,8 @@ static void
|
|||
control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
|
||||
{
|
||||
ptrdiff_t pc = -1, bp = -1;
|
||||
ptrdiff_t lfp = cfp->lfp - th->stack;
|
||||
ptrdiff_t dfp = cfp->dfp - th->stack;
|
||||
char lfp_in_heap = ' ', dfp_in_heap = ' ';
|
||||
ptrdiff_t ep = cfp->ep - th->stack;
|
||||
char ep_in_heap = ' ';
|
||||
char posbuf[MAX_POSBUF+1];
|
||||
int line = 0;
|
||||
int nopos = 0;
|
||||
|
@ -42,13 +41,9 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||
biseq_name = ""; /* RSTRING(cfp->block_iseq->location.label)->ptr; */
|
||||
}
|
||||
|
||||
if (lfp < 0 || (size_t)lfp > th->stack_size) {
|
||||
lfp = (ptrdiff_t)cfp->lfp;
|
||||
lfp_in_heap = 'p';
|
||||
}
|
||||
if (dfp < 0 || (size_t)dfp > th->stack_size) {
|
||||
dfp = (ptrdiff_t)cfp->dfp;
|
||||
dfp_in_heap = 'p';
|
||||
if (ep < 0 || (size_t)ep > th->stack_size) {
|
||||
ep = (ptrdiff_t)cfp->ep;
|
||||
ep_in_heap = 'p';
|
||||
}
|
||||
if (cfp->bp) {
|
||||
bp = cfp->bp - th->stack;
|
||||
|
@ -133,8 +128,7 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||
fprintf(stderr, "p:%04"PRIdPTRDIFF" ", pc);
|
||||
}
|
||||
fprintf(stderr, "s:%04"PRIdPTRDIFF" b:%04"PRIdPTRDIFF" ", (cfp->sp - th->stack), bp);
|
||||
fprintf(stderr, lfp_in_heap == ' ' ? "l:%06"PRIdPTRDIFF" " : "l:%06"PRIxPTRDIFF" ", lfp % 10000);
|
||||
fprintf(stderr, dfp_in_heap == ' ' ? "d:%06"PRIdPTRDIFF" " : "d:%06"PRIxPTRDIFF" ", dfp % 10000);
|
||||
fprintf(stderr, ep_in_heap == ' ' ? "e:%06"PRIdPTRDIFF" " : "e:%06"PRIxPTRDIFF" ", ep % 10000);
|
||||
fprintf(stderr, "%-6s", magic);
|
||||
if (line && !nopos) {
|
||||
fprintf(stderr, " %s", posbuf);
|
||||
|
@ -152,9 +146,7 @@ void
|
|||
rb_vmdebug_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp)
|
||||
{
|
||||
#if 0
|
||||
VALUE *sp = cfp->sp, *bp = cfp->bp;
|
||||
VALUE *lfp = cfp->lfp;
|
||||
VALUE *dfp = cfp->dfp;
|
||||
VALUE *sp = cfp->sp, *bp = cfp->bp, *ep = cfp->ep;
|
||||
VALUE *p, *st, *t;
|
||||
|
||||
fprintf(stderr, "-- stack frame ------------\n");
|
||||
|
@ -166,10 +158,8 @@ rb_vmdebug_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||
fprintf(stderr, " (= %ld)", (long)((VALUE *)GC_GUARDED_PTR_REF(t) - th->stack));
|
||||
}
|
||||
|
||||
if (p == lfp)
|
||||
fprintf(stderr, " <- lfp");
|
||||
if (p == dfp)
|
||||
fprintf(stderr, " <- dfp");
|
||||
if (p == ep)
|
||||
fprintf(stderr, " <- ep");
|
||||
if (p == bp)
|
||||
fprintf(stderr, " <- bp"); /* should not be */
|
||||
|
||||
|
@ -194,7 +184,7 @@ rb_vmdebug_stack_dump_raw_current(void)
|
|||
}
|
||||
|
||||
void
|
||||
rb_vmdebug_env_dump_raw(rb_env_t *env, VALUE *lfp, VALUE *dfp)
|
||||
rb_vmdebug_env_dump_raw(rb_env_t *env, VALUE *ep)
|
||||
{
|
||||
int i;
|
||||
fprintf(stderr, "-- env --------------------\n");
|
||||
|
@ -204,10 +194,8 @@ rb_vmdebug_env_dump_raw(rb_env_t *env, VALUE *lfp, VALUE *dfp)
|
|||
for (i = 0; i < env->env_size; i++) {
|
||||
fprintf(stderr, "%04d: %08"PRIxVALUE" (%p)", -env->local_size + i, env->env[i],
|
||||
(void *)&env->env[i]);
|
||||
if (&env->env[i] == lfp)
|
||||
fprintf(stderr, " <- lfp");
|
||||
if (&env->env[i] == dfp)
|
||||
fprintf(stderr, " <- dfp");
|
||||
if (&env->env[i] == ep)
|
||||
fprintf(stderr, " <- ep");
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
|
@ -232,7 +220,7 @@ rb_vmdebug_proc_dump_raw(rb_proc_t *proc)
|
|||
fprintf(stderr, "-- proc -------------------\n");
|
||||
fprintf(stderr, "self: %s\n", selfstr);
|
||||
GetEnvPtr(proc->envval, env);
|
||||
rb_vmdebug_env_dump_raw(env, proc->block.lfp, proc->block.dfp);
|
||||
rb_vmdebug_env_dump_raw(env, proc->block.ep);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -251,8 +239,7 @@ vm_stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||
|
||||
VALUE rstr;
|
||||
VALUE *sp = cfp->sp;
|
||||
VALUE *lfp = cfp->lfp;
|
||||
VALUE *dfp = cfp->dfp;
|
||||
VALUE *ep = cfp->ep;
|
||||
|
||||
int argc = 0, local_size = 0;
|
||||
const char *name;
|
||||
|
@ -287,14 +274,11 @@ vm_stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||
VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_IFUNC ||
|
||||
VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_EVAL) {
|
||||
|
||||
VALUE *ptr = dfp - local_size;
|
||||
VALUE *ptr = ep - local_size;
|
||||
|
||||
vm_stack_dump_each(th, cfp + 1);
|
||||
control_frame_dump(th, cfp);
|
||||
|
||||
if (lfp != dfp) {
|
||||
local_size++;
|
||||
}
|
||||
for (i = 0; i < argc; i++) {
|
||||
rstr = rb_inspect(*ptr);
|
||||
fprintf(stderr, " arg %2d: %8s (%p)\n", i, StringValueCStr(rstr),
|
||||
|
@ -337,22 +321,20 @@ rb_vmdebug_debug_print_register(rb_thread_t *th)
|
|||
{
|
||||
rb_control_frame_t *cfp = th->cfp;
|
||||
ptrdiff_t pc = -1;
|
||||
ptrdiff_t lfp = cfp->lfp - th->stack;
|
||||
ptrdiff_t dfp = cfp->dfp - th->stack;
|
||||
ptrdiff_t ep = cfp->ep - th->stack;
|
||||
ptrdiff_t cfpi;
|
||||
|
||||
if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
||||
pc = cfp->pc - cfp->iseq->iseq_encoded;
|
||||
}
|
||||
|
||||
if (lfp < 0 || (size_t)lfp > th->stack_size)
|
||||
lfp = -1;
|
||||
if (dfp < 0 || (size_t)dfp > th->stack_size)
|
||||
dfp = -1;
|
||||
if (ep < 0 || (size_t)ep > th->stack_size) {
|
||||
ep = -1;
|
||||
}
|
||||
|
||||
cfpi = ((rb_control_frame_t *)(th->stack + th->stack_size)) - cfp;
|
||||
fprintf(stderr, " [PC] %04"PRIdPTRDIFF", [SP] %04"PRIdPTRDIFF", [LFP] %04"PRIdPTRDIFF", [DFP] %04"PRIdPTRDIFF", [CFP] %04"PRIdPTRDIFF"\n",
|
||||
pc, (cfp->sp - th->stack), lfp, dfp, cfpi);
|
||||
fprintf(stderr, " [PC] %04"PRIdPTRDIFF", [SP] %04"PRIdPTRDIFF", [EP] %04"PRIdPTRDIFF", [CFP] %04"PRIdPTRDIFF"\n",
|
||||
pc, (cfp->sp - th->stack), ep, cfpi);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -371,8 +353,13 @@ rb_vmdebug_debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||
if (iseq != 0 && VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_FINISH) {
|
||||
VALUE *seq = iseq->iseq;
|
||||
ptrdiff_t pc = cfp->pc - iseq->iseq_encoded;
|
||||
int i;
|
||||
|
||||
printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(th, cfp));
|
||||
for (i=0; i<(int)VM_CFP_CNT(th, cfp); i++) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("| ");
|
||||
/* printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(th, cfp)); */
|
||||
if (pc >= 0) {
|
||||
rb_iseq_disasm_insn(0, seq, (size_t)pc, iseq, 0);
|
||||
}
|
||||
|
@ -518,11 +505,10 @@ vm_analysis_register(int reg, int isset)
|
|||
static const char regstrs[][5] = {
|
||||
"pc", /* 0 */
|
||||
"sp", /* 1 */
|
||||
"cfp", /* 2 */
|
||||
"lfp", /* 3 */
|
||||
"dfp", /* 4 */
|
||||
"self", /* 5 */
|
||||
"iseq", /* 6 */
|
||||
"ep", /* 2 */
|
||||
"cfp", /* 3 */
|
||||
"self", /* 4 */
|
||||
"iseq", /* 5 */
|
||||
};
|
||||
static const char getsetstr[][4] = {
|
||||
"get",
|
||||
|
@ -568,7 +554,7 @@ rb_vmdebug_thread_dump_state(VALUE self)
|
|||
|
||||
fprintf(stderr, "Thread state dump:\n");
|
||||
fprintf(stderr, "pc : %p, sp : %p\n", (void *)cfp->pc, (void *)cfp->sp);
|
||||
fprintf(stderr, "cfp: %p, lfp: %p, dfp: %p\n", (void *)cfp, (void *)cfp->lfp, (void *)cfp->dfp);
|
||||
fprintf(stderr, "cfp: %p, ep : %p\n", (void *)cfp, (void *)cfp->ep);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
|
30
vm_eval.c
30
vm_eval.c
|
@ -74,7 +74,7 @@ vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv,
|
|||
rb_control_frame_t *reg_cfp = th->cfp;
|
||||
rb_control_frame_t *cfp =
|
||||
vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
|
||||
recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
|
||||
recv, VM_ENVVAL_BLOCK_PTR(blockptr), 0, reg_cfp->sp, 1);
|
||||
|
||||
cfp->me = me;
|
||||
val = call_cfunc(def->body.cfunc.func, recv, def->body.cfunc.argc, argc, argv);
|
||||
|
@ -896,7 +896,7 @@ rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
|
|||
blockptr->proc = 0;
|
||||
}
|
||||
else {
|
||||
blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
|
||||
blockptr = VM_CF_BLOCK_PTR(th->cfp);
|
||||
}
|
||||
th->passed_block = blockptr;
|
||||
}
|
||||
|
@ -905,10 +905,10 @@ rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
|
|||
else {
|
||||
VALUE err = th->errinfo;
|
||||
if (state == TAG_BREAK) {
|
||||
VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
|
||||
VALUE *cdfp = cfp->dfp;
|
||||
VALUE *escape_ep = GET_THROWOBJ_CATCH_POINT(err);
|
||||
VALUE *cep = cfp->ep;
|
||||
|
||||
if (cdfp == escape_dfp) {
|
||||
if (cep == escape_ep) {
|
||||
state = 0;
|
||||
th->state = 0;
|
||||
th->errinfo = Qnil;
|
||||
|
@ -932,10 +932,10 @@ rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
|
|||
}
|
||||
}
|
||||
else if (state == TAG_RETRY) {
|
||||
VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
|
||||
VALUE *cdfp = cfp->dfp;
|
||||
VALUE *escape_ep = GET_THROWOBJ_CATCH_POINT(err);
|
||||
VALUE *cep = cfp->ep;
|
||||
|
||||
if (cdfp == escape_dfp) {
|
||||
if (cep == escape_ep) {
|
||||
state = 0;
|
||||
th->state = 0;
|
||||
th->errinfo = Qnil;
|
||||
|
@ -1247,10 +1247,10 @@ yield_under(VALUE under, VALUE self, VALUE values)
|
|||
rb_block_t block, *blockptr;
|
||||
NODE *cref;
|
||||
|
||||
if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
|
||||
if ((blockptr = VM_CF_BLOCK_PTR(th->cfp)) != 0) {
|
||||
block = *blockptr;
|
||||
block.self = self;
|
||||
th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
|
||||
VM_CF_LEP(th->cfp)[0] = VM_ENVVAL_BLOCK_PTR(&block);
|
||||
}
|
||||
cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
|
||||
cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
|
||||
|
@ -1611,15 +1611,15 @@ rb_f_local_variables(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (cfp->lfp != cfp->dfp) {
|
||||
if (!VM_EP_LEP_P(cfp->ep)) {
|
||||
/* block */
|
||||
VALUE *dfp = GC_GUARDED_PTR_REF(cfp->dfp[0]);
|
||||
VALUE *ep = VM_CF_PREV_EP(cfp);
|
||||
|
||||
if (vm_collect_local_variables_in_heap(th, dfp, ary)) {
|
||||
if (vm_collect_local_variables_in_heap(th, ep, ary)) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
while (cfp->dfp != dfp) {
|
||||
while (cfp->ep != ep) {
|
||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||
}
|
||||
}
|
||||
|
@ -1660,7 +1660,7 @@ rb_f_block_given_p(void)
|
|||
rb_control_frame_t *cfp = th->cfp;
|
||||
cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
|
||||
|
||||
if (cfp != 0 && RUBY_VM_GET_BLOCK_PTR(cfp)) {
|
||||
if (cfp != 0 && VM_CF_BLOCK_PTR(cfp)) {
|
||||
return Qtrue;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -38,7 +38,7 @@ typedef rb_iseq_t *ISEQ;
|
|||
#if VMDEBUG > 0
|
||||
#define debugs printf
|
||||
#define DEBUG_ENTER_INSN(insn) \
|
||||
debug_print_pre(th, GET_CFP());
|
||||
rb_vmdebug_debug_print_pre(th, GET_CFP());
|
||||
|
||||
#if OPT_STACK_CACHING
|
||||
#define SC_REGS() , reg_a, reg_b
|
||||
|
@ -47,7 +47,7 @@ typedef rb_iseq_t *ISEQ;
|
|||
#endif
|
||||
|
||||
#define DEBUG_END_INSN() \
|
||||
debug_print_post(th, GET_CFP() SC_REGS());
|
||||
rb_vmdebug_debug_print_post(th, GET_CFP() SC_REGS());
|
||||
|
||||
#else
|
||||
|
||||
|
|
196
vm_insnhelper.c
196
vm_insnhelper.c
|
@ -23,53 +23,47 @@
|
|||
static rb_control_frame_t *vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
|
||||
|
||||
static inline rb_control_frame_t *
|
||||
vm_push_frame(rb_thread_t * th, const rb_iseq_t * iseq,
|
||||
VALUE type, VALUE self, VALUE specval,
|
||||
const VALUE *pc, VALUE *sp, VALUE *lfp,
|
||||
vm_push_frame(rb_thread_t *th,
|
||||
const rb_iseq_t *iseq,
|
||||
VALUE type,
|
||||
VALUE self,
|
||||
VALUE specval,
|
||||
const VALUE *pc,
|
||||
VALUE *sp,
|
||||
int local_size)
|
||||
{
|
||||
rb_control_frame_t * const cfp = th->cfp - 1;
|
||||
rb_control_frame_t *const cfp = th->cfp - 1;
|
||||
int i;
|
||||
|
||||
/* check stack overflow */
|
||||
if ((void *)(sp + local_size) >= (void *)cfp) {
|
||||
rb_exc_raise(sysstack_error);
|
||||
}
|
||||
th->cfp = cfp;
|
||||
|
||||
/* setup vm value stack */
|
||||
|
||||
/* nil initialize */
|
||||
/* initialize local variables */
|
||||
for (i=0; i < local_size; i++) {
|
||||
*sp = Qnil;
|
||||
sp++;
|
||||
*sp++ = Qnil;
|
||||
}
|
||||
|
||||
/* set special val */
|
||||
*sp = GC_GUARDED_PTR(specval);
|
||||
|
||||
if (lfp == 0) {
|
||||
lfp = sp;
|
||||
}
|
||||
*sp = specval;
|
||||
|
||||
/* setup vm control frame stack */
|
||||
|
||||
cfp->pc = (VALUE *)pc;
|
||||
cfp->sp = sp + 1;
|
||||
cfp->bp = sp + 1;
|
||||
cfp->ep = sp;
|
||||
cfp->iseq = (rb_iseq_t *) iseq;
|
||||
cfp->flag = type;
|
||||
cfp->self = self;
|
||||
cfp->lfp = lfp;
|
||||
cfp->dfp = sp;
|
||||
cfp->block_iseq = 0;
|
||||
cfp->proc = 0;
|
||||
cfp->me = 0;
|
||||
|
||||
#define COLLECT_PROFILE 0
|
||||
#if COLLECT_PROFILE
|
||||
cfp->prof_time_self = clock();
|
||||
cfp->prof_time_chld = 0;
|
||||
#endif
|
||||
|
||||
if (VMDEBUG == 2) {
|
||||
SDR();
|
||||
}
|
||||
|
@ -80,23 +74,6 @@ vm_push_frame(rb_thread_t * th, const rb_iseq_t * iseq,
|
|||
static inline void
|
||||
vm_pop_frame(rb_thread_t *th)
|
||||
{
|
||||
#if COLLECT_PROFILE
|
||||
rb_control_frame_t *cfp = th->cfp;
|
||||
|
||||
if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
||||
VALUE current_time = clock();
|
||||
rb_control_frame_t *cfp = th->cfp;
|
||||
cfp->prof_time_self = current_time - cfp->prof_time_self;
|
||||
(cfp+1)->prof_time_chld += cfp->prof_time_self;
|
||||
|
||||
cfp->iseq->profile.count++;
|
||||
cfp->iseq->profile.time_cumu = cfp->prof_time_self;
|
||||
cfp->iseq->profile.time_self = cfp->prof_time_self - cfp->prof_time_chld;
|
||||
}
|
||||
else if (0 /* c method? */) {
|
||||
|
||||
}
|
||||
#endif
|
||||
th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
|
||||
|
||||
if (VMDEBUG == 2) {
|
||||
|
@ -445,8 +422,9 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|||
|
||||
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass);
|
||||
|
||||
cfp = vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
|
||||
recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
|
||||
cfp = vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv,
|
||||
VM_ENVVAL_BLOCK_PTR(blockptr), 0, th->cfp->sp, 1);
|
||||
|
||||
cfp->me = me;
|
||||
reg_cfp->sp -= num + 1;
|
||||
|
||||
|
@ -528,9 +506,9 @@ vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
|
|||
*sp++ = Qnil;
|
||||
}
|
||||
|
||||
vm_push_frame(th, iseq,
|
||||
VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
|
||||
iseq->iseq_encoded + opt_pc, sp, 0, 0);
|
||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, recv,
|
||||
VM_ENVVAL_BLOCK_PTR(blockptr),
|
||||
iseq->iseq_encoded + opt_pc, sp, 0);
|
||||
|
||||
cfp->sp = rsp - 1 /* recv */;
|
||||
}
|
||||
|
@ -551,9 +529,9 @@ vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
|
|||
*sp++ = Qnil;
|
||||
}
|
||||
|
||||
vm_push_frame(th, iseq,
|
||||
VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
|
||||
iseq->iseq_encoded + opt_pc, sp, 0, 0);
|
||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, recv,
|
||||
VM_ENVVAL_BLOCK_PTR(blockptr),
|
||||
iseq->iseq_encoded + opt_pc, sp, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -757,6 +735,7 @@ vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block,
|
|||
NODE *ifunc = (NODE *) block->iseq;
|
||||
VALUE val, arg, blockarg;
|
||||
int lambda = block_proc_is_lambda(block->proc);
|
||||
rb_control_frame_t *cfp;
|
||||
|
||||
if (lambda) {
|
||||
arg = rb_ary_new4(argc, argv);
|
||||
|
@ -780,12 +759,11 @@ vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block,
|
|||
blockarg = Qnil;
|
||||
}
|
||||
|
||||
vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC,
|
||||
self, (VALUE)block->dfp,
|
||||
0, th->cfp->sp, block->lfp, 1);
|
||||
cfp = vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC, self,
|
||||
VM_ENVVAL_PREV_EP_PTR(block->ep), 0, th->cfp->sp, 1);
|
||||
|
||||
if (blockargptr) {
|
||||
th->cfp->lfp[0] = GC_GUARDED_PTR((VALUE)blockargptr);
|
||||
VM_CF_LEP(cfp)[0] = VM_ENVVAL_BLOCK_PTR(blockargptr);
|
||||
}
|
||||
val = (*ifunc->nd_cfnc) (arg, ifunc->nd_tval, argc, argv, blockarg);
|
||||
|
||||
|
@ -976,7 +954,7 @@ vm_yield_setup_args(rb_thread_t * const th, const rb_iseq_t *iseq,
|
|||
static VALUE
|
||||
vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_num_t flag)
|
||||
{
|
||||
const rb_block_t *block = GET_BLOCK_PTR();
|
||||
const rb_block_t *block = VM_CF_BLOCK_PTR(reg_cfp);
|
||||
rb_iseq_t *iseq;
|
||||
int argc = (int)num;
|
||||
VALUE type = GET_ISEQ()->local_iseq->type;
|
||||
|
@ -998,9 +976,10 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n
|
|||
opt_pc = vm_yield_setup_args(th, iseq, argc, rsp, 0,
|
||||
block_proc_is_lambda(block->proc));
|
||||
|
||||
vm_push_frame(th, iseq,
|
||||
VM_FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp,
|
||||
iseq->iseq_encoded + opt_pc, rsp + arg_size, block->lfp,
|
||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_BLOCK, block->self,
|
||||
VM_ENVVAL_PREV_EP_PTR(block->ep),
|
||||
iseq->iseq_encoded + opt_pc,
|
||||
rsp + arg_size,
|
||||
iseq->local_size - arg_size);
|
||||
|
||||
return Qundef;
|
||||
|
@ -1015,15 +994,15 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n
|
|||
/* svar */
|
||||
|
||||
static inline NODE *
|
||||
lfp_svar_place(rb_thread_t *th, VALUE *lfp)
|
||||
lep_svar_place(rb_thread_t *th, VALUE *lep)
|
||||
{
|
||||
VALUE *svar;
|
||||
|
||||
if (lfp && th->local_lfp != lfp) {
|
||||
svar = &lfp[-1];
|
||||
if (lep && th->root_lep != lep) {
|
||||
svar = &lep[-1];
|
||||
}
|
||||
else {
|
||||
svar = &th->local_svar;
|
||||
svar = &th->root_svar;
|
||||
}
|
||||
if (NIL_P(*svar)) {
|
||||
*svar = (VALUE)NEW_IF(Qnil, Qnil, Qnil);
|
||||
|
@ -1032,9 +1011,9 @@ lfp_svar_place(rb_thread_t *th, VALUE *lfp)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
lfp_svar_get(rb_thread_t *th, VALUE *lfp, VALUE key)
|
||||
lep_svar_get(rb_thread_t *th, VALUE *lep, VALUE key)
|
||||
{
|
||||
NODE *svar = lfp_svar_place(th, lfp);
|
||||
NODE *svar = lep_svar_place(th, lep);
|
||||
|
||||
switch (key) {
|
||||
case 0:
|
||||
|
@ -1055,9 +1034,9 @@ lfp_svar_get(rb_thread_t *th, VALUE *lfp, VALUE key)
|
|||
}
|
||||
|
||||
static void
|
||||
lfp_svar_set(rb_thread_t *th, VALUE *lfp, VALUE key, VALUE val)
|
||||
lep_svar_set(rb_thread_t *th, VALUE *lep, VALUE key, VALUE val)
|
||||
{
|
||||
NODE *svar = lfp_svar_place(th, lfp);
|
||||
NODE *svar = lep_svar_place(th, lep);
|
||||
|
||||
switch (key) {
|
||||
case 0:
|
||||
|
@ -1078,7 +1057,7 @@ lfp_svar_set(rb_thread_t *th, VALUE *lfp, VALUE key, VALUE val)
|
|||
}
|
||||
|
||||
static inline VALUE
|
||||
vm_getspecial(rb_thread_t *th, VALUE *lfp, VALUE key, rb_num_t type)
|
||||
vm_getspecial(rb_thread_t *th, VALUE *lep, VALUE key, rb_num_t type)
|
||||
{
|
||||
VALUE val;
|
||||
|
||||
|
@ -1087,10 +1066,10 @@ vm_getspecial(rb_thread_t *th, VALUE *lfp, VALUE key, rb_num_t type)
|
|||
if (FIXNUM_P(key)) {
|
||||
k = FIX2INT(key);
|
||||
}
|
||||
val = lfp_svar_get(th, lfp, k);
|
||||
val = lep_svar_get(th, lep, k);
|
||||
}
|
||||
else {
|
||||
VALUE backref = lfp_svar_get(th, lfp, 1);
|
||||
VALUE backref = lep_svar_get(th, lep, 1);
|
||||
|
||||
if (type & 0x01) {
|
||||
switch (type >> 1) {
|
||||
|
@ -1118,24 +1097,24 @@ vm_getspecial(rb_thread_t *th, VALUE *lfp, VALUE key, rb_num_t type)
|
|||
}
|
||||
|
||||
static NODE *
|
||||
vm_get_cref0(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
|
||||
vm_get_cref0(const rb_iseq_t *iseq, const VALUE *ep)
|
||||
{
|
||||
while (1) {
|
||||
if (lfp == dfp) {
|
||||
if (VM_EP_LEP_P(ep)) {
|
||||
if (!RUBY_VM_NORMAL_ISEQ_P(iseq)) return NULL;
|
||||
return iseq->cref_stack;
|
||||
}
|
||||
else if (dfp[-1] != Qnil) {
|
||||
return (NODE *)dfp[-1];
|
||||
else if (ep[-1] != Qnil) {
|
||||
return (NODE *)ep[-1];
|
||||
}
|
||||
dfp = GET_PREV_DFP(dfp);
|
||||
ep = VM_EP_PREV_EP(ep);
|
||||
}
|
||||
}
|
||||
|
||||
static NODE *
|
||||
vm_get_cref(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
|
||||
vm_get_cref(const rb_iseq_t *iseq, const VALUE *ep)
|
||||
{
|
||||
NODE *cref = vm_get_cref0(iseq, lfp, dfp);
|
||||
NODE *cref = vm_get_cref0(iseq, ep);
|
||||
|
||||
if (cref == 0) {
|
||||
rb_bug("vm_get_cref: unreachable");
|
||||
|
@ -1151,19 +1130,19 @@ vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
|
|||
cref->nd_visi = noex;
|
||||
|
||||
if (blockptr) {
|
||||
cref->nd_next = vm_get_cref0(blockptr->iseq, blockptr->lfp, blockptr->dfp);
|
||||
cref->nd_next = vm_get_cref0(blockptr->iseq, blockptr->ep);
|
||||
}
|
||||
else if (cfp) {
|
||||
cref->nd_next = vm_get_cref0(cfp->iseq, cfp->lfp, cfp->dfp);
|
||||
cref->nd_next = vm_get_cref0(cfp->iseq, cfp->ep);
|
||||
}
|
||||
|
||||
return cref;
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
vm_get_cbase(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
|
||||
vm_get_cbase(const rb_iseq_t *iseq, const VALUE *ep)
|
||||
{
|
||||
NODE *cref = vm_get_cref(iseq, lfp, dfp);
|
||||
NODE *cref = vm_get_cref(iseq, ep);
|
||||
VALUE klass = Qundef;
|
||||
|
||||
while (cref) {
|
||||
|
@ -1177,9 +1156,9 @@ vm_get_cbase(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
|
|||
}
|
||||
|
||||
static inline VALUE
|
||||
vm_get_const_base(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
|
||||
vm_get_const_base(const rb_iseq_t *iseq, const VALUE *ep)
|
||||
{
|
||||
NODE *cref = vm_get_cref(iseq, lfp, dfp);
|
||||
NODE *cref = vm_get_cref(iseq, ep);
|
||||
VALUE klass = Qundef;
|
||||
|
||||
while (cref) {
|
||||
|
@ -1216,7 +1195,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
|
|||
|
||||
if (orig_klass == Qnil) {
|
||||
/* in current lexical scope */
|
||||
const NODE *root_cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
|
||||
const NODE *root_cref = vm_get_cref(iseq, th->cfp->ep);
|
||||
const NODE *cref;
|
||||
VALUE klass = orig_klass;
|
||||
|
||||
|
@ -1494,14 +1473,14 @@ vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *iseq,
|
|||
|
||||
while (lcfp->iseq != iseq) {
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
VALUE *tdfp = GET_PREV_DFP(lcfp->dfp);
|
||||
VALUE *tep = VM_EP_PREV_EP(lcfp->ep);
|
||||
while (1) {
|
||||
lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp);
|
||||
if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, lcfp)) {
|
||||
rb_raise(rb_eNoMethodError,
|
||||
"super called outside of method");
|
||||
}
|
||||
if (lcfp->dfp == tdfp) {
|
||||
if (lcfp->ep == tep) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1539,7 +1518,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|||
else {
|
||||
if (state == TAG_BREAK) {
|
||||
rb_control_frame_t *cfp = GET_CFP();
|
||||
VALUE *dfp = GET_DFP();
|
||||
VALUE *ep = GET_EP();
|
||||
int is_orphan = 1;
|
||||
rb_iseq_t *base_iseq = GET_ISEQ();
|
||||
|
||||
|
@ -1547,14 +1526,14 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|||
if (cfp->iseq->type != ISEQ_TYPE_BLOCK) {
|
||||
if (cfp->iseq->type == ISEQ_TYPE_CLASS) {
|
||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||
dfp = cfp->dfp;
|
||||
ep = cfp->ep;
|
||||
goto search_parent;
|
||||
}
|
||||
dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp);
|
||||
ep = VM_EP_PREV_EP(ep);
|
||||
base_iseq = base_iseq->parent_iseq;
|
||||
|
||||
while ((VALUE *) cfp < th->stack + th->stack_size) {
|
||||
if (cfp->dfp == dfp) {
|
||||
if (cfp->ep == ep) {
|
||||
goto search_parent;
|
||||
}
|
||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||
|
@ -1565,14 +1544,14 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|||
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
|
||||
/* lambda{... break ...} */
|
||||
is_orphan = 0;
|
||||
pt = cfp->dfp;
|
||||
pt = cfp->ep;
|
||||
state = TAG_RETURN;
|
||||
}
|
||||
else {
|
||||
dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp);
|
||||
ep = VM_EP_PREV_EP(ep);
|
||||
|
||||
while ((VALUE *)cfp < th->stack + th->stack_size) {
|
||||
if (cfp->dfp == dfp) {
|
||||
if (cfp->ep == ep) {
|
||||
VALUE epc = cfp->pc - cfp->iseq->iseq_encoded;
|
||||
rb_iseq_t *iseq = cfp->iseq;
|
||||
int i;
|
||||
|
@ -1593,7 +1572,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|||
break;
|
||||
|
||||
found:
|
||||
pt = dfp;
|
||||
pt = ep;
|
||||
is_orphan = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -1607,50 +1586,53 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|||
}
|
||||
else if (state == TAG_RETRY) {
|
||||
rb_num_t i;
|
||||
pt = GC_GUARDED_PTR_REF((VALUE *) * GET_DFP());
|
||||
pt = VM_EP_PREV_EP(GET_EP());
|
||||
for (i = 0; i < level; i++) {
|
||||
pt = GC_GUARDED_PTR_REF((VALUE *) * pt);
|
||||
}
|
||||
}
|
||||
else if (state == TAG_RETURN) {
|
||||
rb_control_frame_t *cfp = GET_CFP();
|
||||
VALUE *dfp = GET_DFP();
|
||||
VALUE *lfp = GET_LFP();
|
||||
VALUE *ep = GET_EP();
|
||||
VALUE *target_lep = VM_CF_LEP(cfp);
|
||||
int in_class_frame = 0;
|
||||
|
||||
/* check orphan and get dfp */
|
||||
while ((VALUE *) cfp < th->stack + th->stack_size) {
|
||||
if (!lfp) {
|
||||
lfp = cfp->lfp;
|
||||
}
|
||||
if (cfp->dfp == lfp && cfp->iseq->type == ISEQ_TYPE_CLASS) {
|
||||
in_class_frame = 1;
|
||||
lfp = 0;
|
||||
VALUE *lep = VM_CF_LEP(cfp);
|
||||
|
||||
if (!target_lep) {
|
||||
target_lep = lep;
|
||||
}
|
||||
|
||||
if (cfp->lfp == lfp) {
|
||||
if (lep == target_lep && cfp->iseq->type == ISEQ_TYPE_CLASS) {
|
||||
in_class_frame = 1;
|
||||
target_lep = 0;
|
||||
}
|
||||
|
||||
if (lep == target_lep) {
|
||||
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
|
||||
VALUE *tdfp = dfp;
|
||||
VALUE *tep = ep;
|
||||
|
||||
if (in_class_frame) {
|
||||
/* lambda {class A; ... return ...; end} */
|
||||
dfp = cfp->dfp;
|
||||
ep = cfp->ep;
|
||||
goto valid_return;
|
||||
}
|
||||
|
||||
while (lfp != tdfp) {
|
||||
if (cfp->dfp == tdfp) {
|
||||
while (target_lep != tep) {
|
||||
if (cfp->ep == tep) {
|
||||
/* in lambda */
|
||||
dfp = cfp->dfp;
|
||||
ep = cfp->ep;
|
||||
goto valid_return;
|
||||
}
|
||||
tdfp = GC_GUARDED_PTR_REF((VALUE *)*tdfp);
|
||||
tep = VM_EP_PREV_EP(tep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cfp->dfp == lfp && cfp->iseq->type == ISEQ_TYPE_METHOD) {
|
||||
dfp = lfp;
|
||||
if (cfp->ep == target_lep && cfp->iseq->type == ISEQ_TYPE_METHOD) {
|
||||
ep = target_lep;
|
||||
goto valid_return;
|
||||
}
|
||||
|
||||
|
@ -1660,7 +1642,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|||
rb_vm_localjump_error("unexpected return", throwobj, TAG_RETURN);
|
||||
|
||||
valid_return:
|
||||
pt = dfp;
|
||||
pt = ep;
|
||||
}
|
||||
else {
|
||||
rb_bug("isns(throw): unsupport throw type");
|
||||
|
|
|
@ -81,8 +81,7 @@ extern VALUE ruby_vm_const_missing_count;
|
|||
#define REG_CFP (reg_cfp)
|
||||
#define REG_PC (REG_CFP->pc)
|
||||
#define REG_SP (REG_CFP->sp)
|
||||
#define REG_LFP (REG_CFP->lfp)
|
||||
#define REG_DFP (REG_CFP->dfp)
|
||||
#define REG_EP (REG_CFP->ep)
|
||||
|
||||
#define RESTORE_REGS() do { \
|
||||
REG_CFP = th->cfp; \
|
||||
|
@ -91,16 +90,29 @@ extern VALUE ruby_vm_const_missing_count;
|
|||
#define REG_A reg_a
|
||||
#define REG_B reg_b
|
||||
|
||||
enum vm_regan_regtype {
|
||||
VM_REGAN_PC = 0,
|
||||
VM_REGAN_SP = 1,
|
||||
VM_REGAN_EP = 2,
|
||||
VM_REGAN_CFP = 3,
|
||||
VM_REGAN_SELF = 4,
|
||||
VM_REGAN_ISEQ = 5,
|
||||
};
|
||||
enum vm_regan_acttype {
|
||||
VM_REGAN_ACT_GET = 0,
|
||||
VM_REGAN_ACT_SET = 1,
|
||||
};
|
||||
|
||||
#ifdef COLLECT_USAGE_ANALYSIS
|
||||
#define USAGE_ANALYSIS_REGISTER_HELPER(a, b, v) \
|
||||
(USAGE_ANALYSIS_REGISTER((a), (b)), (v))
|
||||
(USAGE_ANALYSIS_REGISTER((VM_REGAN_#a), (VM_REGAN_ACT_#b)), (v))
|
||||
#else
|
||||
#define USAGE_ANALYSIS_REGISTER_HELPER(a, b, v) (v)
|
||||
#endif
|
||||
|
||||
/* PC */
|
||||
#define GET_PC() (USAGE_ANALYSIS_REGISTER_HELPER(0, 0, REG_PC))
|
||||
#define SET_PC(x) (REG_PC = (USAGE_ANALYSIS_REGISTER_HELPER(0, 1, (x))))
|
||||
#define GET_PC() (USAGE_ANALYSIS_REGISTER_HELPER(PC, GET, REG_PC))
|
||||
#define SET_PC(x) (REG_PC = (USAGE_ANALYSIS_REGISTER_HELPER(PC, SET, (x))))
|
||||
#define GET_CURRENT_INSN() (*GET_PC())
|
||||
#define GET_OPERAND(n) (GET_PC()[(n)])
|
||||
#define ADD_PC(n) (SET_PC(REG_PC + (n)))
|
||||
|
@ -108,18 +120,17 @@ extern VALUE ruby_vm_const_missing_count;
|
|||
#define GET_PC_COUNT() (REG_PC - GET_ISEQ()->iseq_encoded)
|
||||
#define JUMP(dst) (REG_PC += (dst))
|
||||
|
||||
/* FP */
|
||||
#define GET_CFP() (USAGE_ANALYSIS_REGISTER_HELPER(2, 0, REG_CFP))
|
||||
#define GET_LFP() (USAGE_ANALYSIS_REGISTER_HELPER(3, 0, REG_LFP))
|
||||
#define SET_LFP(x) (REG_LFP = (USAGE_ANALYSIS_REGISTER_HELPER(3, 1, (x))))
|
||||
#define GET_DFP() (USAGE_ANALYSIS_REGISTER_HELPER(4, 0, REG_DFP))
|
||||
#define SET_DFP(x) (REG_DFP = (USAGE_ANALYSIS_REGISTER_HELPER(4, 1, (x))))
|
||||
/* frame pointer, environment pointer */
|
||||
#define GET_CFP() (USAGE_ANALYSIS_REGISTER_HELPER(CFP, GET, REG_CFP))
|
||||
#define GET_EP() (USAGE_ANALYSIS_REGISTER_HELPER(EP, GET, REG_EP))
|
||||
#define SET_EP(x) (REG_EP = (USAGE_ANALYSIS_REGISTER_HELPER(EP, SET, (x))))
|
||||
#define GET_LEP() (VM_EP_LEP(GET_EP()))
|
||||
|
||||
/* SP */
|
||||
#define GET_SP() (USAGE_ANALYSIS_REGISTER_HELPER(1, 0, REG_SP))
|
||||
#define SET_SP(x) (REG_SP = (USAGE_ANALYSIS_REGISTER_HELPER(1, 1, (x))))
|
||||
#define INC_SP(x) (REG_SP += (USAGE_ANALYSIS_REGISTER_HELPER(1, 1, (x))))
|
||||
#define DEC_SP(x) (REG_SP -= (USAGE_ANALYSIS_REGISTER_HELPER(1, 1, (x))))
|
||||
#define GET_SP() (USAGE_ANALYSIS_REGISTER_HELPER(SP, GET, REG_SP))
|
||||
#define SET_SP(x) (REG_SP = (USAGE_ANALYSIS_REGISTER_HELPER(SP, SET, (x))))
|
||||
#define INC_SP(x) (REG_SP += (USAGE_ANALYSIS_REGISTER_HELPER(SP, SET, (x))))
|
||||
#define DEC_SP(x) (REG_SP -= (USAGE_ANALYSIS_REGISTER_HELPER(SP, SET, (x))))
|
||||
#define SET_SV(x) (*GET_SP() = (x))
|
||||
/* set current stack value as x */
|
||||
|
||||
|
@ -132,7 +143,7 @@ extern VALUE ruby_vm_const_missing_count;
|
|||
/* deal with variables */
|
||||
/**********************************************************/
|
||||
|
||||
#define GET_PREV_DFP(dfp) ((VALUE *)((dfp)[0] & ~0x03))
|
||||
#define GET_PREV_EP(ep) ((VALUE *)((ep)[0] & ~0x03))
|
||||
|
||||
#define GET_GLOBAL(entry) rb_gvar_get((struct rb_global_entry*)(entry))
|
||||
#define SET_GLOBAL(entry, val) rb_gvar_set((struct rb_global_entry*)(entry), (val))
|
||||
|
@ -170,7 +181,7 @@ extern VALUE ruby_vm_const_missing_count;
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
#define GET_BLOCK_PTR() ((rb_block_t *)(GC_GUARDED_PTR_REF(GET_LFP()[0])))
|
||||
#define GET_BLOCK_PTR() ((rb_block_t *)(GC_GUARDED_PTR_REF(GET_LEP()[0])))
|
||||
|
||||
/**********************************************************/
|
||||
/* deal with control flow 3: exception */
|
||||
|
|
Loading…
Add table
Reference in a new issue