summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2010-11-18 14:54:44 +0000
committerNicholas Clark <nick@ccl4.org>2010-11-18 15:00:44 +0000
commit437388a93114b1acbfb3a173dfa7aa2138fd8283 (patch)
tree54c89721ce3ee574f9ffdd0e83ee54886d68a00b /op.c
parentce057ba89da80863694d58259ca5a4408f7e44c8 (diff)
downloadperl-437388a93114b1acbfb3a173dfa7aa2138fd8283.tar.gz
Refactor newATTRSUB()'s logic for grafting a sub definition to an existing stub
Previously it was using cv_undef() to (partially) free the target CV (the pre-existing stub), before donating it the padlist and outside pointers from the source CV (the definition, just compiled), and then freeing up the remains of the source CV. Instead, explicitly exchange padlist and outside pointers, explicitly assign other fields that need changing (file and stash), and assert that various CvFLAGS are as we expect them.
Diffstat (limited to 'op.c')
-rw-r--r--op.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/op.c b/op.c
index 2e974fd3fd..73f5f4a863 100644
--- a/op.c
+++ b/op.c
@@ -6232,15 +6232,30 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
#endif
) {
cv_flags_t existing_builtin_attrs = CvFLAGS(cv) & CVf_BUILTIN_ATTRS;
- cv_undef(cv);
+ AV *const temp_av = CvPADLIST(cv);
+ CV *const temp_cv = CvOUTSIDE(cv);
+
+ assert(!CvWEAKOUTSIDE(cv));
+ assert(!CvCVGV_RC(cv));
+ assert(CvGV(cv) == gv);
+
+ SvPOK_off(cv);
CvFLAGS(cv) = CvFLAGS(PL_compcv) | existing_builtin_attrs;
- if (!CvWEAKOUTSIDE(cv))
- SvREFCNT_dec(CvOUTSIDE(cv));
CvOUTSIDE(cv) = CvOUTSIDE(PL_compcv);
CvOUTSIDE_SEQ(cv) = CvOUTSIDE_SEQ(PL_compcv);
- CvOUTSIDE(PL_compcv) = 0;
CvPADLIST(cv) = CvPADLIST(PL_compcv);
- CvPADLIST(PL_compcv) = 0;
+ CvOUTSIDE(PL_compcv) = temp_cv;
+ CvPADLIST(PL_compcv) = temp_av;
+
+#ifdef USE_ITHREADS
+ if (CvFILE(cv) && !CvISXSUB(cv)) {
+ /* for XSUBs CvFILE point directly to static memory; __FILE__ */
+ Safefree(CvFILE(cv));
+ }
+#endif
+ CvFILE_set_from_cop(cv, PL_curcop);
+ CvSTASH_set(cv, PL_curstash);
+
/* inner references to PL_compcv must be fixed up ... */
pad_fixup_inner_anons(CvPADLIST(cv), PL_compcv, cv);
if (PERLDB_INTER)/* Advice debugger on the new sub. */