Skip to content

Commit a5d396b

Browse files
committed
Merge pull request #2313 from bitjammer/typeref-uniquing
Typeref uniquing
2 parents 5fdf0b6 + dd7b663 commit a5d396b

File tree

6 files changed

+568
-38
lines changed

6 files changed

+568
-38
lines changed

include/swift/Reflection/TypeRef.h

Lines changed: 197 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,84 @@ enum class TypeRefKind {
3636
#undef TYPEREF
3737
};
3838

39+
/// An identifier containing the unique bit pattern made up of all of the
40+
/// instance data needed to uniquely identify a TypeRef.
41+
///
42+
/// This allows for uniquing (via Equal) and for keying into a dictionary for
43+
/// caching.
44+
///
45+
/// TypeRefs should be comparable by pointers, so if the TypeRefBuilder
46+
/// gets a request to build a TypeRef with the same constructor arguments,
47+
/// it should return the one already created with those arguments, not a fresh
48+
/// copy. This allows for fast identity comparisons and substitutions, for
49+
/// example. We use a similar strategy for Types in the full AST.
50+
class TypeRefID {
51+
52+
std::vector<uint32_t> Bits;
53+
54+
public:
55+
TypeRefID() = default;
56+
57+
template <typename T>
58+
void addPointer(const T *Pointer) {
59+
auto Raw = reinterpret_cast<uint32_t *>(&Pointer);
60+
Bits.push_back(Raw[0]);
61+
if (sizeof(const T *) > 4) {
62+
Bits.push_back(Raw[1]);
63+
}
64+
}
65+
66+
void addInteger(uint32_t Integer) {
67+
Bits.push_back(Integer);
68+
}
69+
70+
void addInteger(uint64_t Integer) {
71+
Bits.push_back((uint32_t)Integer);
72+
Bits.push_back(Integer >> 32);
73+
}
74+
75+
void addString(const std::string &String) {
76+
if (String.empty()) {
77+
Bits.push_back(0);
78+
} else {
79+
size_t i = 0;
80+
size_t chunks = String.size() / 4;
81+
for (size_t chunk = 0; chunk < chunks; ++chunk, i+=4) {
82+
uint32_t entry = ((uint32_t) String[i]) +
83+
(((uint32_t) String[i+1]) << 8) +
84+
(((uint32_t) String[i+2]) << 16) +
85+
(((uint32_t) String[i+3]) << 24);
86+
Bits.push_back(entry);
87+
}
88+
for(; i < String.size(); ++i) {
89+
Bits.push_back(String[i]);
90+
}
91+
}
92+
}
93+
94+
struct Hash {
95+
std::size_t operator()(TypeRefID const &ID) const {
96+
size_t Hash = 0;
97+
std::hash<uint32_t> h;
98+
for (auto x : ID.Bits) {
99+
Hash ^= h(x) + 0x9e3779b9 + (Hash << 6) + (Hash >> 2);
100+
}
101+
return Hash;
102+
}
103+
};
104+
105+
struct Equal {
106+
bool operator()(const TypeRefID &lhs, const TypeRefID &rhs) const {
107+
return lhs.Bits == rhs.Bits;
108+
}
109+
};
110+
111+
112+
bool operator==(const TypeRefID &Other) {
113+
return Bits == Other.Bits;
114+
}
115+
};
116+
39117
class TypeRef;
40118
class TypeRefBuilder;
41119
using DepthAndIndex = std::pair<unsigned, unsigned>;
@@ -80,6 +158,12 @@ class BuiltinTypeRef final : public TypeRef {
80158
return MangledName;
81159
}
82160

161+
static TypeRefID Profile(const std::string &MangledName) {
162+
TypeRefID ID;
163+
ID.addString(MangledName);
164+
return ID;
165+
}
166+
83167
static bool classof(const TypeRef *TR) {
84168
return TR->getKind() == TypeRefKind::Builtin;
85169
}
@@ -107,6 +191,14 @@ class NominalTypeTrait {
107191
}
108192

109193
unsigned getDepth() const;
194+
195+
static TypeRefID Profile(const std::string &MangledName,
196+
const TypeRef *Parent) {
197+
TypeRefID ID;
198+
ID.addString(MangledName);
199+
ID.addPointer(Parent);
200+
return ID;
201+
}
110202
};
111203

