|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object | +--soot.shimple.internal.ShimpleBodyBuilder
This class does the real high-level work. It takes a Jimple body or Jimple/Shimple hybrid body and produces pure Shimple.
The work is done in two main steps:
This class can also translate out of Shimple by producing an equivalent Jimple body with all Phi nodes removed.
Note that this is an internal class, understanding it should not be necessary from a user point-of-view and relying on it directly is not recommended.
ShimpleBody
,
Efficiently
Computing Static Single Assignment Form and the Control Dependence
GraphField Summary | |
protected int[] |
assignmentCounters
|
protected ShimpleBody |
body
|
protected BlockGraph |
cfg
|
protected DominatorTree |
dt
|
protected GuaranteedDefs |
gd
An analysis class that allows us to verify that a variable is guaranteed to be defined at program point P. |
protected java.util.Stack[] |
namingStacks
|
protected java.util.Map |
newLocals
Maps new name Strings to Locals. |
protected java.util.Map |
newLocalsToOldLocal
Maps renamed Locals to original Locals. |
protected java.util.List |
origLocals
A fixed list of all original Locals. |
protected java.util.Map |
unitToBlock
|
Constructor Summary | |
ShimpleBodyBuilder(ShimpleBody body,
boolean hasPhiNodes)
Transforms the provided body to pure SSA form. |
Method Summary | |
static boolean |
doEliminatePhiNodes(ShimpleBody body)
Eliminate Phi nodes in block by naively replacing them with shimple assignment statements in the control flow predecessors. |
boolean |
dominates(Unit champ,
Unit challenger)
Returns true if champ dominates challenger. |
static void |
eliminatePhiNodes(ShimpleBody body)
Remove Phi nodes from current body, high probablity this destroys SSA form. |
protected Local |
fetchNewLocal(Local local,
java.lang.Integer subscript)
Clever convenience function to fetch or create new Local's given a Local and the desired subscript. |
static java.util.List |
getDefBoxesFromBlock(Block block)
Convenience function that really ought to be implemented in soot.toolkits.graph.Block. |
static java.util.Map |
getUnitToBlockMap(BlockGraph blocks)
Convenience function that maps units to blocks. |
static java.util.List |
getUseBoxesFromBlock(Block block)
Convenience function that really ought to be implemented in soot.toolkits.graph.Block |
protected int |
indexOfLocal(Value local)
Convenient function that maps new Locals to the originating Local, and finds the appropriate array index into the naming structures. |
void |
insertTrivialPhiNodes()
Phi node Insertion Algorithm from Cytron et al 91, P24-5, implemented in various bits and pieces by the next functions. |
protected boolean |
isLocalDefinedOnEntry(Local local,
Block block)
Function that allows us to weed out special cases where we do not require Phi nodes. |
static java.lang.String |
makeUniqueLocalName(java.lang.String dupName,
java.util.Set localNames)
Given a set of Strings, return a new name for dupName that is not currently in the set. |
static void |
makeUniqueLocalNames(ShimpleBody body)
Make sure the locals in the given body all have unique String names. |
void |
prependTrivialPhiNode(Local local,
Block frontierBlock)
Inserts a trivial Phi node with the appropriate number of arguments. |
void |
renameLocals()
Variable Renaming Algorithm from Cytron et al 91, P26-8, implemented in various bits and pieces by the next functions. |
void |
renameLocalsSearch(Block block)
Driven by renameLocals(). |
void |
trimExceptionalPhiNodes()
Exceptional Phi nodes have a huge number of arguments and control flow predecessors by default. |
void |
trimPhiNode(PhiExpr phiExpr)
|
Methods inherited from class java.lang.Object |
clone,
equals,
finalize,
getClass,
hashCode,
notify,
notifyAll,
toString,
wait,
wait,
wait |
Field Detail |
protected ShimpleBody body
protected DominatorTree dt
protected BlockGraph cfg
protected java.util.List origLocals
protected GuaranteedDefs gd
protected java.util.Map newLocals
protected java.util.Map newLocalsToOldLocal
protected int[] assignmentCounters
protected java.util.Stack[] namingStacks
protected java.util.Map unitToBlock
Constructor Detail |
public ShimpleBodyBuilder(ShimpleBody body, boolean hasPhiNodes)
Method Detail |
public void insertTrivialPhiNodes()
For each definition of variable V, find the iterated dominance frontier. Each block in the iterated dominance frontier is prepended with a trivial Phi node.
We found out the hard way that this isn't the ideal solution for Jimple because a lot of redundant Phi nodes get inserted probably due to the fact that the algorithm assumes all variables have an initial definition on entry.
While this assumption does not produce incorrect results, it produces hopelessly complicated and ineffectual code.
Our quick solution was to ensure that a variable was defined along all paths to the block where we were considering insertion of a Phi node. If the variable was not defined along at least one path (isLocalDefinedOnEntry()), then certainly a Phi node was superfluous and meaningless. Our GuaranteedDefs flow analysis provided us with the necessary information.
Better and more efficient alternatives suggest themselves. We later found this formulation from IBM's Jikes RVM:
Special Java case: if node N dominates all defs of V, then N does not need a Phi node for V.
public void prependTrivialPhiNode(Local local, Block frontierBlock)
protected boolean isLocalDefinedOnEntry(Local local, Block block)
Temporary implementation, with much room for improvement.
public void renameLocals()
call search(entry) search(X): for each statement A in X do if A is an ordinary assignment for each variable V used do replace use of V by use of V_i where i = Top(S(V)) done fi for each V in LHS(A) do i <- C(V) replace V by new V_i in LHS(A) push i onto S(V) C(V) <- i+1 done done (end of first loop) for each Y in succ(X) do j <- whichPred(Y, X) for each Phi-function F in Y do replace the j-th operand V in RHS(F) by V_i with i = TOP(S(V)) done done (end of second loop) for each Y in Children(X) do call search(Y) done (end of third loop) for each assignment A in X do for each V in oldLHS(A) do pop(S(V)) done done (end of fourth loop) end
public void renameLocalsSearch(Block block)
protected Local fetchNewLocal(Local local, java.lang.Integer subscript)
protected int indexOfLocal(Value local)
public void trimExceptionalPhiNodes()
public void trimPhiNode(PhiExpr phiExpr)
trimExceptionalPhiNodes()
public boolean dominates(Unit champ, Unit challenger)
public static void eliminatePhiNodes(ShimpleBody body)
Dead code elimination + register aggregation are performed as recommended by Cytron. The Aggregator looks like it could use some improvements.
ShimpleOptions
public static boolean doEliminatePhiNodes(ShimpleBody body)
public static void makeUniqueLocalNames(ShimpleBody body)
public static java.lang.String makeUniqueLocalName(java.lang.String dupName, java.util.Set localNames)
public static java.util.List getDefBoxesFromBlock(Block block)
public static java.util.List getUseBoxesFromBlock(Block block)
public static java.util.Map getUnitToBlockMap(BlockGraph blocks)
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |