Skip to content

Commit 15ecd66

Browse files
authored
Merge pull request #80845 from DougGregor/relative-witness-tables-fixes-6.2
[6.2] Relative witness table fixes
2 parents d1470fe + 77caa2d commit 15ecd66

File tree

2 files changed

+59
-20
lines changed

2 files changed

+59
-20
lines changed

stdlib/public/Concurrency/Actor.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,13 @@ extern "C" SWIFT_CC(swift) void _swift_task_enqueueOnExecutor(
506506
static swift_task_is_current_executor_flag
507507
_getIsolationCheckingOptionsFromExecutorWitnessTable(const SerialExecutorWitnessTable *_wtable) {
508508
const WitnessTable* wtable = reinterpret_cast<const WitnessTable*>(_wtable);
509+
#if SWIFT_STDLIB_USE_RELATIVE_PROTOCOL_WITNESS_TABLES
510+
auto description = lookThroughOptionalConditionalWitnessTable(
511+
reinterpret_cast<const RelativeWitnessTable*>(wtable))
512+
->getDescription();
513+
#else
509514
auto description = wtable->getDescription();
515+
#endif
510516
if (!description) {
511517
return swift_task_is_current_executor_flag::None;
512518
}

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ static bool _checkWitnessTableIsolation(
444444
llvm::ArrayRef<const void *> conditionalArgs,
445445
ConformanceExecutionContext &context
446446
) {
447-
#if SWIFT_STDLIB_USE_RELATIVE_PROTOCOL_WITNESS_TABLES && SWIFT_PTRAUTH
447+
#if SWIFT_STDLIB_USE_RELATIVE_PROTOCOL_WITNESS_TABLES
448448
auto description = lookThroughOptionalConditionalWitnessTable(
449449
reinterpret_cast<const RelativeWitnessTable *>(wtable))
450450
->getDescription();
@@ -537,47 +537,80 @@ namespace {
537537

538538
struct ConformanceCacheEntry {
539539
private:
540-
ConformanceCacheKey Key;
540+
/// Storage used when we have global actor isolation on the conformance.
541+
struct ExtendedStorage {
542+
/// The protocol to which the type conforms.
543+
const ProtocolDescriptor *Proto;
544+
545+
/// The global actor to which this conformance is isolated, or NULL for
546+
/// a nonisolated conformances.
547+
const Metadata *globalActorIsolationType = nullptr;
548+
549+
/// When the conformance is global-actor-isolated, this is the conformance
550+
/// of globalActorIsolationType to GlobalActor.
551+
const WitnessTable *globalActorIsolationWitnessTable = nullptr;
552+
};
553+
554+
const Metadata *Type;
555+
llvm::PointerUnion<const ProtocolDescriptor *, const ExtendedStorage *>
556+
ProtoOrStorage;
541557

542-
/// The witness table or along with a bit that indicates whether the
543-
/// conformance is isolated to a global actor.
544-
llvm::PointerUnion<const WitnessTable *, const ConformanceLookupResult *>
545-
WitnessTableOrLookupResult;
558+
/// The witness table.
559+
const WitnessTable *Witness;
546560

547561
public:
548562
ConformanceCacheEntry(ConformanceCacheKey key,
549563
ConformanceLookupResult result)
550-
: Key(key) {
564+
: Type(key.Type), Witness(result.witnessTable)
565+
{
551566
if (result.globalActorIsolationType) {
552-
WitnessTableOrLookupResult = new ConformanceLookupResult(result);
567+
ProtoOrStorage = new ExtendedStorage{
568+
key.Proto, result.globalActorIsolationType,
569+
result.globalActorIsolationWitnessTable
570+
};
553571
} else {
554-
WitnessTableOrLookupResult = result.witnessTable;
572+
ProtoOrStorage = key.Proto;
555573
}
556574
}
557575

558576
bool matchesKey(const ConformanceCacheKey &key) const {
559-
return Key.Type == key.Type && Key.Proto == key.Proto;
577+
return Type == key.Type && getProtocol() == key.Proto;
560578
}
561579

562580
friend llvm::hash_code hash_value(const ConformanceCacheEntry &entry) {
563-
return hash_value(entry.Key);
581+
return hash_value(entry.getKey());
582+
}
583+
584+
/// Get the protocol.
585+
const ProtocolDescriptor *getProtocol() const {
586+
if (auto proto = ProtoOrStorage.dyn_cast<const ProtocolDescriptor *>())
587+
return proto;
588+
589+
if (auto storage = ProtoOrStorage.dyn_cast<const ExtendedStorage *>())
590+
return storage->Proto;
591+
592+
return nullptr;
593+
}
594+
595+
/// Get the conformance cache key.
596+
ConformanceCacheKey getKey() const {
597+
return ConformanceCacheKey(Type, getProtocol());
564598
}
565599

566600
/// Get the cached witness table, or null if we cached failure.
567601
const WitnessTable *getWitnessTable() const {
568-
if (auto witnessTable = WitnessTableOrLookupResult.dyn_cast<const WitnessTable *>())
569-
return witnessTable;
570-
571-
return WitnessTableOrLookupResult.get<const ConformanceLookupResult *>()
572-
->witnessTable;
602+
return Witness;
573603
}
574604

575605
ConformanceLookupResult getResult() const {
576-
if (auto witnessTable = WitnessTableOrLookupResult.dyn_cast<const WitnessTable *>())
577-
return ConformanceLookupResult { witnessTable, nullptr, nullptr };
606+
if (ProtoOrStorage.is<const ProtocolDescriptor *>())
607+
return ConformanceLookupResult { Witness, nullptr, nullptr };
578608

579-
if (auto lookupResult = WitnessTableOrLookupResult.dyn_cast<const ConformanceLookupResult *>())
580-
return *lookupResult;
609+
if (auto storage = ProtoOrStorage.dyn_cast<const ExtendedStorage *>()) {
610+
return ConformanceLookupResult(
611+
Witness, storage->globalActorIsolationType,
612+
storage->globalActorIsolationWitnessTable);
613+
}
581614

582615
return nullptr;
583616
}

0 commit comments

Comments
 (0)