112204
class NominalTypeRef final : public TypeRef, public NominalTypeTrait {
@@ -122,6 +214,8 @@ class NominalTypeRef final : public TypeRef, public NominalTypeTrait {
122214
return A.template makeTypeRef<NominalTypeRef>(MangledName, Parent);
123215
}
124216

217+
using NominalTypeTrait::Profile;
218+
125219
static bool classof(const TypeRef *TR) {
126220
return TR->getKind() == TypeRefKind::Nominal;
127221
}
@@ -152,6 +246,17 @@ class BoundGenericTypeRef final : public TypeRef, public NominalTypeTrait {
152246
return GenericParams;
153247
}
154248

249+
static TypeRefID Profile(const std::string &MangledName,
250+
const std::vector<const TypeRef *> &GenericParams,
251+
const TypeRef *Parent) {
252+
TypeRefID ID;
253+
ID.addString(MangledName);
254+
for (auto Param : GenericParams)
255+
ID.addPointer(Param);
256+
ID.addPointer(Parent);
257+
return ID;
258+
}
259+
155260
static bool classof(const TypeRef *TR) {
156261
return TR->getKind() == TypeRefKind::BoundGeneric;
157262
}
@@ -180,6 +285,16 @@ class TupleTypeRef final : public TypeRef {
180285
return Variadic;
181286
}
182287

288+
static TypeRefID Profile(const std::vector<const TypeRef *> &Elements,
289+
bool Variadic) {
290+
TypeRefID ID;
291+
for (auto Element : Elements)
292+
ID.addPointer(Element);
293+
294+
ID.addInteger(static_cast<uint32_t>(Variadic));
295+
return ID;
296+
}
297+
183298
static bool classof(const TypeRef *TR) {
184299
return TR->getKind() == TypeRefKind::Tuple;
185300
}
@@ -216,6 +331,18 @@ class FunctionTypeRef final : public TypeRef {
216331
return Flags;
217332
}
218333

334+
static TypeRefID Profile(const std::vector<const TypeRef *> &Arguments,
335+
const TypeRef *Result,
336+
FunctionTypeFlags Flags) {
337+
TypeRefID ID;
338+
for (auto Argument : Arguments) {
339+
ID.addPointer(Argument);
340+
}
341+
ID.addPointer(Result);
342+
ID.addInteger(static_cast<uint64_t>(Flags.getIntValue()));
343+
return ID;
344+
}
345+
219346
static bool classof(const TypeRef *TR) {
220347
return TR->getKind() == TypeRefKind::Function;
221348
}
@@ -238,6 +365,12 @@ class ProtocolTypeRef final : public TypeRef {
238365
return MangledName;
239366
}
240367

368+
static TypeRefID Profile(const std::string &MangledName) {
369+
TypeRefID ID;
370+
ID.addString(MangledName);
371+
return ID;
372+
}
373+
241374
static bool classof(const TypeRef *TR) {
242375
return TR->getKind() == TypeRefKind::Protocol;
243376
}
@@ -267,6 +400,14 @@ class ProtocolCompositionTypeRef final : public TypeRef {
267400
return Protocols;
268401
}
269402

403+
static TypeRefID Profile(const std::vector<const TypeRef *> &Protocols) {
404+
TypeRefID ID;
405+
for (auto Protocol : Protocols) {
406+
ID.addPointer(Protocol);
407+
}
408+
return ID;
409+
}
410+
270411
static bool classof(const TypeRef *TR) {
271412
return TR->getKind() == TypeRefKind::ProtocolComposition;
272413
}
@@ -296,6 +437,12 @@ class MetatypeTypeRef final : public TypeRef {
296437
return InstanceType;
297438
}
298439

440+
static TypeRefID Profile(const TypeRef *InstanceType) {
441+
TypeRefID ID;
442+
ID.addPointer(InstanceType);
443+
return ID;
444+
}
445+
299446
static bool classof(const TypeRef *TR) {
300447
return TR->getKind() == TypeRefKind::Metatype;
301448
}
@@ -318,6 +465,12 @@ class ExistentialMetatypeTypeRef final : public TypeRef {
318465
return InstanceType;
319466
}
320467

468+
static TypeRefID Profile(const TypeRef *InstanceType) {
469+
TypeRefID ID;
470+
ID.addPointer(InstanceType);
471+
return ID;
472+
}
473+
321474
static bool classof(const TypeRef *TR) {
322475
return TR->getKind() == TypeRefKind::ExistentialMetatype;
323476
}
@@ -345,6 +498,13 @@ class GenericTypeParameterTypeRef final : public TypeRef {
345498
return Index;
346499
}
347500

501+
static TypeRefID Profile(uint32_t Depth, uint32_t Index) {
502+
TypeRefID ID;
503+
ID.addInteger(Depth);
504+
ID.addInteger(Index);
505+
return ID;
506+
}
507+
348508
static bool classof(const TypeRef *TR) {
349509
return TR->getKind() == TypeRefKind::GenericTypeParameter;
350510
}
@@ -381,21 +541,26 @@ class DependentMemberTypeRef final : public TypeRef {
381541
return cast<ProtocolTypeRef>(Protocol);
382542
}
383543

544+
static TypeRefID Profile(const std::string &Member, const TypeRef *Base,
545+
const TypeRef *Protocol) {
546+
TypeRefID ID;
547+
ID.addString(Member);
548+
ID.addPointer(Base);
549+
ID.addPointer(Protocol);
550+
return ID;
551+
}
552+
384553
static bool classof(const TypeRef *TR) {
385554
return TR->getKind() == TypeRefKind::DependentMember;
386555
}
387556
};
388557

