@@ -309,6 +309,9 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
309
309
// / The set of inherited protocol conformances.
310
310
llvm::FoldingSet<InheritedProtocolConformance> InheritedConformances;
311
311
312
+ // / The set of substitution maps (uniqued by their storage).
313
+ llvm::FoldingSet<SubstitutionMap::Storage> SubstitutionMaps;
314
+
312
315
~Arena () {
313
316
for (auto &conformance : SpecializedConformances)
314
317
conformance.~SpecializedProtocolConformance ();
@@ -2907,11 +2910,9 @@ NameAliasType::NameAliasType(TypeAliasDecl *typealias, Type parent,
2907
2910
}
2908
2911
}
2909
2912
2910
- NameAliasType *NameAliasType::get (
2911
- TypeAliasDecl *typealias,
2912
- Type parent,
2913
- const SubstitutionMap &substitutions,
2914
- Type underlying) {
2913
+ NameAliasType *NameAliasType::get (TypeAliasDecl *typealias, Type parent,
2914
+ const SubstitutionMap &substitutions,
2915
+ Type underlying) {
2915
2916
// Compute the recursive properties.
2916
2917
//
2917
2918
auto properties = underlying->getRecursiveProperties ();
@@ -4293,6 +4294,64 @@ CapturingTypeCheckerDebugConsumer::~CapturingTypeCheckerDebugConsumer() {
4293
4294
delete Log;
4294
4295
}
4295
4296
4297
+ void SubstitutionMap::Storage::Profile (
4298
+ llvm::FoldingSetNodeID &id,
4299
+ GenericSignature *genericSig,
4300
+ ArrayRef<Type> replacementTypes,
4301
+ ArrayRef<ProtocolConformanceRef> conformances) {
4302
+ id.AddPointer (genericSig);
4303
+ id.AddInteger (replacementTypes.size ());
4304
+ for (auto type : replacementTypes)
4305
+ id.AddPointer (type.getPointer ());
4306
+ id.AddInteger (conformances.size ());
4307
+ for (auto conformance : conformances)
4308
+ id.AddPointer (conformance.getOpaqueValue ());
4309
+ }
4310
+
4311
+ SubstitutionMap::Storage *SubstitutionMap::Storage::get (
4312
+ GenericSignature *genericSig,
4313
+ ArrayRef<Type> replacementTypes,
4314
+ ArrayRef<ProtocolConformanceRef> conformances) {
4315
+ // If there is no generic signature, we need no storage.
4316
+ if (!genericSig) {
4317
+ assert (replacementTypes.empty ());
4318
+ assert (conformances.empty ());
4319
+ return nullptr ;
4320
+ }
4321
+
4322
+ // Figure out which arena this should go in.
4323
+ RecursiveTypeProperties properties;
4324
+ for (auto type : replacementTypes) {
4325
+ if (type)
4326
+ properties |= type->getRecursiveProperties ();
4327
+ }
4328
+
4329
+ // Profile the substitution map.
4330
+ llvm::FoldingSetNodeID id;
4331
+ SubstitutionMap::Storage::Profile (id, genericSig, replacementTypes,
4332
+ conformances);
4333
+
4334
+ auto arena = getArena (properties);
4335
+
4336
+ // Did we already record this substitution map?
4337
+ auto &ctx = genericSig->getASTContext ();
4338
+ void *insertPos;
4339
+ auto &substitutionMaps = ctx.Impl .getArena (arena).SubstitutionMaps ;
4340
+ if (auto result = substitutionMaps.FindNodeOrInsertPos (id, insertPos))
4341
+ return result;
4342
+
4343
+ // Allocate the appropriate amount of storage for the signature and its
4344
+ // replacement types and conformances.
4345
+ auto size = Storage::totalSizeToAlloc<Type, ProtocolConformanceRef>(
4346
+ replacementTypes.size (),
4347
+ conformances.size ());
4348
+ auto mem = ctx.Allocate (size, alignof (Storage), arena);
4349
+
4350
+ auto result = new (mem) Storage (genericSig, replacementTypes, conformances);
4351
+ substitutionMaps.InsertNode (result, insertPos);
4352
+ return result;
4353
+ }
4354
+
4296
4355
void GenericSignature::Profile (llvm::FoldingSetNodeID &ID,
4297
4356
TypeArrayView<GenericTypeParamType> genericParams,
4298
4357
ArrayRef<Requirement> requirements) {
0 commit comments