Java Reference
In-Depth Information
Of course, a redundant Phi function will not be changed. If the w is never modified in the
loop body, the Phi function instruction takes the form
w 2 = [ w 1 w 2 ]
and can be removed as it is apparent that w has not been changed.
Phi functions are tightly bound to state vectors. When a block is processed:
If the block has just a single predecessor, then it may inherit the state vector of that
predecessor; the states are simply copied.
If the block has more than one predecessor, then those states in the vectors that differ
must be merged using Phi functions.
For loop headers we conservatively create Phi functions for all variables, and then
later remove redundant Phi functions.
In block B2 in the code for Factorial (Figure 6.7), I3 and I4 identify the instructions
I3:[I0I8]
I4:[I2I9]
These are Phi function instructions capturing the local variable n and result respectively.
I3 is a Phi function with operands I0 and I8 ; I4 is a Phi function with operands I2 and
I9 .
Control-Flow Graph Construction
The best place to look at the translation process is the constructor NEmitter() in class
NEmitter . For each method, the control-flow graph of HIR is constructed in several steps:
1. The NControlFlowGraph constructor is invoked on the method. This produces the
control-flow graph cfg . In this first step, the JVM code is translated to sequences of
tuples:
(a) Objects of type NBasicBlock represent the basic blocks in the control-flow graph.
The control flow is captured by the links successors in each block. There are
also the links predecessors for analysis.
(b) The JVM code is first translated to a list of tuples, corresponding to the JVM
instructions. Each block stores its sequence of tuples in an ArrayList , tuples .
For example, the blocks of tuples for our Factorial example, computeIter()
are as follows:
B0
B1
0:iconst_1
1:istore_1
B2
2:iload_0
3:iconst_0
4:if_icmple 0 13
B3
7:iload_1
8:iload_0
9:iinc 0 255
12:imul
 
Search WWH ::




Custom Search