Next: , Previous: Basic Implementation, Up: Slot-Value


7.2 Compiler Transformations

The compiler can assist in optimizing calls to slot-value: in particular, and despite the highly-dynamic nature of CLOS, compile-time knowledge of the name of the slot being accessed permits precomputation of much of the access (along with a branch to the slow path in case the parameters of the access change between compile-time and run-time).

7.2.1 Within Methods

If the object being accessed is a required parameter to the method, where the parameter variable is unmodified in the method body, and the slot name is a compile-time constant, then fast slot access can be supported through permutation vectors.

(FIXME: what about the metaclasses of the object? Does it have to be standard-class, or can it be funcallable-standard-class? Surely structure-class objects could be completely optimized if the class definition and slot name are both known at compile-time.)

Permutation vectors are built up and maintained to associate a compile-time index associated with a slot name with an index into the slot vector for a class of objects. The permutation vector applicable to a given method call (FIXME: or effective method? set of classes? something else?) is passed to the method body, and slots are accessed by looking up the index to the slot vector in the permutation vector, then looking up the value from the slot vector. (FIXME: a diagram would help, if I understood this bit well enough to draw a diagram).

Subsequent redefinitions of classes or of methods on slot-value-using-class cause an invalid index to be written into the permutation vector, and the call falls back to a full call to slot-value.

If the conditions for (structure or) permutation vector slot access optimization are not met, optimization of slot-value within methods falls back to the same as for calls to slot-value outside of methods, below.

7.2.2 Outside of Methods

A call to slot-value with a compile-time constant slot name argument is compiled into a call to a generic function named (sb-pcl::slot-accessor :global name sb-pcl::reader), together with code providing load-time assurance (via load-time-value) that the generic function is bound and has a suitable accessor method. This generic function then benefits from the same optimizations as ordinary accessors, described in Accessor Discriminating Functions.

(FIXME: how does this get invalidated if we later add methods on slot-value-using-class? Hm, maybe it isn't. I think this is probably a bug, and that adding methods to slot-value-using-class needs to invalidate accessor caches. Bah, humbug. Test code in ex:buggycache, and note that I think that the analogous case involving adding or removing methods from compute-applicable-methods is handled correctly by update-all-c-a-m-gf-info.)

     (defclass foo () ((a :initform 0)))
     (defun foo (x) (slot-value x 'a))
     (foo (make-instance 'foo)) ; => 0
     (defmethod slot-value-using-class :after
       ((class std-class) (object foo)
        (slotd standard-effective-slot-definition))
       (print "hi"))
     (foo (make-instance 'foo)) ; => 0, no print
     (defclass bar (foo) ((a :initform 1)))
     (foo (make-instance 'bar)) ; => 1  and prints "hi"
     (foo (make-instance 'foo)) ; => 0, no print

Example 7.3