Are they the same, copy and Block_copy()? How? or if not, what are the differences?
I was curious about this for a while so I decided to do some researches.
See what I found it my answer.
Finally, I found the answer. copy and Block_copy() are the same, but not that exactly.
Here is what I found :
Let's take a look at the classes of blocks, there are 3 of them :
__NSGlobalBlock__ - You will get a block of this class if you implement a block without any references to the outside of the block.
void(^block)() = ^{ NSLog(@"GRAZZZZ"); };
__NSStackBlock__ - You will get a block of this class if you implement a block with one or more references to the outside of the block, (you will get this when you are running on non-ARC environment only. In ARC env, ARC copies it for you automatically).
// NON-ARC CODE
int theOutsider = 1234;
void(^block)() = ^{ NSLog(@"%d", theOutsider); };
__NSMallocBlock__ - You will get a block of this class if you copy a __NSStackBlock__ block.
int theOutsider = 1234;
void(^block1)() = [^{ NSLog(@"%d", theOutsider); } copy]; // NON-ARC VERSION
void(^block2)() = ^{ NSLog(@"%d", theOutsider); }; // ARC VERSION
For __NSGlobalBlock__, when you call copy to it, it does nothing, just return. So, just ignore it. There is no need to move anything to heap. Below is the assembly of -[__NSGlobalBlock copy] (its super class) :
CoreFoundation`-[__NSGlobalBlock copy]:
0x7fff8bd016f0: pushq %rbp
0x7fff8bd016f1: movq %rsp, %rbp
0x7fff8bd016f4: movq %rdi, %rax
0x7fff8bd016f7: popq %rbp
0x7fff8bd016f8: ret
0x7fff8bd016f9: nopl (%rax)
For __NSStackBlock__ and __NSMallocBlock__, when you call copy to them, they forward to copy method of its super class, -[NSBlock copy]. Here is its assembly code on OS X 10.9 SDK :
CoreFoundation`-[NSBlock copy]:
0x7fff8bcc86a0: pushq %rbp
0x7fff8bcc86a1: movq %rsp, %rbp
0x7fff8bcc86a4: pushq %rbx
0x7fff8bcc86a5: pushq %rax
0x7fff8bcc86a6: movq %rdi, %rbx
0x7fff8bcc86a9: callq 0x7fff8be360ac ; symbol stub for: objc_collectingEnabled
0x7fff8bcc86ae: movq %rbx, %rdi
0x7fff8bcc86b1: addq $0x8, %rsp
0x7fff8bcc86b5: testb %al, %al
0x7fff8bcc86b7: je 0x7fff8bcc86c0 ; -[NSBlock copy] + 32
0x7fff8bcc86b9: popq %rbx
0x7fff8bcc86ba: popq %rbp
0x7fff8bcc86bb: jmpq 0x7fff8be361f6 ; symbol stub for: _Block_copy_collectable
0x7fff8bcc86c0: popq %rbx
0x7fff8bcc86c1: popq %rbp
0x7fff8bcc86c2: jmpq 0x7fff8be361f0 ; symbol stub for: _Block_copy
0x7fff8bcc86c7: nopw (%rax,%rax)
The assembly code on iOS 7.1 SDK :
CoreFoundation`-[NSBlock copy]:
0x17949d0: pushl %ebp
0x17949d1: movl %esp, %ebp
0x17949d3: popl %ebp
0x17949d4: jmp 0x18d3d8a ; symbol stub for: _Block_copy
0x17949d9: nopl (%eax)
As you can see in the code, -[NSBlock copy] does call _Block_copy!.
Enough for copy, let's take a look at Block_copy(). It is defined in Block.h as this :
#define Block_copy(...) ((__typeof(__VA_ARGS__))_Block_copy((const void *)(__VA_ARGS__)))
Block_copy() does call _Block_copy too!!
To this point, I can summarise that copy and Block_copy() are the same!.
Hope this can help someone with the same curiosity as me :D.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With