
These notes correspond to the "July 92 PCL (1b)" version of PCL.

Changes since July 92 PCL (beta) include some minor bug fixes and performance
enhancements, along with new support for MCL 2.0 (thanks to Tom Morgan and
the kind folks at Apple) and for CLISP (thanks to Bruno Haible).

  This version of PCL is much closer than previous versions of PCL
to the metaobject protocol specified in "The Art of the Metaobject Protocol", 
chapters 5 and 6, by Gregor Kiczales, Jim des Riveres, and Daniel G. Bobrow.

[Please read the file march-92-notes.text and may-day-notes.text also.
  Most of those files still apply.]

Newly supported:

accessor-method-slot-definition
no-next-method
generic-function-argument-precedence-order
reader-method-class
writer-method-class
(setf class-name)

defgeneric :method option

class-default-initargs, class-precedence-list, class-prototype,
   and class-slots now signal errors when class is not finalized
   (as specified in AMOP ch 6).

Improvements to slot-access
  Optimization for slot-value of specialized parameter inside of defmethod.
  Optimization for standard cases of slot-value everywhere else.

Additional support for structures
  Redefines defstruct macro to give PCL access to all structure information
  for structure classes in addition to calling the original lisp defstruct.

All AMOP generic-functions now exported.

-------------------------
New gfs which obey AMOP ch 6, and some caveats:

documentation
  Stored in all classes, pcl::documentation works as defined.

generic-function-declarations
  Stored, but ignored.

make-method-lambda
method-function
  Compatible with AMOP, but will require additions to
  compute-discriminating-function and compute-effective-method to
  make fully useful.

  In July 92 PCL, method-function returns the documented AMOP
  method-function specified by the lambda returned by make-method-lambda.
  However, that method-function is not actually used in method function
  dispatch.  Instead, PCL's make-method-lambda and expand-defmethod also
  create an optimized method function (method-optimized-function) or
  closure generator (method-closure-generator) that it actually uses for
  method function caching and dispatch.  This is the same optimized
  function whose lambda-list is the lambda-list of the method used in
  previous versions of PCL.  There are two cases to worry about with this:

  1. The user specializes their own method on make-method-lambda without
     redefining compute-discriminating-function or being careful to make
     sure the method-optimized-function is set up properly (as done by the
     standard make-method-lambda).  Expand-defmethod will detect this case
     and create a method-optimized-function that calls the method-function
     created by the new make-method-lambda with the parameters *of the
     normal make-method-lambda*, i.e. (args methods).  This should work
     for most cases, albeit slowly, but will fail if the user's modification
     expects a different lambda list (as in the example of the AMOP, p. 209).

  2. The user specializes their own method on make-method-lambda, but also
     specializes compute-discriminating-function to call method-function
     directly.  This should work.


-------------------------
Functions which DO NOT obey AMOP:

compute-applicable-methods
compute-applicable-methods-using-classes
  Handles class-eq specializers without signalling an error.  
  See march-92-notes.text

compute-discriminating-function
  [the resulting function works differently different because 
   compute-effective-method is different, and because make-method-lambda 
   does not exist.]

compute-effective-method
  Returns only one value.

-------------------------
Miscellaneous optimizations:

