comparison graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java @ 2842:7596ae867a7b

basic inlining passes all tests, including optimistic inlining
author Lukas Stadler <lukas.stadler@jku.at>
date Wed, 01 Jun 2011 16:26:17 +0200
parents 75e0d39833a0
children 7474789a8120 7f14e6b48a9c
comparison
equal deleted inserted replaced
2841:633e66de40fe 2842:7596ae867a7b
59 * The minimum value to which {@link C1XOptions#TraceBytecodeParserLevel} must be set to trace 59 * The minimum value to which {@link C1XOptions#TraceBytecodeParserLevel} must be set to trace
60 * the frame state before each bytecode instruction as it is parsed. 60 * the frame state before each bytecode instruction as it is parsed.
61 */ 61 */
62 public static final int TRACELEVEL_STATE = 2; 62 public static final int TRACELEVEL_STATE = 2;
63 63
64 private final IR ir;
65 private final C1XCompilation compilation; 64 private final C1XCompilation compilation;
65 private final CompilerGraph graph;
66
66 private final CiStatistics stats; 67 private final CiStatistics stats;
68 private final RiRuntime runtime;
69 private final RiMethod method;
70 private final RiConstantPool constantPool;
67 71
68 private final BytecodeStream stream; // the bytecode stream 72 private final BytecodeStream stream; // the bytecode stream
73 private final LogStream log;
74 private final FrameStateBuilder frameState; // the current execution state
75
69 // bci-to-block mapping 76 // bci-to-block mapping
70 private Block[] blockFromBci; 77 private Block[] blockFromBci;
71 private ArrayList<Block> blockList; 78 private ArrayList<Block> blockList;
72 79
73 private Block syncBlock; 80 private int nextBlockNumber;
81
82 private Value methodSynchronizedObject;
74 private CiExceptionHandler syncHandler; 83 private CiExceptionHandler syncHandler;
75 84
76 private Block unwindBlock; 85 private Block unwindBlock;
77 private Block returnBlock; 86 private Block returnBlock;
78
79 // the constant pool
80 private final RiConstantPool constantPool;
81 87
82 // the worklist of blocks, sorted by depth first number 88 // the worklist of blocks, sorted by depth first number
83 private final PriorityQueue<Block> workList = new PriorityQueue<Block>(10, new Comparator<Block>() { 89 private final PriorityQueue<Block> workList = new PriorityQueue<Block>(10, new Comparator<Block>() {
84 public int compare(Block o1, Block o2) { 90 public int compare(Block o1, Block o2) {
85 return o1.blockID - o2.blockID; 91 return o1.blockID - o2.blockID;
86 } 92 }
87 }); 93 });
88 94
89 private FrameStateBuilder frameState; // the current execution state
90 private Instruction lastInstr; // the last instruction added 95 private Instruction lastInstr; // the last instruction added
91 96
92 private final LogStream log; 97 private final Set<Block> blocksOnWorklist = new HashSet<Block>();
93 98 private final Set<Block> blocksVisited = new HashSet<Block>();
94 private Value rootMethodSynchronizedObject; 99
95
96 private final CompilerGraph graph;
97 100
98 /** 101 /**
99 * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation. 102 * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation.
100 * 103 *
101 * @param compilation the compilation 104 * @param compilation the compilation
102 * @param ir the IR to build the graph into 105 * @param ir the IR to build the graph into
103 * @param graph 106 * @param graph
104 */ 107 */
105 public GraphBuilder(C1XCompilation compilation, IR ir, CompilerGraph graph) { 108 public GraphBuilder(C1XCompilation compilation, RiMethod method, CompilerGraph graph) {
106 this.compilation = compilation; 109 this.compilation = compilation;
107 this.ir = ir; 110 this.graph = graph;
111
112 this.runtime = compilation.runtime;
113 this.method = method;
108 this.stats = compilation.stats; 114 this.stats = compilation.stats;
109 log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null; 115 this.log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null;
110 stream = new BytecodeStream(compilation.method.code()); 116 this.stream = new BytecodeStream(method.code());
111 constantPool = compilation.runtime.getConstantPool(compilation.method); 117
112 this.graph = graph; 118 this.constantPool = runtime.getConstantPool(method);
113 this.frameState = new FrameStateBuilder(compilation.method, graph); 119 this.frameState = new FrameStateBuilder(method, graph);
114 } 120 }
115 121
116 /** 122 /**
117 * Builds the graph for a the specified {@code IRScope}. 123 * Builds the graph for a the specified {@code IRScope}.
118 * @param scope the top IRScope 124 * @param scope the top IRScope
119 */ 125 */
120 public void build() { 126 public void build() {
121 RiMethod rootMethod = compilation.method;
122
123 if (log != null) { 127 if (log != null) {
124 log.println(); 128 log.println();
125 log.println("Compiling " + compilation.method); 129 log.println("Compiling " + method);
126 } 130 }
127 131
128 // 2. compute the block map, setup exception handlers and get the entrypoint(s) 132 // 2. compute the block map, setup exception handlers and get the entrypoint(s)
129 BlockMap blockMap = compilation.getBlockMap(rootMethod); 133 BlockMap blockMap = compilation.getBlockMap(method);
130 134
131 blockList = new ArrayList<Block>(blockMap.blocks); 135 blockList = new ArrayList<Block>(blockMap.blocks);
132 blockFromBci = new Block[rootMethod.code().length]; 136 blockFromBci = new Block[method.code().length];
133 for (int i = 0; i < blockList.size(); i++) { 137 for (int i = 0; i < blockList.size(); i++) {
134 int blockID = ir.nextBlockNumber(); 138 int blockID = nextBlockNumber();
135 assert blockID == i; 139 assert blockID == i;
136 Block block = blockList.get(i); 140 Block block = blockList.get(i);
137 if (block.startBci >= 0) { 141 if (block.startBci >= 0) {
138 blockFromBci[block.startBci] = block; 142 blockFromBci[block.startBci] = block;
139 } 143 }
143 Block startBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI); 147 Block startBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI);
144 markOnWorkList(startBlock); 148 markOnWorkList(startBlock);
145 lastInstr = createTarget(startBlock, frameState); 149 lastInstr = createTarget(startBlock, frameState);
146 graph.start().setStart(lastInstr); 150 graph.start().setStart(lastInstr);
147 151
148 if (isSynchronized(rootMethod.accessFlags())) { 152 if (isSynchronized(method.accessFlags())) {
149 // 4A.1 add a monitor enter to the start block 153 // 4A.1 add a monitor enter to the start block
150 rootMethodSynchronizedObject = synchronizedObject(frameState, compilation.method); 154 methodSynchronizedObject = synchronizedObject(frameState, method);
151 genMonitorEnter(rootMethodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI); 155 genMonitorEnter(methodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI);
152 // 4A.2 finish the start block 156 // 4A.2 finish the start block
153 finishStartBlock(startBlock); 157 finishStartBlock(startBlock);
154 158
155 // 4A.3 setup an exception handler to unlock the root method synchronized object 159 // 4A.3 setup an exception handler to unlock the root method synchronized object
156 syncHandler = new CiExceptionHandler(0, rootMethod.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null); 160 syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null);
157 } else { 161 } else {
158 // 4B.1 simply finish the start block 162 // 4B.1 simply finish the start block
159 finishStartBlock(startBlock); 163 finishStartBlock(startBlock);
160 } 164 }
161 165
163 167
164 // 6B.1 do the normal parsing 168 // 6B.1 do the normal parsing
165 addToWorkList(blockFromBci[0]); 169 addToWorkList(blockFromBci[0]);
166 iterateAllBlocks(); 170 iterateAllBlocks();
167 171
172 // remove Placeholders
168 for (Node n : graph.getNodes()) { 173 for (Node n : graph.getNodes()) {
169 if (n instanceof Placeholder) { 174 if (n instanceof Placeholder) {
170 Placeholder p = (Placeholder) n; 175 Placeholder p = (Placeholder) n;
171 assert p.blockPredecessors().size() == 1; 176 assert p.blockPredecessors().size() == 1;
172 Node pred = p.blockPredecessors().get(0); 177 Node pred = p.blockPredecessors().get(0);
174 pred.successors().setAndClear(predIndex, p, 0); 179 pred.successors().setAndClear(predIndex, p, 0);
175 p.delete(); 180 p.delete();
176 } 181 }
177 } 182 }
178 183
179 for (Node n : graph.getNodes()) { 184 // remove FrameStates
180 assert !(n instanceof Placeholder);
181 }
182
183
184 for (Node n : graph.getNodes()) { 185 for (Node n : graph.getNodes()) {
185 if (n instanceof FrameState) { 186 if (n instanceof FrameState) {
186 boolean delete = false; 187 boolean delete = false;
187 if (n.usages().size() == 0 && n.predecessors().size() == 0) { 188 if (n.usages().size() == 0 && n.predecessors().size() == 0) {
188 delete = true; 189 delete = true;
189 } 190 }
190 // if (n.predecessors().size() == 0 && n.usages().size() == 1 && n.usages().get(0) instanceof BlockBegin) {
191 // n.usages().get(0).inputs().replace(n, null);
192 // delete = true;
193 // }
194 if (delete) { 191 if (delete) {
195 n.delete(); 192 n.delete();
196 } 193 }
197 } 194 }
198 } 195 }
196 }
197
198 private int nextBlockNumber() {
199 stats.blockCount++;
200 return nextBlockNumber++;
199 } 201 }
200 202
201 private Block nextBlock(int bci) { 203 private Block nextBlock(int bci) {
202 Block block = new Block(); 204 Block block = new Block();
203 block.startBci = bci; 205 block.startBci = bci;
204 block.endBci = bci; 206 block.endBci = bci;
205 block.blockID = ir.nextBlockNumber(); 207 block.blockID = nextBlockNumber();
206 return block; 208 return block;
207 } 209 }
208 210
209 private Block unwindBlock() { 211 private Block unwindBlock() {
210 if (unwindBlock == null) { 212 if (unwindBlock == null) {
211 unwindBlock = new Block(); 213 unwindBlock = new Block();
212 unwindBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI; 214 unwindBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
213 unwindBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI; 215 unwindBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
214 unwindBlock.blockID = ir.nextBlockNumber(); 216 unwindBlock.blockID = nextBlockNumber();
215 addToWorkList(unwindBlock); 217 addToWorkList(unwindBlock);
216 } 218 }
217 return unwindBlock; 219 return unwindBlock;
218 } 220 }
219 221
220 private Block returnBlock() { 222 private Block returnBlock() {
221 if (returnBlock == null) { 223 if (returnBlock == null) {
222 returnBlock = new Block(); 224 returnBlock = new Block();
223 returnBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI; 225 returnBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
224 returnBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI; 226 returnBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
225 returnBlock.blockID = ir.nextBlockNumber(); 227 returnBlock.blockID = nextBlockNumber();
226 addToWorkList(returnBlock); 228 addToWorkList(returnBlock);
227 } 229 }
228 return returnBlock; 230 return returnBlock;
229 } 231 }
230
231
232 private Set<Block> blocksOnWorklist = new HashSet<Block>();
233 232
234 private void markOnWorkList(Block block) { 233 private void markOnWorkList(Block block) {
235 blocksOnWorklist.add(block); 234 blocksOnWorklist.add(block);
236 } 235 }
237 236
238 private boolean isOnWorkList(Block block) { 237 private boolean isOnWorkList(Block block) {
239 return blocksOnWorklist.contains(block); 238 return blocksOnWorklist.contains(block);
240 } 239 }
241
242 private Set<Block> blocksVisited = new HashSet<Block>();
243 240
244 private void markVisited(Block block) { 241 private void markVisited(Block block) {
245 blocksVisited.add(block); 242 blocksVisited.add(block);
246 } 243 }
247 244
326 newState.setupPhiForLocal(merge, i).addInput(x); 323 newState.setupPhiForLocal(merge, i).addInput(x);
327 } 324 }
328 } 325 }
329 } 326 }
330 327
331 public RiMethod method() {
332 return compilation.method;
333 }
334
335 public BytecodeStream stream() { 328 public BytecodeStream stream() {
336 return stream; 329 return stream;
337 } 330 }
338 331
339 public int bci() { 332 public int bci() {
358 351
359 private Instruction handleException(Value exceptionObject, int bci) { 352 private Instruction handleException(Value exceptionObject, int bci) {
360 assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci"; 353 assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci";
361 354
362 RiExceptionHandler firstHandler = null; 355 RiExceptionHandler firstHandler = null;
363 RiExceptionHandler[] exceptionHandlers = compilation.method.exceptionHandlers(); 356 RiExceptionHandler[] exceptionHandlers = method.exceptionHandlers();
364 // join with all potential exception handlers 357 // join with all potential exception handlers
365 if (exceptionHandlers != null) { 358 if (exceptionHandlers != null) {
366 for (RiExceptionHandler handler : exceptionHandlers) { 359 for (RiExceptionHandler handler : exceptionHandlers) {
367 // if the handler covers this bytecode index, add it to the list 360 // if the handler covers this bytecode index, add it to the list
368 if (covers(handler, bci)) { 361 if (covers(handler, bci)) {
420 } 413 }
421 return null; 414 return null;
422 } 415 }
423 416
424 private void genLoadConstant(int cpi) { 417 private void genLoadConstant(int cpi) {
425 Object con = constantPool().lookupConstant(cpi); 418 Object con = constantPool.lookupConstant(cpi);
426 419
427 if (con instanceof RiType) { 420 if (con instanceof RiType) {
428 // this is a load of class constant which might be unresolved 421 // this is a load of class constant which might be unresolved
429 RiType riType = (RiType) con; 422 RiType riType = (RiType) con;
430 if (!riType.isResolved()) { 423 if (!riType.isResolved()) {
548 } 541 }
549 542
550 private void genArithmeticOp(CiKind result, int opcode, CiKind x, CiKind y, boolean canTrap) { 543 private void genArithmeticOp(CiKind result, int opcode, CiKind x, CiKind y, boolean canTrap) {
551 Value yValue = frameState.pop(y); 544 Value yValue = frameState.pop(y);
552 Value xValue = frameState.pop(x); 545 Value xValue = frameState.pop(x);
553 Value result1 = append(new ArithmeticOp(opcode, result, xValue, yValue, isStrict(method().accessFlags()), canTrap, graph)); 546 Value result1 = append(new ArithmeticOp(opcode, result, xValue, yValue, isStrict(method.accessFlags()), canTrap, graph));
554 frameState.push(result, result1); 547 frameState.push(result, result1);
555 } 548 }
556 549
557 private void genNegateOp(CiKind kind) { 550 private void genNegateOp(CiKind kind) {
558 frameState.push(kind, append(new NegateOp(frameState.pop(kind), graph))); 551 frameState.push(kind, append(new NegateOp(frameState.pop(kind), graph)));
587 private void genIncrement() { 580 private void genIncrement() {
588 int index = stream().readLocalIndex(); 581 int index = stream().readLocalIndex();
589 int delta = stream().readIncrement(); 582 int delta = stream().readIncrement();
590 Value x = frameState.localAt(index); 583 Value x = frameState.localAt(index);
591 Value y = append(Constant.forInt(delta, graph)); 584 Value y = append(Constant.forInt(delta, graph));
592 frameState.storeLocal(index, append(new ArithmeticOp(IADD, CiKind.Int, x, y, isStrict(method().accessFlags()), false, graph))); 585 frameState.storeLocal(index, append(new ArithmeticOp(IADD, CiKind.Int, x, y, isStrict(method.accessFlags()), false, graph)));
593 } 586 }
594 587
595 private void genGoto(int fromBCI, int toBCI) { 588 private void genGoto(int fromBCI, int toBCI) {
596 appendGoto(createTargetAt(toBCI, frameState)); 589 appendGoto(createTargetAt(toBCI, frameState));
597 } 590 }
639 } 632 }
640 } 633 }
641 634
642 private void genCheckCast() { 635 private void genCheckCast() {
643 int cpi = stream().readCPI(); 636 int cpi = stream().readCPI();
644 RiType type = constantPool().lookupType(cpi, CHECKCAST); 637 RiType type = constantPool.lookupType(cpi, CHECKCAST);
645 boolean isInitialized = type.isResolved(); 638 boolean isInitialized = type.isResolved();
646 Value typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi); 639 Value typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi);
647 Value object = frameState.apop(); 640 Value object = frameState.apop();
648 if (typeInstruction != null) { 641 if (typeInstruction != null) {
649 frameState.apush(append(new CheckCast(type, typeInstruction, object, graph))); 642 frameState.apush(append(new CheckCast(type, typeInstruction, object, graph)));
652 } 645 }
653 } 646 }
654 647
655 private void genInstanceOf() { 648 private void genInstanceOf() {
656 int cpi = stream().readCPI(); 649 int cpi = stream().readCPI();
657 RiType type = constantPool().lookupType(cpi, INSTANCEOF); 650 RiType type = constantPool.lookupType(cpi, INSTANCEOF);
658 boolean isInitialized = type.isResolved(); 651 boolean isInitialized = type.isResolved();
659 Value typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi); 652 Value typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi);
660 Value object = frameState.apop(); 653 Value object = frameState.apop();
661 if (typeInstruction != null) { 654 if (typeInstruction != null) {
662 frameState.ipush(append(new InstanceOf(type, typeInstruction, object, graph))); 655 frameState.ipush(append(new InstanceOf(type, typeInstruction, object, graph)));
664 frameState.ipush(appendConstant(CiConstant.INT_0)); 657 frameState.ipush(appendConstant(CiConstant.INT_0));
665 } 658 }
666 } 659 }
667 660
668 void genNewInstance(int cpi) { 661 void genNewInstance(int cpi) {
669 RiType type = constantPool().lookupType(cpi, NEW); 662 RiType type = constantPool.lookupType(cpi, NEW);
670 if (type.isResolved()) { 663 if (type.isResolved()) {
671 NewInstance n = new NewInstance(type, cpi, constantPool(), graph); 664 NewInstance n = new NewInstance(type, cpi, constantPool, graph);
672 frameState.apush(append(n)); 665 frameState.apush(append(n));
673 } else { 666 } else {
674 append(new Deoptimize(graph)); 667 append(new Deoptimize(graph));
675 frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); 668 frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
676 } 669 }
677 } 670 }
678 671
679 private void genNewTypeArray(int typeCode) { 672 private void genNewTypeArray(int typeCode) {
680 CiKind kind = CiKind.fromArrayTypeCode(typeCode); 673 CiKind kind = CiKind.fromArrayTypeCode(typeCode);
681 RiType elementType = compilation.runtime.asRiType(kind); 674 RiType elementType = runtime.asRiType(kind);
682 NewTypeArray nta = new NewTypeArray(frameState.ipop(), elementType, graph); 675 NewTypeArray nta = new NewTypeArray(frameState.ipop(), elementType, graph);
683 frameState.apush(append(nta)); 676 frameState.apush(append(nta));
684 } 677 }
685 678
686 private void genNewObjectArray(int cpi) { 679 private void genNewObjectArray(int cpi) {
687 RiType type = constantPool().lookupType(cpi, ANEWARRAY); 680 RiType type = constantPool.lookupType(cpi, ANEWARRAY);
688 Value length = frameState.ipop(); 681 Value length = frameState.ipop();
689 if (type.isResolved()) { 682 if (type.isResolved()) {
690 NewArray n = new NewObjectArray(type, length, graph); 683 NewArray n = new NewObjectArray(type, length, graph);
691 frameState.apush(append(n)); 684 frameState.apush(append(n));
692 } else { 685 } else {
695 } 688 }
696 689
697 } 690 }
698 691
699 private void genNewMultiArray(int cpi) { 692 private void genNewMultiArray(int cpi) {
700 RiType type = constantPool().lookupType(cpi, MULTIANEWARRAY); 693 RiType type = constantPool.lookupType(cpi, MULTIANEWARRAY);
701 int rank = stream().readUByte(bci() + 3); 694 int rank = stream().readUByte(bci() + 3);
702 Value[] dims = new Value[rank]; 695 Value[] dims = new Value[rank];
703 for (int i = rank - 1; i >= 0; i--) { 696 for (int i = rank - 1; i >= 0; i--) {
704 dims[i] = frameState.ipop(); 697 dims[i] = frameState.ipop();
705 } 698 }
706 if (type.isResolved()) { 699 if (type.isResolved()) {
707 NewArray n = new NewMultiArray(type, dims, cpi, constantPool(), graph); 700 NewArray n = new NewMultiArray(type, dims, cpi, constantPool, graph);
708 frameState.apush(append(n)); 701 frameState.apush(append(n));
709 } else { 702 } else {
710 append(new Deoptimize(graph)); 703 append(new Deoptimize(graph));
711 frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); 704 frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
712 } 705 }
851 appendInvoke(INVOKESPECIAL, target, args, cpi, constantPool); 844 appendInvoke(INVOKESPECIAL, target, args, cpi, constantPool);
852 } 845 }
853 846
854 private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) { 847 private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) {
855 CiKind resultType = returnKind(target); 848 CiKind resultType = returnKind(target);
856 Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(compilation.method.holder()), graph); 849 Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), graph);
857 Value result = appendWithBCI(invoke); 850 Value result = appendWithBCI(invoke);
858 invoke.setExceptionEdge(handleException(null, bci())); 851 invoke.setExceptionEdge(handleException(null, bci()));
859 frameState.pushReturn(resultType, result); 852 frameState.pushReturn(resultType, result);
860 } 853 }
861 854
863 RiType exact = staticType.exactType(); 856 RiType exact = staticType.exactType();
864 if (exact == null) { 857 if (exact == null) {
865 exact = receiver.exactType(); 858 exact = receiver.exactType();
866 if (exact == null) { 859 if (exact == null) {
867 if (receiver.isConstant()) { 860 if (receiver.isConstant()) {
868 exact = compilation.runtime.getTypeOf(receiver.asConstant()); 861 exact = runtime.getTypeOf(receiver.asConstant());
869 } 862 }
870 if (exact == null) { 863 if (exact == null) {
871 RiType declared = receiver.declaredType(); 864 RiType declared = receiver.declaredType();
872 exact = declared == null || !declared.isResolved() ? null : declared.exactType(); 865 exact = declared == null || !declared.isResolved() ? null : declared.exactType();
873 } 866 }
884 if (exactType == null && declaredType != null) { 877 if (exactType == null && declaredType != null) {
885 exactType = declaredType.exactType(); 878 exactType = declaredType.exactType();
886 } 879 }
887 if (exactType == null && receiver instanceof Local && ((Local) receiver).index() == 0) { 880 if (exactType == null && receiver instanceof Local && ((Local) receiver).index() == 0) {
888 // the exact type isn't known, but the receiver is parameter 0 => use holder 881 // the exact type isn't known, but the receiver is parameter 0 => use holder
889 receiverType = compilation.method.holder(); 882 receiverType = method.holder();
890 exactType = receiverType.exactType(); 883 exactType = receiverType.exactType();
891 } 884 }
892 boolean needsCheck = true; 885 boolean needsCheck = true;
893 if (exactType != null) { 886 if (exactType != null) {
894 // we have an exact type 887 // we have an exact type
924 } 917 }
925 918
926 private void genMonitorEnter(Value x, int bci) { 919 private void genMonitorEnter(Value x, int bci) {
927 int lockNumber = frameState.locksSize(); 920 int lockNumber = frameState.locksSize();
928 MonitorAddress lockAddress = null; 921 MonitorAddress lockAddress = null;
929 if (compilation.runtime.sizeOfBasicObjectLock() != 0) { 922 if (runtime.sizeOfBasicObjectLock() != 0) {
930 lockAddress = new MonitorAddress(lockNumber, graph); 923 lockAddress = new MonitorAddress(lockNumber, graph);
931 append(lockAddress); 924 append(lockAddress);
932 } 925 }
933 MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, graph); 926 MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, graph);
934 appendWithBCI(monitorEnter); 927 appendWithBCI(monitorEnter);
935 frameState.lock(ir, x, lockNumber + 1); 928 frameState.lock(x);
936 if (bci == Instruction.SYNCHRONIZATION_ENTRY_BCI) { 929 if (bci == Instruction.SYNCHRONIZATION_ENTRY_BCI) {
937 monitorEnter.setStateAfter(frameState.create(0)); 930 monitorEnter.setStateAfter(frameState.create(0));
938 } 931 }
939 } 932 }
940 933
942 int lockNumber = frameState.locksSize() - 1; 935 int lockNumber = frameState.locksSize() - 1;
943 if (lockNumber < 0) { 936 if (lockNumber < 0) {
944 throw new CiBailout("monitor stack underflow"); 937 throw new CiBailout("monitor stack underflow");
945 } 938 }
946 MonitorAddress lockAddress = null; 939 MonitorAddress lockAddress = null;
947 if (compilation.runtime.sizeOfBasicObjectLock() != 0) { 940 if (runtime.sizeOfBasicObjectLock() != 0) {
948 lockAddress = new MonitorAddress(lockNumber, graph); 941 lockAddress = new MonitorAddress(lockNumber, graph);
949 append(lockAddress); 942 append(lockAddress);
950 } 943 }
951 appendWithBCI(new MonitorExit(x, lockAddress, lockNumber, graph)); 944 appendWithBCI(new MonitorExit(x, lockAddress, lockNumber, graph));
952 frameState.unlock(); 945 frameState.unlock();
1128 } 1121 }
1129 } 1122 }
1130 } 1123 }
1131 1124
1132 private void createUnwindBlock(Block block) { 1125 private void createUnwindBlock(Block block) {
1133 if (Modifier.isSynchronized(method().accessFlags())) { 1126 if (Modifier.isSynchronized(method.accessFlags())) {
1134 genMonitorExit(rootMethodSynchronizedObject); 1127 genMonitorExit(methodSynchronizedObject);
1135 } 1128 }
1136 append(graph.createUnwind(frameState.apop())); 1129 append(graph.createUnwind(frameState.apop()));
1137 } 1130 }
1138 1131
1139 private void createReturnBlock(Block block) { 1132 private void createReturnBlock(Block block) {
1140 if (method().isConstructor() && method().holder().superType() == null) { 1133 if (method.isConstructor() && method.holder().superType() == null) {
1141 callRegisterFinalizer(); 1134 callRegisterFinalizer();
1142 } 1135 }
1143 CiKind returnKind = method().signature().returnKind().stackKind(); 1136 CiKind returnKind = method.signature().returnKind().stackKind();
1144 Value x = returnKind == CiKind.Void ? null : frameState.pop(returnKind); 1137 Value x = returnKind == CiKind.Void ? null : frameState.pop(returnKind);
1145 assert frameState.stackSize() == 0; 1138 assert frameState.stackSize() == 0;
1146 1139
1147 if (Modifier.isSynchronized(method().accessFlags())) { 1140 if (Modifier.isSynchronized(method.accessFlags())) {
1148 genMonitorExit(rootMethodSynchronizedObject); 1141 genMonitorExit(methodSynchronizedObject);
1149 } 1142 }
1150 append(graph.createReturn(x)); 1143 append(graph.createReturn(x));
1151 } 1144 }
1152 1145
1153 private void createExceptionDispatch(ExceptionBlock block) { 1146 private void createExceptionDispatch(ExceptionBlock block) {
1216 } 1209 }
1217 } 1210 }
1218 1211
1219 private void traceState() { 1212 private void traceState() {
1220 if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) { 1213 if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) {
1221 log.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method())); 1214 log.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method));
1222 for (int i = 0; i < frameState.localsSize(); ++i) { 1215 for (int i = 0; i < frameState.localsSize(); ++i) {
1223 Value value = frameState.localAt(i); 1216 Value value = frameState.localAt(i);
1224 log.println(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value)); 1217 log.println(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
1225 } 1218 }
1226 for (int i = 0; i < frameState.stackSize(); ++i) { 1219 for (int i = 0; i < frameState.stackSize(); ++i) {
1415 case LRETURN : genReturn(frameState.lpop()); break; 1408 case LRETURN : genReturn(frameState.lpop()); break;
1416 case FRETURN : genReturn(frameState.fpop()); break; 1409 case FRETURN : genReturn(frameState.fpop()); break;
1417 case DRETURN : genReturn(frameState.dpop()); break; 1410 case DRETURN : genReturn(frameState.dpop()); break;
1418 case ARETURN : genReturn(frameState.apop()); break; 1411 case ARETURN : genReturn(frameState.apop()); break;
1419 case RETURN : genReturn(null ); break; 1412 case RETURN : genReturn(null ); break;
1420 case GETSTATIC : cpi = stream.readCPI(); genGetStatic(cpi, constantPool().lookupField(cpi, opcode)); break; 1413 case GETSTATIC : cpi = stream.readCPI(); genGetStatic(cpi, constantPool.lookupField(cpi, opcode)); break;
1421 case PUTSTATIC : cpi = stream.readCPI(); genPutStatic(cpi, constantPool().lookupField(cpi, opcode)); break; 1414 case PUTSTATIC : cpi = stream.readCPI(); genPutStatic(cpi, constantPool.lookupField(cpi, opcode)); break;
1422 case GETFIELD : cpi = stream.readCPI(); genGetField(cpi, constantPool().lookupField(cpi, opcode)); break; 1415 case GETFIELD : cpi = stream.readCPI(); genGetField(cpi, constantPool.lookupField(cpi, opcode)); break;
1423 case PUTFIELD : cpi = stream.readCPI(); genPutField(cpi, constantPool().lookupField(cpi, opcode)); break; 1416 case PUTFIELD : cpi = stream.readCPI(); genPutField(cpi, constantPool.lookupField(cpi, opcode)); break;
1424 case INVOKEVIRTUAL : cpi = stream.readCPI(); genInvokeVirtual(constantPool().lookupMethod(cpi, opcode), cpi, constantPool()); break; 1417 case INVOKEVIRTUAL : cpi = stream.readCPI(); genInvokeVirtual(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
1425 case INVOKESPECIAL : cpi = stream.readCPI(); genInvokeSpecial(constantPool().lookupMethod(cpi, opcode), null, cpi, constantPool()); break; 1418 case INVOKESPECIAL : cpi = stream.readCPI(); genInvokeSpecial(constantPool.lookupMethod(cpi, opcode), null, cpi, constantPool); break;
1426 case INVOKESTATIC : cpi = stream.readCPI(); genInvokeStatic(constantPool().lookupMethod(cpi, opcode), cpi, constantPool()); break; 1419 case INVOKESTATIC : cpi = stream.readCPI(); genInvokeStatic(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
1427 case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(constantPool().lookupMethod(cpi, opcode), cpi, constantPool()); break; 1420 case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
1428 case NEW : genNewInstance(stream.readCPI()); break; 1421 case NEW : genNewInstance(stream.readCPI()); break;
1429 case NEWARRAY : genNewTypeArray(stream.readLocalIndex()); break; 1422 case NEWARRAY : genNewTypeArray(stream.readLocalIndex()); break;
1430 case ANEWARRAY : genNewObjectArray(stream.readCPI()); break; 1423 case ANEWARRAY : genNewObjectArray(stream.readCPI()); break;
1431 case ARRAYLENGTH : genArrayLength(); break; 1424 case ARRAYLENGTH : genArrayLength(); break;
1432 case ATHROW : genThrow(stream.currentBCI()); break; 1425 case ATHROW : genThrow(stream.currentBCI()); break;
1466 1459
1467 private void genArrayLength() { 1460 private void genArrayLength() {
1468 frameState.ipush(append(new ArrayLength(frameState.apop(), graph))); 1461 frameState.ipush(append(new ArrayLength(frameState.apop(), graph)));
1469 } 1462 }
1470 1463
1471 private RiConstantPool constantPool() {
1472 return constantPool;
1473 }
1474
1475 /** 1464 /**
1476 * Adds a block to the worklist, if it is not already in the worklist. 1465 * Adds a block to the worklist, if it is not already in the worklist.
1477 * This method will keep the worklist topologically stored (i.e. the lower 1466 * This method will keep the worklist topologically stored (i.e. the lower
1478 * DFNs are earlier in the list). 1467 * DFNs are earlier in the list).
1479 * @param block the block to add to the work list 1468 * @param block the block to add to the work list