@@ -224,6 +224,7 @@ class SILIsolationInfo {
224
224
};
225
225
226
226
class Partition ;
227
+ class TransferringOperandToStateMap ;
227
228
228
229
// / A persistent data structure that is used to "rewind" partition history so
229
230
// / that we can discover when values become part of the same region.
@@ -245,6 +246,7 @@ class IsolationHistory {
245
246
246
247
// TODO: This shouldn't need to be a friend.
247
248
friend class Partition ;
249
+ friend TransferringOperandToStateMap;
248
250
249
251
// / First node in the immutable linked list.
250
252
Node *head = nullptr ;
@@ -298,6 +300,11 @@ class IsolationHistory {
298
300
// / Push that \p other should be merged into this region.
299
301
void pushCFGHistoryJoin (Node *otherNode);
300
302
303
+ // / Push the top node of \p history as a CFG history join.
304
+ void pushCFGHistoryJoin (IsolationHistory history) {
305
+ return pushCFGHistoryJoin (history.getHead ());
306
+ }
307
+
301
308
Node *pop ();
302
309
};
303
310
@@ -457,10 +464,7 @@ class IsolationHistory::Factory {
457
464
IsolationHistory get () { return IsolationHistory (this ); }
458
465
};
459
466
460
- class TransferringOperand {
461
- using ValueType = llvm::PointerIntPair<Operand *, 1 >;
462
- ValueType value;
463
-
467
+ struct TransferringOperandState {
464
468
// / The dynamic isolation info of the region of value when we transferred.
465
469
// /
466
470
// / This will contain the isolated value if we found one.
@@ -469,65 +473,30 @@ class TransferringOperand {
469
473
// / The dynamic isolation history at this point.
470
474
IsolationHistory isolationHistory;
471
475
472
- TransferringOperand (ValueType newValue, SILIsolationInfo isolationRegionInfo,
473
- IsolationHistory isolationHistory)
474
- : value(newValue), isolationInfo(isolationRegionInfo),
475
- isolationHistory (isolationHistory) {
476
- assert (isolationInfo && " Should never see unknown isolation info" );
477
- }
478
-
479
- public:
480
- TransferringOperand (Operand *op, bool isClosureCaptured,
481
- SILIsolationInfo isolationRegionInfo,
482
- IsolationHistory isolationHistory)
483
- : TransferringOperand({op, isClosureCaptured}, isolationRegionInfo,
484
- isolationHistory) {}
485
- explicit TransferringOperand (Operand *op,
486
- SILIsolationInfo isolationRegionInfo,
487
- IsolationHistory isolationHistory)
488
- : TransferringOperand({op, false }, isolationRegionInfo,
489
- isolationHistory) {}
490
-
491
- operator bool () const { return bool (value.getPointer ()); }
492
-
493
- Operand *getOperand () const { return value.getPointer (); }
494
-
495
- SILValue get () const { return getOperand ()->get (); }
496
-
497
- bool isClosureCaptured () const { return value.getInt (); }
498
-
499
- SILInstruction *getUser () const { return getOperand ()->getUser (); }
476
+ // / Set to true if the element associated with the operand's vlaue is closure
477
+ // / captured by the user. In such a case, if our element is a sendable var of
478
+ // / a non-Sendable type, we cannot access it since we could race against an
479
+ // / assignment to the var in a closure.
480
+ bool isClosureCaptured;
500
481
501
- SILIsolationInfo getIsolationInfo () const { return isolationInfo; }
502
-
503
- IsolationHistory getIsolationHistory () const { return isolationHistory; }
504
-
505
- unsigned getOperandNumber () const { return getOperand ()->getOperandNumber (); }
506
-
507
- void print (llvm::raw_ostream &os) const {
508
- os << " Op Num: " << getOperand ()->getOperandNumber () << " . "
509
- << " Capture: " << (isClosureCaptured () ? " yes. " : " no. " )
510
- << " IsolationInfo: " ;
511
- isolationInfo.print (os);
512
- os << " \n User: " << *getUser ();
513
- }
482
+ TransferringOperandState (IsolationHistory history)
483
+ : isolationInfo(), isolationHistory(history), isClosureCaptured(false ) {}
484
+ };
514
485
515
- static void Profile (llvm::FoldingSetNodeID &id, Operand *op,
516
- bool isClosureCaptured,
517
- SILIsolationInfo isolationRegionInfo,
518
- IsolationHistory isolationHistory) {
519
- id.AddPointer (op);
520
- id.AddBoolean (isClosureCaptured);
521
- isolationRegionInfo.Profile (id);
522
- id.AddPointer (isolationHistory.getHead ());
523
- }
486
+ class TransferringOperandToStateMap {
487
+ llvm::SmallDenseMap<Operand *, TransferringOperandState> internalMap;
488
+ IsolationHistory::Factory &isolationHistoryFactory;
524
489
525
- void Profile (llvm::FoldingSetNodeID &id) const {
526
- Profile (id, getOperand (), isClosureCaptured (), isolationInfo,
527
- isolationHistory);
490
+ public:
491
+ TransferringOperandToStateMap (
492
+ IsolationHistory::Factory &isolationHistoryFactory)
493
+ : isolationHistoryFactory(isolationHistoryFactory) {}
494
+ TransferringOperandState &get (Operand *op) const {
495
+ auto *self = const_cast <TransferringOperandToStateMap *>(this );
496
+ auto history = IsolationHistory (&isolationHistoryFactory);
497
+ return self->internalMap .try_emplace (op, TransferringOperandState (history))
498
+ .first ->getSecond ();
528
499
}
529
-
530
- SWIFT_DEBUG_DUMP { print (llvm::dbgs ()); }
531
500
};
532
501
533
502
} // namespace swift
@@ -676,9 +645,8 @@ class Partition {
676
645
677
646
using Element = PartitionPrimitives::Element;
678
647
using Region = PartitionPrimitives::Region;
679
- using TransferringOperandSet = ImmutablePointerSet<TransferringOperand *>;
680
- using TransferringOperandSetFactory =
681
- ImmutablePointerSetFactory<TransferringOperand *>;
648
+ using TransferringOperandSet = ImmutablePointerSet<Operand *>;
649
+ using TransferringOperandSetFactory = ImmutablePointerSetFactory<Operand *>;
682
650
using IsolationHistoryNode = IsolationHistory::Node;
683
651
684
652
private:
@@ -1014,13 +982,16 @@ struct PartitionOpEvaluator {
1014
982
1015
983
protected:
1016
984
TransferringOperandSetFactory &ptrSetFactory;
985
+ TransferringOperandToStateMap &operandToStateMap;
1017
986
1018
987
Partition &p;
1019
988
1020
989
public:
1021
990
PartitionOpEvaluator (Partition &p,
1022
- TransferringOperandSetFactory &ptrSetFactory)
1023
- : ptrSetFactory(ptrSetFactory), p(p) {}
991
+ TransferringOperandSetFactory &ptrSetFactory,
992
+ TransferringOperandToStateMap &operandToStateMap)
993
+ : ptrSetFactory(ptrSetFactory), operandToStateMap(operandToStateMap),
994
+ p (p) {}
1024
995
1025
996
// / Call shouldEmitVerboseLogging on our CRTP subclass.
1026
997
bool shouldEmitVerboseLogging () const {
@@ -1029,7 +1000,7 @@ struct PartitionOpEvaluator {
1029
1000
1030
1001
// / Call handleLocalUseAfterTransfer on our CRTP subclass.
1031
1002
void handleLocalUseAfterTransfer (const PartitionOp &op, Element elt,
1032
- TransferringOperand *transferringOp) const {
1003
+ Operand *transferringOp) const {
1033
1004
return asImpl ().handleLocalUseAfterTransfer (op, elt, transferringOp);
1034
1005
}
1035
1006
@@ -1194,9 +1165,13 @@ struct PartitionOpEvaluator {
1194
1165
}
1195
1166
1196
1167
// Mark op.getOpArgs()[0] as transferred.
1197
- auto *ptrSet = ptrSetFactory.emplace (
1198
- op.getSourceOp (), isClosureCapturedElt, transferredRegionIsolation,
1199
- p.getIsolationHistory ());
1168
+ TransferringOperandState &state = operandToStateMap.get (op.getSourceOp ());
1169
+ state.isClosureCaptured |= isClosureCapturedElt;
1170
+ state.isolationInfo =
1171
+ state.isolationInfo .merge (transferredRegionIsolation);
1172
+ assert (state.isolationInfo && " Cannot have unknown" );
1173
+ state.isolationHistory .pushCFGHistoryJoin (p.getIsolationHistory ());
1174
+ auto *ptrSet = ptrSetFactory.get (op.getSourceOp ());
1200
1175
p.markTransferred (op.getOpArgs ()[0 ], ptrSet);
1201
1176
return ;
1202
1177
}
@@ -1266,9 +1241,8 @@ struct PartitionOpEvaluator {
1266
1241
private:
1267
1242
// Private helper that squelches the error if our transfer instruction and our
1268
1243
// use have the same isolation.
1269
- void
1270
- handleLocalUseAfterTransferHelper (const PartitionOp &op, Element elt,
1271
- TransferringOperand *transferringOp) const {
1244
+ void handleLocalUseAfterTransferHelper (const PartitionOp &op, Element elt,
1245
+ Operand *transferringOp) const {
1272
1246
if (shouldTryToSquelchErrors ()) {
1273
1247
if (auto isolationInfo = SILIsolationInfo::get (op.getSourceInst ())) {
1274
1248
if (isolationInfo.isActorIsolated () &&
@@ -1306,8 +1280,9 @@ struct PartitionOpEvaluatorBaseImpl : PartitionOpEvaluator<Subclass> {
1306
1280
using Super = PartitionOpEvaluator<Subclass>;
1307
1281
1308
1282
PartitionOpEvaluatorBaseImpl (Partition &workingPartition,
1309
- TransferringOperandSetFactory &ptrSetFactory)
1310
- : Super(workingPartition, ptrSetFactory) {}
1283
+ TransferringOperandSetFactory &ptrSetFactory,
1284
+ TransferringOperandToStateMap &operandToStateMap)
1285
+ : Super(workingPartition, ptrSetFactory, operandToStateMap) {}
1311
1286
1312
1287
// / Should we emit extra verbose logging statements when evaluating
1313
1288
// / PartitionOps.
@@ -1326,7 +1301,7 @@ struct PartitionOpEvaluatorBaseImpl : PartitionOpEvaluator<Subclass> {
1326
1301
// / region. Can be used to get the immediate value transferred or the
1327
1302
// / transferring instruction.
1328
1303
void handleLocalUseAfterTransfer (const PartitionOp &op, Element elt,
1329
- TransferringOperand *transferringOp) const {}
1304
+ Operand *transferringOp) const {}
1330
1305
1331
1306
// / This is called if we detect a never transferred element that was passed to
1332
1307
// / a transfer instruction.
@@ -1374,8 +1349,10 @@ struct PartitionOpEvaluatorBaseImpl : PartitionOpEvaluator<Subclass> {
1374
1349
struct PartitionOpEvaluatorBasic final
1375
1350
: PartitionOpEvaluatorBaseImpl<PartitionOpEvaluatorBasic> {
1376
1351
PartitionOpEvaluatorBasic (Partition &workingPartition,
1377
- TransferringOperandSetFactory &ptrSetFactory)
1378
- : PartitionOpEvaluatorBaseImpl(workingPartition, ptrSetFactory) {}
1352
+ TransferringOperandSetFactory &ptrSetFactory,
1353
+ TransferringOperandToStateMap &operandToStateMap)
1354
+ : PartitionOpEvaluatorBaseImpl(workingPartition, ptrSetFactory,
1355
+ operandToStateMap) {}
1379
1356
};
1380
1357
1381
1358
} // namespace swift
0 commit comments