]> git.vpit.fr Git - perl/modules/Scope-Upper.git/blobdiff - Upper.xs
Use a PPCODE: section in CLONE
[perl/modules/Scope-Upper.git] / Upper.xs
index 5bf3b496797c67bf67de422a6679e78e27382f3d..d78c722b3a36a0ba4ac33824d708d7f1ada398b5 100644 (file)
--- a/Upper.xs
+++ b/Upper.xs
 #define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION
 
 typedef struct {
int stack_placeholder;
- I32 cxix;
- I32 items;
char *stack_placeholder;
+ I32   cxix;
+ I32   items;
  SV  **savesp;
- OP  fakeop;
+ OP    fakeop;
 } my_cxt_t;
 
 START_MY_CXT
 
 /* --- Stack manipulations ------------------------------------------------- */
 
-#define SU_SAVE_DESTRUCTOR_SIZE 3
-#define SU_SAVE_INT_SIZE        3
+#define SU_SAVE_PLACEHOLDER() save_pptr(&MY_CXT.stack_placeholder)
+
+#define SU_SAVE_DESTRUCTOR_SIZE  3
+#define SU_SAVE_PLACEHOLDER_SIZE 3
+
+#define SU_SAVE_SCALAR_SIZE 3
+
+#define SU_SAVE_ARY_SIZE      3
+#define SU_SAVE_AELEM_SIZE    4
+#ifdef SAVEADELETE
+# define SU_SAVE_ADELETE_SIZE 3
+#else
+# define SU_SAVE_ADELETE_SIZE SU_SAVE_DESTRUCTOR_SIZE
+#endif
+#if SU_SAVE_AELEM_SIZE < SU_SAVE_ADELETE_SIZE
+# define SU_SAVE_AELEM_OR_ADELETE_SIZE SU_SAVE_ADELETE_SIZE
+#else
+# define SU_SAVE_AELEM_OR_ADELETE_SIZE SU_SAVE_AELEM_SIZE
+#endif
+
+#define SU_SAVE_HASH_SIZE    3
+#define SU_SAVE_HELEM_SIZE   4
+#define SU_SAVE_HDELETE_SIZE 4
+#if SU_SAVE_HELEM_SIZE < SU_SAVE_HDELETE_SIZE
+# define SU_SAVE_HELEM_OR_HDELETE_SIZE SU_SAVE_HDELETE_SIZE
+#else
+# define SU_SAVE_HELEM_OR_HDELETE_SIZE SU_SAVE_HELEM_SIZE
+#endif
+
+#define SU_SAVE_SPTR_SIZE 3
+
+#if !SU_HAS_PERL(5, 8, 9)
+# define SU_SAVE_GP_SIZE 6
+#elif !SU_HAS_PERL(5, 13, 0)
+# define SU_SAVE_GP_SIZE 3
+#else
+# define SU_SAVE_GP_SIZE 4
+#endif
 
 #ifndef SvCANEXISTDELETE
 # define SvCANEXISTDELETE(sv) \
@@ -366,10 +402,11 @@ typedef struct {
  svtype type;
 } su_ud_localize;
 
