summaryrefslogtreecommitdiff
path: root/scope.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2014-02-28 19:46:15 +0000
committerDavid Mitchell <davem@iabyn.com>2014-02-28 19:46:15 +0000
commitf5572cf8315f7c5228c30330db88dd3f604cfdc1 (patch)
treed0538941c0f01aae6d885e49b66ae72db4759520 /scope.c
parentb838857b5256d738820be79973535c28fc4da01c (diff)
parent9af159903dbf2799f16d8b83e8e556583aabd3e2 (diff)
downloadperl-f5572cf8315f7c5228c30330db88dd3f604cfdc1.tar.gz
[MERGE] tweak in-place branch of SAVEt_CLEARSV
clean up the code that clears lexical vars on scope exit; chiefly, wrap all the individual 'unusual case' flag tests in a single big test of the union of all such flags, so that simple lexical vars skip all the tests.
Diffstat (limited to 'scope.c')
-rw-r--r--scope.c60
1 files changed, 40 insertions, 20 deletions
diff --git a/scope.c b/scope.c
index 38eea2f928..4c4f5274d0 100644
--- a/scope.c
+++ b/scope.c
@@ -1036,28 +1036,46 @@ Perl_leave_scope(pTHX_ I32 base)
(SvREFCNT(sv) <= 1 && !SvOBJECT(sv)) ? "clear" : "abandon"
));
+ assert(SvPADMY(sv));
+
/* Can clear pad variable in place? */
- if (SvREFCNT(sv) <= 1 && !SvOBJECT(sv)) {
- /*
- * if a my variable that was made readonly is going out of
- * scope, we want to remove the readonlyness so that it can
- * go out of scope quietly
- */
- if (SvPADMY(sv) && !SvFAKE(sv))
- SvREADONLY_off(sv);
-
- if (SvTYPE(sv) == SVt_PVHV)
- Perl_hv_kill_backrefs(aTHX_ MUTABLE_HV(sv));
- if (SvMAGICAL(sv))
+ if (SvREFCNT(sv) == 1 && !SvOBJECT(sv)) {
+
+ /* these flags are the union of all the relevant flags
+ * in the individual conditions within */
+ if (UNLIKELY(SvFLAGS(sv) & (
+ SVf_READONLY /* for SvREADONLY_off() */
+ | (SVs_GMG|SVs_SMG|SVs_RMG) /* SvMAGICAL() */
+ | SVf_OOK
+ | SVf_THINKFIRST)))
{
- sv_unmagic(sv, PERL_MAGIC_backref);
- if (SvTYPE(sv) != SVt_PVCV)
- mg_free(sv);
- }
- if (SvTHINKFIRST(sv))
- sv_force_normal_flags(sv, SV_IMMEDIATE_UNREF
- |SV_COW_DROP_PV);
+ /* if a my variable that was made readonly is
+ * going out of scope, we want to remove the
+ * readonlyness so that it can go out of scope
+ * quietly
+ */
+ if (SvREADONLY(sv) && !SvFAKE(sv))
+ SvREADONLY_off(sv);
+
+ if (SvOOK(sv)) { /* OOK or HvAUX */
+ if (SvTYPE(sv) == SVt_PVHV)
+ Perl_hv_kill_backrefs(aTHX_ MUTABLE_HV(sv));
+ else
+ sv_backoff(sv);
+ }
+
+ if (SvMAGICAL(sv)) {
+ /* note that backrefs (either in HvAUX or magic)
+ * must be removed before other magic */
+ sv_unmagic(sv, PERL_MAGIC_backref);
+ if (SvTYPE(sv) != SVt_PVCV)
+ mg_free(sv);
+ }
+ if (SvTHINKFIRST(sv))
+ sv_force_normal_flags(sv, SV_IMMEDIATE_UNREF
+ |SV_COW_DROP_PV);
+ }
switch (SvTYPE(sv)) {
case SVt_NULL:
break;
@@ -1077,7 +1095,9 @@ Perl_leave_scope(pTHX_ I32 base)
break;
}
default:
- SvOK_off(sv);
+ assert_not_ROK(sv);
+ assert_not_glob(sv);
+ SvFLAGS(sv) &=~ (SVf_OK|SVf_IVisUV|SVf_UTF8);
break;
}
SvPADSTALE_on(sv); /* mark as no longer live */