Skip to content

Commit 50440ab

Browse files
committed
TypeRef Uniquing
We'd like to be able to compare TypeRefs with pointer equality, but we can't link LLVMSupport, so make a lightweight TypeRefID like FoldingSetID, that only supports the input types necessary to unique TypeRefs. rdar://problem/25924875
1 parent d9368ff commit 50440ab

File tree

6 files changed

+562
-37
lines changed

6 files changed

+562
-37
lines changed

include/swift/Reflection/TypeRef.h

Lines changed: 195 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,82 @@ 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<uintptr_t>(Pointer);
60+
Bits.push_back((uint32_t)Raw);
61+
Bits.push_back(Raw >> 32);
62+
}
63+
64+
void addInteger(uint32_t Integer) {
65+
Bits.push_back(Integer);
66+
}
67+
68+
void addInteger(uint64_t Integer) {
69+
Bits.push_back((uint32_t)Integer);
70+
Bits.push_back(Integer >> 32);
71+
}
72+
73+
void addString(const std::string &String) {
74+
if (String.empty()) {
75+
Bits.push_back(0);
76+
} else {
77+
size_t i = 0;
78+
size_t chunks = String.size() / 4;
79+
for (size_t chunk = 0; chunk < chunks; ++chunk, i+=4) {
80+
uint32_t entry = ((uint32_t) String[i]) +
81+
(((uint32_t) String[i+1]) << 8) +
82+
(((uint32_t) String[i+2]) << 16) +
83+
(((uint32_t) String[i+3]) << 24);
84+
Bits.push_back(entry);
85+
}
86+
for(; i < String.size(); ++i) {
87+
Bits.push_back(String[i]);
88+
}
89+
}
90+
}
91+
92+
struct Hash {
93+
std::size_t operator()(TypeRefID const &ID) const {
94+
size_t Hash = 0;
95+
std::hash<uint32_t> h;
96+
for (auto x : ID.Bits) {
97+
Hash ^= h(x) + 0x9e3779b9 + (Hash << 6) + (Hash >> 2);
98+
}
99+
return Hash;
100+
}
101+
};
102+
103+
struct Equal {
104+
bool operator()(const TypeRefID &lhs, const TypeRefID &rhs) const {
105+
return lhs.Bits == rhs.Bits;
106+
}
107+
};
108+
109+
110+
bool operator==(const TypeRefID &Other) {
111+
return Bits == Other.Bits;
112+
}
113+
};
114+
39115
class TypeRef;
40116
class TypeRefBuilder;
41117
using DepthAndIndex = std::pair<unsigned, unsigned>;
@@ -80,6 +156,12 @@ class BuiltinTypeRef final : public TypeRef {
80156
return MangledName;
81157
}
82158

159+
static TypeRefID Profile(const std::string &MangledName) {
160+
TypeRefID ID;
161+
ID.addString(MangledName);
162+
return ID;
163+
}
164+
83165
static bool classof(const TypeRef *TR) {
84166
return TR->getKind() == TypeRefKind::Builtin;
85167
}
@@ -107,6 +189,14 @@ class NominalTypeTrait {
107189
}
108190

109191
unsigned getDepth() const;
192+
193+
static TypeRefID Profile(const std::string &MangledName,
194+
const TypeRef *Parent) {
195+
TypeRefID ID;
196+
ID.addString(MangledName);
197+
ID.addPointer(Parent);
198+
return ID;
199+
}
110200
};
111201

