11
11
// ===----------------------------------------------------------------------===//
12
12
13
13
#include " swift/Runtime/Config.h"
14
+ #include " swift/Basic/Lazy.h"
15
+ #include " swift/Runtime/Concurrent.h"
14
16
#include " swift/Runtime/Debug.h"
15
17
#include " swift/Runtime/Metadata.h"
16
18
#include " ../runtime/Private.h"
17
19
18
20
using namespace swift ;
19
21
22
+ // / The name demangles to "protocol descriptor for Swift.Hashable".
20
23
extern " C" const ProtocolDescriptor _TMps8Hashable;
21
24
25
+ namespace {
26
+ struct HashableConformanceKey {
27
+ // / The lookup key, the metadata of a type that is possibly derived
28
+ // / from a type that conforms to `Hashable`.
29
+ const Metadata *derivedType;
30
+ };
31
+
32
+ struct HashableConformanceEntry {
33
+ // / The lookup key, the metadata of a type that is possibly derived
34
+ // / from a type that conforms to `Hashable`.
35
+ const Metadata *derivedType;
36
+
37
+ // / The highest (closest to the root) type in the superclass chain
38
+ // / that conforms to `Hashable`.
39
+ const Metadata *baseTypeThatConformsToHashable;
40
+
41
+ HashableConformanceEntry (HashableConformanceKey key,
42
+ const Metadata *baseTypeThatConformsToHashable)
43
+ : derivedType(key.derivedType),
44
+ baseTypeThatConformsToHashable (baseTypeThatConformsToHashable) {}
45
+
46
+ int compareWithKey (const HashableConformanceKey &key) const {
47
+ if (key.derivedType != derivedType) {
48
+ return (uintptr_t (key.derivedType ) < uintptr_t (derivedType) ? -1 : 1 );
49
+ } else {
50
+ return 0 ;
51
+ }
52
+ }
53
+
54
+ static size_t
55
+ getExtraAllocationSize (HashableConformanceKey key,
56
+ const Metadata *baseTypeThatConformsToHashable) {
57
+ return 0 ;
58
+ }
59
+ };
60
+ } // end unnamed namesapce
61
+
62
+ static Lazy<ConcurrentMap<HashableConformanceEntry>> HashableConformances;
63
+
64
+ // / Find the base type that introduces the `Hashable` conformance.
65
+ // /
66
+ // / - Precondition: `type` conforms to `Hashable` (not checked).
67
+ static const Metadata *findHashableBaseType (const Metadata *type) {
68
+ if (HashableConformanceEntry *entry =
69
+ HashableConformances->find (HashableConformanceKey{type})) {
70
+ return entry->baseTypeThatConformsToHashable ;
71
+ }
72
+ const Metadata *baseTypeThatConformsToHashable = type;
73
+ while (true ) {
74
+ const Metadata *superclass =
75
+ _swift_class_getSuperclass (baseTypeThatConformsToHashable);
76
+ if (!superclass)
77
+ break ;
78
+ if (!swift_conformsToProtocol (superclass, &_TMps8Hashable))
79
+ break ;
80
+ baseTypeThatConformsToHashable = superclass;
81
+ }
82
+ HashableConformances->getOrInsert (HashableConformanceKey{type},
83
+ baseTypeThatConformsToHashable);
84
+ return baseTypeThatConformsToHashable;
85
+ }
86
+
22
87
SWIFT_CC (swift) SWIFT_RUNTIME_STDLIB_INTERFACE
23
88
extern "C" void _swift_stdlib_makeAnyHashableUsingDefaultRepresentation(
24
89
const OpaqueValue *value,
@@ -34,22 +99,14 @@ extern "C" void _swift_stdlib_makeAnyHashableUpcastingToHashableBaseType(
34
99
const Metadata *type,
35
100
const WitnessTable *hashableWT
36
101
) {
37
- // FIXME(id-as-any)(performance): cache the result of the lookup.
38
102
switch (type->getKind ()) {
39
103
case MetadataKind::Class:
40
104
case MetadataKind::ObjCClassWrapper:
41
105
case MetadataKind::ForeignClass: {
42
106
// FIXME(id-as-any): handle ForeignClass.
43
- while (true ) {
44
- const Metadata *superclass = _swift_class_getSuperclass (type);
45
- if (!superclass)
46
- break ;
47
- if (!swift_conformsToProtocol (superclass, &_TMps8Hashable))
48
- break ;
49
- type = superclass;
50
- }
51
107
_swift_stdlib_makeAnyHashableUsingDefaultRepresentation (
52
- value, anyHashableResultPointer, type, hashableWT);
108
+ value, anyHashableResultPointer, findHashableBaseType (type),
109
+ hashableWT);
53
110
return ;
54
111
}
55
112
0 commit comments