X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Types.xs;h=faa8740d1e1b22742ef04fe049346d4a7a92bb9e;hb=5373b6a046da88066af5d450a6b7e2d3ffe59d64;hp=9c02bd8a434caf16346b08e3edfb0dfa6c6cc064;hpb=0fc6f069827693c23dd72b19be85c27e0b4a2396;p=perl%2Fmodules%2FLexical-Types.git diff --git a/Types.xs b/Types.xs index 9c02bd8..faa8740 100644 --- a/Types.xs +++ b/Types.xs @@ -93,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 ................................................... */ @@ -398,10 +436,65 @@ 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_op_info_call(pTHX_ const lt_op_info *oi, SV *sv) { +#define lt_op_info_call(O, S) lt_op_info_call(aTHX_ (O), (S)) + SV *orig_pkg, *type_pkg, *type_meth; + int items; + dSP; + + 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); + } +#else /* MULTIPLICITY */ + 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; + + FREETMPS; + LEAVE; + + return; +} + +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; @@ -452,7 +545,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); } @@ -490,58 +583,9 @@ STATIC OP *lt_pp_padsv(pTHX) { lt_op_info oi; if (lt_map_fetch(PL_op, &oi)) { - SV *orig_pkg, *type_pkg, *type_meth; - int items; - dSP; dTARGET; - - 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); - } -#else /* MULTIPLICITY */ - 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); - PUSHTARG; - PUSHs(orig_pkg); - PUTBACK; - - 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); + lt_op_info_call(&oi, TARG); + return oi.old_pp(aTHX); } return PL_op->op_ppaddr(aTHX); @@ -660,8 +704,8 @@ STATIC void lt_peep_rec(pTHX_ OP *o, ptable *seen) { 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); } @@ -740,10 +784,8 @@ STATIC void lt_teardown(pTHX_ void *root) { 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; @@ -771,10 +813,8 @@ STATIC void lt_setup(pTHX) { 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;