112202
class NominalTypeRef final : public TypeRef, public NominalTypeTrait {
@@ -122,6 +212,8 @@ class NominalTypeRef final : public TypeRef, public NominalTypeTrait {
122212
return A.template makeTypeRef<NominalTypeRef>(MangledName, Parent);
123213
}
124214

215+
using NominalTypeTrait::Profile;
216+
125217
static bool classof(const TypeRef *TR) {
126218
return TR->getKind() == TypeRefKind::Nominal;
127219
}
@@ -152,6 +244,17 @@ class BoundGenericTypeRef final : public TypeRef, public NominalTypeTrait {
152244
return GenericParams;
153245
}
154246

247+
static TypeRefID Profile(const std::string &MangledName,
248+
const std::vector<const TypeRef *> &GenericParams,
249+
const TypeRef *Parent) {
250+
TypeRefID ID;
251+
ID.addString(MangledName);
252+
for (auto Param : GenericParams)
253+
ID.addPointer(Param);
254+
ID.addPointer(Parent);
255+
return ID;
256+
}
257+
155258
static bool classof(const TypeRef *TR) {
156259
return TR->getKind() == TypeRefKind::BoundGeneric;
157260
}
@@ -180,6 +283,16 @@ class TupleTypeRef final : public TypeRef {
180283
return Variadic;
181284
}
182285

286+
static TypeRefID Profile(const std::vector<const TypeRef *> &Elements,
287+
bool Variadic) {
288+
TypeRefID ID;
289+
for (auto Element : Elements)
290+
ID.addPointer(Element);
291+
292+
ID.addInteger(static_cast<uint32_t>(Variadic));
293+
return ID;
294+
}
295+
183296
static bool classof(const TypeRef *TR) {
184297
return TR->getKind() == TypeRefKind::Tuple;
185298
}
@@ -216,6 +329,18 @@ class FunctionTypeRef final : public TypeRef {
216329
return Flags;
217330
}
218331

332+
static TypeRefID Profile(const std::vector<const TypeRef *> &Arguments,
333+
const TypeRef *Result,
334+
FunctionTypeFlags Flags) {
335+
TypeRefID ID;
336+
for (auto Argument : Arguments) {
337+
ID.addPointer(Argument);
338+
}
339+
ID.addPointer(Result);
340+
ID.addInteger(static_cast<uint64_t>(Flags.getIntValue()));
341+
return ID;
342+
}
343+
219344
static bool classof(const TypeRef *TR) {
220345
return TR->getKind() == TypeRefKind::Function;
221346
}
@@ -238,6 +363,12 @@ class ProtocolTypeRef final : public TypeRef {
238363
return MangledName;
239364
}
240365

366+
static TypeRefID Profile(const std::string &MangledName) {
367+
TypeRefID ID;
368+
ID.addString(MangledName);
369+
return ID;
370+
}
371+
241372
static bool classof(const TypeRef *TR) {
242373
return TR->getKind() == TypeRefKind::Protocol;
243374
}
@@ -267,6 +398,14 @@ class ProtocolCompositionTypeRef final : public TypeRef {
267398
return Protocols;
268399
}
269400

401+
static TypeRefID Profile(const std::vector<const TypeRef *> &Protocols) {
402+
TypeRefID ID;
403+
for (auto Protocol : Protocols) {
404+
ID.addPointer(Protocol);
405+
}
406+
return ID;
407+
}
408+
270409
static bool classof(const TypeRef *TR) {
271410
return TR->getKind() == TypeRefKind::ProtocolComposition;
272411
}
@@ -296,6 +435,12 @@ class MetatypeTypeRef final : public TypeRef {
296435
return InstanceType;
297436
}
298437

438+
static TypeRefID Profile(const TypeRef *InstanceType) {
439+
TypeRefID ID;
440+
ID.addPointer(InstanceType);
441+
return ID;
442+
}
443+
299444
static bool classof(const TypeRef *TR) {
300445
return TR->getKind() == TypeRefKind::Metatype;
301446
}
@@ -318,6 +463,12 @@ class ExistentialMetatypeTypeRef final : public TypeRef {
318463
return InstanceType;
319464
}
320465

466+
static TypeRefID Profile(const TypeRef *InstanceType) {
467+
TypeRefID ID;
468+
ID.addPointer(InstanceType);
469+
return ID;
470+
}
471+
321472
static bool classof(const TypeRef *TR) {
322473
return TR->getKind() == TypeRefKind::ExistentialMetatype;
323474
}
@@ -345,6 +496,13 @@ class GenericTypeParameterTypeRef final : public TypeRef {
345496
return Index;
346497
}
347498

499+
static TypeRefID Profile(uint32_t Depth, uint32_t Index) {
500+
TypeRefID ID;
501+
ID.addInteger(Depth);
502+
ID.addInteger(Index);
503+
return ID;
504+
}
505+
348506
static bool classof(const TypeRef *TR) {
349507
return TR->getKind() == TypeRefKind::GenericTypeParameter;
350508
}
@@ -381,21 +539,26 @@ class DependentMemberTypeRef final : public TypeRef {
381539
return cast<ProtocolTypeRef>(Protocol);
382540
}
383541

542+
static TypeRefID Profile(const std::string &Member, const TypeRef *Base,
543+
const TypeRef *Protocol) {
544+
TypeRefID ID;
545+
ID.addString(Member);
546+
ID.addPointer(Base);
547+
ID.addPointer(Protocol);
548+
return ID;
549+
}
550+
384551
static bool classof(const TypeRef *TR) {
385552
return TR->getKind() == TypeRefKind::DependentMember;
386553
}
387554
};
388555

