Skip to content

Commit 64f4854

Browse files
committed
Account for whether artificial subclasses are skipped on type caching
MetadataReader caches types only with the metadata address as the key. However a type lookup can be requested skipping artificial subclasses or not. This makes the cached results incorrect if two requests for the same type, but skipping subclasses on one and not on the other, are made. Fix this by adding a second dimension to the cache key. rdar://101519300
1 parent 2c3c3c1 commit 64f4854

File tree

1 file changed

+33
-18
lines changed

1 file changed

+33
-18
lines changed

include/swift/Remote/MetadataReader.h

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,18 @@ class MetadataReader {
193193
/// amounts of data when we encounter corrupt values for sizes/counts.
194194
static const uint64_t MaxMetadataSize = 1048576; // 1MB
195195

196-
/// A cache of built types, keyed by the address of the type.
197-
std::unordered_map<StoredPointer, BuiltType> TypeCache;
196+
/// Define a has function for a std::pair<StoredPointer, bool>
197+
struct TypeCacheKeyHash {
198+
std::size_t operator()(const std::pair<StoredPointer, bool> &x) const {
199+
return std::hash<StoredPointer>()(x.first) ^ std::hash<bool>()(x.second);
200+
}
201+
};
202+
203+
/// A cache of built types, keyed by the address of the type and whether the
204+
/// request ignored articial superclasses or not.
205+
std::unordered_map<std::pair<StoredPointer, bool>, BuiltType,
206+
TypeCacheKeyHash>
207+
TypeCache;
198208

199209
using MetadataRef = RemoteRef<const TargetMetadata<Runtime>>;
200210
using OwnedMetadataRef = MemoryReader::ReadBytesResult;
@@ -821,7 +831,9 @@ class MetadataReader {
821831
readTypeFromMetadata(StoredPointer MetadataAddress,
822832
bool skipArtificialSubclasses = false,
823833
int recursion_limit = defaultTypeRecursionLimit) {
824-
auto Cached = TypeCache.find(MetadataAddress);
834+
std::pair<StoredPointer, bool> TypeCacheKey(MetadataAddress,
835+
skipArtificialSubclasses);
836+
auto Cached = TypeCache.find(TypeCacheKey);
825837
if (Cached != TypeCache.end())
826838
return Cached->second;
827839

@@ -841,7 +853,7 @@ class MetadataReader {
841853
// Insert a negative result into the cache now so that, if we recur with
842854
// the same address, we will return the negative result with the check
843855
// just above.
844-
TypeCache.insert({MetadataAddress, BuiltType()});
856+
TypeCache.insert({TypeCacheKey, BuiltType()});
845857

846858
auto Meta = readMetadata(MetadataAddress);
847859
if (!Meta) return BuiltType();
@@ -890,7 +902,7 @@ class MetadataReader {
890902

891903
auto BuiltTuple =
892904
Builder.createTupleType(elementTypes, labels);
893-
TypeCache[MetadataAddress] = BuiltTuple;
905+
TypeCache[TypeCacheKey] = BuiltTuple;
894906
return BuiltTuple;
895907
}
896908
case MetadataKind::Function: {
@@ -947,7 +959,7 @@ class MetadataReader {
947959

948960
auto BuiltFunction = Builder.createFunctionType(
949961
Parameters, Result, flags, diffKind, globalActor);
950-
TypeCache[MetadataAddress] = BuiltFunction;
962+
TypeCache[TypeCacheKey] = BuiltFunction;
951963
return BuiltFunction;
952964
}
953965
case MetadataKind::Existential: {
@@ -998,7 +1010,7 @@ class MetadataReader {
9981010
}
9991011
auto BuiltExist = Builder.createProtocolCompositionType(
10001012
Protocols, SuperclassType, HasExplicitAnyObject);
1001-
TypeCache[MetadataAddress] = BuiltExist;
1013+
TypeCache[TypeCacheKey] = BuiltExist;
10021014
return BuiltExist;
10031015
}
10041016
case MetadataKind::ExtendedExistential: {
@@ -1076,7 +1088,7 @@ class MetadataReader {
10761088
}
10771089
}
10781090

1079-
TypeCache[MetadataAddress] = builtProto;
1091+
TypeCache[TypeCacheKey] = builtProto;
10801092
return builtProto;
10811093
}
10821094

@@ -1086,7 +1098,7 @@ class MetadataReader {
10861098
readTypeFromMetadata(Metatype->InstanceType, false, recursion_limit);
10871099
if (!Instance) return BuiltType();
10881100
auto BuiltMetatype = Builder.createMetatypeType(Instance);
1089-
TypeCache[MetadataAddress] = BuiltMetatype;
1101+
TypeCache[TypeCacheKey] = BuiltMetatype;
10901102
return BuiltMetatype;
10911103
}
10921104
case MetadataKind::ObjCClassWrapper: {
@@ -1098,7 +1110,7 @@ class MetadataReader {
10981110
return BuiltType();
10991111

11001112
auto BuiltObjCClass = Builder.createObjCClassType(std::move(className));
1101-
TypeCache[MetadataAddress] = BuiltObjCClass;
1113+
TypeCache[TypeCacheKey] = BuiltObjCClass;
11021114
return BuiltObjCClass;
11031115
}
11041116
case MetadataKind::ExistentialMetatype: {
@@ -1107,7 +1119,7 @@ class MetadataReader {
11071119
readTypeFromMetadata(Exist->InstanceType, false, recursion_limit);
11081120
if (!Instance) return BuiltType();
11091121
auto BuiltExist = Builder.createExistentialMetatypeType(Instance);
1110-
TypeCache[MetadataAddress] = BuiltExist;
1122+
TypeCache[TypeCacheKey] = BuiltExist;
11111123
return BuiltExist;
11121124
}
11131125
case MetadataKind::ForeignReferenceType:
@@ -1131,7 +1143,7 @@ class MetadataReader {
11311143
auto name = mangling.result();
11321144

11331145
auto BuiltForeign = Builder.createForeignClassType(std::move(name));
1134-
TypeCache[MetadataAddress] = BuiltForeign;
1146+
TypeCache[TypeCacheKey] = BuiltForeign;
11351147
return BuiltForeign;
11361148
}
11371149
case MetadataKind::HeapLocalVariable:
@@ -1142,7 +1154,7 @@ class MetadataReader {
11421154
case MetadataKind::Opaque:
11431155
default: {
11441156
auto BuiltOpaque = Builder.getOpaqueType();
1145-
TypeCache[MetadataAddress] = BuiltOpaque;
1157+
TypeCache[TypeCacheKey] = BuiltOpaque;
11461158
return BuiltOpaque;
11471159
}
11481160
}
@@ -3084,9 +3096,12 @@ class MetadataReader {
30843096
// If we've skipped an artificial subclasses, check the cache at
30853097
// the superclass. (This also protects against recursion.)
30863098
if (skipArtificialSubclasses && metadata != origMetadata) {
3087-
auto it = TypeCache.find(getAddress(metadata));
3088-
if (it != TypeCache.end())
3099+
auto it =
3100+
TypeCache.find({getAddress(metadata), skipArtificialSubclasses});
3101+
if (it != TypeCache.end()) {
3102+
TypeCache.erase({getAddress(origMetadata), skipArtificialSubclasses});
30893103
return it->second;
3104+
}
30903105
}
30913106

30923107
// Read the nominal type descriptor.
@@ -3115,12 +3130,12 @@ class MetadataReader {
31153130
if (!nominal)
31163131
return BuiltType();
31173132

3118-
TypeCache[getAddress(metadata)] = nominal;
3133+
TypeCache[{getAddress(metadata), skipArtificialSubclasses}] = nominal;
31193134

31203135
// If we've skipped an artificial subclass, remove the
31213136
// recursion-protection entry we made for it.
31223137
if (skipArtificialSubclasses && metadata != origMetadata) {
3123-
TypeCache.erase(getAddress(origMetadata));
3138+
TypeCache.erase({getAddress(origMetadata), skipArtificialSubclasses});
31243139
}
31253140

31263141
return nominal;
@@ -3151,7 +3166,7 @@ class MetadataReader {
31513166
skipArtificialSubclasses, recursion_limit);
31523167
}
31533168

3154-
TypeCache[origMetadataPtr] = BuiltObjCClass;
3169+
TypeCache[{origMetadataPtr, skipArtificialSubclasses}] = BuiltObjCClass;
31553170
return BuiltObjCClass;
31563171
}
31573172

0 commit comments

Comments
 (0)