Browse Source

finished draft of select instruction, merged in the intro root stack

Jeremy Siek 9 years ago
parent
commit
80b96c0011
1 changed files with 147 additions and 93 deletions
  1. 147 93
      book.tex

+ 147 - 93
book.tex

@@ -4027,7 +4027,7 @@ and then return the address of the newly allocated chunk of memory.
 \label{sec:code-generation-gc}
 \label{sec:code-generation-gc}
 
 
 The introduction of garbage collection has a non-trivial impact on our
 The introduction of garbage collection has a non-trivial impact on our
-compiler passes. We introduce 3 new compiler passes and make
+compiler passes. We introduce two new compiler passes and make
 non-trivial changes to \code{flatten} and \code{select-instructions}.
 non-trivial changes to \code{flatten} and \code{select-instructions}.
 The following program will serve as our running example.  It creates
 The following program will serve as our running example.  It creates
 two tuples, one nested inside the other. Both tuples have length
 two tuples, one nested inside the other. Both tuples have length
@@ -4046,11 +4046,11 @@ forms for vectors. Here is the definition of $C_2$, for the output of
 \[
 \[
 \begin{array}{lcl}
 \begin{array}{lcl}
 \Exp &::=& \ldots \mid (\key{vector}\, \Exp^{+}) \\
 \Exp &::=& \ldots \mid (\key{vector}\, \Exp^{+}) \\
-   &\mid & (\key{vector-ref}\, \Arg\, \Int) \mid (\key{vector-set!}\,\Arg\,\Int\,\Arg)
+   &\mid & (\key{vector-ref}\, \Arg\, \Int) \\
+   &\mid & (\key{vector-set!}\,\Arg\,\Int\,\Arg)
 \end{array}
 \end{array}
 \]
 \]
-
-The \code{flatten} pass should treat the new forms much like the other
+The \code{flatten} pass should treat these new forms much like the other
 kinds of expressions. The output on our running example is shown in
 kinds of expressions. The output on our running example is shown in
 Figure~\ref{fig:flatten-gc}.
 Figure~\ref{fig:flatten-gc}.
 
 
@@ -4105,12 +4105,14 @@ their type.
 
 
 For the output of this pass, we add the following forms to $C_2$ and
 For the output of this pass, we add the following forms to $C_2$ and
 remove the \key{vector} form.
 remove the \key{vector} form.
+\marginpar{\tiny I don't like the collection-needed form.
+  Would it make sense to instead expose the free-ptr here?\\--Jeremy}
 \[
 \[
 \begin{array}{lcl}
 \begin{array}{lcl}
-\Exp  &::=& \ldots \mid (\key{collection-needed?}\, \Int) 
-      \mid (\key{allocate}\, \Int \, \Type) \\
-\Stmt &::=& \ldots \mid (\key{initialize}\,\Int\,\Int) 
-    \mid (\key{collect}\, \Int)  \\
+\Exp  &::=& \ldots \mid (\key{allocate}\, \Int \, \Type) \\
+\Stmt &::=& \ldots \mid (\key{initialize}\,\Int\,\Int) \\
+    &\mid& (\key{collect}\, \Int)  \\
+    &\mid & (\key{if}\;(\key{collection-needed?}\, \Int)\;\Stmt^{*}\,\Stmt^{*}) \\
 C_2 & ::= & (\key{program}\, ((\Var . \Type)^{*}) \,\Stmt^{+})
 C_2 & ::= & (\key{program}\, ((\Var . \Type)^{*}) \,\Stmt^{+})
 \end{array}
 \end{array}
 \]
 \]
@@ -4195,84 +4197,132 @@ a root and it is live at that point.
 \end{figure}
 \end{figure}
 
 
 
 
