001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Common Public License (CPL);
005 * You may not use this file except in compliance with the License. You
006 * may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/cpl1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.jikesrvm.compilers.opt.bc2ir;
014
015 import java.util.ArrayList;
016 import java.util.Enumeration;
017 import java.util.HashSet;
018 import java.util.NoSuchElementException;
019
020 import org.jikesrvm.VM;
021 import org.jikesrvm.ArchitectureSpecificOpt.RegisterPool;
022 import org.jikesrvm.adaptive.AosEntrypoints;
023 import org.jikesrvm.adaptive.controller.Controller;
024 import org.jikesrvm.classloader.BytecodeConstants;
025 import org.jikesrvm.classloader.BytecodeStream;
026 import org.jikesrvm.classloader.RVMClass;
027 import org.jikesrvm.classloader.ExceptionHandlerMap;
028 import org.jikesrvm.classloader.RVMField;
029 import org.jikesrvm.classloader.FieldReference;
030 import org.jikesrvm.classloader.RVMMethod;
031 import org.jikesrvm.classloader.MethodReference;
032 import org.jikesrvm.classloader.RVMType;
033 import org.jikesrvm.classloader.TypeReference;
034 import org.jikesrvm.compilers.baseline.SwitchBranchProfile;
035 import org.jikesrvm.compilers.common.CompiledMethod;
036 import org.jikesrvm.compilers.common.CompiledMethods;
037 import org.jikesrvm.compilers.opt.ClassLoaderProxy;
038 import org.jikesrvm.compilers.opt.FieldAnalysis;
039 import org.jikesrvm.compilers.opt.OperationNotImplementedException;
040 import org.jikesrvm.compilers.opt.OptimizingCompilerException;
041 import org.jikesrvm.compilers.opt.Simplifier;
042 import org.jikesrvm.compilers.opt.StaticFieldReader;
043 import org.jikesrvm.compilers.opt.driver.OptConstants;
044 import org.jikesrvm.compilers.opt.driver.OptimizingCompiler;
045 import org.jikesrvm.compilers.opt.inlining.CompilationState;
046 import org.jikesrvm.compilers.opt.inlining.InlineDecision;
047 import org.jikesrvm.compilers.opt.inlining.InlineSequence;
048 import org.jikesrvm.compilers.opt.inlining.Inliner;
049 import org.jikesrvm.compilers.opt.ir.ALoad;
050 import org.jikesrvm.compilers.opt.ir.AStore;
051 import org.jikesrvm.compilers.opt.ir.Athrow;
052 import org.jikesrvm.compilers.opt.ir.BasicBlock;
053 import org.jikesrvm.compilers.opt.ir.BasicBlockEnumeration;
054 import org.jikesrvm.compilers.opt.ir.Binary;
055 import org.jikesrvm.compilers.opt.ir.BoundsCheck;
056 import org.jikesrvm.compilers.opt.ir.CacheOp;
057 import org.jikesrvm.compilers.opt.ir.Call;
058 import org.jikesrvm.compilers.opt.ir.ControlFlowGraph;
059 import org.jikesrvm.compilers.opt.ir.Empty;
060 import org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock;
061 import org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlockBag;
062 import org.jikesrvm.compilers.opt.ir.GetField;
063 import org.jikesrvm.compilers.opt.ir.GetStatic;
064 import org.jikesrvm.compilers.opt.ir.Goto;
065 import org.jikesrvm.compilers.opt.ir.GuardedBinary;
066 import org.jikesrvm.compilers.opt.ir.GuardedUnary;
067 import org.jikesrvm.compilers.opt.ir.IRTools;
068 import org.jikesrvm.compilers.opt.ir.IfCmp;
069 import org.jikesrvm.compilers.opt.ir.InstanceOf;
070 import org.jikesrvm.compilers.opt.ir.Instruction;
071 import org.jikesrvm.compilers.opt.ir.LookupSwitch;
072 import org.jikesrvm.compilers.opt.ir.MonitorOp;
073 import org.jikesrvm.compilers.opt.ir.Multianewarray;
074 import org.jikesrvm.compilers.opt.ir.Move;
075 import org.jikesrvm.compilers.opt.ir.New;
076 import org.jikesrvm.compilers.opt.ir.NewArray;
077 import org.jikesrvm.compilers.opt.ir.NullCheck;
078 import org.jikesrvm.compilers.opt.ir.Nullary;
079 import org.jikesrvm.compilers.opt.ir.Operator;
080 import org.jikesrvm.compilers.opt.ir.Operators;
081 import org.jikesrvm.compilers.opt.ir.OsrBarrier;
082 import org.jikesrvm.compilers.opt.ir.OsrPoint;
083 import org.jikesrvm.compilers.opt.ir.PutField;
084 import org.jikesrvm.compilers.opt.ir.PutStatic;
085 import org.jikesrvm.compilers.opt.ir.Register;
086 import org.jikesrvm.compilers.opt.ir.ResultCarrier;
087 import org.jikesrvm.compilers.opt.ir.StoreCheck;
088 import org.jikesrvm.compilers.opt.ir.TableSwitch;
089 import org.jikesrvm.compilers.opt.ir.Trap;
090 import org.jikesrvm.compilers.opt.ir.TypeCheck;
091 import org.jikesrvm.compilers.opt.ir.Unary;
092 import org.jikesrvm.compilers.opt.ir.ZeroCheck;
093 import org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand;
094 import org.jikesrvm.compilers.opt.ir.operand.BranchOperand;
095 import org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand;
096 import org.jikesrvm.compilers.opt.ir.operand.ConditionOperand;
097 import org.jikesrvm.compilers.opt.ir.operand.ConstantOperand;
098 import org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand;
099 import org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand;
100 import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand;
101 import org.jikesrvm.compilers.opt.ir.operand.LocationOperand;
102 import org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand;
103 import org.jikesrvm.compilers.opt.ir.operand.MethodOperand;
104 import org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand;
105 import org.jikesrvm.compilers.opt.ir.operand.Operand;
106 import org.jikesrvm.compilers.opt.ir.operand.OsrTypeInfoOperand;
107 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
108 import org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand;
109 import org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand;
110 import org.jikesrvm.compilers.opt.ir.operand.TypeOperand;
111 import org.jikesrvm.osr.OSRConstants;
112 import org.jikesrvm.osr.ObjectHolder;
113 import org.jikesrvm.runtime.Entrypoints;
114 import org.jikesrvm.runtime.Magic;
115 import org.vmmagic.pragma.NoInline;
116 import org.vmmagic.unboxed.Address;
117 import org.vmmagic.unboxed.Offset;
118
119 /**
120 * This class translates from bytecode to HIR.
121 * <p>
122 * The only public entry point is BC2IR.generateHIR.
123 * generateHIR is passed an argument GenerationContext.
124 * The context is assumed to be "empty" but "initialized." Invoking
125 * generateHIR on a context results in it being "filled in" with the HIR
126 * for the method (and for any inlined methods) as specified by the
127 * state of the context.
128 * <p>
129 * The basic idea is to abstractly interpret the bytecode stream,
130 * translating it into a register-based IR along the way. At each program
131 * point BC2IR has an abstract stack and an abstract local variable array.
132 * Based on this, and on the bytecode, it can generate instructions.
133 * It also does a number of forward flow-sensitive dataflow analyses and
134 * optimistic optimizations in the process. There's lots of details in
135 * John Whaley's master thesis from MIT. However, one needs to be careful
136 * because this code has substantial diverged from the system described in
137 * his thesis.
138 * Some optimizations/features described in Johns's thesis are not implemented
139 * here. Some optimizations/features implemented here are not described
140 * in John's thesis.
141 * In particular this code takes a different approach to JSRs (inlining them),
142 * and has more advanced and effective implementation of the inlining
143 * transformation. <p>
144 *
145 *
146 * @see IRGenOptions
147 * @see GenerationContext
148 * @see ConvertBCtoHIR
149 */
150 public final class BC2IR
151 implements IRGenOptions, Operators, BytecodeConstants, OptConstants, OSRConstants {
152 /**
153 * Dummy slot.
154 * Used to deal with the fact the longs/doubles take
155 * two words of stack space/local space to represent.
156 * This field needs to be accessed by several of the IR classes,
157 * but is not intended to be referenced by general client code.
158 */
159 public static final DummyStackSlot DUMMY = new DummyStackSlot();
160
161 /**
162 * Generate HIR as specified by the argument GenerationContext.
163 * As a result of calling this method, the cfg field of the generation
164 * context is populated with basic blocks and instructions.
165 * Additionally, other fields of the generation context will be modified
166 * to summarize what happened during IR generation.
167 * <p>
168 * This is the only external entry point to BC2IR.
169 * <p>
170 * Note: most clients should be calling methods in
171 * ConvertBCtoHIR or in Inliner rather than invoking
172 * BC2IR.generateHIR directly.
173 *
174 * @param context the generation context
175 */
176 public static void generateHIR(GenerationContext context) {
177 new BC2IR(context).generateHIR();
178 }
179
180 //////////////////////////////////////////
181 // vvv Implementation details below vvv //
182 //////////////////////////////////////////
183 /**
184 * The generation context.
185 */
186 private GenerationContext gc;
187
188 /**
189 * Bytecodes for the method being generated.
190 */
191 private BytecodeStream bcodes;
192
193 // Fields to support generation of instructions/blocks
194 /**
195 * The set of BasicBlockLEs we are generating
196 */
197 private BBSet blocks;
198
199 /**
200 * Bytecode index of current instruction.
201 */
202 private int instrIndex;
203
204 // OSR field
205 private boolean osrGuardedInline = false;
206
207 /**
208 * OSR field: TODO rework this mechanism!
209 * adjustment of bcIndex of instructions because of
210 * specialized bytecode.
211 */
212 private int bciAdjustment;
213
214 /**
215 * Last instruction generated (for ELIM_COPY_LOCALS)
216 */
217 private Instruction lastInstr;
218
219 /**
220 * Does basic block end here?
221 */
222 private boolean endOfBasicBlock;
223
224 /**
225 * Do we fall through to the next basic block?
226 */
227 private boolean fallThrough;
228
229 /**
230 * Current BBLE.
231 */
232 private BasicBlockLE currentBBLE;
233
234 /**
235 * Current simulated stack state.
236 */
237 private OperandStack stack;
238
239 /**
240 * Current state of local variables.
241 */
242 private Operand[] _localState;
243
244 /**
245 * Index of next basic block.
246 */
247 private int runoff;
248
249 private Operand currentGuard;
250
251 /**
252 * Was something inlined?
253 */
254 private boolean inlinedSomething;
255
256 /**
257 * OSR: used for PSEUDO_InvokeStatic to recover the type info
258 */
259 private int param1, param2;
260
261 /**
262 * osr barrier needs type information of locals and stacks,
263 * it has to be created before a _callHelper.
264 * only when the call site is going to be inlined, the instruction
265 * is inserted before the call site.
266 */
267 private Instruction lastOsrBarrier = null;
268
269 /**
270 * Debugging with method_to_print. Switch following 2
271 * to both be non-final. Set DBG_SELECTIVE to true
272 * DBG_SELECTED will then be true when the method matches.
273 * You must also uncomment the assignment to DBG_SELECTIVE in start
274 */
275 private static final boolean DBG_SELECTIVE = false;
276 private static final boolean DBG_SELECTED = false;
277
278 //////////
279 // End of field declarations
280 //////////
281
282 // Prevent external instantiation
283
284 private BC2IR() {}
285
286 /**
287 * Construct the BC2IR object for the generation context.
288 * After the constructor completes, we're ready to start generating
289 * HIR from bytecode 0 of context.method.
290 *
291 * @param context the context to generate HIR into
292 */
293 private BC2IR(GenerationContext context) {
294 start(context);
295 for (int argIdx = 0, localIdx = 0; argIdx < context.arguments.length;) {
296 TypeReference argType = context.arguments[argIdx].getType();
297 _localState[localIdx++] = context.arguments[argIdx++];
298 if (argType.isLongType() || argType.isDoubleType()) {
299 _localState[localIdx++] = DUMMY;
300 }
301 }
302 finish(context);
303 }
304
305 @NoInline
306 private void start(GenerationContext context) {
307 gc = context;
308 // To use the following you need to change the declarations
309 // in IRGenOption.java
310 if (DBG_SELECTIVE) {
311 if (gc.options.hasMETHOD_TO_PRINT() && gc.options.fuzzyMatchMETHOD_TO_PRINT(gc.method.toString())) {
312 VM.sysWrite("Whoops! you need to uncomment the assignment to DBG_SELECTED");
313 // DBG_SELECTED = true;
314 } else {
315 // DBG_SELECTED = false;
316 }
317
318 }
319
320 if (context.method.isForOsrSpecialization()) {
321 bcodes = context.method.getOsrSynthesizedBytecodes();
322 } else {
323 bcodes = context.method.getBytecodes();
324 }
325
326 // initialize the local state from context.arguments
327 _localState = new Operand[context.method.getLocalWords()];
328
329 if (context.method.isForOsrSpecialization()) {
330 this.bciAdjustment = context.method.getOsrPrologueLength();
331 } else {
332 this.bciAdjustment = 0;
333 }
334
335 this.osrGuardedInline = VM.runningVM &&
336 context.options.OSR_GUARDED_INLINING &&
337 !context.method.isForOsrSpecialization() &&
338 OptimizingCompiler.getAppStarted() &&
339 (Controller.options != null) &&
340 Controller.options.ENABLE_RECOMPILATION;
341 }
342
343 private void finish(GenerationContext context) {
344 // Initialize simulated stack.
345 stack = new OperandStack(context.method.getOperandWords());
346 // Initialize BBSet.
347 blocks = new BBSet(context, bcodes, _localState);
348 // Finish preparing to generate from bytecode 0
349 currentBBLE = blocks.getEntry();
350 gc.prologue.insertOut(currentBBLE.block);
351 if (DBG_CFG || DBG_SELECTED) {
352 db("Added CFG edge from " + gc.prologue + " to " + currentBBLE.block);
353 }
354 runoff = currentBBLE.max;
355 }
356
357 /**
358 * Main generation loop.
359 */
360 private void generateHIR() {
361 // Constructor initialized generation state to start
362 // generating from bytecode 0, so get the ball rolling.
363 if (DBG_BB || DBG_SELECTED) db("bbl: " + printBlocks());
364 generateFrom(0);
365 // While there are more blocks that need it, pick one and generate it.
366 for (currentBBLE = blocks.getNextEmptyBlock(currentBBLE); currentBBLE != null; currentBBLE =
367 blocks.getNextEmptyBlock(currentBBLE)) {
368 // Found a block. Set the generation state appropriately.
369 currentBBLE.clearSelfRegen();
370 runoff = Math.min(blocks.getNextBlockBytecodeIndex(currentBBLE), currentBBLE.max);
371 if (currentBBLE.stackState == null) {
372 stack.clear();
373 } else {
374 stack = currentBBLE.stackState.copy();
375 }
376 _localState = currentBBLE.copyLocalState();
377 if (DBG_BB || DBG_SELECTED) db("bbl: " + printBlocks());
378 // Generate it!
379 generateFrom(currentBBLE.low);
380 }
381 // Construct initial code order, commit to recursive inlines,
382 // insert any synthetic blocks.
383 if (DBG_BB || DBG_SELECTED) db("doing final pass over basic blocks: " + printBlocks());
384 blocks.finalPass(inlinedSomething);
385 }
386
387 // pops the length off the stack
388 //
389 public Instruction generateAnewarray(TypeReference arrayTypeRef, TypeReference elementTypeRef) {
390 if (arrayTypeRef == null) {
391 if (VM.VerifyAssertions) VM._assert(elementTypeRef != null);
392 arrayTypeRef = elementTypeRef.getArrayTypeForElementType();
393 }
394 if (elementTypeRef == null) {
395 elementTypeRef = arrayTypeRef.getArrayElementType();
396 }
397
398 RegisterOperand t = gc.temps.makeTemp(arrayTypeRef);
399 t.setPreciseType();
400 markGuardlessNonNull(t);
401 // We can do early resolution of the array type if the element type
402 // is already initialized.
403 RVMType arrayType = arrayTypeRef.peekType();
404 Operator op;
405 TypeOperand arrayOp;
406
407 if ((arrayType != null) && (arrayType.isInitialized() || arrayType.isInBootImage())) {
408 op = NEWARRAY;
409 arrayOp = makeTypeOperand(arrayType);
410 t.setExtant();
411 } else {
412 RVMType elementType = elementTypeRef.peekType();
413 if ((elementType != null) && (elementType.isInitialized() || elementType.isInBootImage())) {
414 arrayType = arrayTypeRef.resolve();
415 arrayType.resolve();
416 arrayType.instantiate();
417 op = NEWARRAY;
418 arrayOp = makeTypeOperand(arrayType);
419 t.setExtant();
420 } else {
421 op = NEWARRAY_UNRESOLVED;
422 arrayOp = makeTypeOperand(arrayTypeRef);
423 }
424 }
425 Instruction s = NewArray.create(op, t, arrayOp, popInt());
426 push(t.copyD2U());
427 rectifyStateWithErrorHandler();
428 rectifyStateWithExceptionHandler(TypeReference.JavaLangNegativeArraySizeException);
429 return s;
430 }
431
432 /**
433 * Generate instructions for a basic block.
434 * May discover other basic blocks that need to be generated along the way.
435 *
436 * @param fromIndex bytecode index to start from
437 */
438 private void generateFrom(int fromIndex) {
439 if (DBG_BB || DBG_SELECTED) {
440 db("generating code into " + currentBBLE + " with runoff " + runoff);
441 }
442 currentBBLE.setGenerated();
443 endOfBasicBlock = fallThrough = false;
444 lastInstr = null;
445 bcodes.reset(fromIndex);
446 while (true) {
447 // Must keep currentBBLE.high up-to-date in case we try to jump into
448 // the middle of the block we're currently generating. Simply updating
449 // high once endsBasicBlock is true doesn't enable us to catch this case.
450 currentBBLE.high = instrIndex = bcodes.index();
451 int code = bcodes.nextInstruction();
452 if (DBG_BCPARSE) {
453 db("parsing " +
454 instrIndex +
455 " " +
456 code +
457 " : 0x" +
458 Integer.toHexString(code) +
459 " " +
460 ((code < JBC_name.length) ? JBC_name[code] : "unknown bytecode"));
461 }
462 Instruction s = null;
463
464 lastOsrBarrier = null;
465
466 switch (code) {
467 case JBC_nop:
468 break;
469
470 case JBC_aconst_null:
471 push(new NullConstantOperand());
472 break;
473
474 case JBC_iconst_m1:
475 case JBC_iconst_0:
476 case JBC_iconst_1:
477 case JBC_iconst_2:
478 case JBC_iconst_3:
479 case JBC_iconst_4:
480 case JBC_iconst_5:
481 push(new IntConstantOperand(code - JBC_iconst_0));
482 break;
483
484 case JBC_lconst_0:
485 case JBC_lconst_1:
486 pushDual(new LongConstantOperand(code - JBC_lconst_0));
487 break;
488
489 case JBC_fconst_0:
490 push(new FloatConstantOperand(0.f));
491 break;
492
493 case JBC_fconst_1:
494 push(new FloatConstantOperand(1.f));
495 break;
496
497 case JBC_fconst_2:
498 push(new FloatConstantOperand(2.f));
499 break;
500
501 case JBC_dconst_0:
502 pushDual(new DoubleConstantOperand(0.));
503 break;
504
505 case JBC_dconst_1:
506 pushDual(new DoubleConstantOperand(1.));
507 break;
508
509 case JBC_bipush:
510 push(new IntConstantOperand(bcodes.getByteValue()));
511 break;
512
513 case JBC_sipush:
514 push(new IntConstantOperand(bcodes.getShortValue()));
515 break;
516
517 case JBC_ldc:
518 push(getConstantOperand(bcodes.getConstantIndex()));
519 break;
520
521 case JBC_ldc_w:
522 push(getConstantOperand(bcodes.getWideConstantIndex()));
523 break;
524
525 case JBC_ldc2_w:
526 pushDual(getConstantOperand(bcodes.getWideConstantIndex()));
527 break;
528
529 case JBC_iload:
530 s = do_iload(bcodes.getLocalNumber());
531 break;
532
533 case JBC_lload:
534 s = do_lload(bcodes.getLocalNumber());
535 break;
536
537 case JBC_fload:
538 s = do_fload(bcodes.getLocalNumber());
539 break;
540
541 case JBC_dload:
542 s = do_dload(bcodes.getLocalNumber());
543 break;
544
545 case JBC_aload:
546 s = do_aload(bcodes.getLocalNumber());
547 break;
548
549 case JBC_iload_0:
550 case JBC_iload_1:
551 case JBC_iload_2:
552 case JBC_iload_3:
553 s = do_iload(code - JBC_iload_0);
554 break;
555
556 case JBC_lload_0:
557 case JBC_lload_1:
558 case JBC_lload_2:
559 case JBC_lload_3:
560 s = do_lload(code - JBC_lload_0);
561 break;
562
563 case JBC_fload_0:
564 case JBC_fload_1:
565 case JBC_fload_2:
566 case JBC_fload_3:
567 s = do_fload(code - JBC_fload_0);
568 break;
569
570 case JBC_dload_0:
571 case JBC_dload_1:
572 case JBC_dload_2:
573 case JBC_dload_3:
574 s = do_dload(code - JBC_dload_0);
575 break;
576
577 case JBC_aload_0:
578 case JBC_aload_1:
579 case JBC_aload_2:
580 case JBC_aload_3:
581 s = do_aload(code - JBC_aload_0);
582 break;
583
584 case JBC_iaload: {
585 Operand index = popInt();
586 Operand ref = pop();
587 clearCurrentGuard();
588 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
589 break;
590 }
591 if (VM.VerifyAssertions) {
592 assertIsType(ref, TypeReference.IntArray);
593 }
594 s = _aloadHelper(INT_ALOAD, ref, index, TypeReference.Int);
595 }
596 break;
597
598 case JBC_laload: {
599 Operand index = popInt();
600 Operand ref = pop();
601 clearCurrentGuard();
602 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
603 break;
604 }
605 if (VM.VerifyAssertions) {
606 assertIsType(ref, TypeReference.LongArray);
607 }
608 s = _aloadHelper(LONG_ALOAD, ref, index, TypeReference.Long);
609 }
610 break;
611
612 case JBC_faload: {
613 Operand index = popInt();
614 Operand ref = pop();
615 clearCurrentGuard();
616 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
617 break;
618 }
619 if (VM.VerifyAssertions) {
620 assertIsType(ref, TypeReference.FloatArray);
621 }
622 s = _aloadHelper(FLOAT_ALOAD, ref, index, TypeReference.Float);
623 }
624 break;
625
626 case JBC_daload: {
627 Operand index = popInt();
628 Operand ref = pop();
629 clearCurrentGuard();
630 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
631 break;
632 }
633 if (VM.VerifyAssertions) {
634 assertIsType(ref, TypeReference.DoubleArray);
635 }
636 s = _aloadHelper(DOUBLE_ALOAD, ref, index, TypeReference.Double);
637 }
638 break;
639
640 case JBC_aaload: {
641 Operand index = popInt();
642 Operand ref = pop();
643 clearCurrentGuard();
644 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
645 break;
646 }
647 TypeReference type = getRefTypeOf(ref).getArrayElementType();
648 if (VM.VerifyAssertions) VM._assert(type.isReferenceType());
649 s = _aloadHelper(REF_ALOAD, ref, index, type);
650 }
651 break;
652
653 case JBC_baload: {
654 Operand index = popInt();
655 Operand ref = pop();
656 clearCurrentGuard();
657 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
658 break;
659 }
660 TypeReference type = getArrayTypeOf(ref);
661 if (VM.VerifyAssertions) {
662 VM._assert(type == TypeReference.ByteArray || type == TypeReference.BooleanArray);
663 }
664 if (type == TypeReference.ByteArray) {
665 s = _aloadHelper(BYTE_ALOAD, ref, index, TypeReference.Byte);
666 } else {
667 s = _aloadHelper(UBYTE_ALOAD, ref, index, TypeReference.Boolean);
668 }
669 }
670 break;
671
672 case JBC_caload: {
673 Operand index = popInt();
674 Operand ref = pop();
675 clearCurrentGuard();
676 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
677 break;
678 }
679 if (VM.VerifyAssertions) {
680 assertIsType(ref, TypeReference.CharArray);
681 }
682 s = _aloadHelper(USHORT_ALOAD, ref, index, TypeReference.Char);
683 }
684 break;
685
686 case JBC_saload: {
687 Operand index = popInt();
688 Operand ref = pop();
689 clearCurrentGuard();
690 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
691 break;
692 }
693 if (VM.VerifyAssertions) {
694 assertIsType(ref, TypeReference.ShortArray);
695 }
696 s = _aloadHelper(SHORT_ALOAD, ref, index, TypeReference.Short);
697 }
698 break;
699
700 case JBC_istore:
701 s = do_store(bcodes.getLocalNumber(), popInt());
702 break;
703
704 case JBC_lstore:
705 s = do_store(bcodes.getLocalNumber(), popLong());
706 break;
707
708 case JBC_fstore:
709 s = do_store(bcodes.getLocalNumber(), popFloat());
710 break;
711
712 case JBC_dstore:
713 s = do_store(bcodes.getLocalNumber(), popDouble());
714 break;
715
716 case JBC_astore:
717 s = do_astore(bcodes.getLocalNumber());
718 break;
719
720 case JBC_istore_0:
721 case JBC_istore_1:
722 case JBC_istore_2:
723 case JBC_istore_3:
724 s = do_store(code - JBC_istore_0, popInt());
725 break;
726
727 case JBC_lstore_0:
728 case JBC_lstore_1:
729 case JBC_lstore_2:
730 case JBC_lstore_3:
731 s = do_store(code - JBC_lstore_0, popLong());
732 break;
733
734 case JBC_fstore_0:
735 case JBC_fstore_1:
736 case JBC_fstore_2:
737 case JBC_fstore_3:
738 s = do_store(code - JBC_fstore_0, popFloat());
739 break;
740
741 case JBC_dstore_0:
742 case JBC_dstore_1:
743 case JBC_dstore_2:
744 case JBC_dstore_3:
745 s = do_store(code - JBC_dstore_0, popDouble());
746 break;
747
748 case JBC_astore_0:
749 case JBC_astore_1:
750 case JBC_astore_2:
751 case JBC_astore_3:
752 s = do_astore(code - JBC_astore_0);
753 break;
754
755 case JBC_iastore: {
756 Operand val = popInt();
757 Operand index = popInt();
758 Operand ref = pop();
759 clearCurrentGuard();
760 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
761 break;
762 }
763 if (VM.VerifyAssertions) {
764 assertIsType(ref, TypeReference.IntArray);
765 }
766 s =
767 AStore.create(INT_ASTORE,
768 val,
769 ref,
770 index,
771 new LocationOperand(TypeReference.Int),
772 getCurrentGuard());
773 }
774 break;
775
776 case JBC_lastore: {
777 Operand val = popLong();
778 Operand index = popInt();
779 Operand ref = pop();
780 clearCurrentGuard();
781 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
782 break;
783 }
784 if (VM.VerifyAssertions) {
785 assertIsType(ref, TypeReference.LongArray);
786 }
787 s =
788 AStore.create(LONG_ASTORE,
789 val,
790 ref,
791 index,
792 new LocationOperand(TypeReference.Long),
793 getCurrentGuard());
794 }
795 break;
796
797 case JBC_fastore: {
798 Operand val = popFloat();
799 Operand index = popInt();
800 Operand ref = pop();
801 clearCurrentGuard();
802 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
803 break;
804 }
805 if (VM.VerifyAssertions) {
806 assertIsType(ref, TypeReference.FloatArray);
807 }
808 s =
809 AStore.create(FLOAT_ASTORE,
810 val,
811 ref,
812 index,
813 new LocationOperand(TypeReference.Float),
814 getCurrentGuard());
815 }
816 break;
817
818 case JBC_dastore: {
819 Operand val = popDouble();
820 Operand index = popInt();
821 Operand ref = pop();
822 clearCurrentGuard();
823 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
824 break;
825 }
826 if (VM.VerifyAssertions) {
827 assertIsType(ref, TypeReference.DoubleArray);
828 }
829 s =
830 AStore.create(DOUBLE_ASTORE,
831 val,
832 ref,
833 index,
834 new LocationOperand(TypeReference.Double),
835 getCurrentGuard());
836 }
837 break;
838
839 case JBC_aastore: {
840 Operand val = pop();
841 Operand index = popInt();
842 Operand ref = pop();
843 clearCurrentGuard();
844 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
845 break;
846 }
847 TypeReference type = getRefTypeOf(ref).getArrayElementType();
848 if (VM.VerifyAssertions) VM._assert(type.isReferenceType());
849 if (do_CheckStore(ref, val, type)) {
850 break;
851 }
852 s = AStore.create(REF_ASTORE, val, ref, index, new LocationOperand(type), getCurrentGuard());
853 }
854 break;
855
856 case JBC_bastore: {
857 Operand val = popInt();
858 Operand index = popInt();
859 Operand ref = pop();
860 clearCurrentGuard();
861 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
862 break;
863 }
864 TypeReference type = getArrayTypeOf(ref);
865 if (VM.VerifyAssertions) {
866 VM._assert(type == TypeReference.ByteArray || type == TypeReference.BooleanArray);
867 }
868 if (type == TypeReference.ByteArray) {
869 type = TypeReference.Byte;
870 } else {
871 type = TypeReference.Boolean;
872 }
873 s = AStore.create(BYTE_ASTORE, val, ref, index, new LocationOperand(type), getCurrentGuard());
874 }
875 break;
876
877 case JBC_castore: {
878 Operand val = popInt();
879 Operand index = popInt();
880 Operand ref = pop();
881 clearCurrentGuard();
882 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
883 break;
884 }
885 if (VM.VerifyAssertions) {
886 assertIsType(ref, TypeReference.CharArray);
887 }
888 s =
889 AStore.create(SHORT_ASTORE,
890 val,
891 ref,
892 index,
893 new LocationOperand(TypeReference.Char),
894 getCurrentGuard());
895 }
896 break;
897
898 case JBC_sastore: {
899 Operand val = popInt();
900 Operand index = popInt();
901 Operand ref = pop();
902 clearCurrentGuard();
903 if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
904 break;
905 }
906 if (VM.VerifyAssertions) {
907 assertIsType(ref, TypeReference.ShortArray);
908 }
909 s =
910 AStore.create(SHORT_ASTORE,
911 val,
912 ref,
913 index,
914 new LocationOperand(TypeReference.Short),
915 getCurrentGuard());
916 }
917 break;
918
919 case JBC_pop:
920 stack.pop();
921 break;
922
923 case JBC_pop2:
924 stack.pop2();
925 break;
926
927 case JBC_dup: {
928 Operand op1 = stack.pop();
929 stack.push(op1);
930 s = pushCopy(op1);
931 }
932 break;
933
934 case JBC_dup_x1: {
935 Operand op1 = stack.pop();
936 Operand op2 = stack.pop();
937 stack.push(op1);
938 stack.push(op2);
939 s = pushCopy(op1);
940 }
941 break;
942
943 case JBC_dup_x2: {
944 Operand op1 = stack.pop();
945 Operand op2 = stack.pop();
946 Operand op3 = stack.pop();
947 stack.push(op1);
948 stack.push(op3);
949 stack.push(op2);
950 s = pushCopy(op1);
951 }
952 break;
953
954 case JBC_dup2: {
955 Operand op1 = stack.pop();
956 Operand op2 = stack.pop();
957 stack.push(op2);
958 stack.push(op1);
959 s = pushCopy(op2);
960 if (s != null) {
961 appendInstruction(s);
962 s = null;
963 }
964 s = pushCopy(op1);
965 }
966 break;
967
968 case JBC_dup2_x1: {
969 Operand op1 = stack.pop();
970 Operand op2 = stack.pop();
971 Operand op3 = stack.pop();
972 stack.push(op2);
973 stack.push(op1);
974 stack.push(op3);
975 s = pushCopy(op2);
976 if (s != null) {
977 appendInstruction(s);
978 s = null;
979 }
980 s = pushCopy(op1);
981 }
982 break;
983
984 case JBC_dup2_x2: {
985 Operand op1 = stack.pop();
986 Operand op2 = stack.pop();
987 Operand op3 = stack.pop();
988 Operand op4 = stack.pop();
989 stack.push(op2);
990 stack.push(op1);
991 stack.push(op4);
992 stack.push(op3);
993 s = pushCopy(op2);
994 if (s != null) {
995 appendInstruction(s);
996 s = null;
997 }
998 s = pushCopy(op1);
999 }
1000 break;
1001
1002 case JBC_swap: {
1003 Operand op1 = stack.pop();
1004 Operand op2 = stack.pop();
1005 stack.push(op1);
1006 stack.push(op2);
1007 }
1008 break;
1009
1010 case JBC_iadd: {
1011 Operand op2 = popInt();
1012 Operand op1 = popInt();
1013 s = _binaryHelper(INT_ADD, op1, op2, TypeReference.Int);
1014 }
1015 break;
1016
1017 case JBC_ladd: {
1018 Operand op2 = popLong();
1019 Operand op1 = popLong();
1020 s = _binaryDualHelper(LONG_ADD, op1, op2, TypeReference.Long);
1021 }
1022 break;
1023
1024 case JBC_fadd: {
1025 Operand op2 = popFloat();
1026 Operand op1 = popFloat();
1027 s = _binaryHelper(FLOAT_ADD, op1, op2, TypeReference.Float);
1028 }
1029 break;
1030
1031 case JBC_dadd: {
1032 Operand op2 = popDouble();
1033 Operand op1 = popDouble();
1034 s = _binaryDualHelper(DOUBLE_ADD, op1, op2, TypeReference.Double);
1035 }
1036 break;
1037
1038 case JBC_isub: {
1039 Operand op2 = popInt();
1040 Operand op1 = popInt();
1041 s = _binaryHelper(INT_SUB, op1, op2, TypeReference.Int);
1042 }
1043 break;
1044
1045 case JBC_lsub: {
1046 Operand op2 = popLong();
1047 Operand op1 = popLong();
1048 s = _binaryDualHelper(LONG_SUB, op1, op2, TypeReference.Long);
1049 }
1050 break;
1051
1052 case JBC_fsub: {
1053 Operand op2 = popFloat();
1054 Operand op1 = popFloat();
1055 s = _binaryHelper(FLOAT_SUB, op1, op2, TypeReference.Float);
1056 }
1057 break;
1058
1059 case JBC_dsub: {
1060 Operand op2 = popDouble();
1061 Operand op1 = popDouble();
1062 s = _binaryDualHelper(DOUBLE_SUB, op1, op2, TypeReference.Double);
1063 }
1064 break;
1065
1066 case JBC_imul: {
1067 Operand op2 = popInt();
1068 Operand op1 = popInt();
1069 s = _binaryHelper(INT_MUL, op1, op2, TypeReference.Int);
1070 }
1071 break;
1072
1073 case JBC_lmul: {
1074 Operand op2 = popLong();
1075 Operand op1 = popLong();
1076 s = _binaryDualHelper(LONG_MUL, op1, op2, TypeReference.Long);
1077 }
1078 break;
1079
1080 case JBC_fmul: {
1081 Operand op2 = popFloat();
1082 Operand op1 = popFloat();
1083 s = _binaryHelper(FLOAT_MUL, op1, op2, TypeReference.Float);
1084 }
1085 break;
1086
1087 case JBC_dmul: {
1088 Operand op2 = popDouble();
1089 Operand op1 = popDouble();
1090 s = _binaryDualHelper(DOUBLE_MUL, op1, op2, TypeReference.Double);
1091 }
1092 break;
1093
1094 case JBC_idiv: {
1095 clearCurrentGuard();
1096 Operand op2 = popInt();
1097 Operand op1 = popInt();
1098 if (do_IntZeroCheck(op2)) {
1099 break;
1100 }
1101 s = _guardedBinaryHelper(INT_DIV, op1, op2, getCurrentGuard(), TypeReference.Int);
1102 }
1103 break;
1104
1105 case JBC_ldiv: {
1106 clearCurrentGuard();
1107 Operand op2 = popLong();
1108 Operand op1 = popLong();
1109 if (do_LongZeroCheck(op2)) {
1110 break;
1111 }
1112 s = _guardedBinaryDualHelper(LONG_DIV, op1, op2, getCurrentGuard(), TypeReference.Long);
1113 }
1114 break;
1115
1116 case JBC_fdiv: {
1117 Operand op2 = popFloat();
1118 Operand op1 = popFloat();
1119 s = _binaryHelper(FLOAT_DIV, op1, op2, TypeReference.Float);
1120 }
1121 break;
1122
1123 case JBC_ddiv: {
1124 Operand op2 = popDouble();
1125 Operand op1 = popDouble();
1126 s = _binaryDualHelper(DOUBLE_DIV, op1, op2, TypeReference.Double);
1127 }
1128 break;
1129
1130 case JBC_irem: {
1131 clearCurrentGuard();
1132 Operand op2 = popInt();
1133 Operand op1 = popInt();
1134 if (do_IntZeroCheck(op2)) {
1135 break;
1136 }
1137 s = _guardedBinaryHelper(INT_REM, op1, op2, getCurrentGuard(), TypeReference.Int);
1138 }
1139 break;
1140
1141 case JBC_lrem: {
1142 clearCurrentGuard();
1143 Operand op2 = popLong();
1144 Operand op1 = popLong();
1145 if (do_LongZeroCheck(op2)) {
1146 break;
1147 }
1148 s = _guardedBinaryDualHelper(LONG_REM, op1, op2, getCurrentGuard(), TypeReference.Long);
1149 }
1150 break;
1151
1152 case JBC_frem: {
1153 Operand op2 = popFloat();
1154 Operand op1 = popFloat();
1155 s = _binaryHelper(FLOAT_REM, op1, op2, TypeReference.Float);
1156 }
1157 break;
1158
1159 case JBC_drem: {
1160 Operand op2 = popDouble();
1161 Operand op1 = popDouble();
1162 s = _binaryDualHelper(DOUBLE_REM, op1, op2, TypeReference.Double);
1163 }
1164 break;
1165
1166 case JBC_ineg:
1167 s = _unaryHelper(INT_NEG, popInt(), TypeReference.Int);
1168 break;
1169
1170 case JBC_lneg:
1171 s = _unaryDualHelper(LONG_NEG, popLong(), TypeReference.Long);
1172 break;
1173
1174 case JBC_fneg:
1175 s = _unaryHelper(FLOAT_NEG, popFloat(), TypeReference.Float);
1176 break;
1177
1178 case JBC_dneg:
1179 s = _unaryDualHelper(DOUBLE_NEG, popDouble(), TypeReference.Double);
1180 break;
1181
1182 case JBC_ishl: {
1183 Operand op2 = popShiftInt(false);
1184 Operand op1 = popInt();
1185 s = _binaryHelper(INT_SHL, op1, op2, TypeReference.Int);
1186 }
1187 break;
1188
1189 case JBC_lshl: {
1190 Operand op2 = popShiftInt(true);
1191 Operand op1 = popLong();
1192 s = _binaryDualHelper(LONG_SHL, op1, op2, TypeReference.Long);
1193 }
1194 break;
1195
1196 case JBC_ishr: {
1197 Operand op2 = popShiftInt(false);
1198 Operand op1 = popInt();
1199 s = _binaryHelper(INT_SHR, op1, op2, TypeReference.Int);
1200 }
1201 break;
1202
1203 case JBC_lshr: {
1204 Operand op2 = popShiftInt(true);
1205 Operand op1 = popLong();
1206 s = _binaryDualHelper(LONG_SHR, op1, op2, TypeReference.Long);
1207 }
1208 break;
1209
1210 case JBC_iushr: {
1211 Operand op2 = popShiftInt(false);
1212 Operand op1 = popInt();
1213 s = _binaryHelper(INT_USHR, op1, op2, TypeReference.Int);
1214 }
1215 break;
1216
1217 case JBC_lushr: {
1218 Operand op2 = popShiftInt(true);
1219 Operand op1 = popLong();
1220 s = _binaryDualHelper(LONG_USHR, op1, op2, TypeReference.Long);
1221 }
1222 break;
1223
1224 case JBC_iand: {
1225 Operand op2 = popInt();
1226 Operand op1 = popInt();
1227 s = _binaryHelper(INT_AND, op1, op2, TypeReference.Int);
1228 }
1229 break;
1230
1231 case JBC_land: {
1232 Operand op2 = popLong();
1233 Operand op1 = popLong();
1234 s = _binaryDualHelper(LONG_AND, op1, op2, TypeReference.Long);
1235 }
1236 break;
1237
1238 case JBC_ior: {
1239 Operand op2 = popInt();
1240 Operand op1 = popInt();
1241 s = _binaryHelper(INT_OR, op1, op2, TypeReference.Int);
1242 }
1243 break;
1244
1245 case JBC_lor: {
1246 Operand op2 = popLong();
1247 Operand op1 = popLong();
1248 s = _binaryDualHelper(LONG_OR, op1, op2, TypeReference.Long);
1249 }
1250 break;
1251
1252 case JBC_ixor: {
1253 Operand op2 = popInt();
1254 Operand op1 = popInt();
1255 s = _binaryHelper(INT_XOR, op1, op2, TypeReference.Int);
1256 }
1257 break;
1258
1259 case JBC_lxor: {
1260 Operand op2 = popLong();
1261 Operand op1 = popLong();
1262 s = _binaryDualHelper(LONG_XOR, op1, op2, TypeReference.Long);
1263 }
1264 break;
1265
1266 case JBC_iinc: {
1267 int index = bcodes.getLocalNumber();
1268 s = do_iinc(index, bcodes.getIncrement());
1269 }
1270 break;
1271
1272 case JBC_i2l:
1273 s = _unaryDualHelper(INT_2LONG, popInt(), TypeReference.Long);
1274 break;
1275
1276 case JBC_i2f:
1277 s = _unaryHelper(INT_2FLOAT, popInt(), TypeReference.Float);
1278 break;
1279
1280 case JBC_i2d:
1281 s = _unaryDualHelper(INT_2DOUBLE, popInt(), TypeReference.Double);
1282 break;
1283
1284 case JBC_l2i:
1285 s = _unaryHelper(LONG_2INT, popLong(), TypeReference.Int);
1286 break;
1287
1288 case JBC_l2f:
1289 s = _unaryHelper(LONG_2FLOAT, popLong(), TypeReference.Float);
1290 break;
1291
1292 case JBC_l2d:
1293 s = _unaryDualHelper(LONG_2DOUBLE, popLong(), TypeReference.Double);
1294 break;
1295
1296 case JBC_f2i:
1297 s = _unaryHelper(FLOAT_2INT, popFloat(), TypeReference.Int);
1298 break;
1299
1300 case JBC_f2l:
1301 s = _unaryDualHelper(FLOAT_2LONG, popFloat(), TypeReference.Long);
1302 break;
1303
1304 case JBC_f2d:
1305 s = _unaryDualHelper(FLOAT_2DOUBLE, popFloat(), TypeReference.Double);
1306 break;
1307
1308 case JBC_d2i:
1309 s = _unaryHelper(DOUBLE_2INT, popDouble(), TypeReference.Int);
1310 break;
1311
1312 case JBC_d2l:
1313 s = _unaryDualHelper(DOUBLE_2LONG, popDouble(), TypeReference.Long);
1314 break;
1315
1316 case JBC_d2f:
1317 s = _unaryHelper(DOUBLE_2FLOAT, popDouble(), TypeReference.Float);
1318 break;
1319
1320 case JBC_int2byte:
1321 s = _unaryHelper(INT_2BYTE, popInt(), TypeReference.Byte);
1322 break;
1323
1324 case JBC_int2char:
1325 s = _unaryHelper(INT_2USHORT, popInt(), TypeReference.Char);
1326 break;
1327
1328 case JBC_int2short:
1329 s = _unaryHelper(INT_2SHORT, popInt(), TypeReference.Short);
1330 break;
1331
1332 case JBC_lcmp: {
1333 Operand op2 = popLong();
1334 Operand op1 = popLong();
1335 s = _binaryHelper(LONG_CMP, op1, op2, TypeReference.Int);
1336 }
1337 break;
1338
1339 case JBC_fcmpl: {
1340 Operand op2 = popFloat();
1341 Operand op1 = popFloat();
1342 s = _binaryHelper(FLOAT_CMPL, op1, op2, TypeReference.Int);
1343 }
1344 break;
1345
1346 case JBC_fcmpg: {
1347 Operand op2 = popFloat();
1348 Operand op1 = popFloat();
1349 s = _binaryHelper(FLOAT_CMPG, op1, op2, TypeReference.Int);
1350 }
1351 break;
1352
1353 case JBC_dcmpl: {
1354 Operand op2 = popDouble();
1355 Operand op1 = popDouble();
1356 s = _binaryHelper(DOUBLE_CMPL, op1, op2, TypeReference.Int);
1357 }
1358 break;
1359
1360 case JBC_dcmpg: {
1361 Operand op2 = popDouble();
1362 Operand op1 = popDouble();
1363 s = _binaryHelper(DOUBLE_CMPG, op1, op2, TypeReference.Int);
1364 }
1365 break;
1366
1367 case JBC_ifeq:
1368 s = _intIfHelper(ConditionOperand.EQUAL());
1369 break;
1370
1371 case JBC_ifne:
1372 s = _intIfHelper(ConditionOperand.NOT_EQUAL());
1373 break;
1374
1375 case JBC_iflt:
1376 s = _intIfHelper(ConditionOperand.LESS());
1377 break;
1378
1379 case JBC_ifge:
1380 s = _intIfHelper(ConditionOperand.GREATER_EQUAL());
1381 break;
1382
1383 case JBC_ifgt:
1384 s = _intIfHelper(ConditionOperand.GREATER());
1385 break;
1386
1387 case JBC_ifle:
1388 s = _intIfHelper(ConditionOperand.LESS_EQUAL());
1389 break;
1390
1391 case JBC_if_icmpeq:
1392 s = _intIfCmpHelper(ConditionOperand.EQUAL());
1393 break;
1394
1395 case JBC_if_icmpne:
1396 s = _intIfCmpHelper(ConditionOperand.NOT_EQUAL());
1397 break;
1398
1399 case JBC_if_icmplt:
1400 s = _intIfCmpHelper(ConditionOperand.LESS());
1401 break;
1402
1403 case JBC_if_icmpge:
1404 s = _intIfCmpHelper(ConditionOperand.GREATER_EQUAL());
1405 break;
1406
1407 case JBC_if_icmpgt:
1408 s = _intIfCmpHelper(ConditionOperand.GREATER());
1409 break;
1410
1411 case JBC_if_icmple:
1412 s = _intIfCmpHelper(ConditionOperand.LESS_EQUAL());
1413 break;
1414
1415 case JBC_if_acmpeq:
1416 s = _refIfCmpHelper(ConditionOperand.EQUAL());
1417 break;
1418
1419 case JBC_if_acmpne:
1420 s = _refIfCmpHelper(ConditionOperand.NOT_EQUAL());
1421 break;
1422
1423 case JBC_goto: {
1424 int offset = bcodes.getBranchOffset();
1425 if (offset != 3) {
1426 // skip generating frivolous goto's
1427 s = _gotoHelper(offset);
1428 }
1429 }
1430 break;
1431
1432 case JBC_jsr:
1433 s = _jsrHelper(bcodes.getBranchOffset());
1434 break;
1435
1436 case JBC_ret:
1437 s = _retHelper(bcodes.getLocalNumber());
1438 break;
1439
1440 case JBC_tableswitch: {
1441 bcodes.alignSwitch();
1442 Operand op0 = popInt();
1443 int defaultoff = bcodes.getDefaultSwitchOffset();
1444 int low = bcodes.getLowSwitchValue();
1445 int high = bcodes.getHighSwitchValue();
1446 int number = high - low + 1;
1447 if (CF_TABLESWITCH && op0 instanceof IntConstantOperand) {
1448 int v1 = ((IntConstantOperand) op0).value;
1449 int match = bcodes.computeTableSwitchOffset(v1, low, high);
1450 int offset = match == 0 ? defaultoff : match;
1451 bcodes.skipTableSwitchOffsets(number);
1452 if (DBG_CF) {
1453 db("changed tableswitch to goto because index (" + v1 + ") is constant");
1454 }
1455 s = _gotoHelper(offset);
1456 break;
1457 }
1458 s =
1459 TableSwitch.create(TABLESWITCH,
1460 op0,
1461 null,
1462 null,
1463 new IntConstantOperand(low),
1464 new IntConstantOperand(high),
1465 generateTarget(defaultoff),
1466 null,
1467 number * 2);
1468 for (int i = 0; i < number; ++i) {
1469 TableSwitch.setTarget(s, i, generateTarget(bcodes.getTableSwitchOffset(i)));
1470 }
1471 bcodes.skipTableSwitchOffsets(number);
1472
1473 // Set branch probabilities
1474 SwitchBranchProfile sp = gc.getSwitchProfile(instrIndex - bciAdjustment);
1475 if (sp == null) {