summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorMax Maischein <corion@corion.net>2009-05-31 23:50:12 +0200
committerVincent Pit <perl@profvince.com>2009-06-01 21:25:49 +0200
commit900ac0519e4b408fd93443b14b734cc330c59698 (patch)
treebd665ce77316d56aa3259e6d16889d75f586cb62 /hv.c
parent5a1562d6aa780bfc9a14482654d4f7d63a1db386 (diff)
downloadperl-900ac0519e4b408fd93443b14b734cc330c59698.tar.gz
Fix RT26188, speed up keys() on empty hash
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c40
1 files changed, 23 insertions, 17 deletions
diff --git a/hv.c b/hv.c
index 3322848b19..5f233d6ca1 100644
--- a/hv.c
+++ b/hv.c
@@ -2143,26 +2143,32 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags)
}
}
}
- while (!entry) {
- /* OK. Come to the end of the current list. Grab the next one. */
- iter->xhv_riter++; /* HvRITER(hv)++ */
- if (iter->xhv_riter > (I32)xhv->xhv_max /* HvRITER(hv) > HvMAX(hv) */) {
- /* There is no next one. End of the hash. */
- iter->xhv_riter = -1; /* HvRITER(hv) = -1 */
- break;
- }
- entry = (HvARRAY(hv))[iter->xhv_riter];
+ /* Quick bailout if the hash is empty anyway.
+ I don't know if placeholders are included in the KEYS count, so a defensive check
+ */
+ if (HvKEYS(hv) || (flags & HV_ITERNEXT_WANTPLACEHOLDERS)) {
+ while (!entry) {
+ /* OK. Come to the end of the current list. Grab the next one. */
+
+ iter->xhv_riter++; /* HvRITER(hv)++ */
+ if (iter->xhv_riter > (I32)xhv->xhv_max /* HvRITER(hv) > HvMAX(hv) */) {
+ /* There is no next one. End of the hash. */
+ iter->xhv_riter = -1; /* HvRITER(hv) = -1 */
+ break;
+ }
+ entry = (HvARRAY(hv))[iter->xhv_riter];
- if (!(flags & HV_ITERNEXT_WANTPLACEHOLDERS)) {
- /* If we have an entry, but it's a placeholder, don't count it.
- Try the next. */
- while (entry && HeVAL(entry) == &PL_sv_placeholder)
- entry = HeNEXT(entry);
+ if (!(flags & HV_ITERNEXT_WANTPLACEHOLDERS)) {
+ /* If we have an entry, but it's a placeholder, don't count it.
+ Try the next. */
+ while (entry && HeVAL(entry) == &PL_sv_placeholder)
+ entry = HeNEXT(entry);
+ }
+ /* Will loop again if this linked list starts NULL
+ (for HV_ITERNEXT_WANTPLACEHOLDERS)
+ or if we run through it and find only placeholders. */
}
- /* Will loop again if this linked list starts NULL
- (for HV_ITERNEXT_WANTPLACEHOLDERS)
- or if we run through it and find only placeholders. */
}
if (oldentry && HvLAZYDEL(hv)) { /* was deleted earlier? */