389558
class ForeignClassTypeRef final : public TypeRef {
390559
std::string Name;
391-
static const ForeignClassTypeRef *UnnamedSingleton;
392560
public:
393561
ForeignClassTypeRef(const std::string &Name)
394562
: TypeRef(TypeRefKind::ForeignClass), Name(Name) {}
395563

396-
static const ForeignClassTypeRef *getUnnamed();
397-
398-
399564
template <typename Allocator>
400565
static ForeignClassTypeRef *create(Allocator &A,
401566
const std::string &Name) {
@@ -406,6 +571,12 @@ class ForeignClassTypeRef final : public TypeRef {
406571
return Name;
407572
}
408573

574+
static TypeRefID Profile(const std::string &Name) {
575+
TypeRefID ID;
576+
ID.addString(Name);
577+
return ID;
578+
}
579+
409580
static bool classof(const TypeRef *TR) {
410581
return TR->getKind() == TypeRefKind::ForeignClass;
411582
}
@@ -429,6 +600,12 @@ class ObjCClassTypeRef final : public TypeRef {
429600
return Name;
430601
}
431602

603+
static TypeRefID Profile(const std::string &Name) {
604+
TypeRefID ID;
605+
ID.addString(Name);
606+
return ID;
607+
}
608+
432609
static bool classof(const TypeRef *TR) {
433610
return TR->getKind() == TypeRefKind::ObjCClass;
434611
}
@@ -441,6 +618,10 @@ class OpaqueTypeRef final : public TypeRef {
441618

442619
static const OpaqueTypeRef *get();
443620

621+
static TypeRefID Profile() {
622+
return TypeRefID();
623+
}
624+
444625
static bool classof(const TypeRef *TR) {
445626
return TR->getKind() == TypeRefKind::Opaque;
446627
}
@@ -457,6 +638,12 @@ class ReferenceStorageTypeRef : public TypeRef {
457638
const TypeRef *getType() const {
458639
return Type;
459640
}
641+
642+
static TypeRefID Profile(const TypeRef *Type) {
643+
TypeRefID ID;
644+
ID.addPointer(Type);
645+
return ID;
646+
}
460647
};
461648

462649
class UnownedStorageTypeRef final : public ReferenceStorageTypeRef {
@@ -470,6 +657,8 @@ class UnownedStorageTypeRef final : public ReferenceStorageTypeRef {
470657
return A.template makeTypeRef<UnownedStorageTypeRef>(Type);
471658
}
472659

660+
using ReferenceStorageTypeRef::Profile;
661+
473662
static bool classof(const TypeRef *TR) {
474663
return TR->getKind() == TypeRefKind::UnownedStorage;
475664
}
@@ -486,6 +675,8 @@ class WeakStorageTypeRef final : public ReferenceStorageTypeRef {
486675
return A.template makeTypeRef<WeakStorageTypeRef>(Type);
487676
}
488677

678+
using ReferenceStorageTypeRef::Profile;
679+
489680
static bool classof(const TypeRef *TR) {
490681
return TR->getKind() == TypeRefKind::WeakStorage;
491682
}
@@ -502,6 +693,8 @@ class UnmanagedStorageTypeRef final : public ReferenceStorageTypeRef {
502693
return A.template makeTypeRef<UnmanagedStorageTypeRef>(Type);
503694
}
504695

696+
using ReferenceStorageTypeRef::Profile;
697+
505698
static bool classof(const TypeRef *TR) {
506699
return TR->getKind() == TypeRefKind::UnmanagedStorage;
507700
}

0 commit comments

Comments
 (0)