Mercurial > hg > graal-jvmci-8
comparison graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java @ 2773:27512ea6bbcb
exception dispatch simplification:
* BlockMap creates exception dispatch blocks (so they're iterated in the right order)
* GraphBuilder uses exception dispatch blocks, simplified handleException, removed updateDispatchChain
* simplified mergeOrClone
* removed successor & predecessor methods from BlockBegin
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Tue, 24 May 2011 12:07:17 +0200 |
parents | 056e392d63d4 |
children | 93fd92c9f8b0 |
comparison
equal
deleted
inserted
replaced
2772:3e3338a1abb9 | 2773:27512ea6bbcb |
---|---|
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.graph.BlockMap.Block; |
35 import com.sun.c1x.graph.BlockMap.ExceptionBlock; | |
35 import com.sun.c1x.ir.*; | 36 import com.sun.c1x.ir.*; |
36 import com.sun.c1x.util.*; | 37 import com.sun.c1x.util.*; |
37 import com.sun.c1x.value.*; | 38 import com.sun.c1x.value.*; |
38 import com.sun.cri.bytecode.*; | 39 import com.sun.cri.bytecode.*; |
39 import com.sun.cri.ci.*; | 40 import com.sun.cri.ci.*; |
82 private final C1XCompilation compilation; | 83 private final C1XCompilation compilation; |
83 private final CiStatistics stats; | 84 private final CiStatistics stats; |
84 | 85 |
85 private final BytecodeStream stream; // the bytecode stream | 86 private final BytecodeStream stream; // the bytecode stream |
86 // bci-to-block mapping | 87 // bci-to-block mapping |
87 private Block[] blockList; | 88 private Block[] blockFromBci; |
89 private ArrayList<Block> blockList; | |
88 | 90 |
89 // the constant pool | 91 // the constant pool |
90 private final RiConstantPool constantPool; | 92 private final RiConstantPool constantPool; |
91 | 93 |
92 // the worklist of blocks, sorted by depth first number | 94 // the worklist of blocks, sorted by depth first number |
150 } | 152 } |
151 | 153 |
152 // 2. compute the block map, setup exception handlers and get the entrypoint(s) | 154 // 2. compute the block map, setup exception handlers and get the entrypoint(s) |
153 BlockMap blockMap = compilation.getBlockMap(rootMethod); | 155 BlockMap blockMap = compilation.getBlockMap(rootMethod); |
154 | 156 |
155 blockList = new Block[rootMethod.code().length]; | 157 blockList = new ArrayList<Block>(blockMap.blocks); |
156 for (int i = 0; i < blockMap.blocks.size(); i++) { | 158 blockFromBci = new Block[rootMethod.code().length]; |
159 for (int i = 0; i < blockList.size(); i++) { | |
157 int blockID = ir.nextBlockNumber(); | 160 int blockID = ir.nextBlockNumber(); |
158 assert blockID == i; | 161 assert blockID == i; |
159 Block block = blockMap.blocks.get(i); | 162 Block block = blockList.get(i); |
160 blockList[block.startBci] = block; | 163 if (block.startBci >= 0) { |
164 blockFromBci[block.startBci] = block; | |
165 } | |
166 // System.out.println("block " + blockID + " @ " + block.startBci); | |
161 } | 167 } |
162 | 168 |
163 // 1. create the start block | 169 // 1. create the start block |
164 Block startBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI); | 170 Block startBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI); |
165 BlockBegin startBlockBegin = new BlockBegin(0, startBlock.blockID, false, graph); | 171 BlockBegin startBlockBegin = new BlockBegin(0, startBlock.blockID, false, graph); |
169 | 175 |
170 RiExceptionHandler[] handlers = rootMethod.exceptionHandlers(); | 176 RiExceptionHandler[] handlers = rootMethod.exceptionHandlers(); |
171 if (handlers != null && handlers.length > 0) { | 177 if (handlers != null && handlers.length > 0) { |
172 exceptionHandlers = new ArrayList<ExceptionHandler>(handlers.length); | 178 exceptionHandlers = new ArrayList<ExceptionHandler>(handlers.length); |
173 for (RiExceptionHandler ch : handlers) { | 179 for (RiExceptionHandler ch : handlers) { |
174 Block entry = blockList[ch.handlerBCI()]; | 180 Block entry = blockFromBci[ch.handlerBCI()]; |
175 // entry == null means that the exception handler is unreachable according to the BlockMap conservative analysis | 181 // entry == null means that the exception handler is unreachable according to the BlockMap conservative analysis |
176 if (entry != null) { | 182 if (entry != null) { |
177 ExceptionHandler h = new ExceptionHandler(ch); | 183 ExceptionHandler h = new ExceptionHandler(ch); |
178 h.setEntryBlock(entry); | 184 h.setEntryBlock(entry); |
179 exceptionHandlers.add(h); | 185 exceptionHandlers.add(h); |
180 } | 186 } |
181 } | 187 } |
182 flags |= Flag.HasHandler.mask; | 188 flags |= Flag.HasHandler.mask; |
183 } | 189 } |
184 | 190 |
185 mergeOrClone(startBlockBegin, frameState, false); | 191 mergeOrClone(startBlock, frameState); |
186 | 192 |
187 // 3. setup internal state for appending instructions | 193 // 3. setup internal state for appending instructions |
188 lastInstr = startBlockBegin; | 194 lastInstr = startBlockBegin; |
189 lastInstr.appendNext(null); | 195 lastInstr.appendNext(null); |
190 | 196 |
201 syncBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI); | 207 syncBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI); |
202 syncHandler = new BlockBegin(Instruction.SYNCHRONIZATION_ENTRY_BCI, syncBlock.blockID, false, graph); | 208 syncHandler = new BlockBegin(Instruction.SYNCHRONIZATION_ENTRY_BCI, syncBlock.blockID, false, graph); |
203 syncBlock.firstInstruction = syncHandler; | 209 syncBlock.firstInstruction = syncHandler; |
204 markOnWorkList(syncBlock); | 210 markOnWorkList(syncBlock); |
205 | 211 |
212 ExceptionBlock excBlock = new ExceptionBlock(); | |
213 excBlock.startBci = -1; | |
214 excBlock.endBci = -1; | |
215 excBlock.blockID = ir.nextBlockNumber(); | |
216 blockList.add(excBlock); | |
206 ExceptionHandler h = new ExceptionHandler(new CiExceptionHandler(0, rootMethod.code().length, -1, 0, null)); | 217 ExceptionHandler h = new ExceptionHandler(new CiExceptionHandler(0, rootMethod.code().length, -1, 0, null)); |
207 h.setEntryBlock(syncBlock); | 218 h.setEntryBlock(syncBlock); |
208 addExceptionHandler(h); | 219 addExceptionHandler(h); |
209 } else { | 220 } else { |
210 // 4B.1 simply finish the start block | 221 // 4B.1 simply finish the start block |
212 } | 223 } |
213 | 224 |
214 // 5. SKIPPED: look for intrinsics | 225 // 5. SKIPPED: look for intrinsics |
215 | 226 |
216 // 6B.1 do the normal parsing | 227 // 6B.1 do the normal parsing |
217 addToWorkList(blockList[0]); | 228 addToWorkList(blockFromBci[0]); |
218 iterateAllBlocks(); | 229 iterateAllBlocks(); |
219 | 230 |
220 if (syncBlock != null && syncHandler.stateBefore() != null) { | 231 if (syncBlock != null && syncHandler.stateBefore() != null) { |
221 // generate unlocking code if the exception handler is reachable | 232 // generate unlocking code if the exception handler is reachable |
222 fillSyncHandler(rootMethodSynchronizedObject, syncBlock); | 233 fillSyncHandler(rootMethodSynchronizedObject, syncBlock); |
223 } | 234 } |
235 | |
236 // for (Node n : graph.getNodes()) { | |
237 // if (n instanceof FrameState) { | |
238 // boolean delete = false; | |
239 // if (n.usages().size() == 0 && n.predecessors().size() == 0) { | |
240 // delete = true; | |
241 // } | |
242 // if (n.predecessors().size() == 0 && n.usages().size() == 1 && n.usages().get(0) instanceof BlockBegin) { | |
243 // n.usages().get(0).inputs().replace(n, null); | |
244 // delete = true; | |
245 // } | |
246 // if (delete) { | |
247 // n.delete(); | |
248 // System.out.println("deleted framestate"); | |
249 // } | |
250 // } | |
251 // } | |
224 } | 252 } |
225 | 253 |
226 private Block nextBlock(int bci) { | 254 private Block nextBlock(int bci) { |
227 Block block = new Block(); | 255 Block block = new Block(); |
228 block.startBci = bci; | 256 block.startBci = bci; |
258 Goto base = new Goto(target, stateAfter, graph); | 286 Goto base = new Goto(target, stateAfter, graph); |
259 appendWithBCI(base); | 287 appendWithBCI(base); |
260 } | 288 } |
261 | 289 |
262 public void mergeOrClone(Block target, FrameStateAccess newState) { | 290 public void mergeOrClone(Block target, FrameStateAccess newState) { |
263 assert target.firstInstruction instanceof BlockBegin; | 291 Instruction first = target.firstInstruction; |
264 if (target.isLoopHeader) { | 292 int bci = target.startBci; |
265 mergeOrClone(target.firstInstruction, newState, true); | 293 boolean loopHeader = target.isLoopHeader; |
266 } else { | 294 |
267 mergeOrClone(target.firstInstruction, newState, false); | 295 FrameState existingState; |
268 } | 296 if (first instanceof Placeholder) { |
269 } | 297 existingState = ((Placeholder) first).stateBefore(); |
270 | 298 } else { |
271 | 299 assert first instanceof BlockBegin; |
272 private void mergeOrClone(Instruction first, FrameStateAccess stateAfter, boolean loopHeader) { | 300 existingState = ((BlockBegin) first).stateBefore(); |
273 mergeOrClone(first, stateAfter, loopHeader, false); | 301 } |
274 } | 302 |
275 | 303 if (existingState == null) { |
276 private void mergeOrClone(Instruction first, FrameStateAccess stateAfter, boolean loopHeader, boolean blockAppended) { | 304 // copy state because it is modified |
277 if (first instanceof BlockBegin) { | 305 FrameState duplicate = newState.duplicate(bci); |
278 BlockBegin block = (BlockBegin) first; | 306 |
279 FrameState existingState = block.stateBefore(); | 307 // if the block is a loop header, insert all necessary phis |
280 | 308 if (loopHeader) { |
281 if (existingState == null) { | 309 assert first instanceof BlockBegin; |
282 // copy state because it is modified | 310 insertLoopPhis((BlockBegin) first, duplicate); |
283 FrameState duplicate = stateAfter.duplicate(block.bci()); | 311 ((BlockBegin) first).setStateBefore(duplicate); |
284 | 312 } else { |
285 // if the block is a loop header, insert all necessary phis | 313 if (first instanceof Placeholder) { |
286 if (loopHeader) { | 314 ((Placeholder) first).setStateBefore(duplicate); |
287 insertLoopPhis(block, duplicate); | 315 } else { |
316 ((BlockBegin) first).setStateBefore(duplicate); | |
288 } | 317 } |
289 | 318 } |
290 block.setStateBefore(duplicate); | 319 } else { |
291 } else { | 320 |
292 if (!C1XOptions.AssumeVerifiedBytecode && !existingState.isCompatibleWith(stateAfter)) { | 321 if (!C1XOptions.AssumeVerifiedBytecode && !existingState.isCompatibleWith(newState)) { |
293 // stacks or locks do not match--bytecodes would not verify | 322 // stacks or locks do not match--bytecodes would not verify |
294 throw new CiBailout("stack or locks do not match"); | 323 throw new CiBailout("stack or locks do not match"); |
295 } | 324 } |
296 | 325 |
297 assert existingState.localsSize() == stateAfter.localsSize(); | 326 assert existingState.localsSize() == newState.localsSize(); |
298 assert existingState.stackSize() == stateAfter.stackSize(); | 327 assert existingState.stackSize() == newState.stackSize(); |
299 | 328 |
300 existingState.merge(block, stateAfter, blockAppended); | 329 existingState.merge((BlockBegin) first, newState); |
301 } | 330 } |
302 } else { | |
303 assert false; | |
304 } | |
305 | |
306 | |
307 | |
308 | 331 |
309 for (int j = 0; j < frameState.localsSize() + frameState.stackSize(); ++j) { | 332 for (int j = 0; j < frameState.localsSize() + frameState.stackSize(); ++j) { |
310 if (frameState.valueAt(j) != null) { | 333 if (frameState.valueAt(j) != null) { |
311 assert !frameState.valueAt(j).isDeleted(); | 334 assert !frameState.valueAt(j).isDeleted(); |
312 } | 335 } |
354 private void handleException(Instruction x, int bci) { | 377 private void handleException(Instruction x, int bci) { |
355 if (!hasHandler()) { | 378 if (!hasHandler()) { |
356 return; | 379 return; |
357 } | 380 } |
358 | 381 |
359 ArrayList<ExceptionHandler> exceptionHandlers = new ArrayList<ExceptionHandler>(); | |
360 | |
361 assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci"; | 382 assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci"; |
362 | 383 |
384 ExceptionHandler firstHandler = null; | |
363 // join with all potential exception handlers | 385 // join with all potential exception handlers |
364 if (this.exceptionHandlers != null) { | 386 if (this.exceptionHandlers != null) { |
365 for (ExceptionHandler handler : this.exceptionHandlers) { | 387 for (ExceptionHandler handler : this.exceptionHandlers) { |
366 // if the handler covers this bytecode index, add it to the list | 388 // if the handler covers this bytecode index, add it to the list |
367 if (handler.covers(bci)) { | 389 if (handler.covers(bci)) { |
368 ExceptionHandler newHandler = addExceptionHandler(handler, frameState); | 390 firstHandler = new ExceptionHandler(handler); |
369 exceptionHandlers.add(newHandler); | 391 break; |
370 | 392 } |
371 // stop when reaching catch all | 393 } |
372 if (handler.isCatchAll()) { | 394 } |
395 | |
396 if (firstHandler != null) { | |
397 compilation.setHasExceptionHandlers(); | |
398 | |
399 Block dispatchBlock = null; | |
400 for (Block block : blockList) { | |
401 if (block instanceof ExceptionBlock) { | |
402 ExceptionBlock excBlock = (ExceptionBlock) block; | |
403 if (excBlock.handler == firstHandler.handler) { | |
404 dispatchBlock = block; | |
373 break; | 405 break; |
374 } | 406 } |
375 } | 407 } |
376 } | 408 } |
377 } | 409 // if there's no dispatch block then the catch block needs to be a catch all |
378 | 410 if (dispatchBlock == null) { |
379 if (!exceptionHandlers.isEmpty()) { | 411 assert firstHandler.isCatchAll(); |
380 Instruction successor; | 412 dispatchBlock = firstHandler.entryBlock(); |
381 | 413 } |
382 ArrayList<BlockBegin> newBlocks = new ArrayList<BlockBegin>(); | |
383 | |
384 int current = exceptionHandlers.size() - 1; | |
385 if (exceptionHandlers.get(current).isCatchAll()) { | |
386 successor = createTarget(exceptionHandlers.get(current).entryBlock(), null); | |
387 current--; | |
388 } else { | |
389 if (unwindBlock == null) { | |
390 unwindBlock = new BlockBegin(bci, ir.nextBlockNumber(), false, graph); | |
391 Unwind unwind = new Unwind(null, graph); | |
392 unwindBlock.appendNext(unwind); | |
393 } | |
394 successor = unwindBlock; | |
395 } | |
396 | |
397 for (; current >= 0; current--) { | |
398 ExceptionHandler handler = exceptionHandlers.get(current); | |
399 | |
400 BlockBegin newSucc = null; | |
401 for (Node pred : successor.predecessors()) { | |
402 if (pred instanceof ExceptionDispatch) { | |
403 ExceptionDispatch dispatch = (ExceptionDispatch) pred; | |
404 if (dispatch.handler().handler == handler.handler) { | |
405 newSucc = dispatch.begin(); | |
406 break; | |
407 } | |
408 } | |
409 } | |
410 if (newSucc != null) { | |
411 successor = newSucc; | |
412 } else { | |
413 BlockBegin dispatchEntry = new BlockBegin(handler.handlerBCI(), ir.nextBlockNumber(), false, graph); | |
414 | |
415 if (handler.handler.catchType().isResolved()) { | |
416 Instruction entry = createTarget(handler.entryBlock(), null); | |
417 ExceptionDispatch end = new ExceptionDispatch(null, entry, null, handler, null, graph); | |
418 end.setBlockSuccessor(0, successor); | |
419 dispatchEntry.appendNext(end); | |
420 } else { | |
421 Deoptimize deopt = new Deoptimize(graph); | |
422 dispatchEntry.appendNext(deopt); | |
423 Goto end = new Goto(successor, null, graph); | |
424 deopt.appendNext(end); | |
425 } | |
426 | |
427 newBlocks.add(dispatchEntry); | |
428 successor = dispatchEntry; | |
429 } | |
430 } | |
431 | |
432 FrameState entryState = frameState.duplicateWithEmptyStack(bci); | 414 FrameState entryState = frameState.duplicateWithEmptyStack(bci); |
433 | 415 |
434 BlockBegin entry = new BlockBegin(bci, ir.nextBlockNumber(), false, graph); | 416 BlockBegin entry = new BlockBegin(bci, ir.nextBlockNumber(), false, graph); |
435 entry.setStateBefore(entryState); | 417 entry.setStateBefore(entryState); |
436 ExceptionObject exception = new ExceptionObject(graph); | 418 ExceptionObject exception = new ExceptionObject(graph); |
437 entry.appendNext(exception); | 419 entry.appendNext(exception); |
438 FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, exception); | 420 FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, exception); |
421 | |
422 Instruction successor = createTarget(dispatchBlock, stateWithException); | |
439 BlockEnd end = new Goto(successor, stateWithException, graph); | 423 BlockEnd end = new Goto(successor, stateWithException, graph); |
440 exception.appendNext(end); | 424 exception.appendNext(end); |
441 | 425 |
442 if (x instanceof Invoke) { | 426 if (x instanceof Invoke) { |
443 ((Invoke) x).setExceptionEdge(entry); | 427 ((Invoke) x).setExceptionEdge(entry); |
444 } else { | 428 } else { |
445 ((Throw) x).setExceptionEdge(entry); | 429 ((Throw) x).setExceptionEdge(entry); |
446 } | 430 } |
447 | 431 } |
448 updateDispatchChain(end.blockSuccessor(0), stateWithException, bci); | |
449 } | |
450 } | |
451 | |
452 private void updateDispatchChain(BlockBegin dispatchEntry, FrameStateAccess state, int bci) { | |
453 FrameState oldState = dispatchEntry.stateBefore(); | |
454 if (oldState != null && dispatchEntry.predecessors().size() == 1) { | |
455 dispatchEntry.setStateBefore(null); | |
456 } | |
457 mergeOrClone(dispatchEntry, state, false, true); | |
458 FrameState mergedState = dispatchEntry.stateBefore(); | |
459 | |
460 if (dispatchEntry.next() instanceof ExceptionDispatch) { | |
461 // ordinary dispatch handler | |
462 ExceptionDispatch dispatch = (ExceptionDispatch) dispatchEntry.next(); | |
463 dispatch.setStateAfter(mergedState.duplicate(bci)); | |
464 dispatch.setException(mergedState.stackAt(0)); | |
465 dispatch.catchSuccessor().setStateBefore(mergedState.duplicate(bci)); | |
466 updateDispatchChain(dispatch.otherSuccessor(), mergedState, bci); | |
467 } else if (dispatchEntry.next() instanceof Deoptimize) { | |
468 // deoptimizing handler | |
469 dispatchEntry.end().setStateAfter(mergedState.duplicate(bci)); | |
470 updateDispatchChain(dispatchEntry.end().blockSuccessor(0), mergedState, bci); | |
471 } else if (dispatchEntry.next() instanceof Unwind) { | |
472 // unwind handler | |
473 Unwind unwind = (Unwind) dispatchEntry.next(); | |
474 unwind.setStateAfter(mergedState.duplicate(bci)); | |
475 unwind.setException(mergedState.stackAt(0)); | |
476 } else { | |
477 // synchronization or default exception handler, nothing to do | |
478 } | |
479 } | |
480 | |
481 /** | |
482 * Adds an exception handler to the {@linkplain BlockBegin#exceptionHandlerBlocks() list} | |
483 * of exception handlers for the {@link #curBlock current block}. | |
484 */ | |
485 private ExceptionHandler addExceptionHandler(ExceptionHandler handler, FrameStateAccess curState) { | |
486 compilation.setHasExceptionHandlers(); | |
487 | |
488 BlockMap.Block entry = handler.entryBlock(); | |
489 | |
490 // clone exception handler | |
491 ExceptionHandler newHandler = new ExceptionHandler(handler); | |
492 | |
493 // fill in exception handler subgraph lazily | |
494 if (!isVisited(entry)) { | |
495 if (handler.handlerBCI() != Instruction.SYNCHRONIZATION_ENTRY_BCI) { | |
496 addToWorkList(entry); | |
497 } | |
498 } else { | |
499 // This will occur for exception handlers that cover themselves. This code | |
500 // pattern is generated by javac for synchronized blocks. See the following | |
501 // for why this change to javac was made: | |
502 // | |
503 // http://www.cs.arizona.edu/projects/sumatra/hallofshame/java-async-race.html | |
504 } | |
505 return newHandler; | |
506 } | 432 } |
507 | 433 |
508 private void genLoadConstant(int cpi) { | 434 private void genLoadConstant(int cpi) { |
509 Object con = constantPool().lookupConstant(cpi); | 435 Object con = constantPool().lookupConstant(cpi); |
510 | 436 |
1122 } | 1048 } |
1123 | 1049 |
1124 return x; | 1050 return x; |
1125 } | 1051 } |
1126 | 1052 |
1127 private Instruction blockAtOrNull(int bci) { | |
1128 return blockList[bci] != null ? blockList[bci].firstInstruction : null; | |
1129 } | |
1130 | |
1131 private Instruction blockAt(int bci) { | |
1132 Instruction result = blockAtOrNull(bci); | |
1133 assert result != null : "Expected a block to begin at " + bci; | |
1134 return result; | |
1135 } | |
1136 | |
1137 private Instruction createTargetAt(int bci, FrameStateAccess stateAfter) { | 1053 private Instruction createTargetAt(int bci, FrameStateAccess stateAfter) { |
1138 return createTarget(blockList[bci], stateAfter); | 1054 return createTarget(blockFromBci[bci], stateAfter); |
1139 } | 1055 } |
1140 | 1056 |
1141 private Instruction createTarget(Block block, FrameStateAccess stateAfter) { | 1057 private Instruction createTarget(Block block, FrameStateAccess stateAfter) { |
1058 assert block != null && stateAfter != null; | |
1142 if (block.firstInstruction == null) { | 1059 if (block.firstInstruction == null) { |
1143 BlockBegin blockBegin = new BlockBegin(block.startBci, block.blockID, block.isLoopHeader, graph); | 1060 // if (block.isLoopHeader) { |
1144 block.firstInstruction = blockBegin; | 1061 block.firstInstruction = new BlockBegin(block.startBci, block.blockID, block.isLoopHeader, graph); |
1145 } | 1062 // } else { |
1146 if (stateAfter != null) { | 1063 // block.firstInstruction = new Placeholder(graph); |
1147 mergeOrClone(block, stateAfter); | 1064 // } |
1148 } | 1065 } |
1066 mergeOrClone(block, stateAfter); | |
1149 addToWorkList(block); | 1067 addToWorkList(block); |
1150 return block.firstInstruction; | 1068 return block.firstInstruction; |
1151 } | 1069 } |
1152 | 1070 |
1153 private Value synchronizedObject(FrameStateAccess state, RiMethod target) { | 1071 private Value synchronizedObject(FrameStateAccess state, RiMethod target) { |
1207 // now parse the block | 1125 // now parse the block |
1208 frameState.initializeFrom(((BlockBegin) block.firstInstruction).stateBefore()); | 1126 frameState.initializeFrom(((BlockBegin) block.firstInstruction).stateBefore()); |
1209 lastInstr = block.firstInstruction; | 1127 lastInstr = block.firstInstruction; |
1210 assert block.firstInstruction.next() == null; | 1128 assert block.firstInstruction.next() == null; |
1211 | 1129 |
1212 iterateBytecodesForBlock(block); | 1130 if (block instanceof ExceptionBlock) { |
1131 createExceptionDispatch((ExceptionBlock) block); | |
1132 } else { | |
1133 iterateBytecodesForBlock(block); | |
1134 } | |
1135 } | |
1136 } | |
1137 } | |
1138 | |
1139 private void createExceptionDispatch(ExceptionBlock block) { | |
1140 if (block.handler == null) { | |
1141 assert frameState.stackSize() == 1 : "only exception object expected on stack, actual size: " + frameState.stackSize(); | |
1142 if (Modifier.isSynchronized(method().accessFlags())) { | |
1143 // unlock before exiting the method | |
1144 int lockNumber = frameState.locksSize() - 1; | |
1145 MonitorAddress lockAddress = null; | |
1146 if (compilation.runtime.sizeOfBasicObjectLock() != 0) { | |
1147 lockAddress = new MonitorAddress(lockNumber, graph); | |
1148 append(lockAddress); | |
1149 } | |
1150 append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, graph)); | |
1151 frameState.unlock(); | |
1152 } | |
1153 append(new Unwind(frameState.apop(), graph)); | |
1154 } else { | |
1155 assert frameState.stackSize() == 1; | |
1156 | |
1157 if (block.handler.catchType().isResolved()) { | |
1158 Instruction catchSuccessor = createTarget(block.handlerBlock, frameState); | |
1159 Instruction nextDispatch = createTarget(block.next, frameState); | |
1160 append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), frameState.duplicate(bci()), graph)); | |
1161 } else { | |
1162 Deoptimize deopt = new Deoptimize(graph); | |
1163 deopt.setMessage("unresolved " + block.handler.catchType().name()); | |
1164 append(deopt); | |
1165 Instruction nextDispatch = createTarget(block.next, frameState); | |
1166 append(new Goto(nextDispatch, frameState.duplicate(bci()), graph)); | |
1213 } | 1167 } |
1214 } | 1168 } |
1215 } | 1169 } |
1216 | 1170 |
1217 private BlockEnd iterateBytecodesForBlock(Block block) { | 1171 private BlockEnd iterateBytecodesForBlock(Block block) { |
1223 int endBCI = stream.endBCI(); | 1177 int endBCI = stream.endBCI(); |
1224 boolean blockStart = true; | 1178 boolean blockStart = true; |
1225 | 1179 |
1226 int bci = block.startBci; | 1180 int bci = block.startBci; |
1227 while (bci < endBCI) { | 1181 while (bci < endBCI) { |
1228 Block nextBlock = blockList[bci]; | 1182 Block nextBlock = blockFromBci[bci]; |
1229 if (nextBlock != null && nextBlock != block) { | 1183 if (nextBlock != null && nextBlock != block) { |
1230 // we fell through to the next block, add a goto and break | 1184 // we fell through to the next block, add a goto and break |
1231 Instruction next = createTarget(nextBlock, frameState); | 1185 Instruction next = createTarget(nextBlock, frameState); |
1232 end = new Goto(next, null, graph); | 1186 end = new Goto(next, null, graph); |
1233 lastInstr = lastInstr.appendNext(end); | 1187 lastInstr = lastInstr.appendNext(end); |
1261 } | 1215 } |
1262 | 1216 |
1263 // connect to begin and set state | 1217 // connect to begin and set state |
1264 // NOTE that inlining may have changed the block we are parsing | 1218 // NOTE that inlining may have changed the block we are parsing |
1265 assert end != null : "end should exist after iterating over bytecodes"; | 1219 assert end != null : "end should exist after iterating over bytecodes"; |
1266 FrameState stateAtEnd = frameState.create(bci()); | 1220 end.setStateAfter(frameState.create(bci())); |
1267 end.setStateAfter(stateAtEnd); | |
1268 return end; | 1221 return end; |
1269 } | 1222 } |
1270 | 1223 |
1271 private void traceState() { | 1224 private void traceState() { |
1272 if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) { | 1225 if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) { |