X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2Fre-engine-Plugin.git;a=blobdiff_plain;f=Plugin.xs;h=cffc46389e01ad1d6175296136266d36eefd88b1;hp=3e9918b7856a0c3d6bd0d0bcf64b2f8b675b2b29;hb=92cf1014a173792464bbe74d342d9c44bb7698ee;hpb=47afe57f6afc7b312d1da725bb38f99ae70b157a diff --git a/Plugin.xs b/Plugin.xs index 3e9918b..cffc463 100644 --- a/Plugin.xs +++ b/Plugin.xs @@ -13,6 +13,20 @@ #define REP_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S)))))) +#undef ENTERn +#if defined(ENTER_with_name) && !REP_HAS_PERL(5, 11, 4) +# define ENTERn(N) ENTER_with_name(N) +#else +# define ENTERn(N) ENTER +#endif + +#undef LEAVEn +#if defined(LEAVE_with_name) && !REP_HAS_PERL(5, 11, 4) +# define LEAVEn(N) LEAVE_with_name(N) +#else +# define LEAVEn(N) LEAVE +#endif + #ifndef REP_WORKAROUND_REQUIRE_PROPAGATION # define REP_WORKAROUND_REQUIRE_PROPAGATION !REP_HAS_PERL(5, 10, 1) #endif @@ -58,10 +72,10 @@ /* ... Thread-safe hints ................................................... */ typedef struct { - SV *comp; - SV *exec; + SV *comp; + SV *exec; #if REP_WORKAROUND_REQUIRE_PROPAGATION - I32 requires; + IV cxreq; #endif } rep_hint_t; @@ -124,13 +138,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); + 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); + h2->exec = rep_clone(h1->exec, ud->owner); SvREFCNT_inc(h2->exec); #if REP_WORKAROUND_REQUIRE_PROPAGATION - h2->requires = h1->requires; + h2->cxreq = h1->cxreq; #endif ptable_store(ud->tbl, ent->key, h2); @@ -166,35 +180,37 @@ STATIC SV *rep_validate_callback(SV *code) { return SvREFCNT_inc_simple_NN(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); + } + } + + return PTR2IV(NULL); +} +#endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */ + STATIC SV *rep_tag(pTHX_ SV *comp, SV *exec) { #define rep_tag(C, E) rep_tag(aTHX_ (C), (E)) rep_hint_t *h; dMY_CXT; h = PerlMemShared_malloc(sizeof *h); - - h->comp = rep_validate_callback(comp); - h->exec = rep_validate_callback(exec); - + h->comp = rep_validate_callback(comp); + h->exec = rep_validate_callback(exec); #if REP_WORKAROUND_REQUIRE_PROPAGATION - { - const PERL_SI *si; - I32 requires = 0; - - 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) - ++requires; - } - } - - h->requires = requires; - } -#endif + h->cxreq = 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. @@ -220,23 +236,9 @@ STATIC const rep_hint_t *rep_detag(pTHX_ const SV *hint) { #endif /* REP_THREADSAFE */ #if REP_WORKAROUND_REQUIRE_PROPAGATION - { - const PERL_SI *si; - I32 requires = 0; - - 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 - && ++requires > h->requires) - return NULL; - } - } - } -#endif + if (rep_require_tag() != h->cxreq) + return NULL; +#endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */ return h; } @@ -247,12 +249,17 @@ STATIC const rep_hint_t *rep_hint(pTHX) { #define rep_hint() rep_hint(aTHX) SV *hint; +#ifdef cop_hints_fetch_pvn + hint = cop_hints_fetch_pvn(PL_curcop, + __PACKAGE__, __PACKAGE_LEN__, rep_hash, 0); +#else /* We already require 5.9.5 for the regexp engine API. */ hint = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash, NULL, __PACKAGE__, __PACKAGE_LEN__, 0, rep_hash); +#endif return rep_detag(hint); } @@ -271,6 +278,10 @@ Plugin_comp(pTHX_ SV * const pattern, U32 flags) re__engine__Plugin re; const rep_hint_t *h; + h = rep_hint(); + if (!h) /* This looks like a pragma leak. Apply the default behaviour */ + return re_compile(pattern, flags); + /* exp/xend version of the pattern & length */ STRLEN plen; char* exp = SvPV((SV*)pattern, plen); @@ -311,13 +322,22 @@ Plugin_comp(pTHX_ SV * const pattern, U32 flags) re->pattern = (SV*)pattern; SvREFCNT_inc(re->pattern); - /* - * Call our callback function if one was defined, if not we've + /* 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 + * in between */ + if (h->exec) { + re->cb_exec = h->exec; + SvREFCNT_inc_simple_void_NN(h->exec); + } + + re->cb_num_capture_buff_FETCH = NULL; + re->cb_num_capture_buff_STORE = NULL; + re->cb_num_capture_buff_LENGTH = NULL; + + /* Call our callback function if one was defined, if not we've * already set up all the stuff we're going to to need for - * subsequent exec and other calls - */ - h = rep_hint(); - if (h && h->comp) { + * subsequent exec and other calls */ + if (h->comp) { ENTER; SAVETMPS; @@ -331,14 +351,6 @@ Plugin_comp(pTHX_ SV * const pattern, U32 flags) LEAVE; } - /* 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 - * in between */ - if (h && h->exec) { - re->cb_exec = h->exec; - SvREFCNT_inc_simple_void_NN(h->exec); - } - /* If any of the comp-time accessors were called we'll have to * update the regexp struct with the new info. */ @@ -416,11 +428,24 @@ Plugin_checkstr(pTHX_ REGEXP * const RX) void Plugin_free(pTHX_ REGEXP * const RX) { - PERL_UNUSED_ARG(RX); + struct regexp *rx = rxREGEXP(RX); + GET_SELF_FROM_PPRIVATE(rx->pprivate); + + SvREFCNT_dec(self->pattern); + SvREFCNT_dec(self->str); + + SvREFCNT_dec(self->cb_exec); + + SvREFCNT_dec(self->cb_num_capture_buff_FETCH); + SvREFCNT_dec(self->cb_num_capture_buff_STORE); + SvREFCNT_dec(self->cb_num_capture_buff_LENGTH); + + self->rx = NULL; + Safefree(self); + /* dSP; SV * callback; - GET_SELF_FROM_PPRIVATE(rx->pprivate); callback = self->cb_free; @@ -651,6 +676,13 @@ CODE: MY_CXT.tbl = t; MY_CXT.owner = aTHX; } + { + level = PerlMemShared_malloc(sizeof *level); + *level = 1; + LEAVEn("sub"); + SAVEDESTRUCTOR_X(rep_thread_cleanup, level); + ENTERn("sub"); + } #endif @@ -750,10 +782,20 @@ PPCODE: } } +void +_exec(re::engine::Plugin self, ...) +PPCODE: + if (items > 1) { + SvREFCNT_dec(self->cb_exec); + self->cb_exec = ST(1); + SvREFCNT_inc(self->cb_exec); + } + void _num_capture_buff_FETCH(re::engine::Plugin self, ...) 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); } @@ -762,6 +804,7 @@ void _num_capture_buff_STORE(re::engine::Plugin self, ...) 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); } @@ -770,6 +813,7 @@ void _num_capture_buff_LENGTH(re::engine::Plugin self, ...) 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); }