1
0
mirror of https://github.com/golang/go synced 2024-11-19 14:34:42 -07:00

runtime: calculate k only once in mapiternext

Make the calculation of k and v a bit lazier.
None of the following code cares about indirect-vs-direct k,
and it happens on all code paths, so check t.indirectkey earlier.

Simplifies the code and reduces both machine code and stack size.

Change-Id: I5ea4c0772848d7a4b15383baedb9a1f7feb47201
Reviewed-on: https://go-review.googlesource.com/55092
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2017-08-11 08:43:30 -07:00
parent 29e9b89b9a
commit 589fc314af

View File

@ -820,11 +820,14 @@ next:
} }
for ; i < bucketCnt; i++ { for ; i < bucketCnt; i++ {
offi := (i + it.offset) & (bucketCnt - 1) offi := (i + it.offset) & (bucketCnt - 1)
k := add(unsafe.Pointer(b), dataOffset+uintptr(offi)*uintptr(t.keysize))
v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+uintptr(offi)*uintptr(t.valuesize))
if b.tophash[offi] == empty || b.tophash[offi] == evacuatedEmpty { if b.tophash[offi] == empty || b.tophash[offi] == evacuatedEmpty {
continue continue
} }
k := add(unsafe.Pointer(b), dataOffset+uintptr(offi)*uintptr(t.keysize))
if t.indirectkey {
k = *((*unsafe.Pointer)(k))
}
v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+uintptr(offi)*uintptr(t.valuesize))
if checkBucket != noCheck && !h.sameSizeGrow() { if checkBucket != noCheck && !h.sameSizeGrow() {
// Special case: iterator was started during a grow to a larger size // Special case: iterator was started during a grow to a larger size
// and the grow is not done yet. We're working on a bucket whose // and the grow is not done yet. We're working on a bucket whose
@ -833,14 +836,10 @@ next:
// through the oldbucket, skipping any keys that will go // through the oldbucket, skipping any keys that will go
// to the other new bucket (each oldbucket expands to two // to the other new bucket (each oldbucket expands to two
// buckets during a grow). // buckets during a grow).
k2 := k if t.reflexivekey || alg.equal(k, k) {
if t.indirectkey {
k2 = *((*unsafe.Pointer)(k2))
}
if t.reflexivekey || alg.equal(k2, k2) {
// If the item in the oldbucket is not destined for // If the item in the oldbucket is not destined for
// the current new bucket in the iteration, skip it. // the current new bucket in the iteration, skip it.
hash := alg.hash(k2, uintptr(h.hash0)) hash := alg.hash(k, uintptr(h.hash0))
if hash&(uintptr(1)<<it.B-1) != checkBucket { if hash&(uintptr(1)<<it.B-1) != checkBucket {
continue continue
} }
@ -859,9 +858,6 @@ next:
} }
if b.tophash[offi] != evacuatedX && b.tophash[offi] != evacuatedY { if b.tophash[offi] != evacuatedX && b.tophash[offi] != evacuatedY {
// this is the golden data, we can return it. // this is the golden data, we can return it.
if t.indirectkey {
k = *((*unsafe.Pointer)(k))
}
it.key = k it.key = k
if t.indirectvalue { if t.indirectvalue {
v = *((*unsafe.Pointer)(v)) v = *((*unsafe.Pointer)(v))
@ -870,17 +866,13 @@ next:
} else { } else {
// The hash table has grown since the iterator was started. // The hash table has grown since the iterator was started.
// The golden data for this key is now somewhere else. // The golden data for this key is now somewhere else.
k2 := k if t.reflexivekey || alg.equal(k, k) {
if t.indirectkey {
k2 = *((*unsafe.Pointer)(k2))
}
if t.reflexivekey || alg.equal(k2, k2) {
// Check the current hash table for the data. // Check the current hash table for the data.
// This code handles the case where the key // This code handles the case where the key
// has been deleted, updated, or deleted and reinserted. // has been deleted, updated, or deleted and reinserted.
// NOTE: we need to regrab the key as it has potentially been // NOTE: we need to regrab the key as it has potentially been
// updated to an equal() but not identical key (e.g. +0.0 vs -0.0). // updated to an equal() but not identical key (e.g. +0.0 vs -0.0).
rk, rv := mapaccessK(t, h, k2) rk, rv := mapaccessK(t, h, k)
if rk == nil { if rk == nil {
continue // key has been deleted continue // key has been deleted
} }
@ -891,7 +883,7 @@ next:
// updated, so we can just return it. That's lucky for // updated, so we can just return it. That's lucky for
// us because when key!=key we can't look it up // us because when key!=key we can't look it up
// successfully in the current table. // successfully in the current table.
it.key = k2 it.key = k
if t.indirectvalue { if t.indirectvalue {
v = *((*unsafe.Pointer)(v)) v = *((*unsafe.Pointer)(v))
} }