aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/hashmap.go
diff options
context:
space:
mode:
authorMartin Möhrmann <moehrmann@google.com>2017-08-29 13:31:45 +0200
committerMartin Möhrmann <moehrmann@google.com>2017-08-30 07:07:55 +0000
commit54125d191d967da12c5aab957bf6ffcb222df9ed (patch)
treee52915b2831255570569de0ff0327b13113df04e /src/runtime/hashmap.go
parentd77d4f509c61a8e1eaadeabca86ee48710bd8030 (diff)
downloadgo-54125d191d967da12c5aab957bf6ffcb222df9ed.tar.xz
runtime: move dynamic makemap checks into cmd/compile
Check map invariants, type size and alignments during compile time. Keep runtime checks for reflect by adding them to reflect_makemap. Change-Id: Ia28610626591bf7fafb7d5a1ca318da272e54879 Reviewed-on: https://go-review.googlesource.com/59914 Run-TryBot: Martin Möhrmann <moehrmann@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/runtime/hashmap.go')
-rw-r--r--src/runtime/hashmap.go72
1 files changed, 38 insertions, 34 deletions
diff --git a/src/runtime/hashmap.go b/src/runtime/hashmap.go
index 422ccfd41a..37bf6e0aeb 100644
--- a/src/runtime/hashmap.go
+++ b/src/runtime/hashmap.go
@@ -285,7 +285,9 @@ func makemap64(t *maptype, hint int64, h *hmap) *hmap {
// If h != nil, the map can be created directly in h.
// If h.buckets != nil, bucket pointed to can be used as the first bucket.
func makemap(t *maptype, hint int, h *hmap) *hmap {
- if sz := unsafe.Sizeof(hmap{}); sz > 48 || sz != t.hmap.size {
+ // The size of hmap should be 48 bytes on 64 bit
+ // and 28 bytes on 32 bit platforms.
+ if sz := unsafe.Sizeof(hmap{}); sz != 8+5*sys.PtrSize {
println("runtime: sizeof(hmap) =", sz, ", t.hmap.size =", t.hmap.size)
throw("bad hmap size")
}
@@ -298,39 +300,6 @@ func makemap(t *maptype, hint int, h *hmap) *hmap {
throw("runtime.makemap: unsupported map key type")
}
- // check compiler's and reflect's math
- if t.key.size > maxKeySize && (!t.indirectkey || t.keysize != uint8(sys.PtrSize)) ||
- t.key.size <= maxKeySize && (t.indirectkey || t.keysize != uint8(t.key.size)) {
- throw("key size wrong")
- }
- if t.elem.size > maxValueSize && (!t.indirectvalue || t.valuesize != uint8(sys.PtrSize)) ||
- t.elem.size <= maxValueSize && (t.indirectvalue || t.valuesize != uint8(t.elem.size)) {
- throw("value size wrong")
- }
-
- // invariants we depend on. We should probably check these at compile time
- // somewhere, but for now we'll do it here.
- if t.key.align > bucketCnt {
- throw("key align too big")
- }
- if t.elem.align > bucketCnt {
- throw("value align too big")
- }
- if t.key.size%uintptr(t.key.align) != 0 {
- throw("key size not a multiple of key align")
- }
- if t.elem.size%uintptr(t.elem.align) != 0 {
- throw("value size not a multiple of value align")
- }
- if bucketCnt < 8 {
- throw("bucketsize too small for proper alignment")
- }
- if dataOffset%uintptr(t.key.align) != 0 {
- throw("need padding in bucket (key)")
- }
- if dataOffset%uintptr(t.elem.align) != 0 {
- throw("need padding in bucket (value)")
- }
if evacuatedX+1 != evacuatedY {
// evacuate relies on this relationship
throw("bad evacuatedN")
@@ -1183,6 +1152,41 @@ func ismapkey(t *_type) bool {
//go:linkname reflect_makemap reflect.makemap
func reflect_makemap(t *maptype, cap int) *hmap {
+ // Check invariants and reflects math.
+ if sz := unsafe.Sizeof(hmap{}); sz != t.hmap.size {
+ println("runtime: sizeof(hmap) =", sz, ", t.hmap.size =", t.hmap.size)
+ throw("bad hmap size")
+ }
+ if t.key.size > maxKeySize && (!t.indirectkey || t.keysize != uint8(sys.PtrSize)) ||
+ t.key.size <= maxKeySize && (t.indirectkey || t.keysize != uint8(t.key.size)) {
+ throw("key size wrong")
+ }
+ if t.elem.size > maxValueSize && (!t.indirectvalue || t.valuesize != uint8(sys.PtrSize)) ||
+ t.elem.size <= maxValueSize && (t.indirectvalue || t.valuesize != uint8(t.elem.size)) {
+ throw("value size wrong")
+ }
+ if t.key.align > bucketCnt {
+ throw("key align too big")
+ }
+ if t.elem.align > bucketCnt {
+ throw("value align too big")
+ }
+ if t.key.size%uintptr(t.key.align) != 0 {
+ throw("key size not a multiple of key align")
+ }
+ if t.elem.size%uintptr(t.elem.align) != 0 {
+ throw("value size not a multiple of value align")
+ }
+ if bucketCnt < 8 {
+ throw("bucketsize too small for proper alignment")
+ }
+ if dataOffset%uintptr(t.key.align) != 0 {
+ throw("need padding in bucket (key)")
+ }
+ if dataOffset%uintptr(t.elem.align) != 0 {
+ throw("need padding in bucket (value)")
+ }
+
return makemap(t, cap, nil)
}