[Openmcl-devel] GF invocation protocol

Gary Byers gb at clozure.com
Wed Sep 12 00:43:20 PDT 2007

On Tue, 11 Sep 2007, Slava Akhmechet wrote:

> Gary Byers <gb at clozure.com> writes:
>> I think that it's fair to say:
>> 1) Some people need the MOP's GF invocation protocol.
>> 2) A lot of people don't.
> To be fair, you could probably make this argument about every other
> feature of MOP recommendation :)

To varying degrees, yes.

>> Not really.  The way that GF dispatch works in OpenMCL depends on
>> some low-level gunk (method functions receive extra invisible/magic
>> arguments, generic functions rarely use lists to represent the set
>> of arguments that they receive, etc.)
> Ok. In this case, how can I obtain the function associated with a
> funcallable-instance in OpenMCL (from what I understand there is no
> MOP recommendation for doing it)? I'm basically looking for the
> opposite of set-funcallable-instance-function. I might be able to
> achieve what I want via changing it on affected generic functions
> directly.

Well, you can get the "discriminating code" (aka "dcode") for a
generic function via the function CCL::%GF-DCODE:

? (ccl::%gf-dcode #'stream-read-char)
#<Compiled-function CCL::%%ONE-ARG-DCODE #x300040167ABF>
? (ccl::%gf-dcode #'stream-write-char)
#<Compiled-function CCL::%%1ST-TWO-ARG-DCODE #x30004016732F>

Note that these functions accept different arguments (CCL::ARGLIST
will try to show a function's argument list in some mostly-readable
form, for debugging):

? (ccl::arglist #'ccl::%%one-arg-dcode)
? (ccl::arglist #'ccl::%%1st-two-arg-dcode)

There are about half a dozen different builtin dcode functions defined
(along with many other things) in "ccl:level-1;l1-dcode.lisp".
Different dcode functions support different patterns of argument
specialization and themselves accept different arguments; they're
installed by the function CCL::COMPUTE-DCODE, which also modifies the
generic function so that it passes incoming arguments in some way and
a "dispatch table" (a cache, basically) to the dcode function.


(defgeneric example (x y z))

(set-funcallable-instance-function #'example #'(lambda (&rest args) (format t "~& got args: ~s" args)))


(set-funcallable-instance-function #'example #'(lambda (&rest args) (do-MOP-compatible-method-dispatch args)))

The latter case is harder: the ABI for method invocation is different from
what the MOP specifies, and it would be a non-trivial exercise to get
MOP-compliant GF-dispatch code to coexist with the existing stuff, I think.

>> This low-level gunk isn't extensible or very close to what the MOP
>> specifies, but - all other things being equal and in isolation -
>> tends to be faster than doing things in a MOP-compliant way would
>> be.  If overhead's introduced here, it has to be removed from some
>> other aspects of GF dispatch (or GF dispatch would slow down in all
>> cases.)
> I'm not sure what you mean. AFAIK most implementations use optimized
> routines for standard metaclasses and don't allow (or ignore)
> specializations on them. Custom metaclasses, on the other hand, allow
> for specialized behavior so that one can opt for customized
> functionality at a performance cost without affecting performance of
> standard features. Or am I misunderstanding something?

The difference isn't that OpenMCL's GF dispatch code is a lower-level
implementation of the MOP's proptocol, it's that it's basically a
different interface entirely.

> Thanks for your help.
> -- 
> Regards,
> Slava Akhmechet.

More information about the Openmcl-devel mailing list