X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Magic.xs;h=ec49843183def6fa826c8f2edd5e5d5712f11a7c;hb=ca0345bc78a38a61ec2f3886021532a7a205a0b2;hp=c692014ba849694ab98fb37e8f47ddb5726f53c9;hpb=73394f27221b951647864ce37cf623661c480d2e;p=perl%2Fmodules%2FVariable-Magic.git diff --git a/Magic.xs b/Magic.xs index c692014..ec49843 100644 --- a/Magic.xs +++ b/Magic.xs @@ -12,10 +12,6 @@ #define __PACKAGE__ "Variable::Magic" -#define PERL_VERSION_GE(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S)))))) - -#define PERL_VERSION_LE(R, V, S) (PERL_REVISION < (R) || (PERL_REVISION == (R) && (PERL_VERSION < (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION <= (S)))))) - #ifndef VMG_PERL_PATCHLEVEL # ifdef PERL_PATCHNUM # define VMG_PERL_PATCHLEVEL PERL_PATCHNUM @@ -24,9 +20,11 @@ # endif #endif -#define VMG_HAS_PERL_OR(P, R, V, S) ((VMG_PERL_PATCHLEVEL >= (P)) || (!VMG_PERL_PATCHLEVEL && PERL_VERSION_GE((R), (V), (S)))) +#define VMG_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S)))))) + +#define VMG_HAS_PERL_BRANCH(R, V, S) (PERL_REVISION == (R) && PERL_VERSION == (V) && PERL_SUBVERSION >= (S)) -#define VMG_HAS_PERL_AND(P, R, V, S) (PERL_VERSION_GE((R), (V), (S)) && (!VMG_PERL_PATCHLEVEL || (VMG_PERL_PATCHLEVEL >= (P)))) +#define VMG_HAS_PERL_MAINT(R, V, S, P) (PERL_REVISION == (R) && PERL_VERSION == (V) && (VMG_PERL_PATCHLEVEL >= (P) || (!VMG_PERL_PATCHLEVEL && PERL_SUBVERSION >= (S)))) /* --- Threads and multiplicity -------------------------------------------- */ @@ -38,23 +36,32 @@ # define dNOOP #endif -#if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT) -# define VMG_MULTIPLICITY 1 -# ifndef tTHX -# define tTHX PerlInterpreter* +#ifndef VMG_MULTIPLICITY +# if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT) +# define VMG_MULTIPLICITY 1 +# else +# define VMG_MULTIPLICITY 0 # endif -#else -# define VMG_MULTIPLICITY 0 +#endif +#if VMG_MULTIPLICITY && !defined(tTHX) +# define tTHX PerlInterpreter* #endif -#if VMG_MULTIPLICITY && defined(dMY_CXT) && defined(MY_CXT) && defined(START_MY_CXT) && defined(MY_CXT_INIT) && defined(MY_CXT_CLONE) +#if VMG_MULTIPLICITY && defined(USE_ITHREADS) && defined(dMY_CXT) && defined(MY_CXT) && defined(START_MY_CXT) && defined(MY_CXT_INIT) && (defined(MY_CXT_CLONE) || defined(dMY_CXT_SV)) # define VMG_THREADSAFE 1 +# ifndef MY_CXT_CLONE +# define MY_CXT_CLONE \ + dMY_CXT_SV; \ + my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1)); \ + Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t); \ + sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) +# endif #else # define VMG_THREADSAFE 0 # undef dMY_CXT # define dMY_CXT dNOOP # undef MY_CXT -# define MY_CXT vmg_globaldata +# define MY_CXT vmg_globaldata # undef START_MY_CXT # define START_MY_CXT STATIC my_cxt_t MY_CXT; # undef MY_CXT_INIT @@ -63,7 +70,7 @@ # define MY_CXT_CLONE NOOP #endif -#if VMG_MULTIPLICITY +#if VMG_THREADSAFE STATIC SV *vmg_clone(pTHX_ SV *sv, tTHX owner) { #define vmg_clone(P, O) vmg_clone(aTHX_ (P), (O)) @@ -74,7 +81,7 @@ STATIC SV *vmg_clone(pTHX_ SV *sv, tTHX owner) { return sv_dup(sv, ¶m); } -#endif /* VMG_MULTIPLICITY */ +#endif /* VMG_THREADSAFE */ /* --- Compatibility ------------------------------------------------------- */ @@ -106,27 +113,35 @@ STATIC SV *vmg_clone(pTHX_ SV *sv, tTHX owner) { # define MGf_LOCAL 0 #endif -/* uvar magic and Hash::Util::FieldHash were commited with p28419 */ -#if VMG_HAS_PERL_AND(28419, 5, 9, 4) +/* uvar magic and Hash::Util::FieldHash were commited with 28419 */ +#if VMG_HAS_PERL_MAINT(5, 9, 4, 28419) || VMG_HAS_PERL(5, 10, 0) # define VMG_UVAR 1 #else # define VMG_UVAR 0 #endif -#if !defined(VMG_COMPAT_ARRAY_PUSH_NOLEN) && VMG_HAS_PERL_OR(25854, 5, 9, 3) +/* Applied to dev-5.9 as 25854, integrated to maint-5.8 as 28160 */ +#if !defined(VMG_COMPAT_ARRAY_PUSH_NOLEN) && (VMG_HAS_PERL_MAINT(5, 8, 9, 28160) || VMG_HAS_PERL_MAINT(5, 9, 3, 25854) || VMG_HAS_PERL(5, 10, 0)) # define VMG_COMPAT_ARRAY_PUSH_NOLEN 1 #else # define VMG_COMPAT_ARRAY_PUSH_NOLEN 0 #endif -/* since 5.9.5 - see #43357 */ -#if VMG_HAS_PERL_OR(31473, 5, 9, 5) +/* Applied to dev-5.11 as 34908 */ +#if VMG_HAS_PERL_MAINT(5, 11, 0, 34908) +# define VMG_COMPAT_ARRAY_UNSHIFT_NOLEN_VOID 1 +#else +# define VMG_COMPAT_ARRAY_UNSHIFT_NOLEN_VOID 0 +#endif + +/* Applied to dev-5.9 as 31473 (see #43357), integrated to maint-5.8 as 32542 */ +#if VMG_HAS_PERL_MAINT(5, 8, 9, 32542) || VMG_HAS_PERL_MAINT(5, 9, 5, 31473) || VMG_HAS_PERL(5, 10, 0) # define VMG_COMPAT_ARRAY_UNDEF_CLEAR 1 #else # define VMG_COMPAT_ARRAY_UNDEF_CLEAR 0 #endif -#if VMG_HAS_PERL_OR(32969, 5, 11, 0) +#if VMG_HAS_PERL_MAINT(5, 11, 0, 32969) # define VMG_COMPAT_SCALAR_LENGTH_NOLEN 1 #else # define VMG_COMPAT_SCALAR_LENGTH_NOLEN 0 @@ -161,10 +176,7 @@ STATIC void vmg_sv_magicuvar(pTHX_ SV *sv, const char *uf, I32 len) { #define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION -typedef struct { - HV *wizz; - U16 count; -} my_cxt_t; +typedef HV * my_cxt_t; START_MY_CXT @@ -185,7 +197,7 @@ STATIC U16 vmg_gensig(pTHX) { do { sig = SIG_NBR * Drand01() + SIG_MIN; - } while (hv_exists(MY_CXT.wizz, buf, sprintf(buf, "%u", sig))); + } while (hv_exists(MY_CXT, buf, sprintf(buf, "%u", sig))); return sig; } @@ -244,10 +256,10 @@ STATIC SV *vmg_data_new(pTHX_ SV *ctor, SV *sv, AV *args) { if (count != 1) { croak("Callback needs to return 1 scalar\n"); } nsv = POPs; -#if PERL_VERSION_LE(5, 8, 2) - nsv = sv_newref(nsv); /* Workaround some bug in SvREFCNT_inc() */ -#else +#if VMG_HAS_PERL(5, 8, 3) SvREFCNT_inc(nsv); /* Or it will be destroyed in FREETMPS */ +#else + nsv = sv_newref(nsv); /* Workaround some bug in SvREFCNT_inc() */ #endif PUTBACK; @@ -312,7 +324,7 @@ STATIC UV vmg_cast(pTHX_ SV *sv, SV *wiz, AV *args) { if (w->cb_copy) mg->mg_flags |= MGf_COPY; #endif /* MGf_COPY */ -#if MGf_DUP +#if 0 /* MGf_DUP */ if (w->cb_dup) mg->mg_flags |= MGf_DUP; #endif /* MGf_DUP */ @@ -544,6 +556,12 @@ STATIC int vmg_svt_clear(pTHX_ SV *sv, MAGIC *mg) { STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) { /* So that it can survive tmp cleanup in vmg_cb_call */ SvREFCNT_inc(sv); +#if !VMG_HAS_PERL_MAINT(5, 11, 0, 32686) + /* The previous magic tokens were freed but the magic chain wasn't updated, so + * if you access the sv from the callback the old deleted magics will trigger + * and cause memory misreads. Change 32686 solved it that way : */ + SvMAGIC_set(sv, mg); +#endif /* Perl_mg_free will get rid of the magic and decrement mg->mg_obj and * mg->mg_ptr reference count */ return vmg_cb_call1(SV2MGWIZ(mg->mg_ptr)->cb_free, sv, mg->mg_obj); @@ -551,7 +569,7 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) { #if MGf_COPY STATIC int vmg_svt_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key, -# if VMG_HAS_PERL_AND(33256, 5, 11, 0) +# if VMG_HAS_PERL_MAINT(5, 11, 0, 33256) I32 keylen # else int keylen @@ -648,9 +666,10 @@ STATIC int vmg_wizard_free(pTHX_ SV *wiz, MAGIC *mg) { w->owner = NULL; #endif /* VMG_MULTIPLICITY */ - dMY_CXT; - if (hv_delete(MY_CXT.wizz, buf, sprintf(buf, "%u", w->sig), 0)) { - --MY_CXT.count; + { + dMY_CXT; + if (hv_delete(MY_CXT, buf, sprintf(buf, "%u", w->sig), 0) != wiz) + return 0; } SvFLAGS(wiz) |= SVf_BREAK; FREETMPS; @@ -664,7 +683,7 @@ STATIC int vmg_wizard_free(pTHX_ SV *wiz, MAGIC *mg) { #if MGf_COPY if (w->cb_copy != NULL) { SvREFCNT_dec(SvRV(w->cb_copy)); } #endif /* MGf_COPY */ -#if MGf_DUP +#if 0 /* MGf_DUP */ if (w->cb_dup != NULL) { SvREFCNT_dec(SvRV(w->cb_dup)); } #endif /* MGf_DUP */ #if MGf_LOCAL @@ -739,11 +758,11 @@ STATIC U16 vmg_wizard_sig(pTHX_ SV *wiz) { croak(vmg_invalid_wiz); } - dMY_CXT; - - if (!hv_fetch(MY_CXT.wizz, buf, sprintf(buf, "%u", sig), 0)) - sig = 0; - + { + dMY_CXT; + if (!hv_fetch(MY_CXT, buf, sprintf(buf, "%u", sig), 0)) + sig = 0; + } return sig; } @@ -766,10 +785,11 @@ STATIC SV *vmg_wizard_wiz(pTHX_ SV *wiz) { croak(vmg_invalid_wiz); } - dMY_CXT; - - return (old = hv_fetch(MY_CXT.wizz, buf, sprintf(buf, "%u", sig), 0)) - ? *old : NULL; + { + dMY_CXT; + return (old = hv_fetch(MY_CXT, buf, sprintf(buf, "%u", sig), 0)) + ? *old : NULL; + } } #define VMG_SET_CB(S, N) \ @@ -786,11 +806,11 @@ STATIC SV *vmg_wizard_wiz(pTHX_ SV *wiz) { w->cb_ ## N = NULL; \ } -#if VMG_MULTIPLICITY +#if VMG_THREADSAFE #define VMG_CLONE_CB(N) \ - z->cb_ ## N = (w->cb_ ## N) ? newRV_noinc(vmg_clone(SvRV(w->cb_ ## N), \ - w->owner)) \ + z->cb_ ## N = (w->cb_ ## N) ? newRV_inc(vmg_clone(SvRV(w->cb_ ## N), \ + w->owner)) \ : NULL; STATIC MGWIZ *vmg_wizard_clone(pTHX_ const MGWIZ *w) { @@ -831,7 +851,7 @@ STATIC MGWIZ *vmg_wizard_clone(pTHX_ const MGWIZ *w) { return z; } -#endif /* VMG_MULTIPLICITY */ +#endif /* VMG_THREADSAFE */ /* --- XS ------------------------------------------------------------------ */ @@ -843,9 +863,8 @@ BOOT: { HV *stash; MY_CXT_INIT; - MY_CXT.wizz = newHV(); - hv_iterinit(MY_CXT.wizz); /* Allocate iterator */ - MY_CXT.count = 0; + MY_CXT = newHV(); + hv_iterinit(MY_CXT); /* Allocate iterator */ stash = gv_stashpv(__PACKAGE__, 1); newCONSTSUB(stash, "SIG_MIN", newSVuv(SIG_MIN)); newCONSTSUB(stash, "SIG_MAX", newSVuv(SIG_MAX)); @@ -856,6 +875,8 @@ BOOT: newCONSTSUB(stash, "VMG_UVAR", newSVuv(VMG_UVAR)); newCONSTSUB(stash, "VMG_COMPAT_ARRAY_PUSH_NOLEN", newSVuv(VMG_COMPAT_ARRAY_PUSH_NOLEN)); + newCONSTSUB(stash, "VMG_COMPAT_ARRAY_UNSHIFT_NOLEN_VOID", + newSVuv(VMG_COMPAT_ARRAY_UNSHIFT_NOLEN_VOID)); newCONSTSUB(stash, "VMG_COMPAT_ARRAY_UNDEF_CLEAR", newSVuv(VMG_COMPAT_ARRAY_UNDEF_CLEAR)); newCONSTSUB(stash, "VMG_COMPAT_SCALAR_LENGTH_NOLEN", @@ -869,22 +890,19 @@ CLONE(...) PROTOTYPE: DISABLE PREINIT: HV *hv; - U16 count; CODE: #if VMG_THREADSAFE { HE *key; dMY_CXT; - count = MY_CXT.count; hv = newHV(); hv_iterinit(hv); /* Allocate iterator */ - hv_iterinit(MY_CXT.wizz); - while (key = hv_iternext(MY_CXT.wizz)) { + hv_iterinit(MY_CXT); + while ((key = hv_iternext(MY_CXT))) { STRLEN len; char *sig = HePV(key, len); SV *sv; MAGIC *mg; - MGWIZ *w; sv = MGWIZ2SV(vmg_wizard_clone(SV2MGWIZ(HeVAL(key)))); mg = sv_magicext(sv, NULL, PERL_MAGIC_ext, &vmg_wizard_vtbl, NULL, 0); mg->mg_private = SIG_WIZ; @@ -894,8 +912,7 @@ CODE: } { MY_CXT_CLONE; - MY_CXT.wizz = hv; - MY_CXT.count = count; + MY_CXT = hv; } #endif /* VMG_THREADSAFE */ @@ -933,12 +950,12 @@ CODE: if (SvOK(svsig)) { SV **old; sig = vmg_sv2sig(svsig); - if ((old = hv_fetch(MY_CXT.wizz, buf, sprintf(buf, "%u", sig), 0))) { + if ((old = hv_fetch(MY_CXT, buf, sprintf(buf, "%u", sig), 0))) { ST(0) = sv_2mortal(newRV_inc(*old)); XSRETURN(1); } } else { - if (MY_CXT.count >= SIG_NBR) { croak(vmg_toomanysigs); } + if (HvKEYS(MY_CXT) >= SIG_NBR) { croak(vmg_toomanysigs); } sig = vmg_gensig(); } @@ -984,8 +1001,7 @@ CODE: mg->mg_private = SIG_WIZ; SvREADONLY_on(sv); - hv_store(MY_CXT.wizz, buf, sprintf(buf, "%u", sig), sv, 0); - ++MY_CXT.count; + hv_store(MY_CXT, buf, sprintf(buf, "%u", sig), sv, 0); RETVAL = newRV_noinc(sv); OUTPUT: @@ -995,7 +1011,7 @@ SV *gensig() PROTOTYPE: CODE: dMY_CXT; - if (MY_CXT.count >= SIG_NBR) { croak(vmg_toomanysigs); } + if (HvKEYS(MY_CXT) >= SIG_NBR) { croak(vmg_toomanysigs); } RETVAL = newSVuv(vmg_gensig()); OUTPUT: RETVAL