为什么Objective-C编译器需要知道方法签名? [英] Why does the Objective-C compiler need to know method signatures?

查看:100
本文介绍了为什么Objective-C编译器需要知道方法签名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么Objective-C编译器需要在编译时知道将对象推迟到运行时(即动态绑定)时将在对象上调用的方法的签名?例如,如果我写[foo someMethod],为什么编译器必须知道someMethod的签名?

Why does the Objective-C compiler need to know at compile-time the signature of the methods that will be invoked on objects when it could defer that to runtime (i.e., dynamic binding)? For example, if I write [foo someMethod], why it is necessary for the compiler to know the signature of someMethod?

推荐答案

由于至少需要调用约定(对于ARC,有更多的原因,但是调用约定一直是个问题).

Because of calling conventions at a minimum (with ARC, there are more reasons, but calling conventions have always been a problem).

您可能已经被告知[foo someMethod]被转换为函数调用:

You may have been told that [foo someMethod] is converted into a function call:

objc_msgSend(foo, @selector(someMethod))

但是,这并非完全正确.取决于返回的内容(无论是否使用结果,返回的内容都很重要),它可能会转换为许多不同的函数调用.例如,如果它返回一个对象或整数,它将使用objc_msgSend,但是如果它返回一个结构(在ARM和Intel上),则将使用objc_msgSend_stret,并且如果它在Intel上返回一个浮点数(但我相信不是ARM),它将使用objc_msgSend_fpret.这是因为在不同的处理器上,调用约定(如何设置堆栈和寄存器以及如何存储结果)取决于结果.

This, however, isn't exactly true. It may be converted to a number of different function calls depending on what it returns (and what's returned matters whether you use the result or not). For instance, if it returns an object or an integer, it'll use objc_msgSend, but if it returns a structure (on both ARM and Intel) it'll use objc_msgSend_stret, and if it returns a floating point on Intel (but not ARM I believe), it'll use objc_msgSend_fpret. This is all because on different processors the calling conventions (how you set up the stack and registers, and where the result is stored) are different depending on the result.

参数的个数和个数也很重要(可以从ObjC方法名称中推断出这些数字,除非它们是varargs ...对,您也必须处理varargs).在某些处理器上,前几个参数可以放在寄存器中,而后几个参数可以放在堆栈中.如果您的函数采用varargs,则调用约定可能仍然不同.为了编译函数调用,必须了解所有这些信息.

It also matters what the parameters are and how many there are (the number can be inferred from ObjC method names unless they're varargs... right, you have to deal with varargs, too). On some processors, the first several parameters may be put in registers, while later parameters may be put on the stack. If your function takes a varargs, then the calling convention may be different still. All of that has to be known in order to compile the function call.

ObjC可以实现为更纯净的对象模型来避免所有这些情况(就像其他动态语言一样),但这会以性能(空间和时间)为代价.考虑到动态调度的级别,ObjC可以便宜地使方法调用便宜,并且可以轻松地使用纯C机器类型,但是这样做的代价是我们必须让编译器知道有关方法签名的更多细节.

ObjC could be implemented as a more pure object model to avoid all of this (as other, more dynamic languages do), but it would be at the cost of performance (both space and time). ObjC can make method calls surprisingly cheap given the level of dynamic dispatch, and can easily work with pure C machine types, but the cost of that is that we have to let the compiler know more specifics about our method signatures.

顺便说一句,这可能(而且经常这样做)导致真正可怕的错误.如果您有两种方法:

BTW, this can (and every so often does) lead to really horrible bugs. If you have a couple of methods:

- (MyPointObject *)point;

- (CGPoint)point;

也许它们在完全不同的文件中定义为不同类上的方法.但是,如果编译器选择了错误的定义(例如,当您向id发送消息时),那么从-point返回的结果可能是完全垃圾.这是一个非常非常难以发现的错误,以便弄清楚它何时发生(我已经发生在我身上了).

Maybe they're defined in completely different files as methods on different classes. But if the compiler chooses the wrong definition (such as when you're sending a message to id), then the result you get back from -point can be complete garbage. This is a very, very hard bug to figure out when it happens (and I've had it happen to me).

更多背景信息,您可以喜欢格雷格·帕克(Greg Parker)的文章解释objc_msgSend_stret objc_msgSend_fpret . Mike Ash还具有出色的介绍这个话题.如果您想深入这个兔子洞,可以看到bbum的

For a bit more background, you may enjoy Greg Parker's article explaining objc_msgSend_stret and objc_msgSend_fpret. Mike Ash also has an excellent introduction to this topic. And if you want to go deep down this rabbit hole, you can see bbum's instruction-by-instruction investigation of objc_msgSend. It's outdated now, pre-ARC, and only covers x86_64 (since every architecture needs its own implementation), but is still highly educational and recommended.

这篇关于为什么Objective-C编译器需要知道方法签名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