summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Mitchell <davem@fdisolutions.com>2008-12-09 22:42:23 +0000
committerDave Mitchell <davem@fdisolutions.com>2008-12-09 22:42:23 +0000
commit322e88caed9df280e1f5a1ef8b5770ab615ece5b (patch)
tree2915ebe4789be8a28f6934c342dbf68a95fd73a0
parentc700720a41c7b8635385df906a4e8443d8851779 (diff)
downloadperl-322e88caed9df280e1f5a1ef8b5770ab615ece5b.tar.gz
Integrate:
[ 34214] In S_mro_get_linear_isa_dfs(), hv_exists_ent() followed by an optional hv_store_ent() can be replaced with an lvalue fetch. [ 34215] In S_mro_get_linear_isa_dfs(), save copying by making a shared hash key scalar from the key of the hash entry we've just creating. (Currently the hash is disposed of afterwards, but soon it won't, so having both point to the same string buffer will also save memory.) p4raw-link: @34215 on //depot/perl: f46ee2483d022839b174c58babe5076a34c0b367 p4raw-link: @34214 on //depot/perl: 8e45cc2bb9db96fb730868796fbfe1d0f7ece32d p4raw-id: //depot/maint-5.10/perl@35071 p4raw-integrated: from //depot/perl@34215 'edit in' mro.c (@34214..) 'merge in' sv.c (@34213..)
-rw-r--r--mro.c29
-rw-r--r--sv.c2
2 files changed, 28 insertions, 3 deletions
diff --git a/mro.c b/mro.c
index 83fdd719cf..c960fe4d15 100644
--- a/mro.c
+++ b/mro.c
@@ -186,9 +186,32 @@ S_mro_get_linear_isa_dfs(pTHX_ HV *stash, I32 level)
}
while(subrv_items--) {
SV *const subsv = *subrv_p++;
- if(!hv_exists_ent(stored, subsv, 0)) {
- (void)hv_store_ent(stored, subsv, &PL_sv_undef, 0);
- av_push(retval, newSVsv(subsv));
+ /* LVALUE fetch will create a new undefined SV if necessary
+ */
+ HE *const he = hv_fetch_ent(stored, subsv, 1, 0);
+ assert(he);
+ if(HeVAL(he) != &PL_sv_undef) {
+ /* It was newly created. Steal it for our new SV, and
+ replace it in the hash with the "real" thing. */
+ SV *const val = HeVAL(he);
+ HEK *const key = HeKEY_hek(he);
+
+ HeVAL(he) = &PL_sv_undef;
+ /* Save copying by making a shared hash key scalar. We
+ inline this here rather than calling Perl_newSVpvn_share
+ because we already have the scalar, and we already have
+ the hash key. */
+ assert(SvTYPE(val) == SVt_NULL);
+ sv_upgrade(val, SVt_PV);
+ SvPV_set(val, HEK_KEY(share_hek_hek(key)));
+ SvCUR_set(val, HEK_LEN(key));
+ SvREADONLY_on(val);
+ SvFAKE_on(val);
+ SvPOK_on(val);
+ if (HEK_UTF8(key))
+ SvUTF8_on(val);
+
+ av_push(retval, val);
}
}
}
diff --git a/sv.c b/sv.c
index 3fc9838329..b8e6f921e7 100644
--- a/sv.c
+++ b/sv.c
@@ -7272,6 +7272,8 @@ Perl_newSVpvn_share(pTHX_ const char *src, I32 len, U32 hash)
if (!hash)
PERL_HASH(hash, src, len);
new_SV(sv);
+ /* The logic for this is inlined in S_mro_get_linear_isa_dfs(), so if it
+ changes here, update it there too. */
sv_upgrade(sv, SVt_PV);
SvPV_set(sv, sharepvn(src, is_utf8?-len:len, hash));
SvCUR_set(sv, len);