mirror of
https://github.com/golang/go
synced 2024-11-23 06:40:05 -07:00
cmd/compile,runtime,reflect: move embedded bit from offset to name
Previously we stole a bit from the field offset to encode whether a struct field was embedded. Instead, encode that bit in the name field, where we already have some unused bits to play with. The bit associates naturally with the name in any case. This leaves a full uintptr to specify field offsets. This will make the fix for #52740 cleaner. Change-Id: I0bfb85564dc26e8c18101bc8b432f332176d7836 Reviewed-on: https://go-review.googlesource.com/c/go/+/412138 Reviewed-by: Cherry Mui <cherryyz@google.com> Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
cb9bf93078
commit
e1e66a03a6
@ -412,7 +412,7 @@ func dimportpath(p *types.Pkg) {
|
||||
}
|
||||
|
||||
s := base.Ctxt.Lookup("type..importpath." + p.Prefix + ".")
|
||||
ot := dnameData(s, 0, p.Path, "", nil, false)
|
||||
ot := dnameData(s, 0, p.Path, "", nil, false, false)
|
||||
objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA)
|
||||
s.Set(obj.AttrContentAddressable, true)
|
||||
p.Pathsym = s
|
||||
@ -461,12 +461,12 @@ func dnameField(lsym *obj.LSym, ot int, spkg *types.Pkg, ft *types.Field) int {
|
||||
if !types.IsExported(ft.Sym.Name) && ft.Sym.Pkg != spkg {
|
||||
base.Fatalf("package mismatch for %v", ft.Sym)
|
||||
}
|
||||
nsym := dname(ft.Sym.Name, ft.Note, nil, types.IsExported(ft.Sym.Name))
|
||||
nsym := dname(ft.Sym.Name, ft.Note, nil, types.IsExported(ft.Sym.Name), ft.Embedded != 0)
|
||||
return objw.SymPtr(lsym, ot, nsym, 0)
|
||||
}
|
||||
|
||||
// dnameData writes the contents of a reflect.name into s at offset ot.
|
||||
func dnameData(s *obj.LSym, ot int, name, tag string, pkg *types.Pkg, exported bool) int {
|
||||
func dnameData(s *obj.LSym, ot int, name, tag string, pkg *types.Pkg, exported, embedded bool) int {
|
||||
if len(name) >= 1<<29 {
|
||||
base.Fatalf("name too long: %d %s...", len(name), name[:1024])
|
||||
}
|
||||
@ -491,6 +491,9 @@ func dnameData(s *obj.LSym, ot int, name, tag string, pkg *types.Pkg, exported b
|
||||
if pkg != nil {
|
||||
bits |= 1 << 2
|
||||
}
|
||||
if embedded {
|
||||
bits |= 1 << 3
|
||||
}
|
||||
b := make([]byte, l)
|
||||
b[0] = bits
|
||||
copy(b[1:], nameLen[:nameLenLen])
|
||||
@ -513,7 +516,7 @@ func dnameData(s *obj.LSym, ot int, name, tag string, pkg *types.Pkg, exported b
|
||||
var dnameCount int
|
||||
|
||||
// dname creates a reflect.name for a struct field or method.
|
||||
func dname(name, tag string, pkg *types.Pkg, exported bool) *obj.LSym {
|
||||
func dname(name, tag string, pkg *types.Pkg, exported, embedded bool) *obj.LSym {
|
||||
// Write out data as "type.." to signal two things to the
|
||||
// linker, first that when dynamically linking, the symbol
|
||||
// should be moved to a relro section, and second that the
|
||||
@ -538,11 +541,14 @@ func dname(name, tag string, pkg *types.Pkg, exported bool) *obj.LSym {
|
||||
sname = fmt.Sprintf(`%s"".%d`, sname, dnameCount)
|
||||
dnameCount++
|
||||
}
|
||||
if embedded {
|
||||
sname += ".embedded"
|
||||
}
|
||||
s := base.Ctxt.Lookup(sname)
|
||||
if len(s.P) > 0 {
|
||||
return s
|
||||
}
|
||||
ot := dnameData(s, 0, name, tag, pkg, exported)
|
||||
ot := dnameData(s, 0, name, tag, pkg, exported, embedded)
|
||||
objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA)
|
||||
s.Set(obj.AttrContentAddressable, true)
|
||||
return s
|
||||
@ -610,7 +616,7 @@ func dextratypeData(lsym *obj.LSym, ot int, t *types.Type) int {
|
||||
if !exported && a.name.Pkg != typePkg(t) {
|
||||
pkg = a.name.Pkg
|
||||
}
|
||||
nsym := dname(a.name.Name, "", pkg, exported)
|
||||
nsym := dname(a.name.Name, "", pkg, exported, false)
|
||||
|
||||
ot = objw.SymPtrOff(lsym, ot, nsym)
|
||||
ot = dmethodptrOff(lsym, ot, writeType(a.mtype))
|
||||
@ -775,7 +781,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int {
|
||||
}
|
||||
ot = objw.SymPtr(lsym, ot, gcsym, 0) // gcdata
|
||||
|
||||
nsym := dname(p, "", nil, exported)
|
||||
nsym := dname(p, "", nil, exported, false)
|
||||
ot = objw.SymPtrOff(lsym, ot, nsym) // str
|
||||
// ptrToThis
|
||||
if sptr == nil {
|
||||
@ -1074,7 +1080,7 @@ func writeType(t *types.Type) *obj.LSym {
|
||||
if !exported && a.name.Pkg != tpkg {
|
||||
pkg = a.name.Pkg
|
||||
}
|
||||
nsym := dname(a.name.Name, "", pkg, exported)
|
||||
nsym := dname(a.name.Name, "", pkg, exported, false)
|
||||
|
||||
ot = objw.SymPtrOff(lsym, ot, nsym)
|
||||
ot = objw.SymPtrOff(lsym, ot, writeType(a.type_))
|
||||
@ -1180,14 +1186,7 @@ func writeType(t *types.Type) *obj.LSym {
|
||||
// ../../../../runtime/type.go:/structField
|
||||
ot = dnameField(lsym, ot, spkg, f)
|
||||
ot = objw.SymPtr(lsym, ot, writeType(f.Type), 0)
|
||||
offsetAnon := uint64(f.Offset) << 1
|
||||
if offsetAnon>>1 != uint64(f.Offset) {
|
||||
base.Fatalf("%v: bad field offset for %s", t, f.Sym.Name)
|
||||
}
|
||||
if f.Embedded != 0 {
|
||||
offsetAnon |= 1
|
||||
}
|
||||
ot = objw.Uintptr(lsym, ot, offsetAnon)
|
||||
ot = objw.Uintptr(lsym, ot, uint64(f.Offset))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1356,7 +1355,7 @@ func WriteTabs() {
|
||||
// name nameOff
|
||||
// typ typeOff // pointer to symbol
|
||||
// }
|
||||
nsym := dname(p.Sym().Name, "", nil, true)
|
||||
nsym := dname(p.Sym().Name, "", nil, true, false)
|
||||
t := p.Type()
|
||||
if p.Class != ir.PFUNC {
|
||||
t = types.NewPtr(t)
|
||||
|
@ -132,6 +132,15 @@ func decodetypeName(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs
|
||||
return string(data[1+nameLenLen : 1+nameLenLen+int(nameLen)])
|
||||
}
|
||||
|
||||
func decodetypeNameEmbedded(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int) bool {
|
||||
r := decodeRelocSym(ldr, symIdx, relocs, int32(off))
|
||||
if r == 0 {
|
||||
return false
|
||||
}
|
||||
data := ldr.Data(r)
|
||||
return data[0]&(1<<3) != 0
|
||||
}
|
||||
|
||||
func decodetypeFuncInType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, i int) loader.Sym {
|
||||
uadd := commonsize(arch) + 4
|
||||
if arch.PtrSize == 8 {
|
||||
@ -204,12 +213,18 @@ func decodetypeStructFieldType(ldr *loader.Loader, arch *sys.Arch, symIdx loader
|
||||
return decodeRelocSym(ldr, symIdx, &relocs, int32(off+arch.PtrSize))
|
||||
}
|
||||
|
||||
func decodetypeStructFieldOffsAnon(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int64 {
|
||||
func decodetypeStructFieldOffset(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int64 {
|
||||
off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
|
||||
data := ldr.Data(symIdx)
|
||||
return int64(decodeInuxi(arch, data[off+2*arch.PtrSize:], arch.PtrSize))
|
||||
}
|
||||
|
||||
func decodetypeStructFieldEmbedded(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) bool {
|
||||
off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
|
||||
relocs := ldr.Relocs(symIdx)
|
||||
return decodetypeNameEmbedded(ldr, symIdx, &relocs, off)
|
||||
}
|
||||
|
||||
// decodetypeStr returns the contents of an rtype's str field (a nameOff).
|
||||
func decodetypeStr(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) string {
|
||||
relocs := ldr.Relocs(symIdx)
|
||||
|
@ -682,9 +682,9 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie {
|
||||
}
|
||||
fld := d.newdie(die, dwarf.DW_ABRV_STRUCTFIELD, f)
|
||||
d.newrefattr(fld, dwarf.DW_AT_type, d.defgotype(s))
|
||||
offsetAnon := decodetypeStructFieldOffsAnon(d.ldr, d.arch, gotype, i)
|
||||
newmemberoffsetattr(fld, int32(offsetAnon>>1))
|
||||
if offsetAnon&1 != 0 { // is embedded field
|
||||
offset := decodetypeStructFieldOffset(d.ldr, d.arch, gotype, i)
|
||||
newmemberoffsetattr(fld, int32(offset))
|
||||
if decodetypeStructFieldEmbedded(d.ldr, d.arch, gotype, i) {
|
||||
newattr(fld, dwarf.DW_AT_go_embedded_field, dwarf.DW_CLS_FLAG, 1, 0)
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ func Field(v Value, i int) Value {
|
||||
// In the former case, we want v.ptr + offset.
|
||||
// In the latter case, we must have field.offset = 0,
|
||||
// so v.ptr + field.offset is still the correct address.
|
||||
ptr := add(v.ptr, field.offset(), "same as non-reflect &v.field")
|
||||
ptr := add(v.ptr, field.offset, "same as non-reflect &v.field")
|
||||
return Value{typ, ptr, fl}
|
||||
}
|
||||
|
||||
|
@ -269,17 +269,13 @@ type sliceType struct {
|
||||
|
||||
// Struct field
|
||||
type structField struct {
|
||||
name name // name is always non-empty
|
||||
typ *rtype // type of field
|
||||
offsetEmbed uintptr // byte offset of field<<1 | isEmbedded
|
||||
}
|
||||
|
||||
func (f *structField) offset() uintptr {
|
||||
return f.offsetEmbed >> 1
|
||||
name name // name is always non-empty
|
||||
typ *rtype // type of field
|
||||
offset uintptr // byte offset of field
|
||||
}
|
||||
|
||||
func (f *structField) embedded() bool {
|
||||
return f.offsetEmbed&1 != 0
|
||||
return f.name.embedded()
|
||||
}
|
||||
|
||||
// structType represents a struct type.
|
||||
@ -328,6 +324,10 @@ func (n name) hasTag() bool {
|
||||
return (*n.bytes)&(1<<1) != 0
|
||||
}
|
||||
|
||||
func (n name) embedded() bool {
|
||||
return (*n.bytes)&(1<<3) != 0
|
||||
}
|
||||
|
||||
// readVarint parses a varint as encoded by encoding/binary.
|
||||
// It returns the number of encoded bytes and the encoded value.
|
||||
func (n name) readVarint(off int) (int, int) {
|
||||
@ -947,7 +947,10 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
|
||||
if cmpTags && tf.name.tag() != vf.name.tag() {
|
||||
return false
|
||||
}
|
||||
if tf.offsetEmbed != vf.offsetEmbed {
|
||||
if tf.offset != vf.offset {
|
||||
return false
|
||||
}
|
||||
if tf.embedded() != vf.embedded() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ func (a *abiSeq) regAssign(t *rtype, offset uintptr) bool {
|
||||
st := (*structType)(unsafe.Pointer(t))
|
||||
for i := range st.fields {
|
||||
f := &st.fields[i]
|
||||
if !a.regAssign(f.typ, offset+f.offset()) {
|
||||
if !a.regAssign(f.typ, offset+f.offset) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ func IsExported(t Type) bool {
|
||||
}
|
||||
|
||||
func ResolveReflectName(s string) {
|
||||
resolveReflectName(newName(s, "", false))
|
||||
resolveReflectName(newName(s, "", false, false))
|
||||
}
|
||||
|
||||
type Buffer struct {
|
||||
|
@ -433,17 +433,13 @@ type sliceType struct {
|
||||
|
||||
// Struct field
|
||||
type structField struct {
|
||||
name name // name is always non-empty
|
||||
typ *rtype // type of field
|
||||
offsetEmbed uintptr // byte offset of field<<1 | isEmbedded
|
||||
}
|
||||
|
||||
func (f *structField) offset() uintptr {
|
||||
return f.offsetEmbed >> 1
|
||||
name name // name is always non-empty
|
||||
typ *rtype // type of field
|
||||
offset uintptr // byte offset of field
|
||||
}
|
||||
|
||||
func (f *structField) embedded() bool {
|
||||
return f.offsetEmbed&1 != 0
|
||||
return f.name.embedded()
|
||||
}
|
||||
|
||||
// structType represents a struct type.
|
||||
@ -460,6 +456,7 @@ type structType struct {
|
||||
// 1<<0 the name is exported
|
||||
// 1<<1 tag data follows the name
|
||||
// 1<<2 pkgPath nameOff follows the name and tag
|
||||
// 1<<3 the name is of an embedded (a.k.a. anonymous) field
|
||||
//
|
||||
// Following that, there is a varint-encoded length of the name,
|
||||
// followed by the name itself.
|
||||
@ -496,6 +493,10 @@ func (n name) hasTag() bool {
|
||||
return (*n.bytes)&(1<<1) != 0
|
||||
}
|
||||
|
||||
func (n name) embedded() bool {
|
||||
return (*n.bytes)&(1<<3) != 0
|
||||
}
|
||||
|
||||
// readVarint parses a varint as encoded by encoding/binary.
|
||||
// It returns the number of encoded bytes and the encoded value.
|
||||
func (n name) readVarint(off int) (int, int) {
|
||||
@ -565,7 +566,7 @@ func (n name) pkgPath() string {
|
||||
return pkgPathName.name()
|
||||
}
|
||||
|
||||
func newName(n, tag string, exported bool) name {
|
||||
func newName(n, tag string, exported, embedded bool) name {
|
||||
if len(n) >= 1<<29 {
|
||||
panic("reflect.nameFrom: name too long: " + n[:1024] + "...")
|
||||
}
|
||||
@ -586,6 +587,9 @@ func newName(n, tag string, exported bool) name {
|
||||
l += tagLenLen + len(tag)
|
||||
bits |= 1 << 1
|
||||
}
|
||||
if embedded {
|
||||
bits |= 1 << 3
|
||||
}
|
||||
|
||||
b := make([]byte, l)
|
||||
b[0] = bits
|
||||
@ -1256,7 +1260,7 @@ func (t *structType) Field(i int) (f StructField) {
|
||||
if tag := p.name.tag(); tag != "" {
|
||||
f.Tag = StructTag(tag)
|
||||
}
|
||||
f.Offset = p.offset()
|
||||
f.Offset = p.offset
|
||||
|
||||
// NOTE(rsc): This is the only allocation in the interface
|
||||
// presented by a reflect.Type. It would be nice to avoid,
|
||||
@ -1472,7 +1476,7 @@ func (t *rtype) ptrTo() *rtype {
|
||||
prototype := *(**ptrType)(unsafe.Pointer(&iptr))
|
||||
pp := *prototype
|
||||
|
||||
pp.str = resolveReflectName(newName(s, "", false))
|
||||
pp.str = resolveReflectName(newName(s, "", false, false))
|
||||
pp.ptrToThis = 0
|
||||
|
||||
// For the type structures linked into the binary, the
|
||||
@ -1739,7 +1743,10 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
|
||||
if cmpTags && tf.name.tag() != vf.name.tag() {
|
||||
return false
|
||||
}
|
||||
if tf.offsetEmbed != vf.offsetEmbed {
|
||||
if tf.offset != vf.offset {
|
||||
return false
|
||||
}
|
||||
if tf.embedded() != vf.embedded() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -1891,7 +1898,7 @@ func ChanOf(dir ChanDir, t Type) Type {
|
||||
ch := *prototype
|
||||
ch.tflag = tflagRegularMemory
|
||||
ch.dir = uintptr(dir)
|
||||
ch.str = resolveReflectName(newName(s, "", false))
|
||||
ch.str = resolveReflectName(newName(s, "", false, false))
|
||||
ch.hash = fnv1(typ.hash, 'c', byte(dir))
|
||||
ch.elem = typ
|
||||
|
||||
@ -1934,7 +1941,7 @@ func MapOf(key, elem Type) Type {
|
||||
// in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
|
||||
var imap any = (map[unsafe.Pointer]unsafe.Pointer)(nil)
|
||||
mt := **(**mapType)(unsafe.Pointer(&imap))
|
||||
mt.str = resolveReflectName(newName(s, "", false))
|
||||
mt.str = resolveReflectName(newName(s, "", false, false))
|
||||
mt.tflag = 0
|
||||
mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash))
|
||||
mt.key = ktyp
|
||||
@ -2113,7 +2120,7 @@ func FuncOf(in, out []Type, variadic bool) Type {
|
||||
}
|
||||
|
||||
// Populate the remaining fields of ft and store in cache.
|
||||
ft.str = resolveReflectName(newName(str, "", false))
|
||||
ft.str = resolveReflectName(newName(str, "", false, false))
|
||||
ft.ptrToThis = 0
|
||||
return addToCache(&ft.rtype)
|
||||
}
|
||||
@ -2290,7 +2297,7 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
|
||||
gcdata: gcdata,
|
||||
}
|
||||
s := "bucket(" + ktyp.String() + "," + etyp.String() + ")"
|
||||
b.str = resolveReflectName(newName(s, "", false))
|
||||
b.str = resolveReflectName(newName(s, "", false, false))
|
||||
return b
|
||||
}
|
||||
|
||||
@ -2369,7 +2376,7 @@ func SliceOf(t Type) Type {
|
||||
prototype := *(**sliceType)(unsafe.Pointer(&islice))
|
||||
slice := *prototype
|
||||
slice.tflag = 0
|
||||
slice.str = resolveReflectName(newName(s, "", false))
|
||||
slice.str = resolveReflectName(newName(s, "", false, false))
|
||||
slice.hash = fnv1(typ.hash, '[')
|
||||
slice.elem = typ
|
||||
slice.ptrToThis = 0
|
||||
@ -2632,7 +2639,7 @@ func StructOf(fields []StructField) Type {
|
||||
typalign = ft.align
|
||||
}
|
||||
size = offset + ft.size
|
||||
f.offsetEmbed |= offset << 1
|
||||
f.offset = offset
|
||||
|
||||
if ft.size == 0 {
|
||||
lastzero = size
|
||||
@ -2698,7 +2705,7 @@ func StructOf(fields []StructField) Type {
|
||||
*typ = *prototype
|
||||
typ.fields = fs
|
||||
if pkgpath != "" {
|
||||
typ.pkgPath = newName(pkgpath, "", false)
|
||||
typ.pkgPath = newName(pkgpath, "", false, false)
|
||||
}
|
||||
|
||||
// Look in cache.
|
||||
@ -2742,7 +2749,7 @@ func StructOf(fields []StructField) Type {
|
||||
}
|
||||
}
|
||||
|
||||
typ.str = resolveReflectName(newName(str, "", false))
|
||||
typ.str = resolveReflectName(newName(str, "", false, false))
|
||||
typ.tflag = 0 // TODO: set tflagRegularMemory
|
||||
typ.hash = hash
|
||||
typ.size = size
|
||||
@ -2774,14 +2781,14 @@ func StructOf(fields []StructField) Type {
|
||||
continue
|
||||
}
|
||||
// Pad to start of this field with zeros.
|
||||
if ft.offset() > off {
|
||||
n := (ft.offset() - off) / goarch.PtrSize
|
||||
if ft.offset > off {
|
||||
n := (ft.offset - off) / goarch.PtrSize
|
||||
prog = append(prog, 0x01, 0x00) // emit a 0 bit
|
||||
if n > 1 {
|
||||
prog = append(prog, 0x81) // repeat previous bit
|
||||
prog = appendVarint(prog, n-1) // n-1 times
|
||||
}
|
||||
off = ft.offset()
|
||||
off = ft.offset
|
||||
}
|
||||
|
||||
prog = appendGCProg(prog, ft.typ)
|
||||
@ -2803,8 +2810,8 @@ func StructOf(fields []StructField) Type {
|
||||
if comparable {
|
||||
typ.equal = func(p, q unsafe.Pointer) bool {
|
||||
for _, ft := range typ.fields {
|
||||
pi := add(p, ft.offset(), "&x.field safe")
|
||||
qi := add(q, ft.offset(), "&x.field safe")
|
||||
pi := add(p, ft.offset, "&x.field safe")
|
||||
qi := add(q, ft.offset, "&x.field safe")
|
||||
if !ft.typ.equal(pi, qi) {
|
||||
return false
|
||||
}
|
||||
@ -2841,16 +2848,11 @@ func runtimeStructField(field StructField) (structField, string) {
|
||||
}
|
||||
}
|
||||
|
||||
offsetEmbed := uintptr(0)
|
||||
if field.Anonymous {
|
||||
offsetEmbed |= 1
|
||||
}
|
||||
|
||||
resolveReflectType(field.Type.common()) // install in runtime
|
||||
f := structField{
|
||||
name: newName(field.Name, string(field.Tag), field.IsExported()),
|
||||
typ: field.Type.common(),
|
||||
offsetEmbed: offsetEmbed,
|
||||
name: newName(field.Name, string(field.Tag), field.IsExported(), field.Anonymous),
|
||||
typ: field.Type.common(),
|
||||
offset: 0,
|
||||
}
|
||||
return f, field.PkgPath
|
||||
}
|
||||
@ -2874,7 +2876,7 @@ func typeptrdata(t *rtype) uintptr {
|
||||
return 0
|
||||
}
|
||||
f := st.fields[field]
|
||||
return f.offset() + f.typ.ptrdata
|
||||
return f.offset + f.typ.ptrdata
|
||||
|
||||
default:
|
||||
panic("reflect.typeptrdata: unexpected type, " + t.String())
|
||||
@ -2917,7 +2919,7 @@ func ArrayOf(length int, elem Type) Type {
|
||||
prototype := *(**arrayType)(unsafe.Pointer(&iarray))
|
||||
array := *prototype
|
||||
array.tflag = typ.tflag & tflagRegularMemory
|
||||
array.str = resolveReflectName(newName(s, "", false))
|
||||
array.str = resolveReflectName(newName(s, "", false, false))
|
||||
array.hash = fnv1(typ.hash, '[')
|
||||
for n := uint32(length); n > 0; n >>= 8 {
|
||||
array.hash = fnv1(array.hash, byte(n))
|
||||
@ -3097,7 +3099,7 @@ func funcLayout(t *funcType, rcvr *rtype) (frametype *rtype, framePool *sync.Poo
|
||||
} else {
|
||||
s = "funcargs(" + t.String() + ")"
|
||||
}
|
||||
x.str = resolveReflectName(newName(s, "", false))
|
||||
x.str = resolveReflectName(newName(s, "", false, false))
|
||||
|
||||
// cache result for future callers
|
||||
framePool = &sync.Pool{New: func() any {
|
||||
@ -3165,7 +3167,7 @@ func addTypeBits(bv *bitVector, offset uintptr, t *rtype) {
|
||||
tt := (*structType)(unsafe.Pointer(t))
|
||||
for i := range tt.fields {
|
||||
f := &tt.fields[i]
|
||||
addTypeBits(bv, offset+f.offset(), f.typ)
|
||||
addTypeBits(bv, offset+f.offset, f.typ)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1287,7 +1287,7 @@ func (v Value) Field(i int) Value {
|
||||
// In the former case, we want v.ptr + offset.
|
||||
// In the latter case, we must have field.offset = 0,
|
||||
// so v.ptr + field.offset is still the correct address.
|
||||
ptr := add(v.ptr, field.offset(), "same as non-reflect &v.field")
|
||||
ptr := add(v.ptr, field.offset, "same as non-reflect &v.field")
|
||||
return Value{typ, ptr, fl}
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
|
||||
if f.name.isBlank() {
|
||||
continue
|
||||
}
|
||||
h = typehash(f.typ, add(p, f.offset()), h)
|
||||
h = typehash(f.typ, add(p, f.offset), h)
|
||||
}
|
||||
return h
|
||||
default:
|
||||
|
@ -536,7 +536,7 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
|
||||
if f.typ.ptrdata == 0 {
|
||||
continue
|
||||
}
|
||||
cgoCheckArg(f.typ, add(p, f.offset()), true, top, msg)
|
||||
cgoCheckArg(f.typ, add(p, f.offset), true, top, msg)
|
||||
}
|
||||
case kindPtr, kindUnsafePointer:
|
||||
if indir {
|
||||
|
@ -174,7 +174,7 @@ func (p *abiDesc) tryRegAssignArg(t *_type, offset uintptr) bool {
|
||||
st := (*structtype)(unsafe.Pointer(t))
|
||||
for i := range st.fields {
|
||||
f := &st.fields[i]
|
||||
if !p.tryRegAssignArg(f.typ, offset+f.offset()) {
|
||||
if !p.tryRegAssignArg(f.typ, offset+f.offset) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -414,13 +414,9 @@ type ptrtype struct {
|
||||
}
|
||||
|
||||
type structfield struct {
|
||||
name name
|
||||
typ *_type
|
||||
offsetAnon uintptr
|
||||
}
|
||||
|
||||
func (f *structfield) offset() uintptr {
|
||||
return f.offsetAnon >> 1
|
||||
name name
|
||||
typ *_type
|
||||
offset uintptr
|
||||
}
|
||||
|
||||
type structtype struct {
|
||||
@ -443,6 +439,10 @@ func (n name) isExported() bool {
|
||||
return (*n.bytes)&(1<<0) != 0
|
||||
}
|
||||
|
||||
func (n name) isEmbedded() bool {
|
||||
return (*n.bytes)&(1<<3) != 0
|
||||
}
|
||||
|
||||
func (n name) readvarint(off int) (int, int) {
|
||||
v := 0
|
||||
for i := 0; ; i++ {
|
||||
@ -703,7 +703,10 @@ func typesEqual(t, v *_type, seen map[_typePair]struct{}) bool {
|
||||
if tf.name.tag() != vf.name.tag() {
|
||||
return false
|
||||
}
|
||||
if tf.offsetAnon != vf.offsetAnon {
|
||||
if tf.offset != vf.offset {
|
||||
return false
|
||||
}
|
||||
if tf.name.isEmbedded() != vf.name.isEmbedded() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user