emacs.d/clones/www.sbcl.org/sbcl-internals/Compiler-Transformations.html
2023-01-18 20:30:47 +01:00

123 lines
5.8 KiB
HTML

<html lang="en">
<head>
<title>Compiler Transformations - SBCL Internals</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="SBCL Internals">
<meta name="generator" content="makeinfo 4.11">
<link title="Top" rel="start" href="index.html#Top">
<link rel="up" href="Slot_002dValue.html#Slot_002dValue" title="Slot-Value">
<link rel="prev" href="Basic-Implementation.html#Basic-Implementation" title="Basic Implementation">
<link rel="next" href="MOP-Optimizations.html#MOP-Optimizations" title="MOP Optimizations">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
<!--
This manual is part of the SBCL software system. See the `README'
file for more information.
This manual is in the public domain and is provided with
absolutely no warranty. See the `COPYING' and `CREDITS' files for
more information.
-->
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
pre.display { font-family:inherit }
pre.format { font-family:inherit }
pre.smalldisplay { font-family:inherit; font-size:smaller }
pre.smallformat { font-family:inherit; font-size:smaller }
pre.smallexample { font-size:smaller }
pre.smalllisp { font-size:smaller }
span.sc { font-variant:small-caps }
span.roman { font-family:serif; font-weight:normal; }
span.sansserif { font-family:sans-serif; font-weight:normal; }
--></style>
</head>
<body>
<div class="node">
<p>
<a name="Compiler-Transformations"></a>
Next:&nbsp;<a rel="next" accesskey="n" href="MOP-Optimizations.html#MOP-Optimizations">MOP Optimizations</a>,
Previous:&nbsp;<a rel="previous" accesskey="p" href="Basic-Implementation.html#Basic-Implementation">Basic Implementation</a>,
Up:&nbsp;<a rel="up" accesskey="u" href="Slot_002dValue.html#Slot_002dValue">Slot-Value</a>
<hr>
</div>
<!-- node-name, next, previous, up -->
<h3 class="section">7.2 Compiler Transformations</h3>
<p>The compiler can assist in optimizing calls to <code>slot-value</code>: 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).
<h4 class="subsection">7.2.1 Within Methods</h4>
<p><a name="index-permutation-vector-12"></a>
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 <dfn>permutation vectors</dfn>.
<p>(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.)
<p>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).
<p>Subsequent redefinitions of classes or of methods on
<code>slot-value-using-class</code> cause an invalid index to be written into
the permutation vector, and the call falls back to a full call to
<code>slot-value</code>.
<p>If the conditions for (structure or) permutation vector slot access
optimization are not met, optimization of <code>slot-value</code> within
methods falls back to the same as for calls to <code>slot-value</code> outside
of methods, below.
<h4 class="subsection">7.2.2 Outside of Methods</h4>
<p><a name="index-load_002dtime_002dvalue-13"></a>
A call to <code>slot-value</code> with a compile-time constant slot
<var>name</var> argument is compiled into a call to a generic function
named <code>(sb-pcl::slot-accessor :global </code><var>name</var><code> sb-pcl::reader)</code>,
together with code providing load-time assurance (via
<code>load-time-value</code>) 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
<a href="Accessor-Discriminating-Functions.html#Accessor-Discriminating-Functions">Accessor Discriminating Functions</a>.
<p>(FIXME: how does this get invalidated if we later add methods on
<code>slot-value-using-class</code>? Hm, maybe it isn't. I think this is
probably a bug, and that adding methods to <code>slot-value-using-class</code>
needs to invalidate accessor caches. Bah, humbug. Test code in
<a href="ex_003abuggycache.html#ex_003abuggycache">ex:buggycache</a>, and note that I think that the analogous case
involving adding or removing methods from
<code>compute-applicable-methods</code> is handled correctly by
<code>update-all-c-a-m-gf-info</code>.)
<div class="float">
<a name="ex_003abuggycache"></a>
<pre class="example"> (defclass foo () ((a :initform 0)))
(defun foo (x) (slot-value x 'a))
(foo (make-instance 'foo)) ; =&gt; 0
(defmethod slot-value-using-class :after
((class std-class) (object foo)
(slotd standard-effective-slot-definition))
(print "hi"))
(foo (make-instance 'foo)) ; =&gt; 0, no print
(defclass bar (foo) ((a :initform 1)))
(foo (make-instance 'bar)) ; =&gt; 1 and prints "hi"
(foo (make-instance 'foo)) ; =&gt; 0, no print
</pre>
<p><strong class="float-caption">Example 7.3</strong></p></div>
</body></html>