文章由来: ?重新看objc 编译成C++ 时候block 实现时梳理代码时候发现,C++实现的block 内部没找到直接调用__foo_block_impl_0* 这个函数(foo 是定义和实现block 的函数名称,具体看各自测试代block码在哪个函数里面调用的)。
object 代码
// main.m
#import <Foundation/Foundation.h>
void foo() {
????int a_int = 0;
????NSNumber *a_number = [NSNumber numberWithInt:0];
????void(^blockA)(void) = ^(void) {
????????NSLog(@"a_int = %d", a_int);
????????NSLog(@"a_number = %@", a_number);
????};
????a_int = 1;
????a_number = @1;
????blockA();
????return ;
}
int main(int argc, const char * argv[]) {
????foo();
????return 0;
}
对应的C++ 编译之后的主要代码,其他多余代码已经去掉
struct __foo_block_impl_0 {
??struct __block_impl impl;
??struct __foo_block_desc_0* Desc;
??int a_int;
??NSNumber *a_number;
??__foo_block_impl_0(void *fp, struct __foo_block_desc_0 *desc, int _a_int, NSNumber *_a_number, int flags=0) : a_int(_a_int), a_number(_a_number) {
????impl.isa = &_NSConcreteStackBlock;
????impl.Flags = flags;
????impl.FuncPtr = fp;
????Desc = desc;
??}
};
static void __foo_block_func_0(struct __foo_block_impl_0 *__cself) {
??int a_int = __cself->a_int; // bound by copy
??NSNumber *a_number = __cself->a_number; // bound by copy
????????NSLog((NSString *)&__NSConstantStringImpl__var_folders_hf_ff518dhs4cq81s4jf93ppmg00000gn_T_blockTest_e6692f_mi_0, a_int);
????????NSLog((NSString *)&__NSConstantStringImpl__var_folders_hf_ff518dhs4cq81s4jf93ppmg00000gn_T_blockTest_e6692f_mi_1, a_number);
????}
static void __foo_block_copy_0(struct __foo_block_impl_0*dst, struct __foo_block_impl_0*src) {_Block_object_assign((void*)&dst->a_number, (void*)src->a_number, 3/*BLOCK_FIELD_IS_OBJECT*/);}
static void __foo_block_dispose_0(struct __foo_block_impl_0*src) {_Block_object_dispose((void*)src->a_number, 3/*BLOCK_FIELD_IS_OBJECT*/);}
static struct __foo_block_desc_0 {
??size_t reserved;
??size_t Block_size;
??void (*copy)(struct __foo_block_impl_0*, struct __foo_block_impl_0*);
??void (*dispose)(struct __foo_block_impl_0*);
} __foo_block_desc_0_DATA = { 0, sizeof(struct __foo_block_impl_0), __foo_block_copy_0, __foo_block_dispose_0};
void foo() {
????int a_int = 0;
????NSNumber *a_number = ((NSNumber * _Nonnull (*)(id, SEL, int))(void *)objc_msgSend)((id)objc_getClass("NSNumber"), sel_registerName("numberWithInt:"), 0);
????void(*blockA)(void) = ((void (*)())&__foo_block_impl_0((void *)__foo_block_func_0, &__foo_block_desc_0_DATA, a_int, a_number, 570425344));
????a_int = 1;
????a_number = ((NSNumber *(*)(Class, SEL, int))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithInt:"), 1);
????((void (*)(__block_impl *))((__block_impl *)blockA)->FuncPtr)((__block_impl *)blockA);
????return ;
}
int main(int argc, const char * argv[]) {
????foo();
????return 0;
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
会发现?__foo_block_impl_0 虽然在?__foo_block_desc_0 结构体定义,但是在?__foo_block_impl_0 复制给Desc 时候并没有明显的发现调用__foo_block_impl_0拷贝的痕迹,开始以为在调用block 静态函数__foo_block_func_0 时候给int值变量复制系统会自动调用__foo_block_impl_0之类的,但是后面发现并没有,于是 编译成汇编代码:我们把注意力集中到_foo 函数里面的?___block_descriptor_44_e8_32s_e5_v8 ,最终调用到 section里面去了,然后在里面执行了___copy_helper_block_e8_32s, 全局搜索下___copy_helper_block_e8_32s 发现 .section????__TEXT,__cstring,cstring_literals 属于代码段字符串符号表定义表达式(.quad,具体自行网上搜索)__copy_helper_block_e8_32s 。 其他地方实在无法联系到调用___copy_helper_block_e8_32s进行拷贝。
????.section????__TEXT,__text,regular,pure_instructions
????.build_version macos, 11, 0????sdk_version 12, 0
????.globl????_foo????????????????????????????## -- Begin function foo
????.p2align????4, 0x90
_foo:???????????????????????????????????## @foo
????.cfi_startproc
## %bb.0:
????pushq????%rbp
????.cfi_def_cfa_offset 16
????.cfi_offset %rbp, -16
????movq????%rsp, %rbp
????.cfi_def_cfa_register %rbp
????subq????$80, %rsp
????xorl????%edx, %edx
????movl????$0, -4(%rbp)
????movq????_OBJC_CLASSLIST_REFERENCES_$_(%rip), %rdi
????movq????_OBJC_SELECTOR_REFERENCES_(%rip), %rsi
????callq????*_objc_msgSend@GOTPCREL(%rip)
????movq????%rax, %rdi
????callq????_objc_retainAutoreleasedReturnValue
????movq????%rax, %rsi
????leaq????"___block_descriptor_44_e8_32s_e5_v8?0l"(%rip), %rax
????leaq????___foo_block_invoke(%rip), %rcx
????movq????__NSConcreteStackBlock@GOTPCREL(%rip), %rdx
????movq????%rsi, -16(%rbp)
????movq????%rdx, -72(%rbp)
????movl????$-1040187392, -64(%rbp)?????????## imm = 0xC2000000
????movl????$0, -60(%rbp)
????movq????%rcx, -56(%rbp)
????movq????%rax, -48(%rbp)
????movl????-4(%rbp), %eax
????movl????%eax, -32(%rbp)
????leaq????-72(%rbp), %rax
????addq????$32, %rax
????movq????%rax, -80(%rbp)?????????????????## 8-byte Spill
????movq????-16(%rbp), %rdi
????callq????*_objc_retain@GOTPCREL(%rip)
????movq????%rax, -40(%rbp)
????leaq????-72(%rbp), %rdi
????callq????_objc_retainBlock
????leaq????l__unnamed_nsconstantintegernumber_(%rip), %rsi
????movq????%rax, -24(%rbp)
????movl????$1, -4(%rbp)
????leaq????-16(%rbp), %rdi
????callq????_objc_storeStrong
????movq????-24(%rbp), %rax
????movq????%rax, %rdi
????callq????*16(%rax)
????xorl????%eax, %eax
????movl????%eax, %esi
????leaq????-24(%rbp), %rdi
????callq????_objc_storeStrong
????movq????-80(%rbp), %rdi?????????????????## 8-byte Reload
????xorl????%eax, %eax
????movl????%eax, %esi
????callq????_objc_storeStrong
????xorl????%eax, %eax
????movl????%eax, %esi
????leaq????-16(%rbp), %rdi
????callq????_objc_storeStrong
????addq????$80, %rsp
????popq????%rbp
????retq
????.cfi_endproc
????????????????????????????????????????## -- End function
????.p2align????4, 0x90????????????????????????## -- Begin function __foo_block_invoke
___foo_block_invoke:????????????????????## @__foo_block_invoke
????.cfi_startproc
## %bb.0:
????pushq????%rbp
????.cfi_def_cfa_offset 16
????.cfi_offset %rbp, -16
????movq????%rsp, %rbp
????.cfi_def_cfa_register %rbp
????subq????$32, %rsp
????movq????%rdi, %rax
????movq????%rax, -24(%rbp)?????????????????## 8-byte Spill
????leaq????L__unnamed_cfstring_(%rip), %rdi
????movq????%rax, -8(%rbp)
????movq????%rax, %rcx
????movq????%rcx, -16(%rbp)
????movl????40(%rax), %esi
????movb????$0, %al
????callq????_NSLog
????movq????-24(%rbp), %rax?????????????????## 8-byte Reload
????leaq????L__unnamed_cfstring_.2(%rip), %rdi
????movq????32(%rax), %rsi
????movb????$0, %al
????callq????_NSLog
????addq????$32, %rsp
????popq????%rbp
????retq
????.cfi_endproc
????????????????????????????????????????## -- End function
????.private_extern????___copy_helper_block_e8_32s ## -- Begin function __copy_helper_block_e8_32s
????.globl????___copy_helper_block_e8_32s
????.weak_def_can_be_hidden????___copy_helper_block_e8_32s
????.p2align????4, 0x90
___copy_helper_block_e8_32s:????????????## @__copy_helper_block_e8_32s
????.cfi_startproc
## %bb.0:
????pushq????%rbp
????.cfi_def_cfa_offset 16
????.cfi_offset %rbp, -16
????movq????%rsp, %rbp
????.cfi_def_cfa_register %rbp
????subq????$16, %rsp
????movq????%rdi, -8(%rbp)
????movq????%rsi, -16(%rbp)
????movq????-16(%rbp), %rcx
????movq????-8(%rbp), %rax
????movq????%rax, %rdi
????addq????$32, %rdi
????movq????32(%rcx), %rsi
????movq????$0, 32(%rax)
????callq????_objc_storeStrong
????addq????$16, %rsp
????popq????%rbp
????retq
????.cfi_endproc
????????????????????????????????????????## -- End function
????.private_extern????___destroy_helper_block_e8_32s ## -- Begin function __destroy_helper_block_e8_32s
????.globl????___destroy_helper_block_e8_32s
????.weak_def_can_be_hidden????___destroy_helper_block_e8_32s
????.p2align????4, 0x90
___destroy_helper_block_e8_32s:?????????## @__destroy_helper_block_e8_32s
????.cfi_startproc
## %bb.0:
????pushq????%rbp
????.cfi_def_cfa_offset 16
????.cfi_offset %rbp, -16
????movq????%rsp, %rbp
????.cfi_def_cfa_register %rbp
????subq????$16, %rsp
????xorl????%eax, %eax
????movl????%eax, %esi
????movq????%rdi, -8(%rbp)
????movq????-8(%rbp), %rdi
????addq????$32, %rdi
????callq????_objc_storeStrong
????addq????$16, %rsp
????popq????%rbp
????retq
????.cfi_endproc
????????????????????????????????????????## -- End function
????.globl????_main???????????????????????????## -- Begin function main
????.p2align????4, 0x90
_main:??????????????????????????????????## @main
????.cfi_startproc
## %bb.0:
????pushq????%rbp
????.cfi_def_cfa_offset 16
????.cfi_offset %rbp, -16
????movq????%rsp, %rbp
????.cfi_def_cfa_register %rbp
????subq????$16, %rsp
????movl????$0, -4(%rbp)
????movl????%edi, -8(%rbp)
????movq????%rsi, -16(%rbp)
????callq????_foo
????xorl????%eax, %eax
????addq????$16, %rsp
????popq????%rbp
????retq
????.cfi_endproc
????????????????????????????????????????## -- End function
????.section????__DATA,__objc_classrefs,regular,no_dead_strip
????.p2align????3??????????????????????????????## @"OBJC_CLASSLIST_REFERENCES_$_"
_OBJC_CLASSLIST_REFERENCES_$_:
????.quad????_OBJC_CLASS_$_NSNumber
????.section????__TEXT,__objc_methname,cstring_literals
L_OBJC_METH_VAR_NAME_:??????????????????## @OBJC_METH_VAR_NAME_
????.asciz????"numberWithInt:"
????.section????__DATA,__objc_selrefs,literal_pointers,no_dead_strip
????.p2align????3??????????????????????????????## @OBJC_SELECTOR_REFERENCES_
_OBJC_SELECTOR_REFERENCES_:
????.quad????L_OBJC_METH_VAR_NAME_
????.section????__TEXT,__cstring,cstring_literals
L_.str:?????????????????????????????????## @.str
????.asciz????"a_int = %d"
????.section????__DATA,__cfstring
????.p2align????3??????????????????????????????## @_unnamed_cfstring_
L__unnamed_cfstring_:
????.quad????___CFConstantStringClassReference
????.long????1992????????????????????????????## 0x7c8
????.space????4
????.quad????L_.str
????.quad????10??????????????????????????????## 0xa
????.section????__TEXT,__cstring,cstring_literals
L_.str.1:???????????????????????????????## @.str.1
????.asciz????"a_number = %@"
????.section????__DATA,__cfstring
????.p2align????3??????????????????????????????## @_unnamed_cfstring_.2
L__unnamed_cfstring_.2:
????.quad????___CFConstantStringClassReference
????.long????1992????????????????????????????## 0x7c8
????.space????4
????.quad????L_.str.1
????.quad????13??????????????????????????????## 0xd
????.section????__TEXT,__cstring,cstring_literals
L_.str.3:???????????????????????????????## @.str.3
????.asciz????"v8@?0"
????.private_extern????"___block_descriptor_44_e8_32s_e5_v8?0l" ## @"__block_descriptor_44_e8_32s_e5_v8\01?0l"
????.section????__DATA,__const
????.globl????"___block_descriptor_44_e8_32s_e5_v8?0l"
????.weak_def_can_be_hidden????"___block_descriptor_44_e8_32s_e5_v8?0l"
????.p2align????3
"___block_descriptor_44_e8_32s_e5_v8?0l":
????.quad????0??????????????????????????????## 0x0
????.quad????44??????????????????????????????## 0x2c
????.quad????___copy_helper_block_e8_32s
????.quad????___destroy_helper_block_e8_32s
????.quad????L_.str.3
????.quad????256????????????????????????????## 0x100
????.section????__TEXT,__cstring,cstring_literals
L_.str.4:???????????????????????????????## @.str.4
????.asciz????"i"
????.section????__DATA,__objc_intobj,regular,no_dead_strip
????.p2align????3??????????????????????????????## @_unnamed_nsconstantintegernumber_
l__unnamed_nsconstantintegernumber_:
????.quad????_OBJC_CLASS_$_NSConstantIntegerNumber
????.quad????L_.str.4
????.quad????1??????????????????????????????## 0x1
????.section????__DATA,__objc_imageinfo,regular,no_dead_strip
L_OBJC_IMAGE_INFO:
????.long????0
????.long????64
.subsections_via_symbols
目前大概明白了通过传结构体值时发生了参数拷贝,本人对C++不是很熟悉,不是很了解到底C++内部是如何传调用copy函数,只能通过汇编跳转猜测应该是在block 内部赋值DESC 时候进行拷贝(可以当参考思路不能当正确答案,不敢胡乱猜测 !-_-!)。