X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Upper.xs;h=61f8560e5bf4b957971e31d2d65260f41984ef66;hb=34257ad32ccc3d743ea1c90fa6cc051c7821e82f;hp=4ee44e55770b5ce07bd5f68c30b1760b3e29843a;hpb=a4643c73ee1832d2493c61f7b316ebe390bfce94;p=perl%2Fmodules%2FScope-Upper.git diff --git a/Upper.xs b/Upper.xs index 4ee44e5..61f8560 100644 --- a/Upper.xs +++ b/Upper.xs @@ -44,16 +44,12 @@ # define SvPV_nolen_const(S) SvPV_nolen(S) #endif -#ifndef HvNAME_get -# define HvNAME_get(H) HvNAME(H) -#endif - -#ifndef ENTER_with_name -# define ENTER_with_name(N) ENTER +#ifndef SvREFCNT_inc_simple_void +# define SvREFCNT_inc_simple_void(sv) SvREFCNT_inc(sv) #endif -#ifndef LEAVE_with_name -# define LEAVE_with_name(N) LEAVE +#ifndef HvNAME_get +# define HvNAME_get(H) HvNAME(H) #endif #ifndef gv_fetchpvn_flags @@ -184,7 +180,7 @@ STATIC void su_save_adelete(pTHX_ AV *av, I32 idx) { Newx(ud, 1, su_ud_adelete); ud->av = av; ud->idx = idx; - SvREFCNT_inc(av); + SvREFCNT_inc_simple_void(av); SAVEDESTRUCTOR_X(su_adelete, ud); } @@ -360,7 +356,7 @@ STATIC void su_ud_localize_init(pTHX_ su_ud_localize *ud, SV *sv, SV *val, SV *e UV deref = 0; svtype t = SVt_NULL; - SvREFCNT_inc(sv); + SvREFCNT_inc_simple_void(sv); if (SvTYPE(sv) >= SVt_PVGV) { if (!val || !SvROK(val)) { /* local *x; or local *x = $val; */ @@ -405,6 +401,7 @@ STATIC void su_ud_localize_init(pTHX_ su_ud_localize *ud, SV *sv, SV *val, SV *e case SVt_PVCV: case SVt_PVGV: deref = 0; + default: break; } /* When deref is set, val isn't NULL */ @@ -525,11 +522,30 @@ STATIC void su_pop(pTHX_ void *ud) { SU_UD_DEPTH(ud) = --depth; if (depth > 0) { - SU_D(PerlIO_printf(Perl_debug_log, - "%p: set new destructor at depth=%2d scope_ix=%2d save_ix=%2d\n", - ud, depth, PL_scopestack_ix, PL_savestack_ix)); + I32 i = 1; SAVEDESTRUCTOR_X(su_pop, ud); + + /* Skip depths corresponding to scopes for which leave_scope() might not be + * called. */ + while (depth > 1 && PL_scopestack_ix >= i) { + I32 j = PL_scopestack[PL_scopestack_ix - i]; + + if (j < PL_savestack_ix) + break; + + SU_D(PerlIO_printf(Perl_debug_log, + "%p: skip scope%*cat depth=%2d scope_ix=%2d new_top=%2d >= cur_base=%2d\n", + ud, 6, ' ', depth, PL_scopestack_ix - i, j, PL_savestack_ix)); + + SU_UD_DEPTH(ud) = --depth; + + ++i; + } + + SU_D(PerlIO_printf(Perl_debug_log, + "%p: set destructor at depth=%2d scope_ix=%2d save_ix=%2d\n", + ud, depth, PL_scopestack_ix, PL_savestack_ix)); } else { SU_UD_HANDLER(ud)(aTHX_ ud); } @@ -539,18 +555,25 @@ STATIC void su_pop(pTHX_ void *ud) { ud, PL_savestack_ix, PL_scopestack[PL_scopestack_ix])); } +/* --- Global data --------------------------------------------------------- */ + +#define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION + +typedef struct { + int stack_placeholder; + I32 cxix; + I32 items; + SV **savesp; + OP fakeop; +} my_cxt_t; + +START_MY_CXT + /* --- 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)) - I32 i, depth = 0, *origin; - - LEAVE_with_name("sub"); - - if (cxix >= cxstack_ix) { - SU_UD_HANDLER(ud)(aTHX_ ud); - goto done; - } + I32 i, depth = 1, *origin; SU_D(PerlIO_printf(Perl_debug_log, "%p: ### init for cx %d\n", ud, cxix)); @@ -606,6 +629,15 @@ STATIC I32 su_init(pTHX_ I32 cxix, void *ud, I32 size) { "%p: set original destructor at depth=%2d scope_ix=%2d save_ix=%2d\n", ud, depth, PL_scopestack_ix - 1, PL_savestack_ix)); + /* Make sure the first destructor fires by pushing enough fake slots on the + * stack. */ + if (PL_savestack_ix + 3 <= PL_scopestack[PL_scopestack_ix - 1]) { + dMY_CXT; + do { + save_int(&MY_CXT.stack_placeholder); + } while (PL_savestack_ix + 3 <= PL_scopestack[PL_scopestack_ix - 1]); + } + SAVEDESTRUCTOR_X(su_pop, ud); SU_D({ @@ -618,25 +650,9 @@ STATIC I32 su_init(pTHX_ I32 cxix, void *ud, I32 size) { } }); -done: - ENTER_with_name("sub"); - return depth; } -/* --- Global data --------------------------------------------------------- */ - -#define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION - -typedef struct { - I32 cxix; - I32 items; - SV **savesp; - OP fakeop; -} my_cxt_t; - -START_MY_CXT - /* --- Unwind stack -------------------------------------------------------- */ STATIC void su_unwind(pTHX_ void *ud_) { @@ -786,10 +802,14 @@ PROTOTYPES: ENABLE BOOT: { HV *stash; + MY_CXT_INIT; + MY_CXT.stack_placeholder = 0; + stash = gv_stashpv(__PACKAGE__, 1); newCONSTSUB(stash, "TOP", newSViv(0)); newCONSTSUB(stash, "SU_THREADSAFE", newSVuv(SU_THREADSAFE)); + newXSproto("Scope::Upper::unwind", XS_Scope__Upper_unwind, file, NULL); }