diff --git a/linkname.go b/linkname.go index 093c135..ef6600e 100644 --- a/linkname.go +++ b/linkname.go @@ -38,10 +38,23 @@ func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer //go:linkname addReflectOff reflect.addReflectOff func addReflectOff(ptr unsafe.Pointer) int32 +// resolveReflectType adds a *rtype to the reflection lookup map in the runtime. +// It returns a new typeOff that can be used to refer to the pointer. +func resolveReflectType(t *rtype) typeOff { + return typeOff(addReflectOff(unsafe.Pointer(t))) +} + +// resolveReflectText adds a function pointer to the reflection lookup map in +// the runtime. It returns a new textOff that can be used to refer to the +// pointer. +func resolveReflectText(ptr unsafe.Pointer) textOff { + return textOff(addReflectOff(ptr)) +} + // resolveReflectName adds a name to the reflection lookup map in the runtime. // It returns a new nameOff that can be used to refer to the pointer. func resolveReflectName(n name) nameOff { - return nameOff(addReflectOff(unsafe.Pointer(n.bytes))) + return nameOff(addReflectOff(unsafe.Pointer(n.Bytes))) } //go:linkname resolveNameOff reflect.resolveNameOff @@ -51,7 +64,7 @@ func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer func toType(t *rtype) reflect.Type func rtype_nameOff(t *rtype, off nameOff) name { - return name{bytes: (*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))} + return name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))} } func rtype_typeOff(t *rtype, off typeOff) *rtype { diff --git a/map.go b/map.go index 04c18ee..d7b61e2 100644 --- a/map.go +++ b/map.go @@ -3,29 +3,20 @@ package reflectx -import "unsafe" +import ( + "github.com/goplus/reflectx/internal/abi" +) -// mapType represents a map type. -type mapType struct { - rtype - key *rtype // map key type - elem *rtype // map element (value) type - bucket *rtype // internal bucket structure - // function for hashing keys (ptr to key, seed) -> hash - hasher func(unsafe.Pointer, uintptr) uintptr - keysize uint8 // size of key slot - valuesize uint8 // size of value slot - bucketsize uint16 // size of bucket - flags uint32 -} +// mapType is abi.MapType for the noswiss map implementation +type mapType = abi.MapType func cloneMap(st, ost *mapType) { - st.key = ost.key - st.elem = ost.elem - st.bucket = ost.bucket - st.hasher = ost.hasher - st.keysize = ost.keysize - st.valuesize = ost.valuesize - st.bucketsize = ost.bucketsize - st.flags = ost.flags + st.Key = ost.Key + st.Elem = ost.Elem + st.Bucket = ost.Bucket + st.Hasher = ost.Hasher + st.KeySize = ost.KeySize + st.ValueSize = ost.ValueSize + st.BucketSize = ost.BucketSize + st.Flags = ost.Flags } diff --git a/map_go124.go b/map_go124.go index bb85343..e0d33f9 100644 --- a/map_go124.go +++ b/map_go124.go @@ -3,28 +3,20 @@ package reflectx -import "unsafe" +import ( + "github.com/goplus/reflectx/internal/abi" +) -type mapType struct { - rtype - key *rtype - elem *rtype - group *rtype // internal type representing a slot group - // function for hashing keys (ptr to key, seed) -> hash - hasher func(unsafe.Pointer, uintptr) uintptr - groupSize uintptr // == Group.Size_ - slotSize uintptr // size of key/elem slot - elemOff uintptr // offset of elem in key/elem slot - flags uint32 -} +// mapType is abi.MapType for the swiss map implementation +type mapType = abi.MapType func cloneMap(st, ost *mapType) { - st.key = ost.key - st.elem = ost.elem - st.group = ost.group - st.hasher = ost.hasher - st.groupSize = ost.groupSize - st.slotSize = ost.slotSize - st.elemOff = ost.elemOff - st.flags = ost.flags + st.Key = ost.Key + st.Elem = ost.Elem + st.Group = ost.Group + st.Hasher = ost.Hasher + st.GroupSize = ost.GroupSize + st.SlotSize = ost.SlotSize + st.ElemOff = ost.ElemOff + st.Flags = ost.Flags } diff --git a/method.go b/method.go index eee5664..3a90fb8 100644 --- a/method.go +++ b/method.go @@ -180,9 +180,9 @@ func UpdateField(typ reflect.Type, rmap map[reflect.Type]reflect.Type) bool { } rt := totype(typ) st := toStructType(rt) - for i := 0; i < len(st.fields); i++ { - t := replaceType(toType(st.fields[i].typ), rmap) - st.fields[i].typ = totype(t) + for i := 0; i < len(st.Fields); i++ { + t := replaceType(toType(st.Fields[i].Typ), rmap) + st.Fields[i].Typ = totype(t) } return true } @@ -329,7 +329,7 @@ func SetInterfaceType(typ reflect.Type, embedded []reflect.Type, methods []refle }) rt := totype(typ) st := (*interfaceType)(toKindType(rt)) - st.methods = nil + st.Methods = nil var info []string var lastname string var unnamed bool @@ -347,14 +347,14 @@ func SetInterfaceType(typ reflect.Type, embedded []reflect.Type, methods []refle nm := newNameEx(m.Name, "", isexport, !isexport) mname = resolveReflectName(nm) if !isexport { - nm.setPkgPath(m.PkgPath) + setPkgPath(nm, m.PkgPath) } } else { mname = resolveReflectName(newName(m.Name, "", isexport)) } - st.methods = append(st.methods, imethod{ - name: mname, - typ: resolveReflectType(totype(m.Type)), + st.Methods = append(st.Methods, imethod{ + Name: mname, + Typ: resolveReflectType(totype(m.Type)), }) info = append(info, methodStr(m.Name, m.Type)) } @@ -387,7 +387,7 @@ func (ctx *Context) InterfaceOf(embedded []reflect.Type, methods []reflect.Metho }) rt, _ := newType("", "", tyEmptyInterface, 0, 0) st := (*interfaceType)(toKindType(rt)) - st.methods = nil + st.Methods = nil var info []string var lastname string for _, m := range methods { @@ -400,16 +400,16 @@ func (ctx *Context) InterfaceOf(embedded []reflect.Type, methods []reflect.Metho nm := newNameEx(m.Name, "", isexport, !isexport) mname = resolveReflectName(nm) if !isexport { - nm.setPkgPath(m.PkgPath) + setPkgPath(nm, m.PkgPath) } - st.methods = append(st.methods, imethod{ - name: mname, - typ: resolveReflectType(totype(m.Type)), + st.Methods = append(st.Methods, imethod{ + Name: mname, + Typ: resolveReflectType(totype(m.Type)), }) info = append(info, methodStr(m.Name, m.Type)) } - if len(st.methods) > 0 { - rt.equal = interequal + if len(st.Methods) > 0 { + rt.Equal = interequal } var str string if len(info) > 0 { @@ -420,7 +420,7 @@ func (ctx *Context) InterfaceOf(embedded []reflect.Type, methods []reflect.Metho if t, ok := ctx.interfceLookupCache[str]; ok { return t } - rt.str = resolveReflectName(newName(str, "", false)) + rt.Str = resolveReflectName(newName(str, "", false)) typ := toType(rt) ctx.interfceLookupCache[str] = typ return typ diff --git a/methodof.go b/methodof.go index 2a94b6b..a1fdba0 100644 --- a/methodof.go +++ b/methodof.go @@ -95,7 +95,7 @@ func (ctx *Context) registerMethod(info *abi.MethodInfo) (ifn unsafe.Pointer, al } func isMethod(typ reflect.Type) (ok bool) { - return totype(typ).tflag&tflagUserMethod != 0 + return totype(typ).TFlag&tflagUserMethod != 0 } type MethodInfo struct { @@ -113,11 +113,11 @@ type MethodInfo struct { } func MethodByIndex(typ reflect.Type, index int) reflect.Method { - return totype(typ).MethodX(index) + return rtypeMethodX(totype(typ), index) } func MethodByName(typ reflect.Type, name string) (m reflect.Method, ok bool) { - m, ok = totype(typ).MethodByNameX(name) + m, ok = rtypeMethodByNameX(totype(typ), name) return } @@ -127,10 +127,10 @@ func resizeMethod(typ reflect.Type, mcount int, xcount int) error { if ut == nil { return fmt.Errorf("not found uncommonType of %v", typ) } - if uint16(mcount) > ut.mcount { + if uint16(mcount) > ut.Mcount { return fmt.Errorf("too many methods of %v", typ) } - ut.xcount = uint16(xcount) + ut.Xcount = uint16(xcount) return nil } @@ -227,8 +227,8 @@ func (ctx *Context) setMethodSet(typ reflect.Type, methods []Method, sortMethods rt := totype(typ) prt := totype(ptyp) - ms := rt.methods() - pms := prt.methods() + ms := rtypeMethods(rt) + pms := rtypeMethods(prt) var onePtr bool switch typ.Kind() { @@ -252,7 +252,7 @@ func (ctx *Context) setMethodSet(typ reflect.Type, methods []Method, sortMethods isexport := methodIsExported(m.Name) nm := newNameEx(m.Name, "", isexport, !isexport) if !isexport { - nm.setPkgPath(m.PkgPath) + setPkgPath(nm, m.PkgPath) } mname := resolveReflectName(nm) mfn, inTyp, outTyp, mtyp, tfn, ptfn := createMethod(typ, ptyp, m, index) @@ -272,15 +272,15 @@ func (ctx *Context) setMethodSet(typ reflect.Type, methods []Method, sortMethods OnePtr: onePtr, FuncId: m.FuncId, } - pms[i].name = mname - pms[i].mtyp = mtyp - pms[i].tfn = ptfn + pms[i].Name = mname + pms[i].Mtyp = mtyp + pms[i].Tfn = ptfn var pifn unsafe.Pointer = zeroIfn hasIfn := ctx.hasImethod(typ, m) if hasIfn { pifn, _ = ctx.registerMethod(pinfo) } - pms[i].ifn = resolveReflectText(pifn) + pms[i].Ifn = resolveReflectText(pifn) if m.FuncId > 0 { if hasIfn { globalIfnCached++ @@ -308,10 +308,10 @@ func (ctx *Context) setMethodSet(typ reflect.Type, methods []Method, sortMethods globalIfnCached++ } } - ms[index].name = mname - ms[index].mtyp = mtyp - ms[index].tfn = tfn - ms[index].ifn = resolveReflectText(ifn) + ms[index].Name = mname + ms[index].Mtyp = mtyp + ms[index].Tfn = tfn + ms[index].Ifn = resolveReflectText(ifn) if m.FuncId > 0 { if hasIfn { globalIfnCached++ @@ -321,8 +321,8 @@ func (ctx *Context) setMethodSet(typ reflect.Type, methods []Method, sortMethods index++ } } - rt.tflag |= tflagUserMethod - prt.tflag |= tflagUserMethod + rt.TFlag |= tflagUserMethod + prt.TFlag |= tflagUserMethod if ctx.nAllocateError != 0 { ncap := abi.Default.Cap() @@ -342,10 +342,10 @@ func (ctx *Context) setMethodSet(typ reflect.Type, methods []Method, sortMethods func newMethodSet(styp reflect.Type, maxmfunc, maxpfunc int) reflect.Type { rt, _ := newType("", "", styp, maxmfunc, 0) prt, _ := newType("", "", PtrTo(styp), maxpfunc, 0) - rt.ptrToThis = resolveReflectType(prt) - (*ptrType)(unsafe.Pointer(prt)).elem = rt + rt.PtrToThis = resolveReflectType(prt) + (*ptrType)(unsafe.Pointer(prt)).Elem = rt setTypeName(rt, styp.PkgPath(), styp.Name()) - prt.uncommon().pkgPath = resolveReflectName(newName(styp.PkgPath(), "", false)) + prt.Uncommon().PkgPath = resolveReflectName(newName(styp.PkgPath(), "", false)) return toType(rt) } @@ -386,9 +386,9 @@ func argsTypeSize(typ reflect.Type, offset bool) (off uintptr) { for i := 0; i < numIn; i++ { t := typ.Field(i).Type targ := totype(t) - a := uintptr(targ.align) + a := uintptr(targ.Align_) off = (off + a - 1) &^ (a - 1) - n := targ.size + n := targ.Size_ if n == 0 { continue } diff --git a/name.go b/name.go index 88378c1..b12ffa2 100644 --- a/name.go +++ b/name.go @@ -2,65 +2,21 @@ package reflectx import "unsafe" -// name is an encoded type name with optional extra data. -// -// The first byte is a bit field containing: -// -// 1<<0 the name is exported -// 1<<1 tag data follows the name -// 1<<2 pkgPath nameOff follows the name and tag -// -// Following that, there is a varint-encoded length of the name, -// followed by the name itself. -// -// If tag data is present, it also has a varint-encoded length -// followed by the tag itself. -// -// If the import path follows, then 4 bytes at the end of -// the data form a nameOff. The import path is only set for concrete -// methods that are defined in a different package than their type. -// -// If a name starts with "*", then the exported bit represents -// whether the pointed to type is exported. -// -// Note: this encoding must match here and in: -// cmd/compile/internal/reflectdata/reflect.go -// runtime/type.go -// internal/reflectlite/type.go -// cmd/link/internal/ld/decodesym.go +// name is an alias to abi.Name (defined in type.go) +// Helper methods below mirror the original name methods. -type name struct { - bytes *byte +func nameData(n name, off int, whySafe string) *byte { + return (*byte)(add(unsafe.Pointer(n.Bytes), uintptr(off), whySafe)) } -func (n name) data(off int, whySafe string) *byte { - return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe)) +func nameHasTag(n name) bool { + return (*n.Bytes)&(1<<1) != 0 } -func (n name) isExported() bool { - return (*n.bytes)&(1<<0) != 0 -} - -// go1.19 -func (n name) embedded() bool { - return (*n.bytes)&(1<<3) != 0 -} - -// go1.19 -func (n name) setEmbedded() { - (*n.bytes) |= 1 << 3 -} - -func (n name) hasTag() bool { - return (*n.bytes)&(1<<1) != 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) { +func readVarint(n name, off int) (int, int) { v := 0 for i := 0; ; i++ { - x := *n.data(off+i, "read varint") + x := *nameData(n, off+i, "read varint") v += int(x&0x7f) << (7 * i) if x&0x80 == 0 { return i + 1, v @@ -83,59 +39,18 @@ func writeVarint(buf []byte, n int) int { } } -func (n name) name() (s string) { - if n.bytes == nil { - return - } - i, l := n.readVarint(1) - hdr := (*stringHeader)(unsafe.Pointer(&s)) - hdr.Data = unsafe.Pointer(n.data(1+i, "non-empty string")) - hdr.Len = l - return -} - -func (n name) tag() (s string) { - if !n.hasTag() { - return "" - } - i, l := n.readVarint(1) - i2, l2 := n.readVarint(1 + i + l) - hdr := (*stringHeader)(unsafe.Pointer(&s)) - hdr.Data = unsafe.Pointer(n.data(1+i+l+i2, "non-empty string")) - hdr.Len = l2 - return -} - -func (n name) pkgPath() string { - if n.bytes == nil || *n.data(0, "name flag field")&(1<<2) == 0 { - return "" - } - i, l := n.readVarint(1) - off := 1 + i + l - if n.hasTag() { - i2, l2 := n.readVarint(off) - off += i2 + l2 - } - var nameOff int32 - // Note that this field may not be aligned in memory, - // so we cannot use a direct int32 assignment here. - copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off, "name offset field")))[:]) - pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.bytes), nameOff))} - return pkgPathName.name() -} - -func (n name) setPkgPath(pkgpath string) { - if n.bytes == nil || *n.data(0, "name flag pkgPath")&(1<<2) == 0 { +func setPkgPath(n name, pkgpath string) { + if n.Bytes == nil || *nameData(n, 0, "name flag pkgPath")&(1<<2) == 0 { return } - i, l := n.readVarint(1) + i, l := readVarint(n, 1) off := 1 + i + l - if n.hasTag() { - i2, l2 := n.readVarint(off) + if nameHasTag(n) { + i2, l2 := readVarint(n, off) off += i2 + l2 } v := resolveReflectName(newName(pkgpath, "", false)) - copy((*[4]byte)(unsafe.Pointer(n.data(off, "name offset pkgPath")))[:], (*[4]byte)(unsafe.Pointer(&v))[:]) + copy((*[4]byte)(unsafe.Pointer(nameData(n, off, "name offset pkgPath")))[:], (*[4]byte)(unsafe.Pointer(&v))[:]) } func newNameEx(n, tag string, exported bool, pkgpath bool) name { @@ -174,7 +89,7 @@ func newNameEx(n, tag string, exported bool, pkgpath bool) name { copy(tb[tagLenLen:], tag) } - return name{bytes: &b[0]} + return name{Bytes: &b[0]} } func newName(n, tag string, exported bool) name { diff --git a/reflectx.go b/reflectx.go index dba2255..29c03d3 100644 --- a/reflectx.go +++ b/reflectx.go @@ -88,30 +88,30 @@ func setTypeName(t *rtype, pkgpath string, name string) { _, f := path.Split(pkgpath) name = f + "." + name } - t.tflag |= tflagNamed | tflagExtraStar - t.str = resolveReflectName(newName("*"+name, "", exported)) - if t.tflag&tflagUncommon == tflagUncommon { - toUncommonType(t).pkgPath = resolveReflectName(newName(pkgpath, "", false)) + t.TFlag |= tflagNamed | tflagExtraStar + t.Str = resolveReflectName(newName("*"+name, "", exported)) + if t.TFlag&tflagUncommon == tflagUncommon { + toUncommonType(t).PkgPath = resolveReflectName(newName(pkgpath, "", false)) } - switch t.Kind() { + switch reflect.Kind(t.Kind()) { case reflect.Struct: st := (*structType)(toKindType(t)) - st.pkgPath = newName(pkgpath, "", false) + st.PkgPath = newName(pkgpath, "", false) case reflect.Interface: st := (*interfaceType)(toKindType(t)) - st.pkgPath = newName(pkgpath, "", false) + st.PkgPath = newName(pkgpath, "", false) } } func copyType(dst *rtype, src *rtype) { - dst.size = src.size - dst.kind = src.kind - dst.equal = src.equal - dst.align = src.align - dst.fieldAlign = src.fieldAlign - dst.tflag = src.tflag - dst.gcdata = src.gcdata - dst.ptrdata = src.ptrdata + dst.Size_ = src.Size_ + dst.Kind_ = src.Kind_ + dst.Equal = src.Equal + dst.Align_ = src.Align_ + dst.FieldAlign_ = src.FieldAlign_ + dst.TFlag = src.TFlag + dst.GCData = src.GCData + dst.PtrBytes = src.PtrBytes } func isExported(name string) bool { @@ -169,10 +169,10 @@ func (ctx *Context) StructOf(fields []reflect.StructField) reflect.Type { rt := totype(typ) st := toStructType(rt) for _, i := range anonymous { - setEmbedded(&st.fields[i]) + setEmbedded(&st.Fields[i]) } for i, n := range underscore { - st.fields[i].name = n + st.Fields[i].Name = n } str := typ.String() if ts, ok := ctx.structLookupCache[str]; ok { @@ -186,15 +186,15 @@ func (ctx *Context) StructOf(fields []reflect.StructField) reflect.Type { ctx.structLookupCache[str] = []reflect.Type{typ} } // fix equal for blank fields and uncomparable type - if rt.equal != nil && underscoreCount > 0 { - rt.equal = func(p, q unsafe.Pointer) bool { - for i, ft := range st.fields { + if rt.Equal != nil && underscoreCount > 0 { + rt.Equal = func(p, q unsafe.Pointer) bool { + for i, ft := range st.Fields { if fields[i].Name == "_" { continue } - pi := add(p, ft.offset(), "&x.field safe") - qi := add(q, ft.offset(), "&x.field safe") - if !ft.typ.equal(pi, qi) { + pi := add(p, ft.Offset, "&x.field safe") + qi := add(q, ft.Offset, "&x.field safe") + if !ft.Typ.Equal(pi, qi) { return false } } @@ -202,20 +202,12 @@ func (ctx *Context) StructOf(fields []reflect.StructField) reflect.Type { } } - if rt.tflag == 0 && isRegularMemory(typ) { - rt.tflag |= tflagRegularMemory + if rt.TFlag == 0 && isRegularMemory(typ) { + rt.TFlag |= tflagRegularMemory } return typ } -// fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function. -func fnv1(x uint32, list string) uint32 { - for _, b := range list { - x = x*16777619 ^ uint32(b) - } - return x -} - func SetValue(v reflect.Value, x reflect.Value) { switch v.Kind() { case reflect.Bool: @@ -251,19 +243,19 @@ func SetElem(typ reflect.Type, elem reflect.Type) { switch typ.Kind() { case reflect.Ptr: st := (*ptrType)(toKindType(rt)) - st.elem = totype(elem) + st.Elem = totype(elem) case reflect.Slice: st := (*sliceType)(toKindType(rt)) - st.elem = totype(elem) + st.Elem = totype(elem) case reflect.Array: st := (*arrayType)(toKindType(rt)) - st.elem = totype(elem) + st.Elem = totype(elem) case reflect.Map: st := (*mapType)(toKindType(rt)) - st.elem = totype(elem) + st.Elem = totype(elem) case reflect.Chan: st := (*chanType)(toKindType(rt)) - st.elem = totype(elem) + st.Elem = totype(elem) default: panic("reflect: Elem of invalid type " + typ.String()) } @@ -298,15 +290,15 @@ func (ctx *replaceTypeContext) replace(pkg string, typ reflect.Type, m map[strin return } st := (*structType)(toKindType(rt)) - for i := 0; i < len(st.fields); i++ { - et := toType(st.fields[i].typ) + for i := 0; i < len(st.Fields); i++ { + et := toType(st.Fields[i].Typ) if t, ok := m[typeId(et)]; ok { - st.fields[i].typ = totype(t) + st.Fields[i].Typ = totype(t) changed = true } else { if rtyp, ok := ctx.replace(pkg, et, m); ok { changed = true - st.fields[i].typ = totype(rtyp) + st.Fields[i].Typ = totype(rtyp) } } } @@ -315,9 +307,9 @@ func (ctx *replaceTypeContext) replace(pkg string, typ reflect.Type, m map[strin } case reflect.Ptr: st := (*ptrType)(toKindType(rt)) - et := toType(st.elem) + et := toType(st.Elem) if t, ok := m[typeId(et)]; ok { - st.elem = totype(t) + st.Elem = totype(t) return reflect.PtrTo(t), true } else { if rtyp, ok := ctx.replace(pkg, et, m); ok { @@ -326,9 +318,9 @@ func (ctx *replaceTypeContext) replace(pkg string, typ reflect.Type, m map[strin } case reflect.Slice: st := (*sliceType)(toKindType(rt)) - et := toType(st.elem) + et := toType(st.Elem) if t, ok := m[typeId(et)]; ok { - st.elem = totype(t) + st.Elem = totype(t) return reflect.SliceOf(t), true } else { if rtyp, ok := ctx.replace(pkg, et, m); ok { @@ -337,19 +329,19 @@ func (ctx *replaceTypeContext) replace(pkg string, typ reflect.Type, m map[strin } case reflect.Array: st := (*arrayType)(toKindType(rt)) - et := toType(st.elem) + et := toType(st.Elem) if t, ok := m[typeId(et)]; ok { - st.elem = totype(t) - return reflect.ArrayOf(int(st.len), t), true + st.Elem = totype(t) + return reflect.ArrayOf(int(st.Len), t), true } else { if rtyp, ok := ctx.replace(pkg, et, m); ok { - return reflect.ArrayOf(int(st.len), rtyp), true + return reflect.ArrayOf(int(st.Len), rtyp), true } } case reflect.Map: st := (*mapType)(toKindType(rt)) - kt := toType(st.key) - et := toType(st.elem) + kt := toType(st.Key) + et := toType(st.Elem) if t, ok := m[typeId(kt)]; ok { kt = t changed = true @@ -373,9 +365,9 @@ func (ctx *replaceTypeContext) replace(pkg string, typ reflect.Type, m map[strin } case reflect.Chan: st := (*chanType)(toKindType(rt)) - et := toType(st.elem) + et := toType(st.Elem) if t, ok := m[typeId(et)]; ok { - st.elem = totype(t) + st.Elem = totype(t) return reflect.ChanOf(typ.ChanDir(), t), true } else { if rtyp, ok := ctx.replace(pkg, et, m); ok { @@ -384,8 +376,8 @@ func (ctx *replaceTypeContext) replace(pkg string, typ reflect.Type, m map[strin } case reflect.Func: st := (*funcType)(toKindType(rt)) - in := st.in() - out := st.out() + in := funcTypeIn(st) + out := funcTypeOut(st) for i := 0; i < len(in); i++ { et := toType(in[i]) if t, ok := m[typeId(et)]; ok { @@ -429,13 +421,13 @@ func (ctx *replaceTypeContext) replace(pkg string, typ reflect.Type, m map[strin return } st := (*interfaceType)(toKindType(rt)) - for i := 0; i < len(st.methods); i++ { + for i := 0; i < len(st.Methods); i++ { tt := typ.Method(i).Type if t, ok := m[typeId(tt)]; ok { - st.methods[i].typ = resolveReflectType(totype(t)) + st.Methods[i].Typ = resolveReflectType(totype(t)) changed = true } else if rtyp, ok := ctx.replace(pkg, tt, m); ok { - st.methods[i].typ = resolveReflectType(totype(rtyp)) + st.Methods[i].Typ = resolveReflectType(totype(rtyp)) changed = true } } diff --git a/rtype.go b/rtype.go index 46c3900..c6a7b02 100644 --- a/rtype.go +++ b/rtype.go @@ -15,48 +15,6 @@ func toKindType(t *rtype) unsafe.Pointer { return unsafe.Pointer(t) } -// uncommonType is present only for defined types or types with methods -// (if T is a defined type, the uncommonTypes for T and *T have methods). -// Using a pointer to this struct reduces the overall size required -// to describe a non-defined type with no methods. -type uncommonType struct { - pkgPath nameOff // import path; empty for built-in types like int, string - mcount uint16 // number of methods - xcount uint16 // number of exported methods - moff uint32 // offset from this uncommontype to [mcount]method - _ uint32 // unused -} - -type funcTypeFixed1 struct { - funcType - args [1]*rtype -} - -type funcTypeFixed4 struct { - funcType - args [4]*rtype -} -type funcTypeFixed8 struct { - funcType - args [8]*rtype -} -type funcTypeFixed16 struct { - funcType - args [16]*rtype -} -type funcTypeFixed32 struct { - funcType - args [32]*rtype -} -type funcTypeFixed64 struct { - funcType - args [64]*rtype -} -type funcTypeFixed128 struct { - funcType - args [128]*rtype -} - // emptyInterface is the header for an interface{} value. type emptyInterface struct { typ *rtype @@ -69,19 +27,19 @@ func totype(typ reflect.Type) *rtype { } //go:nocheckptr -func (t *uncommonType) methods() []method { - if t == nil || t.mcount == 0 { +func rtypeUncommonMethods(t *uncommonType) []method { + if t == nil || t.Mcount == 0 { return nil } - return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.mcount > 0"))[:t.mcount:t.mcount] + return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.Moff), "t.mcount > 0"))[:t.Mcount:t.Mcount] } //go:nocheckptr -func (t *uncommonType) exportedMethods() []method { - if t == nil || t.xcount == 0 { +func rtypeUncommonExportedMethods(t *uncommonType) []method { + if t == nil || t.Xcount == 0 { return nil } - return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.xcount > 0"))[:t.xcount:t.xcount] + return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.Moff), "t.xcount > 0"))[:t.Xcount:t.Xcount] } func tovalue(v *reflect.Value) *Value { @@ -92,77 +50,32 @@ func toValue(v Value) reflect.Value { return *(*reflect.Value)(unsafe.Pointer(&v)) } -func (t *rtype) uncommon() *uncommonType { +func rtypeUncommon(t *rtype) *uncommonType { return toUncommonType(t) } -func (t *rtype) exportedMethods() []method { - ut := t.uncommon() +func rtypeExportedMethods(t *rtype) []method { + ut := rtypeUncommon(t) if ut == nil { return nil } - return ut.exportedMethods() + return rtypeUncommonExportedMethods(ut) } -func (t *rtype) methods() []method { - ut := t.uncommon() +func rtypeMethods(t *rtype) []method { + ut := rtypeUncommon(t) if ut == nil { return nil } - return ut.methods() + return rtypeUncommonMethods(ut) } -func (t *funcType) in() []*rtype { - uadd := unsafe.Sizeof(*t) - if t.tflag&tflagUncommon != 0 { - uadd += unsafe.Sizeof(uncommonType{}) - } - if t.inCount == 0 { - return nil - } - return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.inCount:t.inCount] +func funcTypeIn(t *funcType) []*rtype { + return t.InSlice() } -func (t *funcType) out() []*rtype { - uadd := unsafe.Sizeof(*t) - if t.tflag&tflagUncommon != 0 { - uadd += unsafe.Sizeof(uncommonType{}) - } - outCount := t.outCount & (1<<15 - 1) - if outCount == 0 { - return nil - } - return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "outCount > 0"))[t.inCount : t.inCount+outCount : t.inCount+outCount] -} - -func (t *rtype) IsVariadic() bool { - if t.Kind() != reflect.Func { - panic("reflect: IsVariadic of non-func type " + toType(t).String()) - } - tt := (*funcType)(unsafe.Pointer(t)) - return tt.outCount&(1<<15) != 0 -} - -type bitVector struct { - n uint32 // number of bits - data []byte -} - -// funcType represents a function type. -// -// A *rtype for each in and out parameter is stored in an array that -// directly follows the funcType (and possibly its uncommonType). So -// a function type with one method, one input, and one output is: -// -// struct { -// funcType -// uncommonType -// [2]*rtype // [0] is in, [1] is out -// } -type funcType struct { - rtype - inCount uint16 - outCount uint16 // top bit is set if last input parameter is ... +func funcTypeOut(t *funcType) []*rtype { + return t.OutSlice() } type uncommonFuncType struct { @@ -183,30 +96,30 @@ func SetUnderlying(typ reflect.Type, styp reflect.Type) { case reflect.Struct: st := (*structType)(unsafe.Pointer(rt)) ost := (*structType)(unsafe.Pointer(ort)) - st.fields = ost.fields + st.Fields = ost.Fields case reflect.Ptr: st := (*ptrType)(unsafe.Pointer(rt)) ost := (*ptrType)(unsafe.Pointer(ort)) - st.elem = ost.elem + st.Elem = ost.Elem case reflect.Slice: st := (*sliceType)(unsafe.Pointer(rt)) ost := (*sliceType)(unsafe.Pointer(ort)) - st.elem = ost.elem + st.Elem = ost.Elem case reflect.Array: st := (*arrayType)(unsafe.Pointer(rt)) ost := (*arrayType)(unsafe.Pointer(ort)) - st.elem = ost.elem - st.slice = ost.slice - st.len = ost.len + st.Elem = ost.Elem + st.Slice = ost.Slice + st.Len = ost.Len case reflect.Chan: st := (*chanType)(unsafe.Pointer(rt)) ost := (*chanType)(unsafe.Pointer(ort)) - st.elem = ost.elem - st.dir = ost.dir + st.Elem = ost.Elem + st.Dir = ost.Dir case reflect.Interface: st := (*interfaceType)(unsafe.Pointer(rt)) ost := (*interfaceType)(unsafe.Pointer(ort)) - st.methods = ost.methods + st.Methods = ost.Methods case reflect.Map: st := (*mapType)(unsafe.Pointer(rt)) ost := (*mapType)(unsafe.Pointer(ort)) @@ -214,8 +127,8 @@ func SetUnderlying(typ reflect.Type, styp reflect.Type) { case reflect.Func: st := (*funcType)(unsafe.Pointer(rt)) ost := (*funcType)(unsafe.Pointer(ort)) - st.inCount = ost.inCount - st.outCount = ost.outCount + st.InCount = ost.InCount + st.OutCount = ost.OutCount numIn := typ.NumIn() numOut := typ.NumOut() narg := numIn + numOut @@ -230,17 +143,17 @@ func SetUnderlying(typ reflect.Type, styp reflect.Type) { } } } - rt.size = ort.size - rt.tflag |= tflagUncommon | tflagExtraStar | tflagNamed - rt.kind = ort.kind - rt.align = ort.align - rt.fieldAlign = ort.fieldAlign - rt.gcdata = ort.gcdata - rt.ptrdata = ort.ptrdata - rt.equal = ort.equal - //rt.str = resolveReflectName(ort.nameOff(ort.str)) + rt.Size_ = ort.Size_ + rt.TFlag |= tflagUncommon | tflagExtraStar | tflagNamed + rt.Kind_ = ort.Kind_ + rt.Align_ = ort.Align_ + rt.FieldAlign_ = ort.FieldAlign_ + rt.GCData = ort.GCData + rt.PtrBytes = ort.PtrBytes + rt.Equal = ort.Equal + //rt.Str = resolveReflectName(rtype_nameOff(ort, ort.Str)) if isRegularMemory(typ) { - rt.tflag |= tflagRegularMemory + rt.TFlag |= tflagRegularMemory } } @@ -259,7 +172,7 @@ func newType(pkg string, name string, styp reflect.Type, mcount int, xcount int) })) st := (*structType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr())) ost := (*structType)(unsafe.Pointer(ort)) - st.fields = ost.fields + st.Fields = ost.Fields case reflect.Ptr: tt = reflect.New(reflect.StructOf([]reflect.StructField{ {Name: "S", Type: reflect.TypeOf(ptrType{})}, @@ -267,7 +180,7 @@ func newType(pkg string, name string, styp reflect.Type, mcount int, xcount int) {Name: "M", Type: reflect.ArrayOf(mcount, reflect.TypeOf(method{}))}, })) st := (*ptrType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr())) - st.elem = totype(styp.Elem()) + st.Elem = totype(styp.Elem()) case reflect.Interface: tt = reflect.New(reflect.StructOf([]reflect.StructField{ {Name: "S", Type: reflect.TypeOf(interfaceType{})}, @@ -275,10 +188,10 @@ func newType(pkg string, name string, styp reflect.Type, mcount int, xcount int) })) st := (*interfaceType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr())) ost := (*interfaceType)(unsafe.Pointer(ort)) - for _, m := range ost.methods { - st.methods = append(st.methods, imethod{ - name: resolveReflectName(ost.nameOff(m.name)), - typ: resolveReflectType(ost.typeOff(m.typ)), + for _, m := range ost.Methods { + st.Methods = append(st.Methods, imethod{ + Name: resolveReflectName(rtype_nameOff(ort, m.Name)), + Typ: resolveReflectType(rtype_typeOff(ort, m.Typ)), }) } case reflect.Slice: @@ -288,7 +201,7 @@ func newType(pkg string, name string, styp reflect.Type, mcount int, xcount int) {Name: "M", Type: reflect.ArrayOf(mcount, reflect.TypeOf(method{}))}, })) st := (*sliceType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr())) - st.elem = totype(styp.Elem()) + st.Elem = totype(styp.Elem()) case reflect.Array: tt = reflect.New(reflect.StructOf([]reflect.StructField{ {Name: "S", Type: reflect.TypeOf(arrayType{})}, @@ -297,9 +210,9 @@ func newType(pkg string, name string, styp reflect.Type, mcount int, xcount int) })) st := (*arrayType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr())) ost := (*arrayType)(unsafe.Pointer(ort)) - st.elem = ost.elem - st.slice = ost.slice - st.len = ost.len + st.Elem = ost.Elem + st.Slice = ost.Slice + st.Len = ost.Len case reflect.Chan: tt = reflect.New(reflect.StructOf([]reflect.StructField{ {Name: "S", Type: reflect.TypeOf(chanType{})}, @@ -308,8 +221,8 @@ func newType(pkg string, name string, styp reflect.Type, mcount int, xcount int) })) st := (*chanType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr())) ost := (*chanType)(unsafe.Pointer(ort)) - st.elem = ost.elem - st.dir = ost.dir + st.Elem = ost.Elem + st.Dir = ost.Dir case reflect.Func: numIn := styp.NumIn() numOut := styp.NumOut() @@ -322,8 +235,8 @@ func newType(pkg string, name string, styp reflect.Type, mcount int, xcount int) })) st := (*funcType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr())) ost := (*funcType)(unsafe.Pointer(ort)) - st.inCount = ost.inCount - st.outCount = ost.outCount + st.InCount = ost.InCount + st.OutCount = ost.OutCount if narg > 0 { args := make([]*rtype, narg, narg) fnoff = uint32(unsafe.Sizeof((*rtype)(nil))) * uint32(narg) @@ -353,23 +266,23 @@ func newType(pkg string, name string, styp reflect.Type, mcount int, xcount int) })) } rt = (*rtype)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr())) - rt.size = ort.size - rt.tflag = ort.tflag | tflagUncommon - rt.kind = ort.kind - rt.align = ort.align - rt.fieldAlign = ort.fieldAlign - rt.gcdata = ort.gcdata - rt.ptrdata = ort.ptrdata - rt.equal = ort.equal - rt.str = resolveReflectName(ort.nameOff(ort.str)) + rt.Size_ = ort.Size_ + rt.TFlag = ort.TFlag | tflagUncommon + rt.Kind_ = ort.Kind_ + rt.Align_ = ort.Align_ + rt.FieldAlign_ = ort.FieldAlign_ + rt.GCData = ort.GCData + rt.PtrBytes = ort.PtrBytes + rt.Equal = ort.Equal + rt.Str = resolveReflectName(rtype_nameOff(ort, ort.Str)) ut := (*uncommonType)(unsafe.Pointer(tt.Elem().Field(1).UnsafeAddr())) - ut.mcount = uint16(mcount) - ut.xcount = uint16(xcount) - ut.moff = uint32(unsafe.Sizeof(uncommonType{})) + ut.Mcount = uint16(mcount) + ut.Xcount = uint16(xcount) + ut.Moff = uint32(unsafe.Sizeof(uncommonType{})) if skind == reflect.Interface { return rt, nil } else if skind == reflect.Func { - ut.moff += fnoff + ut.Moff += fnoff return rt, tt.Elem().Field(3).Slice(0, mcount).Interface().([]method) } return rt, tt.Elem().Field(2).Slice(0, mcount).Interface().([]method) @@ -442,73 +355,68 @@ func TypesByString(s string) []reflect.Type { func DumpType(w io.Writer, typ reflect.Type) { rt := totype(typ) fmt.Fprintf(w, "%#v\n", rt) - for _, m := range rt.methods() { - fmt.Fprintf(w, "%v %v (%v)\t\t%#v\n", - rt.nameOff(m.name).name(), - rt.nameOff(m.name).pkgPath(), - toType(rt.typeOff(m.mtyp)), + for _, m := range rtypeMethods(rt) { + fmt.Fprintf(w, "%v (%v)\t\t%#v\n", + rtype_nameOff(rt, m.Name).Name(), + toType(rtype_typeOff(rt, m.Mtyp)), m) } } func NumMethodX(typ reflect.Type) int { - return totype(typ).NumMethodX() + return len(rtypeMethods(totype(typ))) } func MethodX(typ reflect.Type, i int) reflect.Method { - return totype(typ).MethodX(i) -} - -func (t *rtype) NumMethodX() int { - return len(t.methods()) + return rtypeMethodX(totype(typ), i) } -func (t *rtype) MethodX(i int) (m reflect.Method) { - if t.Kind() == reflect.Interface { +func rtypeMethodX(t *rtype, i int) (m reflect.Method) { + if reflect.Kind(t.Kind()) == reflect.Interface { return toType(t).Method(i) } - methods := t.methods() + methods := rtypeMethods(t) if i < 0 || i >= len(methods) { panic("reflect: Method index out of range") } p := methods[i] - pname := t.nameOff(p.name) - m.Name = pname.name() + pname := rtype_nameOff(t, p.Name) + m.Name = pname.Name() m.Index = i fl := flag(reflect.Func) - if t.tflag&tflagUserMethod != 0 { + if t.TFlag&tflagUserMethod != 0 { fl |= flagIndir } - mtyp := t.typeOff(p.mtyp) + mtyp := rtype_typeOff(t, p.Mtyp) if mtyp == nil { return } ft := (*funcType)(unsafe.Pointer(mtyp)) - in := make([]reflect.Type, 0, 1+len(ft.in())) + in := make([]reflect.Type, 0, 1+len(funcTypeIn(ft))) in = append(in, toType(t)) - for _, arg := range ft.in() { + for _, arg := range funcTypeIn(ft) { in = append(in, toType(arg)) } - out := make([]reflect.Type, 0, len(ft.out())) - for _, ret := range ft.out() { + out := make([]reflect.Type, 0, len(funcTypeOut(ft))) + for _, ret := range funcTypeOut(ft) { out = append(out, toType(ret)) } mt := reflect.FuncOf(in, out, ft.IsVariadic()) m.Type = mt - tfn := t.textOff(p.tfn) + tfn := rtype_textOff(t, p.Tfn) fn := unsafe.Pointer(&tfn) m.Func = toValue(Value{totype(mt), fn, fl}) return m } -func (t *rtype) MethodByNameX(name string) (m reflect.Method, ok bool) { - if t.Kind() == reflect.Interface { +func rtypeMethodByNameX(t *rtype, name string) (m reflect.Method, ok bool) { + if reflect.Kind(t.Kind()) == reflect.Interface { return toType(t).MethodByName(name) } - if ut := t.uncommon(); ut != nil { - for i, p := range ut.methods() { - if t.nameOff(p.name).name() == name { - return t.MethodX(i), true + if ut := rtypeUncommon(t); ut != nil { + for i, p := range rtypeUncommonMethods(ut) { + if rtype_nameOff(t, p.Name).Name() == name { + return rtypeMethodX(t, i), true } } } @@ -521,27 +429,14 @@ func FieldX(v reflect.Value, i int) reflect.Value { mustBe("reflect.Value.Field", v, reflect.Struct) rv := tovalue(&v) tt := (*structType)(unsafe.Pointer(rv.typ)) - if uint(i) >= uint(len(tt.fields)) { + if uint(i) >= uint(len(tt.Fields)) { panic("reflect: Field index out of range") } - field := &tt.fields[i] - typ := field.typ + field := &tt.Fields[i] + typ := field.Typ // Inherit permission bits from v, but clear flagEmbedRO. - fl := rv.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind()) - // Using an unexported field forces flagRO. - // if !field.name.isExported() { - // if field.embedded() { - // fl |= flagEmbedRO - // } else { - // fl |= flagStickyRO - // } - // } - // Either flagIndir is set and v.ptr points at struct, - // or flagIndir is not set and v.ptr is the actual struct data. - // 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(rv.ptr, field.offset(), "same as non-reflect &v.field") + fl := rv.flag&(flagStickyRO|flagIndir|flagAddr) | flag(reflect.Kind(typ.Kind())) + ptr := add(rv.ptr, field.Offset, "same as non-reflect &v.field") return toValue(Value{typ, ptr, fl}) } diff --git a/structfield.go b/structfield.go index ebd228a..3a4b75f 100644 --- a/structfield.go +++ b/structfield.go @@ -1,20 +1,7 @@ package reflectx -// Struct field -type structField struct { - name name // name is always non-empty - typ *rtype // type of field - _offset uintptr // byte offset of field -} - -func (f *structField) offset() uintptr { - return f._offset -} - -func (f *structField) embedded() bool { - return f.name.embedded() -} +// structField is an alias to abi.StructField (defined in type.go) func setEmbedded(f *structField) { - f.name.setEmbedded() + (*f.Name.Bytes) |= 1 << 3 } diff --git a/type.go b/type.go index 1d8c80d..06dfeac 100644 --- a/type.go +++ b/type.go @@ -19,109 +19,42 @@ package reflectx import ( "reflect" "unsafe" -) - -func (t *rtype) nameOff(off nameOff) name { - return rtype_nameOff(t, off) -} - -func (t *rtype) typeOff(off typeOff) *rtype { - return rtype_typeOff(t, off) -} - -func (t *rtype) textOff(off textOff) unsafe.Pointer { - return rtype_textOff(t, off) -} - -// resolveReflectType adds a *rtype to the reflection lookup map in the runtime. -// It returns a new typeOff that can be used to refer to the pointer. -func resolveReflectType(t *rtype) typeOff { - return typeOff(addReflectOff(unsafe.Pointer(t))) -} - -// resolveReflectText adds a function pointer to the reflection lookup map in -// the runtime. It returns a new textOff that can be used to refer to the -// pointer. -func resolveReflectText(ptr unsafe.Pointer) textOff { - return textOff(addReflectOff(ptr)) -} -type nameOff int32 -type typeOff int32 -type textOff int32 + "github.com/goplus/reflectx/internal/abi" +) -// Method on non-interface type -type method struct { - name nameOff // name of method - mtyp typeOff // method type (without receiver) - ifn textOff // fn used in interface call (one-word receiver) - tfn textOff // fn used for normal method call -} +// Type aliases to internal/abi types +type rtype = abi.Type +type nameOff = abi.NameOff +type typeOff = abi.TypeOff +type textOff = abi.TextOff +type tflag = abi.TFlag +type method = abi.Method +type name = abi.Name +type imethod = abi.Imethod +type uncommonType = abi.UncommonType +type structField = abi.StructField +type arrayType = abi.ArrayType +type chanType = abi.ChanType +type interfaceType = abi.InterfaceType +type ptrType = abi.PtrType +type sliceType = abi.SliceType +type structType = abi.StructType +type funcType = abi.FuncType type structTypeUncommon struct { structType u uncommonType } -type tflag uint8 - const ( - // tflagUncommon means that there is a pointer, *uncommonType, - // just beyond the outer type structure. - // - // For example, if t.Kind() == Struct and t.tflag&tflagUncommon != 0, - // then t has uncommonType data and it can be accessed as: - // - // type tUncommon struct { - // structType - // u uncommonType - // } - // u := &(*tUncommon)(unsafe.Pointer(t)).u - tflagUncommon tflag = 1 << 0 - - // tflagExtraStar means the name in the str field has an - // extraneous '*' prefix. This is because for most types T in - // a program, the type *T also exists and reusing the str data - // saves binary size. - tflagExtraStar tflag = 1 << 1 - - // tflagNamed means the type has a name. - tflagNamed tflag = 1 << 2 - - // tflagRegularMemory means that equal and hash functions can treat - // this type as a single region of t.size bytes. - tflagRegularMemory tflag = 1 << 3 - - // tflagUserMethod means the type has reflctx user methods - tflagUserMethod tflag = 1 << 7 + tflagUncommon = abi.TFlagUncommon + tflagExtraStar = abi.TFlagExtraStar + tflagNamed = abi.TFlagNamed + tflagRegularMemory = abi.TFlagRegularMemory + tflagUserMethod tflag = 1 << 7 ) -type rtype struct { - size uintptr - ptrdata uintptr // number of bytes in the type that can contain pointers - hash uint32 // hash of type; avoids computation in hash tables - tflag tflag // extra type information flags - align uint8 // alignment of variable with this type - fieldAlign uint8 // alignment of struct field with this type - kind uint8 // enumeration for C - // function for comparing objects of this type - // (ptr to object A, ptr to object B) -> ==? - equal func(unsafe.Pointer, unsafe.Pointer) bool - gcdata *byte // garbage collection data - str nameOff // string form - ptrToThis typeOff // type for pointer to this type, may be zero -} - -const ( - kindDirectIface = 1 << 5 - kindGCProg = 1 << 6 // Type.gc points to GC program - kindMask = (1 << 5) - 1 -) - -func (t *rtype) Kind() reflect.Kind { - return reflect.Kind(t.kind & kindMask) -} - // add returns p+x. // // The whySafe string is ignored, so that the function still inlines @@ -148,53 +81,6 @@ const ( BothDir = RecvDir | SendDir // chan ) -// arrayType represents a fixed array type. -type arrayType struct { - rtype - elem *rtype // array element type - slice *rtype // slice type - len uintptr -} - -// chanType represents a channel type. -type chanType struct { - rtype - elem *rtype // channel element type - dir uintptr // channel direction (ChanDir) -} - -// imethod represents a method on an interface type -type imethod struct { - name nameOff // name of method - typ typeOff // .(*FuncType) underneath -} - -// interfaceType represents an interface type. -type interfaceType struct { - rtype - pkgPath name // import path - methods []imethod // sorted by hash -} - -// ptrType represents a pointer type. -type ptrType struct { - rtype - elem *rtype // pointer element (pointed at) type -} - -// sliceType represents a slice type. -type sliceType struct { - rtype - elem *rtype // slice element type -} - -// structType represents a struct type. -type structType struct { - rtype - pkgPath name - fields []structField // sorted by offset -} - // go/src/cmd/compile/internal/gc/alg.go#algtype1 // IsRegularMemory reports whether t can be compared/hashed as regular memory. func isRegularMemory(t reflect.Type) bool {