diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-03-06 12:24:58 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-03-06 12:24:58 +0000 |
commit | d84f9b16946bca06ce0557ebe99152d7d445c9ec (patch) | |
tree | 8141a5d835d1e5638231aced09a08c74ff8fadae /vm_insnhelper.c | |
parent | e0f5a6ab4850e2745d5cb6fb081eb81dc024d2d4 (diff) | |
download | ruby-d84f9b16946bca06ce0557ebe99152d7d445c9ec.tar.gz |
* fix namespace issue on singleton class expressions. [Bug #10943]
* vm_core.h, method.h: remove rb_iseq_t::cref_stack. CREF is stored
to rb_method_definition_t::body.iseq_body.cref.
* vm_insnhelper.c: modify SVAR usage.
When calling ISEQ type method, push CREF information onto method
frame, SVAR located place. Before this fix, SVAR is simply nil.
After this patch, CREF (or NULL == Qfalse for not iseq methods)
is stored at the method invocation.
When SVAR is requierd, then put NODE_IF onto SVAR location,
and NDOE_IF::nd_reserved points CREF itself.
* vm.c (vm_cref_new, vm_cref_dump, vm_cref_new_toplevel): added.
* vm_insnhelper.c (vm_push_frame): accept CREF.
* method.h, vm_method.c (rb_add_method_iseq): added. This function
accepts iseq and CREF.
* class.c (clone_method): use rb_add_method_iseq().
* gc.c (mark_method_entry): mark method_entry::body.iseq_body.cref.
* iseq.c: remove CREF related codes.
* insns.def (getinlinecache/setinlinecache): CREF should be cache key
because a different CREF has a different namespace.
* node.c (rb_gc_mark_node): mark NODE_IF::nd_reserved for SVAR.
* proc.c: catch up changes.
* struct.c: ditto.
* insns.def: ditto.
* vm_args.c (raise_argument_error): ditto.
* vm_eval.c: ditto.
* test/ruby/test_class.rb: add a test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r-- | vm_insnhelper.c | 102 |
1 files changed, 66 insertions, 36 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 815cf4e30b..e4afbdb0fb 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -46,6 +46,7 @@ vm_push_frame(rb_thread_t *th, VALUE self, VALUE klass, VALUE specval, + const NODE *cref, const VALUE *pc, VALUE *sp, int local_size, @@ -68,7 +69,8 @@ vm_push_frame(rb_thread_t *th, } /* set special val */ - *sp = specval; + sp[-1] = (VALUE)cref; + sp[ 0] = specval; /* setup vm control frame stack */ @@ -161,6 +163,7 @@ lep_svar_get(rb_thread_t *th, const VALUE *lep, rb_num_t key) const NODE * const svar = *svar_place; if (NIL_P((VALUE)svar)) return Qnil; + if (nd_type(svar) == NODE_CREF) return Qnil; switch (key) { case VM_SVAR_LASTLINE: @@ -188,6 +191,12 @@ lep_svar_set(rb_thread_t *th, VALUE *lep, rb_num_t key, VALUE val) if (NIL_P((VALUE)svar)) { svar = *svar_place = NEW_IF(Qnil, Qnil, Qnil); + svar->nd_reserved = Qfalse; + } + else if (nd_type(svar) == NODE_CREF) { + NODE *cref = svar; + svar = *svar_place = NEW_IF(Qnil, Qnil, Qnil); + svar->nd_reserved = (VALUE)cref; } switch (key) { @@ -245,28 +254,42 @@ vm_getspecial(rb_thread_t *th, VALUE *lep, rb_num_t key, rb_num_t type) } static NODE * -vm_get_cref0(const rb_iseq_t *iseq, const VALUE *ep) +ep_cref(const VALUE *ep) { - while (1) { - if (VM_EP_LEP_P(ep)) { - if (!RUBY_VM_NORMAL_ISEQ_P(iseq)) return NULL; - return iseq->cref_stack; - } - else if (ep[-1] != Qnil) { + const VALUE svar = ep[-1]; + + if (!svar) { + return NULL; + } + else if (nd_type(svar) == NODE_CREF) { + return (NODE *)svar; + } + else { + return (NODE *)((NODE *)svar)->nd_reserved; + } +} + +static NODE * +vm_get_cref0(const VALUE *ep) +{ + while (!VM_EP_LEP_P(ep)) { + if (ep[-1]) { return (NODE *)ep[-1]; } ep = VM_EP_PREV_EP(ep); } + return ep_cref(ep); } NODE * -rb_vm_get_cref(const rb_iseq_t *iseq, const VALUE *ep) +rb_vm_get_cref(const VALUE *ep) { - NODE *cref = vm_get_cref0(iseq, ep); + NODE *cref = vm_get_cref0(ep); if (cref == 0) { rb_bug("rb_vm_get_cref: unreachable"); } + return cref; } @@ -274,6 +297,7 @@ void rb_vm_rewrite_cref_stack(NODE *node, VALUE old_klass, VALUE new_klass, NODE **new_cref_ptr) { NODE *new_node; + while (node) { if (node->nd_clss == old_klass) { new_node = NEW_CREF(new_klass); @@ -294,17 +318,21 @@ rb_vm_rewrite_cref_stack(NODE *node, VALUE old_klass, VALUE new_klass, NODE **ne static NODE * vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr) { - rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp); - NODE *cref = NEW_CREF(klass); - cref->nd_refinements = Qnil; - cref->nd_visi = noex; + NODE *prev_cref = NULL; + NODE *cref = NULL; if (blockptr) { - RB_OBJ_WRITE(cref, &cref->nd_next, vm_get_cref0(blockptr->iseq, blockptr->ep)); + prev_cref = vm_get_cref0(blockptr->ep); } - else if (cfp) { - RB_OBJ_WRITE(cref, &cref->nd_next, vm_get_cref0(cfp->iseq, cfp->ep)); + else { + rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp); + + if (cfp) { + prev_cref = vm_get_cref0(cfp->ep); + } } + cref = vm_cref_new(klass, noex, prev_cref); + /* TODO: why cref->nd_next is 1? */ if (cref->nd_next && cref->nd_next != (void *) 1 && !NIL_P(cref->nd_next->nd_refinements)) { @@ -315,9 +343,9 @@ vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr) } static inline VALUE -vm_get_cbase(const rb_iseq_t *iseq, const VALUE *ep) +vm_get_cbase(const VALUE *ep) { - NODE *cref = rb_vm_get_cref(iseq, ep); + NODE *cref = rb_vm_get_cref(ep); VALUE klass = Qundef; while (cref) { @@ -331,9 +359,9 @@ vm_get_cbase(const rb_iseq_t *iseq, const VALUE *ep) } static inline VALUE -vm_get_const_base(const rb_iseq_t *iseq, const VALUE *ep) +vm_get_const_base(const VALUE *ep) { - NODE *cref = rb_vm_get_cref(iseq, ep); + NODE *cref = rb_vm_get_cref(ep); VALUE klass = Qundef; while (cref) { @@ -373,14 +401,13 @@ vm_get_iclass(rb_control_frame_t *cfp, VALUE klass) } static inline VALUE -vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq, - VALUE orig_klass, ID id, int is_defined) +vm_get_ev_const(rb_thread_t *th, VALUE orig_klass, ID id, int is_defined) { VALUE val; if (orig_klass == Qnil) { /* in current lexical scope */ - const NODE *root_cref = rb_vm_get_cref(iseq, th->cfp->ep); + const NODE *root_cref = rb_vm_get_cref(th->cfp->ep); const NODE *cref; VALUE klass = orig_klass; @@ -1128,7 +1155,7 @@ vm_callee_setup_arg(rb_thread_t *th, rb_call_info_t *ci, const rb_iseq_t *iseq, static VALUE vm_call_iseq_setup(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci) { - vm_callee_setup_arg(th, ci, ci->me->def->body.iseq, cfp->sp - ci->argc); + vm_callee_setup_arg(th, ci, ci->me->def->body.iseq_body.iseq, cfp->sp - ci->argc); return vm_call_iseq_setup_2(th, cfp, ci); } @@ -1148,7 +1175,7 @@ vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info { int i, local_size; VALUE *argv = cfp->sp - ci->argc; - rb_iseq_t *iseq = ci->me->def->body.iseq; + rb_iseq_t *iseq = ci->me->def->body.iseq_body.iseq; VALUE *sp = argv + iseq->param.size; /* clear local variables (arg_size...local_size) */ @@ -1157,7 +1184,7 @@ vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info } vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, ci->recv, ci->defined_class, - VM_ENVVAL_BLOCK_PTR(ci->blockptr), + VM_ENVVAL_BLOCK_PTR(ci->blockptr), ci->me->def->body.iseq_body.cref, iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me, iseq->stack_max); cfp->sp = argv - 1 /* recv */; @@ -1169,7 +1196,7 @@ vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_in { int i; VALUE *argv = cfp->sp - ci->argc; - rb_iseq_t *iseq = ci->me->def->body.iseq; + rb_iseq_t *iseq = ci->me->def->body.iseq_body.iseq; VALUE *src_argv = argv; VALUE *sp_orig, *sp; VALUE finish_flag = VM_FRAME_TYPE_FINISH_P(cfp) ? VM_FRAME_FLAG_FINISH : 0; @@ -1195,7 +1222,8 @@ vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_in } vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag, - ci->recv, ci->defined_class, VM_ENVVAL_BLOCK_PTR(ci->blockptr), + ci->recv, ci->defined_class, + VM_ENVVAL_BLOCK_PTR(ci->blockptr), ci->me->def->body.iseq_body.cref, iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me, iseq->stack_max); cfp->sp = sp_orig; @@ -1377,7 +1405,8 @@ vm_call_cfunc_with_frame(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_i EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass, Qundef); vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv, defined_class, - VM_ENVVAL_BLOCK_PTR(blockptr), 0, th->cfp->sp, 1, me, 0); + VM_ENVVAL_BLOCK_PTR(blockptr), NULL /* cref */, + 0, th->cfp->sp, 1, me, 0); if (len >= 0) rb_check_arity(argc, len, len); @@ -1465,7 +1494,8 @@ vm_call_cfunc_push_frame(rb_thread_t *th) th->passed_ci = 0; vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, ci->recv, ci->defined_class, - VM_ENVVAL_BLOCK_PTR(ci->blockptr), 0, th->cfp->sp + ci->aux.inc_sp, 1, me); + VM_ENVVAL_BLOCK_PTR(ci->blockptr), NULL /* cref */, + 0, th->cfp->sp + ci->aux.inc_sp, 1, me); if (ci->call != vm_call_general) { ci->call = vm_call_cfunc_with_frame; @@ -1754,7 +1784,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci) case VM_METHOD_TYPE_UNDEF: break; case VM_METHOD_TYPE_REFINED:{ - NODE *cref = rb_vm_get_cref(cfp->iseq, cfp->ep); + NODE *cref = rb_vm_get_cref(cfp->ep); VALUE refinements = cref ? cref->nd_refinements : Qnil; VALUE refinement, defined_class; rb_method_entry_t *me; @@ -1983,7 +2013,7 @@ vm_search_super_method(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_inf iseq = iseq->parent_iseq; } - if (ci->me && ci->me->def->type == VM_METHOD_TYPE_ISEQ && ci->me->def->body.iseq == iseq) { + if (ci->me && ci->me->def->type == VM_METHOD_TYPE_ISEQ && ci->me->def->body.iseq_body.iseq == iseq) { ci->klass = RCLASS_SUPER(ci->defined_class); ci->me = rb_method_entry(ci->klass, ci->mid, &ci->defined_class); } @@ -2039,8 +2069,8 @@ vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block, vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC, self, defined_class, - VM_ENVVAL_PREV_EP_PTR(block->ep), 0, - th->cfp->sp, 1, th->passed_bmethod_me, 0); + VM_ENVVAL_PREV_EP_PTR(block->ep), NULL /* cref */, + 0, th->cfp->sp, 1, th->passed_bmethod_me, 0); val = (*ifunc->nd_cfnc) (arg, ifunc->nd_tval, argc, argv, blockarg); @@ -2095,7 +2125,7 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci is_lambda ? VM_FRAME_MAGIC_LAMBDA : VM_FRAME_MAGIC_BLOCK, block->self, block->klass, - VM_ENVVAL_PREV_EP_PTR(block->ep), + VM_ENVVAL_PREV_EP_PTR(block->ep), NULL /* cref */, iseq->iseq_encoded + opt_pc, rsp + arg_size, iseq->local_size - arg_size, 0, iseq->stack_max); |