#define PL_scopestack (vTHX->Iscopestack)
#define PL_scopestack_ix (vTHX->Iscopestack_ix)
#define PL_scopestack_max (vTHX->Iscopestack_max)
+#define PL_scopestack_name (vTHX->Iscopestack_name)
#define PL_screamfirst (vTHX->Iscreamfirst)
#define PL_screamnext (vTHX->Iscreamnext)
#define PL_secondgv (vTHX->Isecondgv)
#define PL_Iscopestack PL_scopestack
#define PL_Iscopestack_ix PL_scopestack_ix
#define PL_Iscopestack_max PL_scopestack_max
+#define PL_Iscopestack_name PL_scopestack_name
#define PL_Iscreamfirst PL_screamfirst
#define PL_Iscreamnext PL_screamnext
#define PL_Isecondgv PL_secondgv
PERLVAR(Istack_max, SV **)
PERLVAR(Iscopestack, I32 *) /* scopes we've ENTERed */
+#ifdef DEBUGGING
+PERLVAR(Iscopestack_name, const char * *) /* name of the scopes we've ENTERed */
+#endif
PERLVAR(Iscopestack_ix, I32)
PERLVAR(Iscopestack_max,I32)
SET_MARK_OFFSET;
Newx(PL_scopestack,REASONABLE(32),I32);
+#ifdef DEBUGGING
+ Newx(PL_scopestack_name,REASONABLE(32),const char*);
+#endif
PL_scopestack_ix = 0;
PL_scopestack_max = REASONABLE(32);
#define PL_scopestack_ix (*Perl_Iscopestack_ix_ptr(aTHX))
#undef PL_scopestack_max
#define PL_scopestack_max (*Perl_Iscopestack_max_ptr(aTHX))
+#undef PL_scopestack_name
+#define PL_scopestack_name (*Perl_Iscopestack_name_ptr(aTHX))
#undef PL_screamfirst
#define PL_screamfirst (*Perl_Iscreamfirst_ptr(aTHX))
#undef PL_screamnext
*MARK-- = SvTIED_obj(MUTABLE_SV(ary), mg);
PUSHMARK(MARK);
PUTBACK;
- ENTER;
+ ENTER_with_name("call_SPLICE");
call_method("SPLICE",GIMME_V);
- LEAVE;
+ LEAVE_with_name("call_SPLICE");
SPAGAIN;
RETURN;
}
*MARK-- = SvTIED_obj(MUTABLE_SV(ary), mg);
PUSHMARK(MARK);
PUTBACK;
- ENTER;
+ ENTER_with_name("call_PUSH");
call_method("PUSH",G_SCALAR|G_DISCARD);
- LEAVE;
+ LEAVE_with_name("call_PUSH");
SPAGAIN;
}
else {
*MARK-- = SvTIED_obj(MUTABLE_SV(ary), mg);
PUSHMARK(MARK);
PUTBACK;
- ENTER;
+ ENTER_with_name("call_UNSHIFT");
call_method("UNSHIFT",G_SCALAR|G_DISCARD);
- LEAVE;
+ LEAVE_with_name("call_UNSHIFT");
SPAGAIN;
}
else {
}
else {
PUTBACK;
- ENTER;
+ ENTER_with_name("call_PUSH");
call_method("PUSH",G_SCALAR|G_DISCARD);
- LEAVE;
+ LEAVE_with_name("call_PUSH");
SPAGAIN;
if (gimme == G_ARRAY) {
I32 i;
PL_stack_sp = PL_stack_base + *PL_markstack_ptr + 1;
pp_pushmark(); /* push dst */
pp_pushmark(); /* push src */
- ENTER; /* enter outer scope */
+ ENTER_with_name("grep"); /* enter outer scope */
SAVETMPS;
if (PL_op->op_private & OPpGREP_LEX)
SAVESPTR(PAD_SVl(PL_op->op_targ));
else
SAVE_DEFSV;
- ENTER; /* enter inner scope */
+ ENTER_with_name("grep_item"); /* enter inner scope */
SAVEVPTR(PL_curpm);
src = PL_stack_base[*PL_markstack_ptr];
}
}
}
- LEAVE; /* exit inner scope */
+ LEAVE_with_name("grep_item"); /* exit inner scope */
/* All done yet? */
if (PL_markstack_ptr[-1] > *PL_markstack_ptr) {
(void)POPMARK; /* pop top */
- LEAVE; /* exit outer scope */
+ LEAVE_with_name("grep"); /* exit outer scope */
(void)POPMARK; /* pop src */
items = --*PL_markstack_ptr - PL_markstack_ptr[-1];
(void)POPMARK; /* pop dst */
else {
SV *src;
- ENTER; /* enter inner scope */
+ ENTER_with_name("grep_item"); /* enter inner scope */
SAVEVPTR(PL_curpm);
/* set $_ to the new source item */
/* don't do recursive DB::DB call */
return NORMAL;
- ENTER;
+ ENTER_with_name("sub");
SAVETMPS;
SAVEI32(PL_debug);
(void)(*CvXSUB(cv))(aTHX_ cv);
CvDEPTH(cv)--;
FREETMPS;
- LEAVE;
+ LEAVE_with_name("sub");
return NORMAL;
}
else {
PAD *iterdata;
#endif
- ENTER;
+ ENTER_with_name("loop1");
SAVETMPS;
if (PL_op->op_targ) {
if (PL_op->op_private & OPpITER_DEF)
cxtype |= CXp_FOR_DEF;
- ENTER;
+ ENTER_with_name("loop2");
PUSHBLOCK(cx, cxtype, SP);
#ifdef USE_ITHREADS
register PERL_CONTEXT *cx;
const I32 gimme = GIMME_V;
- ENTER;
+ ENTER_with_name("loop1");
SAVETMPS;
- ENTER;
+ ENTER_with_name("loop2");
PUSHBLOCK(cx, CXt_LOOP_PLAIN, SP);
PUSHLOOP_PLAIN(cx, SP);
POPLOOP(cx); /* Stack values are safe: release loop vars ... */
PL_curpm = newpm; /* ... and pop $1 et al */
- LEAVE;
- LEAVE;
+ LEAVE_with_name("loop2");
+ LEAVE_with_name("loop1");
return NORMAL;
}
PUSHMARK(mark);
PUTBACK;
(void)(*CvXSUB(cv))(aTHX_ cv);
- LEAVE;
+ LEAVE_with_name("sub");
return retop;
}
else {
PERL_ARGS_ASSERT_SV_COMPILE_2OP;
- ENTER;
+ ENTER_with_name("eval");
lex_start(sv, NULL, FALSE);
SAVETMPS;
/* switch to eval mode */
lex_end();
/* XXX DAPM do this properly one year */
*padp = MUTABLE_AV(SvREFCNT_inc_simple(PL_comppad));
- LEAVE;
+ LEAVE_with_name("eval");
if (IN_PERL_COMPILETIME)
CopHINTS_set(&PL_compiling, PL_hints);
#ifdef OP_IN_REGISTER
POPEVAL(cx);
}
lex_end();
- LEAVE; /* pp_entereval knows about this LEAVE. */
+ LEAVE_with_name("eval"); /* pp_entereval knows about this LEAVE. */
msg = SvPVx_nolen_const(ERRSV);
if (optype == OP_REQUIRE) {
vcmp(sv, sv_2mortal(upg_version(newSVnv(5.009005), FALSE))) >= 0) {
SV *const importsv = vnormal(sv);
*SvPVX_mutable(importsv) = ':';
- ENTER;
+ ENTER_with_name("load_feature");
Perl_load_module(aTHX_ 0, newSVpvs("feature"), NULL, importsv, NULL);
- LEAVE;
+ LEAVE_with_name("load_feature");
}
/* If a version >= 5.11.0 is requested, strictures are on by default! */
if (PL_compcv &&
tryname = SvPVX_const(namesv);
tryrsfp = NULL;
- ENTER;
+ ENTER_with_name("call_INC");
SAVETMPS;
EXTEND(SP, 2);
PUTBACK;
FREETMPS;
- LEAVE;
+ LEAVE_with_name("call_INC");
if (tryrsfp) {
hook_sv = dirsv;
unixname, unixlen, SvREFCNT_inc_simple(hook_sv), 0 );
}
- ENTER;
+ ENTER_with_name("eval");
SAVETMPS;
lex_start(NULL, tryrsfp, TRUE);
TAINT_IF(SvTAINTED(sv));
TAINT_PROPER("eval");
- ENTER;
+ ENTER_with_name("eval");
lex_start(sv, NULL, FALSE);
SAVETMPS;
/* die_where() did LEAVE, or we won't be here */
}
else {
- LEAVE;
+ LEAVE_with_name("eval");
if (!(save_flags & OPf_SPECIAL)) {
CLEAR_ERRSV();
}
POPBLOCK(cx,newpm);
POPEVAL(cx);
PL_curpm = newpm;
- LEAVE;
+ LEAVE_with_name("eval_scope");
PERL_UNUSED_VAR(newsp);
PERL_UNUSED_VAR(gimme);
PERL_UNUSED_VAR(optype);
PERL_CONTEXT *cx;
const I32 gimme = GIMME_V;
- ENTER;
+ ENTER_with_name("eval_scope");
SAVETMPS;
PUSHBLOCK(cx, (CXt_EVAL|CXp_TRYBLOCK), PL_stack_sp);
}
PL_curpm = newpm; /* Don't pop $1 et al till now */
- LEAVE;
+ LEAVE_with_name("eval_scope");
CLEAR_ERRSV();
RETURN;
}
register PERL_CONTEXT *cx;
const I32 gimme = GIMME_V;
- ENTER;
+ ENTER_with_name("given");
SAVETMPS;
sv_setsv(PAD_SV(PL_op->op_targ), POPs);
PL_curpm = newpm; /* pop $1 et al */
- LEAVE;
+ LEAVE_with_name("given");
return NORMAL;
}
PM_SETRE(matcher, ReREFCNT_inc(re));
SAVEFREEOP((OP *) matcher);
- ENTER; SAVETMPS;
+ ENTER_with_name("matcher"); SAVETMPS;
SAVEOP();
return matcher;
}
PERL_UNUSED_ARG(matcher);
FREETMPS;
- LEAVE;
+ LEAVE_with_name("matcher");
}
/* Do a smart match */
RETPUSHYES;
while ( (he = hv_iternext(hv)) ) {
DEBUG_M(Perl_deb(aTHX_ " testing hash key...\n"));
- ENTER;
+ ENTER_with_name("smartmatch_hash_key_test");
SAVETMPS;
PUSHMARK(SP);
PUSHs(hv_iterkeysv(he));
else
andedresults = SvTRUEx(POPs) && andedresults;
FREETMPS;
- LEAVE;
+ LEAVE_with_name("smartmatch_hash_key_test");
}
if (andedresults)
RETPUSHYES;
for (i = 0; i <= len; ++i) {
SV * const * const svp = av_fetch(av, i, FALSE);
DEBUG_M(Perl_deb(aTHX_ " testing array element...\n"));
- ENTER;
+ ENTER_with_name("smartmatch_array_elem_test");
SAVETMPS;
PUSHMARK(SP);
if (svp)
else
andedresults = SvTRUEx(POPs) && andedresults;
FREETMPS;
- LEAVE;
+ LEAVE_with_name("smartmatch_array_elem_test");
}
if (andedresults)
RETPUSHYES;
else {
sm_any_sub:
DEBUG_M(Perl_deb(aTHX_ " applying rule Any-CodeRef\n"));
- ENTER;
+ ENTER_with_name("smartmatch_coderef");
SAVETMPS;
PUSHMARK(SP);
PUSHs(d);
else if (SvTEMP(TOPs))
SvREFCNT_inc_void(TOPs);
FREETMPS;
- LEAVE;
+ LEAVE_with_name("smartmatch_coderef");
RETURN;
}
}
if ((0 == (PL_op->op_flags & OPf_SPECIAL)) && !SvTRUEx(POPs))
return cLOGOP->op_other->op_next;
- ENTER;
+ ENTER_with_name("eval");
SAVETMPS;
PUSHBLOCK(cx, CXt_WHEN, SP);
PL_curpm = newpm; /* pop $1 et al */
- LEAVE;
+ LEAVE_with_name("eval");
return NORMAL;
}
dSP;
int count;
- ENTER;
+ ENTER_with_name("call_filter_sub");
SAVE_DEFSV;
SAVETMPS;
EXTEND(SP, 2);
PUTBACK;
FREETMPS;
- LEAVE;
+ LEAVE_with_name("call_filter_sub");
}
if(SvOK(upstream)) {
/* We've been returned a constant rather than a full subroutine,
but they expect a subroutine reference to apply. */
if (SvROK(cv)) {
- ENTER;
+ ENTER_with_name("sassign_coderef");
SvREFCNT_inc_void(SvRV(cv));
/* newCONSTSUB takes a reference count on the passed in SV
from us. We set the name to NULL, otherwise we get into
SvRV_set(left, MUTABLE_SV(newCONSTSUB(GvSTASH(right), NULL,
SvRV(cv))));
SvREFCNT_dec(cv);
- LEAVE;
+ LEAVE_with_name("sassign_coderef");
} else {
/* What can happen for the corner case *{"BONK"} = \&{"BONK"};
is that
PUSHMARK(MARK - 1);
*MARK = SvTIED_obj(MUTABLE_SV(io), mg);
PUTBACK;
- ENTER;
+ ENTER_with_name("call_PRINT");
if( PL_op->op_type == OP_SAY ) {
/* local $\ = "\n" */
SAVEGENERICSV(PL_ors_sv);
PL_ors_sv = newSVpvs("\n");
}
call_method("PRINT", G_SCALAR);
- LEAVE;
+ LEAVE_with_name("call_PRINT");
SPAGAIN;
MARK = ORIGMARK + 1;
*MARK = *SP;
PUSHMARK(SP);
XPUSHs(SvTIED_obj(MUTABLE_SV(io), mg));
PUTBACK;
- ENTER;
+ ENTER_with_name("call_READLINE");
call_method("READLINE", gimme);
- LEAVE;
+ LEAVE_with_name("call_READLINE");
SPAGAIN;
if (gimme == G_SCALAR) {
SV* const result = POPs;
gimme = G_SCALAR;
}
- ENTER;
+ ENTER_with_name("block");
SAVETMPS;
PUSHBLOCK(cx, CXt_BLOCK, SP);
}
PL_curpm = newpm; /* Don't pop $1 et al till now */
- LEAVE;
+ LEAVE_with_name("block");
RETURN;
}
if (SvTRUEx(POPs))
PL_stack_base[PL_markstack_ptr[-1]++] = PL_stack_base[*PL_markstack_ptr];
++*PL_markstack_ptr;
- LEAVE; /* exit inner scope */
+ LEAVE_with_name("grep_item"); /* exit inner scope */
/* All done yet? */
if (PL_stack_base + *PL_markstack_ptr > SP) {
I32 items;
const I32 gimme = GIMME_V;
- LEAVE; /* exit outer scope */
+ LEAVE_with_name("grep"); /* exit outer scope */
(void)POPMARK; /* pop src */
items = --*PL_markstack_ptr - PL_markstack_ptr[-1];
(void)POPMARK; /* pop dst */
else {
SV *src;
- ENTER; /* enter inner scope */
+ ENTER_with_name("grep_item"); /* enter inner scope */
SAVEVPTR(PL_curpm);
src = PL_stack_base[*PL_markstack_ptr];
}
PUTBACK;
- LEAVE;
+ LEAVE_with_name("sub");
cxstack_ix--;
POPSUB(cx,sv); /* Stack values are safe: release CV and @_ ... */
PL_curpm = newpm; /* ... and pop $1 et al */
* the refcounts so the caller gets a live guy. Cannot set
* TEMP, so sv_2mortal is out of question. */
if (!CvLVALUE(cx->blk_sub.cv)) {
- LEAVE;
+ LEAVE_with_name("sub");
cxstack_ix--;
POPSUB(cx,sv);
PL_curpm = newpm;
* of a tied hash or array */
if (SvFLAGS(TOPs) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY) &&
!(SvRMAGICAL(TOPs) && mg_find(TOPs, PERL_MAGIC_tiedelem))) {
- LEAVE;
+ LEAVE_with_name("sub");
cxstack_ix--;
POPSUB(cx,sv);
PL_curpm = newpm;
}
}
else { /* Should not happen? */
- LEAVE;
+ LEAVE_with_name("sub");
cxstack_ix--;
POPSUB(cx,sv);
PL_curpm = newpm;
&& SvFLAGS(*mark) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY)) {
/* Might be flattened array after $#array = */
PUTBACK;
- LEAVE;
+ LEAVE_with_name("sub");
cxstack_ix--;
POPSUB(cx,sv);
PL_curpm = newpm;
}
PUTBACK;
- LEAVE;
+ LEAVE_with_name("sub");
cxstack_ix--;
POPSUB(cx,sv); /* Stack values are safe: release CV and @_ ... */
PL_curpm = newpm; /* ... and pop $1 et al */
cv = sv_2cv(sv, &stash, &gv, 0);
}
if (!cv) {
- ENTER;
+ ENTER_with_name("sub");
SAVETMPS;
goto try_autoload;
}
break;
}
- ENTER;
+ ENTER_with_name("sub");
SAVETMPS;
retry:
*(PL_stack_base + markix) = *PL_stack_sp;
PL_stack_sp = PL_stack_base + markix;
}
- LEAVE;
+ LEAVE_with_name("sub");
return NORMAL;
}
}
NOOP;
}
else if (gimme == G_SCALAR) {
- ENTER;
+ ENTER_with_name("backtick");
SAVESPTR(PL_rs);
PL_rs = &PL_sv_undef;
sv_setpvs(TARG, ""); /* note that this preserves previous buffer */
while (sv_gets(TARG, fp, SvCUR(TARG)) != NULL)
NOOP;
- LEAVE;
+ LEAVE_with_name("backtick");
XPUSHs(TARG);
SvTAINTED_on(TARG);
}
* without at the same time croaking, for some reason, or if
* perl was built with PERL_EXTERNAL_GLOB */
- ENTER;
+ ENTER_with_name("glob");
#ifndef VMS
if (PL_tainting) {
#endif /* !DOSISH */
result = do_readline();
- LEAVE;
+ LEAVE_with_name("glob");
return result;
}
*MARK-- = SvTIED_obj(MUTABLE_SV(io), mg);
PUSHMARK(MARK);
PUTBACK;
- ENTER;
+ ENTER_with_name("call_OPEN");
call_method("OPEN", G_SCALAR);
- LEAVE;
+ LEAVE_with_name("call_OPEN");
SPAGAIN;
RETURN;
}
PUSHMARK(SP);
XPUSHs(SvTIED_obj(MUTABLE_SV(io), mg));
PUTBACK;
- ENTER;
+ ENTER_with_name("call_CLOSE");
call_method("CLOSE", G_SCALAR);
- LEAVE;
+ LEAVE_with_name("call_CLOSE");
SPAGAIN;
RETURN;
}
PUSHMARK(SP);
XPUSHs(SvTIED_obj(MUTABLE_SV(io), mg));
PUTBACK;
- ENTER;
+ ENTER_with_name("call_FILENO");
call_method("FILENO", G_SCALAR);
- LEAVE;
+ LEAVE_with_name("call_FILENO");
SPAGAIN;
RETURN;
}
if (discp)
XPUSHs(discp);
PUTBACK;
- ENTER;
+ ENTER_with_name("call_BINMODE");
call_method("BINMODE", G_SCALAR);
- LEAVE;
+ LEAVE_with_name("call_BINMODE");
SPAGAIN;
RETURN;
}
}
items = SP - MARK++;
if (sv_isobject(*MARK)) { /* Calls GET magic. */
- ENTER;
+ ENTER_with_name("call_TIE");
PUSHSTACKi(PERLSI_MAGIC);
PUSHMARK(SP);
EXTEND(SP,(I32)items);
DIE(aTHX_ "Can't locate object method \"%s\" via package \"%"SVf"\"",
methname, SVfARG(SvOK(*MARK) ? *MARK : &PL_sv_no));
}
- ENTER;
+ ENTER_with_name("call_TIE");
PUSHSTACKi(PERLSI_MAGIC);
PUSHMARK(SP);
EXTEND(SP,(I32)items);
"Self-ties of arrays and hashes are not supported");
sv_magic(varsv, (SvRV(sv) == varsv ? NULL : sv), how, NULL, 0);
}
- LEAVE;
+ LEAVE_with_name("call_TIE");
SP = PL_stack_base + markoff;
PUSHs(sv);
RETURN;
XPUSHs(SvTIED_obj(MUTABLE_SV(gv), mg));
mXPUSHi(SvREFCNT(obj) - 1);
PUTBACK;
- ENTER;
+ ENTER_with_name("call_UNTIE");
call_sv(MUTABLE_SV(cv), G_VOID);
- LEAVE;
+ LEAVE_with_name("call_UNTIE");
SPAGAIN;
}
else if (mg && SvREFCNT(obj) > 1) {
if (PL_scopestack_ix == PL_scopestack_max) {
PL_scopestack_max = GROW(PL_scopestack_max);
Renew(PL_scopestack, PL_scopestack_max, I32);
+#ifdef DEBUGGING
+ Renew(PL_scopestack_name, PL_scopestack_max, const char*);
+#endif DEBUGGING
}
+#ifdef DEBUGGING
+ PL_scopestack_name[PL_scopestack_ix] = "unknown";
+#endif
PL_scopestack[PL_scopestack_ix++] = PL_savestack_ix;
}
=for apidoc Ams||LEAVE
Closing bracket on a callback. See C<ENTER> and L<perlcall>.
+=over
+
+=item ENTER_with_name(name)
+
+Same as C<ENTER>, but when debugging is enabled it also associates the
+given literal string with the new scope.
+
+=item LEAVE_with_name(name)
+
+Same as C<LEAVE>, but when debugging is enabled it first checks that the
+scope has the given name. Name must be a literal string.
+
+=back
+
=cut
*/
DEBUG_SCOPE("LEAVE") \
pop_scope(); \
} STMT_END
+#define ENTER_with_name(name) \
+ STMT_START { \
+ push_scope(); \
+ PL_scopestack_name[PL_scopestack_ix-1] = name; \
+ DEBUG_SCOPE("ENTER \"" name "\"") \
+ } STMT_END
+#define LEAVE_with_name(name) \
+ STMT_START { \
+ DEBUG_SCOPE("LEAVE \"" name "\"") \
+ assert(strEQ(PL_scopestack_name[PL_scopestack_ix-1], name)); \
+ pop_scope(); \
+ } STMT_END
#else
#define ENTER push_scope()
#define LEAVE pop_scope()
+#define ENTER_with_name(name) ENTER
+#define LEAVE_with_name(name) LEAVE
#endif
#define LEAVE_SCOPE(old) if (PL_savestack_ix > old) leave_scope(old)