Skip to content

Commit 1da926b

Browse files
authored
Merge pull request #16801 from mikeash/fix-metadatalookup-deadlocks-4.2
[Runtime] 4.2 - Change MetadataLookup section vectors to use ConcurrentReadableArray.
2 parents 805c1d3 + 3a58a26 commit 1da926b

File tree

1 file changed

+13
-36
lines changed

1 file changed

+13
-36
lines changed

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include "swift/Runtime/Concurrent.h"
2424
#include "swift/Runtime/HeapObject.h"
2525
#include "swift/Runtime/Metadata.h"
26-
#include "swift/Runtime/Mutex.h"
2726
#include "swift/Strings.h"
2827
#include "llvm/ADT/DenseMap.h"
2928
#include "llvm/ADT/Optional.h"
@@ -106,11 +105,9 @@ namespace {
106105

107106
struct TypeMetadataPrivateState {
108107
ConcurrentMap<NominalTypeDescriptorCacheEntry> NominalCache;
109-
std::vector<TypeMetadataSection> SectionsToScan;
110-
Mutex SectionsToScanLock;
108+
ConcurrentReadableArray<TypeMetadataSection> SectionsToScan;
111109

112110
TypeMetadataPrivateState() {
113-
SectionsToScan.reserve(16);
114111
initializeTypeMetadataRecordLookup();
115112
}
116113

@@ -122,7 +119,6 @@ static void
122119
_registerTypeMetadataRecords(TypeMetadataPrivateState &T,
123120
const TypeMetadataRecord *begin,
124121
const TypeMetadataRecord *end) {
125-
ScopedLock guard(T.SectionsToScanLock);
126122
T.SectionsToScan.push_back(TypeMetadataSection{begin, end});
127123
}
128124

@@ -296,12 +292,9 @@ swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
296292

297293
// returns the nominal type descriptor for the type named by typeName
298294
static const TypeContextDescriptor *
299-
_searchTypeMetadataRecords(const TypeMetadataPrivateState &T,
295+
_searchTypeMetadataRecords(TypeMetadataPrivateState &T,
300296
Demangle::NodePointer node) {
301-
unsigned sectionIdx = 0;
302-
unsigned endSectionIdx = T.SectionsToScan.size();
303-
for (; sectionIdx < endSectionIdx; ++sectionIdx) {
304-
auto &section = T.SectionsToScan[sectionIdx];
297+
for (auto &section : T.SectionsToScan.snapshot()) {
305298
for (const auto &record : section) {
306299
if (auto ntd = record.getTypeContextDescriptor()) {
307300
if (_contextDescriptorMatchesMangling(ntd, node)) {
@@ -342,9 +335,7 @@ _findNominalTypeDescriptor(Demangle::NodePointer node,
342335
return Value->getDescription();
343336

344337
// Check type metadata records
345-
T.SectionsToScanLock.withLock([&] {
346-
foundNominal = _searchTypeMetadataRecords(T, node);
347-
});
338+
foundNominal = _searchTypeMetadataRecords(T, node);
348339

349340
// Check protocol conformances table. Note that this has no support for
350341
// resolving generic types yet.
@@ -395,11 +386,9 @@ namespace {
395386

396387
struct ProtocolMetadataPrivateState {
397388
ConcurrentMap<ProtocolDescriptorCacheEntry> ProtocolCache;
398-
std::vector<ProtocolSection> SectionsToScan;
399-
Mutex SectionsToScanLock;
389+
ConcurrentReadableArray<ProtocolSection> SectionsToScan;
400390

401391
ProtocolMetadataPrivateState() {
402-
SectionsToScan.reserve(16);
403392
initializeProtocolLookup();
404393
}
405394
};
@@ -411,7 +400,6 @@ static void
411400
_registerProtocols(ProtocolMetadataPrivateState &C,
412401
const ProtocolRecord *begin,
413402
const ProtocolRecord *end) {
414-
ScopedLock guard(C.SectionsToScanLock);
415403
C.SectionsToScan.push_back(ProtocolSection{begin, end});
416404
}
417405

@@ -439,12 +427,9 @@ void swift::swift_registerProtocols(const ProtocolRecord *begin,
439427
}
440428

441429
static const ProtocolDescriptor *
442-
_searchProtocolRecords(const ProtocolMetadataPrivateState &C,
430+
_searchProtocolRecords(ProtocolMetadataPrivateState &C,
443431
const llvm::StringRef protocolName){
444-
unsigned sectionIdx = 0;
445-
unsigned endSectionIdx = C.SectionsToScan.size();
446-
for (; sectionIdx < endSectionIdx; ++sectionIdx) {
447-
auto &section = C.SectionsToScan[sectionIdx];
432+
for (auto &section : C.SectionsToScan.snapshot()) {
448433
for (const auto &record : section) {
449434
if (auto protocol = record.Protocol.getPointer()) {
450435
// Drop the "S$" prefix from the protocol record. It's not used in
@@ -472,9 +457,7 @@ _findProtocolDescriptor(llvm::StringRef mangledName) {
472457
return Value->getDescription();
473458

474459
// Check type metadata records
475-
T.SectionsToScanLock.withLock([&] {
476-
foundProtocol = _searchProtocolRecords(T, mangledName);
477-
});
460+
foundProtocol = _searchProtocolRecords(T, mangledName);
478461

479462
if (foundProtocol) {
480463
T.ProtocolCache.getOrInsert(mangledName, foundProtocol);
@@ -534,21 +517,18 @@ class DynamicFieldSection {
534517
DynamicFieldSection(const FieldDescriptor **fields, size_t size)
535518
: Begin(fields), End(fields + size) {}
536519

537-
const FieldDescriptor **begin() { return Begin; }
520+
const FieldDescriptor **begin() const { return Begin; }
538521

539522
const FieldDescriptor **end() const { return End; }
540523
};
541524

542525
struct FieldCacheState {
543526
ConcurrentMap<FieldDescriptorCacheEntry> FieldCache;
544527

545-
Mutex SectionsLock;
546-
std::vector<StaticFieldSection> StaticSections;
547-
std::vector<DynamicFieldSection> DynamicSections;
528+
ConcurrentReadableArray<StaticFieldSection> StaticSections;
529+
ConcurrentReadableArray<DynamicFieldSection> DynamicSections;
548530

549531
FieldCacheState() {
550-
StaticSections.reserve(16);
551-
DynamicSections.reserve(8);
552532
initializeTypeFieldLookup();
553533
}
554534
};
@@ -559,7 +539,6 @@ static Lazy<FieldCacheState> FieldCache;
559539
void swift::swift_registerFieldDescriptors(const FieldDescriptor **records,
560540
size_t size) {
561541
auto &cache = FieldCache.get();
562-
ScopedLock guard(cache.SectionsLock);
563542
cache.DynamicSections.push_back({records, size});
564543
}
565544

@@ -570,7 +549,6 @@ void swift::addImageTypeFieldDescriptorBlockCallback(const void *recordsBegin,
570549

571550
// Field cache should always be sufficiently initialized by this point.
572551
auto &cache = FieldCache.unsafeGetAlreadyInitialized();
573-
ScopedLock guard(cache.SectionsLock);
574552
cache.StaticSections.push_back({recordsBegin, recordsEnd});
575553
}
576554

@@ -1216,16 +1194,15 @@ void swift::swift_getFieldAt(
12161194
return;
12171195
}
12181196

1219-
ScopedLock guard(cache.SectionsLock);
12201197
// Otherwise let's try to find it in one of the sections.
1221-
for (auto &section : cache.DynamicSections) {
1198+
for (auto &section : cache.DynamicSections.snapshot()) {
12221199
for (const auto *descriptor : section) {
12231200
if (isRequestedDescriptor(*descriptor))
12241201
return;
12251202
}
12261203
}
12271204

1228-
for (const auto &section : cache.StaticSections) {
1205+
for (const auto &section : cache.StaticSections.snapshot()) {
12291206
for (auto &descriptor : section) {
12301207
if (isRequestedDescriptor(descriptor))
12311208
return;

0 commit comments

Comments
 (0)