Mercurial > hg > graal-jvmci-8
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 |