comparison graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/GraphBuilder.java @ 2874:d90bf514d647

Renamed packages.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 08 Jun 2011 08:59:54 +0200
parents graal/com.oracle.max.graal.compiler/src/com/sun/c1x/graph/GraphBuilder.java@0341b6424579
children 3570f1f7903e 9fcc456bbc18
comparison
equal deleted inserted replaced
2873:810e2d253e00 2874:d90bf514d647
1 /*
2 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.max.graal.compiler.graph;
24
25 import static com.sun.cri.bytecode.Bytecodes.*;
26 import static java.lang.reflect.Modifier.*;
27
28 import java.lang.reflect.*;
29 import java.util.*;
30
31 import com.oracle.max.graal.compiler.*;
32 import com.oracle.max.graal.compiler.debug.*;
33 import com.oracle.max.graal.compiler.graph.BlockMap.*;
34 import com.oracle.max.graal.compiler.graph.BlockMap.Block;
35 import com.oracle.max.graal.compiler.ir.*;
36 import com.oracle.max.graal.compiler.schedule.*;
37 import com.oracle.max.graal.compiler.util.*;
38 import com.oracle.max.graal.compiler.value.*;
39 import com.oracle.max.graal.graph.*;
40 import com.sun.cri.bytecode.*;
41 import com.sun.cri.ci.*;
42 import com.sun.cri.ri.*;
43 import com.sun.cri.ri.RiType.*;
44
45 /**
46 * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
47 * A number of optimizations may be performed during parsing of the bytecode, including value
48 * numbering, inlining, constant folding, strength reduction, etc.
49 */
50 public final class GraphBuilder {
51
52 /**
53 * The minimum value to which {@link C1XOptions#TraceBytecodeParserLevel} must be set to trace
54 * the bytecode instructions as they are parsed.
55 */
56 public static final int TRACELEVEL_INSTRUCTIONS = 1;
57
58 /**
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.
61 */
62 public static final int TRACELEVEL_STATE = 2;
63
64 private final C1XCompilation compilation;
65 private final CompilerGraph graph;
66
67 private final CiStatistics stats;
68 private final RiRuntime runtime;
69 private final RiMethod method;
70 private final RiConstantPool constantPool;
71
72 private final BytecodeStream stream; // the bytecode stream
73 private final LogStream log;
74 private final FrameStateBuilder frameState; // the current execution state
75
76 // bci-to-block mapping
77 private Block[] blockFromBci;
78 private ArrayList<Block> blockList;
79
80 private int nextBlockNumber;
81
82 private Value methodSynchronizedObject;
83 private CiExceptionHandler syncHandler;
84
85 private Block unwindBlock;
86 private Block returnBlock;
87
88 // the worklist of blocks, sorted by depth first number
89 private final PriorityQueue<Block> workList = new PriorityQueue<Block>(10, new Comparator<Block>() {
90 public int compare(Block o1, Block o2) {
91 return o1.blockID - o2.blockID;
92 }
93 });
94
95 private Instruction lastInstr; // the last instruction added
96
97 private final Set<Block> blocksOnWorklist = new HashSet<Block>();
98 private final Set<Block> blocksVisited = new HashSet<Block>();
99
100
101 /**
102 * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation.
103 *
104 * @param compilation the compilation
105 * @param ir the IR to build the graph into
106 * @param graph
107 */
108 public GraphBuilder(C1XCompilation compilation, RiMethod method, CompilerGraph graph) {
109 this.compilation = compilation;
110 this.graph = graph;
111
112 this.runtime = compilation.runtime;
113 this.method = method;
114 this.stats = compilation.stats;
115 this.log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null;
116 this.stream = new BytecodeStream(method.code());
117
118 this.constantPool = runtime.getConstantPool(method);
119 this.frameState = new FrameStateBuilder(method, graph);
120 }
121
122 /**
123 * Builds the graph for a the specified {@code IRScope}.
124 *
125 * @param createUnwind setting this to true will always generate an unwind block, even if there is no exception
126 * handler and the method is not synchronized
127 */
128 public void build(boolean createUnwind) {
129 if (log != null) {
130 log.println();
131 log.println("Compiling " + method);
132 }
133
134 // 2. compute the block map, setup exception handlers and get the entrypoint(s)
135 BlockMap blockMap = compilation.getBlockMap(method);
136
137 blockList = new ArrayList<Block>(blockMap.blocks);
138 blockFromBci = new Block[method.code().length];
139 for (int i = 0; i < blockList.size(); i++) {
140 int blockID = nextBlockNumber();
141 assert blockID == i;
142 Block block = blockList.get(i);
143 if (block.startBci >= 0) {
144 blockFromBci[block.startBci] = block;
145 }
146 }
147
148 // 1. create the start block
149 Block startBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI);
150 markOnWorkList(startBlock);
151 lastInstr = createTarget(startBlock, frameState);
152 graph.start().setStart(lastInstr);
153
154 if (isSynchronized(method.accessFlags())) {
155 // 4A.1 add a monitor enter to the start block
156 methodSynchronizedObject = synchronizedObject(frameState, method);
157 genMonitorEnter(methodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI);
158 // 4A.2 finish the start block
159 finishStartBlock(startBlock);
160
161 // 4A.3 setup an exception handler to unlock the root method synchronized object
162 syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null);
163 } else {
164 // 4B.1 simply finish the start block
165 finishStartBlock(startBlock);
166
167 if (createUnwind) {
168 syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null);
169 }
170 }
171
172 // 5. SKIPPED: look for intrinsics
173
174 // 6B.1 do the normal parsing
175 addToWorkList(blockFromBci[0]);
176 iterateAllBlocks();
177
178 // remove Placeholders
179 for (Node n : graph.getNodes()) {
180 if (n instanceof Placeholder) {
181 Placeholder p = (Placeholder) n;
182 assert p.blockPredecessors().size() == 1;
183 Node pred = p.blockPredecessors().get(0);
184 int predIndex = p.predecessorsIndex().get(0);
185 pred.successors().setAndClear(predIndex, p, 0);
186 p.delete();
187 }
188 }
189
190 // remove FrameStates
191 for (Node n : graph.getNodes()) {
192 if (n instanceof FrameState) {
193 boolean delete = false;
194 if (n.usages().size() == 0 && n.predecessors().size() == 0) {
195 delete = true;
196 }
197 if (delete) {
198 n.delete();
199 }
200 }
201 }
202 }
203
204 private int nextBlockNumber() {
205 stats.blockCount++;
206 return nextBlockNumber++;
207 }
208
209 private Block nextBlock(int bci) {
210 Block block = new Block();
211 block.startBci = bci;
212 block.endBci = bci;
213 block.blockID = nextBlockNumber();
214 return block;
215 }
216
217 private Block unwindBlock() {
218 if (unwindBlock == null) {
219 unwindBlock = new Block();
220 unwindBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
221 unwindBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
222 unwindBlock.blockID = nextBlockNumber();
223 addToWorkList(unwindBlock);
224 }
225 return unwindBlock;
226 }
227
228 private Block returnBlock() {
229 if (returnBlock == null) {
230 returnBlock = new Block();
231 returnBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
232 returnBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
233 returnBlock.blockID = nextBlockNumber();
234 addToWorkList(returnBlock);
235 }
236 return returnBlock;
237 }
238
239 private void markOnWorkList(Block block) {
240 blocksOnWorklist.add(block);
241 }
242
243 private boolean isOnWorkList(Block block) {
244 return blocksOnWorklist.contains(block);
245 }
246
247 private void markVisited(Block block) {
248 blocksVisited.add(block);
249 }
250
251 private boolean isVisited(Block block) {
252 return blocksVisited.contains(block);
253 }
254
255 private void finishStartBlock(Block startBlock) {
256 assert bci() == 0;
257 Instruction target = createTargetAt(0, frameState);
258 appendGoto(target);
259 }
260
261 public void mergeOrClone(Block target, FrameStateAccess newState) {
262 Instruction first = target.firstInstruction;
263 if (target.isLoopHeader && isVisited(target)) {
264 first = ((LoopBegin) first).loopEnd();
265 }
266 assert first instanceof StateSplit;
267
268 int bci = target.startBci;
269
270 FrameState existingState = ((StateSplit) first).stateBefore();
271
272 if (existingState == null) {
273 // copy state because it is modified
274 FrameState duplicate = newState.duplicate(bci);
275
276 // if the block is a loop header, insert all necessary phis
277 if (first instanceof LoopBegin && target.isLoopHeader) {
278 assert first instanceof Merge;
279 insertLoopPhis((Merge) first, duplicate);
280 ((Merge) first).setStateBefore(duplicate);
281 } else {
282 ((StateSplit) first).setStateBefore(duplicate);
283 }
284 } else {
285 if (!C1XOptions.AssumeVerifiedBytecode && !existingState.isCompatibleWith(newState)) {
286 // stacks or locks do not match--bytecodes would not verify
287 TTY.println(existingState.toString());
288 TTY.println(newState.duplicate(0).toString());
289 throw new CiBailout("stack or locks do not match");
290 }
291 assert existingState.localsSize() == newState.localsSize();
292 assert existingState.stackSize() == newState.stackSize();
293
294 if (first instanceof Placeholder) {
295 assert !target.isLoopHeader;
296 Merge merge = new Merge(graph);
297
298 Placeholder p = (Placeholder) first;
299 assert p.next() == null;
300 p.replace(merge);
301 target.firstInstruction = merge;
302 merge.setStateBefore(existingState);
303 first = merge;
304 }
305
306 existingState.merge((Merge) first, newState);
307 }
308
309 for (int j = 0; j < frameState.localsSize() + frameState.stackSize(); ++j) {
310 if (frameState.valueAt(j) != null) {
311 assert !frameState.valueAt(j).isDeleted();
312 }
313 }
314 }
315
316 private void insertLoopPhis(Merge merge, FrameState newState) {
317 int stackSize = newState.stackSize();
318 for (int i = 0; i < stackSize; i++) {
319 // always insert phis for the stack
320 Value x = newState.stackAt(i);
321 if (x != null) {
322 newState.setupPhiForStack(merge, i).addInput(x);
323 }
324 }
325 int localsSize = newState.localsSize();
326 for (int i = 0; i < localsSize; i++) {
327 Value x = newState.localAt(i);
328 if (x != null) {
329 newState.setupPhiForLocal(merge, i).addInput(x);
330 }
331 }
332 }
333
334 public BytecodeStream stream() {
335 return stream;
336 }
337
338 public int bci() {
339 return stream.currentBCI();
340 }
341
342 private void loadLocal(int index, CiKind kind) {
343 frameState.push(kind, frameState.loadLocal(index));
344 }
345
346 private void storeLocal(CiKind kind, int index) {
347 frameState.storeLocal(index, frameState.pop(kind));
348 }
349
350 public boolean covers(RiExceptionHandler handler, int bci) {
351 return handler.startBCI() <= bci && bci < handler.endBCI();
352 }
353
354 public boolean isCatchAll(RiExceptionHandler handler) {
355 return handler.catchTypeCPI() == 0;
356 }
357
358 private Instruction handleException(Value exceptionObject, int bci) {
359 assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci";
360
361 RiExceptionHandler firstHandler = null;
362 RiExceptionHandler[] exceptionHandlers = method.exceptionHandlers();
363 // join with all potential exception handlers
364 if (exceptionHandlers != null) {
365 for (RiExceptionHandler handler : exceptionHandlers) {
366 // if the handler covers this bytecode index, add it to the list
367 if (covers(handler, bci)) {
368 firstHandler = handler;
369 break;
370 }
371 }
372 }
373
374 if (firstHandler == null) {
375 firstHandler = syncHandler;
376 }
377
378 if (firstHandler != null) {
379 compilation.setHasExceptionHandlers();
380
381 Block dispatchBlock = null;
382 for (Block block : blockList) {
383 if (block instanceof ExceptionBlock) {
384 ExceptionBlock excBlock = (ExceptionBlock) block;
385 if (excBlock.handler == firstHandler) {
386 dispatchBlock = block;
387 break;
388 }
389 }
390 }
391 // if there's no dispatch block then the catch block needs to be a catch all
392 if (dispatchBlock == null) {
393 assert isCatchAll(firstHandler);
394 int handlerBCI = firstHandler.handlerBCI();
395 if (handlerBCI == Instruction.SYNCHRONIZATION_ENTRY_BCI) {
396 dispatchBlock = unwindBlock();
397 } else {
398 dispatchBlock = blockFromBci[handlerBCI];
399 }
400 }
401 FrameState entryState = frameState.duplicateWithEmptyStack(bci);
402
403 StateSplit entry = new Placeholder(graph);
404 entry.setStateBefore(entryState);
405
406 Instruction currentNext = entry;
407 Value currentExceptionObject = exceptionObject;
408 if (currentExceptionObject == null) {
409 ExceptionObject exception = new ExceptionObject(graph);
410 entry.setNext(exception);
411 currentNext = exception;
412 currentExceptionObject = exception;
413 }
414 FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, currentExceptionObject);
415
416 Instruction successor = createTarget(dispatchBlock, stateWithException);
417 currentNext.setNext(successor);
418 return entry;
419 }
420 return null;
421 }
422
423 private void genLoadConstant(int cpi) {
424 Object con = constantPool.lookupConstant(cpi);
425
426 if (con instanceof RiType) {
427 // this is a load of class constant which might be unresolved
428 RiType riType = (RiType) con;
429 if (!riType.isResolved()) {
430 append(new Deoptimize(graph));
431 frameState.push(CiKind.Object, append(Constant.forObject(null, graph)));
432 } else {
433 frameState.push(CiKind.Object, append(new Constant(riType.getEncoding(Representation.JavaClass), graph)));
434 }
435 } else if (con instanceof CiConstant) {
436 CiConstant constant = (CiConstant) con;
437 frameState.push(constant.kind.stackKind(), appendConstant(constant));
438 } else {
439 throw new Error("lookupConstant returned an object of incorrect type");
440 }
441 }
442
443 private void genLoadIndexed(CiKind kind) {
444 Value index = frameState.ipop();
445 Value array = frameState.apop();
446 Value length = append(new ArrayLength(array, graph));
447 Value v = append(new LoadIndexed(array, index, length, kind, graph));
448 frameState.push(kind.stackKind(), v);
449 }
450
451 private void genStoreIndexed(CiKind kind) {
452 Value value = frameState.pop(kind.stackKind());
453 Value index = frameState.ipop();
454 Value array = frameState.apop();
455 Value length = append(new ArrayLength(array, graph));
456 StoreIndexed result = new StoreIndexed(array, index, length, kind, value, graph);
457 append(result);
458 }
459
460 private void stackOp(int opcode) {
461 switch (opcode) {
462 case POP: {
463 frameState.xpop();
464 break;
465 }
466 case POP2: {
467 frameState.xpop();
468 frameState.xpop();
469 break;
470 }
471 case DUP: {
472 Value w = frameState.xpop();
473 frameState.xpush(w);
474 frameState.xpush(w);
475 break;
476 }
477 case DUP_X1: {
478 Value w1 = frameState.xpop();
479 Value w2 = frameState.xpop();
480 frameState.xpush(w1);
481 frameState.xpush(w2);
482 frameState.xpush(w1);
483 break;
484 }
485 case DUP_X2: {
486 Value w1 = frameState.xpop();
487 Value w2 = frameState.xpop();
488 Value w3 = frameState.xpop();
489 frameState.xpush(w1);
490 frameState.xpush(w3);
491 frameState.xpush(w2);
492 frameState.xpush(w1);
493 break;
494 }
495 case DUP2: {
496 Value w1 = frameState.xpop();
497 Value w2 = frameState.xpop();
498 frameState.xpush(w2);
499 frameState.xpush(w1);
500 frameState.xpush(w2);
501 frameState.xpush(w1);
502 break;
503 }
504 case DUP2_X1: {
505 Value w1 = frameState.xpop();
506 Value w2 = frameState.xpop();
507 Value w3 = frameState.xpop();
508 frameState.xpush(w2);
509 frameState.xpush(w1);
510 frameState.xpush(w3);
511 frameState.xpush(w2);
512 frameState.xpush(w1);
513 break;
514 }
515 case DUP2_X2: {
516 Value w1 = frameState.xpop();
517 Value w2 = frameState.xpop();
518 Value w3 = frameState.xpop();
519 Value w4 = frameState.xpop();
520 frameState.xpush(w2);
521 frameState.xpush(w1);
522 frameState.xpush(w4);
523 frameState.xpush(w3);
524 frameState.xpush(w2);
525 frameState.xpush(w1);
526 break;
527 }
528 case SWAP: {
529 Value w1 = frameState.xpop();
530 Value w2 = frameState.xpop();
531 frameState.xpush(w1);
532 frameState.xpush(w2);
533 break;
534 }
535 default:
536 throw Util.shouldNotReachHere();
537 }
538
539 }
540
541 private void genArithmeticOp(CiKind kind, int opcode) {
542 genArithmeticOp(kind, opcode, false);
543 }
544
545 private void genArithmeticOp(CiKind kind, int opcode, boolean canTrap) {
546 genArithmeticOp(kind, opcode, kind, kind, canTrap);
547 }
548
549 private void genArithmeticOp(CiKind result, int opcode, CiKind x, CiKind y, boolean canTrap) {
550 Value yValue = frameState.pop(y);
551 Value xValue = frameState.pop(x);
552 Value result1 = append(new Arithmetic(opcode, result, xValue, yValue, isStrict(method.accessFlags()), canTrap, graph));
553 if (canTrap) {
554 append(new ValueAnchor(result1, graph));
555 }
556 frameState.push(result, result1);
557 }
558
559 private void genNegateOp(CiKind kind) {
560 frameState.push(kind, append(new Negate(frameState.pop(kind), graph)));
561 }
562
563 private void genShiftOp(CiKind kind, int opcode) {
564 Value s = frameState.ipop();
565 Value x = frameState.pop(kind);
566 Shift v;
567 switch(opcode){
568 case ISHL:
569 case LSHL: v = new LeftShift(kind, x, s, graph); break;
570 case ISHR:
571 case LSHR: v = new RightShift(kind, x, s, graph); break;
572 case IUSHR:
573 case LUSHR: v = new UnsignedRightShift(kind, x, s, graph); break;
574 default:
575 throw new CiBailout("should not reach");
576 }
577 frameState.push(kind, append(v));
578 }
579
580 private void genLogicOp(CiKind kind, int opcode) {
581 Value y = frameState.pop(kind);
582 Value x = frameState.pop(kind);
583 Logic v;
584 switch(opcode){
585 case IAND:
586 case LAND: v = new And(kind, x, y, graph); break;
587 case IOR:
588 case LOR: v = new Or(kind, x, y, graph); break;
589 case IXOR:
590 case LXOR: v = new Xor(kind, x, y, graph); break;
591 default:
592 throw new CiBailout("should not reach");
593 }
594 frameState.push(kind, append(v));
595 }
596
597 private void genCompareOp(CiKind kind, int opcode, CiKind resultKind) {
598 Value y = frameState.pop(kind);
599 Value x = frameState.pop(kind);
600 Value value = append(new NormalizeCompare(opcode, resultKind, x, y, graph));
601 if (!resultKind.isVoid()) {
602 frameState.ipush(value);
603 }
604 }
605
606 private void genConvert(int opcode, CiKind from, CiKind to) {
607 CiKind tt = to.stackKind();
608 frameState.push(tt, append(new Convert(opcode, frameState.pop(from.stackKind()), tt, graph)));
609 }
610
611 private void genIncrement() {
612 int index = stream().readLocalIndex();
613 int delta = stream().readIncrement();
614 Value x = frameState.localAt(index);
615 Value y = append(Constant.forInt(delta, graph));
616 frameState.storeLocal(index, append(new Arithmetic(IADD, CiKind.Int, x, y, isStrict(method.accessFlags()), false, graph)));
617 }
618
619 private void genGoto(int fromBCI, int toBCI) {
620 appendGoto(createTargetAt(toBCI, frameState));
621 }
622
623 private void ifNode(Value x, Condition cond, Value y) {
624 assert !x.isDeleted() && !y.isDeleted();
625 If ifNode = new If(new Compare(x, cond, y, graph), graph);
626 append(ifNode);
627 Instruction tsucc = createTargetAt(stream().readBranchDest(), frameState);
628 ifNode.setBlockSuccessor(0, tsucc);
629 Instruction fsucc = createTargetAt(stream().nextBCI(), frameState);
630 ifNode.setBlockSuccessor(1, fsucc);
631 }
632
633 private void genIfZero(Condition cond) {
634 Value y = appendConstant(CiConstant.INT_0);
635 Value x = frameState.ipop();
636 ifNode(x, cond, y);
637 }
638
639 private void genIfNull(Condition cond) {
640 Value y = appendConstant(CiConstant.NULL_OBJECT);
641 Value x = frameState.apop();
642 ifNode(x, cond, y);
643 }
644
645 private void genIfSame(CiKind kind, Condition cond) {
646 Value y = frameState.pop(kind);
647 Value x = frameState.pop(kind);
648 assert !x.isDeleted() && !y.isDeleted();
649 ifNode(x, cond, y);
650 }
651
652 private void genThrow(int bci) {
653 Value exception = frameState.apop();
654 append(new NullCheck(exception, graph));
655
656 Instruction entry = handleException(exception, bci);
657 if (entry != null) {
658 append(entry);
659 } else {
660 frameState.clearStack();
661 frameState.apush(exception);
662 appendGoto(createTarget(unwindBlock(), frameState));
663 }
664 }
665
666 private void genCheckCast() {
667 int cpi = stream().readCPI();
668 RiType type = constantPool.lookupType(cpi, CHECKCAST);
669 boolean isInitialized = type.isResolved();
670 Value typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi);
671 Value object = frameState.apop();
672 if (typeInstruction != null) {
673 frameState.apush(append(new CheckCast(type, typeInstruction, object, graph)));
674 } else {
675 frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
676 }
677 }
678
679 private void genInstanceOf() {
680 int cpi = stream().readCPI();
681 RiType type = constantPool.lookupType(cpi, INSTANCEOF);
682 boolean isInitialized = type.isResolved();
683 Value typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi);
684 Value object = frameState.apop();
685 if (typeInstruction != null) {
686 frameState.ipush(append(new InstanceOf(type, typeInstruction, object, graph)));
687 } else {
688 frameState.ipush(appendConstant(CiConstant.INT_0));
689 }
690 }
691
692 void genNewInstance(int cpi) {
693 RiType type = constantPool.lookupType(cpi, NEW);
694 if (type.isResolved()) {
695 NewInstance n = new NewInstance(type, cpi, constantPool, graph);
696 frameState.apush(append(n));
697 } else {
698 append(new Deoptimize(graph));
699 frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
700 }
701 }
702
703 private void genNewTypeArray(int typeCode) {
704 CiKind kind = CiKind.fromArrayTypeCode(typeCode);
705 RiType elementType = runtime.asRiType(kind);
706 NewTypeArray nta = new NewTypeArray(frameState.ipop(), elementType, graph);
707 frameState.apush(append(nta));
708 }
709
710 private void genNewObjectArray(int cpi) {
711 RiType type = constantPool.lookupType(cpi, ANEWARRAY);
712 Value length = frameState.ipop();
713 if (type.isResolved()) {
714 NewArray n = new NewObjectArray(type, length, graph);
715 frameState.apush(append(n));
716 } else {
717 append(new Deoptimize(graph));
718 frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
719 }
720
721 }
722
723 private void genNewMultiArray(int cpi) {
724 RiType type = constantPool.lookupType(cpi, MULTIANEWARRAY);
725 int rank = stream().readUByte(bci() + 3);
726 Value[] dims = new Value[rank];
727 for (int i = rank - 1; i >= 0; i--) {
728 dims[i] = frameState.ipop();
729 }
730 if (type.isResolved()) {
731 NewArray n = new NewMultiArray(type, dims, cpi, constantPool, graph);
732 frameState.apush(append(n));
733 } else {
734 append(new Deoptimize(graph));
735 frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
736 }
737 }
738
739 private void genGetField(int cpi, RiField field) {
740 CiKind kind = field.kind();
741 Value receiver = frameState.apop();
742 if (field.isResolved()) {
743 LoadField load = new LoadField(receiver, field, graph);
744 appendOptimizedLoadField(kind, load);
745 } else {
746 append(new Deoptimize(graph));
747 frameState.push(kind.stackKind(), append(Constant.defaultForKind(kind, graph)));
748 }
749 }
750
751 private void genPutField(int cpi, RiField field) {
752 Value value = frameState.pop(field.kind().stackKind());
753 Value receiver = frameState.apop();
754 if (field.isResolved()) {
755 StoreField store = new StoreField(receiver, field, value, graph);
756 appendOptimizedStoreField(store);
757 } else {
758 append(new Deoptimize(graph));
759 }
760 }
761
762 private void genGetStatic(int cpi, RiField field) {
763 RiType holder = field.holder();
764 boolean isInitialized = field.isResolved();
765 CiConstant constantValue = null;
766 if (isInitialized) {
767 constantValue = field.constantValue(null);
768 }
769 if (constantValue != null) {
770 frameState.push(constantValue.kind.stackKind(), appendConstant(constantValue));
771 } else {
772 Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi);
773 CiKind kind = field.kind();
774 if (container != null) {
775 LoadField load = new LoadField(container, field, graph);
776 appendOptimizedLoadField(kind, load);
777 } else {
778 append(new Deoptimize(graph));
779 frameState.push(kind.stackKind(), append(Constant.defaultForKind(kind, graph)));
780 }
781 }
782 }
783
784 private void genPutStatic(int cpi, RiField field) {
785 RiType holder = field.holder();
786 Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, field.isResolved(), cpi);
787 Value value = frameState.pop(field.kind().stackKind());
788 if (container != null) {
789 StoreField store = new StoreField(container, field, value, graph);
790 appendOptimizedStoreField(store);
791 } else {
792 append(new Deoptimize(graph));
793 }
794 }
795
796 private Value genTypeOrDeopt(RiType.Representation representation, RiType holder, boolean initialized, int cpi) {
797 if (initialized) {
798 return appendConstant(holder.getEncoding(representation));
799 } else {
800 append(new Deoptimize(graph));
801 return null;
802 }
803 }
804
805 private void appendOptimizedStoreField(StoreField store) {
806 append(store);
807 }
808
809 private void appendOptimizedLoadField(CiKind kind, LoadField load) {
810 // append the load to the instruction
811 Value optimized = append(load);
812 frameState.push(kind.stackKind(), optimized);
813 }
814
815 private void genInvokeStatic(RiMethod target, int cpi, RiConstantPool constantPool) {
816 RiType holder = target.holder();
817 boolean isInitialized = target.isResolved() && holder.isInitialized();
818 if (!isInitialized && C1XOptions.ResolveClassBeforeStaticInvoke) {
819 // Re-use the same resolution code as for accessing a static field. Even though
820 // the result of resolution is not used by the invocation (only the side effect
821 // of initialization is required), it can be commoned with static field accesses.
822 genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi);
823 }
824 Value[] args = frameState.popArguments(target.signature().argumentSlots(false));
825 appendInvoke(INVOKESTATIC, target, args, cpi, constantPool);
826 }
827
828 private void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) {
829 Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
830 genInvokeIndirect(INVOKEINTERFACE, target, args, cpi, constantPool);
831
832 }
833
834 private void genInvokeVirtual(RiMethod target, int cpi, RiConstantPool constantPool) {
835 Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
836 genInvokeIndirect(INVOKEVIRTUAL, target, args, cpi, constantPool);
837
838 }
839
840 private void genInvokeSpecial(RiMethod target, RiType knownHolder, int cpi, RiConstantPool constantPool) {
841 Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
842 invokeDirect(target, args, knownHolder, cpi, constantPool);
843
844 }
845
846 private void genInvokeIndirect(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) {
847 Value receiver = args[0];
848 // attempt to devirtualize the call
849 if (target.isResolved()) {
850 RiType klass = target.holder();
851
852 // 0. check for trivial cases
853 if (target.canBeStaticallyBound() && !isAbstract(target.accessFlags())) {
854 // check for trivial cases (e.g. final methods, nonvirtual methods)
855 invokeDirect(target, args, target.holder(), cpi, constantPool);
856 return;
857 }
858 // 1. check if the exact type of the receiver can be determined
859 RiType exact = getExactType(klass, receiver);
860 if (exact != null && exact.isResolved()) {
861 // either the holder class is exact, or the receiver object has an exact type
862 invokeDirect(exact.resolveMethodImpl(target), args, exact, cpi, constantPool);
863 return;
864 }
865 }
866 // devirtualization failed, produce an actual invokevirtual
867 appendInvoke(opcode, target, args, cpi, constantPool);
868 }
869
870 private CiKind returnKind(RiMethod target) {
871 return target.signature().returnKind();
872 }
873
874 private void invokeDirect(RiMethod target, Value[] args, RiType knownHolder, int cpi, RiConstantPool constantPool) {
875 appendInvoke(INVOKESPECIAL, target, args, cpi, constantPool);
876 }
877
878 private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) {
879 CiKind resultType = returnKind(target);
880 Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), graph);
881 Value result = appendWithBCI(invoke);
882 invoke.setExceptionEdge(handleException(null, bci()));
883 frameState.pushReturn(resultType, result);
884 }
885
886 private RiType getExactType(RiType staticType, Value receiver) {
887 RiType exact = staticType.exactType();
888 if (exact == null) {
889 exact = receiver.exactType();
890 if (exact == null) {
891 if (receiver.isConstant()) {
892 exact = runtime.getTypeOf(receiver.asConstant());
893 }
894 if (exact == null) {
895 RiType declared = receiver.declaredType();
896 exact = declared == null || !declared.isResolved() ? null : declared.exactType();
897 }
898 }
899 }
900 return exact;
901 }
902
903 private void callRegisterFinalizer() {
904 Value receiver = frameState.loadLocal(0);
905 RiType declaredType = receiver.declaredType();
906 RiType receiverType = declaredType;
907 RiType exactType = receiver.exactType();
908 if (exactType == null && declaredType != null) {
909 exactType = declaredType.exactType();
910 }
911 if (exactType == null && receiver instanceof Local && ((Local) receiver).index() == 0) {
912 // the exact type isn't known, but the receiver is parameter 0 => use holder
913 receiverType = method.holder();
914 exactType = receiverType.exactType();
915 }
916 boolean needsCheck = true;
917 if (exactType != null) {
918 // we have an exact type
919 needsCheck = exactType.hasFinalizer();
920 } else {
921 // if either the declared type of receiver or the holder can be assumed to have no finalizers
922 if (declaredType != null && !declaredType.hasFinalizableSubclass()) {
923 if (compilation.recordNoFinalizableSubclassAssumption(declaredType)) {
924 needsCheck = false;
925 }
926 }
927
928 if (receiverType != null && !receiverType.hasFinalizableSubclass()) {
929 if (compilation.recordNoFinalizableSubclassAssumption(receiverType)) {
930 needsCheck = false;
931 }
932 }
933 }
934
935 if (needsCheck) {
936 // append a call to the finalizer registration
937 append(new RegisterFinalizer(frameState.loadLocal(0), frameState.create(bci()), graph));
938 C1XMetrics.InlinedFinalizerChecks++;
939 }
940 }
941
942 private void genReturn(Value x) {
943 frameState.clearStack();
944 if (x != null) {
945 frameState.push(x.kind, x);
946 }
947 appendGoto(createTarget(returnBlock(), frameState));
948 }
949
950 private void genMonitorEnter(Value x, int bci) {
951 int lockNumber = frameState.locksSize();
952 MonitorAddress lockAddress = null;
953 if (runtime.sizeOfBasicObjectLock() != 0) {
954 lockAddress = new MonitorAddress(lockNumber, graph);
955 append(lockAddress);
956 }
957 MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, graph);
958 appendWithBCI(monitorEnter);
959 frameState.lock(x);
960 if (bci == Instruction.SYNCHRONIZATION_ENTRY_BCI) {
961 monitorEnter.setStateAfter(frameState.create(0));
962 }
963 }
964
965 private void genMonitorExit(Value x) {
966 int lockNumber = frameState.locksSize() - 1;
967 if (lockNumber < 0) {
968 throw new CiBailout("monitor stack underflow");
969 }
970 MonitorAddress lockAddress = null;
971 if (runtime.sizeOfBasicObjectLock() != 0) {
972 lockAddress = new MonitorAddress(lockNumber, graph);
973 append(lockAddress);
974 }
975 appendWithBCI(new MonitorExit(x, lockAddress, lockNumber, graph));
976 frameState.unlock();
977 }
978
979 private void genJsr(int dest) {
980 throw new CiBailout("jsr/ret not supported");
981 }
982
983 private void genRet(int localIndex) {
984 throw new CiBailout("jsr/ret not supported");
985 }
986
987 private void genTableswitch() {
988 int bci = bci();
989 Value value = frameState.ipop();
990 BytecodeTableSwitch ts = new BytecodeTableSwitch(stream(), bci);
991 int max = ts.numberOfCases();
992 List<Instruction> list = new ArrayList<Instruction>(max + 1);
993 List<Integer> offsetList = new ArrayList<Integer>(max + 1);
994 for (int i = 0; i < max; i++) {
995 // add all successors to the successor list
996 int offset = ts.offsetAt(i);
997 list.add(null);
998 offsetList.add(offset);
999 }
1000 int offset = ts.defaultOffset();
1001 list.add(null);
1002 offsetList.add(offset);
1003 TableSwitch tableSwitch = new TableSwitch(value, list, ts.lowKey(), graph);
1004 for (int i = 0; i < offsetList.size(); ++i) {
1005 tableSwitch.setBlockSuccessor(i, createTargetAt(bci + offsetList.get(i), frameState));
1006 }
1007 append(tableSwitch);
1008 }
1009
1010 private void genLookupswitch() {
1011 int bci = bci();
1012 Value value = frameState.ipop();
1013 BytecodeLookupSwitch ls = new BytecodeLookupSwitch(stream(), bci);
1014 int max = ls.numberOfCases();
1015 List<Instruction> list = new ArrayList<Instruction>(max + 1);
1016 List<Integer> offsetList = new ArrayList<Integer>(max + 1);
1017 int[] keys = new int[max];
1018 for (int i = 0; i < max; i++) {
1019 // add all successors to the successor list
1020 int offset = ls.offsetAt(i);
1021 list.add(null);
1022 offsetList.add(offset);
1023 keys[i] = ls.keyAt(i);
1024 }
1025 int offset = ls.defaultOffset();
1026 list.add(null);
1027 offsetList.add(offset);
1028 LookupSwitch lookupSwitch = new LookupSwitch(value, list, keys, graph);
1029 for (int i = 0; i < offsetList.size(); ++i) {
1030 lookupSwitch.setBlockSuccessor(i, createTargetAt(bci + offsetList.get(i), frameState));
1031 }
1032 append(lookupSwitch);
1033 }
1034
1035 private Value appendConstant(CiConstant constant) {
1036 return append(new Constant(constant, graph));
1037 }
1038
1039 private Value append(Instruction x) {
1040 return appendWithBCI(x);
1041 }
1042
1043 private Value append(Value v) {
1044 return v;
1045 }
1046
1047 private Value appendWithBCI(Instruction x) {
1048 assert x.predecessors().size() == 0 : "instruction should not have been appended yet";
1049 assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
1050 lastInstr.setNext(x);
1051
1052 lastInstr = x;
1053 if (++stats.nodeCount >= C1XOptions.MaximumInstructionCount) {
1054 // bailout if we've exceeded the maximum inlining size
1055 throw new CiBailout("Method and/or inlining is too large");
1056 }
1057
1058 return x;
1059 }
1060
1061 private Instruction createTargetAt(int bci, FrameStateAccess stateAfter) {
1062 return createTarget(blockFromBci[bci], stateAfter);
1063 }
1064
1065 private Instruction createTarget(Block block, FrameStateAccess stateAfter) {
1066 assert block != null && stateAfter != null;
1067 assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null : "non-loop block must be iterated after all its predecessors";
1068
1069 if (block.isExceptionEntry) {
1070 assert stateAfter.stackSize() == 1;
1071 }
1072
1073 if (block.firstInstruction == null) {
1074 if (block.isLoopHeader) {
1075 // block.firstInstruction = new Merge(block.startBci, graph);
1076
1077 LoopBegin loopBegin = new LoopBegin(graph);
1078 LoopEnd loopEnd = new LoopEnd(graph);
1079 loopEnd.setLoopBegin(loopBegin);
1080 block.firstInstruction = loopBegin;
1081 } else {
1082 block.firstInstruction = new Placeholder(graph);
1083 }
1084 }
1085 mergeOrClone(block, stateAfter);
1086 addToWorkList(block);
1087
1088 if (block.firstInstruction instanceof LoopBegin && isVisited(block)) {
1089 return ((LoopBegin) block.firstInstruction).loopEnd();
1090 } else {
1091 return block.firstInstruction;
1092 }
1093 }
1094
1095 private Value synchronizedObject(FrameStateAccess state, RiMethod target) {
1096 if (isStatic(target.accessFlags())) {
1097 Constant classConstant = new Constant(target.holder().getEncoding(Representation.JavaClass), graph);
1098 return append(classConstant);
1099 } else {
1100 return state.localAt(0);
1101 }
1102 }
1103
1104 private void iterateAllBlocks() {
1105 Block block;
1106 while ((block = removeFromWorkList()) != null) {
1107
1108 // remove blocks that have no predecessors by the time it their bytecodes are parsed
1109 if (block.firstInstruction == null) {
1110 markVisited(block);
1111 continue;
1112 }
1113
1114 if (!isVisited(block)) {
1115 markVisited(block);
1116 // now parse the block
1117 frameState.initializeFrom(((StateSplit) block.firstInstruction).stateBefore());
1118 lastInstr = block.firstInstruction;
1119 assert block.firstInstruction.next() == null : "instructions already appended at block " + block.blockID;
1120
1121 if (block == returnBlock) {
1122 createReturnBlock(block);
1123 } else if (block == unwindBlock) {
1124 createUnwindBlock(block);
1125 } else if (block instanceof ExceptionBlock) {
1126 createExceptionDispatch((ExceptionBlock) block);
1127 } else {
1128 iterateBytecodesForBlock(block);
1129 }
1130 }
1131 }
1132 for (Block b : blocksVisited) {
1133 if (b.isLoopHeader) {
1134 LoopBegin begin = (LoopBegin) b.firstInstruction;
1135 LoopEnd end = begin.loopEnd();
1136
1137 // This can happen with degenerated loops like this one:
1138 // for (;;) {
1139 // try {
1140 // break;
1141 // } catch (UnresolvedException iioe) {
1142 // }
1143 // }
1144 if (end.stateBefore() != null) {
1145 begin.stateBefore().merge(begin, end.stateBefore());
1146 } else {
1147 end.delete();
1148 Merge merge = new Merge(graph);
1149 merge.successors().setAndClear(merge.nextIndex(), begin, begin.nextIndex());
1150 begin.replace(merge);
1151 }
1152 }
1153 }
1154 }
1155
1156 private void createUnwindBlock(Block block) {
1157 if (Modifier.isSynchronized(method.accessFlags())) {
1158 genMonitorExit(methodSynchronizedObject);
1159 }
1160 append(graph.createUnwind(frameState.apop()));
1161 }
1162
1163 private void createReturnBlock(Block block) {
1164 if (method.isConstructor() && method.holder().superType() == null) {
1165 callRegisterFinalizer();
1166 }
1167 CiKind returnKind = method.signature().returnKind().stackKind();
1168 Value x = returnKind == CiKind.Void ? null : frameState.pop(returnKind);
1169 assert frameState.stackSize() == 0;
1170
1171 if (Modifier.isSynchronized(method.accessFlags())) {
1172 genMonitorExit(methodSynchronizedObject);
1173 }
1174 append(graph.createReturn(x));
1175 }
1176
1177 private void createExceptionDispatch(ExceptionBlock block) {
1178 if (block.handler == null) {
1179 assert frameState.stackSize() == 1 : "only exception object expected on stack, actual size: " + frameState.stackSize();
1180 createUnwindBlock(block);
1181 } else {
1182 assert frameState.stackSize() == 1;
1183
1184 Block nextBlock = block.next == null ? unwindBlock() : block.next;
1185 if (block.handler.catchType().isResolved()) {
1186 Instruction catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState);
1187 Instruction nextDispatch = createTarget(nextBlock, frameState);
1188 append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph));
1189 } else {
1190 Deoptimize deopt = new Deoptimize(graph);
1191 deopt.setMessage("unresolved " + block.handler.catchType().name());
1192 append(deopt);
1193 Instruction nextDispatch = createTarget(nextBlock, frameState);
1194 appendGoto(nextDispatch);
1195 }
1196 }
1197 }
1198
1199 private void appendGoto(Instruction target) {
1200 lastInstr.setNext(target);
1201 }
1202
1203 private void iterateBytecodesForBlock(Block block) {
1204 assert frameState != null;
1205
1206 stream.setBCI(block.startBci);
1207
1208 int endBCI = stream.endBCI();
1209 boolean blockStart = true;
1210
1211 int bci = block.startBci;
1212 while (bci < endBCI) {
1213 Block nextBlock = blockFromBci[bci];
1214 if (nextBlock != null && nextBlock != block) {
1215 assert !nextBlock.isExceptionEntry;
1216 // we fell through to the next block, add a goto and break
1217 appendGoto(createTarget(nextBlock, frameState));
1218 break;
1219 }
1220 // read the opcode
1221 int opcode = stream.currentBC();
1222
1223 traceState();
1224 traceInstruction(bci, opcode, blockStart);
1225 processBytecode(bci, opcode);
1226
1227 if (Schedule.isBlockEnd(lastInstr) || lastInstr.next() != null) {
1228 break;
1229 }
1230
1231 stream.next();
1232 bci = stream.currentBCI();
1233 if (lastInstr instanceof StateSplit) {
1234 StateSplit stateSplit = (StateSplit) lastInstr;
1235 if (stateSplit.stateAfter() == null && stateSplit.needsStateAfter()) {
1236 stateSplit.setStateAfter(frameState.create(bci));
1237 }
1238 }
1239 blockStart = false;
1240 }
1241 }
1242
1243 private void traceState() {
1244 if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) {
1245 log.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method));
1246 for (int i = 0; i < frameState.localsSize(); ++i) {
1247 Value value = frameState.localAt(i);
1248 log.println(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
1249 }
1250 for (int i = 0; i < frameState.stackSize(); ++i) {
1251 Value value = frameState.stackAt(i);
1252 log.println(String.format("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
1253 }
1254 for (int i = 0; i < frameState.locksSize(); ++i) {
1255 Value value = frameState.lockAt(i);
1256 log.println(String.format("| lock[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
1257 }
1258 }
1259 }
1260
1261 private void processBytecode(int bci, int opcode) {
1262 int cpi;
1263
1264 // Checkstyle: stop
1265 switch (opcode) {
1266 case NOP : /* nothing to do */ break;
1267 case ACONST_NULL : frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); break;
1268 case ICONST_M1 : frameState.ipush(appendConstant(CiConstant.INT_MINUS_1)); break;
1269 case ICONST_0 : frameState.ipush(appendConstant(CiConstant.INT_0)); break;
1270 case ICONST_1 : frameState.ipush(appendConstant(CiConstant.INT_1)); break;
1271 case ICONST_2 : frameState.ipush(appendConstant(CiConstant.INT_2)); break;
1272 case ICONST_3 : frameState.ipush(appendConstant(CiConstant.INT_3)); break;
1273 case ICONST_4 : frameState.ipush(appendConstant(CiConstant.INT_4)); break;
1274 case ICONST_5 : frameState.ipush(appendConstant(CiConstant.INT_5)); break;
1275 case LCONST_0 : frameState.lpush(appendConstant(CiConstant.LONG_0)); break;
1276 case LCONST_1 : frameState.lpush(appendConstant(CiConstant.LONG_1)); break;
1277 case FCONST_0 : frameState.fpush(appendConstant(CiConstant.FLOAT_0)); break;
1278 case FCONST_1 : frameState.fpush(appendConstant(CiConstant.FLOAT_1)); break;
1279 case FCONST_2 : frameState.fpush(appendConstant(CiConstant.FLOAT_2)); break;
1280 case DCONST_0 : frameState.dpush(appendConstant(CiConstant.DOUBLE_0)); break;
1281 case DCONST_1 : frameState.dpush(appendConstant(CiConstant.DOUBLE_1)); break;
1282 case BIPUSH : frameState.ipush(appendConstant(CiConstant.forInt(stream.readByte()))); break;
1283 case SIPUSH : frameState.ipush(appendConstant(CiConstant.forInt(stream.readShort()))); break;
1284 case LDC : // fall through
1285 case LDC_W : // fall through
1286 case LDC2_W : genLoadConstant(stream.readCPI()); break;
1287 case ILOAD : loadLocal(stream.readLocalIndex(), CiKind.Int); break;
1288 case LLOAD : loadLocal(stream.readLocalIndex(), CiKind.Long); break;
1289 case FLOAD : loadLocal(stream.readLocalIndex(), CiKind.Float); break;
1290 case DLOAD : loadLocal(stream.readLocalIndex(), CiKind.Double); break;
1291 case ALOAD : loadLocal(stream.readLocalIndex(), CiKind.Object); break;
1292 case ILOAD_0 : // fall through
1293 case ILOAD_1 : // fall through
1294 case ILOAD_2 : // fall through
1295 case ILOAD_3 : loadLocal(opcode - ILOAD_0, CiKind.Int); break;
1296 case LLOAD_0 : // fall through
1297 case LLOAD_1 : // fall through
1298 case LLOAD_2 : // fall through
1299 case LLOAD_3 : loadLocal(opcode - LLOAD_0, CiKind.Long); break;
1300 case FLOAD_0 : // fall through
1301 case FLOAD_1 : // fall through
1302 case FLOAD_2 : // fall through
1303 case FLOAD_3 : loadLocal(opcode - FLOAD_0, CiKind.Float); break;
1304 case DLOAD_0 : // fall through
1305 case DLOAD_1 : // fall through
1306 case DLOAD_2 : // fall through
1307 case DLOAD_3 : loadLocal(opcode - DLOAD_0, CiKind.Double); break;
1308 case ALOAD_0 : // fall through
1309 case ALOAD_1 : // fall through
1310 case ALOAD_2 : // fall through
1311 case ALOAD_3 : loadLocal(opcode - ALOAD_0, CiKind.Object); break;
1312 case IALOAD : genLoadIndexed(CiKind.Int ); break;
1313 case LALOAD : genLoadIndexed(CiKind.Long ); break;
1314 case FALOAD : genLoadIndexed(CiKind.Float ); break;
1315 case DALOAD : genLoadIndexed(CiKind.Double); break;
1316 case AALOAD : genLoadIndexed(CiKind.Object); break;
1317 case BALOAD : genLoadIndexed(CiKind.Byte ); break;
1318 case CALOAD : genLoadIndexed(CiKind.Char ); break;
1319 case SALOAD : genLoadIndexed(CiKind.Short ); break;
1320 case ISTORE : storeLocal(CiKind.Int, stream.readLocalIndex()); break;
1321 case LSTORE : storeLocal(CiKind.Long, stream.readLocalIndex()); break;
1322 case FSTORE : storeLocal(CiKind.Float, stream.readLocalIndex()); break;
1323 case DSTORE : storeLocal(CiKind.Double, stream.readLocalIndex()); break;
1324 case ASTORE : storeLocal(CiKind.Object, stream.readLocalIndex()); break;
1325 case ISTORE_0 : // fall through
1326 case ISTORE_1 : // fall through
1327 case ISTORE_2 : // fall through
1328 case ISTORE_3 : storeLocal(CiKind.Int, opcode - ISTORE_0); break;
1329 case LSTORE_0 : // fall through
1330 case LSTORE_1 : // fall through
1331 case LSTORE_2 : // fall through
1332 case LSTORE_3 : storeLocal(CiKind.Long, opcode - LSTORE_0); break;
1333 case FSTORE_0 : // fall through
1334 case FSTORE_1 : // fall through
1335 case FSTORE_2 : // fall through
1336 case FSTORE_3 : storeLocal(CiKind.Float, opcode - FSTORE_0); break;
1337 case DSTORE_0 : // fall through
1338 case DSTORE_1 : // fall through
1339 case DSTORE_2 : // fall through
1340 case DSTORE_3 : storeLocal(CiKind.Double, opcode - DSTORE_0); break;
1341 case ASTORE_0 : // fall through
1342 case ASTORE_1 : // fall through
1343 case ASTORE_2 : // fall through
1344 case ASTORE_3 : storeLocal(CiKind.Object, opcode - ASTORE_0); break;
1345 case IASTORE : genStoreIndexed(CiKind.Int ); break;
1346 case LASTORE : genStoreIndexed(CiKind.Long ); break;
1347 case FASTORE : genStoreIndexed(CiKind.Float ); break;
1348 case DASTORE : genStoreIndexed(CiKind.Double); break;
1349 case AASTORE : genStoreIndexed(CiKind.Object); break;
1350 case BASTORE : genStoreIndexed(CiKind.Byte ); break;
1351 case CASTORE : genStoreIndexed(CiKind.Char ); break;
1352 case SASTORE : genStoreIndexed(CiKind.Short ); break;
1353 case POP : // fall through
1354 case POP2 : // fall through
1355 case DUP : // fall through
1356 case DUP_X1 : // fall through
1357 case DUP_X2 : // fall through
1358 case DUP2 : // fall through
1359 case DUP2_X1 : // fall through
1360 case DUP2_X2 : // fall through
1361 case SWAP : stackOp(opcode); break;
1362 case IADD : // fall through
1363 case ISUB : // fall through
1364 case IMUL : genArithmeticOp(CiKind.Int, opcode); break;
1365 case IDIV : // fall through
1366 case IREM : genArithmeticOp(CiKind.Int, opcode, true); break;
1367 case LADD : // fall through
1368 case LSUB : // fall through
1369 case LMUL : genArithmeticOp(CiKind.Long, opcode); break;
1370 case LDIV : // fall through
1371 case LREM : genArithmeticOp(CiKind.Long, opcode, true); break;
1372 case FADD : // fall through
1373 case FSUB : // fall through
1374 case FMUL : // fall through
1375 case FDIV : // fall through
1376 case FREM : genArithmeticOp(CiKind.Float, opcode); break;
1377 case DADD : // fall through
1378 case DSUB : // fall through
1379 case DMUL : // fall through
1380 case DDIV : // fall through
1381 case DREM : genArithmeticOp(CiKind.Double, opcode); break;
1382 case INEG : genNegateOp(CiKind.Int); break;
1383 case LNEG : genNegateOp(CiKind.Long); break;
1384 case FNEG : genNegateOp(CiKind.Float); break;
1385 case DNEG : genNegateOp(CiKind.Double); break;
1386 case ISHL : // fall through
1387 case ISHR : // fall through
1388 case IUSHR : genShiftOp(CiKind.Int, opcode); break;
1389 case IAND : // fall through
1390 case IOR : // fall through
1391 case IXOR : genLogicOp(CiKind.Int, opcode); break;
1392 case LSHL : // fall through
1393 case LSHR : // fall through
1394 case LUSHR : genShiftOp(CiKind.Long, opcode); break;
1395 case LAND : // fall through
1396 case LOR : // fall through
1397 case LXOR : genLogicOp(CiKind.Long, opcode); break;
1398 case IINC : genIncrement(); break;
1399 case I2L : genConvert(opcode, CiKind.Int , CiKind.Long ); break;
1400 case I2F : genConvert(opcode, CiKind.Int , CiKind.Float ); break;
1401 case I2D : genConvert(opcode, CiKind.Int , CiKind.Double); break;
1402 case L2I : genConvert(opcode, CiKind.Long , CiKind.Int ); break;
1403 case L2F : genConvert(opcode, CiKind.Long , CiKind.Float ); break;
1404 case L2D : genConvert(opcode, CiKind.Long , CiKind.Double); break;
1405 case F2I : genConvert(opcode, CiKind.Float , CiKind.Int ); break;
1406 case F2L : genConvert(opcode, CiKind.Float , CiKind.Long ); break;
1407 case F2D : genConvert(opcode, CiKind.Float , CiKind.Double); break;
1408 case D2I : genConvert(opcode, CiKind.Double, CiKind.Int ); break;
1409 case D2L : genConvert(opcode, CiKind.Double, CiKind.Long ); break;
1410 case D2F : genConvert(opcode, CiKind.Double, CiKind.Float ); break;
1411 case I2B : genConvert(opcode, CiKind.Int , CiKind.Byte ); break;
1412 case I2C : genConvert(opcode, CiKind.Int , CiKind.Char ); break;
1413 case I2S : genConvert(opcode, CiKind.Int , CiKind.Short ); break;
1414 case LCMP : genCompareOp(CiKind.Long, opcode, CiKind.Int); break;
1415 case FCMPL : genCompareOp(CiKind.Float, opcode, CiKind.Int); break;
1416 case FCMPG : genCompareOp(CiKind.Float, opcode, CiKind.Int); break;
1417 case DCMPL : genCompareOp(CiKind.Double, opcode, CiKind.Int); break;
1418 case DCMPG : genCompareOp(CiKind.Double, opcode, CiKind.Int); break;
1419 case IFEQ : genIfZero(Condition.EQ); break;
1420 case IFNE : genIfZero(Condition.NE); break;
1421 case IFLT : genIfZero(Condition.LT); break;
1422 case IFGE : genIfZero(Condition.GE); break;
1423 case IFGT : genIfZero(Condition.GT); break;
1424 case IFLE : genIfZero(Condition.LE); break;
1425 case IF_ICMPEQ : genIfSame(CiKind.Int, Condition.EQ); break;
1426 case IF_ICMPNE : genIfSame(CiKind.Int, Condition.NE); break;
1427 case IF_ICMPLT : genIfSame(CiKind.Int, Condition.LT); break;
1428 case IF_ICMPGE : genIfSame(CiKind.Int, Condition.GE); break;
1429 case IF_ICMPGT : genIfSame(CiKind.Int, Condition.GT); break;
1430 case IF_ICMPLE : genIfSame(CiKind.Int, Condition.LE); break;
1431 case IF_ACMPEQ : genIfSame(frameState.peekKind(), Condition.EQ); break;
1432 case IF_ACMPNE : genIfSame(frameState.peekKind(), Condition.NE); break;
1433 case GOTO : genGoto(stream.currentBCI(), stream.readBranchDest()); break;
1434 case JSR : genJsr(stream.readBranchDest()); break;
1435 case RET : genRet(stream.readLocalIndex()); break;
1436 case TABLESWITCH : genTableswitch(); break;
1437 case LOOKUPSWITCH : genLookupswitch(); break;
1438 case IRETURN : genReturn(frameState.ipop()); break;
1439 case LRETURN : genReturn(frameState.lpop()); break;
1440 case FRETURN : genReturn(frameState.fpop()); break;
1441 case DRETURN : genReturn(frameState.dpop()); break;
1442 case ARETURN : genReturn(frameState.apop()); break;
1443 case RETURN : genReturn(null ); break;
1444 case GETSTATIC : cpi = stream.readCPI(); genGetStatic(cpi, constantPool.lookupField(cpi, opcode)); break;
1445 case PUTSTATIC : cpi = stream.readCPI(); genPutStatic(cpi, constantPool.lookupField(cpi, opcode)); break;
1446 case GETFIELD : cpi = stream.readCPI(); genGetField(cpi, constantPool.lookupField(cpi, opcode)); break;
1447 case PUTFIELD : cpi = stream.readCPI(); genPutField(cpi, constantPool.lookupField(cpi, opcode)); break;
1448 case INVOKEVIRTUAL : cpi = stream.readCPI(); genInvokeVirtual(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
1449 case INVOKESPECIAL : cpi = stream.readCPI(); genInvokeSpecial(constantPool.lookupMethod(cpi, opcode), null, cpi, constantPool); break;
1450 case INVOKESTATIC : cpi = stream.readCPI(); genInvokeStatic(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
1451 case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break;
1452 case NEW : genNewInstance(stream.readCPI()); break;
1453 case NEWARRAY : genNewTypeArray(stream.readLocalIndex()); break;
1454 case ANEWARRAY : genNewObjectArray(stream.readCPI()); break;
1455 case ARRAYLENGTH : genArrayLength(); break;
1456 case ATHROW : genThrow(stream.currentBCI()); break;
1457 case CHECKCAST : genCheckCast(); break;
1458 case INSTANCEOF : genInstanceOf(); break;
1459 case MONITORENTER : genMonitorEnter(frameState.apop(), stream.currentBCI()); break;
1460 case MONITOREXIT : genMonitorExit(frameState.apop()); break;
1461 case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break;
1462 case IFNULL : genIfNull(Condition.EQ); break;
1463 case IFNONNULL : genIfNull(Condition.NE); break;
1464 case GOTO_W : genGoto(stream.currentBCI(), stream.readFarBranchDest()); break;
1465 case JSR_W : genJsr(stream.readFarBranchDest()); break;
1466 case BREAKPOINT:
1467 throw new CiBailout("concurrent setting of breakpoint");
1468 default:
1469 throw new CiBailout("Unsupported opcode " + opcode + " (" + nameOf(opcode) + ") [bci=" + bci + "]");
1470 }
1471 // Checkstyle: resume
1472 }
1473
1474 private void traceInstruction(int bci, int opcode, boolean blockStart) {
1475 if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_INSTRUCTIONS && !TTY.isSuppressed()) {
1476 StringBuilder sb = new StringBuilder(40);
1477 sb.append(blockStart ? '+' : '|');
1478 if (bci < 10) {
1479 sb.append(" ");
1480 } else if (bci < 100) {
1481 sb.append(' ');
1482 }
1483 sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode));
1484 for (int i = bci + 1; i < stream.nextBCI(); ++i) {
1485 sb.append(' ').append(stream.readUByte(i));
1486 }
1487 log.println(sb.toString());
1488 }
1489 }
1490
1491 private void genArrayLength() {
1492 frameState.ipush(append(new ArrayLength(frameState.apop(), graph)));
1493 }
1494
1495 /**
1496 * Adds a block to the worklist, if it is not already in the worklist.
1497 * This method will keep the worklist topologically stored (i.e. the lower
1498 * DFNs are earlier in the list).
1499 * @param block the block to add to the work list
1500 */
1501 private void addToWorkList(Block block) {
1502 if (!isOnWorkList(block)) {
1503 markOnWorkList(block);
1504 sortIntoWorkList(block);
1505 }
1506 }
1507
1508 private void sortIntoWorkList(Block top) {
1509 workList.offer(top);
1510 }
1511
1512 /**
1513 * Removes the next block from the worklist. The list is sorted topologically, so the
1514 * block with the lowest depth first number in the list will be removed and returned.
1515 * @return the next block from the worklist; {@code null} if there are no blocks
1516 * in the worklist
1517 */
1518 private Block removeFromWorkList() {
1519 return workList.poll();
1520 }
1521 }