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) {