@@ -365,15 +365,38 @@ bool swift::isLetAddress(SILValue address) {
365365// MARK: FindReferenceRoot
366366// ===----------------------------------------------------------------------===//
367367
368+ // On some platforms, casting from a metatype to a reference type dynamically
369+ // allocates a ref-counted box for the metatype. Naturally that is the place
370+ // where RC-identity begins. Considering the source of such a casts to be
371+ // RC-identical would confuse ARC optimization, which might eliminate a retain
372+ // of such an object completely.
373+ //
374+ // The SILVerifier checks that none of these operations cast a nontrivial value
375+ // to a reference except unconditional_checked_cast[_value].
376+ bool swift::isRCIdentityPreservingCast (SingleValueInstruction *svi) {
377+ switch (svi->getKind ()) {
378+ default :
379+ return false ;
380+ // Ignore ownership casts
381+ case SILInstructionKind::CopyValueInst:
382+ case SILInstructionKind::BeginBorrowInst:
383+ // Ignore class type casts
384+ case SILInstructionKind::UpcastInst:
385+ case SILInstructionKind::UncheckedRefCastInst:
386+ case SILInstructionKind::RefToBridgeObjectInst:
387+ case SILInstructionKind::BridgeObjectToRefInst:
388+ return true ;
389+ case SILInstructionKind::UnconditionalCheckedCastInst:
390+ case SILInstructionKind::UnconditionalCheckedCastValueInst:
391+ // If the source is nontrivial, then this checked cast may actually create a
392+ // new object, so its source is not ref-count equivalent.
393+ return !svi->getOperand (0 )->getType ().isTrivial (*svi->getFunction ());
394+ }
395+ }
396+
368397namespace {
369398
370399// Essentially RC identity where the starting point is already a reference.
371- //
372- // FIXME: We cannot currently see through type casts for true RC identity,
373- // because property indices are not unique within a class hierarchy. Either fix
374- // RefElementAddr::getFieldNo so it returns a unique index, or figure out a
375- // different way to encode the property's VarDecl. (Note that the lack of a
376- // unique property index could be the source of bugs elsewhere).
377400class FindReferenceRoot {
378401 SmallPtrSet<SILPhiArgument *, 4 > visitedPhis;
379402
@@ -386,18 +409,13 @@ class FindReferenceRoot {
386409
387410protected:
388411 // Return an invalid value for a phi with no resolved inputs.
389- //
390- // FIXME: We should be able to see through RC identity like this:
391- // nextRoot = stripRCIdentityCasts(nextRoot);
392412 SILValue recursiveFindRoot (SILValue ref) {
393- while (true ) {
394- SILValue nextRoot = ref;
395- nextRoot = stripOwnershipInsts (nextRoot);
396- if (nextRoot == ref)
413+ while (auto *svi = dyn_cast<SingleValueInstruction>(ref)) {
414+ if (!isRCIdentityPreservingCast (svi)) {
397415 break ;
398- ref = nextRoot;
399- }
400-
416+ }
417+ ref = svi-> getOperand ( 0 );
418+ };
401419 auto *phi = dyn_cast<SILPhiArgument>(ref);
402420 if (!phi || !phi->isPhiArgument ()) {
403421 return ref;
@@ -558,8 +576,16 @@ const ValueDecl *AccessedStorage::getDecl(SILValue base) const {
558576 return global->getDecl ();
559577
560578 case Class: {
561- auto *decl = getObject ()->getType ().getNominalOrBoundGenericNominal ();
562- return decl ? getIndexedField (decl, getPropertyIndex ()) : nullptr ;
579+ // The property index is relative to the VarDecl in ref_element_addr, and
580+ // can only be reliably determined when the base is avaiable. Otherwise, we
581+ // can only make a best effort to extract it from the object type, which
582+ // might not even be a class in the case of bridge objects.
583+ if (ClassDecl *classDecl =
584+ base ? cast<RefElementAddrInst>(base)->getClassDecl ()
585+ : getObject ()->getType ().getClassOrBoundGenericClass ()) {
586+ return getIndexedField (classDecl, getPropertyIndex ());
587+ }
588+ return nullptr ;
563589 }
564590 case Tail:
565591 return nullptr ;
@@ -1297,7 +1323,14 @@ void AccessPathDefUseTraversal::followProjection(SingleValueInstruction *svi,
12971323AccessPathDefUseTraversal::UseKind
12981324AccessPathDefUseTraversal::visitSingleValueUser (SingleValueInstruction *svi,
12991325 DFSEntry dfs) {
1300- if (isAccessedStorageCast (svi)) {
1326+ if (dfs.isRef ()) {
1327+ if (isRCIdentityPreservingCast (svi)) {
1328+ pushUsers (svi, dfs);
1329+ return IgnoredUse;
1330+ }
1331+ // 'svi' will be processed below as either RefElementAddrInst,
1332+ // RefTailAddrInst, or some unknown LeafUse.
1333+ } else if (isAccessedStorageCast (svi)) {
13011334 pushUsers (svi, dfs);
13021335 return IgnoredUse;
13031336 }
0 commit comments