X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FLexical-Types.git;a=blobdiff_plain;f=Types.xs;h=ab010ab50d4f80bc2a68fe09272b09bbc747cd98;hp=6ead2eb61321356b7f6336749e2def7bd224945b;hb=bc16ea8dc7913595c3d1379136877fa6f7e7af2f;hpb=ac8fadd02eaa275485af784bc3a70fd2c666906c diff --git a/Types.xs b/Types.xs index 6ead2eb..ab010ab 100644 --- a/Types.xs +++ b/Types.xs @@ -39,6 +39,14 @@ # define HvNAMELEN_get(H) strlen(HvNAME_get(H)) #endif +#ifndef OpSIBLING +# ifdef OP_SIBLING +# define OpSIBLING(O) OP_SIBLING(O) +# else +# define OpSIBLING(O) ((O)->op_sibling) +# endif +#endif + #ifndef SvREFCNT_inc_simple_void_NN # define SvREFCNT_inc_simple_void_NN(S) ((void) SvREFCNT_inc(S)) #endif @@ -78,7 +86,7 @@ # undef MY_CXT # define MY_CXT lt_globaldata # undef START_MY_CXT -# define START_MY_CXT STATIC my_cxt_t MY_CXT; +# define START_MY_CXT static my_cxt_t MY_CXT; # undef MY_CXT_INIT # define MY_CXT_INIT NOOP # undef MY_CXT_CLONE @@ -109,7 +117,7 @@ typedef OP *(*lt_ck_t)(pTHX_ OP *); #else -STATIC void lt_ck_replace(pTHX_ OPCODE type, lt_ck_t new_ck, lt_ck_t *old_ck_p){ +static void lt_ck_replace(pTHX_ OPCODE type, lt_ck_t new_ck, lt_ck_t *old_ck_p){ #define lt_ck_replace(T, NC, OCP) lt_ck_replace(aTHX_ (T), (NC), (OCP)) LT_CHECK_MUTEX_LOCK; if (!*old_ck_p) { @@ -121,7 +129,7 @@ STATIC void lt_ck_replace(pTHX_ OPCODE type, lt_ck_t new_ck, lt_ck_t *old_ck_p){ #endif -STATIC void lt_ck_restore(pTHX_ OPCODE type, lt_ck_t *old_ck_p) { +static void lt_ck_restore(pTHX_ OPCODE type, lt_ck_t *old_ck_p) { #define lt_ck_restore(T, OCP) lt_ck_restore(aTHX_ (T), (OCP)) LT_CHECK_MUTEX_LOCK; if (*old_ck_p) { @@ -168,6 +176,8 @@ typedef SV lt_hint_t; #define PTABLE_NAME ptable_hints #define PTABLE_VAL_FREE(V) LT_HINT_FREE(V) +#define PTABLE_NEED_DELETE 0 +#define PTABLE_NEED_WALK 1 #define pPTBL pTHX #define pPTBL_ pTHX_ @@ -184,7 +194,8 @@ typedef SV lt_hint_t; /* ... "Seen" pointer table ................................................ */ #define PTABLE_NAME ptable_seen -#define PTABLE_VAL_FREE(V) NOOP +#define PTABLE_NEED_DELETE 0 +#define PTABLE_NEED_WALK 0 #include "ptable.h" @@ -237,7 +248,7 @@ typedef struct { # define lt_dup_inc(S, U) SvREFCNT_inc(sv_dup((S), &((U)->params))) #endif -STATIC void lt_ptable_clone(pTHX_ ptable_ent *ent, void *ud_) { +static void lt_ptable_clone(pTHX_ ptable_ent *ent, void *ud_) { lt_ptable_clone_ud *ud = ud_; lt_hint_t *h1 = ent->val; lt_hint_t *h2; @@ -259,22 +270,47 @@ 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) { +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 ........................................................... */ #if LT_WORKAROUND_REQUIRE_PROPAGATION -STATIC IV lt_require_tag(pTHX) { +static IV lt_require_tag(pTHX) { #define lt_require_tag() lt_require_tag(aTHX) const CV *cv, *outside; @@ -320,10 +356,16 @@ get_enclosing_cv: #endif /* LT_WORKAROUND_REQUIRE_PROPAGATION */ -STATIC SV *lt_tag(pTHX_ SV *value) { +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,24 +386,24 @@ 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)); } -STATIC SV *lt_detag(pTHX_ const SV *hint) { +static SV *lt_detag(pTHX_ const SV *hint) { #define lt_detag(H) lt_detag(aTHX_ (H)) 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; @@ -378,9 +420,9 @@ STATIC SV *lt_detag(pTHX_ const SV *hint) { return LT_HINT_CODE(h); } -STATIC U32 lt_hash = 0; +static U32 lt_hash = 0; -STATIC SV *lt_hint(pTHX) { +static SV *lt_hint(pTHX) { #define lt_hint() lt_hint(aTHX) SV *hint; #ifdef cop_hints_fetch_pvn @@ -404,6 +446,8 @@ STATIC SV *lt_hint(pTHX) { #define PTABLE_NAME ptable_map #define PTABLE_VAL_FREE(V) PerlMemShared_free(V) +#define PTABLE_NEED_DELETE 1 +#define PTABLE_NEED_WALK 0 #include "ptable.h" @@ -413,7 +457,7 @@ STATIC SV *lt_hint(pTHX) { #ifdef USE_ITHREADS -STATIC perl_mutex lt_op_map_mutex; +static perl_mutex lt_op_map_mutex; #define LT_LOCK(M) MUTEX_LOCK(M) #define LT_UNLOCK(M) MUTEX_UNLOCK(M) @@ -425,7 +469,7 @@ STATIC perl_mutex lt_op_map_mutex; #endif /* !USE_ITHREADS */ -STATIC ptable *lt_op_padxv_map = NULL; +static ptable *lt_op_padxv_map = NULL; typedef struct { OP *(*old_pp)(pTHX); @@ -439,7 +483,7 @@ typedef struct { #endif /* !MULTIPLICITY */ } lt_op_padxv_info; -STATIC void lt_op_padxv_info_call(pTHX_ const lt_op_padxv_info *oi, SV *sv) { +static void lt_op_padxv_info_call(pTHX_ const lt_op_padxv_info *oi, SV *sv) { #define lt_op_padxv_info_call(O, S) lt_op_padxv_info_call(aTHX_ (O), (S)) SV *orig_pkg, *type_pkg, *type_meth; int items; @@ -494,7 +538,7 @@ STATIC void lt_op_padxv_info_call(pTHX_ const lt_op_padxv_info *oi, SV *sv) { return; } -STATIC void lt_padxv_map_store(pTHX_ const OP *o, SV *orig_pkg, SV *type_pkg, SV *type_meth, OP *(*old_pp)(pTHX)) { +static void lt_padxv_map_store(pTHX_ const OP *o, SV *orig_pkg, SV *type_pkg, SV *type_meth, OP *(*old_pp)(pTHX)) { #define lt_padxv_map_store(O, OP, TP, TM, PP) lt_padxv_map_store(aTHX_ (O), (OP), (TP), (TM), (PP)) lt_op_padxv_info *oi; @@ -550,7 +594,7 @@ STATIC void lt_padxv_map_store(pTHX_ const OP *o, SV *orig_pkg, SV *type_pkg, SV LT_UNLOCK(<_op_map_mutex); } -STATIC const lt_op_padxv_info *lt_padxv_map_fetch(const OP *o, lt_op_padxv_info *oi) { +static const lt_op_padxv_info *lt_padxv_map_fetch(const OP *o, lt_op_padxv_info *oi) { const lt_op_padxv_info *val; LT_LOCK(<_op_map_mutex); @@ -568,14 +612,14 @@ STATIC const lt_op_padxv_info *lt_padxv_map_fetch(const OP *o, lt_op_padxv_info #if LT_HAS_PERL(5, 17, 6) -STATIC ptable *lt_op_padrange_map = NULL; +static ptable *lt_op_padrange_map = NULL; typedef struct { OP *(*old_pp)(pTHX); const OP *padxv_start; } lt_op_padrange_info; -STATIC void lt_padrange_map_store(pTHX_ const OP *o, const OP *s, OP *(*old_pp)(pTHX)) { +static void lt_padrange_map_store(pTHX_ const OP *o, const OP *s, OP *(*old_pp)(pTHX)) { #define lt_padrange_map_store(O, S, PP) lt_padrange_map_store(aTHX_ (O), (S), (PP)) lt_op_padrange_info *oi; @@ -592,7 +636,7 @@ STATIC void lt_padrange_map_store(pTHX_ const OP *o, const OP *s, OP *(*old_pp)( LT_UNLOCK(<_op_map_mutex); } -STATIC const lt_op_padrange_info *lt_padrange_map_fetch(const OP *o, lt_op_padrange_info *oi) { +static const lt_op_padrange_info *lt_padrange_map_fetch(const OP *o, lt_op_padrange_info *oi) { const lt_op_padrange_info *val; LT_LOCK(<_op_map_mutex); @@ -610,7 +654,7 @@ STATIC const lt_op_padrange_info *lt_padrange_map_fetch(const OP *o, lt_op_padra #endif -STATIC void lt_map_delete(pTHX_ const OP *o) { +static void lt_map_delete(pTHX_ const OP *o) { #define lt_map_delete(O) lt_map_delete(aTHX_ (O)) LT_LOCK(<_op_map_mutex); @@ -626,7 +670,7 @@ STATIC void lt_map_delete(pTHX_ const OP *o) { /* ... Our pp_padsv ........................................................ */ -STATIC OP *lt_pp_padsv(pTHX) { +static OP *lt_pp_padsv(pTHX) { lt_op_padxv_info oi; if (lt_padxv_map_fetch(PL_op, &oi)) { @@ -642,7 +686,7 @@ STATIC OP *lt_pp_padsv(pTHX) { #if LT_HAS_PERL(5, 17, 6) -STATIC OP *lt_pp_padrange(pTHX) { +static OP *lt_pp_padrange(pTHX) { lt_op_padrange_info roi; if (lt_padrange_map_fetch(PL_op, &roi)) { @@ -652,7 +696,9 @@ 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 = p->op_next) { + while (p->op_type == OP_NULL) + p = p->op_next; 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)); @@ -673,9 +719,9 @@ STATIC OP *lt_pp_padrange(pTHX) { * the op entry in the op map in the padany check function, and we set their * op_ppaddr member in our peephole optimizer replacement below. */ -STATIC OP *(*lt_old_ck_padany)(pTHX_ OP *) = 0; +static OP *(*lt_old_ck_padany)(pTHX_ OP *) = 0; -STATIC OP *lt_ck_padany(pTHX_ OP *o) { +static OP *lt_ck_padany(pTHX_ OP *o) { HV *stash; SV *code; @@ -685,7 +731,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; @@ -752,9 +798,9 @@ skip: return o; } -STATIC OP *(*lt_old_ck_padsv)(pTHX_ OP *) = 0; +static OP *(*lt_old_ck_padsv)(pTHX_ OP *) = 0; -STATIC OP *lt_ck_padsv(pTHX_ OP *o) { +static OP *lt_ck_padsv(pTHX_ OP *o) { lt_map_delete(o); return lt_old_ck_padsv(aTHX_ o); @@ -764,14 +810,14 @@ STATIC OP *lt_ck_padsv(pTHX_ OP *o) { #if LT_HAS_PERL(5, 17, 6) -STATIC int lt_maybe_padrange_setup(pTHX_ OP *o, const OP *start) { +static int lt_maybe_padrange_setup(pTHX_ OP *o, const OP *start) { #define lt_maybe_padrange_setup(O, S) lt_maybe_padrange_setup(aTHX_ (O), (S)) PADOFFSET i, count; const OP *p; 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 = p->op_next) { 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 @@ -793,9 +839,9 @@ STATIC int lt_maybe_padrange_setup(pTHX_ OP *o, const OP *start) { #endif -STATIC peep_t lt_old_peep = 0; /* This is actually the rpeep past 5.13.5 */ +static peep_t lt_old_peep = 0; /* This is actually the rpeep past 5.13.5 */ -STATIC void lt_peep_rec(pTHX_ OP *o, ptable *seen) { +static void lt_peep_rec(pTHX_ OP *o, ptable *seen) { #define lt_peep_rec(O) lt_peep_rec(aTHX_ (O), seen) for (; o; o = o->op_next) { if (ptable_fetch(seen, o)) @@ -823,8 +869,15 @@ STATIC void lt_peep_rec(pTHX_ OP *o, ptable *seen) { && !(o->op_flags & OPf_SPECIAL)) { /* 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); + * my (...) = @_), the first original padxv is its sibling or nephew. + */ + OP *kid = OpSIBLING(o); + if (kid->op_type == OP_NULL && kid->op_flags & OPf_KIDS) { + kid = kUNOP->op_first; + if (kid->op_type == OP_NULL) + kid = OpSIBLING(kid); + } + lt_maybe_padrange_setup(o, kid); } break; case OP_AASSIGN: { @@ -837,7 +890,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 = OpSIBLING(start); lt_maybe_padrange_setup(op, start); } break; @@ -883,23 +936,25 @@ STATIC void lt_peep_rec(pTHX_ OP *o, ptable *seen) { } } -STATIC void lt_peep(pTHX_ OP *o) { +static void lt_peep(pTHX_ OP *o) { dMY_CXT; ptable *seen = MY_CXT.seen; 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 ------------------------------------------ */ -STATIC U32 lt_initialized = 0; +static U32 lt_initialized = 0; -STATIC void lt_teardown(pTHX_ void *root) { +static void lt_teardown(pTHX_ void *root) { if (!lt_initialized) return; @@ -912,9 +967,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); @@ -930,7 +988,7 @@ STATIC void lt_teardown(pTHX_ void *root) { lt_initialized = 0; } -STATIC void lt_setup(pTHX) { +static void lt_setup(pTHX) { #define lt_setup() lt_setup(aTHX) if (lt_initialized) return; @@ -966,7 +1024,7 @@ STATIC void lt_setup(pTHX) { lt_initialized = 1; } -STATIC U32 lt_booted = 0; +static U32 lt_booted = 0; /* --- XS ------------------------------------------------------------------ */ @@ -1006,6 +1064,7 @@ PREINIT: ptable *t; ptable *s; SV *cloned_default_meth; + GV *gv; PPCODE: { { @@ -1027,7 +1086,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