From: Abhijit Menon-Sen Date: Sat, 4 Aug 2001 16:16:03 +0000 (+0530) Subject: Re: [PATCH hv.c] newHVhv shouldn't reset xhv_max so often X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=b56ba0bf6cecdb4ad30f368203c431004b90dc8e;p=p5sagit%2Fp5-mst-13.2.git 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 --- diff --git a/hv.c b/hv.c index 07bccd9..2962de3 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;