001/* 002 * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.phases.graph; 024 025import java.util.*; 026 027import com.oracle.graal.graph.*; 028import com.oracle.graal.nodes.*; 029 030/** 031 * A PostOrderNodeIterator iterates the fixed nodes of the graph in post order starting from a 032 * specified fixed node. 033 * <p> 034 * For this iterator the CFG is defined by the classical CFG nodes ({@link ControlSplitNode}, 035 * {@link AbstractMergeNode}...) and the {@link FixedWithNextNode#next() next} pointers of 036 * {@link FixedWithNextNode}. 037 * <p> 038 * While iterating it maintains a user-defined state by calling the methods available in 039 * {@link MergeableState}. 040 * 041 * @param <T> the type of {@link MergeableState} handled by this PostOrderNodeIterator 042 */ 043public abstract class PostOrderNodeIterator<T extends MergeableState<T>> { 044 045 private final NodeBitMap visitedEnds; 046 private final Deque<AbstractBeginNode> nodeQueue; 047 private final Map<FixedNode, T> nodeStates; 048 private final FixedNode start; 049 050 protected T state; 051 052 public PostOrderNodeIterator(FixedNode start, T initialState) { 053 StructuredGraph graph = start.graph(); 054 visitedEnds = graph.createNodeBitMap(); 055 nodeQueue = new ArrayDeque<>(); 056 nodeStates = Node.newIdentityMap(); 057 this.start = start; 058 this.state = initialState; 059 } 060 061 public void apply() { 062 FixedNode current = start; 063 064 do { 065 if (current instanceof InvokeWithExceptionNode) { 066 invoke((Invoke) current); 067 queueSuccessors(current, null); 068 current = nextQueuedNode(); 069 } else if (current instanceof LoopBeginNode) { 070 state.loopBegin((LoopBeginNode) current); 071 nodeStates.put(current, state); 072 state = state.clone(); 073 loopBegin((LoopBeginNode) current); 074 current = ((LoopBeginNode) current).next(); 075 assert current != null; 076 } else if (current instanceof LoopEndNode) { 077 loopEnd((LoopEndNode) current); 078 finishLoopEnds((LoopEndNode) current); 079 current = nextQueuedNode(); 080 } else if (current instanceof AbstractMergeNode) { 081 merge((AbstractMergeNode) current); 082 current = ((AbstractMergeNode) current).next(); 083 assert current != null; 084 } else if (current instanceof FixedWithNextNode) { 085 FixedNode next = ((FixedWithNextNode) current).next(); 086 assert next != null : current; 087 node(current); 088 current = next; 089 } else if (current instanceof EndNode) { 090 end((EndNode) current); 091 queueMerge((EndNode) current); 092 current = nextQueuedNode(); 093 } else if (current instanceof ControlSinkNode) { 094 node(current); 095 current = nextQueuedNode(); 096 } else if (current instanceof ControlSplitNode) { 097 Set<Node> successors = controlSplit((ControlSplitNode) current); 098 queueSuccessors(current, successors); 099 current = nextQueuedNode(); 100 } else { 101 assert false : current; 102 } 103 } while (current != null); 104 finished(); 105 } 106 107 private void queueSuccessors(FixedNode x, Set<Node> successors) { 108 nodeStates.put(x, state); 109 if (successors != null) { 110 for (Node node : successors) { 111 if (node != null) { 112 nodeStates.put((FixedNode) node.predecessor(), state); 113 nodeQueue.addFirst((AbstractBeginNode) node); 114 } 115 } 116 } else { 117 for (Node node : x.successors()) { 118 if (node != null) { 119 nodeQueue.addFirst((AbstractBeginNode) node); 120 } 121 } 122 } 123 } 124 125 private FixedNode nextQueuedNode() { 126 int maxIterations = nodeQueue.size(); 127 while (maxIterations-- > 0) { 128 AbstractBeginNode node = nodeQueue.removeFirst(); 129 if (node instanceof AbstractMergeNode) { 130 AbstractMergeNode merge = (AbstractMergeNode) node; 131 state = nodeStates.get(merge.forwardEndAt(0)).clone(); 132 ArrayList<T> states = new ArrayList<>(merge.forwardEndCount() - 1); 133 for (int i = 1; i < merge.forwardEndCount(); i++) { 134 T other = nodeStates.get(merge.forwardEndAt(i)); 135 assert other != null; 136 states.add(other); 137 } 138 boolean ready = state.merge(merge, states); 139 if (ready) { 140 return merge; 141 } else { 142 nodeQueue.addLast(merge); 143 } 144 } else { 145 assert node.predecessor() != null; 146 state = nodeStates.get(node.predecessor()).clone(); 147 state.afterSplit(node); 148 return node; 149 } 150 } 151 return null; 152 } 153 154 private void finishLoopEnds(LoopEndNode end) { 155 assert !visitedEnds.isMarked(end); 156 assert !nodeStates.containsKey(end); 157 nodeStates.put(end, state); 158 visitedEnds.mark(end); 159 LoopBeginNode begin = end.loopBegin(); 160 boolean endsVisited = true; 161 for (LoopEndNode le : begin.loopEnds()) { 162 if (!visitedEnds.isMarked(le)) { 163 endsVisited = false; 164 break; 165 } 166 } 167 if (endsVisited) { 168 ArrayList<T> states = new ArrayList<>(begin.loopEnds().count()); 169 for (LoopEndNode le : begin.orderedLoopEnds()) { 170 states.add(nodeStates.get(le)); 171 } 172 T loopBeginState = nodeStates.get(begin); 173 if (loopBeginState != null) { 174 loopBeginState.loopEnds(begin, states); 175 } 176 } 177 } 178 179 private void queueMerge(EndNode end) { 180 assert !visitedEnds.isMarked(end); 181 assert !nodeStates.containsKey(end); 182 nodeStates.put(end, state); 183 visitedEnds.mark(end); 184 AbstractMergeNode merge = end.merge(); 185 boolean endsVisited = true; 186 for (int i = 0; i < merge.forwardEndCount(); i++) { 187 if (!visitedEnds.isMarked(merge.forwardEndAt(i))) { 188 endsVisited = false; 189 break; 190 } 191 } 192 if (endsVisited) { 193 nodeQueue.add(merge); 194 } 195 } 196 197 protected abstract void node(FixedNode node); 198 199 protected void end(EndNode endNode) { 200 node(endNode); 201 } 202 203 protected void merge(AbstractMergeNode merge) { 204 node(merge); 205 } 206 207 protected void loopBegin(LoopBeginNode loopBegin) { 208 node(loopBegin); 209 } 210 211 protected void loopEnd(LoopEndNode loopEnd) { 212 node(loopEnd); 213 } 214 215 protected Set<Node> controlSplit(ControlSplitNode controlSplit) { 216 node(controlSplit); 217 return null; 218 } 219 220 protected void invoke(Invoke invoke) { 221 node(invoke.asNode()); 222 } 223 224 protected void finished() { 225 // nothing to do 226 } 227}