X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FLexical-Types.git;a=blobdiff_plain;f=Types.xs;h=20963ee6764cab9ac3e95cb47ce0870637e92f9b;hp=0cff8fa6e90a930d94f37208b13c9859c4cd1742;hb=b39886a970e497bd4018bd32132e44d5a43080d0;hpb=881d1aecb5e9948bbd7a384deffbab560eab4ef4 diff --git a/Types.xs b/Types.xs index 0cff8fa..20963ee 100644 --- a/Types.xs +++ b/Types.xs @@ -39,14 +39,24 @@ # define HvNAMELEN_get(H) strlen(HvNAME_get(H)) #endif -#ifndef OP_SIBLING -# define OP_SIBLING(O) ((O)->op_sibling) +#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 +#ifdef DEBUGGING +# define LT_ASSERT(C) assert(C) +#else +# define LT_ASSERT(C) +#endif + /* ... Thread safety and multiplicity ...................................... */ /* Safe unless stated otherwise in Makefile.PL */ @@ -82,7 +92,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 @@ -97,12 +107,33 @@ # define aMY_CXT_ #endif +#if LT_THREADSAFE +/* We must use preexistent global mutexes or we will never be able to destroy + * them. */ +# if LT_HAS_PERL(5, 9, 3) +# define LT_LOADED_LOCK MUTEX_LOCK(&PL_my_ctx_mutex) +# define LT_LOADED_UNLOCK MUTEX_UNLOCK(&PL_my_ctx_mutex) +# else +# define LT_LOADED_LOCK OP_REFCNT_LOCK +# define LT_LOADED_UNLOCK OP_REFCNT_UNLOCK +# endif +#else +# define LT_LOADED_LOCK NOOP +# define LT_LOADED_UNLOCK NOOP +#endif + #if defined(OP_CHECK_MUTEX_LOCK) && defined(OP_CHECK_MUTEX_UNLOCK) -# define LT_CHECK_MUTEX_LOCK OP_CHECK_MUTEX_LOCK -# define LT_CHECK_MUTEX_UNLOCK OP_CHECK_MUTEX_UNLOCK +# define LT_CHECK_LOCK OP_CHECK_MUTEX_LOCK +# define LT_CHECK_UNLOCK OP_CHECK_MUTEX_UNLOCK +#elif LT_HAS_PERL(5, 9, 3) +# define LT_CHECK_LOCK OP_REFCNT_LOCK +# define LT_CHECK_UNLOCK OP_REFCNT_UNLOCK #else -# define LT_CHECK_MUTEX_LOCK OP_REFCNT_LOCK -# define LT_CHECK_MUTEX_UNLOCK OP_REFCNT_UNLOCK +/* Before perl 5.9.3, lt_ck_*() calls are already protected by the LT_LOADED + * mutex, which falls back to the OP_REFCNT mutex. Make sure we don't lock it + * twice. */ +# define LT_CHECK_LOCK NOOP +# define LT_CHECK_UNLOCK NOOP #endif typedef OP *(*lt_ck_t)(pTHX_ OP *); @@ -113,30 +144,108 @@ 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; + LT_CHECK_LOCK; if (!*old_ck_p) { *old_ck_p = PL_check[type]; PL_check[type] = new_ck; } - LT_CHECK_MUTEX_UNLOCK; + LT_CHECK_UNLOCK; } #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; + LT_CHECK_LOCK; if (*old_ck_p) { PL_check[type] = *old_ck_p; *old_ck_p = 0; } - LT_CHECK_MUTEX_UNLOCK; + LT_CHECK_UNLOCK; } /* --- Helpers ------------------------------------------------------------- */ +/* ... Check if the module is loaded ....................................... */ + +static I32 lt_loaded = 0; + +#if LT_THREADSAFE + +#define PTABLE_NAME ptable_loaded +#define PTABLE_NEED_DELETE 1 +#define PTABLE_NEED_WALK 0 + +#include "ptable.h" + +#define ptable_loaded_store(T, K, V) ptable_loaded_store(aPTBLMS_ (T), (K), (V)) +#define ptable_loaded_delete(T, K) ptable_loaded_delete(aPTBLMS_ (T), (K)) +#define ptable_loaded_free(T) ptable_loaded_free(aPTBLMS_ (T)) + +static ptable *lt_loaded_cxts = NULL; + +#ifdef DEBUGGING + +static int lt_is_loaded(pTHX_ void *cxt) { +#define lt_is_loaded(C) lt_is_loaded(aTHX_ (C)) + int res = 0; + + LT_LOADED_LOCK; + if (lt_loaded_cxts && ptable_fetch(lt_loaded_cxts, cxt)) + res = 1; + LT_LOADED_UNLOCK; + + return res; +} + +#endif /* DEBUGGING */ + +static int lt_set_loaded_locked(pTHX_ void *cxt) { +#define lt_set_loaded_locked(C) lt_set_loaded_locked(aTHX_ (C)) + int global_setup = 0; + + if (lt_loaded <= 0) { + LT_ASSERT(lt_loaded == 0); + LT_ASSERT(!lt_loaded_cxts); + lt_loaded_cxts = ptable_new(); + global_setup = 1; + } + ++lt_loaded; + LT_ASSERT(lt_loaded_cxts); + ptable_loaded_store(lt_loaded_cxts, cxt, cxt); + + return global_setup; +} + +static int lt_clear_loaded_locked(pTHX_ void *cxt) { +#define lt_clear_loaded_locked(C) lt_clear_loaded_locked(aTHX_ (C)) + int global_teardown = 0; + + if (lt_loaded > 1) { + LT_ASSERT(lt_loaded_cxts); + ptable_loaded_delete(lt_loaded_cxts, cxt); + --lt_loaded; + } else if (lt_loaded_cxts) { + LT_ASSERT(lt_loaded == 1); + ptable_loaded_free(lt_loaded_cxts); + lt_loaded_cxts = NULL; + lt_loaded = 0; + global_teardown = 1; + } + + return global_teardown; +} + +#else + +#define lt_is_loaded(C) (lt_loaded > 0) +#define lt_set_loaded_locked(C) ((lt_loaded++ <= 0) ? 1 : 0) +#define lt_clear_loaded_locked(C) ((--lt_loaded <= 0) ? 1 : 0) + +#endif + /* ... Thread-safe hints ................................................... */ #if LT_WORKAROUND_REQUIRE_PROPAGATION @@ -172,6 +281,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_ @@ -188,7 +299,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" @@ -202,11 +314,12 @@ typedef SV lt_hint_t; #define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION typedef struct { + peep_t old_peep; + ptable *seen; /* It really is a ptable_seen */ #if LT_THREADSAFE - ptable *tbl; /* It really is a ptable_hints */ + ptable *tbl; /* It really is a ptable_hints */ tTHX owner; #endif - ptable *seen; /* It really is a ptable_seen */ SV *default_meth; } my_cxt_t; @@ -241,7 +354,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; @@ -263,47 +376,13 @@ STATIC void lt_ptable_clone(pTHX_ ptable_ent *ent, void *ud_) { ptable_hints_store(ud->tbl, ent->key, h2); } -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; @@ -349,7 +428,7 @@ 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; @@ -388,7 +467,7 @@ STATIC SV *lt_tag(pTHX_ SV *value) { 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 @@ -413,9 +492,9 @@ STATIC SV *lt_detag(pTHX_ const SV *hint) { return LT_HINT_CODE(h); } -STATIC U32 lt_hash = 0; +static VOL 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 @@ -439,6 +518,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" @@ -448,7 +529,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) @@ -460,7 +541,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); @@ -474,7 +555,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; @@ -529,7 +610,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; @@ -585,7 +666,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); @@ -603,14 +684,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; @@ -627,7 +708,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); @@ -645,7 +726,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); @@ -661,7 +742,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)) { @@ -677,7 +758,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)) { @@ -710,9 +791,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; @@ -789,9 +870,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); @@ -801,7 +882,7 @@ 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; @@ -830,9 +911,7 @@ 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 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)) @@ -862,11 +941,11 @@ STATIC void lt_peep_rec(pTHX_ OP *o, ptable *seen) { * Moreover, for non-special padrange ops (i.e. that aren't for * my (...) = @_), the first original padxv is its sibling or nephew. */ - OP *kid = OP_SIBLING(o); + 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 = OP_SIBLING(kid); + kid = OpSIBLING(kid); } lt_maybe_padrange_setup(o, kid); } @@ -881,7 +960,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 = OP_SIBLING(start); + start = OpSIBLING(start); lt_maybe_padrange_setup(op, start); } break; @@ -927,12 +1006,15 @@ STATIC void lt_peep_rec(pTHX_ OP *o, ptable *seen) { } } -STATIC void lt_peep(pTHX_ OP *o) { +static void lt_peep(pTHX_ OP *o) { + ptable *seen; dMY_CXT; - ptable *seen = MY_CXT.seen; - lt_old_peep(aTHX_ o); + LT_ASSERT(lt_is_loaded(&MY_CXT)); + MY_CXT.old_peep(aTHX_ o); + + seen = MY_CXT.seen; if (seen) { ptable_seen_clear(seen); lt_peep_rec(o); @@ -940,109 +1022,125 @@ STATIC void lt_peep(pTHX_ OP *o) { } } -/* --- Interpreter setup/teardown ------------------------------------------ */ +/* --- Module setup/teardown ----------------------------------------------- */ + +static void lt_teardown(pTHX_ void *root) { + dMY_CXT; + LT_LOADED_LOCK; -STATIC U32 lt_initialized = 0; + if (lt_clear_loaded_locked(&MY_CXT)) { + lt_ck_restore(OP_PADANY, <_old_ck_padany); + lt_ck_restore(OP_PADSV, <_old_ck_padsv); -STATIC void lt_teardown(pTHX_ void *root) { - if (!lt_initialized) - return; + ptable_map_free(lt_op_padxv_map); + lt_op_padxv_map = NULL; -#if LT_MULTIPLICITY - if (aTHX != root) - return; +#if LT_HAS_PERL(5, 17, 6) + ptable_map_free(lt_op_padrange_map); + lt_op_padrange_map = NULL; #endif - { - dMY_CXT; -#if LT_THREADSAFE - ptable_hints_free(MY_CXT.tbl); - MY_CXT.tbl = NULL; +#ifdef USE_ITHREADS + MUTEX_DESTROY(<_op_map_mutex); #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); - lt_ck_restore(OP_PADSV, <_old_ck_padsv); + LT_LOADED_UNLOCK; + if (MY_CXT.old_peep) { #if LT_HAS_RPEEP - PL_rpeepp = lt_old_peep; + PL_rpeepp = MY_CXT.old_peep; #else - PL_peepp = lt_old_peep; + PL_peepp = MY_CXT.old_peep; #endif - lt_old_peep = 0; - - lt_initialized = 0; -} - -STATIC void lt_setup(pTHX) { -#define lt_setup() lt_setup(aTHX) - if (lt_initialized) - return; - - { - MY_CXT_INIT; -#if LT_THREADSAFE - MY_CXT.tbl = ptable_new(); - MY_CXT.owner = aTHX; -#endif - MY_CXT.seen = ptable_new(); - MY_CXT.default_meth = newSVpvn("TYPEDSCALAR", 11); - SvREADONLY_on(MY_CXT.default_meth); + MY_CXT.old_peep = 0; } - lt_ck_replace(OP_PADANY, lt_ck_padany, <_old_ck_padany); - lt_ck_replace(OP_PADSV, lt_ck_padsv, <_old_ck_padsv); + ptable_seen_free(MY_CXT.seen); + MY_CXT.seen = NULL; -#if LT_HAS_RPEEP - lt_old_peep = PL_rpeepp; - PL_rpeepp = lt_peep; -#else - lt_old_peep = PL_peepp; - PL_peepp = lt_peep; +#if LT_THREADSAFE + ptable_hints_free(MY_CXT.tbl); + MY_CXT.tbl = NULL; #endif -#if LT_MULTIPLICITY - call_atexit(lt_teardown, aTHX); -#else - call_atexit(lt_teardown, NULL); -#endif + SvREFCNT_dec(MY_CXT.default_meth); + MY_CXT.default_meth = NULL; - lt_initialized = 1; + return; } -STATIC U32 lt_booted = 0; - -/* --- XS ------------------------------------------------------------------ */ - -MODULE = Lexical::Types PACKAGE = Lexical::Types +static void lt_setup(pTHX) { +#define lt_setup() lt_setup(aTHX) + MY_CXT_INIT; /* Takes/release PL_my_ctx_mutex */ -PROTOTYPES: ENABLE + LT_LOADED_LOCK; -BOOT: -{ - if (!lt_booted++) { - HV *stash; + if (lt_set_loaded_locked(&MY_CXT)) { + PERL_HASH(lt_hash, __PACKAGE__, __PACKAGE_LEN__); lt_op_padxv_map = ptable_new(); #if LT_HAS_PERL(5, 17, 6) lt_op_padrange_map = ptable_new(); #endif + #ifdef USE_ITHREADS MUTEX_INIT(<_op_map_mutex); #endif - PERL_HASH(lt_hash, __PACKAGE__, __PACKAGE_LEN__); + lt_ck_replace(OP_PADANY, lt_ck_padany, <_old_ck_padany); + lt_ck_replace(OP_PADSV, lt_ck_padsv, <_old_ck_padsv); + } + + LT_LOADED_UNLOCK; + + { + HV *stash; stash = gv_stashpvn(__PACKAGE__, __PACKAGE_LEN__, 1); newCONSTSUB(stash, "LT_THREADSAFE", newSVuv(LT_THREADSAFE)); newCONSTSUB(stash, "LT_FORKSAFE", newSVuv(LT_FORKSAFE)); } +#if LT_HAS_RPEEP + if (PL_rpeepp != lt_peep) { + MY_CXT.old_peep = PL_rpeepp; + PL_rpeepp = lt_peep; + } +#else + if (PL_peepp != lt_peep) { + MY_CXT.old_peep = PL_peepp; + PL_peepp = lt_peep; + } +#endif + else { + MY_CXT.old_peep = 0; + } + + MY_CXT.seen = ptable_new(); + +#if LT_THREADSAFE + MY_CXT.tbl = ptable_new(); + MY_CXT.owner = aTHX; +#endif + + MY_CXT.default_meth = newSVpvn("TYPEDSCALAR", 11); + SvREADONLY_on(MY_CXT.default_meth); + + call_atexit(lt_teardown, NULL); + + return; +} + +/* --- XS ------------------------------------------------------------------ */ + +MODULE = Lexical::Types PACKAGE = Lexical::Types + +PROTOTYPES: ENABLE + +BOOT: +{ lt_setup(); } @@ -1055,7 +1153,6 @@ PREINIT: ptable *t; ptable *s; SV *cloned_default_meth; - GV *gv; PPCODE: { { @@ -1072,28 +1169,18 @@ PPCODE: } { MY_CXT_CLONE; + MY_CXT.seen = s; MY_CXT.tbl = t; MY_CXT.owner = aTHX; - MY_CXT.seen = s; MY_CXT.default_meth = cloned_default_meth; + { + int global_setup; + LT_LOADED_LOCK; + global_setup = lt_set_loaded_locked(&MY_CXT); + LT_ASSERT(!global_setup); + LT_LOADED_UNLOCK; + } } - 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