Skip to content

IRGen: Don't emit capture descriptor for stack allocated closures #22096

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

aschwaighofer
Copy link
Contributor

No description provided.

@aschwaighofer
Copy link
Contributor Author

@swift-ci Please test and merge

@swift-ci swift-ci merged commit d07513b into swiftlang:master Jan 25, 2019
@jrose-apple
Copy link
Contributor

Does this affect debugging?

@aschwaighofer
Copy link
Contributor Author

Does this affect debugging?

lldb does not use the closure context capture descriptor as far as I can tell:

The only place that I found that reads the capture descriptor is ReflectionContext::getInstanceTypeInfo.

The only place where lldb uses this function is in SwiftLanguageRuntime::GetMemberVariableOffset to get the offset of a member by name.

You would need this information if you wanted to display what is captured by closure. I don't see that we are currently doing this.

No tests fail.

cc @dcci @slavapestov

@jrose-apple
Copy link
Contributor

I don't know how many tests we have for optimized code, but I guess that's because we haven't made that a focus yet. It's possible we're regressing that behavior, but it's probably worth it for this optimization.

@aschwaighofer
Copy link
Contributor Author

This is unrelated to optimized or unoptimized code. We can have stack allocated closures under either mode. The pass that makes closures stack allocated runs in the mandatory pipeline.

@jrose-apple
Copy link
Contributor

Ah, then it may be worth adding explicit checks to LLDB for printing a stack-allocated closure's captures. We shouldn't regress on that.

@aschwaighofer
Copy link
Contributor Author

You can print the captured variables inside of a closure during executing of the closure without the capture descriptor - they are passed as arguments to the function that implements the closure:

$ /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2019-01-24-a.xctoolchain/usr/bin/lldb ./TestClosureDebugging
Process 82636 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
    frame #0: 0x0000000100001af5 TestClosureDebugging`closure #1 in testClosure(a=(x = 1), b=(x = 2)) at TestClosureDebugging.swift:14:13
   11  	
   12  	func testClosure(_ a: A, _ b: B) {
   13  	  useClosure {
-> 14  	    let x = a
   15  	    let y = b
   16  	    print(a.x)
   17  	    print(b.x)
Target 0: (TestClosureDebugging) stopped.
(lldb) print a
(TestClosureDebugging.A) $R0 = 0x0000000100808af0 (x = 1)
(lldb) print b
(TestClosureDebugging.B) $R2 = 0x0000000100808be0 (x = 2)

lldb does not seem to print a closure's captures when you print the closure itself which would require the capture descriptor:

* thread #1, queue = 'com.apple.main-thread', stop reason = step in
    frame #0: 0x00000001000015c9 TestClosureDebugging`useClosure(cl=0x0000000100001c60 TestClosureDebugging`partial apply forwarder for closure #1 () -> () in TestClosureDebugging.testClosure(TestClosureDebugging.A, TestClosureDebugging.B) -> () at <compiler-generated>) at TestClosureDebugging.swift:2:3
   1   	func useClosure(_ cl: () -> ()) {
-> 2   	  cl()
   3   	}
   4   	
   5   	class A {
   6   	  var x = 1
   7   	}
Target 0: (TestClosureDebugging) stopped.
(lldb) print cl
error: <EXPR>:3:1: error: non-escaping value 'cl' may only be called
cl

When you print an escaping closure it does not seem to print the captures either:

* thread #1, queue = 'com.apple.main-thread', stop reason = step in
    frame #0: 0x000000010000154d TestClosureDebugging`useClosure(cl=0x0000000100001c50 TestClosureDebugging`partial apply forwarder for closure #1 () -> () in TestClosureDebugging.testClosure(TestClosureDebugging.A, TestClosureDebugging.B) -> () at <compiler-generated>) at TestClosureDebugging.swift:3:3
   1   	func useClosure(_ cl: @escaping () -> ()) {
   2   	  let f = cl
-> 3   	  f()
   4   	}
   5   	
   6   	class A {
   7   	  var x = 1
Target 0: (TestClosureDebugging) stopped.
(lldb) print f
() -> () $R0 = 0x0000000100001c50 TestClosureDebugging`partial apply forwarder for closure #1 () -> () in TestClosureDebugging.testClosure(TestClosureDebugging.A, TestClosureDebugging.B) -> () at <compiler-generated>
(lldb) print cl
() -> () $R2 = 0x0000000100001c50 TestClosureDebugging`partial apply forwarder for closure #1 () -> () in TestClosureDebugging.testClosure(TestClosureDebugging.A, TestClosureDebugging.B) -> () at <compiler-generated>

@jrose-apple
Copy link
Contributor

Ahh, thanks for the clarification!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants