[jboss-cvs] javassist SVN: r605 - in trunk: src/main/javassist/bytecode/analysis and 2 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Mon Jan 23 12:46:36 EST 2012
Author: chiba
Date: 2012-01-23 12:46:35 -0500 (Mon, 23 Jan 2012)
New Revision: 605
Modified:
trunk/Readme.html
trunk/src/main/javassist/bytecode/analysis/ControlFlow.java
trunk/src/main/javassist/bytecode/stackmap/BasicBlock.java
trunk/src/test/test/javassist/bytecode/analysis/DomTreePrinter.java
Log:
revising ControlFlow.dominatorTree().
Modified: trunk/Readme.html
===================================================================
--- trunk/Readme.html 2011-12-07 05:32:18 UTC (rev 604)
+++ trunk/Readme.html 2012-01-23 17:46:35 UTC (rev 605)
@@ -284,6 +284,7 @@
<p>-version 3.16
<ul>
<li>JIRA JASSIST-126, 127, 144, 145, 146
+ <li><code>javassist.bytecode.analysis.ControlFlow</code> was added.
</ul>
<p>-version 3.15 on July 8, 2011
Modified: trunk/src/main/javassist/bytecode/analysis/ControlFlow.java
===================================================================
--- trunk/src/main/javassist/bytecode/analysis/ControlFlow.java 2011-12-07 05:32:18 UTC (rev 604)
+++ trunk/src/main/javassist/bytecode/analysis/ControlFlow.java 2012-01-23 17:46:35 UTC (rev 605)
@@ -91,10 +91,9 @@
/**
* Returns all the basic blocks in the method body.
- * The first element is the root block of the dominator tree.
*/
public Block[] basicBlocks() {
- dominatorTree();
+ dominatorTree2();
return basicBlocks;
}
@@ -114,15 +113,103 @@
}
/**
- * Returns a dominator tree.
+ * Constructs a dominator tree. This method returns an array of
+ * the tree nodes. The first element of the array is the root
+ * of the tree.
+ *
+ * <p> The order of the elements is the same as that
+ * of the elements in the array returned by the <code>basicBlocks</code>
+ * method.
+ * For every array element <code>node</code>, its index in the
+ * array is obtained by <code>node.block().index()</code>.
*
- * @return the root node or null if the method is abstract.
+ * @return an array of the tree nodes, or null if the method is abstract.
+ * @see Node#block()
+ * @see Block#index()
*/
- public Block dominatorTree() {
+ public Node[] dominatorTree() {
int size = basicBlocks.length;
if (size == 0)
return null;
+ Node[] nodes = new Node[size];
+ boolean[] visited = new boolean[size];
+ int[] distance = new int[size];
+ for (int i = 0; i < size; i++) {
+ nodes[i] = new Node(basicBlocks[i]);
+ visited[i] = false;
+ }
+
+ Access access = new Access(nodes) {
+ BasicBlock[] exits(Node n) { return n.block.getExit(); }
+ BasicBlock[] entrances(Node n) { return n.block.entrances; }
+ };
+ nodes[0].makeDepth1stTree(null, visited, 0, distance, access);
+ for (int i = 0; i < size; i++)
+ visited[i] = false;
+
+ while (nodes[0].makeDominatorTree(visited, distance, access))
+ ;
+
+ Node.setChildren(nodes);
+ return nodes;
+ }
+
+ /**
+ * Constructs a post dominator tree. This method returns an array of
+ * the tree nodes. The parent of the root node is null.
+ *
+ * <p>For every array element <code>node</code>, its index in the
+ * array is obtained by <code>node.block().index()</code>.
+ *
+ * @return an array of the tree nodes, or null if the method is abstract.
+ * @see Node#block()
+ * @see Block#index()
+ */
+ public Node[] postDominatorTree() {
+ int size = basicBlocks.length;
+ if (size == 0)
+ return null;
+
+ Node[] nodes = new Node[size];
+ boolean[] visited = new boolean[size];
+ int[] distance = new int[size];
+ for (int i = 0; i < size; i++) {
+ nodes[i] = new Node(basicBlocks[i]);
+ visited[i] = false;
+ }
+
+ Access access = new Access(nodes) {
+ BasicBlock[] exits(Node n) { return n.block.entrances; }
+ BasicBlock[] entrances(Node n) { return n.block.getExit(); }
+ };
+
+ int counter = 0;
+ for (int i = 0; i < size; i++)
+ if (nodes[i].block.exits() == 0)
+ counter = nodes[i].makeDepth1stTree(null, visited, counter, distance, access);
+
+ for (int i = 0; i < size; i++)
+ visited[i] = false;
+
+ boolean changed;
+ do {
+ changed = false;
+ for (int i = 0; i < size; i++)
+ if (nodes[i].block.exits() == 0)
+ if (nodes[i].makeDominatorTree(visited, distance, access))
+ changed = true;
+ } while (changed);
+
+ Node.setChildren(nodes);
+ return nodes;
+ }
+
+ private Block dominatorTree2() {
+ int size = basicBlocks.length;
+ if (size == 0)
+ return null;
+
if (basicBlocks[0].parent == null) {
// a dominator tree has not been constructed.
boolean[] visited = new boolean[size];
@@ -202,16 +289,18 @@
for (int i = 0; i < entrances.length; i++)
sbuf.append(entrances[i].position).append(", ");
- sbuf.append("}, dominator parent{");
- if (parent != null)
- sbuf.append(parent.position);
+ sbuf.append("}");
- sbuf.append("}, children{");
+ sbuf.append("{parent=");
+ sbuf.append(parent == null ? "*" : parent.position());
+ sbuf.append(", children{");
for (int i = 0; i < children.length; i++)
- sbuf.append(children[i].position).append(", ");
- sbuf.append("}");
+ sbuf.append(children[i].position()).append(", ");
+ sbuf.append("}}");
}
+ BasicBlock[] getExit() { return exit; }
+
/**
* Returns the position of this block in the array of
* basic blocks that the <code>basicBlocks</code> method
@@ -356,7 +445,160 @@
}
}
+ static abstract class Access {
+ Node[] all;
+ Access(Node[] nodes) { all = nodes; }
+ Node node(BasicBlock b) { return all[((Block)b).index]; }
+ abstract BasicBlock[] exits(Node n);
+ abstract BasicBlock[] entrances(Node n);
+ }
+
/**
+ * A node of (post) dominator trees.
+ */
+ public static class Node {
+ private Block block;
+ private Node parent;
+ private Node[] children;
+
+ Node(Block b) {
+ block = b;
+ parent = null;
+ }
+
+ /**
+ * Returns a <code>String</code> representation.
+ */
+ public String toString() {
+ StringBuffer sbuf = new StringBuffer();
+ sbuf.append("Node[pos=").append(block().position());
+ sbuf.append(", parent=");
+ sbuf.append(parent == null ? "*" : parent.block().position());
+ sbuf.append(", children{");
+ for (int i = 0; i < children.length; i++)
+ sbuf.append(children[i].block().position()).append(", ");
+
+ sbuf.append("}]");
+ return sbuf.toString();
+ }
+
+ /**
+ * Returns the basic block indicated by this node.
+ */
+ public Block block() { return block; }
+
+ /**
+ * Returns the parent of this node.
+ */
+ public Node parent() { return parent; }
+
+ /**
+ * Returns the number of the children of this node.
+ */
+ public int children() { return children.length; }
+
+ /**
+ * Returns the n-th child of this node.
+ *
+ * @param n an index in the array of children.
+ */
+ public Node child(int n) { return children[n]; }
+
+ /*
+ * After executing this method, distance[] represents the post order of the tree nodes.
+ * It also represents distances from the root; a bigger number represents a shorter
+ * distance. parent is set to its parent in the depth first spanning tree.
+ */
+ int makeDepth1stTree(Node caller, boolean[] visited, int counter, int[] distance, Access access) {
+ int index = block.index;
+ if (visited[index])
+ return counter;
+
+ visited[index] = true;
+ parent = caller;
+ BasicBlock[] exits = access.exits(this);
+ if (exits != null)
+ for (int i = 0; i < exits.length; i++) {
+ Node n = access.node(exits[i]);
+ counter = n.makeDepth1stTree(this, visited, counter, distance, access);
+ }
+
+ distance[index] = counter++;
+ return counter;
+ }
+
+ boolean makeDominatorTree(boolean[] visited, int[] distance, Access access) {
+ int index = block.index;
+ if (visited[index])
+ return false;
+
+ visited[index] = true;
+ boolean changed = false;
+ BasicBlock[] exits = access.exits(this);
+ if (exits != null)
+ for (int i = 0; i < exits.length; i++) {
+ Node n = access.node(exits[i]);
+ if (n.makeDominatorTree(visited, distance, access))
+ changed = true;
+ }
+
+ BasicBlock[] entrances = access.entrances(this);
+ if (entrances != null)
+ for (int i = 0; i < entrances.length; i++) {
+ if (parent != null) {
+ Node n = getAncestor(parent, access.node(entrances[i]), distance);
+ if (n != parent) {
+ parent = n;
+ changed = true;
+ }
+ }
+ }
+
+ return changed;
+ }
+
+ private static Node getAncestor(Node n1, Node n2, int[] distance) {
+ while (n1 != n2) {
+ if (distance[n1.block.index] < distance[n2.block.index])
+ n1 = n1.parent;
+ else
+ n2 = n2.parent;
+
+ if (n1 == null || n2 == null)
+ return null;
+ }
+
+ return n1;
+ }
+
+ private static void setChildren(Node[] all) {
+ int size = all.length;
+ int[] nchildren = new int[size];
+ for (int i = 0; i < size; i++)
+ nchildren[i] = 0;
+
+ for (int i = 0; i < size; i++) {
+ Node p = all[i].parent;
+ if (p != null)
+ nchildren[p.block.index]++;
+ }
+
+ for (int i = 0; i < size; i++)
+ all[i].children = new Node[nchildren[i]];
+
+ for (int i = 0; i < size; i++)
+ nchildren[i] = 0;
+
+ for (int i = 0; i < size; i++) {
+ Node n = all[i];
+ Node p = n.parent;
+ if (p != null)
+ p.children[nchildren[p.block.index]++] = n;
+ }
+ }
+ }
+
+ /**
* Represents a catch clause.
*/
public static class Catcher {
Modified: trunk/src/main/javassist/bytecode/stackmap/BasicBlock.java
===================================================================
--- trunk/src/main/javassist/bytecode/stackmap/BasicBlock.java 2011-12-07 05:32:18 UTC (rev 604)
+++ trunk/src/main/javassist/bytecode/stackmap/BasicBlock.java 2012-01-23 17:46:35 UTC (rev 605)
@@ -79,7 +79,7 @@
.append(", exit{");
if (exit != null) {
for (int i = 0; i < exit.length; i++)
- sbuf.append(exit[i].position).append(", ");
+ sbuf.append(exit[i].position).append(",");
}
sbuf.append("}, {");
Modified: trunk/src/test/test/javassist/bytecode/analysis/DomTreePrinter.java
===================================================================
--- trunk/src/test/test/javassist/bytecode/analysis/DomTreePrinter.java 2011-12-07 05:32:18 UTC (rev 604)
+++ trunk/src/test/test/javassist/bytecode/analysis/DomTreePrinter.java 2012-01-23 17:46:35 UTC (rev 605)
@@ -3,6 +3,7 @@
import javassist.ClassPool;
import javassist.bytecode.analysis.ControlFlow;
import javassist.bytecode.analysis.ControlFlow.Block;
+import javassist.bytecode.analysis.ControlFlow.Node;
public class DomTreePrinter {
public static void main(String[] args) throws Exception {
@@ -11,6 +12,15 @@
Block[] blocks = cf.basicBlocks();
for (int i = 0; i < blocks.length; i++)
System.out.println(i + ": " + blocks[i]);
+
+ Node[] dom = cf.dominatorTree();
+ for (int i = 0; i < dom.length; i++)
+ System.out.println(i + ": " + dom[i]);
+
+ Node[] pdom = cf.postDominatorTree();
+ for (int i = 0; i < pdom.length; i++)
+ System.out.println(i + ": " + pdom[i]);
+
}
public int dummy(int n, int[] array) {
@@ -50,4 +60,19 @@
} while (i < n);
return array[0];
}
+
+ public int dummy4(int n, int[] array) {
+ int i = 0;
+ do {
+ if (array[i] > 0)
+ if (array[i++] > -1)
+ continue;
+ else
+ return 0;
+ array[0]++;
+ array[1]++;
+ } while (i < n);
+ return array[0];
+ }
+
}
More information about the jboss-cvs-commits
mailing list