X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp_hot.c;h=6fb53d49a4c303f56b0e43e120d41c02b6594312;hb=fca1d8b34fac5a740ae67bc3b873bc01cd76a8a9;hp=35e88688c1e554b929590a94d8c46e6a28027680;hpb=08aeb9f701fa786d490e79e99ac2f9f9de229da3;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp_hot.c b/pp_hot.c index 35e8868..6fb53d4 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -168,18 +168,44 @@ PP(pp_sassign) if (!got_coderef) { /* We've been returned a constant rather than a full subroutine, but they expect a subroutine reference to apply. */ - ENTER; - SvREFCNT_inc_void(SvRV(cv)); - /* newCONSTSUB takes a reference count on the passed in SV - from us. We set the name to NULL, otherwise we get into - all sorts of fun as the reference to our new sub is - donated to the GV that we're about to assign to. - */ - SvRV_set(left, (SV *)newCONSTSUB(GvSTASH(right), NULL, + if (SvROK(cv)) { + ENTER; + SvREFCNT_inc_void(SvRV(cv)); + /* newCONSTSUB takes a reference count on the passed in SV + from us. We set the name to NULL, otherwise we get into + all sorts of fun as the reference to our new sub is + donated to the GV that we're about to assign to. + */ + SvRV_set(left, (SV *)newCONSTSUB(GvSTASH(right), NULL, SvRV(cv))); - SvREFCNT_dec(cv); - LEAVE; + SvREFCNT_dec(cv); + LEAVE; + } else { + /* What can happen for the corner case *{"BONK"} = \&{"BONK"}; + is that + First: ops for \&{"BONK"}; return us the constant in the + symbol table + Second: ops for *{"BONK"} cause that symbol table entry + (and our reference to it) to be upgraded from RV + to typeblob) + Thirdly: We get here. cv is actually PVGV now, and its + GvCV() is actually the subroutine we're looking for + + So change the reference so that it points to the subroutine + of that typeglob, as that's what they were after all along. + */ + GV *const upgraded = (GV *) cv; + CV *const source = GvCV(upgraded); + + assert(source); + assert(CvFLAGS(source) & CVf_CONST); + + SvREFCNT_inc_void(source); + SvREFCNT_dec(upgraded); + SvRV_set(left, (SV *)source); + } } + } SvSetMagicSV(right, left); SETs(right); @@ -1005,6 +1031,8 @@ PP(pp_aassign) } TAINT_NOT; } + if (PL_delaymagic & DM_ARRAY) + SvSETMAGIC((SV*)ary); break; case SVt_PVHV: { /* normal hash */ SV *tmpstr; @@ -1152,14 +1180,6 @@ PP(pp_aassign) *relem++ = (lelem <= lastlelem) ? *lelem++ : &PL_sv_undef; } - /* This is done at the bottom and in this order because - mro_isa_changed_in() can throw exceptions */ - if(PL_delayedisa) { - HV* stash = PL_delayedisa; - PL_delayedisa = NULL; - mro_isa_changed_in(stash); - } - RETURN; } @@ -1266,9 +1286,12 @@ PP(pp_match) } } } - /* remove comment to get faster /g but possibly unsafe $1 vars after a - match. Test for the unsafe vars will fail as well*/ - if (( /* !global && */ rx->nparens) + /* XXX: comment out !global get safe $1 vars after a + match, BUT be aware that this leads to dramatic slowdowns on + /g matches against large strings. So far a solution to this problem + appears to be quite tricky. + Test for the unsafe vars are TODO for now. */ + if (( !global && rx->nparens) || SvTEMP(TARG) || PL_sawampersand || (rx->extflags & (RXf_EVAL_SEEN|RXf_PMf_KEEPCOPY))) r_flags |= REXEC_COPY_STR; @@ -2710,9 +2733,6 @@ try_autoload: gimme = GIMME_V; if ((PL_op->op_private & OPpENTERSUB_DB) && GvCV(PL_DBsub) && !CvNODEBUG(cv)) { - if (CvASSERTION(cv) && PL_DBassertion) - sv_setiv(PL_DBassertion, 1); - Perl_get_db_sub(aTHX_ &sv, cv); if (CvISXSUB(cv)) PL_curcopdb = PL_curcop; @@ -3019,7 +3039,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp) packsv = sv; else { SV* const ref = newSViv(PTR2IV(stash)); - hv_store(PL_stashcache, packname, packlen, ref, 0); + (void)hv_store(PL_stashcache, packname, packlen, ref, 0); } goto fetch; }