@@ -537,9 +537,13 @@ namespace {
537
537
};
538
538
539
539
class EndAccessPseudoComponent : public WritebackPseudoComponent {
540
+ private:
541
+ ExecutorBreadcrumb ExecutorHop;
540
542
public:
541
- EndAccessPseudoComponent (const LValueTypeData &typeData)
542
- : WritebackPseudoComponent(typeData) {}
543
+ EndAccessPseudoComponent (const LValueTypeData &typeData,
544
+ ExecutorBreadcrumb &&executorHop)
545
+ : WritebackPseudoComponent(typeData),
546
+ ExecutorHop (std::move(executorHop)) {}
543
547
544
548
private:
545
549
void writeback (SILGenFunction &SGF, SILLocation loc,
@@ -550,6 +554,7 @@ namespace {
550
554
551
555
assert (base.isLValue ());
552
556
SGF.B .createEndAccess (loc, base.getValue (), /* abort*/ false );
557
+ ExecutorHop.emit (SGF, loc);
553
558
}
554
559
555
560
void dump (raw_ostream &OS, unsigned indent) const override {
@@ -561,13 +566,19 @@ namespace {
561
566
static SILValue enterAccessScope (SILGenFunction &SGF, SILLocation loc,
562
567
SILValue addr, LValueTypeData typeData,
563
568
SGFAccessKind accessKind,
564
- SILAccessEnforcement enforcement) {
569
+ SILAccessEnforcement enforcement,
570
+ Optional<ActorIsolation> actorIso) {
565
571
auto silAccessKind = isReadAccess (accessKind) ? SILAccessKind::Read
566
572
: SILAccessKind::Modify;
567
573
568
574
assert (SGF.isInFormalEvaluationScope () &&
569
575
" tried to enter access scope without a writeback scope!" );
570
576
577
+ // Only expecting global-actor isolation here, since there's no base / self.
578
+ assert (!actorIso || actorIso->isGlobalActor ());
579
+ ExecutorBreadcrumb prevExecutor =
580
+ SGF.emitHopToTargetActor (loc, actorIso, /* maybeSelf=*/ None);
581
+
571
582
// Enter the access.
572
583
addr = SGF.B .createBeginAccess (loc, addr, silAccessKind, enforcement,
573
584
/* hasNoNestedConflict=*/ false ,
@@ -576,7 +587,8 @@ static SILValue enterAccessScope(SILGenFunction &SGF, SILLocation loc,
576
587
// Push a writeback to end it.
577
588
auto accessedMV = ManagedValue::forLValue (addr);
578
589
std::unique_ptr<LogicalPathComponent>
579
- component (new EndAccessPseudoComponent (typeData));
590
+ component (new EndAccessPseudoComponent (typeData,
591
+ std::move (prevExecutor)));
580
592
pushWriteback (SGF, loc, std::move (component), accessedMV,
581
593
MaterializedLValue ());
582
594
@@ -586,10 +598,11 @@ static SILValue enterAccessScope(SILGenFunction &SGF, SILLocation loc,
586
598
static ManagedValue enterAccessScope (SILGenFunction &SGF, SILLocation loc,
587
599
ManagedValue addr, LValueTypeData typeData,
588
600
SGFAccessKind accessKind,
589
- SILAccessEnforcement enforcement) {
601
+ SILAccessEnforcement enforcement,
602
+ Optional<ActorIsolation> actorIso) {
590
603
return ManagedValue::forLValue (
591
604
enterAccessScope (SGF, loc, addr.getLValueAddress (), typeData,
592
- accessKind, enforcement));
605
+ accessKind, enforcement, actorIso ));
593
606
}
594
607
595
608
// Find the base of the formal access at `address`. If the base requires an
@@ -717,8 +730,9 @@ namespace {
717
730
bool IsNonAccessing;
718
731
public:
719
732
RefElementComponent (VarDecl *field, LValueOptions options,
720
- SILType substFieldType, LValueTypeData typeData)
721
- : PhysicalPathComponent(typeData, RefElementKind),
733
+ SILType substFieldType, LValueTypeData typeData,
734
+ Optional<ActorIsolation> actorIso)
735
+ : PhysicalPathComponent(typeData, RefElementKind, actorIso),
722
736
Field (field), SubstFieldType(substFieldType),
723
737
IsNonAccessing(options.IsNonAccessing) {}
724
738
@@ -745,7 +759,8 @@ namespace {
745
759
if (!IsNonAccessing && !Field->isLet ()) {
746
760
if (auto enforcement = SGF.getDynamicEnforcement (Field)) {
747
761
result = enterAccessScope (SGF, loc, result, getTypeData (),
748
- getAccessKind (), *enforcement);
762
+ getAccessKind (), *enforcement,
763
+ takeActorIsolation ());
749
764
}
750
765
}
751
766
@@ -761,7 +776,8 @@ namespace {
761
776
unsigned ElementIndex;
762
777
public:
763
778
TupleElementComponent (unsigned elementIndex, LValueTypeData typeData)
764
- : PhysicalPathComponent(typeData, TupleElementKind),
779
+ : PhysicalPathComponent(typeData, TupleElementKind,
780
+ /* actorIsolation=*/ None),
765
781
ElementIndex (elementIndex) {}
766
782
767
783
virtual bool isLoadingPure () const override { return true ; }
@@ -790,8 +806,9 @@ namespace {
790
806
SILType SubstFieldType;
791
807
public:
792
808
StructElementComponent (VarDecl *field, SILType substFieldType,
793
- LValueTypeData typeData)
794
- : PhysicalPathComponent(typeData, StructElementKind),
809
+ LValueTypeData typeData,
810
+ Optional<ActorIsolation> actorIso)
811
+ : PhysicalPathComponent(typeData, StructElementKind, actorIso),
795
812
Field (field), SubstFieldType(substFieldType) {}
796
813
797
814
virtual bool isLoadingPure () const override { return true ; }
@@ -819,9 +836,9 @@ namespace {
819
836
class ForceOptionalObjectComponent : public PhysicalPathComponent {
820
837
bool isImplicitUnwrap;
821
838
public:
822
- ForceOptionalObjectComponent (LValueTypeData typeData,
823
- bool isImplicitUnwrap)
824
- : PhysicalPathComponent(typeData, OptionalObjectKind ),
839
+ ForceOptionalObjectComponent (LValueTypeData typeData, bool isImplicitUnwrap)
840
+ : PhysicalPathComponent(typeData, OptionalObjectKind,
841
+ /* actorIsolation= */ None ),
825
842
isImplicitUnwrap (isImplicitUnwrap) {}
826
843
827
844
ManagedValue project (SILGenFunction &SGF, SILLocation loc,
@@ -842,7 +859,8 @@ namespace {
842
859
public:
843
860
OpenOpaqueExistentialComponent (CanArchetypeType openedArchetype,
844
861
LValueTypeData typeData)
845
- : PhysicalPathComponent(typeData, OpenOpaqueExistentialKind) {
862
+ : PhysicalPathComponent(typeData, OpenOpaqueExistentialKind,
863
+ /* actorIsolation=*/ None) {
846
864
assert (getSubstFormalType () == openedArchetype);
847
865
}
848
866
@@ -1017,7 +1035,8 @@ namespace {
1017
1035
1018
1036
SILValue addr = Value.getLValueAddress ();
1019
1037
addr = enterAccessScope (SGF, loc, addr, getTypeData (),
1020
- getAccessKind (), *Enforcement);
1038
+ getAccessKind (), *Enforcement,
1039
+ takeActorIsolation ());
1021
1040
1022
1041
return ManagedValue::forLValue (addr);
1023
1042
}
@@ -1034,10 +1053,7 @@ namespace {
1034
1053
} else {
1035
1054
OS << " unenforced" ;
1036
1055
}
1037
- if (ActorIso) {
1038
- OS << " requires actor-hop because " ;
1039
- simple_display (OS, *ActorIso);
1040
- }
1056
+ if (hasActorIsolation ()) OS << " requires actor-hop" ;
1041
1057
OS << " ):\n " ;
1042
1058
Value.dump (OS, indent + 2 );
1043
1059
}
@@ -1451,11 +1467,12 @@ namespace {
1451
1467
backingVar, AccessKind::Write);
1452
1468
} else if (BaseFormalType->mayHaveSuperclass ()) {
1453
1469
RefElementComponent REC (backingVar, LValueOptions (), varStorageType,
1454
- typeData);
1470
+ typeData, /* actorIsolation= */ None );
1455
1471
proj = std::move (REC).project (SGF, loc, base);
1456
1472
} else {
1457
1473
assert (BaseFormalType->getStructOrBoundGenericStruct ());
1458
- StructElementComponent SEC (backingVar, varStorageType, typeData);
1474
+ StructElementComponent SEC (backingVar, varStorageType,
1475
+ typeData, /* actorIsolation=*/ None);
1459
1476
proj = std::move (SEC).project (SGF, loc, base);
1460
1477
}
1461
1478
@@ -1782,7 +1799,8 @@ namespace {
1782
1799
1783
1800
// Enter an unsafe access scope for the access.
1784
1801
addr = enterAccessScope (SGF, loc, addr, getTypeData (), getAccessKind (),
1785
- SILAccessEnforcement::Unsafe);
1802
+ SILAccessEnforcement::Unsafe,
1803
+ ActorIso);
1786
1804
1787
1805
return addr;
1788
1806
}
@@ -2087,7 +2105,8 @@ namespace {
2087
2105
PhysicalKeyPathApplicationComponent (LValueTypeData typeData,
2088
2106
KeyPathTypeKind typeKind,
2089
2107
ManagedValue keyPath)
2090
- : PhysicalPathComponent(typeData, PhysicalKeyPathApplicationKind),
2108
+ : PhysicalPathComponent(typeData, PhysicalKeyPathApplicationKind,
2109
+ /* actorIsolation=*/ None),
2091
2110
TypeKind (typeKind), KeyPath(keyPath) {
2092
2111
assert (typeKind == KPTK_KeyPath ||
2093
2112
typeKind == KPTK_WritableKeyPath ||
@@ -3274,8 +3293,6 @@ void LValue::addMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
3274
3293
using MemberStorageAccessEmitter::MemberStorageAccessEmitter;
3275
3294
3276
3295
void emitUsingStorage (LValueTypeData typeData) {
3277
- assert (!ActorIso);
3278
-
3279
3296
// For static variables, emit a reference to the global variable backing
3280
3297
// them.
3281
3298
// FIXME: This has to be dynamically looked up for classes, and
@@ -3289,7 +3306,7 @@ void LValue::addMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
3289
3306
typeData.getAccessKind (),
3290
3307
AccessStrategy::getStorage (),
3291
3308
FormalRValueType,
3292
- /* actorIsolation= */ None );
3309
+ ActorIso );
3293
3310
return ;
3294
3311
}
3295
3312
@@ -3298,10 +3315,12 @@ void LValue::addMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
3298
3315
SGF.getTypeExpansionContext (), Storage, FormalRValueType);
3299
3316
3300
3317
if (BaseFormalType->mayHaveSuperclass ()) {
3301
- LV.add <RefElementComponent>(Storage, Options, varStorageType, typeData);
3318
+ LV.add <RefElementComponent>(Storage, Options, varStorageType,
3319
+ typeData, ActorIso);
3302
3320
} else {
3303
3321
assert (BaseFormalType->getStructOrBoundGenericStruct ());
3304
- LV.add <StructElementComponent>(Storage, varStorageType, typeData);
3322
+ LV.add <StructElementComponent>(Storage, varStorageType, typeData,
3323
+ ActorIso);
3305
3324
}
3306
3325
3307
3326
// If the member has weak or unowned storage, convert it away.
@@ -4174,18 +4193,17 @@ RValue SILGenFunction::emitLoadOfLValue(SILLocation loc, LValue &&src,
4174
4193
4175
4194
// If the last component is physical, drill down and load from it.
4176
4195
if (component.isPhysical ()) {
4177
- auto actorIso = component.asPhysical ().getActorIsolation ();
4178
-
4179
- // If the load must happen in the context of an actor, do a hop first.
4180
- prevExecutor = emitHopToTargetActor (loc, actorIso, /* actorSelf=*/ None);
4181
-
4182
4196
auto projection = std::move (component).project (*this , loc, addr);
4183
4197
if (projection.getType ().isAddress ()) {
4198
+ auto actorIso = component.asPhysical ().takeActorIsolation ();
4199
+
4200
+ // If the load must happen in the context of an actor, do a hop first.
4201
+ prevExecutor = emitHopToTargetActor (loc, actorIso, /* actorSelf=*/ None);
4184
4202
projection =
4185
4203
emitLoad (loc, projection.getValue (), origFormalType,
4186
4204
substFormalType, rvalueTL, C, IsNotTake, isBaseGuaranteed);
4187
4205
} else if (isReadAccessResultOwned (src.getAccessKind ()) &&
4188
- !projection.isPlusOne (*this )) {
4206
+ !projection.isPlusOne (*this )) {
4189
4207
projection = projection.copy (*this , loc);
4190
4208
}
4191
4209
@@ -4198,7 +4216,6 @@ RValue SILGenFunction::emitLoadOfLValue(SILLocation loc, LValue &&src,
4198
4216
4199
4217
// If we hopped to the target's executor, then we need to hop back.
4200
4218
prevExecutor.emit (*this , loc);
4201
-
4202
4219
return result;
4203
4220
}
4204
4221
0 commit comments