X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Upper.xs;h=682aa879f12664483e6d157a5aaeb5d81d32e3b1;hb=add935e784ba40a5c477b8b8c93fb4a2159b53a1;hp=d78c722b3a36a0ba4ac33824d708d7f1ada398b5;hpb=d9a0dbbfd5e7ec3408a7590705e08cf98e273b6e;p=perl%2Fmodules%2FScope-Upper.git diff --git a/Upper.xs b/Upper.xs index d78c722..682aa87 100644 --- a/Upper.xs +++ b/Upper.xs @@ -48,6 +48,10 @@ # define SvREFCNT_inc_simple_void(sv) SvREFCNT_inc(sv) #endif +#ifndef GvCV_set +# define GvCV_set(G, C) (GvCV(G) = (C)) +#endif + #ifndef HvNAME_get # define HvNAME_get(H) HvNAME(H) #endif @@ -69,6 +73,7 @@ #endif #define SU_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S)))))) +#define SU_HAS_PERL_EXACT(R, V, S) ((PERL_REVISION == (R)) && (PERL_VERSION == (V)) && (PERL_SUBVERSION == (S))) /* --- Threads and multiplicity -------------------------------------------- */ @@ -119,11 +124,12 @@ #define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION typedef struct { - char *stack_placeholder; - I32 cxix; - I32 items; - SV **savesp; - OP fakeop; + char *stack_placeholder; + I32 cxix; + I32 items; + SV **savesp; + LISTOP return_op; + OP proxy_op; } my_cxt_t; START_MY_CXT @@ -163,10 +169,12 @@ START_MY_CXT #if !SU_HAS_PERL(5, 8, 9) # define SU_SAVE_GP_SIZE 6 -#elif !SU_HAS_PERL(5, 13, 0) +#elif !SU_HAS_PERL(5, 13, 0) || (SU_RELEASE && SU_HAS_PERL_EXACT(5, 13, 0)) # define SU_SAVE_GP_SIZE 3 -#else +#elif !SU_HAS_PERL(5, 13, 8) # define SU_SAVE_GP_SIZE 4 +#else +# define SU_SAVE_GP_SIZE 3 #endif #ifndef SvCANEXISTDELETE @@ -402,6 +410,13 @@ typedef struct { svtype type; } su_ud_localize; +#define SU_UD_LOCALIZE_FREE(U) STMT_START { \ + SvREFCNT_dec((U)->elem); \ + SvREFCNT_dec((U)->val); \ + SvREFCNT_dec((U)->sv); \ + SU_UD_FREE(U); \ +} STMT_END + STATIC I32 su_ud_localize_init(pTHX_ su_ud_localize *ud, SV *sv, SV *val, SV *elem) { #define su_ud_localize_init(UD, S, V, E) su_ud_localize_init(aTHX_ (UD), (S), (V), (E)) UV deref = 0; @@ -535,7 +550,7 @@ STATIC void su_localize(pTHX_ void *ud_) { break; case SVt_PVCV: SAVESPTR(GvCV(gv)); - GvCV(gv) = NULL; + GvCV_set(gv, NULL); break; default: gv = (GV *) save_scalar(gv); @@ -546,10 +561,7 @@ STATIC void su_localize(pTHX_ void *ud_) { SvSetMagicSV((SV *) gv, val); done: - SvREFCNT_dec(ud->elem); - SvREFCNT_dec(ud->val); - SvREFCNT_dec(ud->sv); - SU_UD_FREE(ud); + SU_UD_LOCALIZE_FREE(ud); } /* --- Pop a context back -------------------------------------------------- */ @@ -620,8 +632,8 @@ STATIC void su_pop(pTHX_ void *ud) { /* --- Initialize the stack and the action userdata ------------------------ */ -STATIC I32 su_init(pTHX_ I32 cxix, void *ud, I32 size) { -#define su_init(L, U, S) su_init(aTHX_ (L), (U), (S)) +STATIC I32 su_init(pTHX_ void *ud, I32 cxix, I32 size) { +#define su_init(U, C, S) su_init(aTHX_ (U), (C), (S)) I32 i, depth = 1, pad, offset, *origin; SU_D(PerlIO_printf(Perl_debug_log, "%p: ### init for cx %d\n", ud, cxix)); @@ -752,11 +764,13 @@ STATIC void su_unwind(pTHX_ void *ud_) { items, PL_stack_sp - PL_stack_base, *PL_markstack_ptr, mark); }); - PL_op = PL_ppaddr[OP_RETURN](aTHX); + PL_op = (OP *) &(MY_CXT.return_op); + PL_op = PL_op->op_ppaddr(aTHX); + *PL_markstack_ptr = mark; - MY_CXT.fakeop.op_next = PL_op; - PL_op = &(MY_CXT.fakeop); + MY_CXT.proxy_op.op_next = PL_op; + PL_op = &(MY_CXT.proxy_op); } /* --- XS ------------------------------------------------------------------ */ @@ -873,8 +887,18 @@ BOOT: HV *stash; MY_CXT_INIT; + MY_CXT.stack_placeholder = NULL; + /* NewOp() calls calloc() which just zeroes the memory with memset(). */ + Zero(&(MY_CXT.return_op), 1, sizeof(MY_CXT.return_op)); + MY_CXT.return_op.op_type = OP_RETURN; + MY_CXT.return_op.op_ppaddr = PL_ppaddr[OP_RETURN]; + + Zero(&(MY_CXT.proxy_op), 1, sizeof(MY_CXT.proxy_op)); + MY_CXT.proxy_op.op_type = OP_STUB; + MY_CXT.proxy_op.op_ppaddr = NULL; + stash = gv_stashpv(__PACKAGE__, 1); newCONSTSUB(stash, "TOP", newSViv(0)); newCONSTSUB(stash, "SU_THREADSAFE", newSVuv(SU_THREADSAFE)); @@ -1047,7 +1071,7 @@ CODE: SU_UD_ORIGIN(ud) = NULL; SU_UD_HANDLER(ud) = su_reap; ud->cb = newSVsv(hook); - su_init(cxix, ud, SU_SAVE_DESTRUCTOR_SIZE); + su_init(ud, cxix, SU_SAVE_DESTRUCTOR_SIZE); void localize(SV *sv, SV *val, ...) @@ -1062,7 +1086,7 @@ CODE: SU_UD_ORIGIN(ud) = NULL; SU_UD_HANDLER(ud) = su_localize; size = su_ud_localize_init(ud, sv, val, NULL); - su_init(cxix, ud, size); + su_init(ud, cxix, size); void localize_elem(SV *sv, SV *elem, SV *val, ...) @@ -1080,10 +1104,10 @@ CODE: SU_UD_HANDLER(ud) = su_localize; size = su_ud_localize_init(ud, sv, val, elem); if (ud->type != SVt_PVAV && ud->type != SVt_PVHV) { - Safefree(ud); + SU_UD_LOCALIZE_FREE(ud); croak("Can't localize an element of something that isn't an array or a hash"); } - su_init(cxix, ud, size); + su_init(ud, cxix, size); void localize_delete(SV *sv, SV *elem, ...) @@ -1098,4 +1122,4 @@ CODE: SU_UD_ORIGIN(ud) = NULL; SU_UD_HANDLER(ud) = su_localize; size = su_ud_localize_init(ud, sv, NULL, elem); - su_init(cxix, ud, size); + su_init(ud, cxix, size);