-\subsection{Introduce Root Stack (New)}
-\label{sec:shadow-stack}
+\subsection{Select Instructions}
+\label{sec:select-instructions-gc}
 
 
-The goal of this pass is to generate the code for explicitly
-manipulating the root stack. 
+In this pass we generate the code for explicitly manipulating the root
+stack, lower the forms needed for garbage collection, and also lower
+the \code{vector-ref} and \code{vector-set!} forms.
+We shall thread a pointer to the top of root stack through the program
+in local variables whose names all begin with \code{rootstack}.  
 %
 %
 \marginpar{\tiny I would have prefered that we use a dedicated
 \marginpar{\tiny I would have prefered that we use a dedicated
-  register for the top of the root stack\\--Jeremy}
+  register for the top of the root stack. (to do: next year) \\--Jeremy}
 %
 %
-We shall thread a pointer to the top of root stack through the program
-in local variables whose names all begin with \code{rootstack}.  We
-shall obtain the top of the root stack to begin with from the global
-variable \code{rootstack\_begin}.
-
-Most of the action in this pass occurs in the case for
-\code{call-live-roots}.
+We shall obtain the top of the root stack to begin with from the
+global variable \code{rootstack\_begin}.
 
 
+The translation of the \code{call-live-roots} introduces the code that
+manipulates the root stack.  We push all of the call-live roots onto
+the root stack prior to the call to \code{collect} and we move them
+back afterwards.
+%
+\marginpar{\tiny I would prefer to instead have roots live solely
+on the root stack and in registers, not on the normal stack. Then
+we would only need to push the ones in registers, decreasing
+memory traffic. (to do: next year)\\ --Jeremy}
 \begin{lstlisting}
 \begin{lstlisting}
    (call-live-roots (|$x_0 \ldots x_{n-1}$|) (collect |$\itm{bytes}$|))
    (call-live-roots (|$x_0 \ldots x_{n-1}$|) (collect |$\itm{bytes}$|))
    |$\Longrightarrow$|
    |$\Longrightarrow$|
    (movq (var |$x_0$|) (offset (var rootstack.|$\itm{prev}$|) |$0$|))
    (movq (var |$x_0$|) (offset (var rootstack.|$\itm{prev}$|) |$0$|))
    |$\ldots$|
    |$\ldots$|
    (movq (var |$x_{n-1}$|) (offset (var rootstack.|$\itm{prev}$|) |$8(n-1)$|))
    (movq (var |$x_{n-1}$|) (offset (var rootstack.|$\itm{prev}$|) |$8(n-1)$|))
-   (assign rootstack.|$\itm{new}$| (+ rootstack.|$\itm{prev}$| |$n$|))
-   (collect rootstack.|$\itm{new}$| |$\itm{bytes}$|)
+   (movq rootstack.|$\itm{prev}$| rootstack.|$\itm{new}$|)
+   (addq rootstack.|$\itm{new}$| |$n$|)
+   (movq (var rootstack.|$\itm{new}$|) (reg rdi))
+   (movq (int |$\itm{bytes}$|) (reg rsi))
+   (callq collect)
    (movq (offset (var rootstack.|$\itm{prev}$|) |$0$|) (var |$x_0$|))
    (movq (offset (var rootstack.|$\itm{prev}$|) |$0$|) (var |$x_0$|))
    |$\ldots$|
    |$\ldots$|
    (movq (offset (var rootstack.|$\itm{prev}$|) |$8(n-1)$|) (var |$x_{n-1}$|))
    (movq (offset (var rootstack.|$\itm{prev}$|) |$8(n-1)$|) (var |$x_{n-1}$|))
 \end{lstlisting}
 \end{lstlisting}
 
 
