X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Magic.xs;h=3a170c0332a32e77402fffcf5aa91c9816f9c4bd;hb=354ba160bf92d157a773528894a63967565fcd19;hp=1920c7880c80540256905bd955aab2381969ba9b;hpb=110ed6888ddf13f751e5ee0de5b0d8188e2f956e;p=perl%2Fmodules%2FVariable-Magic.git diff --git a/Magic.xs b/Magic.xs index 1920c78..3a170c0 100644 --- a/Magic.xs +++ b/Magic.xs @@ -363,26 +363,26 @@ STATIC void vmg_mgwiz_free(pTHX_ MGWIZ *w) { if (!w) return; - if (w->cb_data) SvREFCNT_dec(SvRV(w->cb_data)); - if (w->cb_get) SvREFCNT_dec(SvRV(w->cb_get)); - if (w->cb_set) SvREFCNT_dec(SvRV(w->cb_set)); - if (w->cb_len) SvREFCNT_dec(SvRV(w->cb_len)); - if (w->cb_clear) SvREFCNT_dec(SvRV(w->cb_clear)); - if (w->cb_free) SvREFCNT_dec(SvRV(w->cb_free)); + if (w->cb_data) SvREFCNT_dec(w->cb_data); + if (w->cb_get) SvREFCNT_dec(w->cb_get); + if (w->cb_set) SvREFCNT_dec(w->cb_set); + if (w->cb_len) SvREFCNT_dec(w->cb_len); + if (w->cb_clear) SvREFCNT_dec(w->cb_clear); + if (w->cb_free) SvREFCNT_dec(w->cb_free); #if MGf_COPY - if (w->cb_copy) SvREFCNT_dec(SvRV(w->cb_copy)); + if (w->cb_copy) SvREFCNT_dec(w->cb_copy); #endif /* MGf_COPY */ #if 0 /* MGf_DUP */ - if (w->cb_dup) SvREFCNT_dec(SvRV(w->cb_dup)); + if (w->cb_dup) SvREFCNT_dec(w->cb_dup); #endif /* MGf_DUP */ #if MGf_LOCAL - if (w->cb_local) SvREFCNT_dec(SvRV(w->cb_local)); + if (w->cb_local) SvREFCNT_dec(w->cb_local); #endif /* MGf_LOCAL */ #if VMG_UVAR - if (w->cb_fetch) SvREFCNT_dec(SvRV(w->cb_fetch)); - if (w->cb_store) SvREFCNT_dec(SvRV(w->cb_store)); - if (w->cb_exists) SvREFCNT_dec(SvRV(w->cb_exists)); - if (w->cb_delete) SvREFCNT_dec(SvRV(w->cb_delete)); + if (w->cb_fetch) SvREFCNT_dec(w->cb_fetch); + if (w->cb_store) SvREFCNT_dec(w->cb_store); + if (w->cb_exists) SvREFCNT_dec(w->cb_exists); + if (w->cb_delete) SvREFCNT_dec(w->cb_delete); #endif /* VMG_UVAR */ Safefree(w->vtbl); @@ -394,8 +394,7 @@ STATIC void vmg_mgwiz_free(pTHX_ MGWIZ *w) { #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) ? vmg_clone(w->cb_ ## N, w->owner) \ : NULL; STATIC MGWIZ *vmg_mgwiz_clone(pTHX_ const MGWIZ *w) { @@ -517,7 +516,7 @@ STATIC MGVTBL vmg_wizard_vtbl = { STATIC SV *vmg_wizard_new(pTHX_ const MGWIZ *w) { #define vmg_wizard_new(W) vmg_wizard_new(aTHX_ (W)) - SV *wiz = newSVuv(PTR2UV(w)); + SV *wiz = newSVuv(PTR2IV(w)); if (w) { MAGIC *mg = sv_magicext(wiz, NULL, PERL_MAGIC_ext, &vmg_wizard_vtbl, NULL, 0); @@ -528,7 +527,7 @@ STATIC SV *vmg_wizard_new(pTHX_ const MGWIZ *w) { return wiz; } -STATIC SV *vmg_wizard_validate(pTHX_ SV *wiz) { +STATIC const SV *vmg_wizard_validate(pTHX_ const SV *wiz) { #define vmg_wizard_validate(W) vmg_wizard_validate(aTHX_ (W)) if (SvROK(wiz)) { wiz = SvRV(wiz); @@ -537,9 +536,11 @@ STATIC SV *vmg_wizard_validate(pTHX_ SV *wiz) { } croak(vmg_invalid_wiz); + /* Not reached */ + return NULL; } -#define vmg_wizard_id(W) SvUV((SV *) (W)) +#define vmg_wizard_id(W) SvIVX((const SV *) (W)) #define vmg_wizard_main_mgwiz(W) INT2PTR(const MGWIZ *, vmg_wizard_id(W)) /* ... Wizard destructor ................................................... */ @@ -566,8 +567,8 @@ STATIC int vmg_wizard_free(pTHX_ SV *sv, MAGIC *mg) { #if VMG_THREADSAFE -STATIC const MGWIZ *vmg_wizard_mgwiz(pTHX_ SV *wiz) { -#define vmg_wizard_mgwiz(W) vmg_wizard_mgwiz(aTHX_ ((SV *) (W))) +STATIC const MGWIZ *vmg_wizard_mgwiz(pTHX_ const SV *wiz) { +#define vmg_wizard_mgwiz(W) vmg_wizard_mgwiz(aTHX_ ((const SV *) (W))) const MGWIZ *w; w = vmg_wizard_main_mgwiz(wiz); @@ -588,10 +589,9 @@ STATIC const MGWIZ *vmg_wizard_mgwiz(pTHX_ SV *wiz) { /* --- User-level functions implementation --------------------------------- */ -STATIC const MAGIC *vmg_find(pTHX_ const SV *sv, SV *wiz) { -#define vmg_find(S, W) vmg_find(aTHX_ (S), (W)) +STATIC const MAGIC *vmg_find(const SV *sv, const SV *wiz) { const MAGIC *mg, *moremagic; - UV wid; + IV wid; if (SvTYPE(sv) < SVt_PVMG) return NULL; @@ -600,7 +600,7 @@ STATIC const MAGIC *vmg_find(pTHX_ const SV *sv, SV *wiz) { for (mg = SvMAGIC(sv); mg; mg = moremagic) { moremagic = mg->mg_moremagic; if (mg->mg_type == PERL_MAGIC_ext && mg->mg_private == SIG_WIZ) { - UV zid = vmg_wizard_id(mg->mg_ptr); + IV zid = vmg_wizard_id(mg->mg_ptr); if (zid == wid) return mg; } @@ -611,10 +611,10 @@ STATIC const MAGIC *vmg_find(pTHX_ const SV *sv, SV *wiz) { /* ... Construct private data .............................................. */ -STATIC SV *vmg_data_new(pTHX_ SV *ctor, SV *sv, AV *args) { -#define vmg_data_new(C, S, A) vmg_data_new(aTHX_ (C), (S), (A)) +STATIC SV *vmg_data_new(pTHX_ SV *ctor, SV *sv, SV **args, I32 items) { +#define vmg_data_new(C, S, A, I) vmg_data_new(aTHX_ (C), (S), (A), (I)) + I32 i; SV *nsv; - I32 i, alen = (args == NULL) ? 0 : av_len(args); dSP; @@ -622,10 +622,10 @@ STATIC SV *vmg_data_new(pTHX_ SV *ctor, SV *sv, AV *args) { SAVETMPS; PUSHMARK(SP); - EXTEND(SP, alen + 1); + EXTEND(SP, items + 1); PUSHs(sv_2mortal(newRV_inc(sv))); - for (i = 0; i < alen; ++i) - PUSHs(*av_fetch(args, i, 0)); + for (i = 0; i < items; ++i) + PUSHs(args[i]); PUTBACK; call_sv(ctor, G_SCALAR); @@ -645,7 +645,7 @@ STATIC SV *vmg_data_new(pTHX_ SV *ctor, SV *sv, AV *args) { return nsv; } -STATIC SV *vmg_data_get(pTHX_ SV *sv, SV *wiz) { +STATIC SV *vmg_data_get(pTHX_ SV *sv, const SV *wiz) { #define vmg_data_get(S, W) vmg_data_get(aTHX_ (S), (W)) const MAGIC *mg = vmg_find(sv, wiz); return mg ? mg->mg_obj : NULL; @@ -668,8 +668,8 @@ STATIC void vmg_uvar_del(SV *sv, MAGIC *prevmagic, MAGIC *mg, MAGIC *moremagic) } #endif /* VMG_UVAR */ -STATIC UV vmg_cast(pTHX_ SV *sv, SV *wiz, AV *args) { -#define vmg_cast(S, W, A) vmg_cast(aTHX_ (S), (W), (A)) +STATIC UV vmg_cast(pTHX_ SV *sv, const SV *wiz, SV **args, I32 items) { +#define vmg_cast(S, W, A, I) vmg_cast(aTHX_ (S), (W), (A), (I)) MAGIC *mg, *moremagic = NULL; SV *data; const MGWIZ *w; @@ -681,8 +681,9 @@ STATIC UV vmg_cast(pTHX_ SV *sv, SV *wiz, AV *args) { w = vmg_wizard_mgwiz(wiz); oldgmg = SvGMAGICAL(sv); - data = (w->cb_data) ? vmg_data_new(w->cb_data, sv, args) : NULL; + data = (w->cb_data) ? vmg_data_new(w->cb_data, sv, args, items) : NULL; mg = sv_magicext(sv, data, PERL_MAGIC_ext, w->vtbl, (const char *) wiz, HEf_SVKEY); + SvREFCNT_dec(data); mg->mg_private = SIG_WIZ; #if MGf_COPY if (w->cb_copy) @@ -750,13 +751,13 @@ done: return 1; } -STATIC UV vmg_dispell(pTHX_ SV *sv, SV *wiz) { +STATIC UV vmg_dispell(pTHX_ SV *sv, const SV *wiz) { #define vmg_dispell(S, W) vmg_dispell(aTHX_ (S), (W)) #if VMG_UVAR U32 uvars = 0; #endif /* VMG_UVAR */ MAGIC *mg, *prevmagic, *moremagic = NULL; - UV wid = vmg_wizard_id(wiz); + IV wid = vmg_wizard_id(wiz); if (SvTYPE(sv) < SVt_PVMG) return 0; @@ -765,7 +766,7 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, SV *wiz) { moremagic = mg->mg_moremagic; if (mg->mg_type == PERL_MAGIC_ext && mg->mg_private == SIG_WIZ) { const MGWIZ *z = vmg_wizard_mgwiz(mg->mg_ptr); - UV zid = vmg_wizard_id(mg->mg_ptr); + IV zid = vmg_wizard_id(mg->mg_ptr); if (zid == wid) { #if VMG_UVAR /* If the current has no uvar, short-circuit uvar deletion. */ @@ -872,7 +873,7 @@ STATIC void vmg_op_info_init(pTHX_ unsigned int opinfo) { if (!MY_CXT.b__op_stashes[0]) { opclass c; require_pv("B.pm"); - for (c = 0; c < OPc_MAX; ++c) + for (c = OPc_NULL; c < OPc_MAX; ++c) MY_CXT.b__op_stashes[c] = gv_stashpv(vmg_opclassnames[c], 1); } break; @@ -990,7 +991,7 @@ STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) { PUSHs(mg->mg_obj ? mg->mg_obj : &PL_sv_undef); if (t < SVt_PVAV) { STRLEN l; - U8 *s = (U8 *) SvPV_const(sv, l); + const U8 *s = (const U8 *) SvPV_const(sv, l); if (DO_UTF8(sv)) len = utf8_length(s, s + l); else @@ -1028,7 +1029,7 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) { PERL_CONTEXT saved_cx; I32 cxix; #endif - unsigned int had_err, has_err, flags = G_SCALAR | G_EVAL; + I32 had_err, has_err, flags = G_SCALAR | G_EVAL; int ret = 0; dSP; @@ -1233,18 +1234,29 @@ STATIC I32 vmg_svt_val(pTHX_ IV action, SV *sv) { #define VMG_SET_CB(S, N) \ cb = (S); \ - w->cb_ ## N = (SvOK(cb) && SvROK(cb)) ? newRV_inc(SvRV(cb)) : NULL; + w->cb_ ## N = (SvOK(cb) && SvROK(cb)) ? SvREFCNT_inc(SvRV(cb)) : NULL; #define VMG_SET_SVT_CB(S, N) \ cb = (S); \ if (SvOK(cb) && SvROK(cb)) { \ t->svt_ ## N = vmg_svt_ ## N; \ - w->cb_ ## N = newRV_inc(SvRV(cb)); \ + w->cb_ ## N = SvREFCNT_inc(SvRV(cb)); \ } else { \ t->svt_ ## N = NULL; \ w->cb_ ## N = NULL; \ } +#if VMG_THREADSAFE + +STATIC void vmg_cleanup(pTHX_ void *ud) { + dMY_CXT; + + ptable_free(MY_CXT.wizards); + MY_CXT.wizards = NULL; +} + +#endif /* VMG_THREADSAFE */ + /* --- XS ------------------------------------------------------------------ */ MODULE = Variable::Magic PACKAGE = Variable::Magic @@ -1263,6 +1275,7 @@ BOOT: MY_CXT.b__op_stashes[0] = NULL; #if VMG_THREADSAFE MUTEX_INIT(&vmg_op_name_init_mutex); + call_atexit(vmg_cleanup, NULL); #endif stash = gv_stashpv(__PACKAGE__, 1); @@ -1294,10 +1307,9 @@ CLONE(...) PROTOTYPE: DISABLE PREINIT: ptable *t; - int *level; U32 had_b__op_stash = 0; opclass c; -CODE: +PPCODE: { my_cxt_t ud; dMY_CXT; @@ -1306,7 +1318,7 @@ CODE: ud.owner = MY_CXT.owner; ptable_walk(MY_CXT.wizards, vmg_ptable_clone, &ud); - for (c = 0; c < OPc_MAX; ++c) { + for (c = OPc_NULL; c < OPc_MAX; ++c) { if (MY_CXT.b__op_stashes[c]) had_b__op_stash |= (((U32) 1) << c); } @@ -1315,11 +1327,12 @@ CODE: MY_CXT_CLONE; MY_CXT.wizards = t; MY_CXT.owner = aTHX; - for (c = 0; c < OPc_MAX; ++c) { + for (c = OPc_NULL; c < OPc_MAX; ++c) { MY_CXT.b__op_stashes[c] = (had_b__op_stash & (((U32) 1) << c)) ? gv_stashpv(vmg_opclassnames[c], 1) : NULL; } } + XSRETURN(0); #endif /* VMG_THREADSAFE */ @@ -1327,11 +1340,9 @@ SV *_wizard(...) PROTOTYPE: DISABLE PREINIT: I32 i = 0; - char buf[8]; + UV opinfo; MGWIZ *w; MGVTBL *t; - MAGIC *mg; - SV *wiz; SV *cb; CODE: dMY_CXT; @@ -1355,10 +1366,13 @@ CODE: Newx(w, 1, MGWIZ); VMG_SET_CB(ST(i++), data); + cb = ST(i++); - w->opinfo = SvOK(cb) ? SvUV(cb) : 0; + opinfo = SvOK(cb) ? SvUV(cb) : 0; + w->opinfo = (U8) ((opinfo < 255) ? opinfo : 255); if (w->opinfo) vmg_op_info_init(w->opinfo); + VMG_SET_SVT_CB(ST(i++), get); VMG_SET_SVT_CB(ST(i++), set); VMG_SET_SVT_CB(ST(i++), len); @@ -1402,23 +1416,14 @@ OUTPUT: SV *cast(SV *sv, SV *wiz, ...) PROTOTYPE: \[$@%&*]$@ PREINIT: - AV *args = NULL; - SV *ret; + SV **args = NULL; + I32 i = 0; CODE: - wiz = vmg_wizard_validate(wiz); if (items > 2) { - I32 i; - args = newAV(); - av_fill(args, items - 2); - for (i = 2; i < items; ++i) { - SV *arg = ST(i); - SvREFCNT_inc(arg); - if (av_store(args, i - 2, arg) == NULL) croak(vmg_argstorefailed); - } + i = items - 2; + args = &ST(2); } - ret = newSVuv(vmg_cast(SvRV(sv), wiz, args)); - SvREFCNT_dec(args); - RETVAL = ret; + RETVAL = newSVuv(vmg_cast(SvRV(sv), vmg_wizard_validate(wiz), args, i)); OUTPUT: RETVAL @@ -1428,8 +1433,7 @@ PROTOTYPE: \[$@%&*]$ PREINIT: SV *data; PPCODE: - wiz = vmg_wizard_validate(wiz); - data = vmg_data_get(SvRV(sv), wiz); + data = vmg_data_get(SvRV(sv), vmg_wizard_validate(wiz)); if (!data) XSRETURN_EMPTY; ST(0) = data; @@ -1437,10 +1441,7 @@ PPCODE: SV *dispell(SV *sv, SV *wiz) PROTOTYPE: \[$@%&*]$ -PREINIT: - U16 sig; CODE: - wiz = vmg_wizard_validate(wiz); - RETVAL = newSVuv(vmg_dispell(SvRV(sv), wiz)); + RETVAL = newSVuv(vmg_dispell(SvRV(sv), vmg_wizard_validate(wiz))); OUTPUT: RETVAL