Skip to content

Commit 8c47b59

Browse files
authored
Merge pull request #82560 from eeckstein/fix-closure-specializer-6.2
[6.2] ClosureSpecializer: don't specialize captures of stack-allocated Objective-C blocks
2 parents f5f058f + 9952649 commit 8c47b59

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

lib/SILOptimizer/IPO/ClosureSpecializer.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,19 @@ static bool isSupportedClosure(const SILInstruction *Closure) {
694694
return false;
695695
}
696696

697+
// Bail if it's an ObjectiveC block which might _not_ be copied onto the heap, i.e
698+
// optimized by SimplifyCopyBlock. We can't do this because the optimization inserts
699+
// retains+releases for captured arguments. That's not possible for stack-allocated blocks.
700+
// TODO: avoid inserting retains+releases at all for captures of `partial_apply [on_stack]`
701+
if (ArgTy.is<SILFunctionType>() &&
702+
ArgTy.getFunctionRepresentation() == SILFunctionTypeRepresentation::Block &&
703+
// A `copy_block` ensures that the block is copied onto the heap.
704+
!isa<CopyBlockInst>(Arg) &&
705+
// SimplifyCopyBlock only works for `partial_apply [on_stack]`.
706+
PAI->isOnStack()) {
707+
return false;
708+
}
709+
697710
// Only @inout/@inout_aliasable addresses are (currently) supported.
698711
// If our argument is an object, continue...
699712
if (ArgTy.isObject()) {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-swift-frontend -parse-as-library -enable-experimental-feature CopyBlockOptimization -O %s -emit-sil | %FileCheck %s
2+
3+
// REQUIRES: swift_feature_CopyBlockOptimization
4+
5+
func callClosure<R>(_ body: () -> R) -> R {
6+
return body()
7+
}
8+
9+
// Check that after removing a copy_block, no retains+releases are inserted for the block.
10+
// CHECK-LABEL: sil {{.*}}@testit :
11+
// CHECK-NOT: retain
12+
// CHECK-NOT: release
13+
// CHECK: } // end sil function 'testit'
14+
@_cdecl("testit")
15+
public func testit(_ block: (_ index: Int) -> Int) -> Bool {
16+
@inline(never)
17+
func c() -> Bool {
18+
return block(0) != 0
19+
}
20+
21+
return callClosure(c)
22+
}

0 commit comments

Comments
 (0)