소스 검색

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

Jeremy Siek 9 년 전
부모
커밋
80b96c0011
1개의 변경된 파일147개의 추가작업 그리고 93개의 파일을 삭제
  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}
 
 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}.
 The following program will serve as our running example.  It creates
 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}
 \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}
 \]
-
-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
 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
 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}
-\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^{+})
 \end{array}
 \]
@@ -4195,84 +4197,132 @@ a root and it is live at that point.
 \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
-  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}
    (call-live-roots (|$x_0 \ldots x_{n-1}$|) (collect |$\itm{bytes}$|))
    |$\Longrightarrow$|
    (movq (var |$x_0$|) (offset (var rootstack.|$\itm{prev}$|) |$0$|))
    |$\ldots$|
    (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$|))
    |$\ldots$|
    (movq (offset (var rootstack.|$\itm{prev}$|) |$8(n-1)$|) (var |$x_{n-1}$|))
 \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}
-   (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}
-\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
 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^{+})
 \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{lstlisting}
+\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
    (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))
-     (callq initialize)
+     (callq initialize)~
      (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))
-     (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))
         (addq (int 0) (var rootstack.2))
-        (movq (var rootstack.2) (reg rdi))
+        ~(movq (var rootstack.2) (reg rdi))
         (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))
-     (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))
      (cmpq (var end-data1464) (global-value fromspace_end))
      (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 rootstack.3) (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))
-        (callq collect)
+        (callq collect)~
         (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))
-     (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.3) 8) (var t.4))
+     (movq (offset (var t.3) 8) (var t.4))~
+
      (movq (var t.4) (reg rax)))
 \end{lstlisting}
 \caption{Output of the \code{select-instructions} pass.}