1
0
Fork 0
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:
ko1 2012-06-11 03:14:59 +00:00
parent 9b29e5f7e1
commit 0a71db8a74
14 changed files with 415 additions and 336 deletions

View file

@ -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
View file

@ -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
View file

@ -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);

View file

@ -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)

View file

@ -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
View file

@ -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);
}
/*

View file

@ -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
View file

@ -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;

View file

@ -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,

View file

@ -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;
}

View file

@ -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 {

View file

@ -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

View file

@ -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");

View file

@ -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 */