aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/hashmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/hashmap.c')
-rw-r--r--src/pkg/runtime/hashmap.c37
1 files changed, 19 insertions, 18 deletions
diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c
index 101c4281f6..c359e2a14d 100644
--- a/src/pkg/runtime/hashmap.c
+++ b/src/pkg/runtime/hashmap.c
@@ -746,9 +746,8 @@ struct hash_iter
byte *buckets; // bucket ptr at hash_iter initialization time
struct Bucket *bptr; // current bucket
- // end point for iteration
- uintptr endbucket;
- bool wrapped;
+ uint32 offset; // intra-bucket offset to start from during iteration
+ bool done;
// state of table at time iterator is initialized
uint8 B;
@@ -768,8 +767,8 @@ hash_iter_init(MapType *t, Hmap *h, struct hash_iter *it)
{
uint32 old;
- if(sizeof(struct hash_iter) / sizeof(uintptr) != 11) {
- runtime·throw("hash_iter size incorrect"); // see ../../cmd/gc/range.c
+ if(sizeof(struct hash_iter) / sizeof(uintptr) != 10) {
+ runtime·throw("hash_iter size incorrect"); // see ../../cmd/gc/reflect.c
}
it->t = t;
it->h = h;
@@ -779,8 +778,9 @@ hash_iter_init(MapType *t, Hmap *h, struct hash_iter *it)
it->buckets = h->buckets;
// iterator state
- it->bucket = it->endbucket = runtime·fastrand1() & (((uintptr)1 << h->B) - 1);
- it->wrapped = false;
+ it->bucket = 0;
+ it->offset = runtime·fastrand1() & (BUCKETSIZE - 1);
+ it->done = false;
it->bptr = nil;
// Remember we have an iterator.
@@ -795,8 +795,8 @@ hash_iter_init(MapType *t, Hmap *h, struct hash_iter *it)
if(h->buckets == nil) {
// Empty map. Force next hash_next to exit without
- // evalulating h->bucket.
- it->wrapped = true;
+ // evaluating h->bucket.
+ it->done = true;
}
}
@@ -810,7 +810,7 @@ hash_next(struct hash_iter *it)
uintptr bucket, oldbucket;
uintptr hash;
Bucket *b;
- uintptr i;
+ uintptr i, offi;
intptr check_bucket;
bool eq;
byte *k, *v;
@@ -825,7 +825,7 @@ hash_next(struct hash_iter *it)
next:
if(b == nil) {
- if(bucket == it->endbucket && it->wrapped) {
+ if(it->done) {
// end of iteration
it->key = nil;
it->value = nil;
@@ -851,14 +851,15 @@ next:
bucket++;
if(bucket == ((uintptr)1 << it->B)) {
bucket = 0;
- it->wrapped = true;
+ it->done = true;
}
i = 0;
}
- k = b->data + h->keysize * i;
- v = b->data + h->keysize * BUCKETSIZE + h->valuesize * i;
- for(; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
- if(b->tophash[i] != Empty && b->tophash[i] != EvacuatedEmpty) {
+ for(; i < BUCKETSIZE; i++) {
+ offi = (i + it->offset) & (BUCKETSIZE - 1);
+ k = b->data + h->keysize * offi;
+ v = b->data + h->keysize * BUCKETSIZE + h->valuesize * offi;
+ if(b->tophash[offi] != Empty && b->tophash[offi] != EvacuatedEmpty) {
if(check_bucket >= 0) {
// Special case: iterator was started during a grow and the
// grow is not done yet. We're working on a bucket whose
@@ -884,12 +885,12 @@ next:
// NOTE: this case is why we need two evacuate tophash
// values, evacuatedX and evacuatedY, that differ in
// their low bit.
- if(check_bucket >> (it->B - 1) != (b->tophash[i] & 1)) {
+ if(check_bucket >> (it->B - 1) != (b->tophash[offi] & 1)) {
continue;
}
}
}
- if(b->tophash[i] != EvacuatedX && b->tophash[i] != EvacuatedY) {
+ if(b->tophash[offi] != EvacuatedX && b->tophash[offi] != EvacuatedY) {
// this is the golden data, we can return it.
it->key = IK(h, k);
it->value = IV(h, v);