guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

vm status update: goops compilation in the house


From: Andy Wingo
Subject: vm status update: goops compilation in the house
Date: Fri, 31 Oct 2008 19:25:43 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)

Hello,

Your friendly neighborhood (oop goops) has been nationalized and
reclaimed by a group calling itself the "People's Compilation Front"
(PCF). I found the following note scrawled on the back of a page of
R6RS, and wished to communicate it to the wider Guile community. I've
added some comments.

    $ ./pre-inst-guile
    Guile Scheme interpreter 0.5 on Guile 1.9.0
    Copyright (C) 2001-2008 Free Software Foundation, Inc.

    Enter `,help' for help.

We should release 1.9.1 soon, no? Maybe that way the PCF can keep the
old version and we can have the new one, like detente in the 70s.

    scheme@(guile-user)> (use-modules (oop goops))

I am afraid that it takes a bit longer to load than it used to; there
are margin notes on the document that suggest that large speedups are
possible, however.

    scheme@(guile-user)> (define-class <foo> ())
    scheme@(guile-user)> (define-method (bar (x <foo>)) (pk 'hi-mom))
    scheme@(guile-user)> (bar (make <foo>))

    ;;; (hi-mom)
    $1 = hi-mom

OK, so the PCF knows how to define classes and invoke methods. What's
the big deal?

    scheme@(guile-user)> (slot-ref (car (generic-function-methods bar)) 
'code-table)
    $2 = ((#<<class> <foo> 86971d0> . #<program #(2 35 #f) (x)>))

Oooh, is that a compiled method?

    scheme@(guile-user)> ,x (cdar $2)
    Disassembly of #<program #(2 35 #f) (x)>:

    nargs = 1  nrest = 0  nlocs = 0  nexts = 0

    Bytecode:

       0    (late-variable-ref 0)           ;; #<program peek stuff>
       2    (object-ref 1)                  ;; hi-mom             at (unknown 
file):2:35
       4    (goto/args 1)                                         at (unknown 
file):2:31

Why yes, yes it is!

    scheme@(guile-user)> (define-class <baz> (<foo>))
    scheme@(guile-user)> (define-method (bar (x <baz>)) (pk 'hi-dad) 
(next-method))
    scheme@(guile-user)> (bar (make <baz>))

    ;;; (hi-dad)

    ;;; (hi-mom)
    $3 = hi-mom

OK... not sure where they're going.. Although, I guess since there is a
(next-method) in this one, the case is slightly different...

    scheme@(guile-user)> (slot-ref (car (generic-function-methods bar)) 
'code-table)
    $4 = ((#<<class> <baz> 85ce110> . #<program 853f980 (x)>))

It took me a while to figure out why this didn't include the old entry,
but besides any cache invalidation effects, the PCF failed to note that
(generic-function-methods bar) was added to, with the new method defined
above -- must be the method on <baz>.

    scheme@(guile-user)> ,x (cdar $4)
    Disassembly of #<program 853f980 (x)>:

    nargs = 1  nrest = 0  nlocs = 1  nexts = 1

    Bytecode:

       0    (local-ref 0)                   ;; `x' (arg)
       2    (external-set 0)                ;; `x' (arg)

OK, capture the `x' arg on the heap...

       4    (object-ref 0)                  ;; #<program 853fa28 args>
       6    (make-closure)                  
       7    (local-set 1)                   ;; `next-method'

These instructions appear to bind the `next-method' local to some
program stuffed in object slot 0...

       9    (late-variable-ref 1)           ;; #<program peek stuff>
      11    (object-ref 2)                  ;; hi-dad
      13    (call 1)                        
      15    (drop)                          
      16    (local-ref 1)                   ;; `next-method'
      18    (goto/args 0)                   

Aha, here they invoke the next method just by referencing the
precomputed local procedure! That's quite clever of them, those
compilationists.

    Externals:

       0    #<program #(2 35 #f) (x)>       

    ----------------------------------------
    Disassembly of #<program 853fa28 args>:

    nargs = 1  nrest = 1  nlocs = 0  nexts = 0

    Bytecode:

       0    (local-ref 0)                   ;; `args' (arg)
       2    (null?)                         
       3    (br-if-not 0 6)                 ;; -> 12

So here we're disassembling the next-method stub; it appears to check if
the rest argument `args' is null; if it is, we continue through here:

       6    (external-ref 1)                ;; (closure variable)
       8    (external-ref 0)                ;; (closure variable)
      10    (goto/args 1)                   

Which appears to tail-call external #1 (relative to this procedure) with
the argument that is in external #0. #1 is probably that procedure above
that was not disassembled, and #0 would be `x'.

      12    (external-ref 1)                ;; (closure variable)
      14    (local-ref 0)                   ;; `args' (arg)
      16    (goto/apply 2)                  

And this seems to be `(apply <external-1> args)', for the case in which
`(next-method)' is given arguments.

Well, what can I say, those compilationists might be some loony people,
but their code looks correct. Should I send them a GNU copyright
assignment form? GNU takes all kinds, no?

Andy
-- 
http://wingolog.org/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]