internal/runtime: cache rtypeList

This commit is contained in:
visualfc
2024-12-20 20:44:39 +08:00
parent c1588d70cd
commit 1d3c98372a
3 changed files with 136 additions and 3 deletions

View File

@@ -130,11 +130,11 @@ func makeMethodValue(op string, v Value) Value {
// v.Type returns the actual type of the method value. // v.Type returns the actual type of the method value.
ftyp := (*funcType)(unsafe.Pointer(v.Type().(*rtype))) ftyp := (*funcType)(unsafe.Pointer(v.Type().(*rtype)))
ptyp := rtypeOf(unsafe.Pointer(uintptr(0))) ptyp := rtypeOf(unsafe.Pointer(uintptr(0)))
typ := runtime.Struct("", 2*unsafe.Sizeof(0), abi.StructField{ typ := runtime.Struct(v.typ().Uncommon().PkgPath_, 2*unsafe.Sizeof(0), abi.StructField{
Name_: "llgo_ctx", Name_: "f",
Typ: &ftyp.Type, Typ: &ftyp.Type,
}, abi.StructField{ }, abi.StructField{
Name_: "f", Name_: "data",
Typ: ptyp, Typ: ptyp,
Offset: unsafe.Sizeof(0), Offset: unsafe.Sizeof(0),
}) })

View File

@@ -203,6 +203,9 @@ func setUncommon(ret *Type, methods []Method) {
// Func returns a function type. // Func returns a function type.
func Func(in, out []*Type, variadic bool) *FuncType { func Func(in, out []*Type, variadic bool) *FuncType {
if t := rtypeList.findFunc(in, out, variadic); t != nil {
return t
}
ret := &FuncType{ ret := &FuncType{
Type: Type{ Type: Type{
Size_: 2 * unsafe.Sizeof(uintptr(0)), Size_: 2 * unsafe.Sizeof(uintptr(0)),
@@ -219,6 +222,7 @@ func Func(in, out []*Type, variadic bool) *FuncType {
ret.TFlag |= abi.TFlagVariadic ret.TFlag |= abi.TFlagVariadic
} }
ret.Str_ = funcStr(ret) ret.Str_ = funcStr(ret)
rtypeList.addType(&ret.Type)
return ret return ret
} }
@@ -266,6 +270,9 @@ func InitNamedInterface(ret *InterfaceType, methods []Imethod) {
} }
func Interface(pkgPath string, methods []Imethod) *InterfaceType { func Interface(pkgPath string, methods []Imethod) *InterfaceType {
if t := rtypeList.findInterface(pkgPath, methods); t != nil {
return t
}
ret := &abi.InterfaceType{ ret := &abi.InterfaceType{
Type: Type{ Type: Type{
Size_: unsafe.Sizeof(eface{}), Size_: unsafe.Sizeof(eface{}),
@@ -284,6 +291,7 @@ func Interface(pkgPath string, methods []Imethod) *InterfaceType {
ret.Equal = interequal ret.Equal = interequal
} }
ret.Str_ = interfaceStr(ret) ret.Str_ = interfaceStr(ret)
rtypeList.addType(&ret.Type)
return ret return ret
} }

View File

@@ -148,6 +148,9 @@ func StructField(name string, typ *Type, off uintptr, tag string, embedded bool)
// Struct returns a struct type. // Struct returns a struct type.
func Struct(pkgPath string, size uintptr, fields ...abi.StructField) *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{ ret := &abi.StructType{
Type: Type{ Type: Type{
Size_: size, Size_: size,
@@ -194,6 +197,7 @@ func Struct(pkgPath string, size uintptr, fields ...abi.StructField) *Type {
if len(fields) == 1 && isDirectIface(fields[0].Typ) { if len(fields) == 1 && isDirectIface(fields[0].Typ) {
ret.Kind_ |= abi.KindDirectIface ret.Kind_ |= abi.KindDirectIface
} }
rtypeList.addType(&ret.Type)
return &ret.Type return &ret.Type
} }
@@ -248,6 +252,9 @@ func setPointer(ptr *abi.PtrType, elem *Type) {
// SliceOf returns the slice type with element elem. // SliceOf returns the slice type with element elem.
func SliceOf(elem *Type) *Type { func SliceOf(elem *Type) *Type {
if t := rtypeList.findElem(abi.Slice, elem, 0); t != nil {
return t
}
ret := &abi.SliceType{ ret := &abi.SliceType{
Type: Type{ Type: Type{
Size_: unsafe.Sizeof([]int{}), Size_: unsafe.Sizeof([]int{}),
@@ -260,11 +267,15 @@ func SliceOf(elem *Type) *Type {
}, },
Elem: elem, Elem: elem,
} }
rtypeList.addType(&ret.Type)
return &ret.Type return &ret.Type
} }
// ArrayOf returns the array type with element elem and length. // ArrayOf returns the array type with element elem and length.
func ArrayOf(length uintptr, elem *Type) *Type { func ArrayOf(length uintptr, elem *Type) *Type {
if t := rtypeList.findElem(abi.Array, elem, length); t != nil {
return t
}
ret := &abi.ArrayType{ ret := &abi.ArrayType{
Type: Type{ Type: Type{
Size_: length * elem.Size_, Size_: length * elem.Size_,
@@ -303,10 +314,14 @@ func ArrayOf(length uintptr, elem *Type) *Type {
if ret.Len == 1 && isDirectIface(ret.Elem) { if ret.Len == 1 && isDirectIface(ret.Elem) {
ret.Kind_ |= abi.KindDirectIface ret.Kind_ |= abi.KindDirectIface
} }
rtypeList.addType(&ret.Type)
return &ret.Type return &ret.Type
} }
func ChanOf(dir int, strChan string, elem *Type) *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{ ret := &abi.ChanType{
Type: Type{ Type: Type{
Size_: pointerSize, Size_: pointerSize,
@@ -322,10 +337,14 @@ func ChanOf(dir int, strChan string, elem *Type) *Type {
Elem: elem, Elem: elem,
Dir: abi.ChanDir(dir), Dir: abi.ChanDir(dir),
} }
rtypeList.addType(&ret.Type)
return &ret.Type return &ret.Type
} }
func MapOf(key, elem *Type, bucket *Type, flags int) *Type { func MapOf(key, elem *Type, bucket *Type, flags int) *Type {
if t := rtypeList.findMap(key, elem); t != nil {
return t
}
ret := &abi.MapType{ ret := &abi.MapType{
Type: Type{ Type: Type{
Size_: unsafe.Sizeof(uintptr(0)), 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 { ret.Hasher = func(p unsafe.Pointer, seed uintptr) uintptr {
return typehash(key, p, seed) return typehash(key, p, seed)
} }
rtypeList.addType(&ret.Type)
return &ret.Type return &ret.Type
} }
@@ -436,6 +456,111 @@ func (r *rtypes) findNamed(pkgPath string, name string) *Type {
return nil 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) { func (r *rtypes) addType(typ *Type) {
r.types = append(r.types, typ) r.types = append(r.types, typ)
} }