Skip to content

Commit 6b046a1

Browse files
committed
StackPromotion: prevent resilient classes from being stack promoted.
Usually resilient classes cannot be promoted anyway, because their initializers are not visible and let the object appear to escape. But in some rare situations this check is needed. rdar://121558570
1 parent ed23973 commit 6b046a1

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/StackPromotion.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ private func tryPromoteAlloc(_ allocRef: AllocRefInstBase,
6868
return false
6969
}
7070

71+
// Usually resilient classes cannot be promoted anyway, because their initializers are
72+
// not visible and let the object appear to escape.
73+
if allocRef.type.nominal.isResilient(in: allocRef.parentFunction) {
74+
return false
75+
}
76+
7177
// The most important check: does the object escape the current function?
7278
if allocRef.isEscaping(context) {
7379
return false
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend -parse-as-library -emit-module -o %t/Module.swiftmodule -module-name=Module %S/Inputs/public_class.swift -O
4+
// RUN: %target-swift-frontend -parse-as-library -emit-module -o %t/Resilient.swiftmodule -module-name=Resilient %S/Inputs/public_class.swift -O -enable-library-evolution
5+
6+
// RUN: %target-sil-opt -stack-promotion -I %t %s | %FileCheck %s
7+
8+
// REQUIRES: swift_in_compiler
9+
10+
sil_stage canonical
11+
12+
import Builtin
13+
import Swift
14+
import SwiftShims
15+
16+
import Module
17+
import Resilient
18+
19+
// CHECK-LABEL: sil @promote_non_resilient :
20+
// CHECK: alloc_ref [stack] $Base
21+
// CHECK: } // end sil function 'promote_non_resilient'
22+
sil @promote_non_resilient : $@convention(thin) () -> () {
23+
bb0:
24+
%0 = alloc_ref $Module.Base
25+
strong_release %0 : $Module.Base
26+
%2 = tuple ()
27+
return %2 : $()
28+
}
29+
30+
// CHECK-LABEL: sil @dont_promote_resilient :
31+
// CHECK: alloc_ref $Base
32+
// CHECK: } // end sil function 'dont_promote_resilient'
33+
sil @dont_promote_resilient : $@convention(thin) () -> () {
34+
bb0:
35+
%0 = alloc_ref $Resilient.Base
36+
strong_release %0 : $Resilient.Base
37+
%2 = tuple ()
38+
return %2 : $()
39+
}

0 commit comments

Comments
 (0)