"io"
"math"
"math/rand"
+ "net"
"os"
. "reflect"
"reflect/internal/example1"
}
}
}
+
+func TestInitFuncTypes(t *testing.T) {
+ n := 100
+ var wg sync.WaitGroup
+
+ wg.Add(n)
+ for i := 0; i < n; i++ {
+ go func() {
+ defer wg.Done()
+ ipT := TypeOf(net.IP{})
+ for i := 0; i < ipT.NumMethod(); i++ {
+ _ = ipT.Method(i)
+ }
+ }()
+ }
+ wg.Wait()
+}
var funcTypes []Type
var funcTypesMutex sync.Mutex
-func initFuncTypes(n int) {
+func initFuncTypes(n int) Type {
funcTypesMutex.Lock()
defer funcTypesMutex.Unlock()
- if n < len(funcTypes) {
- if funcTypes[n] != nil {
- return
- }
- } else {
- newFuncTypes := make([]Type, n+1)
- copy(newFuncTypes, funcTypes)
- funcTypes = newFuncTypes
+ if n < len(funcTypes) && funcTypes[n] != nil {
+ return funcTypes[n]
}
+ newFuncTypes := make([]Type, n+1)
+ copy(newFuncTypes, funcTypes)
+ funcTypes = newFuncTypes
funcTypes[n] = StructOf([]StructField{
{
Name: "FuncType",
Type: ArrayOf(n, TypeOf(&rtype{})),
},
})
+ return funcTypes[n]
}
// FuncOf returns the function type with the given argument and result types.
prototype := *(**funcType)(unsafe.Pointer(&ifunc))
n := len(in) + len(out)
- var ft *funcType
- var args []*rtype
- if n <= 128 {
- initFuncTypes(n)
- o := New(funcTypes[n]).Elem()
- ft = (*funcType)(unsafe.Pointer(o.Field(0).Addr().Pointer()))
- args = unsafe.Slice((**rtype)(unsafe.Pointer(o.Field(1).Addr().Pointer())), n)[0:0:n]
- } else {
+ if n > 128 {
panic("reflect.FuncOf: too many arguments")
}
+ o := New(initFuncTypes(n)).Elem()
+ ft := (*funcType)(unsafe.Pointer(o.Field(0).Addr().Pointer()))
+ args := unsafe.Slice((**rtype)(unsafe.Pointer(o.Field(1).Addr().Pointer())), n)[0:0:n]
*ft = *prototype
// Build a hash and minimally populate ft.