Optimizations of slot-value of specialized parameter inside of
  defmethod:

  1. Closure variables are now used instead of lookup permutation
     vectors to store slot indices when the effective methods are
     cached each set of parameter classes they're called on (which
     is now all the time, using March 92's optimizations), saving an
     aref per slot access.
  2. The cached effective methods optimize slot-access based on the type
     of slot indices for the cached parameters.  There are three cases:
       (a) The most common case -- all specialized parameter slot
        accesses within the defmethod are on :instance allocated slots
        on standard instances without user-defined slot-value-using-class
        methods.  In this case, the cached closure for the method
        directly accesses the slot through an aref on the standard
        instance, without having to call (typep x 'fixnum) or figure out
        what type of instance it is.
       (b) If one of the slot accesses is on a non-:instance allocated slot,
        on a non-standard instance, or has a user-defined slot-value-using-class
        method, and store-optimized-method-lambda-p is true for the
        generic-function and method (the default defined in low.lisp being
        *compile-slot-access-method-functions-at-runtime-p* is T), then the
        method to be cached is compiled at runtime to optimize the slot accesses
        from a stored version of the method-lambda.  The compiled method to be
        cached directly codes in each slot access for the particular index
        and the type of the instance.
       (c). If there are non-standard slot accesses, as in case (b), but
        store-optimized-method-lambda-p for the generic-function and method
        is NIL, then the cached methods are not compiled at runtime.  Instead,
        the cached effective method is similar to previous PCL's, i.e.
        having to check the index and instance type for each slot access,
        though looking up the cached index in a closure variable rather than
        a permutation vector to save an aref.

Further optimizations of slot-value outside of defmethod or inside
  of defmethod, but not of a specialized parameter:

  1. If no non-standard specialized methods have been defined on
     slot-value-using-class, then slot-value directly looks up the
     value of the slot without calling any generic-functions or functions.

  2. If non-standard specialized methods have been defined on
     slot-value-using-class, then PCL arranges to call an automatically
     created generic function that has one method: a reader method defined
     on class slot-object (as in March 92 PCL).  This optimized generic-function
     is now called whether or not the slot-name is constant.

Make-instance, shared-initialize, and allocate-instance speeded up by:
  1. Implementing suggested instance slot-vector allocation optimization
     of the AMOP that copies a slot-vector whose side-effect-free slots
     are already initialized.
  2. Using internal copy of slot-definitions (as structures) to speed
     up time-intensive internal slot accesses (also speeds up
     slot-value-using-class).
  3. Usually assuming and assuring that all slot init-functions are compiled.

declarations of variable types throughout PCL where applicable.

avoids unnecessary class updates by lazier class finalization, giving
  faster compiling and loading.


-------------------------
Miscellaneous optional optimizations (see global variables at beginning
of file low.lisp for full options):

Variable *compile-all-method-functions-p* can be set to T, forcing all
  method functions to be compiled and allowing method function dispatch
  code to assume they are compiled.  Default is NIL.

Generic function store-method-function-p (generic-function method initargs)
  can be specialized to return NIL if the (normally unused) documented
  method-functions are not needed.  Saves some space and compile time.
  Default returns T.  Variable *standard-store-method-function-p*, which
  is what the default store-method-function-p method looks up, can be
  set to NIL if it is known that documented method functions will never
  be needed.

Generic function store-optimized-method-lambda-p (generic-function method initargs)
  can be specialized to return NIL if it is not desireable to optimize
  defmethod slot-accesses for non :instance allocated slots by compiling
  the cached methods at runtime.  (This might be the case if your lisp's
  compiler is slow, e.g. KCL, and each such method will only be called a
  few times, so that the optimization isn't worth the added runtime compile
  time.  Alternatively, *compile-slot-access-method-functions-at-runtime-p*
  in low.lisp can be set to NIL to make this the default for all methods.

-------------------------
Useful extensions to CLOS and AMOP:

boundp-method-class
finalize-all-classes

trace-methods
  Traces all individual methods of a generic-function (as per trace-method).

(setf standard-instance-access)
(setf funcallable-standard-instance-access)
  Functions to allow direct setting of instance slots
  (as standard-instance-access and funcallable-standard-instance-access).

standard-instance-slot-value
(setf standard-instance-slot-value)
standard-instance-slot-boundp
funcallable-standard-instance-slot-value
(setf funcallable-standard-instance-slot-value)
funcallable-standard-instance-slot-boundp
structure-instance-slot-value
(setf structure-instance-slot-value)
structure-instance-slot-boundp
  Macros for highly optimized slot access given type of instance
  (analogous to standard-instance-access):

with-optimized-slots
  Optimized version of with-slots with a couple of useful additions
  to with-slots' functionality.

with-standard-instance-slots
  Slightly faster version of with-optimized-slots for use when instance
  is guaranteed to be a standard-instance.

this-method
  Function locally defined within the body of methods to return the method
  currently being executed.


-------------------------
Useful low-level extensions to PCL:

Class wrappers now have one unreserved field available for programmer use
  (accessed by wrapper-unreserved-field).

Hooks built in to allow programmers to define their own USER-INSTANCE
  low-level type of instances different from STD-INSTANCE, FSC-INSTANCE,
  STRUCTURE-INSTANCE, or BUILT-IN-INSTANCE (see file user-instances.lisp
  as an example of their use to save space over standard instances).


-- Trent Lange
   e-mail:  lange@cs.ucla.edu

