@@ -389,47 +389,55 @@ void EscapeAnalysis::ConnectionGraph::clear() {
389
389
assert (ToMerge.empty ());
390
390
}
391
391
392
+ // This never returns an interior node. It should never be called directly on an
393
+ // address projection of a reference. To get the interior node for an address
394
+ // projection, always ask for the content of the projection's base instead using
395
+ // getValueContent() or getReferenceContent().
396
+ //
397
+ // Address phis are not allowed, so merging an unknown address with a reference
398
+ // address projection is rare. If that happens, then the projection's node loses
399
+ // it's interior property.
392
400
EscapeAnalysis::CGNode *
393
- EscapeAnalysis::ConnectionGraph::getOrCreateNode (ValueBase *V,
394
- PointerKind pointerKind) {
395
- assert (pointerKind != EscapeAnalysis::NoPointer);
396
-
401
+ EscapeAnalysis::ConnectionGraph::getNode (SILValue V) {
402
+ // Early filter obvious non-pointer opcodes.
397
403
if (isa<FunctionRefInst>(V) || isa<DynamicFunctionRefInst>(V) ||
398
404
isa<PreviousDynamicFunctionRefInst>(V))
399
405
return nullptr ;
400
406
401
- CGNode * &Node = Values2Nodes[V];
402
- // Nodes mapped to values must have an indirect pointsTo. Nodes that don't
403
- // have an indirect pointsTo are imaginary nodes that don't directly represnt
404
- // a SIL value.
405
- bool hasReferenceOnly = canOnlyContainReferences (pointerKind);
406
- if (!Node) {
407
- if (isa<SILFunctionArgument>(V)) {
408
- Node = allocNode (V, NodeType::Argument, false , hasReferenceOnly);
409
- if (!isSummaryGraph)
410
- Node->mergeEscapeState (EscapeState::Arguments);
411
- } else {
412
- Node = allocNode (V, NodeType::Value, false , hasReferenceOnly);
413
- }
414
- }
415
- return Node->getMergeTarget ();
416
- }
417
-
418
- EscapeAnalysis::CGNode *
419
- EscapeAnalysis::ConnectionGraph::getNode (ValueBase *V, bool createIfNeeded) {
407
+ // Create the node flags based on the derived value's kind. If the pointer
408
+ // base type has non-reference pointers but they are never accessed in the
409
+ // current function, then ignore them.
420
410
PointerKind pointerKind = EA->getPointerKind (V);
421
411
if (pointerKind == EscapeAnalysis::NoPointer)
422
412
return nullptr ;
423
413
424
414
// Look past address projections, pointer casts, and the like within the same
425
415
// object. Does not look past a dereference such as ref_element_addr, or
426
416
// project_box.
427
- V = EA->getPointerRoot (V);
417
+ SILValue ptrBase = EA->getPointerRoot (V);
418
+ // Do not create a node for undef values so we can verify that node values
419
+ // have the correct pointer kind.
420
+ if (!ptrBase->getFunction ())
421
+ return nullptr ;
428
422
429
- if (!createIfNeeded)
430
- return lookupNode (V );
423
+ assert (EA-> isPointer (ptrBase) &&
424
+ " The base for derived pointer must also be a pointer type " );
431
425
432
- return getOrCreateNode (V, pointerKind);
426
+ bool hasReferenceOnly = canOnlyContainReferences (pointerKind);
427
+ // Update the value-to-node map.
428
+ CGNode *&Node = Values2Nodes[ptrBase];
429
+ if (Node) {
430
+ CGNode *targetNode = Node->getMergeTarget ();
431
+ targetNode->mergeFlags (false /* isInterior*/ , hasReferenceOnly);
432
+ return targetNode;
433
+ }
434
+ if (isa<SILFunctionArgument>(ptrBase)) {
435
+ Node = allocNode (ptrBase, NodeType::Argument, false , hasReferenceOnly);
436
+ if (!isSummaryGraph)
437
+ Node->mergeEscapeState (EscapeState::Arguments);
438
+ } else
439
+ Node = allocNode (ptrBase, NodeType::Value, false , hasReferenceOnly);
440
+ return Node;
433
441
}
434
442
435
443
// / Adds an argument/instruction in which the node's memory is released.
@@ -916,8 +924,8 @@ EscapeAnalysis::ConnectionGraph::getOrCreateAddressContent(SILValue addrVal,
916
924
917
925
bool contentHasReferenceOnly =
918
926
EA->hasReferenceOnly (addrVal->getType ().getObjectType (), *F);
919
- // Address content always has an indirect pointsTo (only reference content can
920
- // have a non-indirect pointsTo ).
927
+ // Address content is never an interior node (only reference content can
928
+ // be an interior node ).
921
929
return getOrCreateContentNode (addrNode, false , contentHasReferenceOnly);
922
930
}
923
931
@@ -926,12 +934,14 @@ EscapeAnalysis::ConnectionGraph::getOrCreateAddressContent(SILValue addrVal,
926
934
CGNode *
927
935
EscapeAnalysis::ConnectionGraph::getOrCreateReferenceContent (SILValue refVal,
928
936
CGNode *refNode) {
929
- // The object node points to internal fields. It neither has indirect pointsTo
930
- // nor reference-only pointsTo.
937
+ // The object node created here points to internal fields. It neither has
938
+ // indirect pointsTo nor reference-only pointsTo.
931
939
CGNode *objNode = getOrCreateContentNode (refNode, true , false );
932
940
if (!objNode->isInterior ())
933
941
return objNode;
934
942
943
+ // Determine whether the object that refVal refers to only contains
944
+ // references.
935
945
bool contentHasReferenceOnly = false ;
936
946
if (refVal) {
937
947
SILType refType = refVal->getType ();
@@ -972,24 +982,19 @@ EscapeAnalysis::ConnectionGraph::getOrCreateUnknownContent(CGNode *addrNode) {
972
982
// on-the-fly.
973
983
EscapeAnalysis::CGNode *
974
984
EscapeAnalysis::ConnectionGraph::getValueContent (SILValue ptrVal) {
975
- // Look past address projections, pointer casts, and the like within the same
976
- // object. Does not look past a dereference such as ref_element_addr, or
977
- // project_box.
978
- SILValue ptrBase = EA->getPointerRoot (ptrVal);
979
-
980
- PointerKind pointerKind = EA->getPointerKind (ptrBase);
981
- if (pointerKind == EscapeAnalysis::NoPointer)
982
- return nullptr ;
983
-
984
- CGNode *addrNode = getOrCreateNode (ptrBase, pointerKind);
985
+ CGNode *addrNode = getNode (ptrVal);
985
986
if (!addrNode)
986
987
return nullptr ;
987
988
988
- if (ptrBase->getType ().isAddress ())
989
- return getOrCreateAddressContent (ptrBase, addrNode);
989
+ // Create content based on the derived pointer. If the base pointer contains
990
+ // other types of references, then the content node will be merged when those
991
+ // references are accessed. If the other references types are never accessed
992
+ // in this function, then they are ignored.
993
+ if (ptrVal->getType ().isAddress ())
994
+ return getOrCreateAddressContent (ptrVal, addrNode);
990
995
991
- if (canOnlyContainReferences (pointerKind ))
992
- return getOrCreateReferenceContent (ptrBase , addrNode);
996
+ if (addrNode-> hasReferenceOnly ( ))
997
+ return getOrCreateReferenceContent (ptrVal , addrNode);
993
998
994
999
// The pointer value may contain raw pointers.
995
1000
return getOrCreateUnknownContent (addrNode);
@@ -2075,10 +2080,12 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
2075
2080
// that may eventually be associated with 'fieldContent', so we must
2076
2081
// assume here that 'fieldContent2' could hold raw pointers. This is
2077
2082
// implied by passing in invalid SILValue.
2078
- CGNode *objNode2 =
2083
+ CGNode *escapingNode =
2079
2084
ConGraph->getOrCreateReferenceContent (SILValue (), fieldNode);
2080
- CGNode *fieldNode2 = objNode2->getContentNodeOrNull ();
2081
- ConGraph->getOrCreateUnknownContent (fieldNode2)->markEscaping ();
2085
+ if (CGNode *indirectFieldNode = escapingNode->getContentNodeOrNull ())
2086
+ escapingNode = indirectFieldNode;
2087
+
2088
+ ConGraph->getOrCreateUnknownContent (escapingNode)->markEscaping ();
2082
2089
return ;
2083
2090
}
2084
2091
case SILInstructionKind::DestroyAddrInst: {
0 commit comments