summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embed.fnc2
-rw-r--r--embed.h1
-rw-r--r--pad.c185
-rw-r--r--proto.h5
4 files changed, 84 insertions, 109 deletions
diff --git a/embed.fnc b/embed.fnc
index ad7e7a4de0..a51f148656 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -2056,8 +2056,6 @@ s |void |deb_stack_n |NN SV** stack_base|I32 stack_min \
: Used in perl.c, pp_ctl.c, toke.c
pda |PADLIST*|pad_new |int flags
: Only used in op.c
-pd |void |pad_undef |NN CV* cv
-: Only used in op.c
Mpd |PADOFFSET|pad_add_name |NN const char *name|const STRLEN len\
|const U32 flags|NULLOK HV *typestash\
|NULLOK HV *ourstash
diff --git a/embed.h b/embed.h
index 0d5553ce89..279683b192 100644
--- a/embed.h
+++ b/embed.h
@@ -1083,7 +1083,6 @@
#define pad_push(a,b) Perl_pad_push(aTHX_ a,b)
#define pad_swipe(a,b) Perl_pad_swipe(aTHX_ a,b)
#define pad_tidy(a) Perl_pad_tidy(aTHX_ a)
-#define pad_undef(a) Perl_pad_undef(aTHX_ a)
#define parse_unicode_opts(a) Perl_parse_unicode_opts(aTHX_ a)
#define parser_free(a) Perl_parser_free(aTHX_ a)
#define peep(a) Perl_peep(aTHX_ a)
diff --git a/pad.c b/pad.c
index 323efc6a70..2c1c81dd56 100644
--- a/pad.c
+++ b/pad.c
@@ -246,106 +246,6 @@ Perl_pad_new(pTHX_ int flags)
return (PADLIST*)padlist;
}
-/*
-=for apidoc pad_undef
-
-Free the padlist associated with a CV.
-If parts of it happen to be current, we null the relevant
-PL_*pad* global vars so that we don't have any dangling references left.
-We also repoint the CvOUTSIDE of any about-to-be-orphaned
-inner subs to the outer of this cv.
-
-(This function should really be called pad_free, but the name was already
-taken)
-
-=cut
-*/
-
-void
-Perl_pad_undef(pTHX_ CV* cv)
-{
- dVAR;
- I32 ix;
- const PADLIST * const padlist = CvPADLIST(cv);
-
- PERL_ARGS_ASSERT_PAD_UNDEF;
-
- pad_peg("pad_undef");
- if (!padlist)
- return;
- if (SvIS_FREED(padlist)) /* may be during global destruction */
- return;
-
- DEBUG_X(PerlIO_printf(Perl_debug_log,
- "Pad undef: cv=0x%"UVxf" padlist=0x%"UVxf" comppad=0x%"UVxf"\n",
- PTR2UV(cv), PTR2UV(padlist), PTR2UV(PL_comppad))
- );
-
- /* detach any '&' anon children in the pad; if afterwards they
- * are still live, fix up their CvOUTSIDEs to point to our outside,
- * bypassing us. */
- /* XXX DAPM for efficiency, we should only do this if we know we have
- * children, or integrate this loop with general cleanup */
-
- if (PL_phase != PERL_PHASE_DESTRUCT) { /* don't bother during global destruction */
- CV * const outercv = CvOUTSIDE(cv);
- const U32 seq = CvOUTSIDE_SEQ(cv);
- AV * const comppad_name = MUTABLE_AV(AvARRAY(padlist)[0]);
- SV ** const namepad = AvARRAY(comppad_name);
- AV * const comppad = MUTABLE_AV(AvARRAY(padlist)[1]);
- SV ** const curpad = AvARRAY(comppad);
- for (ix = AvFILLp(comppad_name); ix > 0; ix--) {
- SV * const namesv = namepad[ix];
- if (namesv && namesv != &PL_sv_undef
- && *SvPVX_const(namesv) == '&')
- {
- CV * const innercv = MUTABLE_CV(curpad[ix]);
- U32 inner_rc = SvREFCNT(innercv);
- assert(inner_rc);
- namepad[ix] = NULL;
- SvREFCNT_dec(namesv);
-
- if (SvREFCNT(comppad) < 2) { /* allow for /(?{ sub{} })/ */
- curpad[ix] = NULL;
- SvREFCNT_dec(innercv);
- inner_rc--;
- }
-
- /* in use, not just a prototype */
- if (inner_rc && (CvOUTSIDE(innercv) == cv)) {
- assert(CvWEAKOUTSIDE(innercv));
- /* don't relink to grandfather if he's being freed */
- if (outercv && SvREFCNT(outercv)) {
- CvWEAKOUTSIDE_off(innercv);
- CvOUTSIDE(innercv) = outercv;
- CvOUTSIDE_SEQ(innercv) = seq;
- SvREFCNT_inc_simple_void_NN(outercv);
- }
- else {
- CvOUTSIDE(innercv) = NULL;
- }
- }
- }
- }
- }
-
- ix = AvFILLp(padlist);
- while (ix >= 0) {
- SV* const sv = AvARRAY(padlist)[ix--];
- if (sv) {
- if (sv == (const SV *)PL_comppad_name)
- PL_comppad_name = NULL;
- else if (sv == (const SV *)PL_comppad) {
- PL_comppad = NULL;
- PL_curpad = NULL;
- }
- }
- SvREFCNT_dec(sv);
- }
- SvREFCNT_dec(MUTABLE_SV(CvPADLIST(cv)));
- CvPADLIST(cv) = NULL;
-}
-
/*
=head1 Embedding Functions
@@ -364,6 +264,7 @@ void
Perl_cv_undef(pTHX_ CV *cv)
{
dVAR;
+ const PADLIST *padlist = CvPADLIST(cv);
PERL_ARGS_ASSERT_CV_UNDEF;
@@ -395,7 +296,89 @@ Perl_cv_undef(pTHX_ CV *cv)
SvPOK_off(MUTABLE_SV(cv)); /* forget prototype */
CvGV_set(cv, NULL);
- pad_undef(cv);
+ /* This statement and the subsequence if block was pad_undef(). */
+ pad_peg("pad_undef");
+
+ if (padlist && !SvIS_FREED(padlist) /* may be during global destruction */
+ ) {
+ I32 ix;
+
+ /* Free the padlist associated with a CV.
+ If parts of it happen to be current, we null the relevant PL_*pad*
+ global vars so that we don't have any dangling references left.
+ We also repoint the CvOUTSIDE of any about-to-be-orphaned inner
+ subs to the outer of this cv. */
+
+ DEBUG_X(PerlIO_printf(Perl_debug_log,
+ "Pad undef: cv=0x%"UVxf" padlist=0x%"UVxf" comppad=0x%"UVxf"\n",
+ PTR2UV(cv), PTR2UV(padlist), PTR2UV(PL_comppad))
+ );
+
+ /* detach any '&' anon children in the pad; if afterwards they
+ * are still live, fix up their CvOUTSIDEs to point to our outside,
+ * bypassing us. */
+ /* XXX DAPM for efficiency, we should only do this if we know we have
+ * children, or integrate this loop with general cleanup */
+
+ if (PL_phase != PERL_PHASE_DESTRUCT) { /* don't bother during global destruction */
+ CV * const outercv = CvOUTSIDE(cv);
+ const U32 seq = CvOUTSIDE_SEQ(cv);
+ AV * const comppad_name = MUTABLE_AV(AvARRAY(padlist)[0]);
+ SV ** const namepad = AvARRAY(comppad_name);
+ AV * const comppad = MUTABLE_AV(AvARRAY(padlist)[1]);
+ SV ** const curpad = AvARRAY(comppad);
+ for (ix = AvFILLp(comppad_name); ix > 0; ix--) {
+ SV * const namesv = namepad[ix];
+ if (namesv && namesv != &PL_sv_undef
+ && *SvPVX_const(namesv) == '&')
+ {
+ CV * const innercv = MUTABLE_CV(curpad[ix]);
+ U32 inner_rc = SvREFCNT(innercv);
+ assert(inner_rc);
+ namepad[ix] = NULL;
+ SvREFCNT_dec(namesv);
+
+ if (SvREFCNT(comppad) < 2) { /* allow for /(?{ sub{} })/ */
+ curpad[ix] = NULL;
+ SvREFCNT_dec(innercv);
+ inner_rc--;
+ }
+
+ /* in use, not just a prototype */
+ if (inner_rc && (CvOUTSIDE(innercv) == cv)) {
+ assert(CvWEAKOUTSIDE(innercv));
+ /* don't relink to grandfather if he's being freed */
+ if (outercv && SvREFCNT(outercv)) {
+ CvWEAKOUTSIDE_off(innercv);
+ CvOUTSIDE(innercv) = outercv;
+ CvOUTSIDE_SEQ(innercv) = seq;
+ SvREFCNT_inc_simple_void_NN(outercv);
+ }
+ else {
+ CvOUTSIDE(innercv) = NULL;
+ }
+ }
+ }
+ }
+ }
+
+ ix = AvFILLp(padlist);
+ while (ix >= 0) {
+ SV* const sv = AvARRAY(padlist)[ix--];
+ if (sv) {
+ if (sv == (const SV *)PL_comppad_name)
+ PL_comppad_name = NULL;
+ else if (sv == (const SV *)PL_comppad) {
+ PL_comppad = NULL;
+ PL_curpad = NULL;
+ }
+ }
+ SvREFCNT_dec(sv);
+ }
+ SvREFCNT_dec(MUTABLE_SV(CvPADLIST(cv)));
+ CvPADLIST(cv) = NULL;
+ }
+
/* remove CvOUTSIDE unless this is an undef rather than a free */
if (!SvREFCNT(cv) && CvOUTSIDE(cv)) {
diff --git a/proto.h b/proto.h
index 3a80ae2ae1..069c5eb5b6 100644
--- a/proto.h
+++ b/proto.h
@@ -2802,11 +2802,6 @@ PERL_CALLCONV void Perl_pad_push(pTHX_ PADLIST *padlist, int depth)
PERL_CALLCONV void Perl_pad_swipe(pTHX_ PADOFFSET po, bool refadjust);
PERL_CALLCONV void Perl_pad_tidy(pTHX_ padtidy_type type);
-PERL_CALLCONV void Perl_pad_undef(pTHX_ CV* cv)
- __attribute__nonnull__(pTHX_1);
-#define PERL_ARGS_ASSERT_PAD_UNDEF \
- assert(cv)
-
PERL_CALLCONV OP* Perl_parse_barestmt(pTHX_ U32 flags);
PERL_CALLCONV OP* Perl_parse_block(pTHX_ U32 flags);
PERL_CALLCONV OP* Perl_parse_fullstmt(pTHX_ U32 flags);