-STATIC void su_ud_localize_init(pTHX_ su_ud_localize *ud, SV *sv, SV *val, SV *elem) {
+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;
  svtype t = SVt_NULL;
+ I32 size;
 
  SvREFCNT_inc_simple_void(sv);
 
@@ -380,6 +417,9 @@ STATIC void su_ud_localize_init(pTHX_ su_ud_localize *ud, SV *sv, SV *val, SV *e
    t = SvTYPE(SvRV(val));
    deref = 1;
   }
+ } else if (SvROK(sv)) {
+  croak("Invalid %s reference as the localization target",
+                 sv_reftype(SvRV(sv), 0));
  } else {
   STRLEN len, l;
   const char *p = SvPV_const(sv, len), *s;
@@ -412,11 +452,25 @@ STATIC void su_ud_localize_init(pTHX_ su_ud_localize *ud, SV *sv, SV *val, SV *e
 
  switch (t) {
   case SVt_PVAV:
+   size  = elem ? SU_SAVE_AELEM_OR_ADELETE_SIZE
+                : SU_SAVE_ARY_SIZE;
+   deref = 0;
+   break;
   case SVt_PVHV:
-  case SVt_PVCV:
+   size  = elem ? SU_SAVE_HELEM_OR_HDELETE_SIZE
+                : SU_SAVE_HASH_SIZE;
+   deref = 0;
+   break;
   case SVt_PVGV:
+   size  = SU_SAVE_GP_SIZE;
+   deref = 0;
+   break;
+  case SVt_PVCV:
+   size  = SU_SAVE_SPTR_SIZE;
    deref = 0;
+   break;
   default:
+   size = SU_SAVE_SCALAR_SIZE;
    break;
  }
  /* When deref is set, val isn't NULL */
@@ -425,6 +479,8 @@ STATIC void su_ud_localize_init(pTHX_ su_ud_localize *ud, SV *sv, SV *val, SV *e
  ud->val  = val ? newSVsv(deref ? SvRV(val) : val) : NULL;
  ud->elem = SvREFCNT_inc(elem);
  ud->type = t;
+
+ return size;
 }
 
 STATIC void su_localize(pTHX_ void *ud_) {
@@ -537,36 +593,22 @@ STATIC void su_pop(pTHX_ void *ud) {
  SU_UD_DEPTH(ud) = --depth;
 
  if (depth > 0) {
-  I32 i = 1, pad;
+  I32 pad;
 
-  if (pad = SU_UD_PAD(ud)) {
+  if ((pad = SU_UD_PAD(ud))) {
    dMY_CXT;
    do {
-    save_int(&MY_CXT.stack_placeholder);
+    SU_D(PerlIO_printf(Perl_debug_log,
+          "%p: push a pad slot at depth=%2d scope_ix=%2d save_ix=%2d\n",
+           ud,                       depth, PL_scopestack_ix, PL_savestack_ix));
+    SU_SAVE_PLACEHOLDER();
    } while (--pad);
   }
-  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: push destructor at depth=%2d scope_ix=%2d save_ix=%2d\n",
            ud,                       depth, PL_scopestack_ix, PL_savestack_ix));
+  SAVEDESTRUCTOR_X(su_pop, ud);
  } else {
   SU_UD_HANDLER(ud)(aTHX_ ud);
  }
@@ -588,9 +630,11 @@ STATIC I32 su_init(pTHX_ I32 cxix, void *ud, I32 size) {
   pad = 0;
  else {
   I32 extra = size - SU_SAVE_DESTRUCTOR_SIZE;
-  pad = extra / SU_SAVE_INT_SIZE + ((extra % SU_SAVE_INT_SIZE) ? 1 : 0);
+  pad = extra / SU_SAVE_PLACEHOLDER_SIZE;
+  if (extra % SU_SAVE_PLACEHOLDER_SIZE)
+   ++pad;
  }
- offset = SU_SAVE_DESTRUCTOR_SIZE + SU_SAVE_INT_SIZE * pad;
+ offset = SU_SAVE_DESTRUCTOR_SIZE + SU_SAVE_PLACEHOLDER_SIZE * pad;
 
  SU_D(PerlIO_printf(Perl_debug_log, "%p: size=%d pad=%d offset=%d\n",
                                      ud,    size,   pad,   offset));
@@ -653,7 +697,7 @@ STATIC I32 su_init(pTHX_ I32 cxix, void *ud, I32 size) {
    SU_D(PerlIO_printf(Perl_debug_log,
                   "%p: push a fake slot      at scope_ix=%2d  save_ix=%2d\n",
                    ud,                      PL_scopestack_ix, PL_savestack_ix));
-   save_int(&MY_CXT.stack_placeholder);
+   SU_SAVE_PLACEHOLDER();
   } while (PL_savestack_ix + SU_SAVE_DESTRUCTOR_SIZE
                                         <= PL_scopestack[PL_scopestack_ix - 1]);
  }
@@ -829,7 +873,7 @@ BOOT:
  HV *stash;
 
  MY_CXT_INIT;
- MY_CXT.stack_placeholder = 0;
+ MY_CXT.stack_placeholder = NULL;
 
  stash = gv_stashpv(__PACKAGE__, 1);
  newCONSTSUB(stash, "TOP",           newSViv(0));
@@ -843,11 +887,11 @@ BOOT:
 void
 CLONE(...)
 PROTOTYPE: DISABLE
-CODE:
- PERL_UNUSED_VAR(items);
+PPCODE:
  {
   MY_CXT_CLONE;
  }
+ XSRETURN(0);
 
 #endif /* SU_THREADSAFE */
 
@@ -1003,25 +1047,21 @@ CODE:
  SU_UD_ORIGIN(ud)  = NULL;
  SU_UD_HANDLER(ud) = su_reap;
  ud->cb = newSVsv(hook);
- su_init(cxix, ud, 3);
+ su_init(cxix, ud, SU_SAVE_DESTRUCTOR_SIZE);
 
 void
 localize(SV *sv, SV *val, ...)
 PROTOTYPE: $$;$
 PREINIT:
  I32 cxix;
- I32 size = 3;
+ I32 size;
  su_ud_localize *ud;
 CODE:
  SU_GET_CONTEXT(2, 2);
  Newx(ud, 1, su_ud_localize);
  SU_UD_ORIGIN(ud)  = NULL;
  SU_UD_HANDLER(ud) = su_localize;
- su_ud_localize_init(ud, sv, val, NULL);
-#if !SU_HAS_PERL(5, 8, 9)
- if (ud->type >= SVt_PVGV)
-  size = 6;
-#endif
+ size = su_ud_localize_init(ud, sv, val, NULL);
  su_init(cxix, ud, size);
 
 void
@@ -1029,6 +1069,7 @@ localize_elem(SV *sv, SV *elem, SV *val, ...)
 PROTOTYPE: $$$;$
 PREINIT:
  I32 cxix;
+ I32 size;
  su_ud_localize *ud;
 CODE:
  if (SvTYPE(sv) >= SVt_PVGV)
@@ -1037,28 +1078,24 @@ CODE:
  Newx(ud, 1, su_ud_localize);
  SU_UD_ORIGIN(ud)  = NULL;
  SU_UD_HANDLER(ud) = su_localize;
- su_ud_localize_init(ud, sv, val, elem);
+ size = su_ud_localize_init(ud, sv, val, elem);
  if (ud->type != SVt_PVAV && ud->type != SVt_PVHV) {
   Safefree(ud);
   croak("Can't localize an element of something that isn't an array or a hash");
  }
- su_init(cxix, ud, 4);
+ su_init(cxix, ud, size);
 
 void
 localize_delete(SV *sv, SV *elem, ...)
 PROTOTYPE: $$;$
 PREINIT:
  I32 cxix;
- I32 size = 4;
+ I32 size;
  su_ud_localize *ud;
 CODE:
  SU_GET_CONTEXT(2, 2);
  Newx(ud, 1, su_ud_localize);
  SU_UD_ORIGIN(ud)  = NULL;
  SU_UD_HANDLER(ud) = su_localize;
- su_ud_localize_init(ud, sv, NULL, elem);
-#if !SU_HAS_PERL(5, 8, 9)
- if (ud->type >= SVt_PVGV)
-  size = 6;
-#endif
+ size = su_ud_localize_init(ud, sv, NULL, elem);
  su_init(cxix, ud, size);