X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Types.xs;h=bf6c0bd4ec363d5a027562097985d8ecf23c75d4;hb=a825e9ba35d8715a17a91575220e61769dd1aa8a;hp=4b3856225042fa8b68990568595565812b8cb535;hpb=edbeb65399a0fb7d5735dbacfb04ffb9bdf64b34;p=perl%2Fmodules%2FLexical-Types.git diff --git a/Types.xs b/Types.xs index 4b38562..bf6c0bd 100644 --- a/Types.xs +++ b/Types.xs @@ -39,12 +39,17 @@ # define HvNAMELEN_get(H) strlen(HvNAME_get(H)) #endif -#ifndef SvREFCNT_inc_simple_NN -# define SvREFCNT_inc_simple_NN SvREFCNT_inc +#ifndef SvREFCNT_inc_simple_void_NN +# define SvREFCNT_inc_simple_void_NN(S) ((void) SvREFCNT_inc(S)) #endif /* ... Thread safety and multiplicity ...................................... */ +/* Safe unless stated otherwise in Makefile.PL */ +#ifndef LT_FORKSAFE +# define LT_FORKSAFE 1 +#endif + #ifndef LT_MULTIPLICITY # if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT) # define LT_MULTIPLICITY 1 @@ -88,6 +93,44 @@ # define aMY_CXT_ #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 +#else +# define LT_CHECK_MUTEX_LOCK OP_REFCNT_LOCK +# define LT_CHECK_MUTEX_UNLOCK OP_REFCNT_UNLOCK +#endif + +typedef OP *(*lt_ck_t)(pTHX_ OP *); + +#ifdef wrap_op_checker + +# define lt_ck_replace(T, NC, OCP) wrap_op_checker((T), (NC), (OCP)) + +#else + +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) { + *old_ck_p = PL_check[type]; + PL_check[type] = new_ck; + } + LT_CHECK_MUTEX_UNLOCK; +} + +#endif + +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) { + PL_check[type] = *old_ck_p; + *old_ck_p = 0; + } + LT_CHECK_MUTEX_UNLOCK; +} + /* --- Helpers ------------------------------------------------------------- */ /* ... Thread-safe hints ................................................... */ @@ -140,14 +183,15 @@ typedef SV lt_hint_t; /* ... "Seen" pointer table ................................................ */ -#if !LT_HAS_RPEEP - #define PTABLE_NAME ptable_seen #define PTABLE_VAL_FREE(V) NOOP #include "ptable.h" -#endif /* !LT_HAS_RPEEP */ +/* PerlMemShared_free() needs the [ap]PTBLMS_? default values */ +#define ptable_seen_store(T, K, V) ptable_seen_store(aPTBLMS_ (T), (K), (V)) +#define ptable_seen_clear(T) ptable_seen_clear(aPTBLMS_ (T)) +#define ptable_seen_free(T) ptable_seen_free(aPTBLMS_ (T)) /* ... Global data ......................................................... */ @@ -158,9 +202,7 @@ typedef struct { ptable *tbl; /* It really is a ptable_hints */ tTHX owner; #endif -#if !LT_HAS_RPEEP ptable *seen; /* It really is a ptable_seen */ -#endif SV *default_meth; } my_cxt_t; @@ -223,9 +265,7 @@ STATIC void lt_thread_cleanup(pTHX_ void *ud) { dMY_CXT; ptable_hints_free(MY_CXT.tbl); -#if !LT_HAS_RPEEP ptable_seen_free(MY_CXT.seen); -#endif /* !LT_HAS_RPEEP */ } #endif /* LT_THREADSAFE */ @@ -289,7 +329,7 @@ STATIC SV *lt_tag(pTHX_ SV *value) { value = SvRV(value); if (SvTYPE(value) >= SVt_PVCV) { code = value; - SvREFCNT_inc_simple_NN(code); + SvREFCNT_inc_simple_void_NN(code); } } @@ -352,7 +392,7 @@ STATIC SV *lt_hint(pTHX) { 0, lt_hash); #else - SV **val = hv_fetch(GvHV(PL_hintgv), __PACKAGE__, __PACKAGE_LEN__, lt_hash); + SV **val = hv_fetch(GvHV(PL_hintgv), __PACKAGE__, __PACKAGE_LEN__, 0); if (!val) return 0; hint = *val; @@ -369,6 +409,7 @@ STATIC SV *lt_hint(pTHX) { /* PerlMemShared_free() needs the [ap]PTBLMS_? default values */ #define ptable_map_store(T, K, V) ptable_map_store(aPTBLMS_ (T), (K), (V)) +#define ptable_map_delete(T, K) ptable_map_delete(aPTBLMS_ (T), (K)) STATIC ptable *lt_op_map = NULL; @@ -395,10 +436,10 @@ typedef struct { SV *type_pkg; SV *type_meth; #endif /* !MULTIPLICITY */ - OP *(*old_pp_padsv)(pTHX); + OP *(*old_pp)(pTHX); } lt_op_info; -STATIC void lt_map_store(pTHX_ const OP *o, SV *orig_pkg, SV *type_pkg, SV *type_meth, OP *(*old_pp_padsv)(pTHX)) { +STATIC void lt_map_store(pTHX_ const OP *o, SV *orig_pkg, SV *type_pkg, SV *type_meth, OP *(*old_pp)(pTHX)) { #define lt_map_store(O, OP, TP, TM, PP) lt_map_store(aTHX_ (O), (OP), (TP), (TM), (PP)) lt_op_info *oi; @@ -449,7 +490,7 @@ STATIC void lt_map_store(pTHX_ const OP *o, SV *orig_pkg, SV *type_pkg, SV *type oi->type_meth = type_meth; #endif /* !MULTIPLICITY */ - oi->old_pp_padsv = old_pp_padsv; + oi->old_pp = old_pp; LT_UNLOCK(<_op_map_mutex); } @@ -487,62 +528,58 @@ STATIC OP *lt_pp_padsv(pTHX) { lt_op_info oi; if (lt_map_fetch(PL_op, &oi)) { - PADOFFSET targ = PL_op->op_targ; - SV *sv = PAD_SVl(targ); - - if (sv) { - SV *orig_pkg, *type_pkg, *type_meth; - int items; - dSP; + SV *orig_pkg, *type_pkg, *type_meth; + int items; + dSP; + dTARGET; - ENTER; - SAVETMPS; + ENTER; + SAVETMPS; #ifdef MULTIPLICITY - { - STRLEN op_len = oi.orig_pkg_len, tp_len = oi.type_pkg_len; - char *buf = oi.buf; - orig_pkg = sv_2mortal(newSVpvn(buf, op_len)); - SvREADONLY_on(orig_pkg); - buf += op_len; - type_pkg = sv_2mortal(newSVpvn(buf, tp_len)); - SvREADONLY_on(type_pkg); - buf += tp_len; - type_meth = sv_2mortal(newSVpvn(buf, oi.type_meth_len)); - SvREADONLY_on(type_meth); - } + { + STRLEN op_len = oi.orig_pkg_len, tp_len = oi.type_pkg_len; + char *buf = oi.buf; + orig_pkg = sv_2mortal(newSVpvn(buf, op_len)); + SvREADONLY_on(orig_pkg); + buf += op_len; + type_pkg = sv_2mortal(newSVpvn(buf, tp_len)); + SvREADONLY_on(type_pkg); + buf += tp_len; + type_meth = sv_2mortal(newSVpvn(buf, oi.type_meth_len)); + SvREADONLY_on(type_meth); + } #else /* MULTIPLICITY */ - orig_pkg = oi.orig_pkg; - type_pkg = oi.type_pkg; - type_meth = oi.type_meth; + orig_pkg = oi.orig_pkg; + type_pkg = oi.type_pkg; + type_meth = oi.type_meth; #endif /* !MULTIPLICITY */ - PUSHMARK(SP); - EXTEND(SP, 3); - PUSHs(type_pkg); - PUSHs(sv); - PUSHs(orig_pkg); - PUTBACK; - - items = call_sv(type_meth, G_ARRAY | G_METHOD); - - SPAGAIN; - switch (items) { - case 0: - break; - case 1: - sv_setsv(sv, POPs); - break; - default: - croak("Typed scalar initializer method should return zero or one scalar, but got %d", items); - } - PUTBACK; + PUSHMARK(SP); + EXTEND(SP, 3); + PUSHs(type_pkg); + PUSHTARG; + PUSHs(orig_pkg); + PUTBACK; - FREETMPS; - LEAVE; + items = call_sv(type_meth, G_ARRAY | G_METHOD); + + SPAGAIN; + switch (items) { + case 0: + break; + case 1: + sv_setsv(TARG, POPs); + break; + default: + croak("Typed scalar initializer method should return zero or one scalar, but got %d", items); } + PUTBACK; + + FREETMPS; + LEAVE; - return oi.old_pp_padsv(aTHX); + return oi.old_pp(aTHX); } return PL_op->op_ppaddr(aTHX); @@ -617,12 +654,12 @@ STATIC OP *lt_ck_padany(pTHX_ OP *o) { if (!type_pkg) { type_pkg = orig_pkg; - SvREFCNT_inc(orig_pkg); + SvREFCNT_inc_simple_void_NN(orig_pkg); } if (!type_meth) { type_meth = orig_meth; - SvREFCNT_inc(orig_meth); + SvREFCNT_inc_simple_void_NN(orig_meth); } lt_map_store(o, orig_pkg, type_pkg, type_meth, o->op_ppaddr); @@ -646,39 +683,23 @@ STATIC OP *lt_ck_padsv(pTHX_ OP *o) { STATIC peep_t lt_old_peep = 0; /* This is actually the rpeep past 5.13.5 */ -#if !LT_HAS_RPEEP -# define LT_PEEP_REC_PROTO STATIC void lt_peep_rec(pTHX_ OP *o, ptable *seen) -#else /* !LT_HAS_RPEEP */ -# define LT_PEEP_REC_PROTO STATIC void lt_peep_rec(pTHX_ OP *o) -#endif /* LT_HAS_RPEEP */ - -LT_PEEP_REC_PROTO; -LT_PEEP_REC_PROTO { -#if !LT_HAS_RPEEP -# define lt_peep_rec(O) lt_peep_rec(aTHX_ (O), seen) -#else /* !LT_HAS_RPEEP */ -# define lt_peep_rec(O) lt_peep_rec(aTHX_ (O)) -#endif /* LT_HAS_RPEEP */ - -#if !LT_HAS_RPEEP - if (ptable_fetch(seen, o)) - return; -#endif - +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) { lt_op_info *oi = NULL; -#if !LT_HAS_RPEEP + if (ptable_fetch(seen, o)) + break; ptable_seen_store(seen, o, o); -#endif + switch (o->op_type) { case OP_PADSV: if (o->op_ppaddr != lt_pp_padsv && o->op_private & OPpLVAL_INTRO) { LT_LOCK(<_op_map_mutex); oi = ptable_fetch(lt_op_map, o); if (oi) { - oi->old_pp_padsv = o->op_ppaddr; - o->op_ppaddr = lt_pp_padsv; + oi->old_pp = o->op_ppaddr; + o->op_ppaddr = lt_pp_padsv; } LT_UNLOCK(<_op_map_mutex); } @@ -724,15 +745,14 @@ LT_PEEP_REC_PROTO { } STATIC void lt_peep(pTHX_ OP *o) { -#if !LT_HAS_RPEEP dMY_CXT; ptable *seen = MY_CXT.seen; - ptable_seen_clear(seen); -#endif /* !LT_HAS_RPEEP */ - lt_old_peep(aTHX_ o); + + ptable_seen_clear(seen); lt_peep_rec(o); + ptable_seen_clear(seen); } /* --- Interpreter setup/teardown ------------------------------------------ */ @@ -754,16 +774,12 @@ STATIC void lt_teardown(pTHX_ void *root) { #if LT_THREADSAFE ptable_hints_free(MY_CXT.tbl); #endif -#if !LT_HAS_RPEEP ptable_seen_free(MY_CXT.seen); -#endif SvREFCNT_dec(MY_CXT.default_meth); } - PL_check[OP_PADANY] = MEMBER_TO_FPTR(lt_old_ck_padany); - lt_old_ck_padany = 0; - PL_check[OP_PADSV] = MEMBER_TO_FPTR(lt_old_ck_padsv); - lt_old_ck_padsv = 0; + lt_ck_restore(OP_PADANY, <_old_ck_padany); + lt_ck_restore(OP_PADSV, <_old_ck_padsv); #if LT_HAS_RPEEP PL_rpeepp = lt_old_peep; @@ -786,17 +802,13 @@ STATIC void lt_setup(pTHX) { MY_CXT.tbl = ptable_new(); MY_CXT.owner = aTHX; #endif -#if !LT_HAS_RPEEP MY_CXT.seen = ptable_new(); -#endif MY_CXT.default_meth = newSVpvn("TYPEDSCALAR", 11); SvREADONLY_on(MY_CXT.default_meth); } - lt_old_ck_padany = PL_check[OP_PADANY]; - PL_check[OP_PADANY] = MEMBER_TO_FPTR(lt_ck_padany); - lt_old_ck_padsv = PL_check[OP_PADSV]; - PL_check[OP_PADSV] = MEMBER_TO_FPTR(lt_ck_padsv); + lt_ck_replace(OP_PADANY, lt_ck_padany, <_old_ck_padany); + lt_ck_replace(OP_PADSV, lt_ck_padsv, <_old_ck_padsv); #if LT_HAS_RPEEP lt_old_peep = PL_rpeepp; @@ -837,6 +849,7 @@ BOOT: stash = gv_stashpvn(__PACKAGE__, __PACKAGE_LEN__, 1); newCONSTSUB(stash, "LT_THREADSAFE", newSVuv(LT_THREADSAFE)); + newCONSTSUB(stash, "LT_FORKSAFE", newSVuv(LT_FORKSAFE)); } lt_setup(); @@ -849,9 +862,7 @@ CLONE(...) PROTOTYPE: DISABLE PREINIT: ptable *t; -#if !LT_HAS_RPEEP ptable *s; -#endif SV *cloned_default_meth; PPCODE: { @@ -865,17 +876,13 @@ PPCODE: cloned_default_meth = lt_dup_inc(MY_CXT.default_meth, &ud); lt_ptable_clone_ud_deinit(ud); } -#if !LT_HAS_RPEEP s = ptable_new(); -#endif } { MY_CXT_CLONE; MY_CXT.tbl = t; MY_CXT.owner = aTHX; -#if !LT_HAS_RPEEP MY_CXT.seen = s; -#endif MY_CXT.default_meth = cloned_default_meth; } reap(3, lt_thread_cleanup, NULL);