diff options
author | Abhijit Menon-Sen <ams@wiw.org> | 2001-08-04 21:46:03 +0530 |
---|---|---|
committer | Jarkko Hietaniemi <jhi@iki.fi> | 2001-08-04 14:09:59 +0000 |
commit | b56ba0bf6cecdb4ad30f368203c431004b90dc8e (patch) | |
tree | f1417a358919532fdcc888e5ff3162f4eee8f255 /hv.c | |
parent | 3377381085987f5c7f3856145d29b4bd2cec1d77 (diff) | |
download | perl-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.c | 68 |
1 files changed, 51 insertions, 17 deletions
@@ -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; |