Patchwork libobjc: documentation update

login
register
mail settings
Submitter Nicola Pero
Date Dec. 22, 2010, 3:14 p.m.
Message ID <1293030867.6584813@192.168.2.229>
Download mbox | patch
Permalink /patch/76419/
State New
Headers show

Comments

Nicola Pero - Dec. 22, 2010, 3:14 p.m.
This patch updates the documentation on libobjc in the GCC manual.

It adds a section explaining first of all how the GNU Objective-C runtime
does message sending, which is different from how the Apple/NeXT Objective-C
runtime does it.  This section is (or should be) totally obvious to the people working
on the Objective-C compiler or runtime but may be new/unexpected for some users
who come from the Apple/NeXT Objective-C runtime, so it's good to have the explanation
there.

Moreover, it explains how the +resolveClassMethod: and +resolveInstanceMethod:
mechanism works (which is new in GCC 4.6 so even some hardcore GNU runtime users
may not know about it) and then explains how the forwarding is currently
implemented between libobjc and gnustep-base.  It's important to document that
because what is documented there (which is what gnustep-base currently uses) is
what we'll preserve (and expand on) in the next release of GCC.  Instead, what
is not documented there, or only mentioned as a deprecated piece about to go
away, will actually go away in the next release of GCC.

I'll wait a day or so for any feedback, suggestions or typo corrections
before committing it.

Thanks

Patch

Index: ChangeLog
===================================================================
--- ChangeLog   (revision 168168)
+++ ChangeLog   (working copy)
@@ -1,3 +1,11 @@ 
+2010-12-22  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * doc/objc.texi (Modern GNU Objective-C runtime API): Mention that
+       reference documentation for functions in the API is in the header
+       files.
+       (Messaging with the GNU Objective-C runtime, Dynamically
+       registering methods, Forwarding hook): New sections.
+
 2010-12-22  Martin Jambor  <mjambor@suse.cz>
 
        PR tree-optimization/45934
Index: doc/objc.texi
===================================================================
--- doc/objc.texi       (revision 168168)
+++ doc/objc.texi       (working copy)
@@ -22,6 +22,7 @@  several resources on the Internet that present the
 * Exceptions::
 * Synchronization::
 * Fast enumeration::
+* Messaging with the GNU Objective-C runtime::
 @end menu
 
 @c =========================================================================
@@ -104,6 +105,9 @@  platform-independent set of threading functions.
 
 @end itemize
 
+The header files contain detailed documentation for each function in
+the GNU Objective-C runtime API.
+
 @c =========================================================================
 @node Traditional GNU Objective-C runtime API
 @subsection Traditional GNU Objective-C runtime API
@@ -1086,3 +1090,137 @@  Finally, note how we declared the @code{len} argum
 value to be of type @code{unsigned long}.  They could also be declared
 to be of type @code{unsigned int} and everything would still work.
 
