]> git.vpit.fr Git - perl/modules/Scope-Upper.git/blob - Upper.xs
d591a759c13ebdb9d4012d2de1ec983deae0aad5
[perl/modules/Scope-Upper.git] / Upper.xs
1 /* This file is part of the Scope::Upper Perl module.
2  * See http://search.cpan.org/dist/Scope-Upper/ */
3
4 #define PERL_NO_GET_CONTEXT
5 #include "EXTERN.h"
6 #include "perl.h" 
7 #include "XSUB.h"
8
9 #define __PACKAGE__ "Scope::Upper"
10
11 #ifndef SU_DEBUG
12 # define SU_DEBUG 0
13 #endif
14
15 /* --- Compatibility ------------------------------------------------------- */
16
17 #ifndef NOOP
18 # define NOOP
19 #endif
20
21 #ifndef dNOOP
22 # define dNOOP
23 #endif
24
25 #ifndef PERL_UNUSED_VAR
26 # define PERL_UNUSED_VAR(V)
27 #endif
28
29 #ifndef STMT_START
30 # define STMT_START do
31 #endif
32
33 #ifndef STMT_END
34 # define STMT_END while (0)
35 #endif
36
37 #if SU_DEBUG
38 # define SU_D(X) STMT_START X STMT_END
39 #else
40 # define SU_D(X)
41 #endif
42
43 #ifndef Newx
44 # define Newx(v, n, c) New(0, v, n, c)
45 #endif
46
47 #ifdef DEBUGGING
48 # ifdef PoisonNew
49 #  define SU_POISON(D, N, T) PoisonNew((D), (N), T)
50 # elif defined(Poison)
51 #  define SU_POISON(D, N, T) Poison((D), (N), T)
52 # endif
53 #endif
54 #ifndef SU_POISON
55 # define SU_POISON(D, N, T) NOOP
56 #endif
57
58 #ifndef SvPV_const
59 # define SvPV_const(S, L) SvPV(S, L)
60 #endif
61
62 #ifndef SvPV_nolen_const
63 # define SvPV_nolen_const(S) SvPV_nolen(S)
64 #endif
65
66 #ifndef SvREFCNT_inc_simple_void
67 # define SvREFCNT_inc_simple_void(sv) SvREFCNT_inc(sv)
68 #endif
69
70 #ifndef GvCV_set
71 # define GvCV_set(G, C) (GvCV(G) = (C))
72 #endif
73
74 #ifndef CvGV_set
75 # define CvGV_set(C, G) (CvGV(C) = (G))
76 #endif
77
78 #ifndef CxHASARGS
79 # define CxHASARGS(C) ((C)->blk_sub.hasargs)
80 #endif
81
82 #ifndef HvNAME_get
83 # define HvNAME_get(H) HvNAME(H)
84 #endif
85
86 #ifndef gv_fetchpvn_flags
87 # define gv_fetchpvn_flags(A, B, C, D) gv_fetchpv((A), (C), (D))
88 #endif
89
90 #ifndef cv_clone
91 # define cv_clone(P) Perl_cv_clone(aTHX_ (P))
92 #endif
93
94 #ifndef PERL_MAGIC_tied
95 # define PERL_MAGIC_tied 'P'
96 #endif
97
98 #ifndef PERL_MAGIC_env
99 # define PERL_MAGIC_env 'E'
100 #endif
101
102 #ifndef NEGATIVE_INDICES_VAR
103 # define NEGATIVE_INDICES_VAR "NEGATIVE_INDICES"
104 #endif
105
106 #define SU_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S))))))
107 #define SU_HAS_PERL_EXACT(R, V, S) ((PERL_REVISION == (R)) && (PERL_VERSION == (V)) && (PERL_SUBVERSION == (S)))
108
109 /* --- Threads and multiplicity -------------------------------------------- */
110
111 #ifndef SU_MULTIPLICITY
112 # if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT)
113 #  define SU_MULTIPLICITY 1
114 # else
115 #  define SU_MULTIPLICITY 0
116 # endif
117 #endif
118 #if SU_MULTIPLICITY && !defined(tTHX)
119 # define tTHX PerlInterpreter*
120 #endif
121
122 #if SU_MULTIPLICITY && defined(USE_ITHREADS) && defined(dMY_CXT) && defined(MY_CXT) && defined(START_MY_CXT) && defined(MY_CXT_INIT) && (defined(MY_CXT_CLONE) || defined(dMY_CXT_SV))
123 # define SU_THREADSAFE 1
124 # ifndef MY_CXT_CLONE
125 #  define MY_CXT_CLONE \
126     dMY_CXT_SV;                                                      \
127     my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1)); \
128     Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t); \
129     sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
130 # endif
131 #else
132 # define SU_THREADSAFE 0
133 # undef  dMY_CXT
134 # define dMY_CXT      dNOOP
135 # undef  MY_CXT
136 # define MY_CXT       su_globaldata
137 # undef  START_MY_CXT
138 # define START_MY_CXT STATIC my_cxt_t MY_CXT;
139 # undef  MY_CXT_INIT
140 # define MY_CXT_INIT  NOOP
141 # undef  MY_CXT_CLONE
142 # define MY_CXT_CLONE NOOP
143 #endif
144
145 /* --- uplevel() data tokens ----------------------------------------------- */
146
147 typedef struct {
148  void *next;
149
150  I32  cxix;
151  CV  *target;
152  bool died;
153
154  PERL_SI *si;
155  PERL_SI *old_curstackinfo;
156  AV      *old_mainstack;
157
158  I32  old_depth;
159  COP *old_curcop;
160
161  bool old_catch;
162  OP  *old_op;
163  CV  *cloned_cv;
164 } su_uplevel_ud;
165
166 STATIC su_uplevel_ud *su_uplevel_ud_new(pTHX) {
167 #define su_uplevel_ud_new() su_uplevel_ud_new(aTHX)
168  su_uplevel_ud *sud;
169  PERL_SI       *si;
170
171  Newx(sud, 1, su_uplevel_ud);
172  sud->next = NULL;
173
174  Newx(si, 1, PERL_SI);
175  si->si_stack   = newAV();
176  AvREAL_off(si->si_stack);
177  si->si_cxstack = NULL;
178  sud->si = si;
179
180  return sud;
181 }
182
183 STATIC void su_uplevel_ud_delete(pTHX_ su_uplevel_ud *sud) {
184 #define su_uplevel_ud_delete(S) su_uplevel_ud_delete(aTHX_ (S))
185  PERL_SI *si = sud->si;
186
187  Safefree(si->si_cxstack);
188  SvREFCNT_dec(si->si_stack);
189  Safefree(si);
190  Safefree(sud);
191
192  return;
193 }
194
195 typedef struct {
196  su_uplevel_ud *root;
197  I32            count;
198 } su_uplevel_storage;
199
200 #ifndef SU_UPLEVEL_STORAGE_SIZE
201 # define SU_UPLEVEL_STORAGE_SIZE 4
202 #endif
203
204 /* --- Global data --------------------------------------------------------- */
205
206 #define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION
207
208 typedef struct {
209  char    *stack_placeholder;
210
211  I32      cxix;
212  I32      items;
213  SV     **savesp;
214  LISTOP   return_op;
215  OP       proxy_op;
216
217  su_uplevel_storage uplevel_storage;
218 } my_cxt_t;
219
220 START_MY_CXT
221
222 /* --- Stack manipulations ------------------------------------------------- */
223
224 #define SU_SAVE_PLACEHOLDER() save_pptr(&MY_CXT.stack_placeholder)
225
226 #define SU_SAVE_DESTRUCTOR_SIZE  3
227 #define SU_SAVE_PLACEHOLDER_SIZE 3
228
229 #define SU_SAVE_SCALAR_SIZE 3
230
231 #define SU_SAVE_ARY_SIZE      3
232 #define SU_SAVE_AELEM_SIZE    4
233 #ifdef SAVEADELETE
234 # define SU_SAVE_ADELETE_SIZE 3
235 #else
236 # define SU_SAVE_ADELETE_SIZE SU_SAVE_DESTRUCTOR_SIZE
237 #endif
238 #if SU_SAVE_AELEM_SIZE < SU_SAVE_ADELETE_SIZE
239 # define SU_SAVE_AELEM_OR_ADELETE_SIZE SU_SAVE_ADELETE_SIZE
240 #else
241 # define SU_SAVE_AELEM_OR_ADELETE_SIZE SU_SAVE_AELEM_SIZE
242 #endif
243
244 #define SU_SAVE_HASH_SIZE    3
245 #define SU_SAVE_HELEM_SIZE   4
246 #define SU_SAVE_HDELETE_SIZE 4
247 #if SU_SAVE_HELEM_SIZE < SU_SAVE_HDELETE_SIZE
248 # define SU_SAVE_HELEM_OR_HDELETE_SIZE SU_SAVE_HDELETE_SIZE
249 #else
250 # define SU_SAVE_HELEM_OR_HDELETE_SIZE SU_SAVE_HELEM_SIZE
251 #endif
252
253 #define SU_SAVE_GVCV_SIZE SU_SAVE_DESTRUCTOR_SIZE
254
255 #if !SU_HAS_PERL(5, 8, 9)
256 # define SU_SAVE_GP_SIZE 6
257 #elif !SU_HAS_PERL(5, 13, 0) || (SU_RELEASE && SU_HAS_PERL_EXACT(5, 13, 0))
258 # define SU_SAVE_GP_SIZE 3
259 #elif !SU_HAS_PERL(5, 13, 8)
260 # define SU_SAVE_GP_SIZE 4
261 #else
262 # define SU_SAVE_GP_SIZE 3
263 #endif
264
265 #ifndef SvCANEXISTDELETE
266 # define SvCANEXISTDELETE(sv) \
267   (!SvRMAGICAL(sv)            \
268    || ((mg = mg_find((SV *) sv, PERL_MAGIC_tied))            \
269        && (stash = SvSTASH(SvRV(SvTIED_obj((SV *) sv, mg)))) \
270        && gv_fetchmethod_autoload(stash, "EXISTS", TRUE)     \
271        && gv_fetchmethod_autoload(stash, "DELETE", TRUE)     \
272       )                       \
273    )
274 #endif
275
276 /* ... Saving array elements ............................................... */
277
278 STATIC I32 su_av_key2idx(pTHX_ AV *av, I32 key) {
279 #define su_av_key2idx(A, K) su_av_key2idx(aTHX_ (A), (K))
280  I32 idx;
281
282  if (key >= 0)
283   return key;
284
285 /* Added by MJD in perl-5.8.1 with 6f12eb6d2a1dfaf441504d869b27d2e40ef4966a */
286 #if SU_HAS_PERL(5, 8, 1)
287  if (SvRMAGICAL(av)) {
288   const MAGIC * const tied_magic = mg_find((SV *) av, PERL_MAGIC_tied);
289   if (tied_magic) {
290    SV * const * const negative_indices_glob =
291                     hv_fetch(SvSTASH(SvRV(SvTIED_obj((SV *) (av), tied_magic))),
292                              NEGATIVE_INDICES_VAR, 16, 0);
293    if (negative_indices_glob && SvTRUE(GvSV(*negative_indices_glob)))
294     return key;
295   }
296  }
297 #endif
298
299  idx = key + av_len(av) + 1;
300  if (idx < 0)
301   return key;
302
303  return idx;
304 }
305
306 #ifndef SAVEADELETE
307
308 typedef struct {
309  AV *av;
310  I32 idx;
311 } su_ud_adelete;
312
313 STATIC void su_adelete(pTHX_ void *ud_) {
314  su_ud_adelete *ud = (su_ud_adelete *) ud_;
315
316  av_delete(ud->av, ud->idx, G_DISCARD);
317  SvREFCNT_dec(ud->av);
318
319  Safefree(ud);
320 }
321
322 STATIC void su_save_adelete(pTHX_ AV *av, I32 idx) {
323 #define su_save_adelete(A, K) su_save_adelete(aTHX_ (A), (K))
324  su_ud_adelete *ud;
325
326  Newx(ud, 1, su_ud_adelete);
327  ud->av  = av;
328  ud->idx = idx;
329  SvREFCNT_inc_simple_void(av);
330
331  SAVEDESTRUCTOR_X(su_adelete, ud);
332 }
333
334 #define SAVEADELETE(A, K) su_save_adelete((A), (K))
335
336 #endif /* SAVEADELETE */
337
338 STATIC void su_save_aelem(pTHX_ AV *av, SV *key, SV *val) {
339 #define su_save_aelem(A, K, V) su_save_aelem(aTHX_ (A), (K), (V))
340  I32 idx;
341  I32 preeminent = 1;
342  SV **svp;
343  HV *stash;
344  MAGIC *mg;
345
346  idx = su_av_key2idx(av, SvIV(key));
347
348  if (SvCANEXISTDELETE(av))
349   preeminent = av_exists(av, idx);
350
351  svp = av_fetch(av, idx, 1);
352  if (!svp || *svp == &PL_sv_undef) croak(PL_no_aelem, idx);
353
354  if (preeminent)
355   save_aelem(av, idx, svp);
356  else
357   SAVEADELETE(av, idx);
358
359  if (val) { /* local $x[$idx] = $val; */
360   SvSetMagicSV(*svp, val);
361  } else {   /* local $x[$idx]; delete $x[$idx]; */
362   av_delete(av, idx, G_DISCARD);
363  }
364 }
365
366 /* ... Saving hash elements ................................................ */
367
368 STATIC void su_save_helem(pTHX_ HV *hv, SV *keysv, SV *val) {
369 #define su_save_helem(H, K, V) su_save_helem(aTHX_ (H), (K), (V))
370  I32 preeminent = 1;
371  HE *he;
372  SV **svp;
373  HV *stash;
374  MAGIC *mg;
375
376  if (SvCANEXISTDELETE(hv) || mg_find((SV *) hv, PERL_MAGIC_env))
377   preeminent = hv_exists_ent(hv, keysv, 0);
378
379  he  = hv_fetch_ent(hv, keysv, 1, 0);
380  svp = he ? &HeVAL(he) : NULL;
381  if (!svp || *svp == &PL_sv_undef) croak("Modification of non-creatable hash value attempted, subscript \"%s\"", SvPV_nolen_const(*svp));
382
383  if (HvNAME_get(hv) && isGV(*svp)) {
384   save_gp((GV *) *svp, 0);
385   return;
386  }
387
388  if (preeminent)
389   save_helem(hv, keysv, svp);
390  else {
391   STRLEN keylen;
392   const char * const key = SvPV_const(keysv, keylen);
393   SAVEDELETE(hv, savepvn(key, keylen),
394                  SvUTF8(keysv) ? -(I32)keylen : (I32)keylen);
395  }
396
397  if (val) { /* local $x{$keysv} = $val; */
398   SvSetMagicSV(*svp, val);
399  } else {   /* local $x{$keysv}; delete $x{$keysv}; */
400   (void)hv_delete_ent(hv, keysv, G_DISCARD, HeHASH(he));
401  }
402 }
403
404 /* ... Saving code slots from a glob ....................................... */
405
406 #if !SU_HAS_PERL(5, 10, 0) && !defined(mro_method_changed_in)
407 # define mro_method_changed_in(G) PL_sub_generation++
408 #endif
409
410 typedef struct {
411  GV *gv;
412  CV *old_cv;
413 } su_save_gvcv_ud;
414
415 STATIC void su_restore_gvcv(pTHX_ void *ud_) {
416  su_save_gvcv_ud *ud = ud_;
417  GV              *gv = ud->gv;
418
419  GvCV_set(gv, ud->old_cv);
420  GvCVGEN(gv) = 0;
421  mro_method_changed_in(GvSTASH(gv));
422
423  Safefree(ud);
424 }
425
426 STATIC void su_save_gvcv(pTHX_ GV *gv) {
427 #define su_save_gvcv(G) su_save_gvcv(aTHX_ (G))
428  su_save_gvcv_ud *ud;
429
430  Newx(ud, 1, su_save_gvcv_ud);
431  ud->gv     = gv;
432  ud->old_cv = GvCV(gv);
433
434  GvCV_set(gv, NULL);
435  GvCVGEN(gv) = 0;
436  mro_method_changed_in(GvSTASH(gv));
437
438  SAVEDESTRUCTOR_X(su_restore_gvcv, ud);
439 }
440
441 /* --- Actions ------------------------------------------------------------- */
442
443 typedef struct {
444  I32 depth;
445  I32 pad;
446  I32 *origin;
447  void (*handler)(pTHX_ void *);
448 } su_ud_common;
449
450 #define SU_UD_DEPTH(U)   (((su_ud_common *) (U))->depth)
451 #define SU_UD_PAD(U)     (((su_ud_common *) (U))->pad)
452 #define SU_UD_ORIGIN(U)  (((su_ud_common *) (U))->origin)
453 #define SU_UD_HANDLER(U) (((su_ud_common *) (U))->handler)
454
455 #define SU_UD_FREE(U) STMT_START { \
456  if (SU_UD_ORIGIN(U)) Safefree(SU_UD_ORIGIN(U)); \
457  Safefree(U); \
458 } STMT_END
459
460 /* ... Reap ................................................................ */
461
462 typedef struct {
463  su_ud_common ci;
464  SV *cb;
465 } su_ud_reap;
466
467 STATIC void su_call(pTHX_ void *ud_) {
468  su_ud_reap *ud = (su_ud_reap *) ud_;
469 #if SU_HAS_PERL(5, 9, 5)
470  PERL_CONTEXT saved_cx;
471  I32 cxix;
472 #endif
473
474  dSP;
475
476  SU_D({
477   PerlIO_printf(Perl_debug_log,
478                 "%p: @@@ call\n%p: depth=%2d scope_ix=%2d save_ix=%2d\n",
479                  ud, ud, SU_UD_DEPTH(ud), PL_scopestack_ix, PL_savestack_ix);
480  });
481
482  ENTER;
483  SAVETMPS;
484
485  PUSHMARK(SP);
486  PUTBACK;
487
488  /* If the recently popped context isn't saved there, it will be overwritten by
489   * the sub scope from call_sv, although it's still needed in our caller. */
490
491 #if SU_HAS_PERL(5, 9, 5)
492  if (cxstack_ix < cxstack_max)
493   cxix = cxstack_ix + 1;
494  else
495   cxix = Perl_cxinc(aTHX);
496  saved_cx = cxstack[cxix];
497 #endif
498
499  call_sv(ud->cb, G_VOID);
500
501 #if SU_HAS_PERL(5, 9, 5)
502  cxstack[cxix] = saved_cx;
503 #endif
504
505  PUTBACK;
506
507  FREETMPS;
508  LEAVE;
509
510  SvREFCNT_dec(ud->cb);
511  SU_UD_FREE(ud);
512 }
513
514 STATIC void su_reap(pTHX_ void *ud) {
515 #define su_reap(U) su_reap(aTHX_ (U))
516  SU_D({
517   PerlIO_printf(Perl_debug_log,
518                 "%p: === reap\n%p: depth=%2d scope_ix=%2d save_ix=%2d\n",
519                  ud, ud, SU_UD_DEPTH(ud), PL_scopestack_ix, PL_savestack_ix);
520  });
521
522  SAVEDESTRUCTOR_X(su_call, ud);
523 }
524
525 /* ... Localize & localize array/hash element .............................. */
526
527 typedef struct {
528  su_ud_common ci;
529  SV    *sv;
530  SV    *val;
531  SV    *elem;
532  svtype type;
533 } su_ud_localize;
534
535 #define SU_UD_LOCALIZE_FREE(U) STMT_START { \
536  SvREFCNT_dec((U)->elem); \
537  SvREFCNT_dec((U)->val);  \
538  SvREFCNT_dec((U)->sv);   \
539  SU_UD_FREE(U);           \
540 } STMT_END
541
542 STATIC I32 su_ud_localize_init(pTHX_ su_ud_localize *ud, SV *sv, SV *val, SV *elem) {
543 #define su_ud_localize_init(UD, S, V, E) su_ud_localize_init(aTHX_ (UD), (S), (V), (E))
544  UV deref = 0;
545  svtype t = SVt_NULL;
546  I32 size;
547
548  SvREFCNT_inc_simple_void(sv);
549
550  if (SvTYPE(sv) >= SVt_PVGV) {
551   if (!val || !SvROK(val)) { /* local *x; or local *x = $val; */
552    t = SVt_PVGV;
553   } else {                   /* local *x = \$val; */
554    t = SvTYPE(SvRV(val));
555    deref = 1;
556   }
557  } else if (SvROK(sv)) {
558   croak("Invalid %s reference as the localization target",
559                  sv_reftype(SvRV(sv), 0));
560  } else {
561   STRLEN len, l;
562   const char *p = SvPV_const(sv, len), *s;
563   for (s = p, l = len; l > 0 && isSPACE(*s); ++s, --l) { }
564   if (!l) {
565    l = len;
566    s = p;
567   }
568   switch (*s) {
569    case '$': t = SVt_PV;   break;
570    case '@': t = SVt_PVAV; break;
571    case '%': t = SVt_PVHV; break;
572    case '&': t = SVt_PVCV; break;
573    case '*': t = SVt_PVGV; break;
574   }
575   if (t != SVt_NULL) {
576    ++s;
577    --l;
578   } else if (val) { /* t == SVt_NULL, type can't be inferred from the sigil */
579    if (SvROK(val) && !sv_isobject(val)) {
580     t = SvTYPE(SvRV(val));
581     deref = 1;
582    } else {
583     t = SvTYPE(val);
584    }
585   }
586   SvREFCNT_dec(sv);
587   sv = newSVpvn(s, l);
588  }
589
590  switch (t) {
591   case SVt_PVAV:
592    size  = elem ? SU_SAVE_AELEM_OR_ADELETE_SIZE
593                 : SU_SAVE_ARY_SIZE;
594    deref = 0;
595    break;
596   case SVt_PVHV:
597    size  = elem ? SU_SAVE_HELEM_OR_HDELETE_SIZE
598                 : SU_SAVE_HASH_SIZE;
599    deref = 0;
600    break;
601   case SVt_PVGV:
602    size  = SU_SAVE_GP_SIZE;
603    deref = 0;
604    break;
605   case SVt_PVCV:
606    size  = SU_SAVE_GVCV_SIZE;
607    deref = 0;
608    break;
609   default:
610    size = SU_SAVE_SCALAR_SIZE;
611    break;
612  }
613  /* When deref is set, val isn't NULL */
614
615  ud->sv   = sv;
616  ud->val  = val ? newSVsv(deref ? SvRV(val) : val) : NULL;
617  ud->elem = SvREFCNT_inc(elem);
618  ud->type = t;
619
620  return size;
621 }
622
623 STATIC void su_localize(pTHX_ void *ud_) {
624 #define su_localize(U) su_localize(aTHX_ (U))
625  su_ud_localize *ud = (su_ud_localize *) ud_;
626  SV *sv   = ud->sv;
627  SV *val  = ud->val;
628  SV *elem = ud->elem;
629  svtype t = ud->type;
630  GV *gv;
631
632  if (SvTYPE(sv) >= SVt_PVGV) {
633   gv = (GV *) sv;
634  } else {
635 #ifdef gv_fetchsv
636   gv = gv_fetchsv(sv, GV_ADDMULTI, t);
637 #else
638   STRLEN len;
639   const char *name = SvPV_const(sv, len);
640   gv = gv_fetchpvn_flags(name, len, GV_ADDMULTI, t);
641 #endif
642  }
643
644  SU_D({
645   SV *z = newSV(0);
646   SvUPGRADE(z, t);
647   PerlIO_printf(Perl_debug_log, "%p: === localize a %s\n",ud, sv_reftype(z, 0));
648   PerlIO_printf(Perl_debug_log,
649                 "%p: depth=%2d scope_ix=%2d save_ix=%2d\n",
650                  ud, SU_UD_DEPTH(ud), PL_scopestack_ix, PL_savestack_ix);
651   SvREFCNT_dec(z);
652  });
653
654  /* Inspired from Alias.pm */
655  switch (t) {
656   case SVt_PVAV:
657    if (elem) {
658     su_save_aelem(GvAV(gv), elem, val);
659     goto done;
660    } else
661     save_ary(gv);
662    break;
663   case SVt_PVHV:
664    if (elem) {
665     su_save_helem(GvHV(gv), elem, val);
666     goto done;
667    } else
668     save_hash(gv);
669    break;
670   case SVt_PVGV:
671    save_gp(gv, 1); /* hide previous entry in symtab */
672    break;
673   case SVt_PVCV:
674    su_save_gvcv(gv);
675    break;
676   default:
677    gv = (GV *) save_scalar(gv);
678    break;
679  }
680
681  if (val)
682   SvSetMagicSV((SV *) gv, val);
683
684 done:
685  SU_UD_LOCALIZE_FREE(ud);
686 }
687
688 /* --- Pop a context back -------------------------------------------------- */
689
690 #if SU_DEBUG
691 # ifdef DEBUGGING
692 #  define SU_CXNAME PL_block_type[CxTYPE(&cxstack[cxstack_ix])]
693 # else
694 #  define SU_CXNAME "XXX"
695 # endif
696 #endif
697
698 STATIC void su_pop(pTHX_ void *ud) {
699 #define su_pop(U) su_pop(aTHX_ (U))
700  I32 depth, base, mark, *origin;
701  depth = SU_UD_DEPTH(ud);
702
703  SU_D(
704   PerlIO_printf(Perl_debug_log,
705    "%p: --- pop a %s\n"
706    "%p: leave scope     at depth=%2d scope_ix=%2d cur_top=%2d cur_base=%2d\n",
707     ud, SU_CXNAME,
708     ud, depth, PL_scopestack_ix,PL_savestack_ix,PL_scopestack[PL_scopestack_ix])
709  );
710
711  origin = SU_UD_ORIGIN(ud);
712  mark   = origin[depth];
713  base   = origin[depth - 1];
714
715  SU_D(PerlIO_printf(Perl_debug_log,
716                     "%p: original scope was %*c top=%2d     base=%2d\n",
717                      ud,                24, ' ',    mark,        base));
718
719  if (base < mark) {
720   SU_D(PerlIO_printf(Perl_debug_log, "%p: clear leftovers\n", ud));
721   PL_savestack_ix = mark;
722   leave_scope(base);
723  }
724  PL_savestack_ix = base;
725
726  SU_UD_DEPTH(ud) = --depth;
727
728  if (depth > 0) {
729   I32 pad;
730
731   if ((pad = SU_UD_PAD(ud))) {
732    dMY_CXT;
733    do {
734     SU_D(PerlIO_printf(Perl_debug_log,
735           "%p: push a pad slot at depth=%2d scope_ix=%2d save_ix=%2d\n",
736            ud,                       depth, PL_scopestack_ix, PL_savestack_ix));
737     SU_SAVE_PLACEHOLDER();
738    } while (--pad);
739   }
740
741   SU_D(PerlIO_printf(Perl_debug_log,
742           "%p: push destructor at depth=%2d scope_ix=%2d save_ix=%2d\n",
743            ud,                       depth, PL_scopestack_ix, PL_savestack_ix));
744   SAVEDESTRUCTOR_X(su_pop, ud);
745  } else {
746   SU_UD_HANDLER(ud)(aTHX_ ud);
747  }
748
749  SU_D(PerlIO_printf(Perl_debug_log,
750                     "%p: --- end pop: cur_top=%2d == cur_base=%2d\n",
751                      ud, PL_savestack_ix, PL_scopestack[PL_scopestack_ix]));
752 }
753
754 /* --- Initialize the stack and the action userdata ------------------------ */
755
756 STATIC I32 su_init(pTHX_ void *ud, I32 cxix, I32 size) {
757 #define su_init(U, C, S) su_init(aTHX_ (U), (C), (S))
758  I32 i, depth = 1, pad, offset, *origin;
759
760  SU_D(PerlIO_printf(Perl_debug_log, "%p: ### init for cx %d\n", ud, cxix));
761
762  if (size <= SU_SAVE_DESTRUCTOR_SIZE)
763   pad = 0;
764  else {
765   I32 extra = size - SU_SAVE_DESTRUCTOR_SIZE;
766   pad = extra / SU_SAVE_PLACEHOLDER_SIZE;
767   if (extra % SU_SAVE_PLACEHOLDER_SIZE)
768    ++pad;
769  }
770  offset = SU_SAVE_DESTRUCTOR_SIZE + SU_SAVE_PLACEHOLDER_SIZE * pad;
771
772  SU_D(PerlIO_printf(Perl_debug_log, "%p: size=%d pad=%d offset=%d\n",
773                                      ud,    size,   pad,   offset));
774
775  for (i = cxstack_ix; i > cxix; --i) {
776   PERL_CONTEXT *cx = cxstack + i;
777   switch (CxTYPE(cx)) {
778 #if SU_HAS_PERL(5, 10, 0)
779    case CXt_BLOCK:
780     SU_D(PerlIO_printf(Perl_debug_log, "%p: cx %d is block\n", ud, i));
781     /* Given and when blocks are actually followed by a simple block, so skip
782      * it if needed. */
783     if (cxix > 0) { /* Implies i > 0 */
784      PERL_CONTEXT *next = cx - 1;
785      if (CxTYPE(next) == CXt_GIVEN || CxTYPE(next) == CXt_WHEN)
786       --cxix;
787     }
788     depth++;
789     break;
790 #endif
791 #if SU_HAS_PERL(5, 11, 0)
792    case CXt_LOOP_FOR:
793    case CXt_LOOP_PLAIN:
794    case CXt_LOOP_LAZYSV:
795    case CXt_LOOP_LAZYIV:
796 #else
797    case CXt_LOOP:
798 #endif
799     SU_D(PerlIO_printf(Perl_debug_log, "%p: cx %d is loop\n", ud, i));
800     depth += 2;
801     break;
802    default:
803     SU_D(PerlIO_printf(Perl_debug_log, "%p: cx %d is other\n", ud, i));
804     depth++;
805     break;
806   }
807  }
808  SU_D(PerlIO_printf(Perl_debug_log, "%p: going down to depth %d\n", ud, depth));
809
810  Newx(origin, depth + 1, I32);
811  origin[0] = PL_scopestack[PL_scopestack_ix - depth];
812  PL_scopestack[PL_scopestack_ix - depth] += size;
813  for (i = depth - 1; i >= 1; --i) {
814   I32 j = PL_scopestack_ix - i;
815   origin[depth - i] = PL_scopestack[j];
816   PL_scopestack[j] += offset;
817  }
818  origin[depth] = PL_savestack_ix;
819
820  SU_UD_ORIGIN(ud) = origin;
821  SU_UD_DEPTH(ud)  = depth;
822  SU_UD_PAD(ud)    = pad;
823
824  /* Make sure the first destructor fires by pushing enough fake slots on the
825   * stack. */
826  if (PL_savestack_ix + SU_SAVE_DESTRUCTOR_SIZE
827                                        <= PL_scopestack[PL_scopestack_ix - 1]) {
828   dMY_CXT;
829   do {
830    SU_D(PerlIO_printf(Perl_debug_log,
831                   "%p: push a fake slot      at scope_ix=%2d  save_ix=%2d\n",
832                    ud,                      PL_scopestack_ix, PL_savestack_ix));
833    SU_SAVE_PLACEHOLDER();
834   } while (PL_savestack_ix + SU_SAVE_DESTRUCTOR_SIZE
835                                         <= PL_scopestack[PL_scopestack_ix - 1]);
836  }
837  SU_D(PerlIO_printf(Perl_debug_log,
838                   "%p: push first destructor at scope_ix=%2d  save_ix=%2d\n",
839                    ud,                      PL_scopestack_ix, PL_savestack_ix));
840  SAVEDESTRUCTOR_X(su_pop, ud);
841
842  SU_D({
843   for (i = 0; i <= depth; ++i) {
844    I32 j = PL_scopestack_ix  - i;
845    PerlIO_printf(Perl_debug_log,
846                  "%p: depth=%2d scope_ix=%2d saved_floor=%2d new_floor=%2d\n",
847                   ud,        i, j, origin[depth - i],
848                                    i == 0 ? PL_savestack_ix : PL_scopestack[j]);
849   }
850  });
851
852  return depth;
853 }
854
855 /* --- Unwind stack -------------------------------------------------------- */
856
857 STATIC void su_unwind(pTHX_ void *ud_) {
858  dMY_CXT;
859  I32 cxix    = MY_CXT.cxix;
860  I32 items   = MY_CXT.items - 1;
861  SV **savesp = MY_CXT.savesp;
862  I32 mark;
863
864  PERL_UNUSED_VAR(ud_);
865
866  if (savesp)
867   PL_stack_sp = savesp;
868
869  if (cxstack_ix > cxix)
870   dounwind(cxix);
871
872  /* Hide the level */
873  if (items >= 0)
874   PL_stack_sp--;
875
876  mark = PL_markstack[cxstack[cxix].blk_oldmarksp];
877  *PL_markstack_ptr = PL_stack_sp - PL_stack_base - items;
878
879  SU_D({
880   I32 gimme = GIMME_V;
881   PerlIO_printf(Perl_debug_log,
882                 "%p: cx=%d gimme=%s items=%d sp=%d oldmark=%d mark=%d\n",
883                 &MY_CXT, cxix,
884                 gimme == G_VOID ? "void" : gimme == G_ARRAY ? "list" : "scalar",
885                 items, PL_stack_sp - PL_stack_base, *PL_markstack_ptr, mark);
886  });
887
888  PL_op = (OP *) &(MY_CXT.return_op);
889  PL_op = PL_op->op_ppaddr(aTHX);
890
891  *PL_markstack_ptr = mark;
892
893  MY_CXT.proxy_op.op_next = PL_op;
894  PL_op = &(MY_CXT.proxy_op);
895 }
896
897 /* --- Uplevel ------------------------------------------------------------- */
898
899 #ifndef OP_GIMME_REVERSE
900 STATIC U8 su_op_gimme_reverse(U8 gimme) {
901  switch (gimme) {
902   case G_VOID:
903    return OPf_WANT_VOID;
904   case G_ARRAY:
905    return OPf_WANT_LIST;
906   default:
907    break;
908  }
909
910  return OPf_WANT_SCALAR;
911 }
912 #define OP_GIMME_REVERSE(G) su_op_gimme_reverse(G)
913 #endif
914
915 #define SU_UPLEVEL_SAVE(f, t) STMT_START { sud->old_##f = PL_##f; PL_##f = (t); } STMT_END
916 #define SU_UPLEVEL_RESTORE(f) STMT_START { PL_##f = sud->old_##f; } STMT_END
917
918 STATIC int su_uplevel_restore_free(pTHX_ SV *sv, MAGIC *mg) {
919  su_uplevel_ud_delete((su_uplevel_ud *) mg->mg_ptr);
920
921  return 0;
922 }
923
924 STATIC MGVTBL su_uplevel_restore_vtbl = {
925  0,
926  0,
927  0,
928  0,
929  su_uplevel_restore_free
930 };
931
932 STATIC void su_uplevel_restore(pTHX_ void *sus_) {
933  su_uplevel_ud *sud = sus_;
934  PERL_SI *cur = sud->old_curstackinfo;
935  PERL_SI *si  = sud->si;
936  dMY_CXT;
937
938  /* When we reach this place, POPSUB has already been called (with our fake
939   * argarray). GvAV(PL_defgv) points to the savearray (that is, what @_ was
940   * before uplevel). argarray is either the fake AV we created in su_uplevel()
941   * or some empty replacement POPSUB creates when @_ is reified. In both cases
942   * we have to destroy it before the context stack is swapped back to its
943   * original state. */
944  SvREFCNT_dec(cxstack[sud->cxix].blk_sub.argarray);
945
946  CATCH_SET(sud->old_catch);
947
948  SvREFCNT_dec(sud->cloned_cv);
949
950  SU_UPLEVEL_RESTORE(op);
951
952  /* stack_grow() wants PL_curstack so restore the old stack first */
953  if (PL_curstackinfo == si) {
954   PL_curstack = cur->si_stack;
955   if (sud->old_mainstack)
956    SU_UPLEVEL_RESTORE(mainstack);
957   SU_UPLEVEL_RESTORE(curstackinfo);
958
959   if (sud->died) {
960    CV *target_cv = sud->target;
961    I32 levels = 0, i;
962
963    /* When we die, the depth of the target CV is not updated because of the
964     * stack switcheroo. So we have to look at all the frames between the
965     * uplevel call and the catch block to count how many call frames to the
966     * target CV were skipped. */
967    for (i = cur->si_cxix; i > sud->cxix; i--) {
968     register const PERL_CONTEXT *cx = cxstack + i;
969
970     if (CxTYPE(cx) == CXt_SUB) {
971      if (cx->blk_sub.cv == target_cv)
972       ++levels;
973     }
974    }
975
976    /* If we died, the replacement stack was already unwinded to the first
977     * eval frame, and all the contexts down there were popped. We don't have
978     * to pop manually any context of the original stack, because they must
979     * have been in the replacement stack as well (since the second was copied
980     * from the first). Thus we only have to make sure the original stack index
981     * points to the context just below the first eval scope under the target
982     * frame. */
983    for (; i >= 0; i--) {
984     register const PERL_CONTEXT *cx = cxstack + i;
985
986     switch (CxTYPE(cx)) {
987      case CXt_SUB:
988       if (cx->blk_sub.cv == target_cv)
989        ++levels;
990       break;
991      case CXt_EVAL:
992       goto found_it;
993       break;
994      default:
995       break;
996     }
997    }
998
999 found_it:
1000    CvDEPTH(target_cv) = sud->old_depth - levels;
1001    PL_curstackinfo->si_cxix = i - 1;
1002
1003 #if !SU_HAS_PERL(5, 13, 1)
1004    /* Since $@ was maybe localized between the target frame and the uplevel
1005     * call, we forcefully flush the save stack to get rid of it and then
1006     * reset $@ to its proper value. Note that the the call to
1007     * su_uplevel_restore() must happen before the "reset $@" item of the save
1008     * stack is processed, as uplevel was called after the localization.
1009     * Andrew's change to how $@ was treated, which were mainly integrated
1010     * between perl 5.13.0 and 5.13.1, fixed this. */
1011    if (ERRSV && SvTRUE(ERRSV)) {
1012     register const PERL_CONTEXT *cx = cxstack + i; /* This is the eval scope */
1013     SV *errsv = SvREFCNT_inc(ERRSV);
1014     PL_scopestack_ix = cx->blk_oldscopesp;
1015     leave_scope(PL_scopestack[PL_scopestack_ix]);
1016     sv_setsv(ERRSV, errsv);
1017     SvREFCNT_dec(errsv);
1018    }
1019 #endif
1020   }
1021  }
1022
1023  SU_UPLEVEL_RESTORE(curcop);
1024
1025  SvREFCNT_dec(sud->target);
1026
1027  PL_stack_base = AvARRAY(cur->si_stack);
1028  PL_stack_sp   = PL_stack_base + AvFILLp(cur->si_stack);
1029  PL_stack_max  = PL_stack_base + AvMAX(cur->si_stack);
1030
1031 #if SU_HAS_PERL(5, 8, 0)
1032  if (MY_CXT.uplevel_storage.count >= SU_UPLEVEL_STORAGE_SIZE) {
1033   /* When an exception is thrown from the uplevel'd subroutine,
1034    * su_uplevel_restore() may be called by the LEAVE in die_unwind() (called
1035    * die_where() in more recent perls), which has the sad habit of keeping a
1036    * pointer to the current context frame across this call. This means that
1037    * we can't free the temporary context stack we used for the uplevel call
1038    * right now, or that pointer upwards would point to garbage. We work around
1039    * this by attaching the state data to a scalar that will be freed "soon".
1040    * This issue has been fixed in perl with commit 8f89e5a9. */
1041   SV *sv = sv_newmortal();
1042   sv_magicext(sv, NULL, PERL_MAGIC_ext, &su_uplevel_restore_vtbl,
1043                         (const char *) sud, 0);
1044  } else {
1045 #endif
1046   sud->next = MY_CXT.uplevel_storage.root;
1047   MY_CXT.uplevel_storage.root = sud;
1048   MY_CXT.uplevel_storage.count++;
1049 #if SU_HAS_PERL(5, 8, 0)
1050  }
1051 #endif
1052
1053  return;
1054 }
1055
1056 STATIC CV *su_cv_clone(pTHX_ CV *old_cv) {
1057 #define su_cv_clone(C) su_cv_clone(aTHX_ (C))
1058  CV *new_cv;
1059
1060  /* Starting from commit b5c19bd7, cv_clone() has an assert that checks whether
1061   * CvDEPTH(CvOUTSIDE(proto)) > 0, so we have to fool cv_clone() with a little
1062   * dance. */
1063 #if defined(DEBUGGING) && SU_HAS_PERL(5, 9, 0)
1064  I32 old_depth;
1065  CV *outside = CvOUTSIDE(old_cv);
1066
1067  if (outside && CvCLONE(outside) && !CvCLONED(outside))
1068   outside = find_runcv(NULL);
1069  old_depth = CvDEPTH(outside);
1070  if (!old_depth)
1071   CvDEPTH(outside) = 1;
1072 #endif
1073
1074  new_cv = cv_clone(old_cv);
1075
1076 #if defined(DEBUGGING) && SU_HAS_PERL(5, 9, 0)
1077  CvDEPTH(outside) = old_depth;
1078 #endif
1079
1080  /* Starting from perl 5.9 (more exactly commit b5c19bd7), cv_clone() is no
1081   * longer able to clone named subs propery. With this commit, pad_findlex()
1082   * stores the parent index of a fake pad entry in the NV slot of the
1083   * corresponding pad name SV, but only for anonymous subs (since named subs
1084   * aren't supposed to be cloned in pure Perl land). To fix this, we just
1085   * manually relink the new fake pad entries to the new ones.
1086   * For some reason perl 5.8 crashes too without this, supposedly because of
1087   * other closure bugs. Hence we enable it everywhere. */
1088  if (!CvCLONE(old_cv)) {
1089   const AV  *old_padname = (const AV *)  AvARRAY(CvPADLIST(old_cv))[0];
1090   AV        *old_pad     = (AV *)        AvARRAY(CvPADLIST(old_cv))[1];
1091   AV        *new_pad     = (AV *)        AvARRAY(CvPADLIST(new_cv))[1];
1092   const SV **old_aryname = (const SV **) AvARRAY(old_padname);
1093   SV       **old_ary     = AvARRAY(old_pad);
1094   SV       **new_ary     = AvARRAY(new_pad);
1095   I32 fname = AvFILLp(old_padname);
1096   I32 fpad  = AvFILLp(old_pad);
1097   I32 ix;
1098
1099   for (ix = fpad; ix > 0; ix--) {
1100    const SV *namesv = (ix <= fname) ? old_aryname[ix] : NULL;
1101
1102    if (namesv && namesv != &PL_sv_undef && SvFAKE(namesv)) {
1103     SvREFCNT_dec(new_ary[ix]);
1104     new_ary[ix] = SvREFCNT_inc(old_ary[ix]);
1105    }
1106   }
1107  }
1108
1109  return new_cv;
1110 }
1111
1112 STATIC I32 su_uplevel(pTHX_ CV *cv, I32 cxix, I32 args) {
1113 #define su_uplevel(C, I, A) su_uplevel(aTHX_ (C), (I), (A))
1114  su_uplevel_ud *sud;
1115  const PERL_CONTEXT *cx = cxstack + cxix;
1116  PERL_SI *si;
1117  PERL_SI *cur = PL_curstackinfo;
1118  SV **old_stack_sp;
1119  CV  *target_cv;
1120  UNOP sub_op;
1121  I32  marksize;
1122  I32  gimme;
1123  I32  old_mark, new_mark;
1124  I32  ret;
1125  dSP;
1126  dMY_CXT;
1127
1128  ENTER;
1129
1130  gimme = GIMME_V;
1131  /* Make PL_stack_sp point just before the CV. */
1132  PL_stack_sp -= args + 1;
1133  old_mark = AvFILLp(PL_curstack) = PL_stack_sp - PL_stack_base;
1134  SPAGAIN;
1135
1136  sud = MY_CXT.uplevel_storage.root;
1137  if (sud) {
1138   MY_CXT.uplevel_storage.root = sud->next;
1139   MY_CXT.uplevel_storage.count--;
1140  } else {
1141   sud = su_uplevel_ud_new();
1142  }
1143  si = sud->si;
1144
1145  sud->cxix = cxix;
1146  sud->died = 1;
1147  SAVEDESTRUCTOR_X(su_uplevel_restore, sud);
1148
1149  si->si_type = cur->si_type;
1150  si->si_next = NULL;
1151  si->si_prev = cur->si_prev;
1152
1153  /* Allocate enough space for all the elements of the original stack up to the
1154   * target context, plus the forthcoming arguments. */
1155  new_mark = cx->blk_oldsp;
1156  av_extend(si->si_stack, new_mark + 1 + args + 1);
1157  Copy(PL_curstack, AvARRAY(si->si_stack), new_mark + 1, SV *);
1158  AvFILLp(si->si_stack) = new_mark;
1159  SU_POISON(AvARRAY(si->si_stack) + new_mark + 1, args + 1, SV *);
1160
1161  /* Specialized SWITCHSTACK() */
1162  PL_stack_base = AvARRAY(si->si_stack);
1163  old_stack_sp  = PL_stack_sp;
1164  PL_stack_sp   = PL_stack_base + AvFILLp(si->si_stack);
1165  PL_stack_max  = PL_stack_base + AvMAX(si->si_stack);
1166  SPAGAIN;
1167
1168 #ifdef DEBUGGING
1169  si->si_markoff = cx->blk_oldmarksp;
1170 #endif
1171
1172  /* Copy the context stack up to the context just below the target. */
1173  si->si_cxix  = (cxix < 0) ? -1 : (cxix - 1);
1174  /* The max size must be at least two so that GROW(max) = (max * 3) / 2 > max */
1175  si->si_cxmax = (cxix < 4) ?  4 : cxix;
1176  Renew(si->si_cxstack, si->si_cxmax + 1,     PERL_CONTEXT);
1177  Copy(cur->si_cxstack, si->si_cxstack, cxix, PERL_CONTEXT);
1178  SU_POISON(si->si_cxstack + cxix, si->si_cxmax + 1 - cxix, PERL_CONTEXT);
1179
1180  target_cv      = cx->blk_sub.cv;
1181  sud->target    = (CV *) SvREFCNT_inc(target_cv);
1182  sud->old_depth = CvDEPTH(target_cv);
1183
1184  /* blk_oldcop is essentially needed for caller() and stack traces. It has no
1185   * run-time implication, since PL_curcop will be overwritten as soon as we
1186   * enter a sub (a sub starts by a nextstate/dbstate). Hence it's safe to just
1187   * make it point to the blk_oldcop for the target frame, so that caller()
1188   * reports the right file name, line number and lexical hints. */
1189  SU_UPLEVEL_SAVE(curcop, cx->blk_oldcop);
1190  /* Don't reset PL_markstack_ptr, or we would overwrite the mark stack below
1191   * this point. */
1192  /* Don't reset PL_curpm, we want the most recent matches. */
1193
1194  SU_UPLEVEL_SAVE(curstackinfo, si);
1195  /* If those two are equal, we need to fool POPSTACK_TO() */
1196  if (PL_mainstack == PL_curstack)
1197   SU_UPLEVEL_SAVE(mainstack, si->si_stack);
1198  else
1199   sud->old_mainstack = NULL;
1200  PL_curstack = si->si_stack;
1201
1202  cv = su_cv_clone(cv);
1203  sud->cloned_cv = cv;
1204  CvGV_set(cv, CvGV(target_cv));
1205
1206  PUSHMARK(SP);
1207  /* Both SP and old_stack_sp points just before the CV. */
1208  Copy(old_stack_sp + 2, SP + 1, args, SV *);
1209  SP += args;
1210  PUSHs((SV *) cv);
1211  PUTBACK;
1212
1213  Zero(&sub_op, 1, UNOP);
1214  sub_op.op_type  = OP_ENTERSUB;
1215  sub_op.op_next  = NULL;
1216  sub_op.op_flags = OP_GIMME_REVERSE(gimme) | OPf_STACKED;
1217  if (PL_DBsub)
1218   sub_op.op_flags |= OPpENTERSUB_DB;
1219
1220  SU_UPLEVEL_SAVE(op, (OP *) &sub_op);
1221
1222  sud->old_catch = CATCH_GET;
1223  CATCH_SET(TRUE);
1224
1225  if (PL_op = PL_ppaddr[OP_ENTERSUB](aTHX)) {
1226   if (CxHASARGS(cx) && cx->blk_sub.argarray) {
1227    /* The call to pp_entersub() has saved the current @_ (in XS terms,
1228     * GvAV(PL_defgv)) in the savearray member, and has created a new argarray
1229     * with what we put on the stack. But we want to fake up the same arguments
1230     * as the ones in use at the context we uplevel to, so we replace the
1231     * argarray with an unreal copy of the original @_. */
1232    AV *av = newAV();
1233    AvREAL_off(av);
1234    av_extend(av, AvMAX(cx->blk_sub.argarray));
1235    AvFILLp(av) = AvFILLp(cx->blk_sub.argarray);
1236    Copy(AvARRAY(cx->blk_sub.argarray), AvARRAY(av), AvFILLp(av) + 1, SV *);
1237    cxstack[cxix].blk_sub.argarray = av;
1238   } else if (PL_DBsub) {
1239    SvREFCNT_inc(cxstack[cxix].blk_sub.argarray);
1240   }
1241
1242   CALLRUNOPS(aTHX);
1243
1244   ret = PL_stack_sp - (PL_stack_base + new_mark);
1245  }
1246
1247  sud->died = 0;
1248
1249  SPAGAIN;
1250
1251  if (ret > 0) {
1252   AV *old_stack = sud->old_curstackinfo->si_stack;
1253
1254   if (old_mark + ret > AvMAX(old_stack)) {
1255    /* Specialized EXTEND(old_sp, ret) */
1256    av_extend(old_stack, old_mark + ret + 1);
1257    old_stack_sp = AvARRAY(old_stack) + old_mark;
1258   }
1259
1260   Copy(PL_stack_sp - ret + 1, old_stack_sp + 1, ret, SV *);
1261   PL_stack_sp        += ret;
1262   AvFILLp(old_stack) += ret;
1263  }
1264
1265  PUTBACK;
1266
1267  LEAVE;
1268
1269  return ret;
1270 }
1271
1272 /* --- Interpreter setup/teardown ------------------------------------------ */
1273
1274 STATIC void su_teardown(pTHX_ void *param) {
1275  su_uplevel_ud *cur, *prev;
1276  dMY_CXT;
1277
1278  cur = MY_CXT.uplevel_storage.root;
1279  if (cur) {
1280   su_uplevel_ud *prev;
1281   do {
1282    prev = cur;
1283    cur  = prev->next;
1284    su_uplevel_ud_delete(prev);
1285   } while (cur);
1286  }
1287
1288  return;
1289 }
1290
1291 STATIC void su_setup(pTHX) {
1292 #define su_setup() su_setup(aTHX)
1293  MY_CXT_INIT;
1294
1295  MY_CXT.stack_placeholder = NULL;
1296
1297  /* NewOp() calls calloc() which just zeroes the memory with memset(). */
1298  Zero(&(MY_CXT.return_op), 1, sizeof(MY_CXT.return_op));
1299  MY_CXT.return_op.op_type   = OP_RETURN;
1300  MY_CXT.return_op.op_ppaddr = PL_ppaddr[OP_RETURN];
1301
1302  Zero(&(MY_CXT.proxy_op), 1, sizeof(MY_CXT.proxy_op));
1303  MY_CXT.proxy_op.op_type   = OP_STUB;
1304  MY_CXT.proxy_op.op_ppaddr = NULL;
1305
1306  MY_CXT.uplevel_storage.root  = NULL;
1307  MY_CXT.uplevel_storage.count = 0;
1308
1309  call_atexit(su_teardown, NULL);
1310
1311  return;
1312 }
1313
1314 /* --- XS ------------------------------------------------------------------ */
1315
1316 #if SU_HAS_PERL(5, 8, 9)
1317 # define SU_SKIP_DB_MAX 2
1318 #else
1319 # define SU_SKIP_DB_MAX 3
1320 #endif
1321
1322 /* Skip context sequences of 1 to SU_SKIP_DB_MAX (included) block contexts
1323  * followed by a DB sub */
1324
1325 #define SU_SKIP_DB(C) \
1326  STMT_START {         \
1327   I32 skipped = 0;    \
1328   PERL_CONTEXT *base = cxstack;      \
1329   PERL_CONTEXT *cx   = base + (C);   \
1330   while (cx >= base && (C) > skipped && CxTYPE(cx) == CXt_BLOCK) \
1331    --cx, ++skipped;                  \
1332   if (cx >= base && (C) > skipped) { \
1333    switch (CxTYPE(cx)) {  \
1334     case CXt_SUB:         \
1335      if (skipped <= SU_SKIP_DB_MAX && cx->blk_sub.cv == GvCV(PL_DBsub)) \
1336       (C) -= skipped + 1; \
1337       break;              \
1338     default:              \
1339      break;               \
1340    }                      \
1341   }                       \
1342  } STMT_END
1343
1344 #define SU_GET_CONTEXT(A, B)   \
1345  STMT_START {                  \
1346   if (items > A) {             \
1347    SV *csv = ST(B);            \
1348    if (!SvOK(csv))             \
1349     goto default_cx;           \
1350    cxix = SvIV(csv);           \
1351    if (cxix < 0)               \
1352     cxix = 0;                  \
1353    else if (cxix > cxstack_ix) \
1354     cxix = cxstack_ix;         \
1355   } else {                     \
1356 default_cx:                    \
1357    cxix = cxstack_ix;          \
1358    if (PL_DBsub)               \
1359     SU_SKIP_DB(cxix);          \
1360   }                            \
1361  } STMT_END
1362
1363 #define SU_GET_LEVEL(A, B) \
1364  STMT_START {              \
1365   level = 0;               \
1366   if (items > 0) {         \
1367    SV *lsv = ST(B);        \
1368    if (SvOK(lsv)) {        \
1369     level = SvIV(lsv);     \
1370     if (level < 0)         \
1371      level = 0;            \
1372    }                       \
1373   }                        \
1374  } STMT_END
1375
1376 XS(XS_Scope__Upper_unwind); /* prototype to pass -Wmissing-prototypes */
1377
1378 XS(XS_Scope__Upper_unwind) {
1379 #ifdef dVAR
1380  dVAR; dXSARGS;
1381 #else
1382  dXSARGS;
1383 #endif
1384  dMY_CXT;
1385  I32 cxix;
1386
1387  PERL_UNUSED_VAR(cv); /* -W */
1388  PERL_UNUSED_VAR(ax); /* -Wall */
1389
1390  SU_GET_CONTEXT(0, items - 1);
1391  do {
1392   PERL_CONTEXT *cx = cxstack + cxix;
1393   switch (CxTYPE(cx)) {
1394    case CXt_SUB:
1395     if (PL_DBsub && cx->blk_sub.cv == GvCV(PL_DBsub))
1396      continue;
1397    case CXt_EVAL:
1398    case CXt_FORMAT:
1399     MY_CXT.cxix  = cxix;
1400     MY_CXT.items = items;
1401     /* pp_entersub will want to sanitize the stack after returning from there
1402      * Screw that, we're insane */
1403     if (GIMME_V == G_SCALAR) {
1404      MY_CXT.savesp = PL_stack_sp;
1405      /* dXSARGS calls POPMARK, so we need to match PL_markstack_ptr[1] */
1406      PL_stack_sp = PL_stack_base + PL_markstack_ptr[1] + 1;
1407     } else {
1408      MY_CXT.savesp = NULL;
1409     }
1410     SAVEDESTRUCTOR_X(su_unwind, NULL);
1411     return;
1412    default:
1413     break;
1414   }
1415  } while (--cxix >= 0);
1416  croak("Can't return outside a subroutine");
1417 }
1418
1419 MODULE = Scope::Upper            PACKAGE = Scope::Upper
1420
1421 PROTOTYPES: ENABLE
1422
1423 BOOT:
1424 {
1425  HV *stash;
1426
1427  stash = gv_stashpv(__PACKAGE__, 1);
1428  newCONSTSUB(stash, "TOP",           newSViv(0));
1429  newCONSTSUB(stash, "SU_THREADSAFE", newSVuv(SU_THREADSAFE));
1430
1431  newXSproto("Scope::Upper::unwind", XS_Scope__Upper_unwind, file, NULL);
1432
1433  su_setup();
1434 }
1435
1436 #if SU_THREADSAFE
1437
1438 void
1439 CLONE(...)
1440 PROTOTYPE: DISABLE
1441 PPCODE:
1442  {
1443   MY_CXT_CLONE;
1444   MY_CXT.uplevel_storage.root  = NULL;
1445   MY_CXT.uplevel_storage.count = 0;
1446  }
1447  XSRETURN(0);
1448
1449 #endif /* SU_THREADSAFE */
1450
1451 SV *
1452 HERE()
1453 PROTOTYPE:
1454 PREINIT:
1455  I32 cxix = cxstack_ix;
1456 CODE:
1457  if (PL_DBsub)
1458   SU_SKIP_DB(cxix);
1459  RETVAL = newSViv(cxix);
1460 OUTPUT:
1461  RETVAL
1462
1463 SV *
1464 UP(...)
1465 PROTOTYPE: ;$
1466 PREINIT:
1467  I32 cxix;
1468 CODE:
1469  SU_GET_CONTEXT(0, 0);
1470  if (--cxix < 0)
1471   cxix = 0;
1472  if (PL_DBsub)
1473   SU_SKIP_DB(cxix);
1474  RETVAL = newSViv(cxix);
1475 OUTPUT:
1476  RETVAL
1477
1478 void
1479 SUB(...)
1480 PROTOTYPE: ;$
1481 PREINIT:
1482  I32 cxix;
1483 PPCODE:
1484  SU_GET_CONTEXT(0, 0);
1485  for (; cxix >= 0; --cxix) {
1486   PERL_CONTEXT *cx = cxstack + cxix;
1487   switch (CxTYPE(cx)) {
1488    default:
1489     continue;
1490    case CXt_SUB:
1491     if (PL_DBsub && cx->blk_sub.cv == GvCV(PL_DBsub))
1492      continue;
1493     ST(0) = sv_2mortal(newSViv(cxix));
1494     XSRETURN(1);
1495   }
1496  }
1497  XSRETURN_UNDEF;
1498
1499 void
1500 EVAL(...)
1501 PROTOTYPE: ;$
1502 PREINIT:
1503  I32 cxix;
1504 PPCODE:
1505  SU_GET_CONTEXT(0, 0);
1506  for (; cxix >= 0; --cxix) {
1507   PERL_CONTEXT *cx = cxstack + cxix;
1508   switch (CxTYPE(cx)) {
1509    default:
1510     continue;
1511    case CXt_EVAL:
1512     ST(0) = sv_2mortal(newSViv(cxix));
1513     XSRETURN(1);
1514   }
1515  }
1516  XSRETURN_UNDEF;
1517
1518 void
1519 SCOPE(...)
1520 PROTOTYPE: ;$
1521 PREINIT:
1522  I32 cxix, level;
1523 PPCODE:
1524  SU_GET_LEVEL(0, 0);
1525  cxix = cxstack_ix;
1526  if (PL_DBsub) {
1527   SU_SKIP_DB(cxix);
1528   while (cxix > 0) {
1529    if (--level < 0)
1530     break;
1531    --cxix;
1532    SU_SKIP_DB(cxix);
1533   }
1534  } else {
1535   cxix -= level;
1536   if (cxix < 0)
1537    cxix = 0;
1538  }
1539  ST(0) = sv_2mortal(newSViv(cxix));
1540  XSRETURN(1);
1541
1542 void
1543 CALLER(...)
1544 PROTOTYPE: ;$
1545 PREINIT:
1546  I32 cxix, level;
1547 PPCODE:
1548  SU_GET_LEVEL(0, 0);
1549  for (cxix = cxstack_ix; cxix > 0; --cxix) {
1550   PERL_CONTEXT *cx = cxstack + cxix;
1551   switch (CxTYPE(cx)) {
1552    case CXt_SUB:
1553     if (PL_DBsub && cx->blk_sub.cv == GvCV(PL_DBsub))
1554      continue;
1555    case CXt_EVAL:
1556    case CXt_FORMAT:
1557     if (--level < 0)
1558      goto done;
1559     break;
1560   }
1561  }
1562 done:
1563  ST(0) = sv_2mortal(newSViv(cxix));
1564  XSRETURN(1);
1565
1566 void
1567 want_at(...)
1568 PROTOTYPE: ;$
1569 PREINIT:
1570  I32 cxix;
1571 PPCODE:
1572  SU_GET_CONTEXT(0, 0);
1573  while (cxix > 0) {
1574   PERL_CONTEXT *cx = cxstack + cxix--;
1575   switch (CxTYPE(cx)) {
1576    case CXt_SUB:
1577    case CXt_EVAL:
1578    case CXt_FORMAT: {
1579     I32 gimme = cx->blk_gimme;
1580     switch (gimme) {
1581      case G_VOID:   XSRETURN_UNDEF; break;
1582      case G_SCALAR: XSRETURN_NO;    break;
1583      case G_ARRAY:  XSRETURN_YES;   break;
1584     }
1585     break;
1586    }
1587   }
1588  }
1589  XSRETURN_UNDEF;
1590
1591 void
1592 reap(SV *hook, ...)
1593 PROTOTYPE: &;$
1594 PREINIT:
1595  I32 cxix;
1596  su_ud_reap *ud;
1597 CODE:
1598  SU_GET_CONTEXT(1, 1);
1599  Newx(ud, 1, su_ud_reap);
1600  SU_UD_ORIGIN(ud)  = NULL;
1601  SU_UD_HANDLER(ud) = su_reap;
1602  ud->cb = newSVsv(hook);
1603  su_init(ud, cxix, SU_SAVE_DESTRUCTOR_SIZE);
1604
1605 void
1606 localize(SV *sv, SV *val, ...)
1607 PROTOTYPE: $$;$
1608 PREINIT:
1609  I32 cxix;
1610  I32 size;
1611  su_ud_localize *ud;
1612 CODE:
1613  SU_GET_CONTEXT(2, 2);
1614  Newx(ud, 1, su_ud_localize);
1615  SU_UD_ORIGIN(ud)  = NULL;
1616  SU_UD_HANDLER(ud) = su_localize;
1617  size = su_ud_localize_init(ud, sv, val, NULL);
1618  su_init(ud, cxix, size);
1619
1620 void
1621 localize_elem(SV *sv, SV *elem, SV *val, ...)
1622 PROTOTYPE: $$$;$
1623 PREINIT:
1624  I32 cxix;
1625  I32 size;
1626  su_ud_localize *ud;
1627 CODE:
1628  if (SvTYPE(sv) >= SVt_PVGV)
1629   croak("Can't infer the element localization type from a glob and the value");
1630  SU_GET_CONTEXT(3, 3);
1631  Newx(ud, 1, su_ud_localize);
1632  SU_UD_ORIGIN(ud)  = NULL;
1633  SU_UD_HANDLER(ud) = su_localize;
1634  size = su_ud_localize_init(ud, sv, val, elem);
1635  if (ud->type != SVt_PVAV && ud->type != SVt_PVHV) {
1636   SU_UD_LOCALIZE_FREE(ud);
1637   croak("Can't localize an element of something that isn't an array or a hash");
1638  }
1639  su_init(ud, cxix, size);
1640
1641 void
1642 localize_delete(SV *sv, SV *elem, ...)
1643 PROTOTYPE: $$;$
1644 PREINIT:
1645  I32 cxix;
1646  I32 size;
1647  su_ud_localize *ud;
1648 CODE:
1649  SU_GET_CONTEXT(2, 2);
1650  Newx(ud, 1, su_ud_localize);
1651  SU_UD_ORIGIN(ud)  = NULL;
1652  SU_UD_HANDLER(ud) = su_localize;
1653  size = su_ud_localize_init(ud, sv, NULL, elem);
1654  su_init(ud, cxix, size);
1655
1656 void
1657 uplevel(SV *code, ...)
1658 PROTOTYPE: &@
1659 PREINIT:
1660  I32 cxix, ret, args = 0;
1661 PPCODE:
1662  if (SvROK(code))
1663   code = SvRV(code);
1664  if (SvTYPE(code) < SVt_PVCV)
1665   croak("First argument to uplevel must be a code reference");
1666  SU_GET_CONTEXT(1, items - 1);
1667  do {
1668   PERL_CONTEXT *cx = cxstack + cxix;
1669   switch (CxTYPE(cx)) {
1670    case CXt_EVAL:
1671     croak("Can't uplevel to an eval frame");
1672    case CXt_FORMAT:
1673     croak("Can't uplevel to a format frame");
1674    case CXt_SUB:
1675     if (PL_DBsub && cx->blk_sub.cv == GvCV(PL_DBsub))
1676      continue;
1677     if (items > 1) {
1678      PL_stack_sp--;
1679      args = items - 2;
1680     }
1681     ret = su_uplevel((CV *) code, cxix, args);
1682     XSRETURN(ret);
1683    default:
1684     break;
1685   }
1686  } while (--cxix >= 0);
1687  croak("Can't uplevel outside a subroutine");