+#endif /* VMG_PROPAGATE_ERRSV_NEEDS_TRAMPOLINE */
+
+ SAVETMPS;
+ }
+
+ /* Don't propagate */
+ return 0;
+ } else {
+ SV *sv = ud->sv;
+ MAGIC *mg;
+
+ /* We are about to croak() while sv is being destroyed. Try to clean up
+ * things a bit. */
+ mg = SvMAGIC(sv);
+ if (mg) {
+ vmg_mg_del(sv, NULL, mg, mg->mg_moremagic);
+ mg_magical(sv);
+ }
+ SvREFCNT_dec(sv);
+
+ vmg_dispell_guard_oncroak(aTHX_ NULL);
+
+ /* After that, propagate the error upwards. */
+ return 1;
+ }
+}
+
+static int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
+ vmg_svt_free_cleanup_ud ud;
+ const vmg_wizard *w;
+ int ret = 0;
+ SV *svr;
+
+ dSP;
+
+ /* During global destruction, we cannot be sure that the wizard and its free
+ * callback are still alive. */
+ if (PL_dirty)
+ return 0;
+
+ w = vmg_wizard_from_mg_nocheck(mg);
+
+ /* So that it survives the temp cleanup below */
+ SvREFCNT_inc_simple_void(sv);
+
+#if !(VMG_HAS_PERL_MAINT(5, 11, 0, 32686) || VMG_HAS_PERL(5, 12, 0))
+ /* The previous magic tokens were freed but the magic chain wasn't updated, so
+ * if you access the sv from the callback the old deleted magics will trigger
+ * and cause memory misreads. Change 32686 solved it that way : */
+ SvMAGIC_set(sv, mg);
+#endif
+
+ ud.sv = sv;
+ if (cxstack_ix < cxstack_max) {
+ ud.in_eval = (CxTYPE(cxstack + cxstack_ix + 1) == CXt_EVAL);
+ ud.base = ud.in_eval ? PL_scopestack[PL_scopestack_ix] : 0;
+ } else {
+ ud.in_eval = 0;
+ ud.base = 0;
+ }
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ EXTEND(SP, 2);
+ PUSHs(sv_2mortal(newRV_inc(sv)));
+ PUSHs(mg->mg_obj ? mg->mg_obj : &PL_sv_undef);
+ if (w->opinfo)
+ XPUSHs(vmg_op_info(w->opinfo));
+ PUTBACK;
+
+ {
+ dMY_CXT;
+ MY_CXT.depth++;
+ vmg_call_sv(w->cb_free, G_SCALAR, vmg_svt_free_cleanup, &ud);
+ MY_CXT.depth--;
+ if (MY_CXT.depth == 0 && MY_CXT.freed_tokens) {
+ /* Free all the tokens in the chain but the current one (if it's present).
+ * It will be taken care of by our caller, Perl_mg_free(). */
+ vmg_magic_chain_free(MY_CXT.freed_tokens, mg);
+ MY_CXT.freed_tokens = NULL;
+ }
+ }
+
+ SPAGAIN;
+ svr = POPs;
+ if (SvOK(svr))
+ ret = (int) SvIV(svr);
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+
+ /* Calling SvREFCNT_dec() will trigger destructors in an infinite loop, so
+ * we have to rely on SvREFCNT() being a lvalue. Heck, even the core does it */
+ --SvREFCNT(sv);
+
+ /* Perl_mg_free will get rid of the magic and decrement mg->mg_obj and
+ * mg->mg_ptr reference count */
+ return ret;
+}
+
+#define vmg_svt_free_noop vmg_svt_default_noop
+
+#if VMG_HAS_PERL_MAINT(5, 11, 0, 33256) || VMG_HAS_PERL(5, 12, 0)
+# define VMG_SVT_COPY_KEYLEN_TYPE I32
+#else
+# define VMG_SVT_COPY_KEYLEN_TYPE int
+#endif
+
+/* ... copy magic .......................................................... */
+
+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);