internal/lib/reflect: makemap
This commit is contained in:
@@ -1463,6 +1463,79 @@ func funcStr(ft *funcType) string {
|
|||||||
return string(repr)
|
return string(repr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MapOf returns the map type with the given key and element types.
|
||||||
|
// For example, if k represents int and e represents string,
|
||||||
|
// MapOf(k, e) represents map[int]string.
|
||||||
|
//
|
||||||
|
// If the key type is not a valid map key type (that is, if it does
|
||||||
|
// not implement Go's == operator), MapOf panics.
|
||||||
|
func MapOf(key, elem Type) Type {
|
||||||
|
ktyp := key.common()
|
||||||
|
etyp := elem.common()
|
||||||
|
|
||||||
|
if ktyp.Equal == nil {
|
||||||
|
panic("reflect.MapOf: invalid key type " + stringFor(ktyp))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look in cache.
|
||||||
|
ckey := cacheKey{Map, ktyp, etyp, 0}
|
||||||
|
if mt, ok := lookupCache.Load(ckey); ok {
|
||||||
|
return mt.(Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look in known types.
|
||||||
|
s := "map[" + stringFor(ktyp) + "]" + stringFor(etyp)
|
||||||
|
// for _, tt := range typesByString(s) {
|
||||||
|
// mt := (*mapType)(unsafe.Pointer(tt))
|
||||||
|
// if mt.Key == ktyp && mt.Elem == etyp {
|
||||||
|
// ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
|
||||||
|
// return ti.(Type)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Make a map type.
|
||||||
|
// Note: flag values must match those used in the TMAP case
|
||||||
|
// in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
|
||||||
|
var imap any = (map[unsafe.Pointer]unsafe.Pointer)(nil)
|
||||||
|
mt := **(**mapType)(unsafe.Pointer(&imap))
|
||||||
|
mt.Str_ = s
|
||||||
|
mt.TFlag = 0
|
||||||
|
mt.Hash = fnv1(etyp.Hash, 'm', byte(ktyp.Hash>>24), byte(ktyp.Hash>>16), byte(ktyp.Hash>>8), byte(ktyp.Hash))
|
||||||
|
mt.Key = ktyp
|
||||||
|
mt.Elem = etyp
|
||||||
|
mt.Bucket = bucketOf(ktyp, etyp)
|
||||||
|
mt.Hasher = func(p unsafe.Pointer, seed uintptr) uintptr {
|
||||||
|
return typehash(ktyp, p, seed)
|
||||||
|
}
|
||||||
|
mt.Flags = 0
|
||||||
|
if ktyp.Size_ > maxKeySize {
|
||||||
|
mt.KeySize = uint8(goarch.PtrSize)
|
||||||
|
mt.Flags |= 1 // indirect key
|
||||||
|
} else {
|
||||||
|
mt.KeySize = uint8(ktyp.Size_)
|
||||||
|
}
|
||||||
|
if etyp.Size_ > maxValSize {
|
||||||
|
mt.ValueSize = uint8(goarch.PtrSize)
|
||||||
|
mt.Flags |= 2 // indirect value
|
||||||
|
} else {
|
||||||
|
mt.MapType.ValueSize = uint8(etyp.Size_)
|
||||||
|
}
|
||||||
|
mt.MapType.BucketSize = uint16(mt.Bucket.Size_)
|
||||||
|
if isReflexive(ktyp) {
|
||||||
|
mt.Flags |= 4
|
||||||
|
}
|
||||||
|
if needKeyUpdate(ktyp) {
|
||||||
|
mt.Flags |= 8
|
||||||
|
}
|
||||||
|
if hashMightPanic(ktyp) {
|
||||||
|
mt.Flags |= 16
|
||||||
|
}
|
||||||
|
mt.PtrToThis_ = nil
|
||||||
|
|
||||||
|
ti, _ := lookupCache.LoadOrStore(ckey, toRType(&mt.Type))
|
||||||
|
return ti.(Type)
|
||||||
|
}
|
||||||
|
|
||||||
// isReflexive reports whether the == operation on the type is reflexive.
|
// isReflexive reports whether the == operation on the type is reflexive.
|
||||||
// That is, x == x for all values x of type t.
|
// That is, x == x for all values x of type t.
|
||||||
func isReflexive(t *abi.Type) bool {
|
func isReflexive(t *abi.Type) bool {
|
||||||
|
|||||||
@@ -2297,9 +2297,9 @@ func (v Value) MapIndex(key Value) Value {
|
|||||||
} else {
|
} else {
|
||||||
k = unsafe.Pointer(&key.ptr)
|
k = unsafe.Pointer(&key.ptr)
|
||||||
}
|
}
|
||||||
e = mapaccess(v.typ(), v.pointer(), k)
|
var ok bool
|
||||||
// }
|
e, ok = mapaccess(v.typ(), v.pointer(), k)
|
||||||
if e == nil {
|
if !ok {
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
typ := tt.Elem
|
typ := tt.Elem
|
||||||
@@ -2519,7 +2519,7 @@ func (v Value) MapRange() *MapIter {
|
|||||||
|
|
||||||
// Force slow panicking path not inlined, so it won't add to the
|
// Force slow panicking path not inlined, so it won't add to the
|
||||||
// inlining budget of the caller.
|
// inlining budget of the caller.
|
||||||
// TODO: undo when the inliner is no longer bottom-up only.
|
// TODO undo when the inliner is no longer bottom-up only.
|
||||||
//
|
//
|
||||||
//go:noinline
|
//go:noinline
|
||||||
func (f flag) panicNotMap() {
|
func (f flag) panicNotMap() {
|
||||||
@@ -2587,11 +2587,14 @@ func chancap(ch unsafe.Pointer) int
|
|||||||
//go:linkname chanlen github.com/goplus/llgo/internal/runtime.ChanLen
|
//go:linkname chanlen github.com/goplus/llgo/internal/runtime.ChanLen
|
||||||
func chanlen(ch unsafe.Pointer) int
|
func chanlen(ch unsafe.Pointer) int
|
||||||
|
|
||||||
|
//go:linkname makemap github.com/goplus/llgo/internal/runtime.MakeMap
|
||||||
|
func makemap(t *abi.Type, cap int) (m unsafe.Pointer)
|
||||||
|
|
||||||
//go:linkname maplen github.com/goplus/llgo/internal/runtime.MapLen
|
//go:linkname maplen github.com/goplus/llgo/internal/runtime.MapLen
|
||||||
func maplen(ch unsafe.Pointer) int
|
func maplen(ch unsafe.Pointer) int
|
||||||
|
|
||||||
//go:linkname mapaccess github.com/goplus/llgo/internal/runtime.MapAccess1
|
//go:linkname mapaccess github.com/goplus/llgo/internal/runtime.MapAccess2
|
||||||
func mapaccess(t *abi.Type, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer)
|
func mapaccess(t *abi.Type, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer, ok bool)
|
||||||
|
|
||||||
//go:linkname mapassign0 github.com/goplus/llgo/internal/runtime.MapAssign
|
//go:linkname mapassign0 github.com/goplus/llgo/internal/runtime.MapAssign
|
||||||
func mapassign0(t *abi.Type, m unsafe.Pointer, key unsafe.Pointer) unsafe.Pointer
|
func mapassign0(t *abi.Type, m unsafe.Pointer, key unsafe.Pointer) unsafe.Pointer
|
||||||
@@ -2635,6 +2638,9 @@ func mapiternext(it *hiter)
|
|||||||
//go:linkname mapclear github.com/goplus/llgo/internal/runtime.mapclear
|
//go:linkname mapclear github.com/goplus/llgo/internal/runtime.mapclear
|
||||||
func mapclear(t *abi.Type, m unsafe.Pointer)
|
func mapclear(t *abi.Type, m unsafe.Pointer)
|
||||||
|
|
||||||
|
//go:linkname typehash github.com/goplus/llgo/internal/runtime.typehash
|
||||||
|
func typehash(t *abi.Type, p unsafe.Pointer, h uintptr) uintptr
|
||||||
|
|
||||||
// MakeSlice creates a new zero-initialized slice value
|
// MakeSlice creates a new zero-initialized slice value
|
||||||
// for the specified slice type, length, and capacity.
|
// for the specified slice type, length, and capacity.
|
||||||
func MakeSlice(typ Type, len, cap int) Value {
|
func MakeSlice(typ Type, len, cap int) Value {
|
||||||
@@ -2655,6 +2661,22 @@ func MakeSlice(typ Type, len, cap int) Value {
|
|||||||
return Value{&typ.(*rtype).t, unsafe.Pointer(&s), flagIndir | flag(Slice)}
|
return Value{&typ.(*rtype).t, unsafe.Pointer(&s), flagIndir | flag(Slice)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MakeMap creates a new map with the specified type.
|
||||||
|
func MakeMap(typ Type) Value {
|
||||||
|
return MakeMapWithSize(typ, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeMapWithSize creates a new map with the specified type
|
||||||
|
// and initial space for approximately n elements.
|
||||||
|
func MakeMapWithSize(typ Type, n int) Value {
|
||||||
|
if typ.Kind() != Map {
|
||||||
|
panic("reflect.MakeMapWithSize of non-map type")
|
||||||
|
}
|
||||||
|
t := typ.common()
|
||||||
|
m := makemap(t, n)
|
||||||
|
return Value{t, m, flag(Map)}
|
||||||
|
}
|
||||||
|
|
||||||
func ifaceE2I(t *abi.Type, src any, dst unsafe.Pointer) {
|
func ifaceE2I(t *abi.Type, src any, dst unsafe.Pointer) {
|
||||||
panic("todo: reflect.ifaceE2I")
|
panic("todo: reflect.ifaceE2I")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user