From 1d3c98372ad4290af6702e56ba16692d4541f60a Mon Sep 17 00:00:00 2001 From: visualfc Date: Fri, 20 Dec 2024 20:44:39 +0800 Subject: [PATCH] internal/runtime: cache rtypeList --- internal/lib/reflect/makefunc.go | 6 +- internal/runtime/z_face.go | 8 ++ internal/runtime/z_type.go | 125 +++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 3 deletions(-) diff --git a/internal/lib/reflect/makefunc.go b/internal/lib/reflect/makefunc.go index 7cf19b17..e01f9b85 100644 --- a/internal/lib/reflect/makefunc.go +++ b/internal/lib/reflect/makefunc.go @@ -130,11 +130,11 @@ func makeMethodValue(op string, v Value) Value { // v.Type returns the actual type of the method value. ftyp := (*funcType)(unsafe.Pointer(v.Type().(*rtype))) ptyp := rtypeOf(unsafe.Pointer(uintptr(0))) - typ := runtime.Struct("", 2*unsafe.Sizeof(0), abi.StructField{ - Name_: "llgo_ctx", + typ := runtime.Struct(v.typ().Uncommon().PkgPath_, 2*unsafe.Sizeof(0), abi.StructField{ + Name_: "f", Typ: &ftyp.Type, }, abi.StructField{ - Name_: "f", + Name_: "data", Typ: ptyp, Offset: unsafe.Sizeof(0), }) diff --git a/internal/runtime/z_face.go b/internal/runtime/z_face.go index 6b007402..143d2c58 100644 --- a/internal/runtime/z_face.go +++ b/internal/runtime/z_face.go @@ -203,6 +203,9 @@ func setUncommon(ret *Type, methods []Method) { // Func returns a function type. func Func(in, out []*Type, variadic bool) *FuncType { + if t := rtypeList.findFunc(in, out, variadic); t != nil { + return t + } ret := &FuncType{ Type: Type{ Size_: 2 * unsafe.Sizeof(uintptr(0)), @@ -219,6 +222,7 @@ func Func(in, out []*Type, variadic bool) *FuncType { ret.TFlag |= abi.TFlagVariadic } ret.Str_ = funcStr(ret) + rtypeList.addType(&ret.Type) return ret } @@ -266,6 +270,9 @@ func InitNamedInterface(ret *InterfaceType, methods []Imethod) { } func Interface(pkgPath string, methods []Imethod) *InterfaceType { + if t := rtypeList.findInterface(pkgPath, methods); t != nil { + return t + } ret := &abi.InterfaceType{ Type: Type{ Size_: unsafe.Sizeof(eface{}), @@ -284,6 +291,7 @@ func Interface(pkgPath string, methods []Imethod) *InterfaceType { ret.Equal = interequal } ret.Str_ = interfaceStr(ret) + rtypeList.addType(&ret.Type) return ret } diff --git a/internal/runtime/z_type.go b/internal/runtime/z_type.go index 24fc4222..013e044b 100644 --- a/internal/runtime/z_type.go +++ b/internal/runtime/z_type.go @@ -148,6 +148,9 @@ func StructField(name string, typ *Type, off uintptr, tag string, embedded bool) // Struct returns a struct type. func Struct(pkgPath string, size uintptr, fields ...abi.StructField) *Type { + if t := rtypeList.findStruct(pkgPath, size, fields); t != nil { + return t + } ret := &abi.StructType{ Type: Type{ Size_: size, @@ -194,6 +197,7 @@ func Struct(pkgPath string, size uintptr, fields ...abi.StructField) *Type { if len(fields) == 1 && isDirectIface(fields[0].Typ) { ret.Kind_ |= abi.KindDirectIface } + rtypeList.addType(&ret.Type) return &ret.Type } @@ -248,6 +252,9 @@ func setPointer(ptr *abi.PtrType, elem *Type) { // SliceOf returns the slice type with element elem. func SliceOf(elem *Type) *Type { + if t := rtypeList.findElem(abi.Slice, elem, 0); t != nil { + return t + } ret := &abi.SliceType{ Type: Type{ Size_: unsafe.Sizeof([]int{}), @@ -260,11 +267,15 @@ func SliceOf(elem *Type) *Type { }, Elem: elem, } + rtypeList.addType(&ret.Type) return &ret.Type } // ArrayOf returns the array type with element elem and length. func ArrayOf(length uintptr, elem *Type) *Type { + if t := rtypeList.findElem(abi.Array, elem, length); t != nil { + return t + } ret := &abi.ArrayType{ Type: Type{ Size_: length * elem.Size_, @@ -303,10 +314,14 @@ func ArrayOf(length uintptr, elem *Type) *Type { if ret.Len == 1 && isDirectIface(ret.Elem) { ret.Kind_ |= abi.KindDirectIface } + rtypeList.addType(&ret.Type) return &ret.Type } func ChanOf(dir int, strChan string, elem *Type) *Type { + if t := rtypeList.findElem(abi.Chan, elem, uintptr(dir)); t != nil { + return t + } ret := &abi.ChanType{ Type: Type{ Size_: pointerSize, @@ -322,10 +337,14 @@ func ChanOf(dir int, strChan string, elem *Type) *Type { Elem: elem, Dir: abi.ChanDir(dir), } + rtypeList.addType(&ret.Type) return &ret.Type } func MapOf(key, elem *Type, bucket *Type, flags int) *Type { + if t := rtypeList.findMap(key, elem); t != nil { + return t + } ret := &abi.MapType{ Type: Type{ Size_: unsafe.Sizeof(uintptr(0)), @@ -347,6 +366,7 @@ func MapOf(key, elem *Type, bucket *Type, flags int) *Type { ret.Hasher = func(p unsafe.Pointer, seed uintptr) uintptr { return typehash(key, p, seed) } + rtypeList.addType(&ret.Type) return &ret.Type } @@ -436,6 +456,111 @@ func (r *rtypes) findNamed(pkgPath string, name string) *Type { return nil } +func (r *rtypes) findElem(kind abi.Kind, elem *Type, extra uintptr) *Type { + for _, typ := range r.types { + if typ.Kind() == kind && typ.Elem() == elem { + switch kind { + case abi.Chan: + if uintptr(typ.ChanDir()) == extra { + return typ + } + case abi.Array: + if uintptr(typ.Len()) == extra { + return typ + } + default: + return typ + } + } + } + return nil +} + +func (r *rtypes) findMap(key, elem *Type) *Type { + for _, typ := range r.types { + if typ.Kind() == abi.Map { + if mt := typ.MapType(); mt.Key == key && mt.Elem == elem { + return typ + } + } + } + return nil +} + +func eqFields(s1, s2 []abi.StructField) bool { + n := len(s1) + if n != len(s2) { + return false + } + for i := 0; i < n; i++ { + f1, f2 := s1[i], s2[i] + if f1.Name_ != f2.Name_ || f1.Embedded_ != f2.Embedded_ || f1.Typ != f2.Typ { + return false + } + } + return true +} + +func (r *rtypes) findStruct(pkgPath string, size uintptr, fields []abi.StructField) *Type { + for _, typ := range r.types { + if typ.Kind() == abi.Struct && typ.Size() == size { + if st := typ.StructType(); st.PkgPath_ == pkgPath && eqFields(st.Fields, fields) { + return typ + } + } + } + return nil +} + +func eqImethods(s1, s2 []Imethod) bool { + n := len(s1) + if n != len(s2) { + return false + } + for i := 0; i < n; i++ { + f1, f2 := s1[i], s2[i] + if f1.Name_ != f2.Name_ || f1.Typ_ != f2.Typ_ { + return false + } + } + return true +} + +func (r *rtypes) findInterface(pkgPath string, methods []Imethod) *abi.InterfaceType { + for _, typ := range r.types { + if typ.Kind() == abi.Interface { + if it := typ.InterfaceType(); it.PkgPath_ == pkgPath && eqImethods(it.Methods, methods) { + return it + } + } + } + return nil +} + +func eqTypes(s1, s2 []*Type) bool { + n := len(s1) + if n != len(s2) { + return false + } + for i := 0; i < n; i++ { + if s1[i] != s2[i] { + return false + } + } + return true +} + +func (r *rtypes) findFunc(in, out []*Type, variadic bool) *abi.FuncType { + for _, typ := range r.types { + if typ.Kind() == abi.Func { + if ft := typ.FuncType(); ft.Variadic() == variadic && eqTypes(ft.In, in) && eqTypes(ft.Out, out) { + return ft + } + } + } + return nil +} + func (r *rtypes) addType(typ *Type) { r.types = append(r.types, typ) }