summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorAbhijit Menon-Sen <ams@wiw.org>2001-08-04 21:46:03 +0530
committerJarkko Hietaniemi <jhi@iki.fi>2001-08-04 14:09:59 +0000
commitb56ba0bf6cecdb4ad30f368203c431004b90dc8e (patch)
treef1417a358919532fdcc888e5ff3162f4eee8f255 /hv.c
parent3377381085987f5c7f3856145d29b4bd2cec1d77 (diff)
downloadperl-b56ba0bf6cecdb4ad30f368203c431004b90dc8e.tar.gz
Re: [PATCH hv.c] newHVhv shouldn't reset xhv_max so often
Message-ID: <20010804161603.C526@lustre.dyn.wiw.org> p4raw-id: //depot/perl@11570
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c68
1 files changed, 51 insertions, 17 deletions
diff --git a/hv.c b/hv.c
index 07bccd9505..2962de3b0d 100644
--- a/hv.c
+++ b/hv.c
@@ -1180,36 +1180,70 @@ Perl_newHV(pTHX)
HV *
Perl_newHVhv(pTHX_ HV *ohv)
{
+ HV *hv = newHV();
STRLEN hv_max, hv_fill;
- register HV *hv = newHV();
if (!ohv || (hv_fill = HvFILL(ohv)) == 0)
return hv;
-
hv_max = HvMAX(ohv);
- while (hv_max && hv_max + 1 >= hv_fill * 2)
- hv_max = hv_max / 2; /* Is always 2^n-1 */
- HvMAX(hv) = hv_max;
-#if 0
- if (! SvTIED_mg((SV*)ohv, PERL_MAGIC_tied)) {
- /* Quick way ???*/
+ if (!SvMAGICAL((SV *)ohv)) {
+ /* It's an ordinary hash, so copy it fast. AMS 20010804 */
+ int i, shared = !!HvSHAREKEYS(ohv);
+ HE **ents, **oents = (HE **)HvARRAY(ohv);
+ New(0, (char *)ents, PERL_HV_ARRAY_ALLOC_BYTES(hv_max+1), char);
+
+ /* In each bucket... */
+ for (i = 0; i <= hv_max; i++) {
+ HE *prev = NULL, *ent = NULL, *oent = oents[i];
+
+ if (!oent) {
+ ents[i] = NULL;
+ continue;
+ }
+
+ /* Copy the linked list of entries. */
+ for (oent = oents[i]; oent; oent = HeNEXT(oent)) {
+ U32 hash = HeHASH(oent);
+ char *key = HeKEY(oent);
+ STRLEN len = HeKLEN_UTF8(oent);
+
+ ent = new_HE();
+ HeVAL(ent) = SvREFCNT_inc(HeVAL(oent));
+ HeKEY_hek(ent) = shared ? share_hek(key, len, hash)
+ : save_hek(key, len, hash);
+ if (prev)
+ HeNEXT(prev) = ent;
+ else
+ ents[i] = ent;
+ prev = ent;
+ HeNEXT(ent) = NULL;
+ }
+ }
+
+ HvMAX(hv) = hv_max;
+ HvFILL(hv) = hv_fill;
+ HvKEYS(hv) = HvKEYS(ohv);
+ HvARRAY(hv) = ents;
}
- else
-#endif
- {
+ else {
+ /* Iterate over ohv, copying keys and values one at a time. */
HE *entry;
- I32 hv_riter = HvRITER(ohv); /* current root of iterator */
- HE *hv_eiter = HvEITER(ohv); /* current entry of iterator */
-
- /* Slow way */
+ I32 riter = HvRITER(ohv);
+ HE *eiter = HvEITER(ohv);
+
+ /* Can we use fewer buckets? (hv_max is always 2^n-1) */
+ while (hv_max && hv_max + 1 >= hv_fill * 2)
+ hv_max = hv_max / 2;
+ HvMAX(hv) = hv_max;
+
hv_iterinit(ohv);
while ((entry = hv_iternext(ohv))) {
hv_store(hv, HeKEY(entry), HeKLEN_UTF8(entry),
newSVsv(HeVAL(entry)), HeHASH(entry));
}
- HvRITER(ohv) = hv_riter;
- HvEITER(ohv) = hv_eiter;
+ HvRITER(ohv) = riter;
+ HvEITER(ohv) = eiter;
}
return hv;