X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Plugin.xs;h=11b5173fd41864ba08f1e3708fe26adf11137d81;hb=9198b4f588644e22e005fe990c8321ce36a08375;hp=940081114ee96d26671b7abc6e378c0265b23882;hpb=6b5ee07d13e0e0db8ad24ec4a6f76cd7a38b0543;p=perl%2Fmodules%2Fre-engine-Plugin.git diff --git a/Plugin.xs b/Plugin.xs index 9400811..11b5173 100644 --- a/Plugin.xs +++ b/Plugin.xs @@ -61,7 +61,7 @@ typedef struct { SV *comp; SV *exec; #if REP_WORKAROUND_REQUIRE_PROPAGATION - IV cxreq; + IV require_tag; #endif } rep_hint_t; @@ -113,7 +113,7 @@ STATIC SV *rep_clone(pTHX_ SV *sv, tTHX owner) { SvREFCNT_dec(stashes); } - return SvREFCNT_inc(dupsv); + return SvREFCNT_inc_simple(dupsv); } STATIC void rep_ptable_clone(pTHX_ ptable_ent *ent, void *ud_) { @@ -124,13 +124,13 @@ STATIC void rep_ptable_clone(pTHX_ ptable_ent *ent, void *ud_) { if (ud->owner == aTHX) return; - h2 = PerlMemShared_malloc(sizeof *h2); - h2->comp = rep_clone(h1->comp, ud->owner); - SvREFCNT_inc(h2->comp); - h2->exec = rep_clone(h1->exec, ud->owner); - SvREFCNT_inc(h2->exec); + h2 = PerlMemShared_malloc(sizeof *h2); + h2->comp = rep_clone(h1->comp, ud->owner); + SvREFCNT_inc_simple_void(h2->comp); + h2->exec = rep_clone(h1->exec, ud->owner); + SvREFCNT_inc_simple_void(h2->exec); #if REP_WORKAROUND_REQUIRE_PROPAGATION - h2->cxreq = h1->cxreq; + h2->require_tag = PTR2IV(rep_clone(INT2PTR(SV *, h1->require_tag), ud->owner)); #endif ptable_store(ud->tbl, ent->key, h2); @@ -160,20 +160,46 @@ STATIC SV *rep_validate_callback(SV *code) { #if REP_WORKAROUND_REQUIRE_PROPAGATION STATIC IV rep_require_tag(pTHX) { #define rep_require_tag() rep_require_tag(aTHX) - const PERL_SI *si; - - for (si = PL_curstackinfo; si; si = si->si_prev) { - I32 cxix; - - for (cxix = si->si_cxix; cxix >= 0; --cxix) { - const PERL_CONTEXT *cx = si->si_cxstack + cxix; - - if (CxTYPE(cx) == CXt_EVAL && cx->blk_eval.old_op_type == OP_REQUIRE) - return PTR2IV(cx); + const CV *cv, *outside; + + cv = PL_compcv; + + if (!cv) { + /* If for some reason the pragma is operational at run-time, try to discover + * the current cv in use. */ + const PERL_SI *si; + + for (si = PL_curstackinfo; si; si = si->si_prev) { + I32 cxix; + + for (cxix = si->si_cxix; cxix >= 0; --cxix) { + const PERL_CONTEXT *cx = si->si_cxstack + cxix; + + switch (CxTYPE(cx)) { + case CXt_SUB: + case CXt_FORMAT: + /* The propagation workaround is only needed up to 5.10.0 and at that + * time format and sub contexts were still identical. And even later the + * cv members offsets should have been kept the same. */ + cv = cx->blk_sub.cv; + goto get_enclosing_cv; + case CXt_EVAL: + cv = cx->blk_eval.cv; + goto get_enclosing_cv; + default: + break; + } + } } + + cv = PL_main_cv; } - return PTR2IV(NULL); +get_enclosing_cv: + for (outside = CvOUTSIDE(cv); outside; outside = CvOUTSIDE(cv)) + cv = outside; + + return PTR2IV(cv); } #endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */ @@ -182,18 +208,21 @@ STATIC SV *rep_tag(pTHX_ SV *comp, SV *exec) { rep_hint_t *h; dMY_CXT; - h = PerlMemShared_malloc(sizeof *h); - h->comp = rep_validate_callback(comp); - h->exec = rep_validate_callback(exec); + h = PerlMemShared_malloc(sizeof *h); + h->comp = rep_validate_callback(comp); + h->exec = rep_validate_callback(exec); #if REP_WORKAROUND_REQUIRE_PROPAGATION - h->cxreq = rep_require_tag(); + h->require_tag = rep_require_tag(); #endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */ #if REP_THREADSAFE - /* We only need for the key to be an unique tag for looking up the value later. - * Allocated memory provides convenient unique identifiers, so that's why we - * use the hint as the key itself. */ - ptable_store(MY_CXT.tbl, h, h); + { + dMY_CXT; + /* We only need for the key to be an unique tag for looking up the value later + * Allocated memory provides convenient unique identifiers, so that's why we + * use the hint as the key itself. */ + ptable_store(MY_CXT.tbl, h, h); + } #endif /* REP_THREADSAFE */ return newSViv(PTR2IV(h)); @@ -202,18 +231,20 @@ STATIC SV *rep_tag(pTHX_ SV *comp, SV *exec) { STATIC const rep_hint_t *rep_detag(pTHX_ const SV *hint) { #define rep_detag(H) rep_detag(aTHX_ (H)) rep_hint_t *h; - dMY_CXT; if (!(hint && SvIOK(hint))) return NULL; h = INT2PTR(rep_hint_t *, SvIVX(hint)); #if REP_THREADSAFE - h = ptable_fetch(MY_CXT.tbl, h); + { + dMY_CXT; + h = ptable_fetch(MY_CXT.tbl, h); + } #endif /* REP_THREADSAFE */ #if REP_WORKAROUND_REQUIRE_PROPAGATION - if (rep_require_tag() != h->cxreq) + if (rep_require_tag() != h->require_tag) return NULL; #endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */ @@ -269,7 +300,7 @@ Plugin_comp(pTHX_ SV * const pattern, U32 flags) /* Our blessed object */ obj = newSV(0); - SvREFCNT_inc(obj); + SvREFCNT_inc_simple_void_NN(obj); Newxz(re, 1, struct replug); sv_setref_pv(obj, "re::engine::Plugin", (void*)re); @@ -301,7 +332,7 @@ Plugin_comp(pTHX_ SV * const pattern, U32 flags) /* Store the pattern for ->pattern */ re->pattern = (SV*)pattern; - SvREFCNT_inc(re->pattern); + SvREFCNT_inc_simple_void(re->pattern); /* If there's an exec callback, store it into the private object so * that it will be the one to be called, even if the engine changes @@ -354,8 +385,9 @@ Plugin_exec(pTHX_ REGEXP * const RX, char *stringarg, char *strend, SV *ret; /* Store the current str for ->str */ - self->str = (SV*)sv; - SvREFCNT_inc(self->str); + SvREFCNT_dec(self->str); + self->str = sv; + SvREFCNT_inc_simple_void(self->str); ENTER; SAVETMPS; @@ -515,7 +547,7 @@ Plugin_numbered_buff_STORE(pTHX_ REGEXP * const RX, const I32 paren, PUSHMARK(SP); XPUSHs(rx->pprivate); XPUSHs(sv_2mortal(newSViv(paren))); - XPUSHs(SvREFCNT_inc((SV *) value)); + XPUSHs((SV *) value); PUTBACK; call_sv(callback, G_DISCARD); @@ -592,12 +624,13 @@ Plugin_package(pTHX_ REGEXP * const RX) STATIC U32 rep_initialized = 0; STATIC void rep_teardown(pTHX_ void *root) { - dMY_CXT; - if (!rep_initialized || aTHX != root) return; - ptable_free(MY_CXT.tbl); + { + dMY_CXT; + ptable_free(MY_CXT.tbl); + } rep_initialized = 0; } @@ -607,9 +640,11 @@ STATIC void rep_setup(pTHX) { if (rep_initialized) return; - MY_CXT_INIT; - MY_CXT.tbl = ptable_new(); - MY_CXT.owner = aTHX; + { + MY_CXT_INIT; + MY_CXT.tbl = ptable_new(); + MY_CXT.owner = aTHX; + } call_atexit(rep_teardown, aTHX); @@ -703,8 +738,9 @@ void stash(re::engine::Plugin self, ...) PPCODE: if (items > 1) { + SvREFCNT_dec(self->stash); self->stash = ST(1); - SvREFCNT_inc(self->stash); + SvREFCNT_inc_simple_void(self->stash); XSRETURN_EMPTY; } else { XPUSHs(self->stash); @@ -758,7 +794,7 @@ PPCODE: if (items > 1) { SvREFCNT_dec(self->cb_exec); self->cb_exec = ST(1); - SvREFCNT_inc(self->cb_exec); + SvREFCNT_inc_simple_void(self->cb_exec); } void @@ -767,7 +803,7 @@ PPCODE: if (items > 1) { SvREFCNT_dec(self->cb_num_capture_buff_FETCH); self->cb_num_capture_buff_FETCH = ST(1); - SvREFCNT_inc(self->cb_num_capture_buff_FETCH); + SvREFCNT_inc_simple_void(self->cb_num_capture_buff_FETCH); } void @@ -776,7 +812,7 @@ PPCODE: if (items > 1) { SvREFCNT_dec(self->cb_num_capture_buff_STORE); self->cb_num_capture_buff_STORE = ST(1); - SvREFCNT_inc(self->cb_num_capture_buff_STORE); + SvREFCNT_inc_simple_void(self->cb_num_capture_buff_STORE); } void @@ -785,7 +821,7 @@ PPCODE: if (items > 1) { SvREFCNT_dec(self->cb_num_capture_buff_LENGTH); self->cb_num_capture_buff_LENGTH = ST(1); - SvREFCNT_inc(self->cb_num_capture_buff_LENGTH); + SvREFCNT_inc_simple_void(self->cb_num_capture_buff_LENGTH); } SV *