389556
class ForeignClassTypeRef final : public TypeRef {
390557
std::string Name;
391-
static const ForeignClassTypeRef *UnnamedSingleton;
392558
public:
393559
ForeignClassTypeRef(const std::string &Name)
394560
: TypeRef(TypeRefKind::ForeignClass), Name(Name) {}
395561

396-
static const ForeignClassTypeRef *getUnnamed();
397-
398-
399562
template <typename Allocator>
400563
static ForeignClassTypeRef *create(Allocator &A,
401564
const std::string &Name) {
@@ -406,6 +569,12 @@ class ForeignClassTypeRef final : public TypeRef {
406569
return Name;
407570
}
408571

572+
static TypeRefID Profile(const std::string &Name) {
573+
TypeRefID ID;
574+
ID.addString(Name);
575+
return ID;
576+
}
577+
409578
static bool classof(const TypeRef *TR) {
410579
return TR->getKind() == TypeRefKind::ForeignClass;
411580
}
@@ -429,6 +598,12 @@ class ObjCClassTypeRef final : public TypeRef {
429598
return Name;
430599
}
431600

601+
static TypeRefID Profile(const std::string &Name) {
602+
TypeRefID ID;
603+
ID.addString(Name);
604+
return ID;
605+
}
606+
432607
static bool classof(const TypeRef *TR) {
433608
return TR->getKind() == TypeRefKind::ObjCClass;
434609
}
@@ -441,6 +616,10 @@ class OpaqueTypeRef final : public TypeRef {
441616

442617
static const OpaqueTypeRef *get();
443618

619+
static TypeRefID Profile() {
620+
return TypeRefID();
621+
}
622+
444623
static bool classof(const TypeRef *TR) {
445624
return TR->getKind() == TypeRefKind::Opaque;
446625
}
@@ -457,6 +636,12 @@ class ReferenceStorageTypeRef : public TypeRef {
457636
const TypeRef *getType() const {
458637
return Type;
459638
}
639+
640+
static TypeRefID Profile(const TypeRef *Type) {
641+
TypeRefID ID;
642+
ID.addPointer(Type);
643+
return ID;
644+
}
460645
};
461646

462647
class UnownedStorageTypeRef final : public ReferenceStorageTypeRef {
@@ -470,6 +655,8 @@ class UnownedStorageTypeRef final : public ReferenceStorageTypeRef {
470655
return A.template makeTypeRef<UnownedStorageTypeRef>(Type);
471656
}
472657

658+
using ReferenceStorageTypeRef::Profile;
659+
473660
static bool classof(const TypeRef *TR) {
474661
return TR->getKind() == TypeRefKind::UnownedStorage;
475662
}
@@ -486,6 +673,8 @@ class WeakStorageTypeRef final : public ReferenceStorageTypeRef {
486673
return A.template makeTypeRef<WeakStorageTypeRef>(Type);
487674
}
488675

676+
using ReferenceStorageTypeRef::Profile;
677+
489678
static bool classof(const TypeRef *TR) {
490679
return TR->getKind() == TypeRefKind::WeakStorage;
491680
}
@@ -502,6 +691,8 @@ class UnmanagedStorageTypeRef final : public ReferenceStorageTypeRef {
502691
return A.template makeTypeRef<UnmanagedStorageTypeRef>(Type);
503692
}
504693

694+
using ReferenceStorageTypeRef::Profile;
695+
505696
static bool classof(const TypeRef *TR) {
506697
return TR->getKind() == TypeRefKind::UnmanagedStorage;
507698
}

0 commit comments

Comments
 (0)