+@c =========================================================================
+@node Messaging with the GNU Objective-C runtime
+@section Messaging with the GNU Objective-C runtime
+
+This section is specific for the GNU Objective-C runtime.  If you are
+using a different runtime, you can skip it.
+
+The implementation of messaging in the GNU Objective-C runtime is
+designed to be portable, and so is based on standard C.
+
+Sending a message in the GNU Objective-C runtime is composed of two
+separate steps.  First, there is a call to the lookup function,
+@code{objc_msg_lookup ()} (or, in the case of messages to super,
+@code{objc_msg_lookup_super ()}).  This runtime function takes as
+argument the receiver and the selector of the method to be called; it
+returns the @code{IMP}, that is a pointer to the function implementing
+the method.  The second step of method invocation consists of casting
+this pointer function to the appropriate function pointer type, and
+calling the function pointed to it with the right arguments.
+
+For example, when the compiler encounters a method invocation such as
+@code{[object init]}, it compiles it into a call to
+@code{objc_msg_lookup (object, @@selector(init))} followed by a cast
+of the returned value to the appropriate function pointer type, and
+then it calls it.
+
+@menu
+* Dynamically registering methods::
+* Forwarding hook::
+@end menu
+
+@c =========================================================================
+@node Dynamically registering methods
+@subsection Dynamically registering methods
+
+If @code{objc_msg_lookup()} does not find a suitable method
+implementation, because the receiver does not implement the required
+method, it tries to see if the class can dynamically register the
+method.
+
+To do so, the runtime checks if the class of the receiver implements
+the method
+
+@smallexample
++ (BOOL) resolveInstanceMethod: (SEL)selector;
+@end smallexample
+
+in the case of an instance method, or 
+
+@smallexample
++ (BOOL) resolveClassMethod: (SEL)selector;
+@end smallexample
+
+in the case of a class method.  If the class implements it, the
+runtime invokes it, passing as argument the selector of the original
+method, and if it returns @code{YES}, the runtime tries the lookup
+again, which could now succeed if a matching method was added
+dynamically by @code{+resolveInstanceMethod:} or
+@code{+resolveClassMethod:}.
+
+This allows classes to dynamically register methods (by adding them to
+the class using @code{class_addMethod}) when they are first called.
+To do so, a class should implement @code{+resolveInstanceMethod:} (or,
+depending on the case, @code{+resolveClassMethod:}) and have it
+recognize the selectors of methods that can be registered dynamically
+at runtime, register them, and return @code{YES}.  It should return
+@code{NO} for methods that it does not dynamically registered at
+runtime.
+
+If @code{+resolveInstanceMethod:} (or @code{+resolveClassMethod:}) is
+not implemented or returns @code{NO}, the runtime then tries the
+forwarding hook.
+
+Support for @code{+resolveInstanceMethod:} and
+@code{resolveClassMethod:} was added to the GNU Objective-C runtime in
+GCC version 4.6.
+
+@c =========================================================================
+@node Forwarding hook
+@subsection Forwarding hook
+
+The GNU Objective-C runtime provides a hook, called
+@code{__objc_msg_forward2}, which is called by
+@code{objc_msg_lookup()} when it can't find a method implementation in
+the runtime tables and after calling @code{+resolveInstanceMethod:}
+and @code{+resolveClassMethod:} has been attempted and did not succeed
+in dynamically registering the method.
+
+To configure the hook, you set the global variable
+@code{__objc_msg_foward2} to a function with the same argument and
+return types of @code{objc_msg_lookup()}.  When
+@code{objc_msg_lookup()} can not find a method implementation, it
+invokes the hook function you provided to get a method implementation
+to return.  So, in practice @code{__objc_msg_forward2} allows you to
+extend @code{objc_msg_lookup()} by adding some custom code that is
+called to do a further lookup when no standard method implementation
+can be found using the normal lookup.
+
+This hook is generally reserved for ``Foundation'' libraries such as
+GNUstep Base, which use it to implement their high-level method
+forwarding API, typically based around the @code{forwardInvocation:}
+method.  So, unless you are implementing your own ``Foundation''
+library, you should not set this hook.
+
+In a typical forwarding implementation, the @code{__objc_msg_forward2}
+hook function determines the argument and return type of the method
+that is being looked up, and then creates a function that takes these
+arguments and has that return type, and returns it to the caller.
+Creating this function is non-trivial and is typically performed using
+a dedicated library such as @code{libffi}.
+
+The forwarding method implementation thus created is returned by
+@code{objc_msg_lookup()} and is executed as if it was a normal method
+implementation.  When the forwarding method implementation is called,
+it is usually expected to pack all arguments into some sort of object
+(typically, an @code{NSInvocation} in a ``Foundation'' library), and
+hand it over to the programmer (@code{forwardInvocation:}) who is then
+allowed to manipulate the method invocation using a high-level API
+provided by the ``Foundation'' library.  For example, the programmer
+may want to examine the method invocation arguments and name and
+potentially change them before forwarding the method invocation to one
+or more local objects (@code{performInvocation:}) or even to remote
+objects (by using Distributed Objects or some other mechanism).  When
+all this completes, the return value is passed back and must be
+returned correctly to the original caller.
+
+Note that the GNU Objective-C runtime currently provides no support
+for method forwarding or method invocations other than the
+@code{__objc_msg_forward2} hook.
+
+If the forwarding hook does not exist or returns @code{NULL}, the
+runtime currently attempts forwarding using an older, deprecated API,
+and if that fails, it aborts the program.  In future versions of the
+GNU Objective-C runtime, the runtime will immediately abort.