#endif
+/* ... Trampoline ops ...................................................... */
+
+/* NewOp() isn't public in perl 5.8.0. */
+#define VMG_RESET_RMG_NEEDS_TRAMPOLINE (VMG_UVAR && (VMG_THREADSAFE || !VMG_HAS_PERL(5, 8, 1)))
+
+#define VMG_NEEDS_TRAMPOLINE VMG_RESET_RMG_NEEDS_TRAMPOLINE
+
+#if VMG_NEEDS_TRAMPOLINE
+
+typedef struct {
+ OP temp;
+ SVOP target;
+} vmg_trampoline;
+
+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;
+ t->temp.op_flags = 0;
+ t->temp.op_private = 0;
+
+ t->target.op_type = OP_STUB;
+ t->target.op_ppaddr = cb;
+ t->target.op_next = NULL;
+ t->target.op_flags = 0;
+ t->target.op_private = 0;
+ t->target.op_sv = NULL;
+}
+
+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;
+
+ t->target.op_sv = sv;
+ t->target.op_next = o->op_next;
+
+ return &t->temp;
+}
+
+#endif /* VMG_NEEDS_TRAMPOLINE */
+
/* ... Safe version of call_sv() ........................................... */
STATIC I32 vmg_call_sv(pTHX_ SV *sv, I32 flags, int (*cleanup)(pTHX_ void *), void *ud) {
#define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION
typedef struct {
- HV *b__op_stashes[OPc_MAX];
- I32 depth;
- MAGIC *freed_tokens;
+ HV *b__op_stashes[OPc_MAX];
+ I32 depth;
+ MAGIC *freed_tokens;
+#if VMG_RESET_RMG_NEEDS_TRAMPOLINE
+ vmg_trampoline reset_rmg;
+#endif
} my_cxt_t;
START_MY_CXT
* mistaken for a tied hash by the rest of hv_common. It will be reset by
* the op_ppaddr of a new fake op injected between the current and the next
* one. */
+
+#if VMG_RESET_RMG_NEEDS_TRAMPOLINE
+
+ dMY_CXT;
+
+ PL_op = vmg_trampoline_bump(&MY_CXT.reset_rmg, sv, PL_op);
+
+#else /* !VMG_RESET_RMG_NEEDS_TRAMPOLINE */
+
OP *nop = PL_op->op_next;
SVOP *svop = NULL;
svop->op_sv = sv;
+#endif /* VMG_RESET_RMG_NEEDS_TRAMPOLINE */
+
SvRMAGICAL_off(sv);
}
MY_CXT_INIT;
for (c = OPc_NULL; c < OPc_MAX; ++c)
MY_CXT.b__op_stashes[c] = NULL;
+
MY_CXT.depth = 0;
MY_CXT.freed_tokens = NULL;
+
+ /* XS doesn't like a blank line here */
+#if VMG_RESET_RMG_NEEDS_TRAMPOLINE
+ vmg_trampoline_init(&MY_CXT.reset_rmg, vmg_pp_reset_rmg);
+#endif
+
+ /* XS doesn't like a blank line here */
#if VMG_THREADSAFE
MUTEX_INIT(&vmg_vtable_refcount_mutex);
MUTEX_INIT(&vmg_op_name_init_mutex);