Mercurial > hg > truffle
comparison graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java @ 2840:75e0d39833a0
new CompilerGraph, create only one Return and one Unwind per CompilerGraph
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Tue, 31 May 2011 16:53:19 +0200 |
parents | 7b5831f0e913 |
children | 7596ae867a7b |
comparison
equal
deleted
inserted
replaced
2837:7b5831f0e913 | 2840:75e0d39833a0 |
---|---|
27 | 27 |
28 import java.lang.reflect.*; | 28 import java.lang.reflect.*; |
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.oracle.max.graal.schedule.Schedule; | 32 import com.oracle.max.graal.schedule.*; |
33 import com.sun.c1x.*; | 33 import com.sun.c1x.*; |
34 import com.sun.c1x.debug.*; | 34 import com.sun.c1x.debug.*; |
35 import com.sun.c1x.graph.BlockMap.*; | 35 import com.sun.c1x.graph.BlockMap.Block; |
36 import com.sun.c1x.graph.BlockMap.ExceptionBlock; | |
36 import com.sun.c1x.ir.*; | 37 import com.sun.c1x.ir.*; |
37 import com.sun.c1x.util.*; | 38 import com.sun.c1x.util.*; |
38 import com.sun.c1x.value.*; | 39 import com.sun.c1x.value.*; |
39 import com.sun.cri.bytecode.*; | 40 import com.sun.cri.bytecode.*; |
40 import com.sun.cri.ci.*; | 41 import com.sun.cri.ci.*; |
41 import com.sun.cri.ri.*; | 42 import com.sun.cri.ri.*; |
42 import com.sun.cri.ri.RiType.*; | 43 import com.sun.cri.ri.RiType.Representation; |
43 | 44 |
44 /** | 45 /** |
45 * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph. | 46 * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph. |
46 * A number of optimizations may be performed during parsing of the bytecode, including value | 47 * A number of optimizations may be performed during parsing of the bytecode, including value |
47 * numbering, inlining, constant folding, strength reduction, etc. | 48 * numbering, inlining, constant folding, strength reduction, etc. |
70 private ArrayList<Block> blockList; | 71 private ArrayList<Block> blockList; |
71 | 72 |
72 private Block syncBlock; | 73 private Block syncBlock; |
73 private CiExceptionHandler syncHandler; | 74 private CiExceptionHandler syncHandler; |
74 | 75 |
76 private Block unwindBlock; | |
77 private Block returnBlock; | |
78 | |
75 // the constant pool | 79 // the constant pool |
76 private final RiConstantPool constantPool; | 80 private final RiConstantPool constantPool; |
77 | 81 |
78 // the worklist of blocks, sorted by depth first number | 82 // the worklist of blocks, sorted by depth first number |
79 private final PriorityQueue<Block> workList = new PriorityQueue<Block>(10, new Comparator<Block>() { | 83 private final PriorityQueue<Block> workList = new PriorityQueue<Block>(10, new Comparator<Block>() { |
87 | 91 |
88 private final LogStream log; | 92 private final LogStream log; |
89 | 93 |
90 private Value rootMethodSynchronizedObject; | 94 private Value rootMethodSynchronizedObject; |
91 | 95 |
92 private final Graph graph; | 96 private final CompilerGraph graph; |
93 | 97 |
94 /** | 98 /** |
95 * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation. | 99 * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation. |
96 * | 100 * |
97 * @param compilation the compilation | 101 * @param compilation the compilation |
98 * @param ir the IR to build the graph into | 102 * @param ir the IR to build the graph into |
99 * @param graph | 103 * @param graph |
100 */ | 104 */ |
101 public GraphBuilder(C1XCompilation compilation, IR ir, Graph graph) { | 105 public GraphBuilder(C1XCompilation compilation, IR ir, CompilerGraph graph) { |
102 this.compilation = compilation; | 106 this.compilation = compilation; |
103 this.ir = ir; | 107 this.ir = ir; |
104 this.stats = compilation.stats; | 108 this.stats = compilation.stats; |
105 log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null; | 109 log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null; |
106 stream = new BytecodeStream(compilation.method.code()); | 110 stream = new BytecodeStream(compilation.method.code()); |
147 genMonitorEnter(rootMethodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI); | 151 genMonitorEnter(rootMethodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI); |
148 // 4A.2 finish the start block | 152 // 4A.2 finish the start block |
149 finishStartBlock(startBlock); | 153 finishStartBlock(startBlock); |
150 | 154 |
151 // 4A.3 setup an exception handler to unlock the root method synchronized object | 155 // 4A.3 setup an exception handler to unlock the root method synchronized object |
152 syncBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI); | |
153 markOnWorkList(syncBlock); | |
154 | |
155 syncHandler = new CiExceptionHandler(0, rootMethod.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null); | 156 syncHandler = new CiExceptionHandler(0, rootMethod.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null); |
156 } else { | 157 } else { |
157 // 4B.1 simply finish the start block | 158 // 4B.1 simply finish the start block |
158 finishStartBlock(startBlock); | 159 finishStartBlock(startBlock); |
159 } | 160 } |
161 // 5. SKIPPED: look for intrinsics | 162 // 5. SKIPPED: look for intrinsics |
162 | 163 |
163 // 6B.1 do the normal parsing | 164 // 6B.1 do the normal parsing |
164 addToWorkList(blockFromBci[0]); | 165 addToWorkList(blockFromBci[0]); |
165 iterateAllBlocks(); | 166 iterateAllBlocks(); |
166 | |
167 if (syncBlock != null && syncBlock.firstInstruction != null) { | |
168 // generate unlocking code if the exception handler is reachable | |
169 fillSyncHandler(rootMethodSynchronizedObject, syncBlock); | |
170 } | |
171 | 167 |
172 for (Node n : graph.getNodes()) { | 168 for (Node n : graph.getNodes()) { |
173 if (n instanceof Placeholder) { | 169 if (n instanceof Placeholder) { |
174 Placeholder p = (Placeholder) n; | 170 Placeholder p = (Placeholder) n; |
175 assert p.blockPredecessors().size() == 1; | 171 assert p.blockPredecessors().size() == 1; |
208 block.endBci = bci; | 204 block.endBci = bci; |
209 block.blockID = ir.nextBlockNumber(); | 205 block.blockID = ir.nextBlockNumber(); |
210 return block; | 206 return block; |
211 } | 207 } |
212 | 208 |
209 private Block unwindBlock() { | |
210 if (unwindBlock == null) { | |
211 unwindBlock = new Block(); | |
212 unwindBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI; | |
213 unwindBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI; | |
214 unwindBlock.blockID = ir.nextBlockNumber(); | |
215 addToWorkList(unwindBlock); | |
216 } | |
217 return unwindBlock; | |
218 } | |
219 | |
220 private Block returnBlock() { | |
221 if (returnBlock == null) { | |
222 returnBlock = new Block(); | |
223 returnBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI; | |
224 returnBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI; | |
225 returnBlock.blockID = ir.nextBlockNumber(); | |
226 addToWorkList(returnBlock); | |
227 } | |
228 return returnBlock; | |
229 } | |
230 | |
231 | |
213 private Set<Block> blocksOnWorklist = new HashSet<Block>(); | 232 private Set<Block> blocksOnWorklist = new HashSet<Block>(); |
214 | 233 |
215 private void markOnWorkList(Block block) { | 234 private void markOnWorkList(Block block) { |
216 blocksOnWorklist.add(block); | 235 blocksOnWorklist.add(block); |
217 } | 236 } |
373 // if there's no dispatch block then the catch block needs to be a catch all | 392 // if there's no dispatch block then the catch block needs to be a catch all |
374 if (dispatchBlock == null) { | 393 if (dispatchBlock == null) { |
375 assert isCatchAll(firstHandler); | 394 assert isCatchAll(firstHandler); |
376 int handlerBCI = firstHandler.handlerBCI(); | 395 int handlerBCI = firstHandler.handlerBCI(); |
377 if (handlerBCI == Instruction.SYNCHRONIZATION_ENTRY_BCI) { | 396 if (handlerBCI == Instruction.SYNCHRONIZATION_ENTRY_BCI) { |
378 dispatchBlock = syncBlock; | 397 dispatchBlock = unwindBlock(); |
379 } else { | 398 } else { |
380 dispatchBlock = blockFromBci[handlerBCI]; | 399 dispatchBlock = blockFromBci[handlerBCI]; |
381 } | 400 } |
382 } | 401 } |
383 FrameState entryState = frameState.duplicateWithEmptyStack(bci); | 402 FrameState entryState = frameState.duplicateWithEmptyStack(bci); |
607 } | 626 } |
608 | 627 |
609 private void genThrow(int bci) { | 628 private void genThrow(int bci) { |
610 Value exception = frameState.apop(); | 629 Value exception = frameState.apop(); |
611 append(new NullCheck(exception, graph)); | 630 append(new NullCheck(exception, graph)); |
631 | |
612 Instruction entry = handleException(exception, bci); | 632 Instruction entry = handleException(exception, bci); |
613 if (entry == null) { | 633 if (entry != null) { |
614 entry = new Unwind(exception, graph.end(), graph); | 634 append(entry); |
615 } | 635 } else { |
616 append(entry); | 636 frameState.clearStack(); |
637 frameState.apush(exception); | |
638 appendGoto(createTarget(unwindBlock(), frameState)); | |
639 } | |
617 } | 640 } |
618 | 641 |
619 private void genCheckCast() { | 642 private void genCheckCast() { |
620 int cpi = stream().readCPI(); | 643 int cpi = stream().readCPI(); |
621 RiType type = constantPool().lookupType(cpi, CHECKCAST); | 644 RiType type = constantPool().lookupType(cpi, CHECKCAST); |
891 C1XMetrics.InlinedFinalizerChecks++; | 914 C1XMetrics.InlinedFinalizerChecks++; |
892 } | 915 } |
893 } | 916 } |
894 | 917 |
895 private void genReturn(Value x) { | 918 private void genReturn(Value x) { |
896 if (method().isConstructor() && method().holder().superType() == null) { | |
897 callRegisterFinalizer(); | |
898 } | |
899 | |
900 frameState.clearStack(); | 919 frameState.clearStack(); |
901 if (Modifier.isSynchronized(method().accessFlags())) { | 920 if (x != null) { |
902 // unlock before exiting the method | 921 frameState.push(x.kind, x); |
903 int lockNumber = frameState.locksSize() - 1; | 922 } |
904 MonitorAddress lockAddress = null; | 923 appendGoto(createTarget(returnBlock(), frameState)); |
905 if (compilation.runtime.sizeOfBasicObjectLock() != 0) { | |
906 lockAddress = new MonitorAddress(lockNumber, graph); | |
907 append(lockAddress); | |
908 } | |
909 append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, graph)); | |
910 frameState.unlock(); | |
911 } | |
912 append(new Return(x, graph)); | |
913 } | 924 } |
914 | 925 |
915 private void genMonitorEnter(Value x, int bci) { | 926 private void genMonitorEnter(Value x, int bci) { |
916 int lockNumber = frameState.locksSize(); | 927 int lockNumber = frameState.locksSize(); |
917 MonitorAddress lockAddress = null; | 928 MonitorAddress lockAddress = null; |
1064 } else { | 1075 } else { |
1065 return state.localAt(0); | 1076 return state.localAt(0); |
1066 } | 1077 } |
1067 } | 1078 } |
1068 | 1079 |
1069 private void fillSyncHandler(Value lock, Block syncHandler) { | |
1070 lastInstr = syncHandler.firstInstruction; | |
1071 while (lastInstr.next() != null) { | |
1072 // go forward to the end of the block | |
1073 lastInstr = lastInstr.next(); | |
1074 } | |
1075 | |
1076 frameState.initializeFrom(((StateSplit) syncHandler.firstInstruction).stateBefore()); | |
1077 | |
1078 assert lock != null; | |
1079 assert frameState.locksSize() > 0 && frameState.lockAt(frameState.locksSize() - 1) == lock; | |
1080 | |
1081 // Exit the monitor and unwind the stack. | |
1082 genMonitorExit(lock); | |
1083 append(new Unwind(frameState.apop(), graph.end(), graph)); | |
1084 | |
1085 // The sync handler is always the last thing to add => we can clear the frameState. | |
1086 frameState = null; | |
1087 lastInstr = null; | |
1088 } | |
1089 | |
1090 private void iterateAllBlocks() { | 1080 private void iterateAllBlocks() { |
1091 Block block; | 1081 Block block; |
1092 while ((block = removeFromWorkList()) != null) { | 1082 while ((block = removeFromWorkList()) != null) { |
1093 | 1083 |
1094 // remove blocks that have no predecessors by the time it their bytecodes are parsed | 1084 // remove blocks that have no predecessors by the time it their bytecodes are parsed |
1102 // now parse the block | 1092 // now parse the block |
1103 frameState.initializeFrom(((StateSplit) block.firstInstruction).stateBefore()); | 1093 frameState.initializeFrom(((StateSplit) block.firstInstruction).stateBefore()); |
1104 lastInstr = block.firstInstruction; | 1094 lastInstr = block.firstInstruction; |
1105 assert block.firstInstruction.next() == null : "instructions already appended at block " + block.blockID; | 1095 assert block.firstInstruction.next() == null : "instructions already appended at block " + block.blockID; |
1106 | 1096 |
1107 if (block instanceof ExceptionBlock) { | 1097 if (block == returnBlock) { |
1098 createReturnBlock(block); | |
1099 } else if (block == unwindBlock) { | |
1100 createUnwindBlock(block); | |
1101 } else if (block instanceof ExceptionBlock) { | |
1108 createExceptionDispatch((ExceptionBlock) block); | 1102 createExceptionDispatch((ExceptionBlock) block); |
1109 } else { | 1103 } else { |
1110 iterateBytecodesForBlock(block); | 1104 iterateBytecodesForBlock(block); |
1111 } | 1105 } |
1112 } | 1106 } |
1133 } | 1127 } |
1134 } | 1128 } |
1135 } | 1129 } |
1136 } | 1130 } |
1137 | 1131 |
1132 private void createUnwindBlock(Block block) { | |
1133 if (Modifier.isSynchronized(method().accessFlags())) { | |
1134 genMonitorExit(rootMethodSynchronizedObject); | |
1135 } | |
1136 append(graph.createUnwind(frameState.apop())); | |
1137 } | |
1138 | |
1139 private void createReturnBlock(Block block) { | |
1140 if (method().isConstructor() && method().holder().superType() == null) { | |
1141 callRegisterFinalizer(); | |
1142 } | |
1143 CiKind returnKind = method().signature().returnKind().stackKind(); | |
1144 Value x = returnKind == CiKind.Void ? null : frameState.pop(returnKind); | |
1145 assert frameState.stackSize() == 0; | |
1146 | |
1147 if (Modifier.isSynchronized(method().accessFlags())) { | |
1148 genMonitorExit(rootMethodSynchronizedObject); | |
1149 } | |
1150 append(graph.createReturn(x)); | |
1151 } | |
1152 | |
1138 private void createExceptionDispatch(ExceptionBlock block) { | 1153 private void createExceptionDispatch(ExceptionBlock block) { |
1139 if (block.handler == null) { | 1154 if (block.handler == null) { |
1140 assert frameState.stackSize() == 1 : "only exception object expected on stack, actual size: " + frameState.stackSize(); | 1155 assert frameState.stackSize() == 1 : "only exception object expected on stack, actual size: " + frameState.stackSize(); |
1141 if (Modifier.isSynchronized(method().accessFlags())) { | 1156 createUnwindBlock(block); |
1142 // unlock before exiting the method | |
1143 int lockNumber = frameState.locksSize() - 1; | |
1144 MonitorAddress lockAddress = null; | |
1145 if (compilation.runtime.sizeOfBasicObjectLock() != 0) { | |
1146 lockAddress = new MonitorAddress(lockNumber, graph); | |
1147 append(lockAddress); | |
1148 } | |
1149 append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, graph)); | |
1150 frameState.unlock(); | |
1151 } | |
1152 append(new Unwind(frameState.apop(), graph.end(), graph)); | |
1153 } else { | 1157 } else { |
1154 assert frameState.stackSize() == 1; | 1158 assert frameState.stackSize() == 1; |
1155 | 1159 |
1160 Block nextBlock = block.next == null ? unwindBlock() : block.next; | |
1156 if (block.handler.catchType().isResolved()) { | 1161 if (block.handler.catchType().isResolved()) { |
1157 Instruction catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState); | 1162 Instruction catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState); |
1158 Instruction nextDispatch = createTarget(block.next, frameState); | 1163 Instruction nextDispatch = createTarget(nextBlock, frameState); |
1159 append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph)); | 1164 append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph)); |
1160 } else { | 1165 } else { |
1161 Deoptimize deopt = new Deoptimize(graph); | 1166 Deoptimize deopt = new Deoptimize(graph); |
1162 deopt.setMessage("unresolved " + block.handler.catchType().name()); | 1167 deopt.setMessage("unresolved " + block.handler.catchType().name()); |
1163 append(deopt); | 1168 append(deopt); |
1164 Instruction nextDispatch = createTarget(block.next, frameState); | 1169 Instruction nextDispatch = createTarget(nextBlock, frameState); |
1165 appendGoto(nextDispatch); | 1170 appendGoto(nextDispatch); |
1166 } | 1171 } |
1167 } | 1172 } |
1168 } | 1173 } |
1169 | 1174 |
1183 while (bci < endBCI) { | 1188 while (bci < endBCI) { |
1184 Block nextBlock = blockFromBci[bci]; | 1189 Block nextBlock = blockFromBci[bci]; |
1185 if (nextBlock != null && nextBlock != block) { | 1190 if (nextBlock != null && nextBlock != block) { |
1186 assert !nextBlock.isExceptionEntry; | 1191 assert !nextBlock.isExceptionEntry; |
1187 // 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 |
1188 Instruction next = createTarget(nextBlock, frameState); | 1193 appendGoto(createTarget(nextBlock, frameState)); |
1189 appendGoto(next); | |
1190 break; | 1194 break; |
1191 } | 1195 } |
1192 // read the opcode | 1196 // read the opcode |
1193 int opcode = stream.currentBC(); | 1197 int opcode = stream.currentBC(); |
1194 | 1198 |