Skip to content

Commit 9151305

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 9151305

File tree

1 file changed

+35
-18
lines changed

1 file changed

+35
-18
lines changed

include/swift/Remote/MetadataReader.h

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#ifndef SWIFT_REMOTE_METADATAREADER_H
1818
#define SWIFT_REMOTE_METADATAREADER_H
1919

20+
#include "llvm/ADT/Hashing.h"
21+
2022
#include "swift/Runtime/Metadata.h"
2123
#include "swift/Remote/MemoryReader.h"
2224
#include "swift/Demangling/Demangler.h"
@@ -193,8 +195,18 @@ class MetadataReader {
193195
/// amounts of data when we encounter corrupt values for sizes/counts.
194196
static const uint64_t MaxMetadataSize = 1048576; // 1MB
195197

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

199211
using MetadataRef = RemoteRef<const TargetMetadata<Runtime>>;
200212
using OwnedMetadataRef = MemoryReader::ReadBytesResult;
@@ -821,7 +833,9 @@ class MetadataReader {
821833
readTypeFromMetadata(StoredPointer MetadataAddress,
822834
bool skipArtificialSubclasses = false,
823835
int recursion_limit = defaultTypeRecursionLimit) {
824-
auto Cached = TypeCache.find(MetadataAddress);
836+
std::pair<StoredPointer, bool> TypeCacheKey(MetadataAddress,
837+
skipArtificialSubclasses);
838+
auto Cached = TypeCache.find(TypeCacheKey);
825839
if (Cached != TypeCache.end())
826840
return Cached->second;
827841

@@ -841,7 +855,7 @@ class MetadataReader {
841855
// Insert a negative result into the cache now so that, if we recur with
842856
// the same address, we will return the negative result with the check
843857
// just above.
844-
TypeCache.insert({MetadataAddress, BuiltType()});
858+
TypeCache.insert({TypeCacheKey, BuiltType()});
845859

846860
auto Meta = readMetadata(MetadataAddress);
847861
if (!Meta) return BuiltType();
@@ -890,7 +904,7 @@ class MetadataReader {
890904

891905
auto BuiltTuple =
892906
Builder.createTupleType(elementTypes, labels);
893-
TypeCache[MetadataAddress] = BuiltTuple;
907+
TypeCache[TypeCacheKey] = BuiltTuple;
894908
return BuiltTuple;
895909
}
896910
case MetadataKind::Function: {
@@ -947,7 +961,7 @@ class MetadataReader {
947961

948962
auto BuiltFunction = Builder.createFunctionType(
949963
Parameters, Result, flags, diffKind, globalActor);
950-
TypeCache[MetadataAddress] = BuiltFunction;
964+
TypeCache[TypeCacheKey] = BuiltFunction;
951965
return BuiltFunction;
952966
}
953967
case MetadataKind::Existential: {
@@ -998,7 +1012,7 @@ class MetadataReader {
9981012
}
9991013
auto BuiltExist = Builder.createProtocolCompositionType(
10001014
Protocols, SuperclassType, HasExplicitAnyObject);
1001-
TypeCache[MetadataAddress] = BuiltExist;
1015+
TypeCache[TypeCacheKey] = BuiltExist;
10021016
return BuiltExist;
10031017
}
10041018
case MetadataKind::ExtendedExistential: {
@@ -1076,7 +1090,7 @@ class MetadataReader {
10761090
}
10771091
}
10781092

1079-
TypeCache[MetadataAddress] = builtProto;
1093+
TypeCache[TypeCacheKey] = builtProto;
10801094
return builtProto;
10811095
}
10821096

@@ -1086,7 +1100,7 @@ class MetadataReader {
10861100
readTypeFromMetadata(Metatype->InstanceType, false, recursion_limit);
10871101
if (!Instance) return BuiltType();
10881102
auto BuiltMetatype = Builder.createMetatypeType(Instance);
1089-
TypeCache[MetadataAddress] = BuiltMetatype;
1103+
TypeCache[TypeCacheKey] = BuiltMetatype;
10901104
return BuiltMetatype;
10911105
}
10921106
case MetadataKind::ObjCClassWrapper: {
@@ -1098,7 +1112,7 @@ class MetadataReader {
10981112
return BuiltType();
10991113

11001114
auto BuiltObjCClass = Builder.createObjCClassType(std::move(className));
1101-
TypeCache[MetadataAddress] = BuiltObjCClass;
1115+
TypeCache[TypeCacheKey] = BuiltObjCClass;
11021116
return BuiltObjCClass;
11031117
}
11041118
case MetadataKind::ExistentialMetatype: {
@@ -1107,7 +1121,7 @@ class MetadataReader {
11071121
readTypeFromMetadata(Exist->InstanceType, false, recursion_limit);
11081122
if (!Instance) return BuiltType();
11091123
auto BuiltExist = Builder.createExistentialMetatypeType(Instance);
1110-
TypeCache[MetadataAddress] = BuiltExist;
1124+
TypeCache[TypeCacheKey] = BuiltExist;
11111125
return BuiltExist;
11121126
}
11131127
case MetadataKind::ForeignReferenceType:
@@ -1131,7 +1145,7 @@ class MetadataReader {
11311145
auto name = mangling.result();
11321146

11331147
auto BuiltForeign = Builder.createForeignClassType(std::move(name));
1134-
TypeCache[MetadataAddress] = BuiltForeign;
1148+
TypeCache[TypeCacheKey] = BuiltForeign;
11351149
return BuiltForeign;
11361150
}
11371151
case MetadataKind::HeapLocalVariable:
@@ -1142,7 +1156,7 @@ class MetadataReader {
11421156
case MetadataKind::Opaque:
11431157
default: {
11441158
auto BuiltOpaque = Builder.getOpaqueType();
1145-
TypeCache[MetadataAddress] = BuiltOpaque;
1159+
TypeCache[TypeCacheKey] = BuiltOpaque;
11461160
return BuiltOpaque;
11471161
}
11481162
}
@@ -3084,9 +3098,12 @@ class MetadataReader {
30843098
// If we've skipped an artificial subclasses, check the cache at
30853099
// the superclass. (This also protects against recursion.)
30863100
if (skipArtificialSubclasses && metadata != origMetadata) {
3087-
auto it = TypeCache.find(getAddress(metadata));
3088-
if (it != TypeCache.end())
3101+
auto it =
3102+
TypeCache.find({getAddress(metadata), skipArtificialSubclasses});
3103+
if (it != TypeCache.end()) {
3104+
TypeCache.erase({getAddress(origMetadata), skipArtificialSubclasses});
30893105
return it->second;
3106+
}
30903107
}
30913108

30923109
// Read the nominal type descriptor.
@@ -3115,12 +3132,12 @@ class MetadataReader {
31153132
if (!nominal)
31163133
return BuiltType();
31173134

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

31203137
// If we've skipped an artificial subclass, remove the
31213138
// recursion-protection entry we made for it.
31223139
if (skipArtificialSubclasses && metadata != origMetadata) {
3123-
TypeCache.erase(getAddress(origMetadata));
3140+
TypeCache.erase({getAddress(origMetadata), skipArtificialSubclasses});
31243141
}
31253142

31263143
return nominal;
@@ -3151,7 +3168,7 @@ class MetadataReader {
31513168
skipArtificialSubclasses, recursion_limit);
31523169
}
31533170

3154-
TypeCache[origMetadataPtr] = BuiltObjCClass;
3171+
TypeCache[{origMetadataPtr, skipArtificialSubclasses}] = BuiltObjCClass;
31553172
return BuiltObjCClass;
31563173
}
31573174

0 commit comments

Comments
 (0)