2

my question as the title says.obviously, the first parameter was used for this pointer , in some taste of c++.what about the second one? thak you.

vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
hao haochao
  • 91
  • 1
  • 8

3 Answers3

9

The signature of objc_msgSend() is:

id objc_msgSend(id self, SEL op, ...);

Every method call is compiled down to a call to this function. I.e., if you call:

[anArray objectAtIndex:42];

That will be compiled as if it were:

objc_msgSend(anArray, @selector(objectAtIndex:), 42);

Now, to your question, why do methods get compiled down to a function that has the SEL as the second argument. Or, more specifically, why is this method:

- (id)objectAtIndex:(NSUInteger)index;

Exactly equivalent to this C function:

id object_at_index(id object, SEL _cmd, NSUInteger index);

The answer is speed speed speed.

Speed

Specifically, by doing this, then objc_msgSend() never has to rewrite the stack frame* and it can also use a tail call optimization to jump directly to the method invocation. This is the same reason why you never see objc_msgSend() in backtraces in the debugger (save for when you actually crash/break in the messenger).

objc_msgSend() uses the object and the _cmd to look up the implementation of the method and then, quite literally, jumps to that implementation.

Very fast. Stack frame untouched.

And, as others have stated, having _cmd around in the method implementation can be handy for a variety of reasons. As well, it also means that the messenger can do neat tricks like proxy support via NSInvocation and the like.

*rewriting the stack frame can be insanely complex and expensive. Some of the arguments might be in registers some of the time, etc... All architecture dependent ABI nastiness. One of the biggest challenges to writing things like imp_implementationWithBlock() was figuring out how to do so without touching the stack because doing so would have been too slow and too bloated to be viable.

bbum
  • 162,346
  • 23
  • 271
  • 359
  • hi,@bbum. i don't have objc_msgSend implementation instead of objc_msglookup on GNUSTEP. i take a look at the GNUSTEP's objc_msglookup source, it was totally writen by ASM language, for speeding up. that asm codes used to lookup IMP, and return what the obj_msgSend found.finally, the invocation of returned IMP given back to caller of the objc_msglookup ,then executing it by caller . by the way, could you please tell me what the tail call optimization to objc_msgSend is ,and is compiler optimization behavior,or programming tricks? – hao haochao Jan 14 '13 at 10:07
  • Here: http://www.friday.com/bbum/2009/12/18/objc_msgsend-part-1-the-road-map/ The GNUSTEP objc runtime is quite similar to the Apple runtime. I'd be surprised if they aren't using tail calling as an optimization, too (tail call optimization is explained in the above link). – bbum Jan 14 '13 at 17:24
  • Yes, you can take a look at its implementation here http://svn.gna.org/svn/gnustep/libs/libobjc2/trunk/objc_msgSend.x86-32.S – Fred Frith-MacDonald Jan 15 '13 at 09:27
2

The purpose of having the second parameter contain the selector is to enable a common dispatch mechanism. As such, the method dispatch code always expects the second parameter to be the selector, and dispatches based on that, or follows the inheritance chain up, or even creates an NSInvocation and calls forwardInvocation:.

Generally, only system-level routines use the selector argument, although it's rather nice to have it when you hit an exception or are in the debugger trying to figure out what routine is giving you difficulties if you are using forwardInvocation

gaige
  • 17,263
  • 6
  • 57
  • 68
0

From the documentation:

Discussion

This data type is a pointer to the start of the function that implements the method. This function uses standard C calling conventions as implemented for the current CPU architecture. The first argument is a pointer to self (that is, the memory for the particular instance of this class, or, for a class method, a pointer to the metaclass). The second argument is the method selector. The method arguments follow.

In Objective-C when you call a method you need to know the target, the selector and the eventual arguments. Let's suppose that you are trying to do this manually: how can you know which method to call if you don't know the selector? Do you call some random method? No, you call the right method because you know the method name.

Ramy Al Zuhouri
  • 21,580
  • 26
  • 105
  • 187
  • hi, @Ramy Al Zuhouri. i know that the second argument is method selector(SEL) , which signs the message used to lookup method. but why to be the second argument of any method.i don't understand what benefit come of this situation.just like the fisrt argument used for accessing class method, memeber var, metaclass. but what about the second argument – hao haochao Jan 13 '13 at 16:19
  • In c++ a method call is composed by at least two things: the target and the method name. Something like obj.myMethod(). Well the second argument is used to distinguish which method we want to call. In Objective-C will be @selector(myMethod). – Ramy Al Zuhouri Jan 13 '13 at 16:25
  • Perhaps you could elaborate on this. Quoting Apple's documentation verbatim is far from an acceptable answer. – CodaFi Jan 13 '13 at 16:41
  • @haohaochao I haven't understood the last sentence, can you please explain it better? – Ramy Al Zuhouri Jan 13 '13 at 16:46
  • hi guys. i think gaige's answer is what i want.whatever, thank you. – hao haochao Jan 13 '13 at 17:56
  • From your recent questions, I'd like to suggest you a book. Objective-C Phrasebook by David Chisnall. – Fred Frith-MacDonald Jan 13 '13 at 20:31
  • hello @Fred Frith-MacDonald . i see you again. thanks you'r advice,and i think i really need some book to learn objective-c systematicly, or some book as refernce. i saw your recommended book from amazon seems appropriate for me . thank you. have you nice day.bye – hao haochao Jan 14 '13 at 06:42