diff options
author | Damian Gryski <[email protected]> | 2023-06-07 11:56:44 -0700 |
---|---|---|
committer | Ron Evans <[email protected]> | 2023-06-08 07:55:37 +0200 |
commit | 37849c4897755212e9e1874735a9d00f5f94896d (patch) | |
tree | ce335eff97b3ff498a36635b61b562592c706cd6 | |
parent | 213e73ad842e930c79856ebcc284e19890dc9774 (diff) | |
download | tinygo-37849c4897755212e9e1874735a9d00f5f94896d.tar.gz tinygo-37849c4897755212e9e1874735a9d00f5f94896d.zip |
compiler,reflect: use two bits of the meta byte for comparable/isBinary
Fixes #3683
-rw-r--r-- | compiler/interface.go | 10 | ||||
-rw-r--r-- | src/reflect/type.go | 61 |
2 files changed, 16 insertions, 55 deletions
diff --git a/compiler/interface.go b/compiler/interface.go index c491646e5..6a9e638b5 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -238,6 +238,16 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { c.interfaceTypes.Set(typ, global) } metabyte := getTypeKind(typ) + + // Precompute these so we don't have to calculate them at runtime. + if types.Comparable(typ) { + metabyte |= 1 << 6 + } + + if hashmapIsBinaryKey(typ) { + metabyte |= 1 << 7 + } + switch typ := typ.(type) { case *types.Basic: typeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))} diff --git a/src/reflect/type.go b/src/reflect/type.go index d27e39142..00b47a7e1 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -395,8 +395,10 @@ type Type interface { // Constants for the 'meta' byte. const ( - kindMask = 31 // mask to apply to the meta byte to get the Kind value - flagNamed = 32 // flag that is set if this is a named type + kindMask = 31 // mask to apply to the meta byte to get the Kind value + flagNamed = 32 // flag that is set if this is a named type + flagComparable = 64 // flag that is set if this type is comparable + flagIsBinary = 128 // flag that is set if this type uses the hashmap binary algorithm ) // The base type struct. All type structs start with this. @@ -940,63 +942,12 @@ func (t *rawType) Implements(u Type) bool { // Comparable returns whether values of this type can be compared to each other. func (t *rawType) Comparable() bool { - switch t.Kind() { - case Invalid: - return false - case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: - return true - case Float32, Float64, Complex64, Complex128: - return true - case String: - return true - case UnsafePointer: - return true - case Chan: - return true - case Interface: - return true - case Pointer: - return true - case Slice: - return false - case Array: - return t.elem().Comparable() - case Func: - return false - case Map: - return false - case Struct: - numField := t.NumField() - for i := 0; i < numField; i++ { - if !t.rawField(i).Type.Comparable() { - return false - } - } - return true - default: - panic(TypeError{"Comparable"}) - } + return (t.meta & flagComparable) == flagComparable } // isbinary() returns if the hashmapAlgorithmBinary functions can be used on this type func (t *rawType) isBinary() bool { - switch t.Kind() { - case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: - return true - case Pointer: - return true - case Array: - return t.elem().isBinary() - case Struct: - numField := t.NumField() - for i := 0; i < numField; i++ { - if !t.rawField(i).Type.isBinary() { - return false - } - } - return true - } - return false + return (t.meta & flagIsBinary) == flagIsBinary } func (t *rawType) ChanDir() ChanDir { |