Commit 98a9d368 authored by Austin Clements's avatar Austin Clements

runtime: add pointer size to type structure

This adds a field to the runtime type structure that records the size
of the prefix of objects of that type containing pointers. Any data
after this offset is scalar data.

This is necessary for shrinking the type bitmaps to 1 bit and will
help the garbage collector efficiently estimate the amount of heap
that needs to be scanned.

Change-Id: I1318d79e6360dca0ac980245016c562e61f52ff5
Reviewed-on: https://go-review.googlesource.com/9691Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 91938fd1
......@@ -676,12 +676,64 @@ func haspointers(t *Type) bool {
fallthrough
default:
ret = true
case TFIELD:
Fatal("haspointers: unexpected type, %v", t)
}
t.Haspointers = 1 + uint8(obj.Bool2int(ret))
return ret
}
// typeptrsize returns the length in bytes of the prefix of t
// containing pointer data. Anything after this offset is scalar data.
func typeptrsize(t *Type) uint64 {
if !haspointers(t) {
return 0
}
switch t.Etype {
case TPTR32,
TPTR64,
TUNSAFEPTR,
TFUNC,
TCHAN,
TMAP:
return uint64(Widthptr)
case TSTRING:
// struct { byte *str; intgo len; }
return uint64(Widthptr)
case TINTER:
// struct { Itab *tab; void *data; } or
// struct { Type *type; void *data; }
return 2 * uint64(Widthptr)
case TARRAY:
if Isslice(t) {
// struct { byte *array; uintgo len; uintgo cap; }
return uint64(Widthptr)
}
// haspointers already eliminated t.Bound == 0.
return uint64(t.Bound-1)*uint64(t.Type.Width) + typeptrsize(t.Type)
case TSTRUCT:
// Find the last field that has pointers.
var lastPtrField *Type
for t1 := t.Type; t1 != nil; t1 = t1.Down {
if haspointers(t1.Type) {
lastPtrField = t1
}
}
return uint64(lastPtrField.Width) + typeptrsize(lastPtrField.Type)
default:
Fatal("typeptrsize: unexpected type, %v", t)
return 0
}
}
/*
* commonType
* ../../runtime/type.go:/commonType
......@@ -728,6 +780,7 @@ func dcommontype(s *Sym, ot int, t *Type) int {
// actual type structure
// type commonType struct {
// size uintptr
// ptrsize uintptr
// hash uint32
// _ uint8
// align uint8
......@@ -741,6 +794,7 @@ func dcommontype(s *Sym, ot int, t *Type) int {
// zero unsafe.Pointer
// }
ot = duintptr(s, ot, uint64(t.Width))
ot = duintptr(s, ot, typeptrsize(t))
ot = duint32(s, ot, typehash(t))
ot = duint8(s, ot, 0) // unused
......
......@@ -41,23 +41,25 @@ func decode_inuxi(p []byte, sz int) uint64 {
}
}
// commonsize returns the size of the common prefix for all type
// structures (runtime._type).
func commonsize() int {
return 8*Thearch.Ptrsize + 8
return 9*Thearch.Ptrsize + 8
}
// Type.commonType.kind
func decodetype_kind(s *LSym) uint8 {
return uint8(s.P[1*Thearch.Ptrsize+7] & obj.KindMask) // 0x13 / 0x1f
return uint8(s.P[2*Thearch.Ptrsize+7] & obj.KindMask) // 0x13 / 0x1f
}
// Type.commonType.kind
func decodetype_noptr(s *LSym) uint8 {
return uint8(s.P[1*Thearch.Ptrsize+7] & obj.KindNoPointers) // 0x13 / 0x1f
return uint8(s.P[2*Thearch.Ptrsize+7] & obj.KindNoPointers) // 0x13 / 0x1f
}
// Type.commonType.kind
func decodetype_usegcprog(s *LSym) uint8 {
return uint8(s.P[1*Thearch.Ptrsize+7] & obj.KindGCProg) // 0x13 / 0x1f
return uint8(s.P[2*Thearch.Ptrsize+7] & obj.KindGCProg) // 0x13 / 0x1f
}
// Type.commonType.size
......@@ -72,11 +74,11 @@ func decodetype_gcprog(s *LSym) *LSym {
x := "type..gcprog." + s.Name[5:]
return Linklookup(Ctxt, x, 0)
}
return decode_reloc_sym(s, 1*int32(Thearch.Ptrsize)+8+2*int32(Thearch.Ptrsize))
return decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+2*int32(Thearch.Ptrsize))
}
func decodetype_gcprog_shlib(s *LSym) uint64 {
return decode_inuxi(s.P[1*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize):], Thearch.Ptrsize)
return decode_inuxi(s.P[2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize):], Thearch.Ptrsize)
}
func decodetype_gcmask(s *LSym) []byte {
......@@ -85,7 +87,7 @@ func decodetype_gcmask(s *LSym) []byte {
// of gcmask for types defined in that shared library.
return s.gcmask
}
mask := decode_reloc_sym(s, 1*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize))
mask := decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize))
return mask.P
}
......
......@@ -246,6 +246,7 @@ const (
// so that code cannot convert from, say, *arrayType to *ptrType.
type rtype struct {
size uintptr
ptrsize uintptr
hash uint32 // hash of type; avoids computation in hash tables
_ uint8 // unused/padding
align uint8 // alignment of variable with this type
......@@ -1825,12 +1826,14 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
}
// overflow
gc.append(bitsPointer)
tptrsize := gc.size
if runtime.GOARCH == "amd64p32" {
gc.append(bitsScalar)
}
b := new(rtype)
b.size = gc.size
b.ptrsize = tptrsize
b.kind = kind
b.gc[0], _ = gc.finalize()
s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
......@@ -1917,6 +1920,9 @@ func ArrayOf(count int, elem Type) Type {
panic("reflect.ArrayOf: array size would exceed virtual address space")
}
array.size = typ.size * uintptr(count)
if count > 0 && typ.ptrsize != 0 {
array.ptrsize = typ.size*uintptr(count-1) + typ.ptrsize
}
array.align = typ.align
array.fieldAlign = typ.fieldAlign
array.uncommonType = nil
......@@ -2084,6 +2090,7 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
// build dummy rtype holding gc program
x := new(rtype)
x.size = gc.size
x.ptrsize = gc.size // over-approximation
var hasPtr bool
x.gc[0], hasPtr = gc.finalize()
if !hasPtr {
......
......@@ -8,9 +8,12 @@ package runtime
import "unsafe"
// Needs to be in sync with ../../cmd/internal/ld/decodesym.go:/^commonsize and pkg/reflect/type.go:/type.
// Needs to be in sync with ../cmd/internal/ld/decodesym.go:/^func.commonsize,
// ../cmd/internal/gc/reflect.go:/^func.dcommontype and
// ../reflect/type.go:/^type.rtype.
type _type struct {
size uintptr
ptrsize uintptr // Bytes of prefix containing pointer slots.
hash uint32
_unused uint8
align uint8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment