]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile,runtime,reflect: move embedded bit from offset to name
authorKeith Randall <khr@golang.org>
Tue, 14 Jun 2022 20:38:02 +0000 (13:38 -0700)
committerKeith Randall <khr@google.com>
Tue, 14 Jun 2022 23:22:11 +0000 (23:22 +0000)
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>
13 files changed:
src/cmd/compile/internal/reflectdata/reflect.go
src/cmd/link/internal/ld/decodesym.go
src/cmd/link/internal/ld/dwarf.go
src/internal/reflectlite/export_test.go
src/internal/reflectlite/type.go
src/reflect/abi.go
src/reflect/export_test.go
src/reflect/type.go
src/reflect/value.go
src/runtime/alg.go
src/runtime/cgocall.go
src/runtime/syscall_windows.go
src/runtime/type.go

index 3ffb7dcefa7059018166aecfaaaa87633bcd65e1..21301ab1499e3a7c856c62ad3577b74a773bb550 100644 (file)
@@ -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)
index a6ae202859e81dd3a480240ffb51ce32ff4752f9..b0f4b875633ce068a176ee55e6a05497e7e0b52f 100644 (file)
@@ -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)
index 6ed9697aec43e9037405eb4bfbc6e9a5d0cf8811..c42511ea3f04c1e2698b27851a49a97daf18e355 100644 (file)
@@ -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)
                        }
                }
index 3e5c258fb177b9c55ebe237b51fa442231222270..e9a928bdc6a9abe6ec64588d14ec744093edcd77 100644 (file)
@@ -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}
 }
 
index bc6fc947738f4fbc19b898b37260be9c5e787b81..21e3c1278d0423f14f20b656bd48df425a38e96b 100644 (file)
@@ -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
                        }
                }
index 9957d237689043c04bffadca718be687ac9d9403..32cb314188704c05230e561c63ddff09c7ac5d98 100644 (file)
@@ -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
                        }
                }
index a5a3c1c27103c8cf6ebde103160e8740948de1c3..f7d2cc362d5875885d0c5ae300c6e1e47d09e561 100644 (file)
@@ -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 {
index 97040b51887bd4f7b0b944e61f9be0c111ab29ac..7b8cf0ee621aa841f849b44f119edf9c237fb1d7 100644 (file)
@@ -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)
                }
        }
 }
index 5abdca28207abc446d06ca4dcdb5892452bcc943..74554a3ac80be920990b0881d0ad68ec0961767b 100644 (file)
@@ -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}
 }
 
index 5d7d1c77f4dbe3b3e32c2d0d82cb1332968df456..2a413eeef352ce54835c39880f8ee55386a6a2fa 100644 (file)
@@ -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:
index 977d049378e13611de54e39f745b38e71a6ac67a..892654ed5b1a4a551346e42dc4bd62ff4a0935fc 100644 (file)
@@ -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 {
index a841a31a27e0f1c6f4aa687d2a5e4ec08d699922..e42d71ad65e2852864f5f6d8424fb88e3ced1b91 100644 (file)
@@ -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
                        }
                }
index b650d6d79598195fcd5f13314d086044aa49d80b..e8e7819ecfe6cd218262f18aa8afe3b5604ba86f 100644 (file)
@@ -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
                        }
                }