Skip to content

Commit 37849c4

Browse files
dgryskideadprogram
authored andcommitted
compiler,reflect: use two bits of the meta byte for comparable/isBinary
Fixes #3683
1 parent 213e73a commit 37849c4

File tree

2 files changed

+16
-55
lines changed

2 files changed

+16
-55
lines changed

compiler/interface.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,16 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
238238
c.interfaceTypes.Set(typ, global)
239239
}
240240
metabyte := getTypeKind(typ)
241+
242+
// Precompute these so we don't have to calculate them at runtime.
243+
if types.Comparable(typ) {
244+
metabyte |= 1 << 6
245+
}
246+
247+
if hashmapIsBinaryKey(typ) {
248+
metabyte |= 1 << 7
249+
}
250+
241251
switch typ := typ.(type) {
242252
case *types.Basic:
243253
typeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))}

src/reflect/type.go

Lines changed: 6 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,10 @@ type Type interface {
395395

396396
// Constants for the 'meta' byte.
397397
const (
398-
kindMask = 31 // mask to apply to the meta byte to get the Kind value
399-
flagNamed = 32 // flag that is set if this is a named type
398+
kindMask = 31 // mask to apply to the meta byte to get the Kind value
399+
flagNamed = 32 // flag that is set if this is a named type
400+
flagComparable = 64 // flag that is set if this type is comparable
401+
flagIsBinary = 128 // flag that is set if this type uses the hashmap binary algorithm
400402
)
401403

402404
// The base type struct. All type structs start with this.
@@ -940,63 +942,12 @@ func (t *rawType) Implements(u Type) bool {
940942

941943
// Comparable returns whether values of this type can be compared to each other.
942944
func (t *rawType) Comparable() bool {
943-
switch t.Kind() {
944-
case Invalid:
945-
return false
946-
case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
947-
return true
948-
case Float32, Float64, Complex64, Complex128:
949-
return true
950-
case String:
951-
return true
952-
case UnsafePointer:
953-
return true
954-
case Chan:
955-
return true
956-
case Interface:
957-
return true
958-
case Pointer:
959-
return true
960-
case Slice:
961-
return false
962-
case Array:
963-
return t.elem().Comparable()
964-
case Func:
965-
return false
966-
case Map:
967-
return false
968-
case Struct:
969-
numField := t.NumField()
970-
for i := 0; i < numField; i++ {
971-
if !t.rawField(i).Type.Comparable() {
972-
return false
973-
}
974-
}
975-
return true
976-
default:
977-
panic(TypeError{"Comparable"})
978-
}
945+
return (t.meta & flagComparable) == flagComparable
979946
}
980947

981948
// isbinary() returns if the hashmapAlgorithmBinary functions can be used on this type
982949
func (t *rawType) isBinary() bool {
983-
switch t.Kind() {
984-
case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
985-
return true
986-
case Pointer:
987-
return true
988-
case Array:
989-
return t.elem().isBinary()
990-
case Struct:
991-
numField := t.NumField()
992-
for i := 0; i < numField; i++ {
993-
if !t.rawField(i).Type.isBinary() {
994-
return false
995-
}
996-
}
997-
return true
998-
}
999-
return false
950+
return (t.meta & flagIsBinary) == flagIsBinary
1000951
}
1001952

1002953
func (t *rawType) ChanDir() ChanDir {

0 commit comments

Comments
 (0)