-We extend $C_2$ yet again with form for refering to global variables
-and we change the \code{collect} form for invoking the garbage
-collector, adding a parameter for the top of the root stack.  The
-\key{call-live-roots} form is no longer needed in the output of this
-pass.
-\[
-\begin{array}{lcl}
-\Exp  &::=& \ldots \mid (\key{global-value}\, \itm{name}) \\
-\Stmt &::=& \ldots \mid (\key{collect}\, \Arg \,\Int) 
-\end{array}
-\]
-
-Figure~\ref{fig:introduce-rootstack-output} shows the output of the
-\code{introduce-rootstack} pass on the running example.
-
-\begin{figure}[tbp]
+%% We extend $C_2$ yet again with form for refering to global variables
+%% and we change the \code{collect} form for invoking the garbage
+%% collector, adding a parameter for the top of the root stack.  The
+%% \key{call-live-roots} form is no longer needed in the output of this
+%% pass.
+%% \[
+%% \begin{array}{lcl}
+%% \Exp  &::=& \ldots \mid (\key{global-value}\, \itm{name}) \\
+%% \Stmt &::=& \ldots \mid (\key{collect}\, \Arg \,\Int) 
+%% \end{array}
+%% \]
+
+%% Figure~\ref{fig:introduce-rootstack-output} shows the output of the
+%% \code{introduce-rootstack} pass on the running example.
+
+%% \begin{figure}[tbp]
+%% \begin{lstlisting}
+%%    (program (t.1 t.2 t.3 t.4 void.1 void.2
+%%               rootstack.1 rootstack.2 rootstack.3)
+%%      (initialize 10000 10000)
+%%      ~(assign rootstack.3 (global-value rootstack_begin))~
+%%      (if (collection-needed? 16)
+%%        (~(assign rootstack.2 (+ rootstack.3 0))
+%%         (collect rootstack.2 16)~)
+%%        ())
+%%      (assign t.1 (allocate 1 (Vector Integer)))
+%%      (assign void.1 (vector-set! t.1 0 42))
+%%      (if (collection-needed? 16)
+%%        (~(movq (var t.1) (offset (var rootstack.3) 0))
+%%         (assign rootstack.1 (+ rootstack.3 8))
+%%         (collect rootstack.1 16)
+%%         (movq (offset (var rootstack.3) 0) (var t.1))~)
+%%        ())
+%%      (assign t.2 (allocate 1 (Vector (Vector Integer))))
+%%      (assign void.2 (vector-set! t.2 0 t.1))
+%%      (assign t.3 (vector-ref t.2 0))
+%%      (assign t.4 (vector-ref t.3 0))
+%%      (return t.4))
+%% \end{lstlisting}
+%% \caption{Output of the \code{introduce-rootstack} pass.}
+%% \label{fig:introduce-rootstack-output}
+%% \end{figure}
+
+\noindent We simply translate \code{initialize} into a call to the
+function in \code{runtime.c}.
 \begin{lstlisting}
 \begin{lstlisting}
-   (program (t.1 t.2 t.3 t.4 void.1 void.2
-             rootstack.1 rootstack.2 rootstack.3)
-     (initialize 10000 10000)
-     ~(assign rootstack.3 (global-value rootstack_begin))~
-     (if (collection-needed? 16)
-       (~(assign rootstack.2 (+ rootstack.3 0))
-        (collect rootstack.2 16)~)
-       ())
-     (assign t.1 (allocate 1 (Vector Integer)))
-     (assign void.1 (vector-set! t.1 0 42))
-     (if (collection-needed? 16)
-       (~(movq (var t.1) (offset (var rootstack.3) 0))
-        (assign rootstack.1 (+ rootstack.3 8))
-        (collect rootstack.1 16)
-        (movq (offset (var rootstack.3) 0) (var t.1))~)
-       ())
-     (assign t.2 (allocate 1 (Vector (Vector Integer))))
-     (assign void.2 (vector-set! t.2 0 t.1))
-     (assign t.3 (vector-ref t.2 0))
-     (assign t.4 (vector-ref t.3 0))
-     (return t.4))
+   (initialize |$\itm{rootlen}\;\itm{heaplen}$|)
+   |$\Longrightarrow$|
+   (movq (int |$\itm{rootlen}$|) (reg rdi))
+   (movq (int |$\itm{heaplen}$|) (reg rsi))
+   (callq initialize)
+\end{lstlisting}
+%
+We translate the special \code{collection-needed?} predicate into code
+that compares the \code{free\_ptr} to the \code{fromspace\_end}.
+%
+\marginpar{\tiny To improve the code generation here, we should
+ extend the 'if' form to all the relational operators.
+(to do: this week)\\--Jeremy}
+%
+\begin{lstlisting}
+   (if (collection-needed? |$\itm{bytes}$|) |$\itm{thn}$| |$\itm{els}$|)
+   |$\Longrightarrow$|
+   (movq (global-value free_ptr) (var end-data.1))
+   (addq (int |$\itm{bytes}$|) (var end-data.1))
+   (cmpq (var end-data.1) (global-value fromspace_end))
+   (setl (byte-reg al))
+   (movzbq (byte-reg al) (var lt.1))
+   (if (eq? (int 0) (var lt.1))
+       |$\itm{els}$|
+       |$\itm{thn}$|)
 \end{lstlisting}
 \end{lstlisting}
