- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
从C的伪代码到汇编,动手实现objc_msgSend
objc_msgSend 函数支撑了我们使用 Objective-C 实现的一切。Gwynne Raskind , Friday QA 的读者,建议我谈谈 objc_msgSe nd的内部实现。要理解某件事还有比自己动 手实现一次更好的方法吗?咱们来自己动手实现一个 objc_msgSend。
Tramapoli ne! Trampopoli ne!( 蹦床)
当你写了一个发送 Objective-C 消息的方法:
[obj message]
编译器会生成一个 objc_msgSend调用:
objc_msgSend(obj, @selector (message));
之后objc_msgSe nd会负责转发这个消息。
它都做了什么?它会查找合适的函数指针或者 IMP,然后调用,最后跳转。任何传给
objc_msgSend的参数,最终都会成为IMP的参数。IMP的返回值成为了最开始被调用的 方法的返回值。
因为objcmsgSend只是负责接收参数,找到合适的函数指针,然后跳转,有时管这种
叫做trampoline (译注:[蹦床]((computing)).更通用的来说,任何一段负责把一段代
码转发到另一处的代码,都可以被叫做 trampoli ne 。
这种转发的行为使 objc_msgSend变得特殊起来。因为它只是简单的查找合适的代 码,然后直接跳转过去,这相当的通用。传入任何参数组合都可以,因为它只是把这些参 数留给IMP去读取。返回值有些棘手,但最终都可以看成 objc_msgSend的不同变种。
不幸的是,这些转发行为都不能用纯 C实现。因为没有方法可以将传入 C函数的泛
参(gen eric parameters )传给另一个函数。 你可以使用变参,但是变参和普通参数的传
递方法不同,而且慢,所以这不适合普通的 C参数。
如果要用C来实现objc_msgSend,基本样子应该像这样:
id objc_msgSend(id self, SEL _cmd, ...)
{
Class c = object_getClass(self);
IMP imp = class_getMethodImplementation(c, _cmd);
return imp(self, _cmd, ...);
}
这有点过于简单。事实上会有一个方法缓存来提升查找速度,像这样:
id objc_msgSend(id self, SEL _cmd,…)
{
Class c = object_getClass(self);
IMP imp = cache_lookup(c, _cmd);
if(!imp)
imp = class_getMethodlmplementation(c, _cmd);
return imp(self, _cmd, ...);
}
通常为了速度,cache_lookup 使用in li ne 函数实现。
汇编
在Apple版的run time 中,为了最大化速度,整个函数是使用汇编实现的。在
Objective-C 中每次发送消息都会调用 objc_msgSend,在一个应用中最简单的动作都会有
成千或者上百万的消息。
为了让事情更简单,我自己的实现中会尽可能少的使用汇编,使用独立的 C函数抽象
复杂度。汇编代码会实现下面的功能:
id objc_msgSend(id self, SEL _cmd, ...)
{
IMP imp = GetImplementation(self, _cmd);
imp(self, _cmd, ...);
}
6.
7. GetImplementation 可以用更可读的方式工作。
汇编代码需要:
把所有潜在的参数存储在安全的地方,确保 GetImplementation 不会覆盖它们。
调用 GetImplementation 。
把返回值保存在某处。
恢复所有的参数值。
让我们开始吧!
这里我会尝试使用 X86-64 汇编,这样可以很方便的在 Mac上工作。这些概念也可以
应用于i386 或者ARM
这个函数会保存在独立的文件中,叫做 msgsend-asm.s。这个文件可以像源文件那样
传递给编译器,然后会被编译并链接到程序中。
第一件事要做的是声明全局的符号( global symbol )。因为一些无聊的历史原因, C
函数的global symbol 会在名字前有个下划线:
.globl _objc_msgSend
_objc_msgSend:
编译器会很高兴的链接最近可使用的 (n earest available) objc_msgSe nd 。简单的链
接这个到一个测试 app已经可以让[obj messag
您可能关注的文档
最近下载
- 水力发电原理与设备(图文)课件.ppt VIP
- 水电站运行与管理课件PPT.pptx VIP
- 2026年高考数学一轮复习专题2.4 指数与指数函数(举一反三讲义)(全国)(解析版).pdf VIP
- 医学装备部工作制度.docx VIP
- 2023年新高一(初升高)暑期数学衔接(新人教版)第11讲 指数与指数函数(教师版).docx VIP
- 学堂在线马克思主义经典著作研读期末考试答案.docx VIP
- 黑布林阅读初三1《哈克贝利·费恩历险记》中文版.pdf
- 2026届绵阳高三上学期第一次诊断性考试物理试题+答案.doc VIP
- 黑布林《哈克贝利费恩历险记》中文翻译.docx VIP
- 《神经网络模型》课件.ppt VIP
原创力文档


文档评论(0)