Re: Some in-depth Obj-C runtime questions.
Re: Some in-depth Obj-C runtime questions.
- Subject: Re: Some in-depth Obj-C runtime questions.
- From: Chris Kane <email@hidden>
- Date: Mon, 2 Jul 2001 18:36:47 -0600
On Monday, July 2, 2001, at 01:42 AM, John C. Randolph wrote:
>
Poking around in GDB, I obtained the following description for the
>
method signature of [NSView drawRect:].
>
>
(gdb) po [sender
>
methodSignatureForSelector:(SEL)NSSelectorFromString(@"drawRect:")]
>
NSMethodSignature <0x18c45a0> types(v@:{?={?=ff}{?=ff}}) nargs(3)
>
frameSize(160) retType(v) retSize(0)
>
{0 : type(@:{?={?=ff}{?=ff}}) size(4) offset(128)}
>
{1 : type(:{?={?=ff}{?=ff}}) size(4) offset(132)}
>
{2 : type({?={?=ff}{?=ff}}) size(16) offset(136)}
>
{0 : type({?=ff}{?=ff}}) size(8) offset(136)}
>
{0 : type(ff}{?=ff}}) size(4) offset(136)}
>
{1 : type(f}{?=ff}}) size(4) offset(140)}
>
{1 : type({?=ff}}) size(8) offset(144)}
>
{0 : type(ff}}) size(4) offset(144)}
>
{1 : type(f}}) size(4) offset(148)}
>
>
Now, this method should have three arguments: self, _cmd, and rect.
>
"rect" of course, is a struct containing two other structs, an NSPoint
>
and an NSSize, each of which is a struct of two floats.
[...]
>
{0 : type({?=ff}{?=ff}}) size(8) offset(136)}
>
> {0 : type(ff}{?=ff}}) size(4) offset(136)}
>
> {1 : type(f}{?=ff}}) size(4) offset(140)}
>
>
Here's what I don't get. This looks to me like a bug in the
>
-description method, because I would expect this to be:
>
>
{0 : type({?=ff}{?=ff}}) size(8) offset(136)}
>
{0 : type(f) size(4) offset(136)}
>
{1 : type(f) size(4) offset(140)}
>
>
since the components of the NSPoint are just floats, I don't see why
>
they're followed by what looks like a struct encoding.
Look carefully at what is happening in the case of the overall dump
above, the text after the "type(" on each line. Then look at the
specific "recursive" case of the rect parameter. The same thing is
happening, which is the type code for that value, and the rest of the
string, is being emitted.
>
If I forget about using -description and just go right to
>
>
(gdb) p (char *) [$5 getArgumentTypeAtIndex:2]
>
>
I get:
>
>
"{?={?=ff}{?=ff}}\000"
>
>
Can I safely assume that the size of any argument can be obtained by
>
just tallying up the sizes of all the f's, i's, :'s, etc?
No, because ObjC adopts the ABI (application binary interface) of the
underlying C language on whatever platform it's on. That is, a function
call and a message expression end up being compiled down to,
essentially, the same sort of sequences of code.
The problem is that the ABI specifies how arguments are packaged up and
layed out into registers, stack, wherever. This does not necessarily
map to sizes of individual components (if that even has a meaning) of a
struct, for example. The rules for PowerPC are quite complex; for
example, the layout/size of the data in a struct in memory (say, a
global variable or whatever) is not the same as the same struct being
passed as a parameter in several cases. If you go back a few years on
the OmniGroup macosx-dev mailing list archives, more details -- probably
not complete -- of this has been discussed before.
If instead we defined ObjC calling conventions like "A translator can do
what it likes with arguments to function calls, but for a message send,
it must do this and this and this...", then things might be more
predictable. But probably slower to send a message.
>
How is [NSMethodSignature description] obtaining the offsets of each of
>
these elements? Is it pulling them out of the runtime, or relying on
>
the type encoding?
Computing them using the rules for the particular platform ABI, AND
taking into account what the runtime's expectations are, for functions
like _objc_msgForward(). The ObjC runtime doesn't know much about
dealing with individual arguments, even if it looks like it does;
NSMethodSignature has more of a clue.
>
One other question, is why is self's offset 128 bytes from the
>
beginning of the stack frame? What all is in the stack frame besides
>
the return address?
These things are wherever the ObjC runtime wants/expects them for things
like forwarding and objc_msgSendv(). They don't necessarily relate to
anything "real", or "actual" stack frames created by a compiler.
NSMethodSignature/NSInvocation and the runtime just need to agree in a
particular release.
Chris Kane
Cocoa Frameworks, Apple, Inc.