This section explains how messages can be dispatched, i.e. how the implementation of a method can be invoked, given the message.
A method is translated by the compiler to a C function with essentially the same arguments as the method, with two mandatory additions and some additions depending on the return type of the method. For the method
(boolean, Any) next
defined for the instance tom.Enumerator
, the C function
implementing this is
tom_byte i_tom_Enumerator__or__next (tom_object self, selector cmd, tom_object *ret1)
As can be seen, the first element of the tuple return type is the type
returned by the implementation C function. Such a function always has
two `implicit' first arguments: self
being the object receiving
the message, and cmd
being the message sent. Following these two
are the `normal' arguments to the method, which are none in this case.
Finally, any of the remaining return values are to be returned in the
pointer arguments supplied after the normal arguments. In the example,
a pointer for returning the second tuple element is provided.
A message is dispatched by invoking the method implementation for the
given (self, cmd)
pair. The lookup of the implementation,
i.e. the pointer to the C function, can be done in three different ways:
trt_lookup
with the receiver and the selector
to be invoked (i.e. the values to be passed for self
and
cmd
). trt_lookup
returns a function pointer to the method
implementation. Invoke that function with the arguments.
trt_lookup
function. This is a rather unwise way of invoking a method as it
considerably increases code size.
trt_send
to dispatch a message, the function
trt_send
is invoked with all the arguments to be passed to the
method implementation. trt_send
will perform the lookup and jump
directly to the implementation.
These different dispatching mechanisms can be selected by an option to otmc. They are described here for explanatory purposes; never implement any of these directly in your C code; the next section explains how to do that portably.
Sending is the preferred way of dispatching messages, though possibly
not present on all TOM implementations as it involves an assembly
language routine. Also note that there are dependencies of the
applicability of some dispatching mechanisms. For example, it is
impossible to use sending on dynamically loaded code on hppa-hpux
machines. This is not a TOM feature but due to the interspace stubs
needed by the hpux shared library interspace calls, added to the fact
that a callee stores the return program counter in the stack frame of
the caller.
When doing profiling on a TOM program, all code should really use the
lookup way of dispatching instead of sending to dispatch. Otherwise,
all methods will be reported to only invoke trt_send
, and
trt_send
will be reported as the culprit which invoked every
method and thus effectively void the use of the call graph.
Go to the first, previous, next, last section, table of contents.