I'm looking into how the @objc annotation in Swift affects the generated assembly code. From what I can tell, this annotation generates a trampoline function which performs two functions:
- Moves the
selfargument fromx0intox20to conform to the Swift ABI - Calls
retainandreleaseon all of the arguments (before and after the call into Swift code, respectively)
Here is the assembly code of the scene:WillConnectTo:options: trampoline from an iOS app, for example:
MyApp`@objc SceneDelegate.scene(_:willConnectTo:options:):
0x102a850fc <+0>: stp x24, x23, [sp, #-0x40]!
0x102a85100 <+4>: stp x22, x21, [sp, #0x10]
0x102a85104 <+8>: stp x20, x19, [sp, #0x20]
0x102a85108 <+12>: stp x29, x30, [sp, #0x30]
0x102a8510c <+16>: add x29, sp, #0x30 ; =0x30
0x102a85110 <+20>: mov x19, x4
0x102a85114 <+24>: mov x20, x3
0x102a85118 <+28>: mov x21, x2
0x102a8511c <+32>: mov x22, x0
0x102a85120 <+36>: bl 0x102a85640 ; symbol stub for: objc_retain
0x102a85124 <+40>: mov x23, x0
0x102a85128 <+44>: mov x0, x21
0x102a8512c <+48>: bl 0x102a85640 ; symbol stub for: objc_retain
0x102a85130 <+52>: mov x21, x0
0x102a85134 <+56>: mov x0, x20
0x102a85138 <+60>: bl 0x102a85640 ; symbol stub for: objc_retain
0x102a8513c <+64>: mov x24, x0
0x102a85140 <+68>: mov x0, x19
0x102a85144 <+72>: bl 0x102a85640 ; symbol stub for: objc_retain
0x102a85148 <+76>: mov x19, x0
0x102a8514c <+80>: mov x0, x21
0x102a85150 <+84>: mov x20, x22
0x102a85154 <+88>: bl 0x102a853a4 ; function signature specialization <Arg[1] = Dead, Arg[2] = Dead> of MyApp(_: __C.UIScene, willConnectTo: __C.UISceneSession, options: __C.UISceneConnectionOptions) -> () at SceneDelegate.swift:17
-> 0x102a85158 <+92>: mov x0, x21
0x102a8515c <+96>: bl 0x102a85634 ; symbol stub for: objc_release
0x102a85160 <+100>: mov x0, x24
0x102a85164 <+104>: bl 0x102a85634 ; symbol stub for: objc_release
0x102a85168 <+108>: mov x0, x19
0x102a8516c <+112>: bl 0x102a85634 ; symbol stub for: objc_release
0x102a85170 <+116>: mov x0, x23
0x102a85174 <+120>: ldp x29, x30, [sp, #0x30]
0x102a85178 <+124>: ldp x20, x19, [sp, #0x20]
0x102a8517c <+128>: ldp x22, x21, [sp, #0x10]
0x102a85180 <+132>: ldp x24, x23, [sp], #0x40
0x102a85184 <+136>: b 0x102a85634 ; symbol stub for: objc_release
I understand why we need (1), but what is the purpose of (2)? In what scenario would these extra retain and release calls be necessary? Why can't we simply forward all of the arguments directly to the Swift function? I'm guessing there is a way for the Objective-C objects to be deallocated in the middle of the Swift function, but I'm having trouble thinking of an example of how this can happen.