I am having problem understanding part of the function of "selectors", as described in Apple's guide. I've bolded the parts where I am getting confused:
In Objective-C, selector has two meanings. It can be used to refer
simply to the name of a method when it’s used in a source-code message
to an object. It also, though, refers to the unique identifier that
replaces the name when the source code is compiled. Compiled
selectors are of type SEL. All methods with the same name have the
same selector. You can use a selector to invoke a method on an
object—this provides the basis for the implementation of the
target-action design pattern in Cocoa.
Methods and Selectors For efficiency, full ASCII names are not used as
method selectors in compiled code. Instead, the compiler writes each
method name into a table, then pairs the name with a unique identifier
that represents the method at runtime. The runtime system makes sure
each identifier is unique: No two selectors are the same, and all
methods with the same name have the same selector.
Can anyone explain these bits? Additionally, if different classes have methods with the same name, will they also have the same selector?
All selectors are uniqued -- both at compile time and, dynamically, at runtime through sel_getUid() or the preferred sel_registerName() (the latter being largely preferred, the former still around for historical reasons) -- for speed.
Back story: to call a method, the runtime needs a selector that identifies what is to be called and an object that it will be called on. This is why every single method call in Objective-C has two parameters: the obvious and well known self and the invisible, implied, parameter _cmd. _cmd is the SEL of the method currently executing. That is, you can paste this code into any method to see the name -- the selector -- of the currently executing method:
NSLog(#"%#", NSStringFromSelector(_cmd));
Note that _cmd is not a global; it really is an argument to your method. See below.
By uniquing the selectors, all selector based operations are implemented using pointer equality tests instead of string processing or any pointer de-referencing at all.
In particular, every single time you make a method call:
[someObject doSomething: toThis withOptions: flags]; // calls SEL doSomething:withOptions:
The compiler generates this code (or a very closely related variant):
objc_msgSend(someObject, #selector(doSomething:withOptions:), toThis, flags);
The very first thing objc_msgSend() does is check to see if someObject is nil and short-circuit if it is (nil-eats-message). The next (ignoring tagged pointers) is to look up the selector in someObjects class (the isa pointer, in fact), find the implementation, and call it (using a tail call optimization).
That find the implementation thing has to be fast and to make it really fast, you want the key to finding the implementation of the method to be as fast and stable as possible. To do that, you want the key to be directly usable and globally unique to the process.
Thus, the selectors are uniqued.
That it also happens to save memory is an fantastic benefit, but the messenger would use more memory than it does today if messenging could be made 2x faster (but not 10x for 2x -- or even 2x memory for 2x speed -- while speed is critical, memory use is also critical, certainly).
If you really want to dive deep on how objc_msgSend() works, I wrote a bit of a guide. Note that it is slightly out of date as it was written before tagged pointers, blocks-as-implementation, and ARC were disclosed. I should update the articles.
Yes. Classes do share selectors.
I can give an example from the source code objc-sel.mm, but when you use sel_registerUid() (used behind the scenes in #selector()),
It copies the input string into an internal buffer (if the string hasn't been registered before), for which all future SELs point to.
This is done for less memory usage, and easier message forwarding.
It also, though, refers to the unique identifier that replaces the name when the source code is compiled... All methods with the same name have the same selector.
For this, I refer to an excellent blog post on selectors:
A selector is the same for all methods that have the same name and parameters — regardless of which objects define them, whether those objects are related in the class hierarchy, or actually have nothing to do with each other. At runtime, Objective-C goes to the class and outright asks it, "Do you respond to this selector?", and calls the resulting function pointer if it does.
The runtime system makes sure each identifier is unique: No two selectors are the same, and all methods with the same name have the same selector.
In a screwed up way, this makes sense. If Method A and Method B have the exact same name and arguments, wouldn't it be more efficient to store their selector as one lookup and query the receiver instead of deciding between two basically equally named selectors at runtime?
Look at the SEL type, you don't have to define which class this selector is from, you just give it a method name, for example:
SEL animationSelector = #selector(addAnimation:forKey:);
You can imagine it as a streetname, for example. Many cities can have the same streetnames, but a streetname without a city is worthless. Same for selectors, you can define a selector without adding the object where it's in. But it's complete worthless without fitting class..
Related
I'm trying to understand the method "withArgs: executeMethod: " in smalltalk, squeak.
1. I am trying to understand what is the role of the method?
2. What arguments need to be passed to it for it to be carried out?
A good way to understand this method is by considering it as a syntactic variant of the general expression
object msg: arg (*)
where object is the receiver of the message with selector msg: and arg its argument. There are of course variants with no or multiple arguments, but the idea is the same.
When object receives this message (*) the Virtual Machine (VM) looks up for the CompiledMethod with selector msg: in the object's hierarchy, and transfers it the control, binding self to object and the formal argument of the method to arg.
Notice that this invocation is managed by the VM, no by the Virtual Image (VI). So, how could we reflect the same in the VI? Well, there are two steps in this behavior (1) find the method and (2) bind its formal receiver and arguments to the actual ones and let it run.
Step (1) is the so called lookup algorithm. It is easily implemented in Smalltalk: just ask the receiver its class, check whether the class includes the selector #msg: and, if not, go to the superclass and repeat. If all checks fail, issue the doesNotUnderstand: message.
Step (2) exactly requires what #withArgs:executeMethod: provides. It allows us to say
object withArgs: {arg} executeMethod: method
where method is the CompiledMethod found in step (1). [We have to use {arg} rather than arg because the plural in withArgs: suggests that the method expects an Array of arguments.]
Why would we want this?
Generally speaking, giving the VI the capability to mimic behavior implemented in the VM is good because it makes metaprogramming easier (and more natural).
More practically, a relevant example of the use of this capability is the implementation of Method Wrappers. Briefly described, given any particular method, you can wrap it (as the wrappee) inside a wrapper method, which also has a preBlock. If you then substitute the original method in the MethodDictionary where it belongs, with the wrapper, you can let the wrapper first execute the preBlock and then the intended method. The first task is easy: just send the message preBlock value. For the second we have the method (the wrappee), the receiver and the arguments (if any). So, to complete the task you only need to send to the receiver withArgs:executeMethod: with the actual argument(s) and the wrappee.
Ah! Let's not forget to mention that one of the reasons for having Method Wrappers is to measure testing coverage.
Note also that withArgs:executeMethod: does not require the second argument, i.e., the method to execute, to be in any class, let alone the class of the receiver. In particular, you could create a CompiledMethod on the fly and execute it on any given object. Of course, it is up to you to make sure that the execution will not crash the VM by, say, using the third ivar of the receiver if the receiver has only two etc. A simple way to create a CompiledMethod without installing it in any class is by asking the Smalltalk compiler to do so (look for senders of newCompiler to learn how to do that).
I'm new to Objective-C and was wondering if anyone could provide any information to clarify this for me. My (possibly wrong) understanding of object instantiation in other languages is that the object will get it's own copies of instance variables as well as instance methods, but I'm noticing that all the literature I've read thus far about Objective-C seems to indicate that the object only gets copies of instance variables, and that even when calling an instance method, program control reverts back to the original method defined inside the class itself. For example, this page from Apple's developer site shows program flow diagrams that suggest this:
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW1
Also in Kochan's "Programming in Objective-C", 6th ed., pg. 41, referring to an example fraction class and object, the author states that:
"The first message sends the setNumerator: message to myFraction...control is then sent to the setNumerator: method you defined for your Fraction class...Objective-C...knows that it's the method from this class to use because it knows that myFraction is an object from the Fraction class"
On pg. 42, he continues:
"When you allocate a new object...enough space is reserved in memory to store the object's data, which includes space for its instance variables, plus a little more..."
All of this would seem to indicate to me that there is only ever one copy of any method, the original method defined within the class, and when calling an instance method, Objective-C simply passes control to that original copy and temporarily "wires it" to the called object's instance variables. I know I may not be using the right terminology, but is this correct? It seems logical as creating multiple copies of the same methods would be a waste of memory, but this is causing me to rethink my entire understanding of object instantiation. Any input would be greatly appreciated! Thank you.
Your reasoning is correct. The instance methods are shared by all instances of a class. The reason is, as you suspect, that doing it the other way would be a massive waste of memory.
The temporary wiring you speak of is that each method has an additional hidden parameter passed to it: a pointer to the calling object. Since that gives the method access to the calling object, then it can easily access all of the necessary instance variables and all is well. Note that any static variable exists in only a single instance as well and if you are not aware of that, unexpected things can happen. However, regular local variables are not shared and are recreated for each call of a method.
Apple's documention on the topic is very good so have a look for more info.
Just think of a method as a set of instructions. There is no reason to have a copy of the same method for each object. I think you may be mistaken about other languages as well. Methods are associated with the class, not individual objects.
Yes, your thinking is more or less right (although it's simpler than that: behind the scenes in most such languages methods don't need to be "wired" to anything, they just take an extra parameter for self and insert struct lookups before references to instance variables).
What might be confusing you is that not all languages work this way, in their implementations and semantically. Object-oriented languages are (very roughly) divided into two camps: class-based, like Objective-C; and prototype-based, like Javascript. In the second camp of languages, a method or procedure really is an object in its own right and can often be assigned directly to an object's instance variables as well - there are no classes to lookup methods from, only objects and other objects, all with the same first-class status (this is an oversimplification, good languages still allow for sharing and efficiency).
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.
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.
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
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.
In Objective-C, there are at least two ways to get (or create? Hence the question) a selector: #selector(foo:bar:), or NSSelectorFromString(#"foo:bar:"). But what is the lifetime of a selector?
Since selectors know (at least) their name, they are unlikely to be copiable values of a fixed size that can be shuffled around the program. This means that someone needs to allocate and possibly deallocate them. Most objects from the Cocoa framework have retain-release semantics, which make their ownership explicit and relatively easy to track. However, I see no clear concept of ownership for selectors.
I expect that selectors obtained with the first syntax live as globals for the whole life of the program (like literal strings), but what about the other? If I create/get a selector with NSSelectorFromString(#"foo:bar:"), will it be valid for the whole life of my program too?
It's "get", not "create". Both of those simply retrieve the selector, which is created and owned by the runtime system. The SEL's lifetime is therefore effectively immortal.
If you wanted to create a selector yourself, you would need to use the runtime function sel_registerName(). This function is used by NSSelectorFromString() if you pass it a name which is as yet unknown to the runtime.
As per Apple's documentation, selectors are registered globally and live forever. If you pass a new or unknown selector name to NSSelectorFromString it will be registered as a new selector.
When creating an iOS program is there any performance hit if I pass around SELs (#selectors) and invoke them in other classes? Is this significantly slower than normal method invocations?
Why would there be a performance hit for messaging (the one thing ObjC is famous for) from other classes? Of course, compared to C functions, there is some overhead (thanks to the addition of two more parts to a method). Selectors are simply data types, so passing them to type SEL is no more costly than sending a BOOL or an int over. However, to actually call a SEL type from a passed selector, the creation of an NSInvocation object is recommended, which would slightly increase the overhead time.
And you are more or less safe in objC, as messages to nil (you did mention other classes), produce nil.
Well it might not have much of effect except on first run as compiler creates a reference to every objects and it's dependencies along with classes at compile time , so it might be a bit slow at loading time(that too in very large programs..) but not much after that provided not very big objects are created in the intermediate steps and also it doesn't involve any large dynamic operation as here i am talking only about calling a local function and calling the same function from a different class.
Anyways why would you use selector to reference to some function in a different class.
From my limited knowledge, a selector is simply an encoding of a method name. Given that in objective-c methods are called by sending messages to objects, I don't see why there should be a performance difference between an explicit method call ([object method]) and an implicit call ([objectDelegate selector]).