X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Upper.xs;h=999eabaed83fc506825a7dc6659a6934c3e76c0b;hb=bb599962d594880ba0069b297a293eacd95092d9;hp=24e3f0a2e09d5dd9029ab23e6d6022121a345b2b;hpb=84662f0d82519cb851bb79144bc4b45aa78646f5;p=perl%2Fmodules%2FScope-Upper.git diff --git a/Upper.xs b/Upper.xs index 24e3f0a..999eaba 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 @@ -120,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 @@ -166,8 +171,10 @@ START_MY_CXT # define SU_SAVE_GP_SIZE 6 #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 @@ -309,6 +316,45 @@ STATIC void su_save_helem(pTHX_ HV *hv, SV *keysv, SV *val) { } } +/* ... Saving code slots from a glob ....................................... */ + +#if SU_HAS_PERL(5, 13, 10) + +/* Since perl 5.13.10, GvCV() is only a rvalue so we no longer can store a + * pointer to the gvcv member of the gv. */ + +typedef struct { + GV *gv; + CV *old_cv; +} su_save_gvcv_ud; + +STATIC void su_restore_gvcv(pTHX_ void *ud_) { + su_save_gvcv_ud *ud = ud_; + + GvCV_set(ud->gv, ud->old_cv); + + Safefree(ud); +} + +STATIC void su_save_gvcv(pTHX_ GV *gv) { +#define su_save_gvcv(gv) su_save_gvcv(aTHX_ (gv)) + su_save_gvcv_ud *ud; + + Newx(ud, 1, su_save_gvcv_ud); + ud->gv = gv; + ud->old_cv = GvCV(gv); + + GvCV_set(gv, NULL); + + SAVEDESTRUCTOR_X(su_restore_gvcv, ud); +} + +#else + +#define su_save_gvcv(gv) SAVESPTR(GvCV(gv)), GvCV_set((gv), NULL) + +#endif + /* --- Actions ------------------------------------------------------------- */ typedef struct { @@ -542,8 +588,7 @@ STATIC void su_localize(pTHX_ void *ud_) { save_gp(gv, 1); /* hide previous entry in symtab */ break; case SVt_PVCV: - SAVESPTR(GvCV(gv)); - GvCV(gv) = NULL; + su_save_gvcv(gv); break; default: gv = (GV *) save_scalar(gv); @@ -757,11 +802,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 ------------------------------------------------------------------ */ @@ -878,8 +925,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));