Skip to content

Commit dfbe7c1

Browse files
committed
[rbi] Refactor out code for handling ref_element_addr so I can use it for class_methods as well.
The two pieces of code are fundamentally doing the same thing so I can reuse the code. I am doing the refactoring as a separate change so that it is easier to review.
1 parent 13937fd commit dfbe7c1

File tree

1 file changed

+58
-41
lines changed

1 file changed

+58
-41
lines changed

lib/SILOptimizer/Utils/SILIsolationInfo.cpp

Lines changed: 58 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,61 @@ static bool isPartialApplyNonisolatedUnsafe(PartialApplyInst *pai) {
426426
return foundOneNonIsolatedUnsafe;
427427
}
428428

429+
/// Return the SILIsolationInfo for a class field.
430+
///
431+
/// \arg queriedValue the actual value that SILIsolationInfo::get was called
432+
/// upon. This is used for IsolationHistory.
433+
///
434+
/// \arg classValue this is the actual underlying class value that we are
435+
/// extracting a field out of. As an example this is the base passed to
436+
/// ref_element_addr or class_method.
437+
///
438+
/// \arg field the actual AST field that we discovered we are querying. This
439+
/// could be the field of the ref_element_addr or an accessor decl extracted
440+
/// from a SILDeclRef of a class_method.
441+
static SILIsolationInfo computeIsolationForClassField(SILValue queriedValue,
442+
SILValue classValue,
443+
ValueDecl *field) {
444+
auto varIsolation = swift::getActorIsolation(field);
445+
446+
// If we have a global actor isolated field, then we know that we override
447+
// the actual isolation of the actor or global actor isolated class with
448+
// some other form of isolation. In such a case, we need to use that
449+
// isolation instead.
450+
if (varIsolation.isGlobalActor()) {
451+
assert(!varIsolation.isNonisolatedUnsafe() &&
452+
"Cannot apply both nonisolated(unsafe) and a global actor attribute "
453+
"to the same declaration");
454+
return SILIsolationInfo::getGlobalActorIsolated(
455+
queriedValue, varIsolation.getGlobalActor());
456+
}
457+
458+
if (auto instance = ActorInstance::getForValue(classValue)) {
459+
if (auto *fArg = llvm::dyn_cast_or_null<SILFunctionArgument>(
460+
instance.maybeGetValue())) {
461+
if (auto info =
462+
SILIsolationInfo::getActorInstanceIsolated(queriedValue, fArg))
463+
return info.withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe());
464+
}
465+
}
466+
467+
auto *nomDecl = classValue->getType().getNominalOrBoundGenericNominal();
468+
469+
if (nomDecl->isAnyActor())
470+
return SILIsolationInfo::getActorInstanceIsolated(queriedValue, classValue,
471+
nomDecl)
472+
.withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe());
473+
474+
if (auto isolation = swift::getActorIsolation(nomDecl);
475+
isolation && isolation.isGlobalActor()) {
476+
return SILIsolationInfo::getGlobalActorIsolated(queriedValue,
477+
isolation.getGlobalActor())
478+
.withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe());
479+
}
480+
481+
return SILIsolationInfo::getDisconnected(varIsolation.isNonisolatedUnsafe());
482+
}
483+
429484
SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) {
430485
if (auto fas = FullApplySite::isa(inst)) {
431486
// Before we do anything, see if we have a sending result. In such a case,
@@ -594,48 +649,10 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) {
594649
return SILIsolationInfo::getDisconnected(partialApplyIsNonIsolatedUnsafe);
595650
}
596651

597-
// See if the memory base is a ref_element_addr from an address. If so, add
598-
// the actor derived flag.
599-
//
600-
// This is important so we properly handle setters.
652+
// See if the memory base is a ref_element_addr from an address.
601653
if (auto *rei = dyn_cast<RefElementAddrInst>(inst)) {
602-
auto varIsolation = swift::getActorIsolation(rei->getField());
603-
604-
// If we have a global actor isolated field, then we know that we override
605-
// the actual isolation of the actor or global actor isolated class with
606-
// some other form of isolation. In such a case, we need to use that
607-
// isolation instead.
608-
if (varIsolation.isGlobalActor()) {
609-
return SILIsolationInfo::getGlobalActorIsolated(
610-
rei, varIsolation.getGlobalActor())
611-
.withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe());
612-
}
613-
614-
if (auto instance = ActorInstance::getForValue(rei->getOperand())) {
615-
if (auto *fArg = llvm::dyn_cast_or_null<SILFunctionArgument>(
616-
instance.maybeGetValue())) {
617-
if (auto info = SILIsolationInfo::getActorInstanceIsolated(rei, fArg))
618-
return info.withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe());
619-
}
620-
}
621-
622-
auto *nomDecl =
623-
rei->getOperand()->getType().getNominalOrBoundGenericNominal();
624-
625-
if (nomDecl->isAnyActor())
626-
return SILIsolationInfo::getActorInstanceIsolated(rei, rei->getOperand(),
627-
nomDecl)
628-
.withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe());
629-
630-
if (auto isolation = swift::getActorIsolation(nomDecl);
631-
isolation && isolation.isGlobalActor()) {
632-
return SILIsolationInfo::getGlobalActorIsolated(
633-
rei, isolation.getGlobalActor())
634-
.withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe());
635-
}
636-
637-
return SILIsolationInfo::getDisconnected(
638-
varIsolation.isNonisolatedUnsafe());
654+
return computeIsolationForClassField(rei, rei->getOperand(),
655+
rei->getField());
639656
}
640657

641658
// Check if we have a global_addr inst.

0 commit comments

Comments
 (0)