Mercurial > hg > graal-jvmci-8
comparison graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java @ 2707:7ed72769d51a
exception handling related changes:
* changed blockPredecessors to list of Instructions, instead of Blocks
* removed explicit predecessor management in BlockBegin, now using predecessors from Graph structure
* replaced generated LIR exception entries with exception dispatch chains in IR
* added Unwind and ExceptionDispatch instructions
* removed ExceptionEntry flag in BlockBegin and all code depending on it
* removed exceptionHandler list from Instruction, replaced by exception Edge on Invoke and Throw
* replaced list of ExceptionHandlers with single exception edge in debug info
misc:
* changed GraphvizPrinter layout (smaller ports on large nodes)
* removed defunct run config
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Wed, 18 May 2011 18:09:20 +0200 |
parents | 0ea5f12e873a |
children | 4272b7af2d17 |
comparison
equal
deleted
inserted
replaced
2677:0ea5f12e873a | 2707:7ed72769d51a |
---|---|
69 return false; | 69 return false; |
70 } | 70 } |
71 | 71 |
72 public void setEnd(BlockEnd end) { | 72 public void setEnd(BlockEnd end) { |
73 assert end != null; | 73 assert end != null; |
74 BlockEnd old = this.end(); | 74 successors().set(super.successorCount() + SUCCESSOR_END, end); |
75 if (old != end) { | |
76 if (old != null) { | |
77 // disconnect this block from its current successors | |
78 for (BlockBegin s : old.blockSuccessors()) { | |
79 s.blockPredecessors().remove(this.end()); | |
80 } | |
81 } | |
82 successors().set(super.successorCount() + SUCCESSOR_END, end); | |
83 for (BlockBegin s : end.blockSuccessors()) { | |
84 s.addPredecessor(end); | |
85 } | |
86 } | |
87 } | 75 } |
88 | 76 |
89 private static final List<BlockBegin> NO_HANDLERS = Collections.emptyList(); | 77 private static final List<BlockBegin> NO_HANDLERS = Collections.emptyList(); |
90 | 78 |
91 /** | 79 /** |
92 * An enumeration of flags for block entries indicating various things. | 80 * An enumeration of flags for block entries indicating various things. |
93 */ | 81 */ |
94 public enum BlockFlag { | 82 public enum BlockFlag { |
95 StandardEntry, | 83 StandardEntry, |
96 ExceptionEntry, | |
97 SubroutineEntry, | 84 SubroutineEntry, |
98 BackwardBranchTarget, | 85 BackwardBranchTarget, |
99 IsOnWorkList, | 86 IsOnWorkList, |
100 WasVisited, | 87 WasVisited, |
101 DefaultExceptionHandler, | 88 DefaultExceptionHandler, |
115 /** | 102 /** |
116 * Denotes the current set of {@link BlockBegin.BlockFlag} settings. | 103 * Denotes the current set of {@link BlockBegin.BlockFlag} settings. |
117 */ | 104 */ |
118 private int blockFlags; | 105 private int blockFlags; |
119 | 106 |
120 /** | |
121 * The {@link BlockBegin} nodes for which this node is a successor. | |
122 */ | |
123 private final List<BlockEnd> predecessors; | |
124 | |
125 private int depthFirstNumber; | 107 private int depthFirstNumber; |
126 private int linearScanNumber; | 108 private int linearScanNumber; |
127 private int loopDepth; | 109 private int loopDepth; |
128 private int loopIndex; | 110 private int loopIndex; |
129 | 111 |
130 private BlockBegin dominator; | 112 private BlockBegin dominator; |
131 private List<BlockBegin> exceptionHandlerBlocks; | |
132 private List<FrameState> exceptionHandlerStates; | |
133 | 113 |
134 // LIR block | 114 // LIR block |
135 public LIRBlock lirBlock; | 115 public LIRBlock lirBlock; |
136 | 116 |
137 /** | 117 /** |
143 public BlockBegin(int bci, int blockID, Graph graph) { | 123 public BlockBegin(int bci, int blockID, Graph graph) { |
144 super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); | 124 super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); |
145 this.blockID = blockID; | 125 this.blockID = blockID; |
146 depthFirstNumber = -1; | 126 depthFirstNumber = -1; |
147 linearScanNumber = -1; | 127 linearScanNumber = -1; |
148 predecessors = new ArrayList<BlockEnd>(2); | |
149 loopIndex = -1; | 128 loopIndex = -1; |
150 setBCI(bci); | 129 setBCI(bci); |
151 } | 130 } |
152 | 131 |
153 /** | 132 /** |
154 * Gets the list of predecessors of this block. | 133 * Gets the list of predecessors of this block. |
155 * @return the predecessor list | 134 * @return the predecessor list |
156 */ | 135 */ |
157 public List<BlockEnd> blockPredecessors() { | 136 @SuppressWarnings({ "unchecked", "rawtypes" }) |
158 // return Collections.unmodifiableList(predecessors); | 137 public List<Instruction> blockPredecessors() { |
159 return predecessors; | 138 if (predecessors().size() == 1 && predecessors().get(0) == graph().root()) { |
139 return Collections.EMPTY_LIST; | |
140 } else { | |
141 return (List) Collections.unmodifiableList(predecessors()); | |
142 } | |
160 } | 143 } |
161 | 144 |
162 /** | 145 /** |
163 * Gets the dominator of this block. | 146 * Gets the dominator of this block. |
164 * @return the dominator block | 147 * @return the dominator block |
203 * Gets the loop index of this block. | 186 * Gets the loop index of this block. |
204 * @return the loop index | 187 * @return the loop index |
205 */ | 188 */ |
206 public int loopIndex() { | 189 public int loopIndex() { |
207 return loopIndex; | 190 return loopIndex; |
208 } | |
209 | |
210 /** | |
211 * Gets the exception handlers that cover one or more instructions of this basic block. | |
212 * | |
213 * @return the exception handlers | |
214 */ | |
215 public List<BlockBegin> exceptionHandlerBlocks() { | |
216 return exceptionHandlerBlocks == null ? NO_HANDLERS : exceptionHandlerBlocks; | |
217 } | |
218 | |
219 public List<FrameState> exceptionHandlerStates() { | |
220 return exceptionHandlerStates; | |
221 } | 191 } |
222 | 192 |
223 public void setDepthFirstNumber(int depthFirstNumber) { | 193 public void setDepthFirstNumber(int depthFirstNumber) { |
224 assert depthFirstNumber >= 0; | 194 assert depthFirstNumber >= 0; |
225 this.depthFirstNumber = depthFirstNumber; | 195 this.depthFirstNumber = depthFirstNumber; |
286 queue.offer(this); | 256 queue.offer(this); |
287 mark.put(this, this); | 257 mark.put(this, this); |
288 BlockBegin block; | 258 BlockBegin block; |
289 while ((block = queue.poll()) != null) { | 259 while ((block = queue.poll()) != null) { |
290 closure.apply(block); | 260 closure.apply(block); |
291 queueBlocks(queue, block.exceptionHandlerBlocks(), mark); | 261 |
262 Instruction inst = block; | |
263 ArrayList<BlockBegin> excBlocks = new ArrayList<BlockBegin>(); | |
264 while (inst != null) { | |
265 if (inst instanceof Invoke) { | |
266 excBlocks.add(((Invoke) inst).exceptionEdge()); | |
267 } else if (inst instanceof Throw) { | |
268 excBlocks.add(((Throw) inst).exceptionEdge()); | |
269 } | |
270 inst = inst.next(); | |
271 } | |
272 while (excBlocks.remove(null)) { | |
273 // nothing | |
274 } | |
275 if (excBlocks.size() > 0) { | |
276 queueBlocks(queue, excBlocks, mark); | |
277 } | |
278 | |
292 queueBlocks(queue, block.end().blockSuccessors(), mark); | 279 queueBlocks(queue, block.end().blockSuccessors(), mark); |
293 if (predecessors) { | 280 if (predecessors) { |
294 queueBlockEnds(queue, block.predecessors, mark); | 281 queueBlockEnds(queue, block.blockPredecessors(), mark); |
295 } | 282 } |
296 } | 283 } |
297 } | 284 } |
298 | 285 |
299 private void queueBlocks(LinkedList<BlockBegin> queue, List<BlockBegin> list, IdentityHashMap<BlockBegin, BlockBegin> mark) { | 286 private void queueBlocks(LinkedList<BlockBegin> queue, List<BlockBegin> list, IdentityHashMap<BlockBegin, BlockBegin> mark) { |
305 } | 292 } |
306 } | 293 } |
307 } | 294 } |
308 } | 295 } |
309 | 296 |
310 private void queueBlockEnds(LinkedList<BlockBegin> queue, List<BlockEnd> list, IdentityHashMap<BlockBegin, BlockBegin> mark) { | 297 private void queueBlockEnds(LinkedList<BlockBegin> queue, List<Instruction> list, IdentityHashMap<BlockBegin, BlockBegin> mark) { |
311 if (list != null) { | 298 if (list != null) { |
312 for (BlockEnd end : list) { | 299 for (Instruction end : list) { |
313 BlockBegin b = end.begin(); | 300 BlockBegin b = end.block(); |
314 if (!mark.containsKey(b)) { | 301 if (!mark.containsKey(b)) { |
315 queue.offer(b); | 302 queue.offer(b); |
316 mark.put(b, b); | 303 mark.put(b, b); |
317 } | 304 } |
318 } | 305 } |
322 private void iterate(IdentityHashMap<BlockBegin, BlockBegin> mark, BlockClosure closure) { | 309 private void iterate(IdentityHashMap<BlockBegin, BlockBegin> mark, BlockClosure closure) { |
323 if (!mark.containsKey(this)) { | 310 if (!mark.containsKey(this)) { |
324 mark.put(this, this); | 311 mark.put(this, this); |
325 closure.apply(this); | 312 closure.apply(this); |
326 BlockEnd e = end(); | 313 BlockEnd e = end(); |
327 if (exceptionHandlerBlocks != null) { | 314 |
328 iterateReverse(mark, closure, exceptionHandlerBlocks); | 315 Instruction inst = this; |
329 } | 316 ArrayList<BlockBegin> excBlocks = new ArrayList<BlockBegin>(); |
317 while (inst != null) { | |
318 if (inst instanceof Invoke) { | |
319 excBlocks.add(((Invoke) inst).exceptionEdge()); | |
320 } else if (inst instanceof Throw) { | |
321 excBlocks.add(((Throw) inst).exceptionEdge()); | |
322 } | |
323 inst = inst.next(); | |
324 } | |
325 while (excBlocks.remove(null)) { | |
326 // nothing | |
327 } | |
328 if (excBlocks.size() > 0) { | |
329 iterateReverse(mark, closure, excBlocks); | |
330 } | |
331 | |
332 // if (exceptionHandlerBlocks != null) { | |
333 // iterateReverse(mark, closure, exceptionHandlerBlocks); | |
334 // } | |
330 assert e != null : "block must have block end"; | 335 assert e != null : "block must have block end"; |
331 iterateReverse(mark, closure, e.blockSuccessors()); | 336 iterateReverse(mark, closure, e.blockSuccessors()); |
332 } | 337 } |
333 } | 338 } |
334 | 339 |
335 private void iterateReverse(IdentityHashMap<BlockBegin, BlockBegin> mark, BlockClosure closure, List<BlockBegin> list) { | 340 private void iterateReverse(IdentityHashMap<BlockBegin, BlockBegin> mark, BlockClosure closure, List<BlockBegin> list) { |
336 for (int i = list.size() - 1; i >= 0; i--) { | 341 for (int i = list.size() - 1; i >= 0; i--) { |
337 list.get(i).iterate(mark, closure); | 342 list.get(i).iterate(mark, closure); |
338 } | |
339 } | |
340 | |
341 /** | |
342 * Adds an exception handler that covers one or more instructions in this block. | |
343 * | |
344 * @param handler the entry block for the exception handler to add | |
345 */ | |
346 public void addExceptionHandler(BlockBegin handler) { | |
347 assert handler != null && handler.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry); | |
348 if (exceptionHandlerBlocks == null) { | |
349 exceptionHandlerBlocks = new ArrayList<BlockBegin>(3); | |
350 exceptionHandlerBlocks.add(handler); | |
351 } else if (!exceptionHandlerBlocks.contains(handler)) { | |
352 exceptionHandlerBlocks.add(handler); | |
353 } | |
354 } | |
355 | |
356 /** | |
357 * Adds a frame state that merges into the exception handler whose entry is this block. | |
358 * | |
359 * @param state the frame state at an instruction that raises an exception that can be caught by the exception | |
360 * handler represented by this block | |
361 * @return the index of {@code state} in the list of frame states merging at this block (i.e. the frames states for | |
362 * all instruction throwing an exception caught by this exception handler) | |
363 */ | |
364 public int addExceptionState(FrameState state) { | |
365 assert checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry); | |
366 if (exceptionHandlerStates == null) { | |
367 exceptionHandlerStates = new ArrayList<FrameState>(4); | |
368 } | |
369 exceptionHandlerStates.add(state); | |
370 return exceptionHandlerStates.size() - 1; | |
371 } | |
372 | |
373 /** | |
374 * Add a predecessor to this block. | |
375 * @param pred the predecessor to add | |
376 */ | |
377 public void addPredecessor(BlockEnd pred) { | |
378 assert pred != null; | |
379 predecessors.add(pred); | |
380 } | |
381 | |
382 /** | |
383 * Removes all occurrences of the specified block from the predecessor list of this block. | |
384 * @param pred the predecessor to remove | |
385 */ | |
386 public void removePredecessor(BlockEnd pred) { | |
387 while (predecessors.remove(pred)) { | |
388 // the block may appear multiple times in the list | |
389 // XXX: this is not very efficient, consider Util.removeAllFromList | |
390 } | 343 } |
391 } | 344 } |
392 | 345 |
393 @Override | 346 @Override |
394 public void accept(ValueVisitor v) { | 347 public void accept(ValueVisitor v) { |
407 | 360 |
408 // copy state because it is modified | 361 // copy state because it is modified |
409 FrameState duplicate = newState.duplicate(bci()); | 362 FrameState duplicate = newState.duplicate(bci()); |
410 assert duplicate.bci == bci() : "duplicate.bci=" + duplicate.bci + " my bci=" + bci(); | 363 assert duplicate.bci == bci() : "duplicate.bci=" + duplicate.bci + " my bci=" + bci(); |
411 | 364 |
412 if (C1XOptions.UseStackMapTableLiveness) { | 365 if (C1XOptions.UseStackMapTableLiveness && method != null) { |
413 // if a liveness map is available, use it to invalidate dead locals | 366 // if a liveness map is available, use it to invalidate dead locals |
414 CiBitMap[] livenessMap = method.livenessMap(); | 367 CiBitMap[] livenessMap = method.livenessMap(); |
415 if (livenessMap != null && bci() >= 0) { | 368 if (livenessMap != null && bci() >= 0) { |
416 assert bci() < livenessMap.length; | 369 assert bci() < livenessMap.length; |
417 CiBitMap liveness = livenessMap[bci()]; | 370 CiBitMap liveness = livenessMap[bci()]; |
487 | 440 |
488 public void setCriticalEdgeSplit(boolean value) { | 441 public void setCriticalEdgeSplit(boolean value) { |
489 setBlockFlag(BlockFlag.CriticalEdgeSplit, value); | 442 setBlockFlag(BlockFlag.CriticalEdgeSplit, value); |
490 } | 443 } |
491 | 444 |
492 public boolean isExceptionEntry() { | |
493 return checkBlockFlag(BlockFlag.ExceptionEntry); | |
494 } | |
495 | |
496 public void setExceptionEntry() { | |
497 setBlockFlag(BlockFlag.ExceptionEntry); | |
498 } | |
499 | |
500 public boolean isSubroutineEntry() { | 445 public boolean isSubroutineEntry() { |
501 return checkBlockFlag(BlockFlag.SubroutineEntry); | 446 return checkBlockFlag(BlockFlag.SubroutineEntry); |
502 } | 447 } |
503 | 448 |
504 public void setSubroutineEntry() { | 449 public void setSubroutineEntry() { |
554 } | 499 } |
555 | 500 |
556 public void copyBlockFlags(BlockBegin other) { | 501 public void copyBlockFlags(BlockBegin other) { |
557 copyBlockFlag(other, BlockBegin.BlockFlag.ParserLoopHeader); | 502 copyBlockFlag(other, BlockBegin.BlockFlag.ParserLoopHeader); |
558 copyBlockFlag(other, BlockBegin.BlockFlag.SubroutineEntry); | 503 copyBlockFlag(other, BlockBegin.BlockFlag.SubroutineEntry); |
559 copyBlockFlag(other, BlockBegin.BlockFlag.ExceptionEntry); | |
560 copyBlockFlag(other, BlockBegin.BlockFlag.WasVisited); | 504 copyBlockFlag(other, BlockBegin.BlockFlag.WasVisited); |
561 } | 505 } |
562 | 506 |
563 @Override | 507 @Override |
564 public String toString() { | 508 public String toString() { |
617 /** | 561 /** |
618 * Get the number of predecessors. | 562 * Get the number of predecessors. |
619 * @return the number of predecessors | 563 * @return the number of predecessors |
620 */ | 564 */ |
621 public int numberOfPreds() { | 565 public int numberOfPreds() { |
622 // assert predecessors.size() == predecessors().size(); | 566 // ignore the graph root |
623 return predecessors.size(); | 567 if (predecessors().size() == 1 && predecessors().get(0) == graph().root()) { |
568 return 0; | |
569 } else { | |
570 return predecessors().size(); | |
571 } | |
624 } | 572 } |
625 | 573 |
626 /** | 574 /** |
627 * @return the label associated with the block, used by the LIR | 575 * @return the label associated with the block, used by the LIR |
628 */ | 576 */ |
643 lirBlock = new LIRBlock(); | 591 lirBlock = new LIRBlock(); |
644 } | 592 } |
645 return lirBlock; | 593 return lirBlock; |
646 } | 594 } |
647 | 595 |
648 public int exceptionHandlerPco() { | 596 public int blockEntryPco() { |
649 return lirBlock == null ? 0 : lirBlock.exceptionHandlerPCO; | 597 return lirBlock == null ? 0 : lirBlock.blockEntryPco; |
650 } | 598 } |
651 | 599 |
652 public void setExceptionHandlerPco(int codeOffset) { | 600 public void setBlockEntryPco(int codeOffset) { |
653 lirBlock().exceptionHandlerPCO = codeOffset; | 601 lirBlock().blockEntryPco = codeOffset; |
654 } | 602 } |
655 | 603 |
656 public int numberOfExceptionHandlers() { | 604 public Instruction predAt(int j) { |
657 return exceptionHandlerBlocks == null ? 0 : exceptionHandlerBlocks.size(); | 605 return (Instruction) predecessors().get(j); |
658 } | |
659 | |
660 public BlockBegin exceptionHandlerAt(int i) { | |
661 return exceptionHandlerBlocks.get(i); | |
662 } | |
663 | |
664 public BlockEnd predAt(int j) { | |
665 // assert predecessors.get(j) == predecessors().get(j); | |
666 return predecessors.get(j); | |
667 } | 606 } |
668 | 607 |
669 public int firstLirInstructionId() { | 608 public int firstLirInstructionId() { |
670 return lirBlock.firstLirInstructionID; | 609 return lirBlock.firstLirInstructionID; |
671 } | 610 } |
680 | 619 |
681 public void setLastLirInstructionId(int lastLirInstructionId) { | 620 public void setLastLirInstructionId(int lastLirInstructionId) { |
682 lirBlock.lastLirInstructionID = lastLirInstructionId; | 621 lirBlock.lastLirInstructionID = lastLirInstructionId; |
683 } | 622 } |
684 | 623 |
685 public boolean isPredecessor(BlockEnd block) { | 624 public boolean isPredecessor(Instruction block) { |
686 // assert predecessors.contains(block) == predecessors().contains(block); | 625 return predecessors().contains(block); |
687 return predecessors.contains(block); | |
688 } | 626 } |
689 | 627 |
690 public void printWithoutPhis(LogStream out) { | 628 public void printWithoutPhis(LogStream out) { |
691 // print block id | 629 // print block id |
692 BlockEnd end = end(); | 630 BlockEnd end = end(); |
693 out.print("B").print(blockID).print(" "); | 631 out.print("B").print(blockID).print(" "); |
694 | 632 |
695 // print flags | 633 // print flags |
696 StringBuilder sb = new StringBuilder(8); | 634 StringBuilder sb = new StringBuilder(8); |
697 if (isExceptionEntry()) { | |
698 sb.append('E'); | |
699 } | |
700 if (isSubroutineEntry()) { | 635 if (isSubroutineEntry()) { |
701 sb.append('s'); | 636 sb.append('s'); |
702 } | 637 } |
703 if (isParserLoopHeader()) { | 638 if (isParserLoopHeader()) { |
704 sb.append("LH"); | 639 sb.append("LH"); |
721 out.print(" ."); | 656 out.print(" ."); |
722 for (BlockBegin successor : end.blockSuccessors()) { | 657 for (BlockBegin successor : end.blockSuccessors()) { |
723 out.print(" B").print(successor.blockID); | 658 out.print(" B").print(successor.blockID); |
724 } | 659 } |
725 } | 660 } |
726 // print exception handlers | |
727 if (!exceptionHandlers().isEmpty()) { | |
728 out.print(" (xhandlers"); | |
729 for (BlockBegin handler : exceptionHandlerBlocks()) { | |
730 out.print(" B").print(handler.blockID); | |
731 } | |
732 out.print(')'); | |
733 } | |
734 | 661 |
735 // print dominator block | 662 // print dominator block |
736 if (dominator() != null) { | 663 if (dominator() != null) { |
737 out.print(" dom B").print(dominator().blockID); | 664 out.print(" dom B").print(dominator().blockID); |
738 } | 665 } |
739 | 666 |
740 // print predecessors | 667 // print predecessors |
741 if (!blockPredecessors().isEmpty()) { | 668 if (!blockPredecessors().isEmpty()) { |
742 out.print(" pred:"); | 669 out.print(" pred:"); |
743 for (BlockEnd pred : blockPredecessors()) { | 670 for (Instruction pred : blockPredecessors()) { |
744 out.print(" B").print(pred.begin().blockID); | 671 out.print(" B").print(pred.block().blockID); |
745 } | 672 } |
746 } | 673 } |
747 } | 674 } |
748 | 675 |
749 @Override | 676 @Override |
872 @Override | 799 @Override |
873 public String shortName() { | 800 public String shortName() { |
874 return "BlockBegin #" + blockID; | 801 return "BlockBegin #" + blockID; |
875 } | 802 } |
876 | 803 |
804 /** | |
805 * Iterates over all successors of this block: successors of the end node and exception handler. | |
806 */ | |
807 public void allSuccessorsDo(boolean backwards, BlockClosure closure) { | |
808 if (backwards) { | |
809 for (int i = numberOfSux() - 1; i >= 0; i--) { | |
810 closure.apply(suxAt(i)); | |
811 } | |
812 } else { | |
813 for (int i = 0; i < numberOfSux(); i++) { | |
814 closure.apply(suxAt(i)); | |
815 } | |
816 } | |
817 for (Instruction x = next(); x != null; x = x.next()) { | |
818 if (x instanceof Invoke && ((Invoke) x).exceptionEdge() != null) { | |
819 closure.apply(((Invoke) x).exceptionEdge()); | |
820 } else if (x instanceof Throw && ((Throw) x).exceptionEdge() != null) { | |
821 closure.apply(((Throw) x).exceptionEdge()); | |
822 } | |
823 } | |
824 } | |
825 | |
826 public void verifyPredecessors() { | |
827 for (int i = 0; i < numberOfPreds(); i++) { | |
828 predAt(i); | |
829 } | |
830 | |
831 } | |
832 | |
877 | 833 |
878 } | 834 } |