X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=universal.c;h=b92bd7a5680ccdf729d555bfc260b2890d075054;hb=30ef33217aeee51ee47b2433e9384b011646254a;hp=550ea4dfee7a9cf410a694f591ade16fb383f7a7;hpb=f044d0d1cebf908527bb010d8157554092773e3b;p=p5sagit%2Fp5-mst-13.2.git diff --git a/universal.c b/universal.c index 550ea4d..b92bd7a 100644 --- a/universal.c +++ b/universal.c @@ -49,7 +49,7 @@ S_isa_lookup(pTHX_ HV *stash, const char *name, HV* name_stash, if (gvp && (gv = *gvp) != (GV*)&PL_sv_undef && (subgen = GvSV(gv)) && (hv = GvHV(gv))) { - if (SvIV(subgen) == PL_sub_generation) { + if (SvIV(subgen) == (IV)PL_sub_generation) { SV* sv; SV** svp = (SV**)hv_fetch(hv, name, len, FALSE); if (svp && (sv = *svp) != (SV*)&PL_sv_undef) { @@ -513,16 +513,23 @@ XS(XS_Internals_hv_clear_placehold) /* I don't care how many parameters were passed in, but I want to avoid the unused variable warning. */ - items = HvPLACEHOLDERS(hv); + items = (I32)HvPLACEHOLDERS(hv); if (items) { HE *entry; I32 riter = HvRITER(hv); HE *eiter = HvEITER(hv); hv_iterinit(hv); - while (items - && (entry - = hv_iternext_flags(hv, HV_ITERNEXT_WANTPLACEHOLDERS))) { + /* This may look suboptimal with the items *after* the iternext, but + it's quite deliberate. We only get here with items==0 if we've + just deleted the last placeholder in the hash. If we've just done + that then it means that the hash is in lazy delete mode, and the + HE is now only referenced in our iterator. If we just quit the loop + and discarded our iterator then the HE leaks. So we do the && the + other way to ensure iternext is called just one more time, which + has the side effect of triggering the lazy delete. */ + while ((entry = hv_iternext_flags(hv, HV_ITERNEXT_WANTPLACEHOLDERS)) + && items) { SV *val = hv_iterval(hv, entry); if (val == &PL_sv_undef) {