X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Magic.xs;h=15d51caac77c520d969b8e37c84648c423e13edb;hb=7bd7c3d822cc5f91b1ebf227e3756d2ef6e977e1;hp=e45baeab02d807bb2a3fa7bea8ffba7662d85f89;hpb=4de8639a5eb25d672b6248bd80e433abd0a267e2;p=perl%2Fmodules%2FVariable-Magic.git diff --git a/Magic.xs b/Magic.xs index e45baea..15d51ca 100644 --- a/Magic.xs +++ b/Magic.xs @@ -220,6 +220,48 @@ STATIC void vmg_mg_magical(SV *sv) { #endif +/* ... Trampoline ops ...................................................... */ + +/* NewOp() isn't public in perl 5.8.0. */ +#define VMG_RESET_RMG_NEEDS_TRAMPOLINE (VMG_UVAR && (VMG_THREADSAFE || !VMG_HAS_PERL(5, 8, 1))) + +#define VMG_NEEDS_TRAMPOLINE VMG_RESET_RMG_NEEDS_TRAMPOLINE + +#if VMG_NEEDS_TRAMPOLINE + +typedef struct { + OP temp; + SVOP target; +} vmg_trampoline; + +STATIC void vmg_trampoline_init(vmg_trampoline *t, OP *(*cb)(pTHX)) { + t->temp.op_type = OP_STUB; + t->temp.op_ppaddr = 0; + t->temp.op_next = (OP *) &t->target; + t->temp.op_flags = 0; + t->temp.op_private = 0; + + t->target.op_type = OP_STUB; + t->target.op_ppaddr = cb; + t->target.op_next = NULL; + t->target.op_flags = 0; + t->target.op_private = 0; + t->target.op_sv = NULL; +} + +STATIC OP *vmg_trampoline_bump(pTHX_ vmg_trampoline *t, SV *sv, OP *o) { +#define vmg_trampoline_bump(T, S, O) vmg_trampoline_bump(aTHX_ (T), (S), (O)) + t->temp = *o; + t->temp.op_next = (OP *) &t->target; + + t->target.op_sv = sv; + t->target.op_next = o->op_next; + + return &t->temp; +} + +#endif /* VMG_NEEDS_TRAMPOLINE */ + /* ... Safe version of call_sv() ........................................... */ STATIC I32 vmg_call_sv(pTHX_ SV *sv, I32 flags, int (*cleanup)(pTHX_ void *), void *ud) { @@ -401,9 +443,12 @@ STATIC const char vmg_argstorefailed[] = "Error while storing arguments"; #define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION typedef struct { - HV *b__op_stashes[OPc_MAX]; - I32 depth; - MAGIC *freed_tokens; + HV *b__op_stashes[OPc_MAX]; + I32 depth; + MAGIC *freed_tokens; +#if VMG_RESET_RMG_NEEDS_TRAMPOLINE + vmg_trampoline reset_rmg; +#endif } my_cxt_t; START_MY_CXT @@ -1189,6 +1234,8 @@ STATIC int vmg_cb_call(pTHX_ SV *cb, unsigned int flags, SV *sv, ...) { #define vmg_cb_call3(I, OI, S, A1, A2, A3) \ vmg_cb_call(aTHX_ (I), VMG_CB_FLAGS((OI), 3), (S), (A1), (A2), (A3)) +/* ... Default no-op magic callback ........................................ */ + STATIC int vmg_svt_default_noop(pTHX_ SV *sv, MAGIC *mg) { return 0; } @@ -1448,8 +1495,12 @@ STATIC int vmg_svt_local(pTHX_ SV *nsv, MAGIC *mg) { #if VMG_UVAR -STATIC OP *vmg_pp_resetuvar(pTHX) { - SvRMAGICAL_on(cSVOP_sv); +STATIC OP *vmg_pp_reset_rmg(pTHX) { + SVOP *o = cSVOPx(PL_op); + + SvRMAGICAL_on(o->op_sv); + o->op_sv = NULL; + return NORMAL; } @@ -1530,17 +1581,35 @@ STATIC I32 vmg_svt_val(pTHX_ IV action, SV *sv) { * mistaken for a tied hash by the rest of hv_common. It will be reset by * the op_ppaddr of a new fake op injected between the current and the next * one. */ - OP *nop = PL_op->op_next; - if (!nop || nop->op_ppaddr != vmg_pp_resetuvar) { - SVOP *svop; + +#if VMG_RESET_RMG_NEEDS_TRAMPOLINE + + dMY_CXT; + + PL_op = vmg_trampoline_bump(&MY_CXT.reset_rmg, sv, PL_op); + +#else /* !VMG_RESET_RMG_NEEDS_TRAMPOLINE */ + + OP *nop = PL_op->op_next; + SVOP *svop = NULL; + + if (nop && nop->op_ppaddr == vmg_pp_reset_rmg) { + svop = (SVOP *) nop; + } else { NewOp(1101, svop, 1, SVOP); - svop->op_type = OP_STUB; - svop->op_ppaddr = vmg_pp_resetuvar; - svop->op_next = nop; - svop->op_flags = 0; - svop->op_sv = sv; - PL_op->op_next = (OP *) svop; + svop->op_type = OP_STUB; + svop->op_ppaddr = vmg_pp_reset_rmg; + svop->op_next = nop; + svop->op_flags = 0; + svop->op_private = 0; + + PL_op->op_next = (OP *) svop; } + + svop->op_sv = sv; + +#endif /* VMG_RESET_RMG_NEEDS_TRAMPOLINE */ + SvRMAGICAL_off(sv); } @@ -1606,8 +1675,16 @@ BOOT: MY_CXT_INIT; for (c = OPc_NULL; c < OPc_MAX; ++c) MY_CXT.b__op_stashes[c] = NULL; + MY_CXT.depth = 0; MY_CXT.freed_tokens = NULL; + + /* XS doesn't like a blank line here */ +#if VMG_RESET_RMG_NEEDS_TRAMPOLINE + vmg_trampoline_init(&MY_CXT.reset_rmg, vmg_pp_reset_rmg); +#endif + + /* XS doesn't like a blank line here */ #if VMG_THREADSAFE MUTEX_INIT(&vmg_vtable_refcount_mutex); MUTEX_INIT(&vmg_op_name_init_mutex); @@ -1725,7 +1802,6 @@ PROTOTYPE: \[$@%&*]$@ PREINIT: const vmg_wizard *w = NULL; SV **args = NULL; - UV ret; I32 i = 0; CODE: if (items > 2) {