-\caption{Output of the \code{introduce-rootstack} pass.}
-\label{fig:introduce-rootstack-output}
-\end{figure}
-
 
 
-\subsection{Select Instructions}
-\label{sec:select-instructions-gc}
+The \code{vector-ref} and \code{vector-set!} forms translate into
+\code{movq} instructions with the appropriate \code{offset}.
+\begin{lstlisting}
+(assign |$\itm{lhs}$| (vector-ref |$\itm{vec}$| |$n$|))
+|$\Longrightarrow$|
+(movq (offset |$\itm{vec}'$| |$n$|) |$\itm{lhs}$|)
 
 
-UNDER CONSTRUCTION
+(assign |$\itm{lhs}$| (vector-set! |$\itm{vec}$| |$n$| |$\itm{arg}$|))
+|$\Longrightarrow$|
+(movq |$\itm{arg}'$| (offset |$\itm{vec}'$| |$n$|))
+\end{lstlisting}
+The $\itm{vec}'$ and $\itm{arg}'$ are obtained by recursively
+processing $\itm{vec}$ and $\itm{arg}$.
 
 
 The $x86_2$ language differs from $x86_1$ just in the addition of the
 The $x86_2$ language differs from $x86_1$ just in the addition of the
 form for global variables and a form for adding an offset to an
 form for global variables and a form for adding an offset to an
@@ -4285,55 +4335,59 @@ address.
 x86_2 &::= & (\key{program} \;\itm{info} \; \Instr^{+})
 x86_2 &::= & (\key{program} \;\itm{info} \; \Instr^{+})
 \end{array}
 \end{array}
 \]
 \]
