comparison graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java @ 2733:2ef23785ca93

Merge.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Thu, 19 May 2011 17:36:46 +0200
parents a2f62de90c76 027adfafd47e
children d913f3049cee
comparison
equal deleted inserted replaced
2732:beea26b73b3f 2733:2ef23785ca93
29 import java.util.*; 29 import java.util.*;
30 30
31 import com.oracle.graal.graph.*; 31 import com.oracle.graal.graph.*;
32 import com.sun.c1x.*; 32 import com.sun.c1x.*;
33 import com.sun.c1x.debug.*; 33 import com.sun.c1x.debug.*;
34 import com.sun.c1x.graph.BlockMap.Block;
34 import com.sun.c1x.ir.*; 35 import com.sun.c1x.ir.*;
35 import com.sun.c1x.util.*; 36 import com.sun.c1x.util.*;
36 import com.sun.c1x.value.*; 37 import com.sun.c1x.value.*;
37 import com.sun.cri.bytecode.*; 38 import com.sun.cri.bytecode.*;
38 import com.sun.cri.ci.*; 39 import com.sun.cri.ci.*;
81 private final C1XCompilation compilation; 82 private final C1XCompilation compilation;
82 private final CiStatistics stats; 83 private final CiStatistics stats;
83 84
84 private final BytecodeStream stream; // the bytecode stream 85 private final BytecodeStream stream; // the bytecode stream
85 // bci-to-block mapping 86 // bci-to-block mapping
86 private BlockBegin[] blockList; 87 private Block[] blockList;
87 88
88 // the constant pool 89 // the constant pool
89 private final RiConstantPool constantPool; 90 private final RiConstantPool constantPool;
90 91
91 // the worklist of blocks, managed like a sorted list 92 // the worklist of blocks, sorted by depth first number
92 private BlockBegin[] workList; 93 private final PriorityQueue<Block> workList = new PriorityQueue<Block>(10, new Comparator<Block>() {
93 94 public int compare(Block o1, Block o2) {
94 // the current position in the worklist 95 return o1.blockID - o2.blockID;
95 private int workListIndex; 96 }
97 });
96 98
97 /** 99 /**
98 * Mask of {@link Flag} values. 100 * Mask of {@link Flag} values.
99 */ 101 */
100 private int flags; 102 private int flags;
101 103
102 // Exception handler list 104 // Exception handler list
103 private List<ExceptionHandler> exceptionHandlers; 105 private List<ExceptionHandler> exceptionHandlers;
104 106
105 private BlockBegin curBlock; // the current block 107 private Block curBlock; // the current block
106 private FrameStateBuilder frameState; // the current execution state 108 private final FrameStateBuilder frameState; // the current execution state
107 private Instruction lastInstr; // the last instruction added 109 private Instruction lastInstr; // the last instruction added
110 private Instruction placeholder;
111
112
108 private final LogStream log; 113 private final LogStream log;
109 114
110 private Value rootMethodSynchronizedObject; 115 private Value rootMethodSynchronizedObject;
111 116
112 private final Graph graph; 117 private final Graph graph;
113 118
114 private BlockBegin unwindBlock; 119 private BlockBegin unwindBlock;
120
121 private final Set<Instruction> loopHeaders = new HashSet<Instruction>();
115 122
116 /** 123 /**
117 * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation. 124 * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation.
118 * 125 *
119 * @param compilation the compilation 126 * @param compilation the compilation
148 } 155 }
149 156
150 // 2. compute the block map, setup exception handlers and get the entrypoint(s) 157 // 2. compute the block map, setup exception handlers and get the entrypoint(s)
151 BlockMap blockMap = compilation.getBlockMap(rootMethod); 158 BlockMap blockMap = compilation.getBlockMap(rootMethod);
152 159
153 blockList = new BlockBegin[rootMethod.code().length]; 160 blockList = new Block[rootMethod.code().length];
154 for (int i = 0; i < blockMap.blocks.size(); i++) { 161 for (int i = 0; i < blockMap.blocks.size(); i++) {
155 BlockMap.Block block = blockMap.blocks.get(i); 162 Block block = blockMap.blocks.get(i);
156 BlockBegin blockBegin = new BlockBegin(block.startBci, ir.nextBlockNumber(), graph); 163
157 if (block.isLoopHeader) { 164 // if (block.isLoopHeader) {
158 blockBegin.setParserLoopHeader(true); 165 BlockBegin blockBegin = new BlockBegin(block.startBci, ir.nextBlockNumber(), graph);
159 } 166 blockBegin.setDepthFirstNumber(blockBegin.blockID);
160 blockBegin.setDepthFirstNumber(blockBegin.blockID); 167
161 blockList[block.startBci] = blockBegin; 168 block.firstInstruction = blockBegin;
169 blockList[block.startBci] = block;
170
171 if (block.isLoopHeader) {
172 loopHeaders.add(blockBegin);
173 }
174 // } else {
175 // blockList[block.startBci] = new Placeholder(graph);
176 // }
162 } 177 }
163 178
164 179
165 // 1. create the start block 180 // 1. create the start block
166 BlockBegin startBlock = new BlockBegin(0, ir.nextBlockNumber(), graph); 181 Block startBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI);
167 graph.root().setStart(startBlock); 182 BlockBegin startBlockBegin = new BlockBegin(0, startBlock.blockID, graph);
183 startBlock.firstInstruction = startBlockBegin;
184
185 graph.root().setStart(startBlockBegin);
168 curBlock = startBlock; 186 curBlock = startBlock;
169 187
170 RiExceptionHandler[] handlers = rootMethod.exceptionHandlers(); 188 RiExceptionHandler[] handlers = rootMethod.exceptionHandlers();
171 if (handlers != null && handlers.length > 0) { 189 if (handlers != null && handlers.length > 0) {
172 exceptionHandlers = new ArrayList<ExceptionHandler>(handlers.length); 190 exceptionHandlers = new ArrayList<ExceptionHandler>(handlers.length);
173 for (RiExceptionHandler ch : handlers) { 191 for (RiExceptionHandler ch : handlers) {
174 BlockBegin entry = blockAtOrNull(ch.handlerBCI()); 192 Block entry = blockList[ch.handlerBCI()];
175 // entry == null means that the exception handler is unreachable according to the BlockMap conservative analysis 193 // entry == null means that the exception handler is unreachable according to the BlockMap conservative analysis
176 if (entry != null) { 194 if (entry != null) {
177 ExceptionHandler h = new ExceptionHandler(ch); 195 ExceptionHandler h = new ExceptionHandler(ch);
178 h.setEntryBlock(entry); 196 h.setEntryBlock(entry);
179 exceptionHandlers.add(h); 197 exceptionHandlers.add(h);
180 } 198 }
181 } 199 }
182 flags |= Flag.HasHandler.mask; 200 flags |= Flag.HasHandler.mask;
183 } 201 }
184 202
185 startBlock.mergeOrClone(frameState, rootMethod); 203 assert !loopHeaders.contains(startBlock);
186 BlockBegin syncHandler = null; 204 startBlockBegin.mergeOrClone(frameState, rootMethod, false);
187 205
188 // 3. setup internal state for appending instructions 206 // 3. setup internal state for appending instructions
189 curBlock = startBlock; 207 curBlock = startBlock;
190 lastInstr = startBlock; 208 lastInstr = startBlockBegin;
191 lastInstr.appendNext(null); 209 lastInstr.appendNext(null);
192 210
193 BlockBegin entryBlock = blockList[0]; 211 Instruction entryBlock = blockAt(0);
212 BlockBegin syncHandler = null;
213 Block syncBlock = null;
194 if (isSynchronized(rootMethod.accessFlags())) { 214 if (isSynchronized(rootMethod.accessFlags())) {
195 // 4A.1 add a monitor enter to the start block 215 // 4A.1 add a monitor enter to the start block
196 rootMethodSynchronizedObject = synchronizedObject(frameState, compilation.method); 216 rootMethodSynchronizedObject = synchronizedObject(frameState, compilation.method);
197 genMonitorEnter(rootMethodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI); 217 genMonitorEnter(rootMethodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI);
198 // 4A.2 finish the start block 218 // 4A.2 finish the start block
199 finishStartBlock(startBlock, entryBlock); 219 finishStartBlock(startBlockBegin, entryBlock);
200 220
201 // 4A.3 setup an exception handler to unlock the root method synchronized object 221 // 4A.3 setup an exception handler to unlock the root method synchronized object
202 syncHandler = new BlockBegin(Instruction.SYNCHRONIZATION_ENTRY_BCI, ir.nextBlockNumber(), graph); 222 syncBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI);
203 markOnWorkList(syncHandler); 223 syncHandler = new BlockBegin(Instruction.SYNCHRONIZATION_ENTRY_BCI, syncBlock.blockID, graph);
224 syncBlock.firstInstruction = syncHandler;
225 markOnWorkList(syncBlock);
204 226
205 ExceptionHandler h = new ExceptionHandler(new CiExceptionHandler(0, rootMethod.code().length, -1, 0, null)); 227 ExceptionHandler h = new ExceptionHandler(new CiExceptionHandler(0, rootMethod.code().length, -1, 0, null));
206 h.setEntryBlock(syncHandler); 228 h.setEntryBlock(syncBlock);
207 addExceptionHandler(h); 229 addExceptionHandler(h);
208 } else { 230 } else {
209 // 4B.1 simply finish the start block 231 // 4B.1 simply finish the start block
210 finishStartBlock(startBlock, entryBlock); 232 finishStartBlock(startBlockBegin, entryBlock);
211 } 233 }
212 234
213 // 5. SKIPPED: look for intrinsics 235 // 5. SKIPPED: look for intrinsics
214 236
215 // 6B.1 do the normal parsing 237 // 6B.1 do the normal parsing
216 addToWorkList(entryBlock); 238 addToWorkList(blockList[0]);
217 iterateAllBlocks(); 239 iterateAllBlocks();
218 240
219 if (syncHandler != null && syncHandler.stateBefore() != null) { 241 if (syncBlock != null && syncHandler.stateBefore() != null) {
220 // generate unlocking code if the exception handler is reachable 242 // generate unlocking code if the exception handler is reachable
221 fillSyncHandler(rootMethodSynchronizedObject, syncHandler); 243 fillSyncHandler(rootMethodSynchronizedObject, syncBlock);
222 } 244 }
223 } 245 }
224 246
225 private Set<BlockBegin> blocksOnWorklist = new HashSet<BlockBegin>(); 247 private Block nextBlock(int bci) {
226 248 Block block = new Block();
227 private void markOnWorkList(BlockBegin block) { 249 block.startBci = bci;
250 block.endBci = bci;
251 block.blockID = ir.nextBlockNumber();
252 return block;
253 }
254
255 private Set<Block> blocksOnWorklist = new HashSet<Block>();
256
257 private void markOnWorkList(Block block) {
228 blocksOnWorklist.add(block); 258 blocksOnWorklist.add(block);
229 } 259 }
230 260
231 private boolean isOnWorkList(BlockBegin block) { 261 private boolean isOnWorkList(Block block) {
232 return blocksOnWorklist.contains(block); 262 return blocksOnWorklist.contains(block);
233 } 263 }
234 264
235 private Set<BlockBegin> blocksVisited = new HashSet<BlockBegin>(); 265 private Set<Block> blocksVisited = new HashSet<Block>();
236 266
237 private void markVisited(BlockBegin block) { 267 private void markVisited(Block block) {
238 blocksVisited.add(block); 268 blocksVisited.add(block);
239 } 269 }
240 270
241 private boolean isVisited(BlockBegin block) { 271 private boolean isVisited(Block block) {
242 return blocksVisited.contains(block); 272 return blocksVisited.contains(block);
243 } 273 }
244 274
245 private void finishStartBlock(BlockBegin startBlock, BlockBegin stdEntry) { 275 private void finishStartBlock(BlockBegin startBlock, Instruction stdEntry) {
246 assert curBlock == startBlock; 276 assert bci() == 0;
277 assert curBlock.firstInstruction == startBlock;
247 FrameState stateAfter = frameState.create(bci()); 278 FrameState stateAfter = frameState.create(bci());
248 Goto base = new Goto(stdEntry, stateAfter, graph); 279 Goto base = new Goto((BlockBegin) stdEntry, stateAfter, graph);
249 appendWithBCI(base); 280 appendWithBCI(base);
250 startBlock.setEnd(base); 281 startBlock.setEnd(base);
251 assert stdEntry.stateBefore() == null; 282 // assert stdEntry instanceof Placeholder;
252 stdEntry.mergeOrClone(stateAfter, method()); 283 assert ((BlockBegin) stdEntry).stateBefore() == null;
284 prepareTarget(0);
285 mergeOrClone(stdEntry, stateAfter, method(), loopHeaders.contains(stdEntry));
286 }
287
288 private void prepareTarget(int bci) {
289 }
290
291 private void mergeOrClone(Instruction block, FrameState stateAfter, RiMethod method, boolean loopHeader) {
292 ((BlockBegin) block).mergeOrClone(stateAfter, method, loopHeader);
253 } 293 }
254 294
255 public RiMethod method() { 295 public RiMethod method() {
256 return compilation.method; 296 return compilation.method;
257 } 297 }
300 } 340 }
301 } 341 }
302 } 342 }
303 343
304 if (!exceptionHandlers.isEmpty()) { 344 if (!exceptionHandlers.isEmpty()) {
305 BlockBegin successor; 345 Instruction successor;
306 346
307 ArrayList<BlockBegin> newBlocks = new ArrayList<BlockBegin>(); 347 ArrayList<BlockBegin> newBlocks = new ArrayList<BlockBegin>();
308 348
309 int current = exceptionHandlers.size() - 1; 349 int current = exceptionHandlers.size() - 1;
310 if (exceptionHandlers.get(current).isCatchAll()) { 350 if (exceptionHandlers.get(current).isCatchAll()) {
311 successor = exceptionHandlers.get(current).entryBlock(); 351 successor = exceptionHandlers.get(current).entryBlock().firstInstruction;
312 current--; 352 current--;
313 } else { 353 } else {
314 if (unwindBlock == null) { 354 if (unwindBlock == null) {
315 unwindBlock = new BlockBegin(bci, ir.nextBlockNumber(), graph); 355 unwindBlock = new BlockBegin(bci, ir.nextBlockNumber(), graph);
316 Unwind unwind = new Unwind(null, graph); 356 Unwind unwind = new Unwind(null, graph);
322 362
323 for (; current >= 0; current--) { 363 for (; current >= 0; current--) {
324 ExceptionHandler handler = exceptionHandlers.get(current); 364 ExceptionHandler handler = exceptionHandlers.get(current);
325 365
326 BlockBegin newSucc = null; 366 BlockBegin newSucc = null;
327 for (Instruction pred : successor.blockPredecessors()) { 367 for (Node pred : successor.predecessors()) {
328 if (pred instanceof ExceptionDispatch) { 368 if (pred instanceof ExceptionDispatch) {
329 ExceptionDispatch dispatch = (ExceptionDispatch) pred; 369 ExceptionDispatch dispatch = (ExceptionDispatch) pred;
330 if (dispatch.handler().handler == handler.handler) { 370 if (dispatch.handler().handler == handler.handler) {
331 newSucc = dispatch.begin(); 371 newSucc = dispatch.begin();
332 break; 372 break;
335 } 375 }
336 if (newSucc != null) { 376 if (newSucc != null) {
337 successor = newSucc; 377 successor = newSucc;
338 } else { 378 } else {
339 BlockBegin dispatchEntry = new BlockBegin(handler.handlerBCI(), ir.nextBlockNumber(), graph); 379 BlockBegin dispatchEntry = new BlockBegin(handler.handlerBCI(), ir.nextBlockNumber(), graph);
380
340 if (handler.handler.catchType().isResolved()) { 381 if (handler.handler.catchType().isResolved()) {
341 ExceptionDispatch end = new ExceptionDispatch(null, handler.entryBlock(), null, handler, null, graph); 382 ExceptionDispatch end = new ExceptionDispatch(null, (BlockBegin) handler.entryBlock().firstInstruction, null, handler, null, graph);
342 end.setBlockSuccessor(0, successor); 383 end.setBlockSuccessor(0, (BlockBegin) successor);
343 dispatchEntry.appendNext(end); 384 dispatchEntry.appendNext(end);
344 dispatchEntry.setEnd(end); 385 dispatchEntry.setEnd(end);
345 } else { 386 } else {
346 Deoptimize deopt = new Deoptimize(graph); 387 Deoptimize deopt = new Deoptimize(graph);
347 dispatchEntry.appendNext(deopt); 388 dispatchEntry.appendNext(deopt);
348 Goto end = new Goto(successor, null, graph); 389 Goto end = new Goto((BlockBegin) successor, null, graph);
349 deopt.appendNext(end); 390 deopt.appendNext(end);
350 dispatchEntry.setEnd(end); 391 dispatchEntry.setEnd(end);
351 } 392 }
393
352 newBlocks.add(dispatchEntry); 394 newBlocks.add(dispatchEntry);
353 successor = dispatchEntry; 395 successor = dispatchEntry;
354 } 396 }
355 } 397 }
356 398
359 BlockBegin entry = new BlockBegin(bci, ir.nextBlockNumber(), graph); 401 BlockBegin entry = new BlockBegin(bci, ir.nextBlockNumber(), graph);
360 entry.setStateBefore(entryState); 402 entry.setStateBefore(entryState);
361 ExceptionObject exception = new ExceptionObject(graph); 403 ExceptionObject exception = new ExceptionObject(graph);
362 entry.appendNext(exception); 404 entry.appendNext(exception);
363 FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, exception); 405 FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, exception);
364 BlockEnd end = new Goto(successor, stateWithException, graph); 406 BlockEnd end = new Goto((BlockBegin) successor, stateWithException, graph);
365 exception.appendNext(end); 407 exception.appendNext(end);
366 entry.setEnd(end); 408 entry.setEnd(end);
367 409
368 if (x instanceof Invoke) { 410 if (x instanceof Invoke) {
369 ((Invoke) x).setExceptionEdge(entry); 411 ((Invoke) x).setExceptionEdge(entry);
377 419
378 private void updateDispatchChain(BlockBegin dispatchEntry, FrameStateAccess state, int bci) { 420 private void updateDispatchChain(BlockBegin dispatchEntry, FrameStateAccess state, int bci) {
379 FrameState oldState = dispatchEntry.stateBefore(); 421 FrameState oldState = dispatchEntry.stateBefore();
380 if (oldState != null && dispatchEntry.predecessors().size() == 1) { 422 if (oldState != null && dispatchEntry.predecessors().size() == 1) {
381 dispatchEntry.setStateBefore(null); 423 dispatchEntry.setStateBefore(null);
382 oldState.delete(); 424 }
383 } 425 dispatchEntry.mergeOrClone(state, null, false);
384 dispatchEntry.mergeOrClone(state, null);
385 FrameState mergedState = dispatchEntry.stateBefore(); 426 FrameState mergedState = dispatchEntry.stateBefore();
386 427
387 if (dispatchEntry.next() instanceof ExceptionDispatch) { 428 if (dispatchEntry.next() instanceof ExceptionDispatch) {
388 // ordinary dispatch handler 429 // ordinary dispatch handler
389 ExceptionDispatch dispatch = (ExceptionDispatch) dispatchEntry.next(); 430 ExceptionDispatch dispatch = (ExceptionDispatch) dispatchEntry.next();
410 * of exception handlers for the {@link #curBlock current block}. 451 * of exception handlers for the {@link #curBlock current block}.
411 */ 452 */
412 private ExceptionHandler addExceptionHandler(ExceptionHandler handler, FrameStateAccess curState) { 453 private ExceptionHandler addExceptionHandler(ExceptionHandler handler, FrameStateAccess curState) {
413 compilation.setHasExceptionHandlers(); 454 compilation.setHasExceptionHandlers();
414 455
415 BlockBegin entry = handler.entryBlock(); 456 BlockMap.Block entry = handler.entryBlock();
416 457
417 // clone exception handler 458 // clone exception handler
418 ExceptionHandler newHandler = new ExceptionHandler(handler); 459 ExceptionHandler newHandler = new ExceptionHandler(handler);
419 460
420 // fill in exception handler subgraph lazily 461 // fill in exception handler subgraph lazily
421 if (!isVisited(entry)) { 462 if (!isVisited(entry)) {
422 addToWorkList(entry); 463 if (handler.handlerBCI() != Instruction.SYNCHRONIZATION_ENTRY_BCI) {
464 addToWorkList(blockList[handler.handlerBCI()]);
465 }
423 } else { 466 } else {
424 // This will occur for exception handlers that cover themselves. This code 467 // This will occur for exception handlers that cover themselves. This code
425 // pattern is generated by javac for synchronized blocks. See the following 468 // pattern is generated by javac for synchronized blocks. See the following
426 // for why this change to javac was made: 469 // for why this change to javac was made:
427 // 470 //
600 Value y = append(Constant.forInt(delta, graph)); 643 Value y = append(Constant.forInt(delta, graph));
601 frameState.storeLocal(index, append(new ArithmeticOp(IADD, CiKind.Int, x, y, isStrict(method().accessFlags()), false, graph))); 644 frameState.storeLocal(index, append(new ArithmeticOp(IADD, CiKind.Int, x, y, isStrict(method().accessFlags()), false, graph)));
602 } 645 }
603 646
604 private void genGoto(int fromBCI, int toBCI) { 647 private void genGoto(int fromBCI, int toBCI) {
605 append(new Goto(blockAt(toBCI), null, graph)); 648 append(new Goto((BlockBegin) blockAt(toBCI), null, graph));
606 } 649 }
607 650
608 private void ifNode(Value x, Condition cond, Value y, FrameState stateBefore) { 651 private void ifNode(Value x, Condition cond, Value y, FrameState stateBefore) {
609 BlockBegin tsucc = blockAt(stream().readBranchDest()); 652 Instruction tsucc = blockAt(stream().readBranchDest());
610 BlockBegin fsucc = blockAt(stream().nextBCI()); 653 Instruction fsucc = blockAt(stream().nextBCI());
611 append(new If(x, cond, y, tsucc, fsucc, null, graph)); 654 append(new If(x, cond, y, (BlockBegin) tsucc, (BlockBegin) fsucc, null, graph));
612 stateBefore.delete(); 655 stateBefore.delete();
613 } 656 }
614 657
615 private void genIfZero(Condition cond) { 658 private void genIfZero(Condition cond) {
616 Value y = appendConstant(CiConstant.INT_0); 659 Value y = appendConstant(CiConstant.INT_0);
976 1019
977 private void genTableswitch() { 1020 private void genTableswitch() {
978 int bci = bci(); 1021 int bci = bci();
979 BytecodeTableSwitch ts = new BytecodeTableSwitch(stream(), bci); 1022 BytecodeTableSwitch ts = new BytecodeTableSwitch(stream(), bci);
980 int max = ts.numberOfCases(); 1023 int max = ts.numberOfCases();
981 List<BlockBegin> list = new ArrayList<BlockBegin>(max + 1); 1024 List<Instruction> list = new ArrayList<Instruction>(max + 1);
982 boolean isBackwards = false; 1025 boolean isBackwards = false;
983 for (int i = 0; i < max; i++) { 1026 for (int i = 0; i < max; i++) {
984 // add all successors to the successor list 1027 // add all successors to the successor list
985 int offset = ts.offsetAt(i); 1028 int offset = ts.offsetAt(i);
986 list.add(blockAt(bci + offset)); 1029 list.add(blockAt(bci + offset));
989 int offset = ts.defaultOffset(); 1032 int offset = ts.defaultOffset();
990 isBackwards |= offset < 0; // if the default successor is backwards 1033 isBackwards |= offset < 0; // if the default successor is backwards
991 list.add(blockAt(bci + offset)); 1034 list.add(blockAt(bci + offset));
992 boolean isSafepoint = isBackwards && !noSafepoints(); 1035 boolean isSafepoint = isBackwards && !noSafepoints();
993 FrameState stateBefore = isSafepoint ? frameState.create(bci()) : null; 1036 FrameState stateBefore = isSafepoint ? frameState.create(bci()) : null;
994 append(new TableSwitch(frameState.ipop(), list, ts.lowKey(), stateBefore, graph)); 1037 append(new TableSwitch(frameState.ipop(), (List) list, ts.lowKey(), stateBefore, graph));
995 } 1038 }
996 1039
997 private void genLookupswitch() { 1040 private void genLookupswitch() {
998 int bci = bci(); 1041 int bci = bci();
999 BytecodeLookupSwitch ls = new BytecodeLookupSwitch(stream(), bci); 1042 BytecodeLookupSwitch ls = new BytecodeLookupSwitch(stream(), bci);
1000 int max = ls.numberOfCases(); 1043 int max = ls.numberOfCases();
1001 List<BlockBegin> list = new ArrayList<BlockBegin>(max + 1); 1044 List<Instruction> list = new ArrayList<Instruction>(max + 1);
1002 int[] keys = new int[max]; 1045 int[] keys = new int[max];
1003 boolean isBackwards = false; 1046 boolean isBackwards = false;
1004 for (int i = 0; i < max; i++) { 1047 for (int i = 0; i < max; i++) {
1005 // add all successors to the successor list 1048 // add all successors to the successor list
1006 int offset = ls.offsetAt(i); 1049 int offset = ls.offsetAt(i);
1011 int offset = ls.defaultOffset(); 1054 int offset = ls.defaultOffset();
1012 isBackwards |= offset < 0; // if the default successor is backwards 1055 isBackwards |= offset < 0; // if the default successor is backwards
1013 list.add(blockAt(bci + offset)); 1056 list.add(blockAt(bci + offset));
1014 boolean isSafepoint = isBackwards && !noSafepoints(); 1057 boolean isSafepoint = isBackwards && !noSafepoints();
1015 FrameState stateBefore = isSafepoint ? frameState.create(bci()) : null; 1058 FrameState stateBefore = isSafepoint ? frameState.create(bci()) : null;
1016 append(new LookupSwitch(frameState.ipop(), list, keys, stateBefore, graph)); 1059 append(new LookupSwitch(frameState.ipop(), (List) list, keys, stateBefore, graph));
1017 } 1060 }
1018 1061
1019 private Value appendConstant(CiConstant constant) { 1062 private Value appendConstant(CiConstant constant) {
1020 return appendWithBCI(new Constant(constant, graph)); 1063 return appendWithBCI(new Constant(constant, graph));
1021 } 1064 }
1031 } 1074 }
1032 1075
1033 assert x.next() == null : "instruction should not have been appended yet"; 1076 assert x.next() == null : "instruction should not have been appended yet";
1034 assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; 1077 assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
1035 1078
1079 if (placeholder != null) {
1080 placeholder = null;
1081 }
1082
1036 lastInstr = lastInstr.appendNext(x); 1083 lastInstr = lastInstr.appendNext(x);
1037 if (++stats.nodeCount >= C1XOptions.MaximumInstructionCount) { 1084 if (++stats.nodeCount >= C1XOptions.MaximumInstructionCount) {
1038 // bailout if we've exceeded the maximum inlining size 1085 // bailout if we've exceeded the maximum inlining size
1039 throw new CiBailout("Method and/or inlining is too large"); 1086 throw new CiBailout("Method and/or inlining is too large");
1040 } 1087 }
1041 1088
1042 return x; 1089 return x;
1043 } 1090 }
1044 1091
1045 private BlockBegin blockAtOrNull(int bci) { 1092 private Instruction blockAtOrNull(int bci) {
1046 return blockList[bci]; 1093 return blockList[bci] != null ? blockList[bci].firstInstruction : null;
1047 } 1094 }
1048 1095
1049 private BlockBegin blockAt(int bci) { 1096 private Instruction blockAt(int bci) {
1050 BlockBegin result = blockAtOrNull(bci); 1097 Instruction result = blockAtOrNull(bci);
1051 assert result != null : "Expected a block to begin at " + bci; 1098 assert result != null : "Expected a block to begin at " + bci;
1052 return result; 1099 return result;
1053 } 1100 }
1054 1101
1055 private Value synchronizedObject(FrameStateAccess state, RiMethod target) { 1102 private Value synchronizedObject(FrameStateAccess state, RiMethod target) {
1059 } else { 1106 } else {
1060 return state.localAt(0); 1107 return state.localAt(0);
1061 } 1108 }
1062 } 1109 }
1063 1110
1064 private void fillSyncHandler(Value lock, BlockBegin syncHandler) { 1111 private void fillSyncHandler(Value lock, Block syncHandler) {
1065 BlockBegin origBlock = curBlock; 1112 Block origBlock = curBlock;
1066 FrameState origState = frameState.create(-1); 1113 FrameState origState = frameState.create(-1);
1067 Instruction origLast = lastInstr; 1114 Instruction origLast = lastInstr;
1068 1115
1069 lastInstr = curBlock = syncHandler; 1116 lastInstr = syncHandler.firstInstruction;
1117 curBlock = syncHandler;
1070 while (lastInstr.next() != null) { 1118 while (lastInstr.next() != null) {
1071 // go forward to the end of the block 1119 // go forward to the end of the block
1072 lastInstr = lastInstr.next(); 1120 lastInstr = lastInstr.next();
1073 } 1121 }
1074 frameState.initializeFrom(syncHandler.stateBefore()); 1122 frameState.initializeFrom(((BlockBegin) syncHandler.firstInstruction).stateBefore());
1075 1123
1076 int bci = Instruction.SYNCHRONIZATION_ENTRY_BCI; 1124 int bci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
1077 1125
1078 assert lock != null; 1126 assert lock != null;
1079 assert frameState.locksSize() > 0 && frameState.lockAt(frameState.locksSize() - 1) == lock; 1127 assert frameState.locksSize() > 0 && frameState.lockAt(frameState.locksSize() - 1) == lock;
1086 // exit the monitor 1134 // exit the monitor
1087 genMonitorExit(lock, Instruction.SYNCHRONIZATION_ENTRY_BCI); 1135 genMonitorExit(lock, Instruction.SYNCHRONIZATION_ENTRY_BCI);
1088 1136
1089 genThrow(bci); 1137 genThrow(bci);
1090 BlockEnd end = (BlockEnd) lastInstr; 1138 BlockEnd end = (BlockEnd) lastInstr;
1091 curBlock.setEnd(end); 1139 ((BlockBegin) curBlock.firstInstruction).setEnd(end);
1092 end.setStateAfter(frameState.create(bci())); 1140 end.setStateAfter(frameState.create(bci()));
1093 1141
1094 curBlock = origBlock; 1142 curBlock = origBlock;
1095 frameState.initializeFrom(origState); 1143 frameState.initializeFrom(origState);
1096 origState.delete(); 1144 origState.delete();
1097 lastInstr = origLast; 1145 lastInstr = origLast;
1098 } 1146 }
1099 1147
1100 private void iterateAllBlocks() { 1148 private void iterateAllBlocks() {
1101 BlockBegin b; 1149 Block block;
1102 while ((b = removeFromWorkList()) != null) { 1150 while ((block = removeFromWorkList()) != null) {
1103 1151
1104 // remove blocks that have no predecessors by the time it their bytecodes are parsed 1152 // remove blocks that have no predecessors by the time it their bytecodes are parsed
1105 if (b.blockPredecessors().size() == 0) { 1153 if (block.firstInstruction.predecessors().size() == 0) {
1106 markVisited(b); 1154 markVisited(block);
1107 continue; 1155 continue;
1108 } 1156 }
1109 1157
1110 if (!isVisited(b)) { 1158 if (!isVisited(block)) {
1111 markVisited(b); 1159 markVisited(block);
1112 // now parse the block 1160 // now parse the block
1113 curBlock = b; 1161 curBlock = block;
1114 frameState.initializeFrom(b.stateBefore()); 1162 if (block.firstInstruction instanceof Placeholder) {
1115 lastInstr = b; 1163 assert false;
1116 b.appendNext(null); 1164 placeholder = block.firstInstruction;
1117 1165 frameState.initializeFrom(((Placeholder) placeholder).stateBefore());
1118 iterateBytecodesForBlock(b.bci()); 1166 lastInstr = null;
1167 } else {
1168 assert block.firstInstruction instanceof BlockBegin;
1169 placeholder = null;
1170 frameState.initializeFrom(((BlockBegin) block.firstInstruction).stateBefore());
1171 lastInstr = block.firstInstruction;
1172 }
1173 assert block.firstInstruction.next() == null;
1174
1175 iterateBytecodesForBlock(block.startBci);
1119 } 1176 }
1120 } 1177 }
1121 } 1178 }
1122 1179
1123 private BlockEnd iterateBytecodesForBlock(int bci) { 1180 private BlockEnd iterateBytecodesForBlock(int bci) {
1124 assert frameState != null; 1181 assert frameState != null;
1125 stream.setBCI(bci); 1182 stream.setBCI(bci);
1126 1183
1127 BlockBegin block = curBlock; 1184 BlockBegin block = (BlockBegin) curBlock.firstInstruction;
1128 BlockEnd end = null; 1185 BlockEnd end = null;
1129 int endBCI = stream.endBCI(); 1186 int endBCI = stream.endBCI();
1130 boolean blockStart = true; 1187 boolean blockStart = true;
1131 1188
1132 while (bci < endBCI) { 1189 while (bci < endBCI) {
1133 BlockBegin nextBlock = blockAtOrNull(bci); 1190 Instruction nextBlock = blockAtOrNull(bci);
1134 if (nextBlock != null && nextBlock != block) { 1191 if (nextBlock != null && nextBlock != block) {
1135 // we fell through to the next block, add a goto and break 1192 // we fell through to the next block, add a goto and break
1136 end = new Goto(nextBlock, null, graph); 1193 end = new Goto((BlockBegin) nextBlock, null, graph);
1137 lastInstr = lastInstr.appendNext(end); 1194 lastInstr = lastInstr.appendNext(end);
1138 break; 1195 break;
1139 } 1196 }
1140 // read the opcode 1197 // read the opcode
1141 int opcode = stream.currentBC(); 1198 int opcode = stream.currentBC();
1167 // connect to begin and set state 1224 // connect to begin and set state
1168 // NOTE that inlining may have changed the block we are parsing 1225 // NOTE that inlining may have changed the block we are parsing
1169 assert end != null : "end should exist after iterating over bytecodes"; 1226 assert end != null : "end should exist after iterating over bytecodes";
1170 FrameState stateAtEnd = frameState.create(bci()); 1227 FrameState stateAtEnd = frameState.create(bci());
1171 end.setStateAfter(stateAtEnd); 1228 end.setStateAfter(stateAtEnd);
1172 curBlock.setEnd(end); 1229 block.setEnd(end);
1173 1230
1174 // propagate the state 1231 // propagate the state
1175 for (BlockBegin succ : end.blockSuccessors()) { 1232 for (BlockBegin succ : end.blockSuccessors()) {
1176 assert succ.blockPredecessors().contains(curBlock.end()); 1233 assert succ.blockPredecessors().contains(block.end());
1177 succ.mergeOrClone(stateAtEnd, method()); 1234 succ.mergeOrClone(stateAtEnd, method(), loopHeaders.contains(succ));
1178 addToWorkList(succ); 1235 addToWorkList(blockList[succ.bci()]);
1179 } 1236 }
1180 return end; 1237 return end;
1181 } 1238 }
1182 1239
1183 private void traceState() { 1240 private void traceState() {
1452 * Adds a block to the worklist, if it is not already in the worklist. 1509 * Adds a block to the worklist, if it is not already in the worklist.
1453 * This method will keep the worklist topologically stored (i.e. the lower 1510 * This method will keep the worklist topologically stored (i.e. the lower
1454 * DFNs are earlier in the list). 1511 * DFNs are earlier in the list).
1455 * @param block the block to add to the work list 1512 * @param block the block to add to the work list
1456 */ 1513 */
1457 private void addToWorkList(BlockBegin block) { 1514 private void addToWorkList(Block block) {
1458 if (!isOnWorkList(block)) { 1515 if (!isOnWorkList(block)) {
1459 markOnWorkList(block); 1516 markOnWorkList(block);
1460 sortIntoWorkList(block); 1517 sortIntoWorkList(block);
1461 } 1518 }
1462 } 1519 }
1463 1520
1464 private void sortIntoWorkList(BlockBegin top) { 1521 private void sortIntoWorkList(Block top) {
1465 // XXX: this is O(n), since the whole list is sorted; a heap could achieve O(nlogn), but 1522 workList.offer(top);
1466 // would only pay off for large worklists
1467 if (workList == null) {
1468 // need to allocate the worklist
1469 workList = new BlockBegin[5];
1470 } else if (workListIndex == workList.length) {
1471 // need to grow the worklist
1472 BlockBegin[] nworkList = new BlockBegin[workList.length * 3];
1473 System.arraycopy(workList, 0, nworkList, 0, workList.length);
1474 workList = nworkList;
1475 }
1476 // put the block at the end of the array
1477 workList[workListIndex++] = top;
1478 int dfn = top.depthFirstNumber();
1479 assert dfn >= 0 : top + " does not have a depth first number";
1480 int i = workListIndex - 2;
1481 // push top towards the beginning of the array
1482 for (; i >= 0; i--) {
1483 BlockBegin b = workList[i];
1484 if (b.depthFirstNumber() >= dfn) {
1485 break; // already in the right position
1486 }
1487 workList[i + 1] = b; // bubble b down by one
1488 workList[i] = top; // and overwrite it with top
1489 }
1490 } 1523 }
1491 1524
1492 /** 1525 /**
1493 * Removes the next block from the worklist. The list is sorted topologically, so the 1526 * Removes the next block from the worklist. The list is sorted topologically, so the
1494 * block with the lowest depth first number in the list will be removed and returned. 1527 * block with the lowest depth first number in the list will be removed and returned.
1495 * @return the next block from the worklist; {@code null} if there are no blocks 1528 * @return the next block from the worklist; {@code null} if there are no blocks
1496 * in the worklist 1529 * in the worklist
1497 */ 1530 */
1498 private BlockBegin removeFromWorkList() { 1531 private Block removeFromWorkList() {
1499 if (workListIndex == 0) { 1532 return workList.poll();
1500 return null;
1501 }
1502 // pop the last item off the end
1503 return workList[--workListIndex];
1504 } 1533 }
1505 1534
1506 /** 1535 /**
1507 * Checks whether this graph has any handlers. 1536 * Checks whether this graph has any handlers.
1508 * @return {@code true} if there are any exception handlers 1537 * @return {@code true} if there are any exception handlers