@@ -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 ||
@@ -3275,8 +3294,6 @@ void LValue::addMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
3275
3294
using MemberStorageAccessEmitter::MemberStorageAccessEmitter;
3276
3295
3277
3296
void emitUsingStorage (LValueTypeData typeData) {
3278
- assert (!ActorIso);
3279
-
3280
3297
// For static variables, emit a reference to the global variable backing
3281
3298
// them.
3282
3299
// FIXME: This has to be dynamically looked up for classes, and
@@ -3290,7 +3307,7 @@ void LValue::addMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
3290
3307
typeData.getAccessKind (),
3291
3308
AccessStrategy::getStorage (),
3292
3309
FormalRValueType,
3293
- /* actorIsolation= */ None );
3310
+ ActorIso );
3294
3311
return ;
3295
3312
}
3296
3313
@@ -3299,10 +3316,12 @@ void LValue::addMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
3299
3316
SGF.getTypeExpansionContext (), Storage, FormalRValueType);
3300
3317
3301
3318
if (BaseFormalType->mayHaveSuperclass ()) {
3302
- LV.add <RefElementComponent>(Storage, Options, varStorageType, typeData);
3319
+ LV.add <RefElementComponent>(Storage, Options, varStorageType,
3320
+ typeData, ActorIso);
3303
3321
} else {
3304
3322
assert (BaseFormalType->getStructOrBoundGenericStruct ());
3305
- LV.add <StructElementComponent>(Storage, varStorageType, typeData);
3323
+ LV.add <StructElementComponent>(Storage, varStorageType, typeData,
3324
+ ActorIso);
3306
3325
}
3307
3326
3308
3327
// If the member has weak or unowned storage, convert it away.
@@ -4175,18 +4194,17 @@ RValue SILGenFunction::emitLoadOfLValue(SILLocation loc, LValue &&src,
4175
4194
4176
4195
// If the last component is physical, drill down and load from it.
4177
4196
if (component.isPhysical ()) {
4178
- auto actorIso = component.asPhysical ().getActorIsolation ();
4179
-
4180
- // If the load must happen in the context of an actor, do a hop first.
4181
- prevExecutor = emitHopToTargetActor (loc, actorIso, /* actorSelf=*/ None);
4182
-
4183
4197
auto projection = std::move (component).project (*this , loc, addr);
4184
4198
if (projection.getType ().isAddress ()) {
4199
+ auto actorIso = component.asPhysical ().takeActorIsolation ();
4200
+
4201
+ // If the load must happen in the context of an actor, do a hop first.
4202
+ prevExecutor = emitHopToTargetActor (loc, actorIso, /* actorSelf=*/ None);
4185
4203
projection =
4186
4204
emitLoad (loc, projection.getValue (), origFormalType,
4187
4205
substFormalType, rvalueTL, C, IsNotTake, isBaseGuaranteed);
4188
4206
} else if (isReadAccessResultOwned (src.getAccessKind ()) &&
4189
- !projection.isPlusOne (*this )) {
4207
+ !projection.isPlusOne (*this )) {
4190
4208
projection = projection.copy (*this , loc);
4191
4209
}
4192
4210
@@ -4199,7 +4217,6 @@ RValue SILGenFunction::emitLoadOfLValue(SILLocation loc, LValue &&src,
4199
4217
4200
4218
// If we hopped to the target's executor, then we need to hop back.
4201
4219
prevExecutor.emit (*this , loc);
4202
-
4203
4220
return result;
4204
4221
}
4205
4222
0 commit comments