Re: fixes to goops + light structs + 'u' slots

2008-04-19 Thread Andy Wingo
Hi Mikael,

On Tue 15 Apr 2008 00:16, Mikael Djurfeldt [EMAIL PROTECTED] writes:

 2008/4/14, Andy Wingo [EMAIL PROTECTED]:
 Regarding memory consumption. Currently, structs are double-cells: one
  word for the vtable, one for the data, one empty, and one for the
  STRUCT_GC_CHAIN, used (please correct me) during GC to ensure that
  structs are freed before their vtables.

 I wash my hands.  :-)  When I left, structs where two words.

commit 08c880a36746289330f3722522960ea21fe4ddc8
Author: Mikael Djurfeldt [EMAIL PROTECTED]
Date:   Wed Aug 9 18:29:31 2000 +

* struct.c (scm_make_struct, scm_make_vtable_vtable): Structs
handles are now double cells; Initialize SCM_STRUCT_GC_CHAIN to
0.
(scm_struct_gc_init, scm_free_structs): New GC C hooks.
(scm_struct_prehistory): Install them.

It is natural for our memory to fade over this much time ;-)

But if at any point something sparks in your brain to figure out a way
around the GC chain, I'd certainly be interested. Otherwise we could put
that empty third word to good use.

Andy
-- 
http://wingolog.org/




GOOPS todo

2008-04-19 Thread Andy Wingo
Hi all,

Mikael has mentioned on a number of occasions that GOOPS has some
unfinished pieces. I couldn't find any information on this in the
workbook, so I decided to write down a summary of the things that I've
seen. Please add to this list if you know of more things, or if I am
mistaken or miss something fundamental.

I'll be poking at some of these over time, but any help is appreciated!


incompleteness

* Slot access compilation in compute-getter-method /
  compute-setter-method assumes that slots are SCM objects, whereas if
  they are implemented as subclasses of foreign-slot they are raw
  machine words.

* Generic application only works for instances of generic, or for
  instances of a couple of other specially blessed classes. This is
  because for these classes, the C code knows how the objects will be
  laid out in memory, and can access memory directly instead of using
  slot-ref. In general in GOOPS (and in MOPs in general) there is a
  tension between extensibility and efficiency; the former is expressed
  in protocols of generic functions, and the latter in invariants and
  possibilities for direct memory access.

  The evaluator really needs to be able to do direct memory access, if
  possible. So for that reason the existing bits of generic function
  dispatch that are wired into eval.c check instances of those blessed
  clases, via checks like (SCM_OBJ_CLASS_FLAGS (proc) 
  SCM_CLASSF_PURE_GENERIC).

  This direct memory access also has repercussions in tail recursion;
  that if the code to dispatch a method can't bottom out in eval.c, we
  lose tail recursion.

  So, we need to add support for instances of subclasses of generic,
  without losing efficiency. Apparently there is some code for this, see
  goops.scm:apply-generic.

* We have no :before or :after methods. I don't know if STKlos had these
  either.

* GOOPS should define a with-accessors macro.

cruft

* define-method, if it finds that a variable is defined with its generic
  name, then verifies that the value is not #f, with the note *fixme*
  Temporary hack for the current module system. This appears to be
  completely unnecessary.

* use of the (apply append (map ...)) idiom instead of mapappend or the
  like in a few places

* objects.[ch] seems to be an unnecessary abstraction, now that GOOPS is
  in the core. It purports to define procedures that deal in classes,
  metaclasses, generics, etc., but in fact very little of this code is
  used, AFAICT.

documentation

* What is an extended-generic ? Seems to have to do with the module
  system's generics merging foo.

* What is an operator ? What is the goal of set-object-procedure! ?

* GOOPS reference should be folded into Guile's reference, as it is now
  part of Guile.

* A description of the method dispatch process, including the
  optimizations, would be really, really helpful. The interfaces that a
  MOP provides are carefully coded around potential optimizations that
  are not expressed in the specification, and not immediately obvious
  (to me). So some understanding of this negative specification would
  really help when hacking on this code.

* Possibly the worst section of Guile's manual:

