internal/runtime: cache rtypeList
This commit is contained in:
@@ -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),
|
||||
})
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user