summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2010-08-01 15:18:51 +0100
committerDavid Mitchell <davem@iabyn.com>2010-08-01 21:47:31 +0100
commit5648c0ae71de0db3ebfb4199727bc21e89c146c0 (patch)
tree6154d88ceb21e1a21bfa48cbe08a805564149b0e /hv.c
parent757971c467ea1792cbf102db9a0cc3a9dde58fea (diff)
downloadperl-5648c0ae71de0db3ebfb4199727bc21e89c146c0.tar.gz
optimise single backreferences
Rather than creating an AV and pushing the backref onto it, store a single backref directly in the mg_obj or xhv_backreferences slot. If the backref is an AV, then we skip this optimisation (although I don't think at the moment, that an AV would ever be pointed to by some backref magic). So the test of whether the optimisation is is in effect is whether the thing in the slot is an AV or not.
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/hv.c b/hv.c
index f110d15099..9b5a3ba4d7 100644
--- a/hv.c
+++ b/hv.c
@@ -1682,17 +1682,25 @@ S_hfreeentries(pTHX_ HV *hv)
* iteration we have to allow for this. */
if (iter->xhv_backreferences) {
- /* The sv_magic will increase the reference count of the AV,
- so we need to drop it first. */
- SvREFCNT_dec(iter->xhv_backreferences);
- if (AvFILLp(iter->xhv_backreferences) == -1) {
- /* Turns out that the array is empty. Just free it. */
+ if (SvTYPE(iter->xhv_backreferences) == SVt_PVAV) {
+ /* The sv_magic will increase the reference count of the AV,
+ so we need to drop it first. */
SvREFCNT_dec(iter->xhv_backreferences);
+ if (AvFILLp(iter->xhv_backreferences) == -1) {
+ /* Turns out that the array is empty. Just free it. */
+ SvREFCNT_dec(iter->xhv_backreferences);
- } else {
- sv_magic(MUTABLE_SV(hv),
- MUTABLE_SV(iter->xhv_backreferences),
- PERL_MAGIC_backref, NULL, 0);
+ } else {
+ sv_magic(MUTABLE_SV(hv),
+ MUTABLE_SV(iter->xhv_backreferences),
+ PERL_MAGIC_backref, NULL, 0);
+ }
+ }
+ else {
+ MAGIC *mg;
+ sv_magic(MUTABLE_SV(hv), NULL, PERL_MAGIC_backref, NULL, 0);
+ mg = mg_find(MUTABLE_SV(hv), PERL_MAGIC_backref);
+ mg->mg_obj = (SV*)iter->xhv_backreferences;
}
iter->xhv_backreferences = NULL;
}
@@ -2047,7 +2055,8 @@ Perl_hv_kill_backrefs(pTHX_ HV *hv) {
if (av) {
HvAUX(hv)->xhv_backreferences = 0;
Perl_sv_kill_backrefs(aTHX_ MUTABLE_SV(hv), av);
- SvREFCNT_dec(av);
+ if (SvTYPE(av) == SVt_PVAV)
+ SvREFCNT_dec(av);
}
}