+ depth = PL_scopestack_ix - cxstack[cxix].blk_oldscopesp;
+#ifdef SU_HAS_NEW_CXT
+ depth += (cxstack_ix - cxix); /* each context frame holds 1 scope */
+#endif
+ XSH_D(su_debug_log(
+ "%p: going down by depth=%d with scope_ix=%d save_ix=%d\n",
+ ud, depth, PL_scopestack_ix, PL_savestack_ix));
+
+ /* Artificially increase the position of each savestack frame boundary
+ * to make space to squeeze in a 'size' sized entry (first one) or a
+ * SU_SAVE_DESTRUCTOR_SIZE sized entry (higher ones). In addition, make
+ * sure that each boundary is higher than the previous, so that *every*
+ * scope exit triggers a call to leave_scope(). Each scope exit will call
+ * the su_pop() destructor, which is responsible for: freeing any
+ * savestack entries below the artificially raised floor; then pushing a
+ * new destructor in that space. On the final pop, the "real" savestack
+ * action is pushed rather than another destructor.
+ *
+ * On older perls, savestack frame boundaries are specified by a range of
+ * scopestack entries (one per ENTER). Each scope entry typically does
+ * one or two ENTERs followed by a PUSHBLOCK. Thus the
+ * cx->blku_oldscopesp field set by the PUSHBLOCK points to the next free
+ * slot, which is one above the last of the ENTERs. In the debugging
+ * output we indicate that by bracketing the ENTERs directly preceding
+ * that context push with dashes, e.g.:
+ *
+ * 13b98d8: ------------------
+ * 13b98d8: ENTER origin[0] scope[3] savestack=3+3
+ * 13b98d8: ENTER origin[1] scope[4] savestack=9+3
+ * 13b98d8: cx=1 LOOP_LAZYIV
+ * 13b98d8: ------------------
+ *
+ * In addition to context stack pushes, other activities can push ENTERs
+ * too, such as grep expr and XS sub calls.
+ *
+ * For newer perls (SU_HAS_NEW_CXT), a context push no longer does any
+ * ENTERs; instead the old savestack position is stored in the new
+ * cx->blk_oldsaveix field; thus this field specifies an additional
+ * savestack frame boundary point in addition to the scopestack entries,
+ * and will also need adjusting.
+ *
+ * We record the original and modified position of each boundary in the
+ * origin array.
+ *
+ * The passed cxix argument represents the scope we wish to inject into;
+ * we have to adjust all the savestack frame boundaries above (but not
+ * including) that context.
+ */
+
+ Newx(origin, depth, su_ud_origin_elem);
+
+ cur_cx_ix = cxix;
+ cur_scope_ix = cxstack[cxix].blk_oldscopesp;
+#ifdef SU_HAS_NEW_CXT
+ XSH_D(su_debug_log("%p: cx=%-2d %-11s\n",
+ ud, cur_cx_ix, SU_CXNAME(cxstack+cur_cx_ix)));
+ cur_cx_ix++;
+#endif
+
+ for (i = 0; cur_scope_ix < PL_scopestack_ix; i++) {
+ I32 *ixp;
+ I32 offset;
+
+#ifdef SU_HAS_NEW_CXT
+
+ if ( cur_cx_ix <= cxstack_ix
+ && cur_scope_ix == cxstack[cur_cx_ix].blk_oldscopesp
+ )
+ ixp = &(cxstack[cur_cx_ix++].blk_oldsaveix);
+ else
+ ixp = &PL_scopestack[cur_scope_ix++]; /* an ENTER pushed after cur context */