Bug #10689 » save-target-cfp-in-errinfo.patch
eval_intern.h | ||
---|---|---|
(RNODE((obj))->u3.value = (val))
|
||
#define GET_THROWOBJ_VAL(obj) ((VALUE)RNODE((obj))->u1.value)
|
||
#define GET_THROWOBJ_CATCH_POINT(obj) ((VALUE*)RNODE((obj))->u2.value)
|
||
#define GET_THROWOBJ_CATCH_POINT(obj) ((rb_control_frame_t*)RNODE((obj))->u2.value)
|
||
#define GET_THROWOBJ_STATE(obj) ((int)RNODE((obj))->u3.value)
|
||
#define SCOPE_TEST(f) (rb_vm_cref()->nd_visi & (f))
|
vm.c | ||
---|---|---|
return ep;
|
||
}
|
||
static inline rb_control_frame_t *
|
||
VM_EP_CF(rb_thread_t *th, VALUE *ep)
|
||
{
|
||
rb_control_frame_t *cfp = th->cfp;
|
||
if (!ep) {
|
||
return NULL;
|
||
}
|
||
while ((VALUE *) cfp < th->stack + th->stack_size) {
|
||
if (cfp->ep == ep) {
|
||
return cfp;
|
||
}
|
||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||
}
|
||
rb_bug("VM_EP_CF: no corresponding cfp");
|
||
}
|
||
VALUE *
|
||
rb_vm_ep_local_ep(VALUE *ep)
|
||
{
|
||
... | ... | |
return local_var_list_finish(&vars);
|
||
}
|
||
static void vm_rewrite_ep_in_errinfo(rb_thread_t *th);
|
||
static VALUE vm_make_proc_from_block(rb_thread_t *th, rb_block_t *block);
|
||
static VALUE vm_make_env_object(rb_thread_t * th, rb_control_frame_t *cfp, VALUE *blockprocptr);
|
||
... | ... | |
}
|
||
envval = vm_make_env_each(th, cfp, cfp->ep, lep);
|
||
vm_rewrite_ep_in_errinfo(th);
|
||
if (PROCDEBUG) {
|
||
check_env_value(envval);
|
||
... | ... | |
return envval;
|
||
}
|
||
static void
|
||
vm_rewrite_ep_in_errinfo(rb_thread_t *th)
|
||
{
|
||
rb_control_frame_t *cfp = th->cfp;
|
||
while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
|
||
/* 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->ep[-2]; /* #$! */
|
||
if (RB_TYPE_P(errinfo, T_NODE)) {
|
||
VALUE *escape_ep = GET_THROWOBJ_CATCH_POINT(errinfo);
|
||
if (! ENV_IN_HEAP_P(th, escape_ep)) {
|
||
VALUE epval = *escape_ep;
|
||
if (!SPECIAL_CONST_P(epval) && RBASIC(epval)->klass == rb_cEnv) {
|
||
rb_env_t *epenv;
|
||
GetEnvPtr(epval, epenv);
|
||
SET_THROWOBJ_CATCH_POINT(errinfo, (VALUE)(epenv->env + epenv->local_size));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||
}
|
||
}
|
||
void
|
||
rb_vm_stack_to_heap(rb_thread_t *th)
|
||
{
|
||
... | ... | |
static void
|
||
vm_iter_break(rb_thread_t *th, VALUE val)
|
||
{
|
||
rb_control_frame_t *cfp = th->cfp;
|
||
VALUE *ep = VM_CF_PREV_EP(cfp);
|
||
VALUE *ep = VM_CF_PREV_EP(th->cfp);
|
||
rb_control_frame_t *cfp = VM_EP_CF(th, ep);
|
||
th->state = TAG_BREAK;
|
||
th->errinfo = (VALUE)NEW_THROW_OBJECT(val, (VALUE)ep, TAG_BREAK);
|
||
th->errinfo = (VALUE)NEW_THROW_OBJECT(val, (VALUE)cfp, TAG_BREAK);
|
||
TH_JUMP_TAG(th, TAG_BREAK);
|
||
}
|
||
... | ... | |
VALUE catch_iseqval;
|
||
rb_control_frame_t *cfp;
|
||
VALUE type;
|
||
VALUE *escape_ep;
|
||
rb_control_frame_t *escape_cfp;
|
||
err = th->errinfo;
|
||
... | ... | |
cfp = th->cfp;
|
||
epc = cfp->pc - cfp->iseq->iseq_encoded;
|
||
escape_ep = NULL;
|
||
escape_cfp = NULL;
|
||
if (state == TAG_BREAK || state == TAG_RETURN) {
|
||
escape_ep = GET_THROWOBJ_CATCH_POINT(err);
|
||
escape_cfp = GET_THROWOBJ_CATCH_POINT(err);
|
||
if (cfp->ep == escape_ep) {
|
||
if (cfp == escape_cfp) {
|
||
if (state == TAG_RETURN) {
|
||
if (!VM_FRAME_TYPE_FINISH_P(cfp)) {
|
||
SET_THROWOBJ_CATCH_POINT(err, (VALUE)(cfp + 1)->ep);
|
||
SET_THROWOBJ_CATCH_POINT(err, (VALUE)(cfp + 1));
|
||
SET_THROWOBJ_STATE(err, state = TAG_BREAK);
|
||
}
|
||
else {
|
||
... | ... | |
break;
|
||
}
|
||
else if (entry->type == CATCH_TYPE_RETRY) {
|
||
VALUE *escape_ep;
|
||
escape_ep = GET_THROWOBJ_CATCH_POINT(err);
|
||
if (cfp->ep == escape_ep) {
|
||
rb_control_frame_t *escape_cfp;
|
||
escape_cfp = GET_THROWOBJ_CATCH_POINT(err);
|
||
if (cfp == escape_cfp) {
|
||
cfp->pc = cfp->iseq->iseq_encoded + entry->cont;
|
||
th->errinfo = Qnil;
|
||
goto vm_loop_start;
|
||
... | ... | |
}
|
||
}
|
||
}
|
||
else if (state == TAG_BREAK && ((VALUE)escape_ep & ~0x03) == 0) {
|
||
else if (state == TAG_BREAK && ((VALUE)escape_cfp & ~0x01) == 0) {
|
||
type = CATCH_TYPE_BREAK;
|
||
search_restart_point:
|
vm_eval.c | ||
---|---|---|
else {
|
||
VALUE err = th->errinfo;
|
||
if (state == TAG_BREAK) {
|
||
VALUE *escape_ep = GET_THROWOBJ_CATCH_POINT(err);
|
||
VALUE *cep = cfp->ep;
|
||
rb_control_frame_t *escape_cfp = GET_THROWOBJ_CATCH_POINT(err);
|
||
if (cep == escape_ep) {
|
||
if (cfp == escape_cfp) {
|
||
state = 0;
|
||
th->state = 0;
|
||
th->errinfo = Qnil;
|
||
... | ... | |
}
|
||
}
|
||
else if (state == TAG_RETRY) {
|
||
VALUE *escape_ep = GET_THROWOBJ_CATCH_POINT(err);
|
||
VALUE *cep = cfp->ep;
|
||
rb_control_frame_t *escape_cfp = GET_THROWOBJ_CATCH_POINT(err);
|
||
if (cep == escape_ep) {
|
||
if (cfp == escape_cfp) {
|
||
rb_vm_rewind_cfp(th, cfp);
|
||
state = 0;
|
vm_insnhelper.c | ||
---|---|---|
rb_num_t level = throw_state >> 16;
|
||
if (state != 0) {
|
||
rb_control_frame_t *escape_cfp = 0;
|
||
VALUE *pt = 0;
|
||
if (flag != 0) {
|
||
pt = (void *) 1;
|
||
escape_cfp = (void *) 0x01;
|
||
}
|
||
else {
|
||
if (state == TAG_BREAK) {
|
||
... | ... | |
}
|
||
}
|
||
th->state = state;
|
||
return (VALUE)NEW_THROW_OBJECT(throwobj, (VALUE) pt, state);
|
||
if (pt) {
|
||
escape_cfp = VM_EP_CF(th, pt);
|
||
}
|
||
return (VALUE)NEW_THROW_OBJECT(throwobj, (VALUE)escape_cfp, state);
|
||
}
|
||
else {
|
||
/* continue throw */
|
- « Previous
- 1
- 2
- Next »