Author: Hakan Ardo <[email protected]>
Branch: extradoc
Changeset: r3647:8acff13ed641
Date: 2011-06-12 11:42 +0200
http://bitbucket.org/pypy/extradoc/changeset/8acff13ed641/
Log: describe virtuals
diff --git a/talk/iwtc11/paper.tex b/talk/iwtc11/paper.tex
--- a/talk/iwtc11/paper.tex
+++ b/talk/iwtc11/paper.tex
@@ -469,23 +469,72 @@
jump($l_1$, $p_{0}$, $p_{9}$, $i_3$, $i_8$)
\end{lstlisting}
-\subsection{Virtualization}
-Using escape analysis we can XXX
+\subsection{Allocation removal}
+By using escape analysis it is possible to identify objects that are
+allocated within the loop but never escapes it. That is the object are
+short lived and no references to them exists outside the loop. This
+is performed by processing the operation from top to bottom and
+optimistically removing every \lstinline{new} operation. Later on if
+it is discovered that a reference to the object escapes the loop, the
+\lstinline{new} operation is inserted at this point. All operations
+(\lstinline{get} and \lstinline{set}) on the removed objects are also
+removed and the optimizer needs to keep track of the value of all
+attributes of the object.
-Let $\tilde J$ be all variables in $J$ not representing virtuals (in the
-same order). Extend it with all non virtual fields, $H_i$, of the
-removed virtuals,
+Consider again the original unoptimized trace of
+Figure~\label{fig:peeled-trace}. Line 10 contains the first
+allocation. It is removed and $p_5$ is marked as virtual. This means
+that it refers to an virtual object that was not yet
+(and might never be) allocated. Line 12 sets the \lstinline{intval}
+attribute of $p_5$. This operation is also removed and the optimizer
+registers that the attribute \lstinline{intval} of $p_5$ is $i_4$.
+
+When the optimizer reaches line 13 it needs to construct the
+arguments for the \lstinline{jump} operation, which contains the virtual
+reference $p_5$. This can be achieved by exploding $p_5$ into it's
+attributes. In this case there is only one attribute and it's value is
+$i_4$, which means the $p_5$ is replaced with $i_4$ in the jump
+arguments.
+
+In the general case, each virtual in the jump arguments is exploded into a
+vector of variables containing the values of all it's attributes. If some
+of the attributes are themselves virtuals they are recursively exploded
+to make the vector contain only non virtual variables. Some care has
+to be taken to always place the attributes in the same order when
+performing this explosion. Notation becomes somewhat simpler if also every non
+virtual variable of the jump arguments is exploded into a vector. This will
+be a vector containing the original variable only. To summarize, for
+every variable, $J_k$, of the original jump arguments, $J$, let
\begin{equation}
- \hat J = \left(\tilde J_1, \tilde J_2, \cdots, \tilde J_{|\tilde J|},
- H_1, H_2, \cdots, H_{|H}\right)
+ \tilde J^{\left(k\right)} = \left\{
+ \begin{array}{ll}
+ \left(J_k\right) & \text{if $J_k$ is not virtual} \\
+ H^{\left(k\right)} & \text{if $J_k$ is virtual}
+ \end{array}
+ \right.
+ ,
\end{equation}
-and let
+where $H^{\left(k\right)}$ is a vector containing all non virtual
+attributes of $J_k$. The arguments of the optimized \lstinline{jump}
+operation are constructed as the concatenation all the $\tilde
J^{\left(k\right)}$ vectors,
+\begin{equation}
+ \hat J = \left(
+ \begin{array}{cccc}
+ \tilde J^{\left(1\right)} & \tilde J^{\left(2\right)} & \cdots &
+ \tilde J^{\left(|J|\right)} \\
+ \end{array}
+ \right)
+ .
+\end{equation}
+and the arguments of the \lstinline{jump} operation of the second
+operation, $K$, are replaced by inlining $\hat J$,
\begin{equation}
\hat K = \left(m\left(\hat J_1\right), m\left(\hat J_1\right),
\cdots, m\left(\hat J_{|\hat J|}\right)\right)
.
\end{equation}
-
+In the optimized trace $I$ is replaced by $\hat I$ and $K$ by $\hat
+K$. The trace from Figure~\ref{fig:unopt-trace} will be optimized into
\begin{lstlisting}[mathescape,numbers =
right,basicstyle=\setstretch{1.05}\ttfamily\scriptsize]
$l_0$($p_{0}$, $p_{1}$):
@@ -497,17 +546,29 @@
# inside BoxedInteger.add__int
$i_{3}$ = get($p_{0}$, intval)
$i_{4}$ = int_add($i_{2}$, $i_{3}$)
-jump($l_1$, $p_{0}$, $i_3$, $i_4$)
+ # inside BoxedInteger.__init__
+jump($l_1$, $p_{0}$, $i_{4}$)
-$l_1$($p_{0}$, $p_{5}$, $i_3$, $i_4$):
+$l_1$($p_{0}$, $i_{4}$):
# inside f: y = y.add(step)
# inside BoxedInteger.add
+ guard_class($p_{0}$, BoxedInteger)
# inside BoxedInteger.add__int
- $i_{8}$ = int_add($i_{4}$, $i_{3}$)
-jump($l_1$, $p_{0}$, $i_3$, $i_8$)
+ $i_{7}$ = get($p_{0}$, intval)
+ $i_{8}$ = int_add($i_{4}$, $i_{7}$)
+ # inside BoxedInteger.__init__
+jump($l_1$, $p_{0}$, $i_8$)
\end{lstlisting}
-And we're down to a single integer addition!
+Note that virtuals are only exploded into their attributes when
+constructing the arguments of the jump of the first iteration. This
+explosion can't be repeated when constructing the arguments of the
+jump of the second iteration as it has to mach the first. This means
+the objects that was passed as pointers (non virtuals) from the first
+iteration to the second also has to be passed as pointers from the
+second iteration to the third. If one of these objects are virtual
+at the end of the second iteration they need to be allocated right
+before the jump.
\section{Benchmarks}
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit