Mercurial > hg > truffle
view src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEnv.java @ 4487:aae5b3773e63
Added CFG editor from c1visualizer.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Tue, 31 Jan 2012 00:23:10 +0100 |
parents | |
children | c43083cc96e9 |
line wrap: on
line source
package at.ssw.visualizer.cfg.model; import at.ssw.visualizer.model.cfg.BasicBlock; import at.ssw.visualizer.model.cfg.ControlFlowGraph; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; /** * This is the container class for the data model, * it prepares creates nodes and edges for the CfgScene * from a ControlFlowGraph of the Compilation Model */ public class CfgEnv { private ControlFlowGraph cfg; private Map<CfgNode, LoopInfo> loopMap;//maps: LoopHeader --> LoopInfo private CfgNodeImpl[] nodeArr; private CfgEdgeImpl[] edgeArr; public CfgEnv(ControlFlowGraph cfg) { this.cfg = cfg; int blockCount = cfg.getBasicBlocks().size(); CfgNodeImpl[] nodes = new CfgNodeImpl[blockCount]; Map<BasicBlock, CfgNodeImpl> block2nodeMap = new HashMap<BasicBlock, CfgNodeImpl>(); Map<CfgNodeImpl, Set<CfgEdgeImpl>> inputMap = new HashMap<CfgNodeImpl, Set<CfgEdgeImpl>>(); ArrayList<CfgEdgeImpl> allEdges = new ArrayList<CfgEdgeImpl>(); List<BasicBlock> blocks = cfg.getBasicBlocks(); //create nodes for(int idx=0 ; idx < blockCount ; idx++) { BasicBlock b = blocks.get(idx); String description = "Name: " + b.getName() + "\n"; description += "BCI: [" + b.getFromBci() + "," + b.getToBci() + "]\n"; if (b.getLoopDepth() > 0) { description += "Loop " + b.getLoopIndex() + " Depth " + b.getLoopDepth() + "\n"; } description += "Predecessors: " + getBlockList(b.getPredecessors()) + "\n"; description += "Successors: " + getBlockList(b.getSuccessors()) + "\n"; description += "XHandlers: " + getBlockList(b.getXhandlers()); if (b.getDominator() != null) { description += "\nDominator: " + b.getDominator().getName(); } nodes[idx] = new CfgNodeImpl(b, idx, description); block2nodeMap.put(b, nodes[idx]); } //create edges Set<String> cache = new HashSet<String>();//avoids identical edges with same source and same target for(int i = 0 ; i < blockCount ; i++) { BasicBlock b = blocks.get(i); List<CfgEdgeImpl> outputEdges = new ArrayList<CfgEdgeImpl>(); Set<BasicBlock> successors = new HashSet<BasicBlock>(); successors.addAll(b.getSuccessors()); successors.addAll(b.getXhandlers()); for(BasicBlock sb : successors) { CfgNodeImpl succNode = block2nodeMap.get(sb); CfgEdgeImpl edge = new CfgEdgeImpl(nodes[i], succNode); if(cache.contains(edge.toString())) continue; cache.add(edge.toString()); //check for symtric edges if(sb.getXhandlers().contains(b) || sb.getSuccessors().contains(b)) edge.setSymmetric(true); outputEdges.add(edge); } allEdges.addAll(outputEdges); nodes[i].setOutputEdges(outputEdges.toArray(new CfgEdgeImpl[outputEdges.size()])); } for(CfgEdgeImpl e: allEdges) { //CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); CfgNodeImpl tar = (CfgNodeImpl) e.getTargetNode(); Set<CfgEdgeImpl> set = inputMap.get(tar); if( set == null) { set = new HashSet<CfgEdgeImpl>(); set.add(e); inputMap.put(tar, set); } set.add(e); } for(CfgNodeImpl n : nodes){ Set<CfgEdgeImpl> inputEdges = inputMap.get(n); if(inputEdges == null) continue; n.setInputEdges(inputEdges.toArray(new CfgEdgeImpl[inputEdges.size()])); } CfgEdgeImpl[] edges = allEdges.toArray(new CfgEdgeImpl[allEdges.size()]); this.edgeArr=edges; this.nodeArr=nodes; CfgNodeImpl rootNode = nodeArr[0]; setNodeLevels(rootNode); indexLoops(rootNode); } private String getBlockList(List<? extends BasicBlock> blocks) { if (blocks.size() == 0) { return "None"; } StringBuilder sb = new StringBuilder(); String prefix = ""; for (BasicBlock b : blocks) { sb.append(prefix).append(b.getName()); prefix = ", "; } return sb.toString(); } public CfgNode[] getNodes(){ return this.nodeArr; } public CfgEdge[] getEdges(){ return this.edgeArr; } public Map<CfgNode, LoopInfo> getLoopMap() { return loopMap; } public void setLoopMap(Map<CfgNode, LoopInfo> loopMap) { this.loopMap = loopMap; } private void indexLoops(CfgNodeImpl rootNode){ LoopEnv env = new LoopEnv(Arrays.asList(nodeArr)); loopDetection(env, rootNode); calcLoopDepth(env); int loopIndex=1; for(LoopInfo info : env.loopMap.values()) { info.setLoopIndex(loopIndex++); info.setLoopDepth(info.getHeader().getLoopDepth()); for(CfgNode n : info.getMembers()){ if(n.getLoopDepth()>info.getLoopDepth()) continue; CfgNodeImpl ni = (CfgNodeImpl) n; ni.setLoopDepth(info.getLoopDepth()); ni.setLoopIndex(info.getLoopIndex()); } } for(LoopInfo info : env.loopMap.values()) { HashSet<CfgNode> members = new HashSet<CfgNode>(info.getMembers()); members.remove(info.getHeader());//remove own header for(CfgNode n: members){ if(n.isLoopHeader()) { LoopInfo memberInfo = env.loopMap.get(n); if (info.getLoopDepth() == memberInfo.getLoopDepth()-1) memberInfo.setParent(info); } } } this.loopMap = env.loopMap; } private class LoopEnv { Set<CfgNodeImpl> allNodes; Set<CfgNodeImpl> activeNodes; Set<CfgNodeImpl> visitedNodes; Map<CfgNode, LoopInfo> loopMap; private int loopIndex=0; public LoopEnv(Collection<CfgNodeImpl> nodes){ allNodes = new HashSet<CfgNodeImpl>(nodes); activeNodes = new HashSet<CfgNodeImpl>(2 * allNodes.size()); visitedNodes = new HashSet<CfgNodeImpl>(2 * allNodes.size()); loopMap = new HashMap<CfgNode, LoopInfo>(); } public int getLoopIndex(){ return ++loopIndex; } } private void loopDetection(LoopEnv env, CfgNodeImpl root) { for (CfgNodeImpl n : env.allNodes) { n.setLoopHeader(false); for (CfgEdge e : n.getInputEdges()) { CfgEdgeImpl ei = (CfgEdgeImpl) e; ei.setBackEdge(false); } } visit(env, root, null); } private void visit(LoopEnv env, CfgNodeImpl n, CfgEdgeImpl e) { if (env.activeNodes.contains(n)) { // This node is b loop header! n.setLoopHeader(true); e.setBackEdge(true); } else if (!env.visitedNodes.contains(n)) { env.visitedNodes.add(n); env.activeNodes.add(n); for (CfgEdge edge : n.getOutputEdges()) { if(!edge.getTargetNode().isOSR()) { CfgEdgeImpl ei = (CfgEdgeImpl) edge; CfgNodeImpl ni = (CfgNodeImpl) edge.getTargetNode(); visit(env, ni, ei); } } env.activeNodes.remove(n); } } private void calcLoopDepth(LoopEnv env) { for (CfgNodeImpl n : env.allNodes) { env.visitedNodes.clear(); if (n.isLoopHeader()) { LoopInfo loop = new LoopInfo(); loop.setHeader(n); n.setLoopIndex(env.getLoopIndex()); HashSet<CfgNode> members = new HashSet<CfgNode>(); loop.setMembers(members); members.add(n); env.loopMap.put(loop.getHeader(), loop); int loopDepth = n.getLoopDepth() + 1; loop.setLoopDepth(loopDepth); n.setLoopDepth(loopDepth); for (CfgEdge e : n.getInputEdges()) { if (e.isBackEdge() && !e.getSourceNode().isOSR()) { CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); backwardIteration(env, n, src, loop); loop.getBackEdges().add(e); } } } } } private void backwardIteration(LoopEnv env, CfgNodeImpl endNode, CfgNodeImpl n, LoopInfo loop) { if (endNode != n && !env.visitedNodes.contains(n)) { env.visitedNodes.add(n); for (CfgEdge e : n.getInputEdges()) { if (!e.getSourceNode().isOSR()) { CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); backwardIteration(env, endNode, src, loop); } } loop.getMembers().add(n); n.setLoopDepth(n.getLoopDepth() + 1); } } private void setNodeLevels(CfgNode rootNode){ Set<CfgNode> cache = new HashSet<CfgNode>(); Queue<CfgNode> queue = new LinkedList<CfgNode>(); queue.add(rootNode); cache.add(rootNode); int level=0; int[] nodeCount = new int[2]; nodeCount[0]=1; while(!queue.isEmpty()){ CfgNodeImpl curNode = (CfgNodeImpl) queue.poll(); curNode.setLevel(level); nodeCount[0]--; for(CfgEdge outEdge : curNode.getOutputEdges()) { CfgNode succNode = outEdge.getTargetNode(); if(cache.contains(succNode)) continue; cache.add(succNode); queue.add(succNode); nodeCount[1]++; } if(nodeCount[0]==0){ nodeCount[0]=nodeCount[1]; nodeCount[1]=0; level++; } } } public ControlFlowGraph getCfg() { return cfg; } }