comparison graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java @ 14902:c25b121d36ec

Rename BytecodeParseHelper to AbstractBytecodeParser.
author Josef Eisl <josef.eisl@jku.at>
date Mon, 31 Mar 2014 17:51:11 +0200
parents graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParseHelper.java@b4d069921b5f
children ea57ed7085cf
comparison
equal deleted inserted replaced
14901:b4d069921b5f 14902:c25b121d36ec
1 /*
2 * Copyright (c) 2014, 2014, 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
24 package com.oracle.graal.java;
25
26 import static com.oracle.graal.api.code.TypeCheckHints.*;
27 import static com.oracle.graal.bytecode.Bytecodes.*;
28 import static java.lang.reflect.Modifier.*;
29
30 import java.util.*;
31
32 import com.oracle.graal.api.code.*;
33 import com.oracle.graal.api.meta.*;
34 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
35 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
36 import com.oracle.graal.bytecode.*;
37 import com.oracle.graal.debug.*;
38 import com.oracle.graal.graph.*;
39 import com.oracle.graal.java.BciBlockMapping.BciBlock;
40 import com.oracle.graal.nodes.*;
41 import com.oracle.graal.nodes.calc.*;
42 import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert;
43 import com.oracle.graal.phases.*;
44
45 public abstract class AbstractBytecodeParser<T extends KindInterface, F extends AbstractFrameStateBuilder<T>> {
46
47 protected F frameState;
48 protected BytecodeStream stream; // the bytecode stream
49 private GraphBuilderConfiguration graphBuilderConfig;
50 protected ResolvedJavaMethod method;
51 protected BciBlock currentBlock;
52 protected ProfilingInfo profilingInfo;
53 protected OptimisticOptimizations optimisticOpts;
54 protected ConstantPool constantPool;
55 private final MetaAccessProvider metaAccess;
56 protected int entryBCI;
57
58 public AbstractBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, F frameState,
59 BytecodeStream stream, ProfilingInfo profilingInfo, ConstantPool constantPool, int entryBCI) {
60 this.frameState = frameState;
61 this.graphBuilderConfig = graphBuilderConfig;
62 this.optimisticOpts = optimisticOpts;
63 this.metaAccess = metaAccess;
64 this.stream = stream;
65 this.profilingInfo = profilingInfo;
66 this.constantPool = constantPool;
67 this.entryBCI = entryBCI;
68 this.method = method;
69 assert metaAccess != null;
70 }
71
72 /**
73 * Start the bytecode parser.
74 */
75 protected abstract void build();
76
77 public void setCurrentFrameState(F frameState) {
78 this.frameState = frameState;
79 }
80
81 public final void setStream(BytecodeStream stream) {
82 this.stream = stream;
83 }
84
85 protected final BytecodeStream getStream() {
86 return stream;
87 }
88
89 protected int bci() {
90 return stream.currentBCI();
91 }
92
93 public void loadLocal(int index, Kind kind) {
94 frameState.push(kind, frameState.loadLocal(index));
95 }
96
97 public void storeLocal(Kind kind, int index) {
98 T value;
99 if (kind == Kind.Object) {
100 value = frameState.xpop();
101 // astore and astore_<n> may be used to store a returnAddress (jsr)
102 assert value.getKind() == Kind.Object || value.getKind() == Kind.Int;
103 } else {
104 value = frameState.pop(kind);
105 }
106 frameState.storeLocal(index, value);
107 }
108
109 /**
110 * @param type the unresolved type of the constant
111 */
112 protected abstract void handleUnresolvedLoadConstant(JavaType type);
113
114 /**
115 * @param type the unresolved type of the type check
116 * @param object the object value whose type is being checked against {@code type}
117 */
118 protected abstract void handleUnresolvedCheckCast(JavaType type, T object);
119
120 /**
121 * @param type the unresolved type of the type check
122 * @param object the object value whose type is being checked against {@code type}
123 */
124 protected abstract void handleUnresolvedInstanceOf(JavaType type, T object);
125
126 /**
127 * @param type the type being instantiated
128 */
129 protected abstract void handleUnresolvedNewInstance(JavaType type);
130
131 /**
132 * @param type the type of the array being instantiated
133 * @param length the length of the array
134 */
135 protected abstract void handleUnresolvedNewObjectArray(JavaType type, T length);
136
137 /**
138 * @param type the type being instantiated
139 * @param dims the dimensions for the multi-array
140 */
141 protected abstract void handleUnresolvedNewMultiArray(JavaType type, List<T> dims);
142
143 /**
144 * @param field the unresolved field
145 * @param receiver the object containing the field or {@code null} if {@code field} is static
146 */
147 protected abstract void handleUnresolvedLoadField(JavaField field, T receiver);
148
149 /**
150 * @param field the unresolved field
151 * @param value the value being stored to the field
152 * @param receiver the object containing the field or {@code null} if {@code field} is static
153 */
154 protected abstract void handleUnresolvedStoreField(JavaField field, T value, T receiver);
155
156 /**
157 * @param representation
158 * @param type
159 */
160 protected abstract void handleUnresolvedExceptionType(Representation representation, JavaType type);
161
162 // protected abstract void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind);
163
164 // protected abstract DispatchBeginNode handleException(T exceptionObject, int bci);
165
166 private void genLoadConstant(int cpi, int opcode) {
167 Object con = lookupConstant(cpi, opcode);
168
169 if (con instanceof JavaType) {
170 // this is a load of class constant which might be unresolved
171 JavaType type = (JavaType) con;
172 if (type instanceof ResolvedJavaType) {
173 frameState.push(Kind.Object, appendConstant(((ResolvedJavaType) type).getEncoding(Representation.JavaClass)));
174 } else {
175 handleUnresolvedLoadConstant(type);
176 }
177 } else if (con instanceof Constant) {
178 Constant constant = (Constant) con;
179 frameState.push(constant.getKind().getStackKind(), appendConstant(constant));
180 } else {
181 throw new Error("lookupConstant returned an object of incorrect type");
182 }
183 }
184
185 protected abstract T genLoadIndexed(T index, T array, Kind kind);
186
187 private void genLoadIndexed(Kind kind) {
188 emitExplicitExceptions(frameState.peek(1), frameState.peek(0));
189
190 T index = frameState.ipop();
191 T array = frameState.apop();
192 frameState.push(kind.getStackKind(), append(genLoadIndexed(array, index, kind)));
193 }
194
195 protected abstract T genStoreIndexed(T array, T index, Kind kind, T value);
196
197 private void genStoreIndexed(Kind kind) {
198 emitExplicitExceptions(frameState.peek(2), frameState.peek(1));
199
200 T value = frameState.pop(kind.getStackKind());
201 T index = frameState.ipop();
202 T array = frameState.apop();
203 append(genStoreIndexed(array, index, kind, value));
204 }
205
206 private void stackOp(int opcode) {
207 switch (opcode) {
208 case POP: {
209 frameState.xpop();
210 break;
211 }
212 case POP2: {
213 frameState.xpop();
214 frameState.xpop();
215 break;
216 }
217 case DUP: {
218 T w = frameState.xpop();
219 frameState.xpush(w);
220 frameState.xpush(w);
221 break;
222 }
223 case DUP_X1: {
224 T w1 = frameState.xpop();
225 T w2 = frameState.xpop();
226 frameState.xpush(w1);
227 frameState.xpush(w2);
228 frameState.xpush(w1);
229 break;
230 }
231 case DUP_X2: {
232 T w1 = frameState.xpop();
233 T w2 = frameState.xpop();
234 T w3 = frameState.xpop();
235 frameState.xpush(w1);
236 frameState.xpush(w3);
237 frameState.xpush(w2);
238 frameState.xpush(w1);
239 break;
240 }
241 case DUP2: {
242 T w1 = frameState.xpop();
243 T w2 = frameState.xpop();
244 frameState.xpush(w2);
245 frameState.xpush(w1);
246 frameState.xpush(w2);
247 frameState.xpush(w1);
248 break;
249 }
250 case DUP2_X1: {
251 T w1 = frameState.xpop();
252 T w2 = frameState.xpop();
253 T w3 = frameState.xpop();
254 frameState.xpush(w2);
255 frameState.xpush(w1);
256 frameState.xpush(w3);
257 frameState.xpush(w2);
258 frameState.xpush(w1);
259 break;
260 }
261 case DUP2_X2: {
262 T w1 = frameState.xpop();
263 T w2 = frameState.xpop();
264 T w3 = frameState.xpop();
265 T w4 = frameState.xpop();
266 frameState.xpush(w2);
267 frameState.xpush(w1);
268 frameState.xpush(w4);
269 frameState.xpush(w3);
270 frameState.xpush(w2);
271 frameState.xpush(w1);
272 break;
273 }
274 case SWAP: {
275 T w1 = frameState.xpop();
276 T w2 = frameState.xpop();
277 frameState.xpush(w1);
278 frameState.xpush(w2);
279 break;
280 }
281 default:
282 throw GraalInternalError.shouldNotReachHere();
283 }
284 }
285
286 protected abstract T genIntegerAdd(Kind kind, T x, T y);
287
288 protected abstract T genIntegerSub(Kind kind, T x, T y);
289
290 protected abstract T genIntegerMul(Kind kind, T x, T y);
291
292 protected abstract T genFloatAdd(Kind kind, T x, T y, boolean isStrictFP);
293
294 protected abstract T genFloatSub(Kind kind, T x, T y, boolean isStrictFP);
295
296 protected abstract T genFloatMul(Kind kind, T x, T y, boolean isStrictFP);
297
298 protected abstract T genFloatDiv(Kind kind, T x, T y, boolean isStrictFP);
299
300 protected abstract T genFloatRem(Kind kind, T x, T y, boolean isStrictFP);
301
302 private void genArithmeticOp(Kind result, int opcode) {
303 T y = frameState.pop(result);
304 T x = frameState.pop(result);
305 boolean isStrictFP = isStrict(method.getModifiers());
306 T v;
307 switch (opcode) {
308 case IADD:
309 case LADD:
310 v = genIntegerAdd(result, x, y);
311 break;
312 case FADD:
313 case DADD:
314 v = genFloatAdd(result, x, y, isStrictFP);
315 break;
316 case ISUB:
317 case LSUB:
318 v = genIntegerSub(result, x, y);
319 break;
320 case FSUB:
321 case DSUB:
322 v = genFloatSub(result, x, y, isStrictFP);
323 break;
324 case IMUL:
325 case LMUL:
326 v = genIntegerMul(result, x, y);
327 break;
328 case FMUL:
329 case DMUL:
330 v = genFloatMul(result, x, y, isStrictFP);
331 break;
332 case FDIV:
333 case DDIV:
334 v = genFloatDiv(result, x, y, isStrictFP);
335 break;
336 case FREM:
337 case DREM:
338 v = genFloatRem(result, x, y, isStrictFP);
339 break;
340 default:
341 throw new GraalInternalError("should not reach");
342 }
343 frameState.push(result, append(v));
344 }
345
346 protected abstract T genIntegerDiv(Kind kind, T x, T y);
347
348 protected abstract T genIntegerRem(Kind kind, T x, T y);
349
350 private void genIntegerDivOp(Kind result, int opcode) {
351 T y = frameState.pop(result);
352 T x = frameState.pop(result);
353 T v;
354 switch (opcode) {
355 case IDIV:
356 case LDIV:
357 v = genIntegerDiv(result, x, y);
358 break;
359 case IREM:
360 case LREM:
361 v = genIntegerRem(result, x, y);
362 break;
363 default:
364 throw new GraalInternalError("should not reach");
365 }
366 frameState.push(result, append(v));
367 }
368
369 protected abstract T genNegateOp(T x);
370
371 private void genNegateOp(Kind kind) {
372 frameState.push(kind, append(genNegateOp(frameState.pop(kind))));
373 }
374
375 protected abstract T genLeftShift(Kind kind, T x, T y);
376
377 protected abstract T genRightShift(Kind kind, T x, T y);
378
379 protected abstract T genUnsignedRightShift(Kind kind, T x, T y);
380
381 private void genShiftOp(Kind kind, int opcode) {
382 T s = frameState.ipop();
383 T x = frameState.pop(kind);
384 T v;
385 switch (opcode) {
386 case ISHL:
387 case LSHL:
388 v = genLeftShift(kind, x, s);
389 break;
390 case ISHR:
391 case LSHR:
392 v = genRightShift(kind, x, s);
393 break;
394 case IUSHR:
395 case LUSHR:
396 v = genUnsignedRightShift(kind, x, s);
397 break;
398 default:
399 throw new GraalInternalError("should not reach");
400 }
401 frameState.push(kind, append(v));
402 }
403
404 protected abstract T genAnd(Kind kind, T x, T y);
405
406 protected abstract T genOr(Kind kind, T x, T y);
407
408 protected abstract T genXor(Kind kind, T x, T y);
409
410 private void genLogicOp(Kind kind, int opcode) {
411 T y = frameState.pop(kind);
412 T x = frameState.pop(kind);
413 T v;
414 switch (opcode) {
415 case IAND:
416 case LAND:
417 v = genAnd(kind, x, y);
418 break;
419 case IOR:
420 case LOR:
421 v = genOr(kind, x, y);
422 break;
423 case IXOR:
424 case LXOR:
425 v = genXor(kind, x, y);
426 break;
427 default:
428 throw new GraalInternalError("should not reach");
429 }
430 frameState.push(kind, append(v));
431 }
432
433 protected abstract T genNormalizeCompare(T x, T y, boolean isUnorderedLess);
434
435 private void genCompareOp(Kind kind, boolean isUnorderedLess) {
436 T y = frameState.pop(kind);
437 T x = frameState.pop(kind);
438 frameState.ipush(append(genNormalizeCompare(x, y, isUnorderedLess)));
439 }
440
441 protected abstract T genFloatConvert(FloatConvert op, T input);
442
443 private void genFloatConvert(FloatConvert op, Kind from, Kind to) {
444 T input = frameState.pop(from.getStackKind());
445 frameState.push(to.getStackKind(), append(genFloatConvert(op, input)));
446 }
447
448 protected abstract T genNarrow(T input, int bitCount);
449
450 protected abstract T genSignExtend(T input, int bitCount);
451
452 protected abstract T genZeroExtend(T input, int bitCount);
453
454 private void genSignExtend(Kind from, Kind to) {
455 T input = frameState.pop(from.getStackKind());
456 if (from != from.getStackKind()) {
457 input = append(genNarrow(input, from.getBitCount()));
458 }
459 frameState.push(to.getStackKind(), append(genSignExtend(input, to.getBitCount())));
460 }
461
462 private void genZeroExtend(Kind from, Kind to) {
463 T input = frameState.pop(from.getStackKind());
464 if (from != from.getStackKind()) {
465 input = append(genNarrow(input, from.getBitCount()));
466 }
467 frameState.push(to.getStackKind(), append(genZeroExtend(input, to.getBitCount())));
468 }
469
470 private void genNarrow(Kind from, Kind to) {
471 T input = frameState.pop(from.getStackKind());
472 frameState.push(to.getStackKind(), append(genNarrow(input, to.getBitCount())));
473 }
474
475 private void genIncrement() {
476 int index = getStream().readLocalIndex();
477 int delta = getStream().readIncrement();
478 T x = frameState.loadLocal(index);
479 T y = appendConstant(Constant.forInt(delta));
480 frameState.storeLocal(index, append(genIntegerAdd(Kind.Int, x, y)));
481 }
482
483 private void genGoto() {
484 appendGoto(createTarget(currentBlock.getSuccessors().get(0), frameState));
485 // assert currentBlock.numNormalSuccessors() == 1;
486 assert currentBlock.getSuccessors().size() == 1;
487 }
488
489 protected abstract T genObjectEquals(T x, T y);
490
491 protected abstract T genIntegerEquals(T x, T y);
492
493 protected abstract T genIntegerLessThan(T x, T y);
494
495 protected abstract T genUnique(T x);
496
497 protected abstract T genIf(T condition, T falseSuccessor, T trueSuccessor, double d);
498
499 private void ifNode(T x, Condition cond, T y) {
500 // assert !x.isDeleted() && !y.isDeleted();
501 // assert currentBlock.numNormalSuccessors() == 2;
502 assert currentBlock.getSuccessors().size() == 2;
503 BciBlock trueBlock = currentBlock.getSuccessors().get(0);
504 BciBlock falseBlock = currentBlock.getSuccessors().get(1);
505 if (trueBlock == falseBlock) {
506 appendGoto(createTarget(trueBlock, frameState));
507 return;
508 }
509
510 double probability = profilingInfo.getBranchTakenProbability(bci());
511 if (probability < 0) {
512 assert probability == -1 : "invalid probability";
513 Debug.log("missing probability in %s at bci %d", method, bci());
514 probability = 0.5;
515 }
516
517 if (!optimisticOpts.removeNeverExecutedCode()) {
518 if (probability == 0) {
519 probability = 0.0000001;
520 } else if (probability == 1) {
521 probability = 0.999999;
522 }
523 }
524
525 // the mirroring and negation operations get the condition into canonical form
526 boolean mirror = cond.canonicalMirror();
527 boolean negate = cond.canonicalNegate();
528
529 T a = mirror ? y : x;
530 T b = mirror ? x : y;
531
532 T condition;
533 assert !a.getKind().isNumericFloat();
534 if (cond == Condition.EQ || cond == Condition.NE) {
535 if (a.getKind() == Kind.Object) {
536 condition = genObjectEquals(a, b);
537 } else {
538 condition = genIntegerEquals(a, b);
539 }
540 } else {
541 assert a.getKind() != Kind.Object && !cond.isUnsigned();
542 condition = genIntegerLessThan(a, b);
543 }
544 condition = genUnique(condition);
545
546 T trueSuccessor = createBlockTarget(probability, trueBlock, frameState);
547 T falseSuccessor = createBlockTarget(1 - probability, falseBlock, frameState);
548
549 T ifNode = negate ? genIf(condition, falseSuccessor, trueSuccessor, 1 - probability) : genIf(condition, trueSuccessor, falseSuccessor, probability);
550 append(ifNode);
551 }
552
553 private void genIfZero(Condition cond) {
554 T y = appendConstant(Constant.INT_0);
555 T x = frameState.ipop();
556 ifNode(x, cond, y);
557 }
558
559 private void genIfNull(Condition cond) {
560 T y = appendConstant(Constant.NULL_OBJECT);
561 T x = frameState.apop();
562 ifNode(x, cond, y);
563 }
564
565 private void genIfSame(Kind kind, Condition cond) {
566 T y = frameState.pop(kind);
567 T x = frameState.pop(kind);
568 // assert !x.isDeleted() && !y.isDeleted();
569 ifNode(x, cond, y);
570 }
571
572 protected abstract void genThrow();
573
574 protected JavaType lookupType(int cpi, int bytecode) {
575 eagerResolvingForSnippets(cpi, bytecode);
576 JavaType result = constantPool.lookupType(cpi, bytecode);
577 assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType;
578 return result;
579 }
580
581 private JavaMethod lookupMethod(int cpi, int opcode) {
582 eagerResolvingForSnippets(cpi, opcode);
583 JavaMethod result = constantPool.lookupMethod(cpi, opcode);
584 /*
585 * In general, one cannot assume that the declaring class being initialized is useful, since
586 * the actual concrete receiver may be a different class (except for static calls). Also,
587 * interfaces are initialized only under special circumstances, so that this assertion would
588 * often fail for interface calls.
589 */
590 assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaMethod && (opcode != INVOKESTATIC || ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized())) : result;
591 return result;
592 }
593
594 private JavaField lookupField(int cpi, int opcode) {
595 eagerResolvingForSnippets(cpi, opcode);
596 JavaField result = constantPool.lookupField(cpi, opcode);
597 assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result;
598 return result;
599 }
600
601 private Object lookupConstant(int cpi, int opcode) {
602 eagerResolvingForSnippets(cpi, opcode);
603 Object result = constantPool.lookupConstant(cpi);
604 assert !graphBuilderConfig.eagerResolving() || !(result instanceof JavaType) || (result instanceof ResolvedJavaType) : result;
605 return result;
606 }
607
608 private void eagerResolvingForSnippets(int cpi, int bytecode) {
609 if (graphBuilderConfig.eagerResolving()) {
610 constantPool.loadReferencedType(cpi, bytecode);
611 }
612 }
613
614 private JavaTypeProfile getProfileForTypeCheck(ResolvedJavaType type) {
615 if (!optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) {
616 return null;
617 } else {
618 return profilingInfo.getTypeProfile(bci());
619 }
620 }
621
622 protected abstract T genCheckCast(ResolvedJavaType type, T object, JavaTypeProfile profileForTypeCheck, boolean b);
623
624 private void genCheckCast() {
625 int cpi = getStream().readCPI();
626 JavaType type = lookupType(cpi, CHECKCAST);
627 T object = frameState.apop();
628 if (type instanceof ResolvedJavaType) {
629 JavaTypeProfile profileForTypeCheck = getProfileForTypeCheck((ResolvedJavaType) type);
630 T checkCastNode = append(genCheckCast((ResolvedJavaType) type, object, profileForTypeCheck, false));
631 frameState.apush(checkCastNode);
632 } else {
633 handleUnresolvedCheckCast(type, object);
634 }
635 }
636
637 protected abstract T genInstanceOf(ResolvedJavaType type, T object, JavaTypeProfile profileForTypeCheck);
638
639 protected abstract T genConditional(T x);
640
641 private void genInstanceOf() {
642 int cpi = getStream().readCPI();
643 JavaType type = lookupType(cpi, INSTANCEOF);
644 T object = frameState.apop();
645 if (type instanceof ResolvedJavaType) {
646 ResolvedJavaType resolvedType = (ResolvedJavaType) type;
647 T instanceOfNode = genInstanceOf((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType));
648 frameState.ipush(append(genConditional(genUnique(instanceOfNode))));
649 } else {
650 handleUnresolvedInstanceOf(type, object);
651 }
652 }
653
654 protected abstract T createNewInstance(ResolvedJavaType type, boolean fillContents);
655
656 void genNewInstance(int cpi) {
657 JavaType type = lookupType(cpi, NEW);
658 if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) {
659 frameState.apush(append(createNewInstance((ResolvedJavaType) type, true)));
660 } else {
661 handleUnresolvedNewInstance(type);
662 }
663 }
664
665 /**
666 * Gets the kind of array elements for the array type code that appears in a
667 * {@link Bytecodes#NEWARRAY} bytecode.
668 *
669 * @param code the array type code
670 * @return the kind from the array type code
671 */
672 public static Class<?> arrayTypeCodeToClass(int code) {
673 // Checkstyle: stop
674 switch (code) {
675 case 4:
676 return boolean.class;
677 case 5:
678 return char.class;
679 case 6:
680 return float.class;
681 case 7:
682 return double.class;
683 case 8:
684 return byte.class;
685 case 9:
686 return short.class;
687 case 10:
688 return int.class;
689 case 11:
690 return long.class;
691 default:
692 throw new IllegalArgumentException("unknown array type code: " + code);
693 }
694 // Checkstyle: resume
695 }
696
697 private void genNewPrimitiveArray(int typeCode) {
698 Class<?> clazz = arrayTypeCodeToClass(typeCode);
699 ResolvedJavaType elementType = metaAccess.lookupJavaType(clazz);
700 frameState.apush(append(createNewArray(elementType, frameState.ipop(), true)));
701 }
702
703 private void genNewObjectArray(int cpi) {
704 JavaType type = lookupType(cpi, ANEWARRAY);
705 T length = frameState.ipop();
706 if (type instanceof ResolvedJavaType) {
707 frameState.apush(append(createNewArray((ResolvedJavaType) type, length, true)));
708 } else {
709 handleUnresolvedNewObjectArray(type, length);
710 }
711
712 }
713
714 protected abstract T createNewArray(ResolvedJavaType elementType, T length, boolean fillContents);
715
716 private void genNewMultiArray(int cpi) {
717 JavaType type = lookupType(cpi, MULTIANEWARRAY);
718 int rank = getStream().readUByte(bci() + 3);
719 List<T> dims = new ArrayList<>(Collections.nCopies(rank, null));
720 for (int i = rank - 1; i >= 0; i--) {
721 dims.set(i, frameState.ipop());
722 }
723 if (type instanceof ResolvedJavaType) {
724 frameState.apush(append(createNewMultiArray((ResolvedJavaType) type, dims)));
725 } else {
726 handleUnresolvedNewMultiArray(type, dims);
727 }
728 }
729
730 protected abstract T createNewMultiArray(ResolvedJavaType type, List<T> dims);
731
732 protected abstract T genLoadField(T receiver, ResolvedJavaField field);
733
734 private void genGetField(JavaField field) {
735 emitExplicitExceptions(frameState.peek(0), null);
736
737 Kind kind = field.getKind();
738 T receiver = frameState.apop();
739 if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) {
740 appendOptimizedLoadField(kind, genLoadField(receiver, (ResolvedJavaField) field));
741 } else {
742 handleUnresolvedLoadField(field, receiver);
743 }
744 }
745
746 protected abstract void emitNullCheck(T receiver);
747
748 protected static final ArrayIndexOutOfBoundsException cachedArrayIndexOutOfBoundsException = new ArrayIndexOutOfBoundsException();
749 protected static final NullPointerException cachedNullPointerException = new NullPointerException();
750 static {
751 cachedArrayIndexOutOfBoundsException.setStackTrace(new StackTraceElement[0]);
752 cachedNullPointerException.setStackTrace(new StackTraceElement[0]);
753 }
754
755 protected abstract void emitBoundsCheck(T index, T length);
756
757 private static final DebugMetric EXPLICIT_EXCEPTIONS = Debug.metric("ExplicitExceptions");
758
759 protected abstract T genArrayLength(T x);
760
761 protected void emitExplicitExceptions(T receiver, T outOfBoundsIndex) {
762 assert receiver != null;
763 if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) {
764 return;
765 }
766
767 emitNullCheck(receiver);
768 if (outOfBoundsIndex != null) {
769 T length = append(genArrayLength(receiver));
770 emitBoundsCheck(outOfBoundsIndex, length);
771 }
772 EXPLICIT_EXCEPTIONS.increment();
773 }
774
775 protected abstract T genStoreField(T receiver, ResolvedJavaField field, T value);
776
777 private void genPutField(JavaField field) {
778 emitExplicitExceptions(frameState.peek(1), null);
779
780 T value = frameState.pop(field.getKind().getStackKind());
781 T receiver = frameState.apop();
782 if (field instanceof ResolvedJavaField && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) {
783 appendOptimizedStoreField(genStoreField(receiver, (ResolvedJavaField) field, value));
784 } else {
785 handleUnresolvedStoreField(field, value, receiver);
786 }
787 }
788
789 private void genGetStatic(JavaField field) {
790 Kind kind = field.getKind();
791 if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
792 appendOptimizedLoadField(kind, genLoadField(null, (ResolvedJavaField) field));
793 } else {
794 handleUnresolvedLoadField(field, null);
795 }
796 }
797
798 private void genPutStatic(JavaField field) {
799 T value = frameState.pop(field.getKind().getStackKind());
800 if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
801 appendOptimizedStoreField(genStoreField(null, (ResolvedJavaField) field, value));
802 } else {
803 handleUnresolvedStoreField(field, value, null);
804 }
805 }
806
807 protected void appendOptimizedStoreField(T store) {
808 append(store);
809 }
810
811 protected void appendOptimizedLoadField(Kind kind, T load) {
812 // append the load to the instruction
813 T optimized = append(load);
814 frameState.push(kind.getStackKind(), optimized);
815 }
816
817 protected abstract void genInvokeStatic(JavaMethod target);
818
819 protected abstract void genInvokeInterface(JavaMethod target);
820
821 protected abstract void genInvokeDynamic(JavaMethod target);
822
823 protected abstract void genInvokeVirtual(JavaMethod target);
824
825 protected abstract void genInvokeSpecial(JavaMethod target);
826
827 protected abstract void genReturn(T x);
828
829 protected abstract T genMonitorEnter(T x);
830
831 protected abstract T genMonitorExit(T x, T returnValue);
832
833 protected abstract void genJsr(int dest);
834
835 protected abstract void genRet(int localIndex);
836
837 private double[] switchProbability(int numberOfCases, int bci) {
838 double[] prob = profilingInfo.getSwitchProbabilities(bci);
839 if (prob != null) {
840 assert prob.length == numberOfCases;
841 } else {
842 Debug.log("Missing probability (switch) in %s at bci %d", method, bci);
843 prob = new double[numberOfCases];
844 for (int i = 0; i < numberOfCases; i++) {
845 prob[i] = 1.0d / numberOfCases;
846 }
847 }
848 assert allPositive(prob);
849 return prob;
850 }
851
852 private static boolean allPositive(double[] a) {
853 for (double d : a) {
854 if (d < 0) {
855 return false;
856 }
857 }
858 return true;
859 }
860
861 /**
862 * Helper function that sums up the probabilities of all keys that lead to a specific successor.
863 *
864 * @return an array of size successorCount with the accumulated probability for each successor.
865 */
866 private static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) {
867 double[] probability = new double[successorCount];
868 for (int i = 0; i < keySuccessors.length; i++) {
869 probability[keySuccessors[i]] += keyProbabilities[i];
870 }
871 return probability;
872 }
873
874 private void genSwitch(BytecodeSwitch bs) {
875 int bci = bci();
876 T value = frameState.ipop();
877
878 int nofCases = bs.numberOfCases();
879 double[] keyProbabilities = switchProbability(nofCases + 1, bci);
880
881 Map<Integer, SuccessorInfo> bciToBlockSuccessorIndex = new HashMap<>();
882 for (int i = 0; i < currentBlock.getSuccessorCount(); i++) {
883 assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessors().get(i).startBci);
884 if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessors().get(i).startBci)) {
885 bciToBlockSuccessorIndex.put(currentBlock.getSuccessors().get(i).startBci, new SuccessorInfo(i));
886 }
887 }
888
889 ArrayList<BciBlock> actualSuccessors = new ArrayList<>();
890 int[] keys = new int[nofCases];
891 int[] keySuccessors = new int[nofCases + 1];
892 int deoptSuccessorIndex = -1;
893 int nextSuccessorIndex = 0;
894 for (int i = 0; i < nofCases + 1; i++) {
895 if (i < nofCases) {
896 keys[i] = bs.keyAt(i);
897 }
898
899 if (isNeverExecutedCode(keyProbabilities[i])) {
900 if (deoptSuccessorIndex < 0) {
901 deoptSuccessorIndex = nextSuccessorIndex++;
902 actualSuccessors.add(null);
903 }
904 keySuccessors[i] = deoptSuccessorIndex;
905 } else {
906 int targetBci = i >= nofCases ? bs.defaultTarget() : bs.targetAt(i);
907 SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
908 if (info.actualIndex < 0) {
909 info.actualIndex = nextSuccessorIndex++;
910 actualSuccessors.add(currentBlock.getSuccessors().get(info.blockIndex));
911 }
912 keySuccessors[i] = info.actualIndex;
913 }
914 }
915
916 double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities);
917 T switchNode = append(genIntegerSwitch(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors));
918 for (int i = 0; i < actualSuccessors.size(); i++) {
919 setBlockSuccessor(switchNode, i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState));
920 }
921
922 }
923
924 protected abstract void setBlockSuccessor(T switchNode, int i, T createBlockTarget);
925
926 protected abstract T genIntegerSwitch(T value, int size, int[] keys, double[] keyProbabilities, int[] keySuccessors);
927
928 private static class SuccessorInfo {
929
930 int blockIndex;
931 int actualIndex;
932
933 public SuccessorInfo(int blockSuccessorIndex) {
934 this.blockIndex = blockSuccessorIndex;
935 actualIndex = -1;
936 }
937 }
938
939 protected abstract T appendConstant(Constant constant);
940
941 protected abstract T append(T v);
942
943 private boolean isNeverExecutedCode(double probability) {
944 return probability == 0 && optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI;
945 }
946
947 protected abstract T genDeoptimization();
948
949 protected T createTarget(double probability, BciBlock block, AbstractFrameStateBuilder<T> stateAfter) {
950 assert probability >= 0 && probability <= 1.01 : probability;
951 if (isNeverExecutedCode(probability)) {
952 return genDeoptimization();
953 } else {
954 assert block != null;
955 return createTarget(block, stateAfter);
956 }
957 }
958
959 protected abstract T createTarget(BciBlock trueBlock, AbstractFrameStateBuilder<T> state);
960
961 /**
962 * Returns a block begin node with the specified state. If the specified probability is 0, the
963 * block deoptimizes immediately.
964 */
965 protected abstract T createBlockTarget(double probability, BciBlock bciBlock, AbstractFrameStateBuilder<T> stateAfter);
966
967 protected abstract void processBlock(BciBlock block);
968
969 protected abstract void appendGoto(T target);
970
971 protected abstract void iterateBytecodesForBlock(BciBlock block);
972
973 public void processBytecode(int bci, int opcode) {
974 int cpi;
975
976 // Checkstyle: stop
977 // @formatter:off
978 switch (opcode) {
979 case NOP : /* nothing to do */ break;
980 case ACONST_NULL : frameState.apush(appendConstant(Constant.NULL_OBJECT)); break;
981 case ICONST_M1 : frameState.ipush(appendConstant(Constant.INT_MINUS_1)); break;
982 case ICONST_0 : frameState.ipush(appendConstant(Constant.INT_0)); break;
983 case ICONST_1 : frameState.ipush(appendConstant(Constant.INT_1)); break;
984 case ICONST_2 : frameState.ipush(appendConstant(Constant.INT_2)); break;
985 case ICONST_3 : frameState.ipush(appendConstant(Constant.INT_3)); break;
986 case ICONST_4 : frameState.ipush(appendConstant(Constant.INT_4)); break;
987 case ICONST_5 : frameState.ipush(appendConstant(Constant.INT_5)); break;
988 case LCONST_0 : frameState.lpush(appendConstant(Constant.LONG_0)); break;
989 case LCONST_1 : frameState.lpush(appendConstant(Constant.LONG_1)); break;
990 case FCONST_0 : frameState.fpush(appendConstant(Constant.FLOAT_0)); break;
991 case FCONST_1 : frameState.fpush(appendConstant(Constant.FLOAT_1)); break;
992 case FCONST_2 : frameState.fpush(appendConstant(Constant.FLOAT_2)); break;
993 case DCONST_0 : frameState.dpush(appendConstant(Constant.DOUBLE_0)); break;
994 case DCONST_1 : frameState.dpush(appendConstant(Constant.DOUBLE_1)); break;
995 case BIPUSH : frameState.ipush(appendConstant(Constant.forInt(stream.readByte()))); break;
996 case SIPUSH : frameState.ipush(appendConstant(Constant.forInt(stream.readShort()))); break;
997 case LDC : // fall through
998 case LDC_W : // fall through
999 case LDC2_W : genLoadConstant(stream.readCPI(), opcode); break;
1000 case ILOAD : loadLocal(stream.readLocalIndex(), Kind.Int); break;
1001 case LLOAD : loadLocal(stream.readLocalIndex(), Kind.Long); break;
1002 case FLOAD : loadLocal(stream.readLocalIndex(), Kind.Float); break;
1003 case DLOAD : loadLocal(stream.readLocalIndex(), Kind.Double); break;
1004 case ALOAD : loadLocal(stream.readLocalIndex(), Kind.Object); break;
1005 case ILOAD_0 : // fall through
1006 case ILOAD_1 : // fall through
1007 case ILOAD_2 : // fall through
1008 case ILOAD_3 : loadLocal(opcode - ILOAD_0, Kind.Int); break;
1009 case LLOAD_0 : // fall through
1010 case LLOAD_1 : // fall through
1011 case LLOAD_2 : // fall through
1012 case LLOAD_3 : loadLocal(opcode - LLOAD_0, Kind.Long); break;
1013 case FLOAD_0 : // fall through
1014 case FLOAD_1 : // fall through
1015 case FLOAD_2 : // fall through
1016 case FLOAD_3 : loadLocal(opcode - FLOAD_0, Kind.Float); break;
1017 case DLOAD_0 : // fall through
1018 case DLOAD_1 : // fall through
1019 case DLOAD_2 : // fall through
1020 case DLOAD_3 : loadLocal(opcode - DLOAD_0, Kind.Double); break;
1021 case ALOAD_0 : // fall through
1022 case ALOAD_1 : // fall through
1023 case ALOAD_2 : // fall through
1024 case ALOAD_3 : loadLocal(opcode - ALOAD_0, Kind.Object); break;
1025 case IALOAD : genLoadIndexed(Kind.Int ); break;
1026 case LALOAD : genLoadIndexed(Kind.Long ); break;
1027 case FALOAD : genLoadIndexed(Kind.Float ); break;
1028 case DALOAD : genLoadIndexed(Kind.Double); break;
1029 case AALOAD : genLoadIndexed(Kind.Object); break;
1030 case BALOAD : genLoadIndexed(Kind.Byte ); break;
1031 case CALOAD : genLoadIndexed(Kind.Char ); break;
1032 case SALOAD : genLoadIndexed(Kind.Short ); break;
1033 case ISTORE : storeLocal(Kind.Int, stream.readLocalIndex()); break;
1034 case LSTORE : storeLocal(Kind.Long, stream.readLocalIndex()); break;
1035 case FSTORE : storeLocal(Kind.Float, stream.readLocalIndex()); break;
1036 case DSTORE : storeLocal(Kind.Double, stream.readLocalIndex()); break;
1037 case ASTORE : storeLocal(Kind.Object, stream.readLocalIndex()); break;
1038 case ISTORE_0 : // fall through
1039 case ISTORE_1 : // fall through
1040 case ISTORE_2 : // fall through
1041 case ISTORE_3 : storeLocal(Kind.Int, opcode - ISTORE_0); break;
1042 case LSTORE_0 : // fall through
1043 case LSTORE_1 : // fall through
1044 case LSTORE_2 : // fall through
1045 case LSTORE_3 : storeLocal(Kind.Long, opcode - LSTORE_0); break;
1046 case FSTORE_0 : // fall through
1047 case FSTORE_1 : // fall through
1048 case FSTORE_2 : // fall through
1049 case FSTORE_3 : storeLocal(Kind.Float, opcode - FSTORE_0); break;
1050 case DSTORE_0 : // fall through
1051 case DSTORE_1 : // fall through
1052 case DSTORE_2 : // fall through
1053 case DSTORE_3 : storeLocal(Kind.Double, opcode - DSTORE_0); break;
1054 case ASTORE_0 : // fall through
1055 case ASTORE_1 : // fall through
1056 case ASTORE_2 : // fall through
1057 case ASTORE_3 : storeLocal(Kind.Object, opcode - ASTORE_0); break;
1058 case IASTORE : genStoreIndexed(Kind.Int ); break;
1059 case LASTORE : genStoreIndexed(Kind.Long ); break;
1060 case FASTORE : genStoreIndexed(Kind.Float ); break;
1061 case DASTORE : genStoreIndexed(Kind.Double); break;
1062 case AASTORE : genStoreIndexed(Kind.Object); break;
1063 case BASTORE : genStoreIndexed(Kind.Byte ); break;
1064 case CASTORE : genStoreIndexed(Kind.Char ); break;
1065 case SASTORE : genStoreIndexed(Kind.Short ); break;
1066 case POP : // fall through
1067 case POP2 : // fall through
1068 case DUP : // fall through
1069 case DUP_X1 : // fall through
1070 case DUP_X2 : // fall through
1071 case DUP2 : // fall through
1072 case DUP2_X1 : // fall through
1073 case DUP2_X2 : // fall through
1074 case SWAP : stackOp(opcode); break;
1075 case IADD : // fall through
1076 case ISUB : // fall through
1077 case IMUL : genArithmeticOp(Kind.Int, opcode); break;
1078 case IDIV : // fall through
1079 case IREM : genIntegerDivOp(Kind.Int, opcode); break;
1080 case LADD : // fall through
1081 case LSUB : // fall through
1082 case LMUL : genArithmeticOp(Kind.Long, opcode); break;
1083 case LDIV : // fall through
1084 case LREM : genIntegerDivOp(Kind.Long, opcode); break;
1085 case FADD : // fall through
1086 case FSUB : // fall through
1087 case FMUL : // fall through
1088 case FDIV : // fall through
1089 case FREM : genArithmeticOp(Kind.Float, opcode); break;
1090 case DADD : // fall through
1091 case DSUB : // fall through
1092 case DMUL : // fall through
1093 case DDIV : // fall through
1094 case DREM : genArithmeticOp(Kind.Double, opcode); break;
1095 case INEG : genNegateOp(Kind.Int); break;
1096 case LNEG : genNegateOp(Kind.Long); break;
1097 case FNEG : genNegateOp(Kind.Float); break;
1098 case DNEG : genNegateOp(Kind.Double); break;
1099 case ISHL : // fall through
1100 case ISHR : // fall through
1101 case IUSHR : genShiftOp(Kind.Int, opcode); break;
1102 case IAND : // fall through
1103 case IOR : // fall through
1104 case IXOR : genLogicOp(Kind.Int, opcode); break;
1105 case LSHL : // fall through
1106 case LSHR : // fall through
1107 case LUSHR : genShiftOp(Kind.Long, opcode); break;
1108 case LAND : // fall through
1109 case LOR : // fall through
1110 case LXOR : genLogicOp(Kind.Long, opcode); break;
1111 case IINC : genIncrement(); break;
1112 case I2F : genFloatConvert(FloatConvert.I2F, Kind.Int, Kind.Float); break;
1113 case I2D : genFloatConvert(FloatConvert.I2D, Kind.Int, Kind.Double); break;
1114 case L2F : genFloatConvert(FloatConvert.L2F, Kind.Long, Kind.Float); break;
1115 case L2D : genFloatConvert(FloatConvert.L2D, Kind.Long, Kind.Double); break;
1116 case F2I : genFloatConvert(FloatConvert.F2I, Kind.Float, Kind.Int); break;
1117 case F2L : genFloatConvert(FloatConvert.F2L, Kind.Float, Kind.Long); break;
1118 case F2D : genFloatConvert(FloatConvert.F2D, Kind.Float, Kind.Double); break;
1119 case D2I : genFloatConvert(FloatConvert.D2I, Kind.Double, Kind.Int); break;
1120 case D2L : genFloatConvert(FloatConvert.D2L, Kind.Double, Kind.Long); break;
1121 case D2F : genFloatConvert(FloatConvert.D2F, Kind.Double, Kind.Float); break;
1122 case L2I : genNarrow(Kind.Long, Kind.Int); break;
1123 case I2L : genSignExtend(Kind.Int, Kind.Long); break;
1124 case I2B : genSignExtend(Kind.Byte, Kind.Int); break;
1125 case I2S : genSignExtend(Kind.Short, Kind.Int); break;
1126 case I2C : genZeroExtend(Kind.Char, Kind.Int); break;
1127 case LCMP : genCompareOp(Kind.Long, false); break;
1128 case FCMPL : genCompareOp(Kind.Float, true); break;
1129 case FCMPG : genCompareOp(Kind.Float, false); break;
1130 case DCMPL : genCompareOp(Kind.Double, true); break;
1131 case DCMPG : genCompareOp(Kind.Double, false); break;
1132 case IFEQ : genIfZero(Condition.EQ); break;
1133 case IFNE : genIfZero(Condition.NE); break;
1134 case IFLT : genIfZero(Condition.LT); break;
1135 case IFGE : genIfZero(Condition.GE); break;
1136 case IFGT : genIfZero(Condition.GT); break;
1137 case IFLE : genIfZero(Condition.LE); break;
1138 case IF_ICMPEQ : genIfSame(Kind.Int, Condition.EQ); break;
1139 case IF_ICMPNE : genIfSame(Kind.Int, Condition.NE); break;
1140 case IF_ICMPLT : genIfSame(Kind.Int, Condition.LT); break;
1141 case IF_ICMPGE : genIfSame(Kind.Int, Condition.GE); break;
1142 case IF_ICMPGT : genIfSame(Kind.Int, Condition.GT); break;
1143 case IF_ICMPLE : genIfSame(Kind.Int, Condition.LE); break;
1144 case IF_ACMPEQ : genIfSame(Kind.Object, Condition.EQ); break;
1145 case IF_ACMPNE : genIfSame(Kind.Object, Condition.NE); break;
1146 case GOTO : genGoto(); break;
1147 case JSR : genJsr(stream.readBranchDest()); break;
1148 case RET : genRet(stream.readLocalIndex()); break;
1149 case TABLESWITCH : genSwitch(new BytecodeTableSwitch(getStream(), bci())); break;
1150 case LOOKUPSWITCH : genSwitch(new BytecodeLookupSwitch(getStream(), bci())); break;
1151 case IRETURN : genReturn(frameState.ipop()); break;
1152 case LRETURN : genReturn(frameState.lpop()); break;
1153 case FRETURN : genReturn(frameState.fpop()); break;
1154 case DRETURN : genReturn(frameState.dpop()); break;
1155 case ARETURN : genReturn(frameState.apop()); break;
1156 case RETURN : genReturn(null); break;
1157 case GETSTATIC : cpi = stream.readCPI(); genGetStatic(lookupField(cpi, opcode)); break;
1158 case PUTSTATIC : cpi = stream.readCPI(); genPutStatic(lookupField(cpi, opcode)); break;
1159 case GETFIELD : cpi = stream.readCPI(); genGetField(lookupField(cpi, opcode)); break;
1160 case PUTFIELD : cpi = stream.readCPI(); genPutField(lookupField(cpi, opcode)); break;
1161 case INVOKEVIRTUAL : cpi = stream.readCPI(); genInvokeVirtual(lookupMethod(cpi, opcode)); break;
1162 case INVOKESPECIAL : cpi = stream.readCPI(); genInvokeSpecial(lookupMethod(cpi, opcode)); break;
1163 case INVOKESTATIC : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break;
1164 case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break;
1165 case INVOKEDYNAMIC : cpi = stream.readCPI4(); genInvokeDynamic(lookupMethod(cpi, opcode)); break;
1166 case NEW : genNewInstance(stream.readCPI()); break;
1167 case NEWARRAY : genNewPrimitiveArray(stream.readLocalIndex()); break;
1168 case ANEWARRAY : genNewObjectArray(stream.readCPI()); break;
1169 case ARRAYLENGTH : genArrayLength(); break;
1170 case ATHROW : genThrow(); break;
1171 case CHECKCAST : genCheckCast(); break;
1172 case INSTANCEOF : genInstanceOf(); break;
1173 case MONITORENTER : genMonitorEnter(frameState.apop()); break;
1174 case MONITOREXIT : genMonitorExit(frameState.apop(), null); break;
1175 case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break;
1176 case IFNULL : genIfNull(Condition.EQ); break;
1177 case IFNONNULL : genIfNull(Condition.NE); break;
1178 case GOTO_W : genGoto(); break;
1179 case JSR_W : genJsr(stream.readBranchDest()); break;
1180 case BREAKPOINT:
1181 throw new BailoutException("concurrent setting of breakpoint");
1182 default:
1183 throw new BailoutException("Unsupported opcode " + opcode + " (" + nameOf(opcode) + ") [bci=" + bci + "]");
1184 }
1185 // @formatter:on
1186 // Checkstyle: resume
1187 }
1188
1189 private void genArrayLength() {
1190 frameState.ipush(append(genArrayLength(frameState.apop())));
1191 }
1192
1193 public ResolvedJavaMethod getMethod() {
1194 return method;
1195 }
1196
1197 public F getFrameState() {
1198 return frameState;
1199 }
1200
1201 }