arr = types.NewArray(keytype, BUCKETSIZE)
arr.SetNoalg(true)
- field = append(field, makefield("keys", arr))
+ keys := makefield("keys", arr)
+ field = append(field, keys)
arr = types.NewArray(valtype, BUCKETSIZE)
arr.SetNoalg(true)
- field = append(field, makefield("values", arr))
+ values := makefield("values", arr)
+ field = append(field, values)
// Make sure the overflow pointer is the last memory in the struct,
// because the runtime assumes it can use size-ptrSize as the
if !types.Haspointers(t.Val()) && !types.Haspointers(t.Key()) && t.Val().Width <= MAXVALSIZE && t.Key().Width <= MAXKEYSIZE {
otyp = types.Types[TUINTPTR]
}
- ovf := makefield("overflow", otyp)
- field = append(field, ovf)
+ overflow := makefield("overflow", otyp)
+ field = append(field, overflow)
// link up fields
bucket.SetNoalg(true)
bucket.SetFields(field[:])
dowidth(bucket)
+ // Check invariants that map code depends on.
+ if BUCKETSIZE < 8 {
+ Fatalf("bucket size too small for proper alignment")
+ }
+ if keytype.Align > BUCKETSIZE {
+ Fatalf("key align too big for %v", t)
+ }
+ if valtype.Align > BUCKETSIZE {
+ Fatalf("value align too big for %v", t)
+ }
+ if keytype.Width > MAXKEYSIZE {
+ Fatalf("key size to large for %v", t)
+ }
+ if valtype.Width > MAXVALSIZE {
+ Fatalf("value size to large for %v", t)
+ }
+ if t.Key().Width > MAXKEYSIZE && !keytype.IsPtr() {
+ Fatalf("key indirect incorrect for %v", t)
+ }
+ if t.Val().Width > MAXVALSIZE && !valtype.IsPtr() {
+ Fatalf("value indirect incorrect for %v", t)
+ }
+ if keytype.Width%int64(keytype.Align) != 0 {
+ Fatalf("key size not a multiple of key align for %v", t)
+ }
+ if valtype.Width%int64(valtype.Align) != 0 {
+ Fatalf("value size not a multiple of value align for %v", t)
+ }
+ if bucket.Align%keytype.Align != 0 {
+ Fatalf("bucket align not multiple of key align %v", t)
+ }
+ if bucket.Align%valtype.Align != 0 {
+ Fatalf("bucket align not multiple of value align %v", t)
+ }
+ if keys.Offset%int64(keytype.Align) != 0 {
+ Fatalf("bad alignment of keys in mapbucket for %v", t)
+ }
+ if values.Offset%int64(valtype.Align) != 0 {
+ Fatalf("bad alignment of values in mapbucket for %v", t)
+ }
+
// Double-check that overflow field is final memory in struct,
// with no padding at end. See comment above.
- if ovf.Offset != bucket.Width-int64(Widthptr) {
- Fatalf("bad math in mapbucket for %v", t)
+ if overflow.Offset != bucket.Width-int64(Widthptr) {
+ Fatalf("bad offset of overflow in mapbucket for %v", t)
}
t.MapType().Bucket = bucket
hmap.SetLocal(t.Local())
hmap.SetFields(fields)
dowidth(hmap)
+
+ // The size of hmap should be 48 bytes on 64 bit
+ // and 28 bytes on 32 bit platforms.
+ if size := int64(8 + 5*Widthptr); hmap.Width != size {
+ Fatalf("hmap size not correct: got %d, want %d", hmap.Width, size)
+ }
+
t.MapType().Hmap = hmap
hmap.StructType().Map = t
return 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")
}
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")
//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)
}