X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Types.xs;h=02e5da71947dad06be2ab3c875f8eca5e2550949;hb=d3cb9f3bbe0d0ce0841b21fea6834f8ecc11b67b;hp=6ead2eb61321356b7f6336749e2def7bd224945b;hpb=ac8fadd02eaa275485af784bc3a70fd2c666906c;p=perl%2Fmodules%2FLexical-Types.git diff --git a/Types.xs b/Types.xs index 6ead2eb..02e5da7 100644 --- a/Types.xs +++ b/Types.xs @@ -39,6 +39,10 @@ # define HvNAMELEN_get(H) strlen(HvNAME_get(H)) #endif +#ifndef OP_SIBLING +# define OP_SIBLING(O) ((O)->op_sibling) +#endif + #ifndef SvREFCNT_inc_simple_void_NN # define SvREFCNT_inc_simple_void_NN(S) ((void) SvREFCNT_inc(S)) #endif @@ -259,15 +263,40 @@ STATIC void lt_ptable_clone(pTHX_ ptable_ent *ent, void *ud_) { ptable_hints_store(ud->tbl, ent->key, h2); } -#include "reap.h" - STATIC void lt_thread_cleanup(pTHX_ void *ud) { dMY_CXT; ptable_hints_free(MY_CXT.tbl); + MY_CXT.tbl = NULL; ptable_seen_free(MY_CXT.seen); + MY_CXT.seen = NULL; + SvREFCNT_dec(MY_CXT.default_meth); + MY_CXT.default_meth = NULL; +} + +STATIC int lt_endav_free(pTHX_ SV *sv, MAGIC *mg) { + SAVEDESTRUCTOR_X(lt_thread_cleanup, NULL); + + return 0; } +STATIC MGVTBL lt_endav_vtbl = { + 0, + 0, + 0, + 0, + lt_endav_free +#if MGf_COPY + , 0 +#endif +#if MGf_DUP + , 0 +#endif +#if MGf_LOCAL + , 0 +#endif +}; + #endif /* LT_THREADSAFE */ /* ... Hint tags ........................................................... */ @@ -323,7 +352,13 @@ get_enclosing_cv: STATIC SV *lt_tag(pTHX_ SV *value) { #define lt_tag(V) lt_tag(aTHX_ (V)) lt_hint_t *h; - SV *code = NULL; + SV *code = NULL; +#if LT_THREADSAFE + dMY_CXT; + + if (!MY_CXT.tbl) + return newSViv(0); +#endif /* LT_THREADSAFE */ if (SvROK(value)) { value = SvRV(value); @@ -344,13 +379,10 @@ STATIC SV *lt_tag(pTHX_ SV *value) { #endif /* !LT_HINT_STRUCT */ #if LT_THREADSAFE - { - 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_hints_store(MY_CXT.tbl, h, h); - } + /* 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_hints_store(MY_CXT.tbl, h, h); #endif /* LT_THREADSAFE */ return newSViv(PTR2IV(h)); @@ -361,7 +393,10 @@ STATIC SV *lt_detag(pTHX_ const SV *hint) { lt_hint_t *h; #if LT_THREADSAFE dMY_CXT; -#endif + + if (!MY_CXT.tbl) + return NULL; +#endif /* LT_THREADSAFE */ if (!(hint && SvIOK(hint))) return NULL; @@ -652,7 +687,7 @@ STATIC OP *lt_pp_padrange(pTHX) { base = PL_op->op_targ; count = PL_op->op_private & OPpPADRANGE_COUNTMASK; - for (i = 0, p = roi.padxv_start; i < count && p; ++i, p = p->op_sibling) { + for (i = 0, p = roi.padxv_start; i < count && p; ++i, p = OP_SIBLING(p)) { lt_op_padxv_info oi; if (p->op_type == OP_PADSV && lt_padxv_map_fetch(p, &oi)) lt_op_padxv_info_call(&oi, PAD_SV(base + i)); @@ -685,7 +720,7 @@ STATIC OP *lt_ck_padany(pTHX_ OP *o) { if (stash && (code = lt_hint())) { dMY_CXT; SV *orig_pkg = newSVpvn(HvNAME_get(stash), HvNAMELEN_get(stash)); - SV *orig_meth = MY_CXT.default_meth; + SV *orig_meth = MY_CXT.default_meth; /* Guarded by lt_hint() */ SV *type_pkg = NULL; SV *type_meth = NULL; int items; @@ -771,7 +806,7 @@ STATIC int lt_maybe_padrange_setup(pTHX_ OP *o, const OP *start) { count = o->op_private & OPpPADRANGE_COUNTMASK; - for (i = 0, p = start; i < count && p; ++i, p = p->op_sibling) { + for (i = 0, p = start; i < count && p; ++i, p = OP_SIBLING(p)) { if (p->op_type == OP_PADSV) { /* In a padrange sequence, either all lexicals are typed, or none are. * Thus we can stop at the first padsv op. However, note that these @@ -824,7 +859,7 @@ STATIC void lt_peep_rec(pTHX_ OP *o, ptable *seen) { /* A padrange op is guaranteed to have previously been a pushmark. * Moreover, for non-special padrange ops (i.e. that aren't for * my (...) = @_), the original padxv ops are its siblings. */ - lt_maybe_padrange_setup(o, o->op_sibling); + lt_maybe_padrange_setup(o, OP_SIBLING(o)); } break; case OP_AASSIGN: { @@ -837,7 +872,7 @@ STATIC void lt_peep_rec(pTHX_ OP *o, ptable *seen) { && op->op_flags & OPf_SPECIAL) { const OP *start = cUNOPx(cBINOPo->op_last)->op_first; if (start->op_type == OP_PUSHMARK) - start = start->op_sibling; + start = OP_SIBLING(start); lt_maybe_padrange_setup(op, start); } break; @@ -889,9 +924,11 @@ STATIC void lt_peep(pTHX_ OP *o) { lt_old_peep(aTHX_ o); - ptable_seen_clear(seen); - lt_peep_rec(o); - ptable_seen_clear(seen); + if (seen) { + ptable_seen_clear(seen); + lt_peep_rec(o); + ptable_seen_clear(seen); + } } /* --- Interpreter setup/teardown ------------------------------------------ */ @@ -912,9 +949,12 @@ STATIC void lt_teardown(pTHX_ void *root) { dMY_CXT; #if LT_THREADSAFE ptable_hints_free(MY_CXT.tbl); + MY_CXT.tbl = NULL; #endif ptable_seen_free(MY_CXT.seen); + MY_CXT.seen = NULL; SvREFCNT_dec(MY_CXT.default_meth); + MY_CXT.default_meth = NULL; } lt_ck_restore(OP_PADANY, <_old_ck_padany); @@ -1006,6 +1046,7 @@ PREINIT: ptable *t; ptable *s; SV *cloned_default_meth; + GV *gv; PPCODE: { { @@ -1027,7 +1068,23 @@ PPCODE: MY_CXT.seen = s; MY_CXT.default_meth = cloned_default_meth; } - reap(3, lt_thread_cleanup, NULL); + gv = gv_fetchpv(__PACKAGE__ "::_THREAD_CLEANUP", 0, SVt_PVCV); + if (gv) { + CV *cv = GvCV(gv); + if (!PL_endav) + PL_endav = newAV(); + SvREFCNT_inc(cv); + if (!av_store(PL_endav, av_len(PL_endav) + 1, (SV *) cv)) + SvREFCNT_dec(cv); + sv_magicext((SV *) PL_endav, NULL, PERL_MAGIC_ext, <_endav_vtbl, NULL, 0); + } + XSRETURN(0); + +void +_THREAD_CLEANUP(...) +PROTOTYPE: DISABLE +PPCODE: + lt_thread_cleanup(aTHX_ NULL); XSRETURN(0); #endif