|
@@ -10491,14 +10491,31 @@ Figure~\ref{fig:Lvec-concrete-syntax} defines the concrete syntax for
|
|
|
operator, and 4) obtaining the number of elements (the length) of a
|
|
|
tuple.}
|
|
|
%
|
|
|
-The program in Figure~\ref{fig:vector-eg} shows an example use of
|
|
|
-tuples. It creates a 3-tuple \code{t} and a 1-tuple that is stored at
|
|
|
-index $2$ of the 3-tuple, demonstrating that tuples are first-class
|
|
|
-values. The element at index $1$ of \code{t} is
|
|
|
-\racket{\code{\#t}}\python{True}, so the ``then'' branch of the
|
|
|
-\key{if} is taken. The element at index $0$ of \code{t} is \code{40},
|
|
|
-to which we add \code{2}, the element at index $0$ of the 1-tuple. So
|
|
|
-the result of the program is \code{42}.
|
|
|
+The program below shows an example use of tuples. It creates a 3-tuple
|
|
|
+\code{t} and a 1-tuple that is stored at index $2$ of the 3-tuple,
|
|
|
+demonstrating that tuples are first-class values. The element at
|
|
|
+index $1$ of \code{t} is \racket{\code{\#t}}\python{\code{True}}, so the
|
|
|
+``then'' branch of the \key{if} is taken. The element at index $0$ of
|
|
|
+\code{t} is \code{40}, to which we add \code{2}, the element at index
|
|
|
+$0$ of the 1-tuple. So the result of the program is \code{42}.
|
|
|
+%
|
|
|
+{\if\edition\racketEd
|
|
|
+\begin{lstlisting}
|
|
|
+ (let ([t (vector 40 #t (vector 2))])
|
|
|
+ (if (vector-ref t 1)
|
|
|
+ (+ (vector-ref t 0)
|
|
|
+ (vector-ref (vector-ref t 2) 0))
|
|
|
+ 44))
|
|
|
+\end{lstlisting}
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+\begin{lstlisting}
|
|
|
+t = 40, True, (2,)
|
|
|
+print( t[0] + t[2][0] if t[1] else 44 )
|
|
|
+\end{lstlisting}
|
|
|
+\fi}
|
|
|
+
|
|
|
+
|
|
|
|
|
|
\begin{figure}[tbp]
|
|
|
\centering
|
|
@@ -10551,26 +10568,6 @@ the result of the program is \code{42}.
|
|
|
\label{fig:Lvec-concrete-syntax}
|
|
|
\end{figure}
|
|
|
|
|
|
-\begin{figure}[tbp]
|
|
|
-{\if\edition\racketEd
|
|
|
-\begin{lstlisting}
|
|
|
- (let ([t (vector 40 #t (vector 2))])
|
|
|
- (if (vector-ref t 1)
|
|
|
- (+ (vector-ref t 0)
|
|
|
- (vector-ref (vector-ref t 2) 0))
|
|
|
- 44))
|
|
|
-\end{lstlisting}
|
|
|
-\fi}
|
|
|
-{\if\edition\pythonEd
|
|
|
-\begin{lstlisting}
|
|
|
-t = 40, True, (2,)
|
|
|
-print( t[0] + t[2][0] if t[1] else 44 )
|
|
|
-\end{lstlisting}
|
|
|
-\fi}
|
|
|
-\caption{Example program that creates tuples and reads from them.}
|
|
|
-\label{fig:vector-eg}
|
|
|
-\end{figure}
|
|
|
-
|
|
|
\begin{figure}[tp]
|
|
|
\centering
|
|
|
\fbox{
|
|
@@ -10715,7 +10712,7 @@ print( t[0] )
|
|
|
\fi}
|
|
|
%
|
|
|
From the perspective of programmer-observable behavior, tuples live
|
|
|
-forever. Of course, if they really lived forever, then many programs
|
|
|
+forever. Of course, if they really lived forever then many programs
|
|
|
would run out of memory. The language's runtime system must therefore
|
|
|
perform automatic garbage collection.
|
|
|
|
|
@@ -11066,11 +11063,11 @@ are several ways to accomplish this.
|
|
|
guide the
|
|
|
collector~\citep{Appel:1989aa,Goldberg:1991aa,Diwan:1992aa}.
|
|
|
\end{enumerate}
|
|
|
-Dynamically typed languages, such as Lisp, need to tag objects
|
|
|
-anyways, so option 1 is a natural choice for those languages.
|
|
|
-However, \LangVec{} is a statically typed language, so it would be
|
|
|
-unfortunate to require tags on every object, especially small and
|
|
|
-pervasive objects like integers and Booleans. Option 3 is the
|
|
|
+Dynamically typed languages, such as \racket{Racket}\python{Python},
|
|
|
+need to tag objects anyways, so option 1 is a natural choice for those
|
|
|
+languages. However, \LangVec{} is a statically typed language, so it
|
|
|
+would be unfortunate to require tags on every object, especially small
|
|
|
+and pervasive objects like integers and Booleans. Option 3 is the
|
|
|
best-performing choice for statically typed languages, but comes with
|
|
|
a relatively high implementation complexity. To keep this chapter
|
|
|
within a 2-week time budget, we recommend a combination of options 1
|
|
@@ -11211,7 +11208,7 @@ significant changes to \code{select\_instructions},
|
|
|
following program will serve as our running example. It creates two
|
|
|
tuples, one nested inside the other. Both tuples have length one. The
|
|
|
program accesses the element in the inner tuple tuple.
|
|
|
-% tests/s2_17.rkt
|
|
|
+% tests/vectors_test_17.rkt
|
|
|
{\if\edition\racketEd
|
|
|
\begin{lstlisting}
|
|
|
(vector-ref (vector-ref (vector (vector 42)) 0) 0)
|
|
@@ -11219,7 +11216,7 @@ program accesses the element in the inner tuple tuple.
|
|
|
\fi}
|
|
|
{\if\edition\pythonEd
|
|
|
\begin{lstlisting}
|
|
|
-((42,),)[0][0]
|
|
|
+print( ((42,),)[0][0] )
|
|
|
\end{lstlisting}
|
|
|
\fi}
|
|
|
|
|
@@ -11239,45 +11236,65 @@ to wrap \code{HasType} around each AST node that it generates.
|
|
|
\section{Expose Allocation}
|
|
|
\label{sec:expose-allocation}
|
|
|
|
|
|
-\python{UNDER CONSTRUCTION}
|
|
|
-
|
|
|
-The pass \code{expose-allocation} lowers the \code{vector} creation
|
|
|
-form into a conditional call to the collector followed by the
|
|
|
-allocation. We choose to place the \code{expose-allocation} pass
|
|
|
+The pass \code{expose\_allocation} lowers tuple creation
|
|
|
+into a conditional call to the collector followed by the
|
|
|
+allocation. We choose to place the \code{expose\_allocation} pass
|
|
|
before \code{remove\_complex\_operands} because the code generated by
|
|
|
-\code{expose-allocation} contains complex operands. We also place
|
|
|
-\code{expose-allocation} before \code{explicate\_control} because
|
|
|
-\code{expose-allocation} introduces new variables using \code{let},
|
|
|
-but \code{let} is gone after \code{explicate\_control}.
|
|
|
-
|
|
|
-The output of \code{expose-allocation} is a language \LangAlloc{} that
|
|
|
-extends \LangVec{} with the three new forms that we use in the translation
|
|
|
-of the \code{vector} form.
|
|
|
+\code{expose\_allocation} contains complex operands.
|
|
|
+
|
|
|
+The output of \code{expose\_allocation} is a language \LangAlloc{}
|
|
|
+that extends \LangVec{} with new forms that we use in the translation
|
|
|
+of tuple creation.
|
|
|
+%
|
|
|
+{\if\edition\racketEd
|
|
|
\[
|
|
|
\begin{array}{lcl}
|
|
|
\Exp &::=& \cdots
|
|
|
\MID (\key{collect} \,\itm{int})
|
|
|
\MID (\key{allocate} \,\itm{int}\,\itm{type})
|
|
|
- \MID (\key{global-value} \,\itm{name})
|
|
|
+ \MID (\key{global-value} \,\itm{name})
|
|
|
\end{array}
|
|
|
\]
|
|
|
-The $(\key{collect}\,n)$ form runs the garbage collector, requesting
|
|
|
-$n$ bytes. It will become a call to the \code{collect} function in
|
|
|
-\code{runtime.c} in \code{select\_instructions}. The
|
|
|
-$(\key{allocate}\,n\,T)$ form creates an tuple of $n$ elements.
|
|
|
-\index{subject}{allocate}
|
|
|
-The $T$ parameter is the type of the tuple: \code{(Vector $\Type_1 \ldots
|
|
|
- \Type_n$)} where $\Type_i$ is the type of the $i$th element in the
|
|
|
-tuple. The $(\key{global-value}\,\itm{name})$ form reads the value of
|
|
|
-a global variable, such as \code{free\_ptr}.
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+\[
|
|
|
+\begin{array}{lcl}
|
|
|
+ \Exp &::=& \cdots\\
|
|
|
+ &\MID& \key{collect}(\itm{int})
|
|
|
+ \MID \key{allocate}(\itm{int},\itm{type})
|
|
|
+ \MID \key{global\_value}(\itm{name}) \\
|
|
|
+ &\MID& \key{begin:} ~ \Stmt^{*} ~ \Exp
|
|
|
+\end{array}
|
|
|
+\]
|
|
|
+
|
|
|
+\fi}
|
|
|
+
|
|
|
+The \CCOLLECT{n} form runs the garbage collector, requesting $n$
|
|
|
+bytes. During instruction selection, it will become a call to the
|
|
|
+\code{collect} function in \code{runtime.c}. The \CALLOCATE{n}{T}
|
|
|
+form creates a tuple with space for $n$ elements, but they are not
|
|
|
+initialized. \index{subject}{allocate} The $T$ parameter is the type
|
|
|
+of the tuple:
|
|
|
+%
|
|
|
+\VECTY{\racket{$\Type_1 \ldots \Type_n$}\python{$\Type_1, \ldots, \Type_n$}}
|
|
|
+%
|
|
|
+where $\Type_i$ is the type of the $i$th element in the tuple. The
|
|
|
+\CGLOBAL{\itm{name}} form reads the value of a global variable, such
|
|
|
+as \code{free\_ptr}.
|
|
|
+%
|
|
|
+\python{The \code{begin} form is an expression that executes a
|
|
|
+ sequence of statements and then produces the value of the expression
|
|
|
+ at the end.}
|
|
|
|
|
|
-In the following, we show the transformation for the \code{vector}
|
|
|
-form into 1) a sequence of let-bindings for the initializing
|
|
|
+The following shows the transformation of tuple creation into 1) a
|
|
|
+sequence of temporary variables bindings for the initializing
|
|
|
expressions, 2) a conditional call to \code{collect}, 3) a call to
|
|
|
-\code{allocate}, and 4) the initialization of the vector. In the
|
|
|
-following, \itm{len} refers to the length of the vector and
|
|
|
+\code{allocate}, and 4) the initialization of the vector. The
|
|
|
+\itm{len} placeholder refers to the length of the vector and
|
|
|
\itm{bytes} is how many total bytes need to be allocated for the
|
|
|
vector, which is 8 for the tag plus \itm{len} times 8.
|
|
|
+%
|
|
|
+{\if\edition\racketEd
|
|
|
\begin{lstlisting}
|
|
|
(has-type (vector |$e_0 \ldots e_{n-1}$|) |\itm{type}|)
|
|
|
|$\Longrightarrow$|
|
|
@@ -11291,18 +11308,38 @@ vector, which is 8 for the tag plus \itm{len} times 8.
|
|
|
(let ([_ (vector-set! |$v$| |$n-1$| |$x_{n-1}$|)])
|
|
|
|$v$|) ... )))) ...)
|
|
|
\end{lstlisting}
|
|
|
-In the above, we suppressed all of the \code{has-type} forms in the
|
|
|
-output for the sake of readability. The placement of the initializing
|
|
|
-expressions $e_0,\ldots,e_{n-1}$ prior to the \code{allocate} and the
|
|
|
-sequence of \code{vector-set!} is important, as those expressions may
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+\begin{lstlisting}
|
|
|
+ (|$e_0$|, |$\ldots$|, |$e_{n-1}$|)
|
|
|
+|$\Longrightarrow$|
|
|
|
+ begin:
|
|
|
+ |$x_0$| = |$e_0$|
|
|
|
+ |$\vdots$|
|
|
|
+ |$x_{n-1}$| = |$e_{n-1}$|
|
|
|
+ if global_value(free_ptr) + |\itm{bytes}| < global_value(fromspace_end):
|
|
|
+ 0
|
|
|
+ else:
|
|
|
+ collect(|\itm{bytes}|)
|
|
|
+ |$v$| = allocate(|\itm{len}|, |\itm{type}|)
|
|
|
+ |$v$|[0] = |$x_0$|
|
|
|
+ |$\vdots$|
|
|
|
+ |$v$|[|$n-1$|] = |$x_{n-1}$|
|
|
|
+ |$v$|
|
|
|
+\end{lstlisting}
|
|
|
+\fi}
|
|
|
+%
|
|
|
+The placement of the initializing expressions $e_0,\ldots,e_{n-1}$
|
|
|
+prior to the \code{allocate} is important, as those expressions may
|
|
|
trigger garbage collection and we cannot have an allocated but
|
|
|
uninitialized tuple on the heap during a collection.
|
|
|
|
|
|
Figure~\ref{fig:expose-alloc-output} shows the output of the
|
|
|
-\code{expose-allocation} pass on our running example.
|
|
|
+\code{expose\_allocation} pass on our running example.
|
|
|
|
|
|
\begin{figure}[tbp]
|
|
|
-% tests/s2_17.rkt
|
|
|
+ % tests/s2_17.rkt
|
|
|
+{\if\edition\racketEd
|
|
|
\begin{lstlisting}
|
|
|
(vector-ref
|
|
|
(vector-ref
|
|
@@ -11316,11 +11353,7 @@ Figure~\ref{fig:expose-alloc-output} shows the output of the
|
|
|
)])
|
|
|
(let ([alloc7971 (allocate 1 (Vector Integer))])
|
|
|
(let ([initret7973 (vector-set! alloc7971 0 vecinit7972)])
|
|
|
- alloc7971)
|
|
|
- )
|
|
|
- )
|
|
|
- )
|
|
|
- ])
|
|
|
+ alloc7971))))])
|
|
|
(let ([collectret7978
|
|
|
(if (< (+ (global-value free_ptr) 16)
|
|
|
(global-value fromspace_end))
|
|
@@ -11329,15 +11362,41 @@ Figure~\ref{fig:expose-alloc-output} shows the output of the
|
|
|
)])
|
|
|
(let ([alloc7975 (allocate 1 (Vector (Vector Integer)))])
|
|
|
(let ([initret7977 (vector-set! alloc7975 0 vecinit7976)])
|
|
|
- alloc7975)
|
|
|
- )
|
|
|
- )
|
|
|
- )
|
|
|
+ alloc7975))))
|
|
|
0)
|
|
|
0)
|
|
|
\end{lstlisting}
|
|
|
-\caption{Output of the \code{expose-allocation} pass, minus
|
|
|
- all of the \code{has-type} forms.}
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+\begin{lstlisting}
|
|
|
+print( |$T_1$|[0][0] )
|
|
|
+\end{lstlisting}
|
|
|
+where $T_1$ is
|
|
|
+\begin{lstlisting}
|
|
|
+ begin:
|
|
|
+ tmp.1 = |$T_2$|
|
|
|
+ if global_value(free_ptr) + 16 < global_value(fromspace_end):
|
|
|
+ 0
|
|
|
+ else:
|
|
|
+ collect(16)
|
|
|
+ tmp.2 = allocate(1, tuple[tuple[int]])
|
|
|
+ tmp.2[0] = tmp.1
|
|
|
+ tmp.2
|
|
|
+\end{lstlisting}
|
|
|
+and $T_2$ is
|
|
|
+\begin{lstlisting}
|
|
|
+ begin:
|
|
|
+ tmp.3 = 42
|
|
|
+ if global_value(free_ptr) + 16 < global_value(fromspace_end):
|
|
|
+ 0
|
|
|
+ else:
|
|
|
+ collect(16)
|
|
|
+ tmp.4 = allocate(1, tuple[int])
|
|
|
+ tmp.4[0] = tmp.3
|
|
|
+ tmp.4
|
|
|
+\end{lstlisting}
|
|
|
+\fi}
|
|
|
+\caption{Output of the \code{expose\_allocation} pass.}
|
|
|
\label{fig:expose-alloc-output}
|
|
|
\end{figure}
|
|
|
|
|
@@ -11345,8 +11404,20 @@ Figure~\ref{fig:expose-alloc-output} shows the output of the
|
|
|
\section{Remove Complex Operands}
|
|
|
\label{sec:remove-complex-opera-Lvec}
|
|
|
|
|
|
-The new forms \code{collect}, \code{allocate}, and \code{global-value}
|
|
|
-should all be treated as complex operands.
|
|
|
+{\if\edition\racketEd
|
|
|
+%
|
|
|
+The forms \code{collect}, \code{allocate}, and \code{global\_value}
|
|
|
+should be treated as complex operands.
|
|
|
+%
|
|
|
+\fi}
|
|
|
+%
|
|
|
+{\if\edition\pythonEd
|
|
|
+%
|
|
|
+The expressions \code{Allocate}, \code{GlobalValue}, \code{Begin}, and
|
|
|
+\code{Subscript} should be treated as complex operands. The
|
|
|
+sub-expressions of \code{Subscript} must be atomic.
|
|
|
+%
|
|
|
+\fi}
|
|
|
%% A new case for
|
|
|
%% \code{HasType} is needed and the case for \code{Prim} needs to be
|
|
|
%% handled carefully to prevent the \code{Prim} node from being separated
|
|
@@ -11360,21 +11431,53 @@ pass, which is \LangVec{} in monadic normal form.
|
|
|
\fbox{
|
|
|
\begin{minipage}{0.96\textwidth}
|
|
|
\small
|
|
|
+{\if\edition\racketEd
|
|
|
\[
|
|
|
\begin{array}{rcl}
|
|
|
- \Atm &::=& \gray{ \INT{\Int} \MID \VAR{\Var} \MID \BOOL{\itm{bool}} }
|
|
|
- \MID \VOID{} \\
|
|
|
+ \Atm &::=& \gray{ \INT{\Int} \MID \VAR{\Var} \MID \BOOL{\itm{bool}}
|
|
|
+ \MID \VOID{} } \\
|
|
|
\Exp &::=& \gray{ \Atm \MID \READ{} } \\
|
|
|
&\MID& \gray{ \NEG{\Atm} \MID \ADD{\Atm}{\Atm} } \\
|
|
|
&\MID& \gray{ \LET{\Var}{\Exp}{\Exp} } \\
|
|
|
&\MID& \gray{ \UNIOP{\key{'not}}{\Atm} } \\
|
|
|
&\MID& \gray{ \BINOP{\itm{cmp}}{\Atm}{\Atm} \MID \IF{\Exp}{\Exp}{\Exp} }\\
|
|
|
- &\MID& \LP\key{Collect}~\Int\RP \MID \LP\key{Allocate}~\Int~\Type\RP
|
|
|
- \MID \LP\key{GlobalValue}~\Var\RP\\
|
|
|
+ &\MID& \COLLECT{\Int} \RP \MID \ALLOCATE{\Int}{\Type}
|
|
|
+ \MID \GLOBALVALUE{\Var}\\
|
|
|
% &\MID& \LP\key{HasType}~\Exp~\Type\RP \\
|
|
|
\LangVecANFM{} &::=& \gray{ \PROGRAM{\code{'()}}{\Exp} }
|
|
|
\end{array}
|
|
|
\]
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+\[
|
|
|
+\begin{array}{lcl}
|
|
|
+\itm{binop} &::=& \code{Add()} \MID \code{Sub()} \\
|
|
|
+\itm{boolop} &::=& \code{And()} \MID \code{Or()} \\
|
|
|
+\itm{cmp} &::= & \code{Eq()} \MID \code{NotEq()} \MID \code{Lt()} \MID \code{LtE()} \MID \code{Gt()} \MID \code{GtE()} \MID \code{Is()} \\
|
|
|
+\itm{uniop} &::=& \code{USub()} \MID \code{Not()} \\
|
|
|
+\itm{bool} &::=& \code{True} \MID \code{False} \\
|
|
|
+\Atm &::=& \INT{\Int} \MID \VAR{\Var} \MID \BOOL{\itm{bool}} \\
|
|
|
+\Exp &::=& \Atm \MID \READ{} \MID \\
|
|
|
+ &\MID& \BINOP{\Exp}{\itm{binop}}{\Exp}
|
|
|
+ \MID \UNIOP{\itm{uniop}}{\Exp}\\
|
|
|
+ &\MID& \CMP{\Exp}{\itm{cmp}}{\Exp}
|
|
|
+ \MID \BOOLOP{\itm{boolop}}{\Exp}{\Exp}\\
|
|
|
+ &\MID& \IF{\Exp}{\Exp}{\Exp} \\
|
|
|
+ &\MID& \GET{\Atm}{\Atm} \\
|
|
|
+ &\MID& \LEN{\Exp}\\
|
|
|
+ &\MID& \ALLOCATE{\Int}{\Type}
|
|
|
+ \MID \GLOBALVALUE{\Var}\RP\\
|
|
|
+ &\MID& \BEGIN{\Stmt^{*}}{\Exp} \\
|
|
|
+\Stmt{} &::=& \PRINT{\Exp} \MID \EXPR{\Exp} \\
|
|
|
+ &\MID& \ASSIGN{\VAR{\Var}}{\Exp} \\
|
|
|
+ &\MID& \ASSIGN{\PUT{\Atm}{\Atm}}{\Exp} \\
|
|
|
+ &\MID& \IFSTMT{\Exp}{\Stmt^{+}}{\Stmt^{+}}\\
|
|
|
+ &\MID& \WHILESTMT{\Exp}{\Stmt^{+}}
|
|
|
+ \MID \COLLECT{\Int} \\
|
|
|
+\LangLoopM{} &::=& \PROGRAM{\code{'()}}{\Stmt^{*}}
|
|
|
+\end{array}
|
|
|
+\]
|
|
|
+\fi}
|
|
|
\end{minipage}
|
|
|
}
|
|
|
\caption{\LangVecANF{} is \LangVec{} in monadic normal form.}
|
|
@@ -11390,6 +11493,7 @@ pass, which is \LangVec{} in monadic normal form.
|
|
|
\fbox{
|
|
|
\begin{minipage}{0.96\textwidth}
|
|
|
\small
|
|
|
+{\if\edition\racketEd
|
|
|
\[
|
|
|
\begin{array}{lcl}
|
|
|
\Atm &::=& \gray{ \INT{\Int} \MID \VAR{\Var} \MID \BOOL{\itm{bool}} }\\
|
|
@@ -11409,6 +11513,29 @@ pass, which is \LangVec{} in monadic normal form.
|
|
|
\LangCVecM{} & ::= & \gray{ \CPROGRAM{\itm{info}}{\LP\LP\itm{label}\,\key{.}\,\Tail\RP\ldots\RP} }
|
|
|
\end{array}
|
|
|
\]
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+\[
|
|
|
+\begin{array}{lcl}
|
|
|
+\Atm &::=& \INT{\Int} \MID \VAR{\Var} \MID \BOOL{\itm{bool}} \\
|
|
|
+\Exp &::= & \Atm \MID \READ{} \\
|
|
|
+ &\MID& \BINOP{\Atm}{\itm{binop}}{\Atm}
|
|
|
+ \MID \UNIOP{\itm{uniop}}{\Atm} \\
|
|
|
+ &\MID& \CMP{\Atm}{\itm{cmp}}{\Atm}
|
|
|
+ \MID \BOOLOP{\itm{boolop}}{\Atm}{\Atm} \\
|
|
|
+ &\MID& \GET{\Atm}{\Atm}
|
|
|
+ \MID \ALLOCATE{\Int}{\Type} \MID \GLOBALVALUE{\Var}\RP\\
|
|
|
+ &\MID& \LEN{\Atm} \\
|
|
|
+\Stmt &::=& \PRINT{\Exp} \MID \EXPR{\Exp} \\
|
|
|
+ &\MID& \ASSIGN{\VAR{\Var}}{\Exp}
|
|
|
+ \MID \RETURN{\Exp} \MID \GOTO{\itm{label}} \\
|
|
|
+ &\MID& \IFSTMT{\CMP{\Atm}{\itm{cmp}}{\Atm}}{\LS\GOTO{\itm{label}}\RS}{\LS\GOTO{\itm{label}}\RS} \\
|
|
|
+ &\MID& \COLLECT{\Int} \\
|
|
|
+ &\MID& \ASSIGN{\PUT{\Atm}{\Atm}}{\Atm} \\
|
|
|
+\LangCVecM{} & ::= & \CPROGRAM{\itm{info}}{\LC\itm{label}\,\key{:}\,\Stmt^{*}, \ldots \RC}
|
|
|
+\end{array}
|
|
|
+\]
|
|
|
+\fi}
|
|
|
\end{minipage}
|
|
|
}
|
|
|
\caption{The abstract syntax of \LangCVec{}, extending \LangCIf{}
|
|
@@ -11418,13 +11545,23 @@ pass, which is \LangVec{} in monadic normal form.
|
|
|
|
|
|
The output of \code{explicate\_control} is a program in the
|
|
|
intermediate language \LangCVec{}, whose abstract syntax is defined in
|
|
|
-Figure~\ref{fig:c2-syntax}. (The concrete syntax is defined in
|
|
|
-Figure~\ref{fig:c2-concrete-syntax} of the Appendix.) The new forms
|
|
|
-of \LangCVec{} include the \key{allocate}, \key{vector-ref}, and
|
|
|
-\key{vector-set!}, and \key{global-value} expressions and the
|
|
|
-\code{collect} statement. The \code{explicate\_control} pass can treat
|
|
|
-these new forms much like the other expression forms that we've
|
|
|
-already encoutered.
|
|
|
+Figure~\ref{fig:c2-syntax}. \racket{(The concrete syntax is defined
|
|
|
+ in Figure~\ref{fig:c2-concrete-syntax} of the Appendix.)} The new
|
|
|
+expressions of \LangCVec{} include \key{allocate},
|
|
|
+%
|
|
|
+\racket{\key{vector-ref}, and \key{vector-set!},}
|
|
|
+%
|
|
|
+\python{accessing tuple elements,}
|
|
|
+%
|
|
|
+and \key{global\_value}.
|
|
|
+%
|
|
|
+\python{It also includes the \code{collect} statment and
|
|
|
+assignment to a tuple element.}
|
|
|
+%
|
|
|
+\racket{It also includes the new \code{collect} statement.}
|
|
|
+%
|
|
|
+The \code{explicate\_control} pass can treat these new forms much like
|
|
|
+the other forms that we've already encoutered.
|
|
|
|
|
|
|
|
|
\section{Select Instructions and the \LangXGlobal{} Language}
|
|
@@ -11440,29 +11577,50 @@ already encoutered.
|
|
|
|
|
|
In this pass we generate x86 code for most of the new operations that
|
|
|
were needed to compile tuples, including \code{Allocate},
|
|
|
-\code{Collect}, \code{vector-ref}, \code{vector-set!}, and
|
|
|
-\code{void}. We compile \code{GlobalValue} to \code{Global} because
|
|
|
-the later has a different concrete syntax (see
|
|
|
-Figures~\ref{fig:x86-2-concrete} and \ref{fig:x86-2}).
|
|
|
-\index{subject}{x86}
|
|
|
+\code{Collect}, and accessing tuple elements.
|
|
|
+%
|
|
|
+We compile \code{GlobalValue} to \code{Global} because the later has a
|
|
|
+different concrete syntax (see Figures~\ref{fig:x86-2-concrete} and
|
|
|
+\ref{fig:x86-2}). \index{subject}{x86}
|
|
|
|
|
|
-The \code{vector-ref} and \code{vector-set!} forms translate into
|
|
|
-\code{movq} instructions. (The plus one in the offset is to get past
|
|
|
-the tag at the beginning of the tuple representation.)
|
|
|
+The tuple read and write forms translate into \code{movq}
|
|
|
+instructions. (The plus one in the offset is to get past the tag at
|
|
|
+the beginning of the tuple representation.)
|
|
|
+%
|
|
|
+\begin{center}
|
|
|
+\begin{minipage}{\textwidth}
|
|
|
+{\if\edition\racketEd
|
|
|
\begin{lstlisting}
|
|
|
-|$\itm{lhs}$| = (vector-ref |$\itm{vec}$| |$n$|);
|
|
|
+|$\itm{lhs}$| = (vector-ref |$\itm{tup}$| |$n$|);
|
|
|
|$\Longrightarrow$|
|
|
|
-movq |$\itm{vec}'$|, %r11
|
|
|
+movq |$\itm{tup}'$|, %r11
|
|
|
movq |$8(n+1)$|(%r11), |$\itm{lhs'}$|
|
|
|
|
|
|
-|$\itm{lhs}$| = (vector-set! |$\itm{vec}$| |$n$| |$\itm{arg}$|);
|
|
|
+|$\itm{lhs}$| = (vector-set! |$\itm{tup}$| |$n$| |$\itm{rhs}$|);
|
|
|
|$\Longrightarrow$|
|
|
|
-movq |$\itm{vec}'$|, %r11
|
|
|
-movq |$\itm{arg}'$|, |$8(n+1)$|(%r11)
|
|
|
+movq |$\itm{tup}'$|, %r11
|
|
|
+movq |$\itm{rhs}'$|, |$8(n+1)$|(%r11)
|
|
|
movq $0, |$\itm{lhs'}$|
|
|
|
\end{lstlisting}
|
|
|
-The $\itm{lhs}'$, $\itm{vec}'$, and $\itm{arg}'$ are obtained by
|
|
|
-translating $\itm{vec}$ and $\itm{arg}$ to x86. The move of $\itm{vec}'$ to
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+\begin{lstlisting}
|
|
|
+|$\itm{lhs}$| = |$\itm{tup}$|[|$n$|]
|
|
|
+|$\Longrightarrow$|
|
|
|
+movq |$\itm{tup}'$|, %r11
|
|
|
+movq |$8(n+1)$|(%r11), |$\itm{lhs'}$|
|
|
|
+
|
|
|
+|$\itm{tup}$|[|$n$|] = |$\itm{rhs}$|
|
|
|
+|$\Longrightarrow$|
|
|
|
+movq |$\itm{tup}'$|, %r11
|
|
|
+movq |$\itm{rhs}'$|, |$8(n+1)$|(%r11)
|
|
|
+movq $0, |$\itm{lhs'}$|
|
|
|
+\end{lstlisting}
|
|
|
+\fi}
|
|
|
+\end{minipage}
|
|
|
+\end{center}
|
|
|
+The $\itm{lhs}'$, $\itm{tup}'$, and $\itm{rhs}'$ are obtained by
|
|
|
+translating $\itm{tup}$ and $\itm{rhs}$ to x86. The move of $\itm{tup}'$ to
|
|
|
register \code{r11} ensures that offset expression
|
|
|
\code{$-8(n+1)$(\%r11)} contains a register operand. This requires
|
|
|
removing \code{r11} from consideration by the register allocating.
|
|
@@ -11470,22 +11628,22 @@ removing \code{r11} from consideration by the register allocating.
|
|
|
Why not use \code{rax} instead of \code{r11}? Suppose we instead used
|
|
|
\code{rax}. Then the generated code for \code{vector-set!} would be
|
|
|
\begin{lstlisting}
|
|
|
-movq |$\itm{vec}'$|, %rax
|
|
|
-movq |$\itm{arg}'$|, |$8(n+1)$|(%rax)
|
|
|
+movq |$\itm{tup}'$|, %rax
|
|
|
+movq |$\itm{rhs}'$|, |$8(n+1)$|(%rax)
|
|
|
movq $0, |$\itm{lhs}'$|
|
|
|
\end{lstlisting}
|
|
|
-Next, suppose that $\itm{arg}'$ ends up as a stack location, so
|
|
|
+Next, suppose that $\itm{rhs}'$ ends up as a stack location, so
|
|
|
\code{patch\_instructions} would insert a move through \code{rax}
|
|
|
as follows.
|
|
|
\begin{lstlisting}
|
|
|
-movq |$\itm{vec}'$|, %rax
|
|
|
-movq |$\itm{arg}'$|, %rax
|
|
|
+movq |$\itm{tup}'$|, %rax
|
|
|
+movq |$\itm{rhs}'$|, %rax
|
|
|
movq %rax, |$8(n+1)$|(%rax)
|
|
|
movq $0, |$\itm{lhs}'$|
|
|
|
\end{lstlisting}
|
|
|
But the above sequence of instructions does not work because we're
|
|
|
-trying to use \code{rax} for two different values ($\itm{vec}'$ and
|
|
|
-$\itm{arg}'$) at the same time!
|
|
|
+trying to use \code{rax} for two different values ($\itm{tup}'$ and
|
|
|
+$\itm{rhs}'$) at the same time!
|
|
|
|
|
|
We compile the \code{allocate} form to operations on the
|
|
|
\code{free\_ptr}, as shown below. The address in the \code{free\_ptr}
|
|
@@ -11499,6 +11657,7 @@ tag is organized. We recommend using the Racket operations
|
|
|
\code{bitwise-ior} and \code{arithmetic-shift} to compute the tag
|
|
|
during compilation. The type annotation in the \code{vector} form is
|
|
|
used to determine the pointer mask region of the tag.
|
|
|
+{\if\edition\racketEd
|
|
|
\begin{lstlisting}
|
|
|
|$\itm{lhs}$| = (allocate |$\itm{len}$| (Vector |$\itm{type} \ldots$|));
|
|
|
|$\Longrightarrow$|
|
|
@@ -11507,13 +11666,24 @@ used to determine the pointer mask region of the tag.
|
|
|
movq $|$\itm{tag}$|, 0(%r11)
|
|
|
movq %r11, |$\itm{lhs}'$|
|
|
|
\end{lstlisting}
|
|
|
-
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+\begin{lstlisting}
|
|
|
+ |$\itm{lhs}$| = allocate(|$\itm{len}$|, tuple[|$\itm{type}, \ldots$]|);
|
|
|
+ |$\Longrightarrow$|
|
|
|
+ movq free_ptr(%rip), %r11
|
|
|
+ addq |$8(\itm{len}+1)$|, free_ptr(%rip)
|
|
|
+ movq $|$\itm{tag}$|, 0(%r11)
|
|
|
+ movq %r11, |$\itm{lhs}'$|
|
|
|
+\end{lstlisting}
|
|
|
+\fi}
|
|
|
The \code{collect} form is compiled to a call to the \code{collect}
|
|
|
function in the runtime. The arguments to \code{collect} are 1) the
|
|
|
top of the root stack and 2) the number of bytes that need to be
|
|
|
allocated. We use another dedicated register, \code{r15}, to
|
|
|
store the pointer to the top of the root stack. So \code{r15} is not
|
|
|
available for use by the register allocator.
|
|
|
+{\if\edition\racketEd
|
|
|
\begin{lstlisting}
|
|
|
(collect |$\itm{bytes}$|)
|
|
|
|$\Longrightarrow$|
|
|
@@ -11521,7 +11691,16 @@ available for use by the register allocator.
|
|
|
movq $|\itm{bytes}|, %rsi
|
|
|
callq collect
|
|
|
\end{lstlisting}
|
|
|
-
|
|
|
+\fi}
|
|
|
+{\if\edition\pythonEd
|
|
|
+\begin{lstlisting}
|
|
|
+ collect(|$\itm{bytes}$|)
|
|
|
+ |$\Longrightarrow$|
|
|
|
+ movq %r15, %rdi
|
|
|
+ movq $|\itm{bytes}|, %rsi
|
|
|
+ callq collect
|
|
|
+\end{lstlisting}
|
|
|
+\fi}
|
|
|
|
|
|
|
|
|
\begin{figure}[tp]
|
|
@@ -11548,7 +11727,7 @@ available for use by the register allocator.
|
|
|
\begin{array}{lcl}
|
|
|
\Arg &::=& \gray{ \INT{\Int} \MID \REG{\Reg} \MID \DEREF{\Reg}{\Int}
|
|
|
\MID \BYTEREG{\Reg}} \\
|
|
|
- &\MID& (\key{Global}~\Var) \\
|
|
|
+ &\MID& \GLOBAL{\Var} \\
|
|
|
\LangXGlobalM{} &::= & \gray{ \XPROGRAM{\itm{info}}{\LP\LP\itm{label} \,\key{.}\, \Block \RP\ldots\RP} }
|
|
|
\end{array}
|
|
|
\]
|
|
@@ -11707,6 +11886,7 @@ accomplishes this task. The garbage collector tests each root to see
|
|
|
if it is null prior to dereferencing it.
|
|
|
|
|
|
\begin{figure}[htbp]
|
|
|
+ % TODO: Python Version -Jeremy
|
|
|
\begin{minipage}[t]{0.5\textwidth}
|
|
|
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
|
|
|
block35:
|
|
@@ -11790,7 +11970,7 @@ conclusion:
|
|
|
retq
|
|
|
\end{lstlisting}
|
|
|
\end{minipage}
|
|
|
-\caption{Output of the \code{print\_x86} pass.}
|
|
|
+\caption{Output of the \code{prelude\_and\_conclusion} pass.}
|
|
|
\label{fig:print-x86-output-gc}
|
|
|
\end{figure}
|
|
|
|
|
@@ -11832,6 +12012,7 @@ conclusion:
|
|
|
Figure~\ref{fig:Lvec-passes} gives an overview of all the passes needed
|
|
|
for the compilation of \LangVec{}.
|
|
|
|
|
|
+{\if\edition\racketEd
|
|
|
\section{Challenge: Simple Structures}
|
|
|
\label{sec:simple-structures}
|
|
|
\index{subject}{struct}
|
|
@@ -11916,7 +12097,6 @@ mark. The following example uses \code{set-point-x!} to change the
|
|
|
structures and test your compiler.
|
|
|
\end{exercise}
|
|
|
|
|
|
-
|
|
|
\section{Challenge: Arrays}
|
|
|
\label{sec:arrays}
|
|
|
|
|
@@ -12319,6 +12499,8 @@ from the set.
|
|
|
passes your test suite.
|
|
|
\end{exercise}
|
|
|
|
|
|
+\fi}
|
|
|
+
|
|
|
% Further Reading
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
@@ -15543,11 +15725,13 @@ for the compilation of \LangDyn{}.
|
|
|
\fi % racketEd
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
+{\if\edition\pythonEd
|
|
|
\chapter{Objects}
|
|
|
\label{ch:Robject}
|
|
|
\index{subject}{objects}
|
|
|
\index{subject}{classes}
|
|
|
|
|
|
+\fi}
|
|
|
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
@@ -16488,8 +16672,8 @@ the target type is \code{PVector}. Instead of using
|
|
|
|$\Rightarrow$|
|
|
|
(let |$\itm{tmp}$| |$e'$|
|
|
|
(if (eq? (tag-of-any |$\itm{tmp}$| 2))
|
|
|
- (let |$\itm{vec}$| (value-of |$\itm{tmp}$| (PVector Any |$\ldots$| Any))
|
|
|
- (if (eq? (proxy-vector-length |$\itm{vec}$|) |$n$|) |$\itm{vec}$| (exit)))
|
|
|
+ (let |$\itm{tup}$| (value-of |$\itm{tmp}$| (PVector Any |$\ldots$| Any))
|
|
|
+ (if (eq? (proxy-vector-length |$\itm{tup}$|) |$n$|) |$\itm{tup}$| (exit)))
|
|
|
(exit)))
|
|
|
\end{lstlisting}
|
|
|
|