5.15 Objects

 -- Scheme Procedure: entity? obj
 -- C Function: scm_entity_p (obj)
 Return `#t' if OBJ is an entity.

 -- Scheme Procedure: operator? obj
 -- C Function: scm_operator_p (obj)
 Return `#t' if OBJ is an operator.

 -- Scheme Procedure: set-object-procedure! obj proc
 -- C Function: scm_set_object_procedure_x (obj, proc)
 Set the object procedure of OBJ to PROC.  OBJ must be either an
 entity or an operator.

 -- Scheme Procedure: make-class-object metaclass layout
 -- C Function: scm_make_class_object (metaclass, layout)
 Create a new class object of class METACLASS, with the slot layout
 specified by LAYOUT.

 -- Scheme Procedure: make-subclass-object class layout
 -- C Function: scm_make_subclass_object (class, layout)
 Create a subclass object of CLASS, with the slot layout specified
 by LAYOUT.

optimization possibilities

* mutation of the method cache causes a full copy of the cache, so that
  it doesn't disturb other threads -- we should look to see what e.g.
  CLOS does about this

* method cache code could be rewritten in C (dispatch.scm), although I
  have never had a problem with it -- it doesn't show up on my profiles.

nastiness

* method compilation (e.g. the process of going from a define-method to
  a procedure -- basically, making sure that next-method does the right
  thing) is hacky, involving manual manipulation of the data structure
  describing the procedure's environment, calling procedure-source, etc.
  Also, the procedure-source call means that you can't make a subr
  implement a method. I do not understand the comment in compile.scm
  about next-method inlining -- what does this mean?

  (Why isn't compile-method run at macro-expansion (e.g. define-method)
  time?)

* GOOPS mucks around too 

Re: fixes to goops + light structs + 'u' slots

2008-04-19 Thread Mikael Djurfeldt
2008/4/19, Andy Wingo [EMAIL PROTECTED]:
  I wash my hands.  :-)  When I left, structs where two words.
 commit 08c880a36746289330f3722522960ea21fe4ddc8
  Author: Mikael Djurfeldt [EMAIL PROTECTED]

  It is natural for our memory to fade over this much time ;-)

  But if at any point something sparks in your brain to figure out a way
  around the GC chain, I'd certainly be interested. Otherwise we could put
  that empty third word to good use.

Sigh... Well, apparently I'm the very author of this GC chain thing
you are talking to me about.  The only thing I can say is that there
was probably a reason at the time to do this.  Of course, when looking
at it now, it doesn't look like good design.  In fact, and to be
honest, I've never had the impression that structs are good design
either.  The GC chain mostly looks like a bug fix, doesn't it?  The
problem is that you don't always have time and resources to redesign
the whole thing.  Most changes I've done to Guile have been done for
the use of Guile in my work.  The Right thing to do is probably to
throw out structs and design new GOOPS objects, something I  wanted to
do from the start.  Also, when considering GC-related
things---remember that a lot of design decisions have been made
against the garbage collector as it looked like three revisions ago,
or something like that.  The current GC is a very different beast.

Also, I've seen your GOOPS todo.  It's nice to see your willingness to
continue development on GOOPS.  Unfortunately, I won't have the time
to help.  Just don't be too quick to throw things out.  Some code
needs to be replaced, but then, again, some code has thought behind
it.  Since you say that you couldn't find information in the workbook,
I'll try to dig up my ideas regarding the PURE_GENERIC flag and the
apply-generic MOP.  The extended-generic stuff is a way to get
insulation between two modules A and B which both import a module C.
Otherwise I think I should shut up.

Oh, and please *don't* try to compile methods at macro expansion time.
 GOOPS method compilation is based on the crazy idea to have one
compiled method per combination of argument types.  The idea is that
this won't give you a combinatorial explosion if you compile lazily,
waiting until the first application for a certain combination.   This
was an experiment.  Apparently, it works well enough in practise.  The
*big* possibility is that since each compiled method in the method
cache has typed arguments, there is the opportunity for *very*
interesting optimizations, such as elimination of a lot of the type
dispatch (e.g. that in accessors and in other calls to generics).