mirror of
https://github.com/decatur/j2js-compiler.git
synced 2025-01-18 12:25:42 +01:00
335 lines
8.9 KiB
Java
335 lines
8.9 KiB
Java
/*
|
|
* Copyright 2005 by Wolfgang Kuehn
|
|
* Created on 12.11.2005
|
|
*/
|
|
package com.j2js.cfg;
|
|
|
|
import java.util.Collection;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.LinkedHashSet;
|
|
import java.util.Set;
|
|
|
|
import com.j2js.ASTNodeStack;
|
|
import com.j2js.cfg.transformation.Transformation;
|
|
import com.j2js.dom.Block;
|
|
import com.j2js.dom.Expression;
|
|
import com.j2js.dom.IfStatement;
|
|
|
|
/**
|
|
* @author wolfgang
|
|
*/
|
|
public class Node {
|
|
|
|
public class Reference {
|
|
public Node source;
|
|
public boolean isBackward = false;
|
|
}
|
|
|
|
public static int NON_HEADER = 0;
|
|
public static int REDUCIBLE = 1;
|
|
public static int IRREDUCIBLE = 2;
|
|
|
|
String id;
|
|
|
|
Set<Edge> inEdges = new LinkedHashSet<Edge>();
|
|
Set<Edge> outEdges = new LinkedHashSet<Edge>();
|
|
Graph graph;
|
|
private int currentPc = -1;
|
|
private int initialPc = -1;
|
|
public ASTNodeStack stack = new ASTNodeStack();
|
|
public Block block = new Block();
|
|
public boolean closed = false;
|
|
|
|
protected int preOrderIndex = -1;
|
|
|
|
private Node domParent; // Block that (immediately) dominates this Block
|
|
private Set<Node> domChildren = new HashSet<Node>(); // Blocks that this Block dominates
|
|
|
|
IfStatement ifStmt;
|
|
public Expression switchExpression;
|
|
|
|
public Transformation trans;
|
|
public Collection<Node> jsrCallers = new HashSet<Node>();
|
|
|
|
public boolean isSwitchHeader = false;
|
|
|
|
public Node(Graph theGraph, int pc) {
|
|
this(theGraph);
|
|
setInitialPc(pc);
|
|
}
|
|
|
|
public Node(Graph theGraph) {
|
|
graph = theGraph;
|
|
}
|
|
|
|
public int getComplexity() {
|
|
Node node = this;
|
|
int complexity = 0;
|
|
while (node.trans != null) {
|
|
complexity++;
|
|
node = node.trans.header;
|
|
}
|
|
return complexity;
|
|
}
|
|
|
|
/**
|
|
* @return Returns the pc.
|
|
*/
|
|
public int getCurrentPc() {
|
|
return currentPc;
|
|
}
|
|
/**
|
|
* @param pc The pc to set.
|
|
*/
|
|
public void setCurrentPc(int pc) {
|
|
currentPc = pc;
|
|
}
|
|
|
|
public void close() {
|
|
closed = true;
|
|
}
|
|
|
|
public void addEdge(Edge e) {
|
|
if (e.source == this) {
|
|
if (!outEdges.add(e)) {
|
|
throw new RuntimeException("\n" + this + "\nalready bound to " + e);
|
|
}
|
|
}
|
|
|
|
if (e.target == this) {
|
|
if (!inEdges.add(e)) {
|
|
throw new RuntimeException("" + this + " already bound to " + e);
|
|
}
|
|
}
|
|
}
|
|
|
|
public String toString() {
|
|
String s = getClass().getName();
|
|
// Same as getClass().getSimpleName() in JDK 5.0.
|
|
s = s.replaceFirst(".*\\.", "");
|
|
|
|
s += " " + id + "[" + initialPc + ", " + currentPc + "]";
|
|
//if (preOrderIndex >= 0) s += " preIndex=" + preOrderIndex;
|
|
if (domParent != null) s += " dominated by " + domParent.id;
|
|
if (isLoopHeader()) s += " LH";
|
|
return s;
|
|
}
|
|
|
|
public String describe() {
|
|
String s = toString();
|
|
Iterator iter = outEdges.iterator();
|
|
while (iter.hasNext()) {
|
|
Edge e = (Edge) iter.next();
|
|
s += "\n\t" + e;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
|
|
/**
|
|
* @return Returns the inEdges.
|
|
*/
|
|
public Set<Edge> getInEdges() {
|
|
return inEdges;
|
|
}
|
|
|
|
public Edge getSelfEdge() {
|
|
Iterator iterator = inEdges.iterator();
|
|
while (iterator.hasNext()) {
|
|
Edge edge = (Edge) iterator.next();
|
|
if (edge.source == this) return edge;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// public Set getGlobalInEdges() {
|
|
// HashSet set = new HashSet();
|
|
// Iterator iterator = inEdges.iterator();
|
|
// while (iterator.hasNext()) {
|
|
// Edge edge = (Edge) iterator.next();
|
|
// if (edge.global) set.add(edge);
|
|
// }
|
|
// return set;
|
|
// }
|
|
|
|
// public Set getForewardOutEdges() {
|
|
// HashSet set = new HashSet();
|
|
// Iterator iterator = outEdges.iterator();
|
|
// while (iterator.hasNext()) {
|
|
// Edge edge = (Edge) iterator.next();
|
|
// if (!edge.isBackEdge()) set.add(edge);
|
|
// }
|
|
// return set;
|
|
// }
|
|
|
|
/**
|
|
* @return Returns the outEdges.
|
|
*/
|
|
public Set<Edge> getOutEdges() {
|
|
return outEdges;
|
|
}
|
|
|
|
public Edge[] getOutEdgesArray() {
|
|
return outEdges.toArray(new Edge[outEdges.size()]);
|
|
}
|
|
|
|
public Edge[] getInEdgesArray() {
|
|
return inEdges.toArray(new Edge[inEdges.size()]);
|
|
}
|
|
|
|
public int getPreOrderIndex() {
|
|
return preOrderIndex;
|
|
}
|
|
|
|
public void setPreOrderIndex(int thePreOrderIndex) {
|
|
preOrderIndex = thePreOrderIndex;
|
|
}
|
|
|
|
public Set<Node> succs() {
|
|
Set<Node> list = new LinkedHashSet<Node>();
|
|
Edge[] edges = getOutEdgesArray();
|
|
for (int i=edges.length-1; i>=0; i--) {
|
|
list.add(edges[i].target);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
public Set<Node> preds() {
|
|
Set<Node> list = new LinkedHashSet<Node>();
|
|
Iterator iter = inEdges.iterator();
|
|
while (iter.hasNext()) {
|
|
Edge e = (Edge) iter.next();
|
|
list.add(e.source);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
public Node getPred() {
|
|
int count = inEdges.size();
|
|
if (count != 1) throw new RuntimeException("Requested unique predecessor, found " + count);
|
|
return inEdges.iterator().next().source;
|
|
}
|
|
|
|
public Node getSucc() {
|
|
return getOutEdge().target;
|
|
}
|
|
|
|
public Edge getLocalOutEdgeOrNull() {
|
|
Edge outEdge = null;
|
|
Iterator iter = outEdges.iterator();
|
|
while (iter.hasNext()) {
|
|
Edge edge = (Edge) iter.next();
|
|
if (outEdge != null) new RuntimeException("Found multiple local out-edges");
|
|
outEdge = edge;
|
|
}
|
|
return outEdge;
|
|
}
|
|
|
|
public Edge getOutEdge() {
|
|
int count = outEdges.size();
|
|
if (count != 1) throw new RuntimeException("Requested unique successor, found " + count);
|
|
return outEdges.iterator().next();
|
|
}
|
|
|
|
/**
|
|
* Return true if this node is equal to or dominates the specified node.
|
|
*/
|
|
public boolean isDomAncestor(Node node) {
|
|
do {
|
|
if (node == null) return false;
|
|
if (node == this) return true;
|
|
node = node.getDomParent();
|
|
} while (true);
|
|
}
|
|
|
|
public Set<Node> getDomChildren() {
|
|
return domChildren;
|
|
}
|
|
|
|
public Node getDomChild() {
|
|
if (domChildren.size() != 1) throw new RuntimeException("Node must have single child");
|
|
return getDomChildren().iterator().next();
|
|
}
|
|
|
|
public Node getDomParent() {
|
|
return domParent;
|
|
}
|
|
|
|
public void setDomParent(Node newDomParent) {
|
|
// If this Block already had a dominator specified, remove
|
|
// it from its dominator's children.
|
|
if (domParent != null) {
|
|
domParent.domChildren.remove(this);
|
|
}
|
|
|
|
domParent = newDomParent;
|
|
|
|
// Add this Block to its new dominator's children.
|
|
if (domParent != null) {
|
|
domParent.domChildren.add(this);
|
|
}
|
|
}
|
|
|
|
public boolean isBranch() {
|
|
Edge[] edges = getOutEdgesArray();
|
|
if (edges.length != 2) return false;
|
|
if (edges[0] instanceof ConditionalEdge && edges[1] instanceof ConditionalEdge) return true;
|
|
if ((edges[0] instanceof ConditionalEdge) || (edges[1] instanceof ConditionalEdge))
|
|
throw new RuntimeException("Node must not have mixed edges");
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns either the true or false edge.
|
|
*/
|
|
public ConditionalEdge getConditionalEdge(boolean trueFalse) {
|
|
if (!isBranch()) throw new RuntimeException("Node must be a branch");
|
|
Iterator<Edge> iter = outEdges.iterator();
|
|
Edge edge = iter.next();
|
|
if (!trueFalse) edge = iter.next();
|
|
return (ConditionalEdge) edge;
|
|
}
|
|
|
|
public String getId() {
|
|
return id;
|
|
}
|
|
|
|
public int getInitialPc() {
|
|
return initialPc;
|
|
}
|
|
|
|
public Graph getGraph() {
|
|
return graph;
|
|
}
|
|
|
|
public void setInitialPc(int theInitialPc) {
|
|
initialPc = theInitialPc;
|
|
currentPc = theInitialPc;
|
|
}
|
|
|
|
public boolean isLoopHeader() {
|
|
Iterator iter = inEdges.iterator();
|
|
while (iter.hasNext()) {
|
|
Edge edge = (Edge) iter.next();
|
|
if (edge.isBackEdge()) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean hasSelfEdges() {
|
|
Iterator iter = outEdges.iterator();
|
|
while (iter.hasNext()) {
|
|
Edge edge = (Edge) iter.next();
|
|
if (edge.target == this) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// public void replaceEdge(Edge oldEdge, Edge newEdge) {
|
|
// source.outEdges.remove(this);
|
|
// newSource.outEdges.add(this);
|
|
// source = newSource;
|
|
// }
|
|
}
|