aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDamian Gryski <[email protected]>2023-06-07 11:56:44 -0700
committerRon Evans <[email protected]>2023-06-08 07:55:37 +0200
commit37849c4897755212e9e1874735a9d00f5f94896d (patch)
treece335eff97b3ff498a36635b61b562592c706cd6
parent213e73ad842e930c79856ebcc284e19890dc9774 (diff)
downloadtinygo-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.go10
-rw-r--r--src/reflect/type.go61
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 {