Skip to content

Instantly share code, notes, and snippets.

@stuartcarnie
Created July 6, 2011 06:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stuartcarnie/1066669 to your computer and use it in GitHub Desktop.
Save stuartcarnie/1066669 to your computer and use it in GitHub Desktop.
Nested blocks discussion
void RetrieveFriends(GameCenter& gameCenter, GKLocalPlayer* localPlayer)
{
[localPlayer loadFriendsWithCompletionHandler:^(NSArray* friends, NSError* error)
{
// 1. this block is copied and retained by loadFriendsWithCompletionHandler
// 2. When called, loadPlayersForIdentifiers:withCompletionHandler will copy and retain the block below,
// which doesn't exist until the outer block is called
[GKPlayer loadPlayersForIdentifiers:friends withCompletionHandler:^(NSArray* players, NSError* error2)
{
// Finally, dispatch_async will copy and retain the block which is passed to it below
dispatch_async(dispatch_get_main_queue(), ^(void)
{
TestLala(gameCenter); //, friends, players, error2);
});
}];
}];
}
.globl _RetrieveFriends
.align 2
.code 16
.thumb_func _RetrieveFriends
_RetrieveFriends:
Leh_func_begin1:
push {r4, r5, r7, lr}
add r7, sp, #8
sub sp, #56
add r2, sp, #20
movs r3, #0
str r0, [r2, #32]
str r1, [r2, #28]
str r2, [sp, #16]
add r2, sp, #24
ldr.n r4, LCPI1_0
LPC1_0:
add r4, pc
ldr r4, [r4]
ldr r5, [sp, #16]
str r4, [r5, #4]
movs r4, #1
lsls r4, r4, #30
str r4, [r5, #8]
str r3, [r5, #12]
ldr.n r3, LCPI1_1
LPC1_1:
add r3, pc
str r3, [r5, #16]
ldr.n r3, LCPI1_2
LPC1_2:
add r3, pc
str r3, [r5, #20]
ldr r3, [r5, #32]
str r3, [r5, #24]
ldr r3, [r5, #28]
str r3, [r5]
ldr.n r4, LCPI1_3
LPC1_3:
add r4, pc
str r1, [sp, #12]
ldr r1, [r4]
str r0, [sp, #8]
mov r0, r3
blx _objc_msgSend
ldr r0, [sp, #12]
ldr r1, [sp, #8]
str r1, [sp, #4]
str r0, [sp]
subs r4, r7, #7
subs r4, #1
mov sp, r4
pop {r4, r5, r7, pc}
.align 2
LCPI1_0:
.long L__NSConcreteStackBlock$non_lazy_ptr-(LPC1_0+4)
.align 2
LCPI1_1:
.long ___RetrieveFriends_block_invoke_1-(LPC1_1+4)
.align 2
LCPI1_2:
.long ___block_descriptor_tmp_3.54-(LPC1_2+4)
.align 2
LCPI1_3:
.long L_OBJC_SELECTOR_REFERENCES_1-(LPC1_3+4)
Leh_func_end1:
.align 2
.code 16
.thumb_func ___RetrieveFriends_block_invoke_1
___RetrieveFriends_block_invoke_1:
Leh_func_begin2:
push {r4, r5, r6, r7, lr}
add r7, sp, #12
sub sp, #72
add r3, sp, #28
movs r4, #0
str r0, [r3, #40]
str r1, [r3, #36]
str r2, [r3, #32]
ldr r5, [r3, #40]
ldr r5, [r5, #20]
str r5, [r3]
str r3, [sp, #24]
add r3, sp, #36
ldr.n r5, LCPI2_0
LPC2_0:
add r5, pc
ldr r5, [r5]
ldr r6, [sp, #24]
str r5, [r6, #8]
movs r5, #1
lsls r5, r5, #30
str r5, [r6, #12]
str r4, [r6, #16]
ldr.n r4, LCPI2_1
LPC2_1:
add r4, pc
str r4, [r6, #20]
ldr.n r4, LCPI2_2
LPC2_2:
add r4, pc
str r4, [r6, #24]
ldr r4, [r6]
str r4, [r6, #28]
ldr.n r4, LCPI2_3
LPC2_3:
add r4, pc
ldr r4, [r4]
str r4, [r6, #4]
ldr.n r5, LCPI2_4
LPC2_4:
add r5, pc
str r1, [sp, #20]
ldr r1, [r5]
str r2, [sp, #16]
ldr r2, [r6, #36]
str r0, [sp, #12]
mov r0, r4
blx _objc_msgSend
ldr r0, [sp, #16]
ldr r1, [sp, #20]
ldr r2, [sp, #12]
str r2, [sp, #8]
str r0, [sp, #4]
str r1, [sp]
subs r4, r7, #7
subs r4, #5
mov sp, r4
pop {r4, r5, r6, r7, pc}
.align 2
LCPI2_0:
.long L__NSConcreteStackBlock$non_lazy_ptr-(LPC2_0+4)
.align 2
LCPI2_1:
.long ___RetrieveFriends_block_invoke_2-(LPC2_1+4)
.align 2
LCPI2_2:
.long ___block_descriptor_tmp_2.52-(LPC2_2+4)
.align 2
LCPI2_3:
.long L_OBJC_CLASSLIST_REFERENCES_$_0-(LPC2_3+4)
.align 2
LCPI2_4:
.long L_OBJC_SELECTOR_REFERENCES_0-(LPC2_4+4)
Leh_func_end2:
.align 2
.code 16
.thumb_func ___RetrieveFriends_block_invoke_2
___RetrieveFriends_block_invoke_2:
Leh_func_begin3:
push {r4, r5, r7, lr}
add r7, sp, #8
sub sp, #64
add r3, sp, #24
movs r4, #0
str r0, [r3, #36]
str r1, [r3, #32]
str r2, [r3, #28]
ldr r5, [r3, #36]
ldr r5, [r5, #20]
str r5, [r3]
str r1, [sp, #20]
add r1, sp, #28
ldr.n r5, LCPI3_0
LPC3_0:
add r5, pc
ldr r5, [r5]
str r5, [r3, #4]
movs r5, #1
lsls r5, r5, #30
str r5, [r3, #8]
str r4, [r3, #12]
ldr.n r4, LCPI3_1
LPC3_1:
add r4, pc
str r4, [r3, #16]
ldr.n r4, LCPI3_2
LPC3_2:
add r4, pc
str r4, [r3, #20]
ldr r4, [r3]
str r4, [r3, #24]
ldr.n r3, LCPI3_3
LPC3_3:
add r3, pc
str r0, [sp, #16]
ldr r0, [r3]
str r2, [sp, #12]
blx _dispatch_async
ldr r0, [sp, #12]
ldr r1, [sp, #20]
ldr r2, [sp, #16]
str r2, [sp, #8]
str r0, [sp, #4]
str r1, [sp]
subs r4, r7, #7
subs r4, #1
mov sp, r4
pop {r4, r5, r7, pc}
.align 2
LCPI3_0:
.long L__NSConcreteStackBlock$non_lazy_ptr-(LPC3_0+4)
.align 2
LCPI3_1:
.long ___RetrieveFriends_block_invoke_3-(LPC3_1+4)
.align 2
LCPI3_2:
.long ___block_descriptor_tmp_1.50-(LPC3_2+4)
.align 2
LCPI3_3:
.long L__dispatch_main_q$non_lazy_ptr-(LPC3_3+4)
Leh_func_end3:
.align 1
.code 16
.thumb_func ___RetrieveFriends_block_invoke_3
___RetrieveFriends_block_invoke_3:
Leh_func_begin4:
push {r7, lr}
mov r7, sp
sub sp, #16
add r1, sp, #8
str r0, [r1, #4]
ldr r2, [r0, #20]
str r2, [r1]
str r0, [sp, #4]
mov r0, r2
bl _TestLala
ldr r0, [sp, #4]
str r0, [sp]
mov sp, r7
pop {r7, pc}
Leh_func_end4:
@stuartcarnie
Copy link
Author

Looking at the assembly, you can see there are 3 separate symbols which represent each of the blocks (which are just functions), ___RetrieveFriends_block_invoke_1, ___RetrieveFriends_block_invoke_2 and ___RetrieveFriends_block_invoke_3.

The only object that is would potentially need to be retained is the localPlayer parameter, however it is used immediately and no longer needed for any of the nested calls. We're also assuming that the gameCenter reference is likely a singleton or lives for a long time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment