]> git.vpit.fr Git - perl/modules/Variable-Magic.git/blobdiff - Magic.xs
Update the ActivePerl/gcc-3.4 hack for EUMM 7.04
[perl/modules/Variable-Magic.git] / Magic.xs
index 03363e1057916ede0fa519cd2ac56f38a681b8bb..44d4c89331b76978793645243ff53e31afe4f2d7 100644 (file)
--- a/Magic.xs
+++ b/Magic.xs
 
 #else
 
-STATIC void vmg_mg_magical(SV *sv) {
+static void vmg_mg_magical(SV *sv) {
  const MAGIC *mg;
 
  SvMAGICAL_off(sv);
@@ -248,7 +248,7 @@ typedef struct {
  SVOP target;
 } vmg_trampoline;
 
-STATIC void vmg_trampoline_init(vmg_trampoline *t, OP *(*cb)(pTHX)) {
+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;
@@ -263,7 +263,7 @@ STATIC void vmg_trampoline_init(vmg_trampoline *t, OP *(*cb)(pTHX)) {
  t->target.op_sv      = NULL;
 }
 
-STATIC OP *vmg_trampoline_bump(pTHX_ vmg_trampoline *t, SV *sv, OP *o) {
+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;
@@ -276,17 +276,46 @@ STATIC OP *vmg_trampoline_bump(pTHX_ vmg_trampoline *t, SV *sv, OP *o) {
 
 #endif /* VMG_NEEDS_TRAMPOLINE */
 
+/* --- Cleaner version of sv_magicext() ------------------------------------ */
+
+static MAGIC *vmg_sv_magicext(pTHX_ SV *sv, SV *obj, const MGVTBL *vtbl, const void *ptr, I32 len) {
+#define vmg_sv_magicext(S, O, V, P, L) vmg_sv_magicext(aTHX_ (S), (O), (V), (P), (L))
+ MAGIC *mg;
+
+ mg = sv_magicext(sv, obj, PERL_MAGIC_ext, vtbl, ptr, len);
+ if (!mg)
+  return NULL;
+
+ mg->mg_private = 0;
+
+ if (vtbl->svt_copy)
+  mg->mg_flags |= MGf_COPY;
+#if MGf_DUP
+ if (vtbl->svt_dup)
+  mg->mg_flags |= MGf_DUP;
+#endif /* MGf_DUP */
+#if MGf_LOCAL
+ if (vtbl->svt_local)
+  mg->mg_flags |= MGf_LOCAL;
+#endif /* MGf_LOCAL */
+
+ if (mg->mg_flags & MGf_REFCOUNTED)
+  SvREFCNT_dec(obj);
+
+ return mg;
+}
+
 /* --- Safe version of call_sv() ------------------------------------------- */
 
-STATIC I32 vmg_call_sv(pTHX_ SV *sv, I32 flags, int (*cleanup)(pTHX_ void *), void *ud) {
+static I32 vmg_call_sv(pTHX_ SV *sv, I32 flags, int (*cleanup)(pTHX_ void *), void *ud) {
 #define vmg_call_sv(S, F, C, U) vmg_call_sv(aTHX_ (S), (F), (C), (U))
  I32 ret, cxix;
  PERL_CONTEXT saved_cx;
  SV *old_err = NULL;
 
  if (SvTRUE(ERRSV)) {
-  old_err = ERRSV;
-  ERRSV   = newSV(0);
+  old_err = newSVsv(ERRSV);
+  sv_setsv(ERRSV, &PL_sv_undef);
  }
 
  cxix     = (cxstack_ix < cxstack_max) ? (cxstack_ix + 1) : Perl_cxinc(aTHX);
@@ -299,11 +328,8 @@ STATIC I32 vmg_call_sv(pTHX_ SV *sv, I32 flags, int (*cleanup)(pTHX_ void *), vo
  cxstack[cxix] = saved_cx;
 
  if (SvTRUE(ERRSV)) {
-  if (old_err) {
-   sv_setsv(old_err, ERRSV);
-   SvREFCNT_dec(ERRSV);
-   ERRSV = old_err;
-  }
+  SvREFCNT_dec(old_err);
+
   if (IN_PERL_COMPILETIME) {
    if (!PL_in_eval) {
     if (PL_errors)
@@ -326,8 +352,8 @@ STATIC I32 vmg_call_sv(pTHX_ SV *sv, I32 flags, int (*cleanup)(pTHX_ void *), vo
   }
  } else {
   if (old_err) {
-   SvREFCNT_dec(ERRSV);
-   ERRSV = old_err;
+   sv_setsv(ERRSV, old_err);
+   SvREFCNT_dec(old_err);
   }
  }
 
@@ -337,22 +363,25 @@ STATIC I32 vmg_call_sv(pTHX_ SV *sv, I32 flags, int (*cleanup)(pTHX_ void *), vo
 /* --- Stolen chunk of B --------------------------------------------------- */
 
 typedef enum {
- OPc_NULL   = 0,
- OPc_BASEOP = 1,
- OPc_UNOP   = 2,
- OPc_BINOP  = 3,
- OPc_LOGOP  = 4,
- OPc_LISTOP = 5,
- OPc_PMOP   = 6,
- OPc_SVOP   = 7,
- OPc_PADOP  = 8,
- OPc_PVOP   = 9,
- OPc_LOOP   = 10,
- OPc_COP    = 11,
- OPc_MAX    = 12
+ OPc_NULL,
+ OPc_BASEOP,
+ OPc_UNOP,
+ OPc_BINOP,
+ OPc_LOGOP,
+ OPc_LISTOP,
+ OPc_PMOP,
+ OPc_SVOP,
+ OPc_PADOP,
+ OPc_PVOP,
+ OPc_LOOP,
+ OPc_COP,
+#if VMG_HAS_PERL(5, 21, 5)
+ OPc_METHOP,
+#endif
+ OPc_MAX
 } opclass;
 
-STATIC const char *const vmg_opclassnames[] = {
+static const char *const vmg_opclassnames[] = {
  "B::NULL",
  "B::OP",
  "B::UNOP",
@@ -364,10 +393,14 @@ STATIC const char *const vmg_opclassnames[] = {
  "B::PADOP",
  "B::PVOP",
  "B::LOOP",
- "B::COP"
+ "B::COP",
+#if VMG_HAS_PERL(5, 21, 5)
+ "B::METHOP",
+#endif
+ NULL
 };
 
-STATIC opclass vmg_opclass(const OP *o) {
+static opclass vmg_opclass(const OP *o) {
 #if 0
  if (!o)
   return OPc_NULL;
@@ -436,6 +469,10 @@ STATIC opclass vmg_opclass(const OP *o) {
     return OPc_BASEOP;
    else
     return OPc_PVOP;
+#if VMG_HAS_PERL(5, 21, 5)
+  case OA_METHOP:
+   return OPc_METHOP;
+#endif
  }
 
  return OPc_BASEOP;
@@ -443,9 +480,9 @@ STATIC opclass vmg_opclass(const OP *o) {
 
 /* --- Error messages ------------------------------------------------------ */
 
-STATIC const char vmg_invalid_wiz[]    = "Invalid wizard object";
-STATIC const char vmg_wrongargnum[]    = "Wrong number of arguments";
-STATIC const char vmg_argstorefailed[] = "Error while storing arguments";
+static const char vmg_invalid_wiz[]    = "Invalid wizard object";
+static const char vmg_wrongargnum[]    = "Wrong number of arguments";
+static const char vmg_argstorefailed[] = "Error while storing arguments";
 
 /* --- Context-safe global data -------------------------------------------- */
 
@@ -474,7 +511,7 @@ typedef struct {
  U32     refcount;
 } vmg_vtable;
 
-STATIC vmg_vtable *vmg_vtable_alloc(pTHX) {
+static vmg_vtable *vmg_vtable_alloc(pTHX) {
 #define vmg_vtable_alloc() vmg_vtable_alloc(aTHX)
  vmg_vtable *t;
 
@@ -488,9 +525,9 @@ STATIC vmg_vtable *vmg_vtable_alloc(pTHX) {
 
 #define vmg_vtable_vtbl(T) (T)->vtbl
 
-STATIC perl_mutex vmg_vtable_refcount_mutex;
+static perl_mutex vmg_vtable_refcount_mutex;
 
-STATIC vmg_vtable *vmg_vtable_dup(pTHX_ vmg_vtable *t) {
+static vmg_vtable *vmg_vtable_dup(pTHX_ vmg_vtable *t) {
 #define vmg_vtable_dup(T) vmg_vtable_dup(aTHX_ (T))
  VMG_LOCK(&vmg_vtable_refcount_mutex);
  ++t->refcount;
@@ -499,7 +536,7 @@ STATIC vmg_vtable *vmg_vtable_dup(pTHX_ vmg_vtable *t) {
  return t;
 }
 
-STATIC void vmg_vtable_free(pTHX_ vmg_vtable *t) {
+static void vmg_vtable_free(pTHX_ vmg_vtable *t) {
 #define vmg_vtable_free(T) vmg_vtable_free(aTHX_ (T))
  U32 refcount;
 
@@ -517,7 +554,7 @@ STATIC void vmg_vtable_free(pTHX_ vmg_vtable *t) {
 
 typedef MGVTBL vmg_vtable;
 
-STATIC vmg_vtable *vmg_vtable_alloc(pTHX) {
+static vmg_vtable *vmg_vtable_alloc(pTHX) {
 #define vmg_vtable_alloc() vmg_vtable_alloc(aTHX)
  vmg_vtable *t;
 
@@ -552,9 +589,9 @@ typedef struct {
 #endif /* VMG_UVAR */
 } vmg_wizard;
 
-STATIC void vmg_op_info_init(pTHX_ unsigned int opinfo);
+static void vmg_op_info_init(pTHX_ unsigned int opinfo);
 
-STATIC vmg_wizard *vmg_wizard_alloc(pTHX_ UV opinfo) {
+static vmg_wizard *vmg_wizard_alloc(pTHX_ UV opinfo) {
 #define vmg_wizard_alloc(O) vmg_wizard_alloc(aTHX_ (O))
  vmg_wizard *w;
 
@@ -570,7 +607,7 @@ STATIC vmg_wizard *vmg_wizard_alloc(pTHX_ UV opinfo) {
  return w;
 }
 
-STATIC void vmg_wizard_free(pTHX_ vmg_wizard *w) {
+static void vmg_wizard_free(pTHX_ vmg_wizard *w) {
 #define vmg_wizard_free(W) vmg_wizard_free(aTHX_ (W))
  if (!w)
   return;
@@ -613,7 +650,7 @@ STATIC void vmg_wizard_free(pTHX_ vmg_wizard *w) {
  z->cb_ ## N = (w->cb_ ## N) ? SvREFCNT_inc(sv_dup(w->cb_ ## N, params)) \
                              : NULL;
 
-STATIC const vmg_wizard *vmg_wizard_dup(pTHX_ const vmg_wizard *w, CLONE_PARAMS *params) {
+static const vmg_wizard *vmg_wizard_dup(pTHX_ const vmg_wizard *w, CLONE_PARAMS *params) {
 #define vmg_wizard_dup(W, P) vmg_wizard_dup(aTHX_ (W), (P))
  vmg_wizard *z;
 
@@ -653,7 +690,7 @@ STATIC const vmg_wizard *vmg_wizard_dup(pTHX_ const vmg_wizard *w, CLONE_PARAMS
 
 /* --- Wizard SV objects --------------------------------------------------- */
 
-STATIC int vmg_wizard_sv_free(pTHX_ SV *sv, MAGIC *mg) {
+static int vmg_wizard_sv_free(pTHX_ SV *sv, MAGIC *mg) {
  vmg_wizard_free((vmg_wizard *) mg->mg_ptr);
 
  return 0;
@@ -661,7 +698,7 @@ STATIC int vmg_wizard_sv_free(pTHX_ SV *sv, MAGIC *mg) {
 
 #if VMG_THREADSAFE
 
-STATIC int vmg_wizard_sv_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *params) {
+static int vmg_wizard_sv_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *params) {
  mg->mg_ptr = (char *) vmg_wizard_dup((const vmg_wizard *) mg->mg_ptr, params);
 
  return 0;
@@ -669,7 +706,7 @@ STATIC int vmg_wizard_sv_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *params) {
 
 #endif /* VMG_THREADSAFE */
 
-STATIC MGVTBL vmg_wizard_sv_vtbl = {
+static MGVTBL vmg_wizard_sv_vtbl = {
  NULL,               /* get */
  NULL,               /* set */
  NULL,               /* len */
@@ -686,7 +723,7 @@ STATIC MGVTBL vmg_wizard_sv_vtbl = {
 #endif /* MGf_LOCAL */
 };
 
-STATIC SV *vmg_wizard_sv_new(pTHX_ const vmg_wizard *w) {
+static SV *vmg_wizard_sv_new(pTHX_ const vmg_wizard *w) {
 #define vmg_wizard_sv_new(W) vmg_wizard_sv_new(aTHX_ (W))
  SV *wiz;
 
@@ -696,14 +733,8 @@ STATIC SV *vmg_wizard_sv_new(pTHX_ const vmg_wizard *w) {
  wiz = newSViv(PTR2IV(w));
 #endif
 
- if (w) {
-  MAGIC *mg = sv_magicext(wiz, NULL, PERL_MAGIC_ext, &vmg_wizard_sv_vtbl,
-                                     (const char *) w, 0);
-  mg->mg_private = 0;
-#if VMG_THREADSAFE
-  mg->mg_flags  |= MGf_DUP;
-#endif
- }
+ vmg_sv_magicext(wiz, NULL, &vmg_wizard_sv_vtbl, w, 0);
+
  SvREADONLY_on(wiz);
 
  return wiz;
@@ -713,7 +744,7 @@ STATIC SV *vmg_wizard_sv_new(pTHX_ const vmg_wizard *w) {
 
 #define vmg_sv_has_wizard_type(S) (SvTYPE(S) >= SVt_PVMG)
 
-STATIC const vmg_wizard *vmg_wizard_from_sv_nocheck(const SV *wiz) {
+static const vmg_wizard *vmg_wizard_from_sv_nocheck(const SV *wiz) {
  MAGIC *mg;
 
  for (mg = SvMAGIC(wiz); mg; mg = mg->mg_moremagic) {
@@ -734,7 +765,7 @@ STATIC const vmg_wizard *vmg_wizard_from_sv_nocheck(const SV *wiz) {
 
 #define vmg_wizard_from_sv(W) (vmg_sv_has_wizard_type(W) ? vmg_wizard_from_sv_nocheck(W) : NULL)
 
-STATIC const vmg_wizard *vmg_wizard_from_mg(const MAGIC *mg) {
+static const vmg_wizard *vmg_wizard_from_mg(const MAGIC *mg) {
  if (mg->mg_type == PERL_MAGIC_ext && mg->mg_len == HEf_SVKEY) {
   SV *sv = (SV *) mg->mg_ptr;
 
@@ -749,7 +780,7 @@ STATIC const vmg_wizard *vmg_wizard_from_mg(const MAGIC *mg) {
 
 /* --- User-level functions implementation --------------------------------- */
 
-STATIC const MAGIC *vmg_find(const SV *sv, const vmg_wizard *w) {
+static const MAGIC *vmg_find(const SV *sv, const vmg_wizard *w) {
  const MAGIC *mg;
  IV wid;
 
@@ -770,7 +801,7 @@ STATIC const MAGIC *vmg_find(const SV *sv, const vmg_wizard *w) {
 
 /* ... Construct private data .............................................. */
 
-STATIC SV *vmg_data_new(pTHX_ SV *ctor, SV *sv, SV **args, I32 items) {
+static SV *vmg_data_new(pTHX_ SV *ctor, SV *sv, SV **args, I32 items) {
 #define vmg_data_new(C, S, A, I) vmg_data_new(aTHX_ (C), (S), (A), (I))
  I32 i;
  SV *nsv;
@@ -804,7 +835,7 @@ STATIC SV *vmg_data_new(pTHX_ SV *ctor, SV *sv, SV **args, I32 items) {
  return nsv;
 }
 
-STATIC SV *vmg_data_get(pTHX_ SV *sv, const vmg_wizard *w) {
+static SV *vmg_data_get(pTHX_ SV *sv, const vmg_wizard *w) {
 #define vmg_data_get(S, W) vmg_data_get(aTHX_ (S), (W))
  const MAGIC *mg = vmg_find(sv, w);
 
@@ -815,7 +846,7 @@ STATIC SV *vmg_data_get(pTHX_ SV *sv, const vmg_wizard *w) {
 
 #if VMG_UVAR
 
-STATIC I32 vmg_svt_val(pTHX_ IV, SV *);
+static I32 vmg_svt_val(pTHX_ IV, SV *);
 
 typedef struct {
  struct ufuncs new_uf;
@@ -824,7 +855,7 @@ typedef struct {
 
 #endif /* VMG_UVAR */
 
-STATIC void vmg_mg_del(pTHX_ SV *sv, MAGIC *prevmagic, MAGIC *mg, MAGIC *moremagic) {
+static void vmg_mg_del(pTHX_ SV *sv, MAGIC *prevmagic, MAGIC *mg, MAGIC *moremagic) {
 #define vmg_mg_del(S, P, M, N) vmg_mg_del(aTHX_ (S), (P), (M), (N))
  dMY_CXT;
 
@@ -859,7 +890,7 @@ STATIC void vmg_mg_del(pTHX_ SV *sv, MAGIC *prevmagic, MAGIC *mg, MAGIC *moremag
  }
 }
 
-STATIC int vmg_magic_chain_free(pTHX_ MAGIC *mg, MAGIC *skip) {
+static int vmg_magic_chain_free(pTHX_ MAGIC *mg, MAGIC *skip) {
 #define vmg_magic_chain_free(M, S) vmg_magic_chain_free(aTHX_ (M), (S))
  int skipped = 0;
 
@@ -877,7 +908,7 @@ STATIC int vmg_magic_chain_free(pTHX_ MAGIC *mg, MAGIC *skip) {
  return skipped;
 }
 
-STATIC UV vmg_cast(pTHX_ SV *sv, const vmg_wizard *w, const SV *wiz, SV **args, I32 items) {
+static UV vmg_cast(pTHX_ SV *sv, const vmg_wizard *w, const SV *wiz, SV **args, I32 items) {
 #define vmg_cast(S, W, WIZ, A, I) vmg_cast(aTHX_ (S), (W), (WIZ), (A), (I))
  MAGIC  *mg;
  MGVTBL *t;
@@ -892,22 +923,7 @@ STATIC UV vmg_cast(pTHX_ SV *sv, const vmg_wizard *w, const SV *wiz, SV **args,
  data = (w->cb_data) ? vmg_data_new(w->cb_data, sv, args, items) : NULL;
 
  t  = vmg_vtable_vtbl(w->vtable);
- mg = sv_magicext(sv, data, PERL_MAGIC_ext, t, (const char *) wiz, HEf_SVKEY);
- mg->mg_private = 0;
-
- /* sv_magicext() calls mg_magical and increments data's refcount */
- SvREFCNT_dec(data);
-
- if (t->svt_copy)
-  mg->mg_flags |= MGf_COPY;
-#if 0
- if (t->svt_dup)
-  mg->mg_flags |= MGf_DUP;
-#endif
-#if MGf_LOCAL
- if (t->svt_local)
-  mg->mg_flags |= MGf_LOCAL;
-#endif /* MGf_LOCAL */
+ mg = vmg_sv_magicext(sv, data, t, wiz, HEf_SVKEY);
 
  if (SvTYPE(sv) < SVt_PVHV)
   goto done;
@@ -963,7 +979,7 @@ done:
  return 1;
 }
 
-STATIC UV vmg_dispell(pTHX_ SV *sv, const vmg_wizard *w) {
+static UV vmg_dispell(pTHX_ SV *sv, const vmg_wizard *w) {
 #define vmg_dispell(S, W) vmg_dispell(aTHX_ (S), (W))
 #if VMG_UVAR
  U32 uvars = 0;
@@ -1053,13 +1069,13 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, const vmg_wizard *w) {
 #define VMG_OP_INFO_OBJECT 2
 
 #if VMG_THREADSAFE
-STATIC perl_mutex vmg_op_name_init_mutex;
+static perl_mutex vmg_op_name_init_mutex;
 #endif
 
-STATIC U32           vmg_op_name_init      = 0;
-STATIC unsigned char vmg_op_name_len[MAXO] = { 0 };
+static U32           vmg_op_name_init      = 0;
+static unsigned char vmg_op_name_len[MAXO] = { 0 };
 
-STATIC void vmg_op_info_init(pTHX_ unsigned int opinfo) {
+static void vmg_op_info_init(pTHX_ unsigned int opinfo) {
 #define vmg_op_info_init(W) vmg_op_info_init(aTHX_ (W))
  switch (opinfo) {
   case VMG_OP_INFO_NAME:
@@ -1087,7 +1103,7 @@ STATIC void vmg_op_info_init(pTHX_ unsigned int opinfo) {
  }
 }
 
-STATIC SV *vmg_op_info(pTHX_ unsigned int opinfo) {
+static SV *vmg_op_info(pTHX_ unsigned int opinfo) {
 #define vmg_op_info(W) vmg_op_info(aTHX_ (W))
  if (!PL_op)
   return &PL_sv_undef;
@@ -1116,7 +1132,7 @@ STATIC SV *vmg_op_info(pTHX_ unsigned int opinfo) {
 #define VMG_CB_CALL_OPINFO     (VMG_OP_INFO_NAME|VMG_OP_INFO_OBJECT) /* 1|2 */
 #define VMG_CB_CALL_GUARD      4
 
-STATIC int vmg_dispell_guard_oncroak(pTHX_ void *ud) {
+static int vmg_dispell_guard_oncroak(pTHX_ void *ud) {
  dMY_CXT;
 
  MY_CXT.depth--;
@@ -1132,7 +1148,7 @@ STATIC int vmg_dispell_guard_oncroak(pTHX_ void *ud) {
  return 1;
 }
 
-STATIC int vmg_dispell_guard_free(pTHX_ SV *sv, MAGIC *mg) {
+static int vmg_dispell_guard_free(pTHX_ SV *sv, MAGIC *mg) {
  vmg_magic_chain_free((MAGIC *) mg->mg_ptr, NULL);
 
  return 0;
@@ -1140,7 +1156,7 @@ STATIC int vmg_dispell_guard_free(pTHX_ SV *sv, MAGIC *mg) {
 
 #if VMG_THREADSAFE
 
-STATIC int vmg_dispell_guard_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *params) {
+static int vmg_dispell_guard_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *params) {
  /* The freed magic tokens aren't cloned by perl because it cannot reach them
   * (they have been detached from their parent SV when they were enqueued).
   * Hence there's nothing to purge in the new thread. */
@@ -1151,7 +1167,7 @@ STATIC int vmg_dispell_guard_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *params) {
 
 #endif /* VMG_THREADSAFE */
 
-STATIC MGVTBL vmg_dispell_guard_vtbl = {
+static MGVTBL vmg_dispell_guard_vtbl = {
  NULL,                   /* get */
  NULL,                   /* set */
  NULL,                   /* len */
@@ -1168,18 +1184,17 @@ STATIC MGVTBL vmg_dispell_guard_vtbl = {
 #endif /* MGf_LOCAL */
 };
 
-STATIC SV *vmg_dispell_guard_new(pTHX_ MAGIC *root) {
+static SV *vmg_dispell_guard_new(pTHX_ MAGIC *root) {
 #define vmg_dispell_guard_new(R) vmg_dispell_guard_new(aTHX_ (R))
  SV *guard;
 
  guard = sv_newmortal();
- sv_magicext(guard, NULL, PERL_MAGIC_ext, &vmg_dispell_guard_vtbl,
-                          (char *) root, 0);
+ vmg_sv_magicext(guard, NULL, &vmg_dispell_guard_vtbl, root, 0);
 
  return guard;
 }
 
-STATIC int vmg_cb_call(pTHX_ SV *cb, unsigned int flags, SV *sv, ...) {
+static int vmg_cb_call(pTHX_ SV *cb, unsigned int flags, SV *sv, ...) {
  va_list ap;
  int ret = 0;
  unsigned int i, args, opinfo;
@@ -1248,13 +1263,13 @@ STATIC int vmg_cb_call(pTHX_ SV *cb, unsigned int flags, SV *sv, ...) {
 
 /* ... Default no-op magic callback ........................................ */
 
-STATIC int vmg_svt_default_noop(pTHX_ SV *sv, MAGIC *mg) {
+static int vmg_svt_default_noop(pTHX_ SV *sv, MAGIC *mg) {
  return 0;
 }
 
 /* ... get magic ........................................................... */
 
-STATIC int vmg_svt_get(pTHX_ SV *sv, MAGIC *mg) {
+static int vmg_svt_get(pTHX_ SV *sv, MAGIC *mg) {
  const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
 
  return vmg_cb_call1(w->cb_get, w->opinfo, sv, mg->mg_obj);
@@ -1264,7 +1279,7 @@ STATIC int vmg_svt_get(pTHX_ SV *sv, MAGIC *mg) {
 
 /* ... set magic ........................................................... */
 
-STATIC int vmg_svt_set(pTHX_ SV *sv, MAGIC *mg) {
+static int vmg_svt_set(pTHX_ SV *sv, MAGIC *mg) {
  const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
 
  return vmg_cb_call1(w->cb_set, w->opinfo, sv, mg->mg_obj);
@@ -1274,7 +1289,7 @@ STATIC int vmg_svt_set(pTHX_ SV *sv, MAGIC *mg) {
 
 /* ... len magic ........................................................... */
 
-STATIC U32 vmg_sv_len(pTHX_ SV *sv) {
+static U32 vmg_sv_len(pTHX_ SV *sv) {
 #define vmg_sv_len(S) vmg_sv_len(aTHX_ (S))
  STRLEN len;
 #if VMG_HAS_PERL(5, 9, 3)
@@ -1286,7 +1301,7 @@ STATIC U32 vmg_sv_len(pTHX_ SV *sv) {
  return DO_UTF8(sv) ? utf8_length(s, s + len) : len;
 }
 
-STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) {
+static U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) {
  const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
  unsigned int opinfo = w->opinfo;
  U32 len, ret;
@@ -1331,7 +1346,7 @@ STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) {
  return ret;
 }
 
-STATIC U32 vmg_svt_len_noop(pTHX_ SV *sv, MAGIC *mg) {
+static U32 vmg_svt_len_noop(pTHX_ SV *sv, MAGIC *mg) {
  U32    len = 0;
  svtype t   = SvTYPE(sv);
 
@@ -1346,7 +1361,7 @@ STATIC U32 vmg_svt_len_noop(pTHX_ SV *sv, MAGIC *mg) {
 
 /* ... clear magic ......................................................... */
 
-STATIC int vmg_svt_clear(pTHX_ SV *sv, MAGIC *mg) {
+static int vmg_svt_clear(pTHX_ SV *sv, MAGIC *mg) {
  const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
  unsigned int flags  = w->opinfo;
 
@@ -1363,12 +1378,12 @@ STATIC int vmg_svt_clear(pTHX_ SV *sv, MAGIC *mg) {
 
 #if VMG_PROPAGATE_ERRSV_NEEDS_TRAMPOLINE
 
-STATIC OP *vmg_pp_propagate_errsv(pTHX) {
+static OP *vmg_pp_propagate_errsv(pTHX) {
  SVOP *o = cSVOPx(PL_op);
 
  if (o->op_sv) {
-  SvREFCNT_dec(ERRSV);
-  ERRSV    = o->op_sv;
+  sv_setsv(ERRSV, o->op_sv);
+  SvREFCNT_dec(o->op_sv);
   o->op_sv = NULL;
  }
 
@@ -1377,12 +1392,9 @@ STATIC OP *vmg_pp_propagate_errsv(pTHX) {
 
 #endif /* VMG_PROPAGATE_ERRSV_NEEDS_TRAMPOLINE */
 
-STATIC int vmg_propagate_errsv_free(pTHX_ SV *sv, MAGIC *mg) {
- if (mg->mg_obj) {
-  ERRSV         = mg->mg_obj;
-  mg->mg_obj    = NULL;
-  mg->mg_flags &= ~MGf_REFCOUNTED;
- }
+static int vmg_propagate_errsv_free(pTHX_ SV *sv, MAGIC *mg) {
+ if (mg->mg_obj)
+  sv_setsv(ERRSV, mg->mg_obj);
 
  return 0;
 }
@@ -1390,7 +1402,7 @@ STATIC int vmg_propagate_errsv_free(pTHX_ SV *sv, MAGIC *mg) {
 /* perl is already kind enough to handle the cloning of the mg_obj member,
    hence we don't need to define a dup magic callback. */
 
-STATIC MGVTBL vmg_propagate_errsv_vtbl = {
+static MGVTBL vmg_propagate_errsv_vtbl = {
  0,                        /* get */
  0,                        /* set */
  0,                        /* len */
@@ -1409,7 +1421,7 @@ typedef struct {
  I32  base;
 } vmg_svt_free_cleanup_ud;
 
-STATIC int vmg_svt_free_cleanup(pTHX_ void *ud_) {
+static int vmg_svt_free_cleanup(pTHX_ void *ud_) {
  vmg_svt_free_cleanup_ud *ud = VOID2(vmg_svt_free_cleanup_ud *, ud_);
 
  if (ud->in_eval) {
@@ -1427,20 +1439,16 @@ STATIC int vmg_svt_free_cleanup(pTHX_ void *ud_) {
     PL_op = vmg_trampoline_bump(&MY_CXT.propagate_errsv, errsv, PL_op);
    } else if (optype == OP_LEAVEEVAL) {
     SV *guard = sv_newmortal();
-    sv_magicext(guard, errsv, PERL_MAGIC_ext, &vmg_propagate_errsv_vtbl,
-                              NULL, 0);
+    vmg_sv_magicext(guard, errsv, &vmg_propagate_errsv_vtbl, NULL, 0);
    }
 #else /* !VMG_PROPAGATE_ERRSV_NEEDS_TRAMPOLINE */
 # if !VMG_HAS_PERL(5, 8, 9)
    {
     SV *guard = sv_newmortal();
-    sv_magicext(guard, errsv, PERL_MAGIC_ext, &vmg_propagate_errsv_vtbl,
-                              NULL, 0);
+    vmg_sv_magicext(guard, errsv, &vmg_propagate_errsv_vtbl, NULL, 0);
    }
 # else
-   sv_magicext(ERRSV, errsv, PERL_MAGIC_ext, &vmg_propagate_errsv_vtbl,
-                             NULL, 0);
-   SvREFCNT_dec(errsv);
+   vmg_sv_magicext(ERRSV, errsv, &vmg_propagate_errsv_vtbl, NULL, 0);
 # endif
 #endif /* VMG_PROPAGATE_ERRSV_NEEDS_TRAMPOLINE */
 
@@ -1469,7 +1477,7 @@ STATIC int vmg_svt_free_cleanup(pTHX_ void *ud_) {
  }
 }
 
-STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
+static int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
  vmg_svt_free_cleanup_ud ud;
  const vmg_wizard *w;
  int ret = 0;
@@ -1555,7 +1563,7 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
 
 /* ... copy magic .......................................................... */
 
-STATIC int vmg_svt_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key, VMG_SVT_COPY_KEYLEN_TYPE keylen) {
+static int vmg_svt_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key, VMG_SVT_COPY_KEYLEN_TYPE keylen) {
  const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
  SV *keysv;
  int ret;
@@ -1578,14 +1586,14 @@ STATIC int vmg_svt_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key, VMG_S
  return ret;
 }
 
-STATIC int vmg_svt_copy_noop(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key, VMG_SVT_COPY_KEYLEN_TYPE keylen) {
+static int vmg_svt_copy_noop(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key, VMG_SVT_COPY_KEYLEN_TYPE keylen) {
  return 0;
 }
 
 /* ... dup magic ........................................................... */
 
 #if 0
-STATIC int vmg_svt_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param) {
+static int vmg_svt_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param) {
  return 0;
 }
 #define vmg_svt_dup_noop vmg_svt_dup
@@ -1595,7 +1603,7 @@ STATIC int vmg_svt_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param) {
 
 #if MGf_LOCAL
 
-STATIC int vmg_svt_local(pTHX_ SV *nsv, MAGIC *mg) {
+static int vmg_svt_local(pTHX_ SV *nsv, MAGIC *mg) {
  const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
 
  return vmg_cb_call1(w->cb_local, w->opinfo, nsv, mg->mg_obj);
@@ -1609,7 +1617,7 @@ STATIC int vmg_svt_local(pTHX_ SV *nsv, MAGIC *mg) {
 
 #if VMG_UVAR
 
-STATIC OP *vmg_pp_reset_rmg(pTHX) {
+static OP *vmg_pp_reset_rmg(pTHX) {
  SVOP *o = cSVOPx(PL_op);
 
  SvRMAGICAL_on(o->op_sv);
@@ -1618,7 +1626,7 @@ STATIC OP *vmg_pp_reset_rmg(pTHX) {
  return NORMAL;
 }
 
-STATIC I32 vmg_svt_val(pTHX_ IV action, SV *sv) {
+static I32 vmg_svt_val(pTHX_ IV action, SV *sv) {
  vmg_uvar_ud *ud;
  MAGIC *mg, *umg, *moremagic;
  SV *key = NULL, *newkey = NULL;