diff options
author | Nicholas Clark <nick@ccl4.org> | 2005-06-21 12:39:27 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2005-06-21 12:39:27 +0000 |
commit | 6a76db8b55b6281740baab9e0ef221938c776ccd (patch) | |
tree | 8dd732447acb85bff372c5f27d33064684ca8f57 /sv.c | |
parent | 668825592272d9b757847b1a84b8de3cb1b3540b (diff) | |
download | perl-6a76db8b55b6281740baab9e0ef221938c776ccd.tar.gz |
Avoid having NULL entries in the weakref backreference array, and
make S_sv_add_backref O(1) (instead of O(n))
p4raw-id: //depot/perl@24924
Diffstat (limited to 'sv.c')
-rw-r--r-- | sv.c | 26 |
1 files changed, 17 insertions, 9 deletions
@@ -5230,13 +5230,6 @@ S_sv_add_backref(pTHX_ SV *tsv, SV *sv) * by magic_killbackrefs() when tsv is being freed */ } if (AvFILLp(av) >= AvMAX(av)) { - I32 i; - SV **svp = AvARRAY(av); - for (i = AvFILLp(av); i >= 0; i--) - if (!svp[i]) { - svp[i] = sv; /* reuse the slot */ - return; - } av_extend(av, AvFILLp(av)+1); } AvARRAY(av)[++AvFILLp(av)] = sv; /* av_push() */ @@ -5258,8 +5251,23 @@ S_sv_del_backref(pTHX_ SV *sv) Perl_croak(aTHX_ "panic: del_backref"); av = (AV *)mg->mg_obj; svp = AvARRAY(av); - for (i = AvFILLp(av); i >= 0; i--) - if (svp[i] == sv) svp[i] = Nullsv; + /* We shouldn't be in here more than once, but for paranoia reasons lets + not assume this. */ + for (i = AvFILLp(av); i >= 0; i--) { + if (svp[i] == sv) { + const SSize_t fill = AvFILLp(av); + if (i != fill) { + /* We weren't the last entry. + An unordered list has this property that you can take the + last element off the end to fill the hole, and it's still + an unordered list :-) + */ + svp[i] = svp[fill]; + } + svp[fill] = Nullsv; + AvFILLp(av) = fill - 1; + } + } } /* |