aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/reflect/export_test.go18
-rw-r--r--src/reflect/type.go42
-rw-r--r--src/runtime/runtime1.go21
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,