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
// actual type structure
// type commonType struct {
// size uintptr
+ // ptrsize uintptr
// hash uint32
// _ uint8
// align uint8
// 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
}
}
+// 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
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 {
// 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
}
// 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
}
// 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 + ")"
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
// 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 {
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