diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/reflect/export_test.go | 18 | ||||
| -rw-r--r-- | src/reflect/type.go | 42 | ||||
| -rw-r--r-- | src/runtime/runtime1.go | 21 |
3 files changed, 51 insertions, 30 deletions
diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go index 51b57c780c..4ecdb1ef2e 100644 --- a/src/reflect/export_test.go +++ b/src/reflect/export_test.go @@ -72,15 +72,21 @@ func FuncLayout(t Type, rcvr Type) (frametype Type, argSize, retOffset uintptr, } func TypeLinks() []string { + first, rest := compiledTypelinks() + var r []string - sections, offset := typelinks() - for i, offs := range offset { - rodata := sections[i] - for _, off := range offs { - typ := (*rtype)(resolveTypeOff(rodata, off)) - r = append(r, typ.String()) + + addTypes := func(types []*abi.Type) { + for _, typ := range types { + r = append(r, stringFor(typ)) } } + + addTypes(first) + for _, rt := range rest { + addTypes(rt) + } + return r } diff --git a/src/reflect/type.go b/src/reflect/type.go index c58bbaa26d..47233af1a2 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -1710,26 +1710,16 @@ func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool { return false } -// typelinks is implemented in package runtime. -// It returns a slice of the sections in each module, -// and a slice of *rtype offsets in each module. -// -// The types in each module are sorted by string. That is, the first -// two linked types of the first module are: -// -// d0 := sections[0] -// t1 := (*rtype)(add(d0, offset[0][0])) -// t2 := (*rtype)(add(d0, offset[0][1])) -// -// and -// -// t1.String() < t2.String() +// compiledTypelinks is implemented in package runtime. +// It returns the types defined by the first module, +// and a slice of types defined in any other modules. +// Each slice of types is sorted by string. // // Note that strings are not unique identifiers for types: // there can be more than one with a given string. // Only types we might want to look up are included: // pointers, channels, maps, slices, and arrays. -func typelinks() (sections []unsafe.Pointer, offset [][]int32) +func compiledTypelinks() ([]*abi.Type, [][]*abi.Type) // rtypeOff should be an internal detail, // but widely used packages access it using linkname. @@ -1744,7 +1734,7 @@ func rtypeOff(section unsafe.Pointer, off int32) *abi.Type { return (*abi.Type)(add(section, uintptr(off), "sizeof(rtype) > 0")) } -// typesByString returns the subslice of typelinks() whose elements have +// typesByString returns all known types whose elements have // the given string representation. // It may be empty (no known types with that string) or may have // multiple elements (multiple types with that string). @@ -1760,19 +1750,17 @@ func rtypeOff(section unsafe.Pointer, off int32) *abi.Type { // //go:linkname typesByString func typesByString(s string) []*abi.Type { - sections, offset := typelinks() + first, rest := compiledTypelinks() var ret []*abi.Type - for offsI, offs := range offset { - section := sections[offsI] - + searchTypes := func(types []*abi.Type) { // We are looking for the first index i where the string becomes >= s. // This is a copy of sort.Search, with f(h) replaced by (*typ[h].String() >= s). - i, j := 0, len(offs) + i, j := 0, len(types) for i < j { h := int(uint(i+j) >> 1) // avoid overflow when computing h // i ≤ h < j - if !(stringFor(rtypeOff(section, offs[h])) >= s) { + if !(stringFor(types[h]) >= s) { i = h + 1 // preserves f(i-1) == false } else { j = h // preserves f(j) == true @@ -1783,14 +1771,20 @@ func typesByString(s string) []*abi.Type { // Having found the first, linear scan forward to find the last. // We could do a second binary search, but the caller is going // to do a linear scan anyway. - for j := i; j < len(offs); j++ { - typ := rtypeOff(section, offs[j]) + for j := i; j < len(types); j++ { + typ := types[j] if stringFor(typ) != s { break } ret = append(ret, typ) } } + + searchTypes(first) + for _, r := range rest { + searchTypes(r) + } + return ret } diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index 10754eee1c..8da3682261 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "internal/bytealg" "internal/goarch" "internal/runtime/atomic" @@ -627,6 +628,9 @@ func releasem(mp *m) { // Do not remove or change the type signature. // See go.dev/issue/67401. // +// This is obsolete and only remains for external packages. +// New code should use reflect_compiledTypelinks. +// //go:linkname reflect_typelinks reflect.typelinks func reflect_typelinks() ([]unsafe.Pointer, [][]int32) { modules := activeModules() @@ -649,6 +653,23 @@ func reflect_typelinks() ([]unsafe.Pointer, [][]int32) { return sections, ret } +// reflect_compiledTypelinks returns the typelink types +// generated by the compiler for all current modules. +// The normal case is a single module, so this returns one +// slice for the main module, and a slice of slices, normally nil, +// for other modules. +// +//go:linkname reflect_compiledTypelinks reflect.compiledTypelinks +func reflect_compiledTypelinks() ([]*abi.Type, [][]*abi.Type) { + modules := activeModules() + firstTypes := moduleTypelinks(modules[0]) + var rest [][]*abi.Type + for _, md := range modules[1:] { + rest = append(rest, moduleTypelinks(md)) + } + return firstTypes, rest +} + // reflect_resolveNameOff resolves a name offset from a base pointer. // // reflect_resolveNameOff is for package reflect, |
