Block解析_1
2016-02-29 21:15
176 查看
本文翻译原文:http://www.galloway.me.uk/2012/10/a-look-inside-blocks-episode-1/
点击打开链接
基本的:
现在给block添加一个变量
代码相关的编译信息如下(armv7,03)
这个是runBlockA函数,这个非常简单。现在倒回去看一看,这个函数仅仅是调用了block。r0(寄存器r0)里面放入了函数的第一个参数。因此第一条指令的意思就是r1载入的值是r0+12个单元里存放的值。把这个当做加了12个字节指针的解引用。我们现在转移到这个地址.注意到r1被使用了,那么r0里面一定是block本身。这样看来这里正在调用的这个函数把block当做了它的第一个参数。
从这一点上,我可以确定block很可能是某种结构,该结构的功能块应该执行的是存储12字节到上述结构。当一个block被传递的时候,只是传递此结构里的一个指针。
现在来看看doBlockA这个方法
这个同样很简单。这是一个程序计数器相对的载入。你可以当成仅仅是载入一个叫做__block_literal_global的一个变量到r0中。接下来runBlockA函数被调用了。所以我们知道block对象被传递给了runBlockA,这个__block_literal_global一定就是block对象。
现在已经取得了一些进展。但是__block_literal_global精确来说是什么。
这非常像一个结构体,这个结构体里面有5个4字节长的值,这一定就是runBlockA起作用的那个block。结构体中的12个字节是那个看起来像个函数指针它叫做__doBlockA_block_invoke_0。记住这就是runBlockA跳转的。
但是什么是NSConcreteGlobalBlock,__doBlockA_block_invoke_0和__block_descriptor_tmp很有趣,它们同样出现了下面的文件中。
__doBlockA_block_invoke_0看起来像一个实现它自己的的block,因为我们使用的是一个空的block。这个函数立刻返回了,正如我们预计空函数是如何编译的那样。
接下来看一看__block_descriptor_tmp,这次似乎出现了另一种结构体,这次里面有四个值。第二个值20表示__block_literal_global是多大,这可能是一个容量值?还有一个C语言的字符串叫.str,它的值是v4@?0。这看起来像一种形式的编码。这可能是block形式的编码(没有返回值没有参数)。另一个值我也不知道是干吗的。
但是源头就在那里不是吗?
这个是LLVM项目compiler-rt分析的block头文Block_private.h头文件中关于Block的struct声明:
这看起来多么的熟悉,Block_Layout结构体就是__block_literal_global所指,Block_descriptor结构体就是__block_descriptor_tmp所指。
Block_layout中的isa指针非常有意思,因为他就是_NSConcreteBlock所指,同样还是block怎么样仿真成为一个OC对象的真相。如果_NSConcreteBlock是一个类,那么OC的消息传递机制很乐于将block当做一个普通的对象对待,这很像Toll Free Bridging点击打开链接。
把之前那些全部都拼起来看,编译器对于这些代码做了这些事情:
点击打开链接
对于Block的内部实现:第一部分
今天我已经观察过Block从编译器的角度来看它是怎么工作的。通过Block,我认为苹果加到C语言的闭包函数很不错同时从编译器的角度来说的确成功成为C语言的一部分。我曾经好奇过什么是Block,它是怎么神奇的会成为一个OC的对象(你可以retain,copy,release一个实力对象),这篇文章主要就是对Block进行探讨。基本的:
void(^block)(void) = ^{ NSLog(@"I am a block"); };刚刚创建了一个变量"block"并且给它赋值了一个block,这个操作很简单是吗?不,我更想知道的是编译器对于这段代码做了什么。
现在给block添加一个变量
void(^block1)(int) = ^(int a){ NSLog(@"I am a block a = %d", a); };或者甚至给个返回值
int(^block2)(void) = ^{ NSLog(@"I am a block"); return 1; };
深入来看一个简单的例子
我的第一个想法就是看看编译器是如何编译一个简单的block的,思考一下以下这段代码typedef void(^BlockA)(void); __attribute__((noinline)) void runBlockA(BlockA block){ block(); } void doBlockA(){ BlockA block = ^{ //empty block }; runBlockA(block); }建立两个函数的原因就是我想知道block是如何被调用的,还有它是如何创建的。如果它们在一个函数里面的话优化器可能会做一些处理,我们就看不到到底发生了什么。我已经把runBlockA变成了无内联关系,因此优化器不会内联doBlockA里的那个函数,这样做减少了同样的问题。
代码相关的编译信息如下(armv7,03)
这个是runBlockA函数,这个非常简单。现在倒回去看一看,这个函数仅仅是调用了block。r0(寄存器r0)里面放入了函数的第一个参数。因此第一条指令的意思就是r1载入的值是r0+12个单元里存放的值。把这个当做加了12个字节指针的解引用。我们现在转移到这个地址.注意到r1被使用了,那么r0里面一定是block本身。这样看来这里正在调用的这个函数把block当做了它的第一个参数。
从这一点上,我可以确定block很可能是某种结构,该结构的功能块应该执行的是存储12字节到上述结构。当一个block被传递的时候,只是传递此结构里的一个指针。
现在来看看doBlockA这个方法
这个同样很简单。这是一个程序计数器相对的载入。你可以当成仅仅是载入一个叫做__block_literal_global的一个变量到r0中。接下来runBlockA函数被调用了。所以我们知道block对象被传递给了runBlockA,这个__block_literal_global一定就是block对象。
现在已经取得了一些进展。但是__block_literal_global精确来说是什么。
这非常像一个结构体,这个结构体里面有5个4字节长的值,这一定就是runBlockA起作用的那个block。结构体中的12个字节是那个看起来像个函数指针它叫做__doBlockA_block_invoke_0。记住这就是runBlockA跳转的。
但是什么是NSConcreteGlobalBlock,__doBlockA_block_invoke_0和__block_descriptor_tmp很有趣,它们同样出现了下面的文件中。
__doBlockA_block_invoke_0看起来像一个实现它自己的的block,因为我们使用的是一个空的block。这个函数立刻返回了,正如我们预计空函数是如何编译的那样。
接下来看一看__block_descriptor_tmp,这次似乎出现了另一种结构体,这次里面有四个值。第二个值20表示__block_literal_global是多大,这可能是一个容量值?还有一个C语言的字符串叫.str,它的值是v4@?0。这看起来像一种形式的编码。这可能是block形式的编码(没有返回值没有参数)。另一个值我也不知道是干吗的。
但是源头就在那里不是吗?
这个是LLVM项目compiler-rt分析的block头文Block_private.h头文件中关于Block的struct声明:
这看起来多么的熟悉,Block_Layout结构体就是__block_literal_global所指,Block_descriptor结构体就是__block_descriptor_tmp所指。
Block_layout中的isa指针非常有意思,因为他就是_NSConcreteBlock所指,同样还是block怎么样仿真成为一个OC对象的真相。如果_NSConcreteBlock是一个类,那么OC的消息传递机制很乐于将block当做一个普通的对象对待,这很像Toll Free Bridging点击打开链接。
把之前那些全部都拼起来看,编译器对于这些代码做了这些事情:
相关文章推荐
- R语言学习:数据结构3-矩阵、数组
- 详解OpenGL中的各种变换(投影变换,模型变换,视图变换)
- Android性能分析——Activity启动速度分析工具
- 架构漫谈(一):什么是架构?
- 由于想强制自己不看某直播视频网站就写了一个小程序
- ThoughtWorks面试题(标记给自己看)
- 第23章 SEH结构化异常处理(3)_终止处理程序
- linux磁盘结构与管理
- HTTP与TCP的关系,无连接、无状态详解
- Visual C++上机指南
- 开源框架spring详解-----AOP的深刻理解(1)
- 插入排序之折半插入排序-binaryinsertsort
- node.JS md5加密中文与php结果不一致的解决方法
- HDU2072 单词数
- elf_i386或elf_x86_64:没有那个文件或目录 解决方法
- github clone 代码到本地全步骤
- Qt小软件:LanFileSender(局域网文件传输小工具)
- Git(一):Git与版本号控制简单介绍
- Material Design -- TextInputLayout
- 111. Minimum Depth of Binary Tree