X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=hv.c;h=852ee165a51dc10826dba5f22678d803124b5aa2;hb=382b8d976294e2f8b1ced0b3776a3fb280b0ecd4;hp=7ae2340835cddafa7f6c117c5bd44abec4eddb53;hpb=a0d0e21ea6ea90a22318550944fe6cb09ae10cda;p=p5sagit%2Fp5-mst-13.2.git diff --git a/hv.c b/hv.c index 7ae2340..852ee16 100644 --- a/hv.c +++ b/hv.c @@ -17,6 +17,44 @@ static void hsplit _((HV *hv)); static void hfreeentries _((HV *hv)); +static HE* more_he(); + +static HE* +new_he() +{ + HE* he; + if (he_root) { + he = he_root; + he_root = (HE*)he->hent_next; + return he; + } + return more_he(); +} + +static void +del_he(p) +HE* p; +{ + p->hent_next = (HE*)he_root; + he_root = p; +} + +static HE* +more_he() +{ + register HE* he; + register HE* heend; + he_root = (HE*)safemalloc(1008); + he = he_root; + heend = &he[1008 / sizeof(HE) - 1]; + while (he < heend) { + he->hent_next = (HE*)(he + 1); + he++; + } + he->hent_next = 0; + return new_he(); +} + SV** hv_fetch(hv,key,klen,lval) HV *hv; @@ -142,8 +180,8 @@ register U32 hash; entry->hent_val = val; return &entry->hent_val; } - New(501,entry, 1, HE); + entry = new_he(); entry->hent_klen = klen; entry->hent_key = savepvn(key,klen); entry->hent_val = val; @@ -162,10 +200,11 @@ register U32 hash; } SV * -hv_delete(hv,key,klen) +hv_delete(hv,key,klen,flags) HV *hv; char *key; U32 klen; +I32 flags; { register XPVHV* xhv; register char *s; @@ -207,7 +246,10 @@ U32 klen; *oentry = entry->hent_next; if (i && !*oentry) xhv->xhv_fill--; - sv = sv_mortalcopy(entry->hent_val); + if (flags & G_DISCARD) + sv = Nullsv; + else + sv = sv_mortalcopy(entry->hent_val); if (entry == xhv->xhv_eiter) entry->hent_klen = -1; else @@ -278,10 +320,33 @@ HV *hv; register HE **b; register HE *entry; register HE **oentry; + I32 tmp; a = (HE**)xhv->xhv_array; nomemok = TRUE; +#ifdef STRANGE_MALLOC Renew(a, newsize, HE*); +#else + i = newsize * sizeof(HE*); +#define MALLOC_OVERHEAD 16 + tmp = MALLOC_OVERHEAD; + while (tmp - MALLOC_OVERHEAD < i) + tmp += tmp; + tmp -= MALLOC_OVERHEAD; + tmp /= sizeof(HE*); + assert(tmp >= newsize); + New(2,a, tmp, HE*); + Copy(xhv->xhv_array, a, oldsize, HE*); + if (oldsize >= 64 && *(char*)&xhv->xnv_nv == 0) { + sv_add_arena((char*)xhv->xhv_array, oldsize * sizeof(HE*), 0); + sv_add_arena(((char*)a) + newsize * sizeof(HE*), + newsize * sizeof(HE*) - MALLOC_OVERHEAD, + SVf_FAKE); + } + else + Safefree(xhv->xhv_array); +#endif + nomemok = FALSE; Zero(&a[oldsize], oldsize, HE*); /* zero 2nd half*/ xhv->xhv_max = --newsize; @@ -322,6 +387,7 @@ newHV() xhv->xhv_max = 7; /* start with 8 buckets */ xhv->xhv_fill = 0; xhv->xhv_pmroot = 0; + *(char*)&xhv->xnv_nv = 0; (void)hv_iterinit(hv); /* so each() will start off right */ return hv; } @@ -334,7 +400,7 @@ register HE *hent; return; SvREFCNT_dec(hent->hent_val); Safefree(hent->hent_key); - Safefree(hent); + del_he(hent); } void @@ -345,7 +411,7 @@ register HE *hent; return; sv_2mortal(hent->hent_val); /* free between statements */ Safefree(hent->hent_key); - Safefree(hent); + del_he(hent); } void @@ -409,7 +475,14 @@ HV *hv; return; xhv = (XPVHV*)SvANY(hv); hfreeentries(hv); +#ifdef STRANGE_MALLOC Safefree(xhv->xhv_array); +#else + if (xhv->xhv_max < 127 || *(char*)&xhv->xnv_nv) + Safefree(xhv->xhv_array); + else /* We used last half, so use first half for SV arena too. */ + sv_add_arena((char*)xhv->xhv_array, (xhv->xhv_max + 1) * sizeof(HE*),0); +#endif if (HvNAME(hv)) { Safefree(HvNAME(hv)); HvNAME(hv) = 0; @@ -418,6 +491,7 @@ HV *hv; xhv->xhv_max = 7; /* it's a normal associative array */ xhv->xhv_fill = 0; xhv->xhv_keys = 0; + *(char*)&xhv->xnv_nv = 1; if (SvRMAGICAL(hv)) mg_clear((SV*)hv); @@ -457,8 +531,8 @@ HV *hv; entry->hent_key = 0; } else { - Newz(504,entry, 1, HE); - xhv->xhv_eiter = entry; + xhv->xhv_eiter = entry = new_he(); + Zero(entry, 1, HE); } magic_nextpack((SV*) hv,mg,key); if (SvOK(key)) { @@ -471,7 +545,7 @@ HV *hv; } if (entry->hent_val) SvREFCNT_dec(entry->hent_val); - Safefree(entry); + del_he(entry); xhv->xhv_eiter = Null(HE*); return Null(HE*); }