Mercurial > hg > truffle
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 |