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