-
-
-Figure~\ref{fig:select-instr-output-gc}
+Figure~\ref{fig:select-instr-output-gc} shows the output of the
+\code{select-instructions} pass on the running example.
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
-\begin{lstlisting}
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
    (program (t.1 t.2 t.3 t.4 void.1 void.2
    (program (t.1 t.2 t.3 t.4 void.1 void.2
-             rootstack.1 rootstack.2 rootstack.3 lt1465
-             end-data1464 lt1463 end-data1462)
-     (movq (int 10000) (reg rdi))
+              rootstack.1 rootstack.2 rootstack.3 lt1465
+              end-data1464 lt.1 end-data.1)
+     ~(movq (int 10000) (reg rdi))
      (movq (int 10000) (reg rsi))
      (movq (int 10000) (reg rsi))
-     (callq initialize)
+     (callq initialize)~
      (movq (global-value rootstack_begin) (var rootstack.3))
      (movq (global-value rootstack_begin) (var rootstack.3))
-     (movq (global-value free_ptr) (var end-data1462))
-     (addq (int 16) (var end-data1462))
-     (cmpq (var end-data1462) (global-value fromspace_end))
+     ~(movq (global-value free_ptr) (var end-data.1))
+     (addq (int 16) (var end-data.1))
+     (cmpq (var end-data.1) (global-value fromspace_end))
      (setl (byte-reg al))
      (setl (byte-reg al))
-     (movzbq (byte-reg al) (var lt1463))
-     (if (eq? (int 0) (var lt1463))
+     (movzbq (byte-reg al) (var lt.1))~
+     (if ~(eq? (int 0) (var lt.1))~
        ()
        ()
        ((movq (var rootstack.3) (var rootstack.2))
        ((movq (var rootstack.3) (var rootstack.2))
         (addq (int 0) (var rootstack.2))
         (addq (int 0) (var rootstack.2))
-        (movq (var rootstack.2) (reg rdi))
+        ~(movq (var rootstack.2) (reg rdi))
         (movq (int 16) (reg rsi))
         (movq (int 16) (reg rsi))
-        (callq collect)))
-     (movq (global-value free_ptr) (var t.1))
+        (callq collect)~))
+
+     ~(movq (global-value free_ptr) (var t.1))
      (addq (int 16) (global-value free_ptr))
      (addq (int 16) (global-value free_ptr))
-     (movq (int 32) (offset (var t.1) 0))
-     (movq (int 42) (offset (var t.1) 8))
-     (movq (global-value free_ptr) (var end-data1464))
+     (movq (int 32) (offset (var t.1) 0))~
+
+     ~(movq (int 42) (offset (var t.1) 8))~
+
+     ~(movq (global-value free_ptr) (var end-data1464))
      (addq (int 16) (var end-data1464))
      (addq (int 16) (var end-data1464))
      (cmpq (var end-data1464) (global-value fromspace_end))
      (cmpq (var end-data1464) (global-value fromspace_end))
      (setl (byte-reg al))
      (setl (byte-reg al))
-     (movzbq (byte-reg al) (var lt1465))
-     (if (eq? (int 0) (var lt1465))
+     (movzbq (byte-reg al) (var lt1465))~
+     (if ~(eq? (int 0) (var lt1465))~
        ()
        ()
        ((movq (var t.1) (offset (var rootstack.3) 0))
        ((movq (var t.1) (offset (var rootstack.3) 0))
         (movq (var rootstack.3) (var rootstack.1))
         (movq (var rootstack.3) (var rootstack.1))
         (addq (int 8) (var rootstack.1))
         (addq (int 8) (var rootstack.1))
-        (movq (var rootstack.1) (reg rdi))
+        ~(movq (var rootstack.1) (reg rdi))
         (movq (int 16) (reg rsi))
         (movq (int 16) (reg rsi))
-        (callq collect)
+        (callq collect)~
         (movq (offset (var rootstack.3) 0) (var t.1))))
         (movq (offset (var rootstack.3) 0) (var t.1))))
-     (movq (global-value free_ptr) (var t.2))
+     ~(movq (global-value free_ptr) (var t.2))
      (addq (int 16) (global-value free_ptr))
      (addq (int 16) (global-value free_ptr))
-     (movq (int 160) (offset (var t.2) 0))
-     (movq (var t.1) (offset (var t.2) 8))
+     (movq (int 160) (offset (var t.2) 0))~
+
+     ~(movq (var t.1) (offset (var t.2) 8))
      (movq (offset (var t.2) 8) (var t.3))
      (movq (offset (var t.2) 8) (var t.3))
-     (movq (offset (var t.3) 8) (var t.4))
+     (movq (offset (var t.3) 8) (var t.4))~
+
      (movq (var t.4) (reg rax)))
      (movq (var t.4) (reg rax)))
 \end{lstlisting}
 \end{lstlisting}
 \caption{Output of the \code{select-instructions} pass.}
 \caption{Output of the \code{select-instructions} pass.}