gt:                     index += 2;
context: /*
   * Bytecode Analysis Framework
   * Copyright (C) 2003,2004 University of Maryland
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
   * License along with this library; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  
  package edu.umd.cs.findbugs.ba;
  
  import edu.umd.cs.findbugs.SystemProperties;
  
  /**
   * Scan the raw bytecodes of a method. This is useful in order to find out
   * quickly whether or not a method uses particular instructions.
   * 
   * @author David Hovemeyer
   */
  public class BytecodeScanner implements org.apache.bcel.Constants {
      private static final boolean DEBUG = SystemProperties.getBoolean("bs.debug");
  
      /**
       * Callback interface to report scanned instructions.
       */
      public interface Callback {
          /**
           * Called to indicate that a particular bytecode has been scanned.
           * 
           * @param opcode
           *            the opcode of the instruction
           * @param index
           *            the bytecode offset of the instruction
           */
          public void handleInstruction(int opcode, int index);
      }
  
      /**
       * Convert the unsigned value of a byte into a short.
       * 
       * @param value
       *            the byte
       * @return the byte's unsigned value as a short
       */
      private static short unsignedValueOf(byte value) {
          short result;
          if ((value & 0x80) != 0) {
              result = (short) (value & 0x7F);
              result |= 0x80;
          } else {
              result = value;
          }
          return result;
      }
  
      /**
       * Extract an int from bytes at the given offset in the array.
       * 
       * @param arr
       *            the array
       * @param offset
       *            the offset in the array
       */
      private static int extractInt(byte[] arr, int offset) {
          return ((arr[offset] & 0xFF) << 24) | ((arr[offset + 1] & 0xFF) << 16) | ((arr[offset + 2] & 0xFF) << 8)
                  | (arr[offset + 3] & 0xFF);
      }
  
      private static final int PAD[] = { 0, 3, 2, 1 };
  
      /**
       * Scan the raw bytecodes of a method.
       * 
       * @param instructionList
       *            the bytecodes
       * @param callback
       *            the callback object
       */
      public void scan(byte[] instructionList, Callback callback) {
  
          boolean wide = false;
  
          for (int index = 0; index < instructionList.length;) {
              short opcode = unsignedValueOf(instructionList[index]);
              callback.handleInstruction(opcode, index);
  
              if (DEBUG)
                  System.out.println(index + ": " + OPCODE_NAMES[opcode]);
  
              switch (opcode) {
  
              // Single byte instructions.
              case NOP:
              case ACONST_NULL:
              case ICONST_M1:
              case ICONST_0:
              case ICONST_1:
              case ICONST_2:
              case ICONST_3:
              case ICONST_4:
              case ICONST_5:
              case LCONST_0:
              case LCONST_1:
              case FCONST_0:
              case FCONST_1:
              case FCONST_2:
              case DCONST_0:
              case DCONST_1:
              case ILOAD_0:
              case ILOAD_1:
              case ILOAD_2:
              case ILOAD_3:
              case LLOAD_0:
              case LLOAD_1:
              case LLOAD_2:
              case LLOAD_3:
              case FLOAD_0:
              case FLOAD_1:
              case FLOAD_2:
              case FLOAD_3:
              case DLOAD_0:
              case DLOAD_1:
              case DLOAD_2:
              case DLOAD_3:
              case ALOAD_0:
              case ALOAD_1:
              case ALOAD_2:
              case ALOAD_3:
              case IALOAD:
              case LALOAD:
              case FALOAD:
              case DALOAD:
              case AALOAD:
              case BALOAD:
              case CALOAD:
              case SALOAD:
              case ISTORE_0:
              case ISTORE_1:
              case ISTORE_2:
              case ISTORE_3:
              case LSTORE_0:
              case LSTORE_1:
              case LSTORE_2:
              case LSTORE_3:
              case FSTORE_0:
              case FSTORE_1:
              case FSTORE_2:
              case FSTORE_3:
              case DSTORE_0:
              case DSTORE_1:
              case DSTORE_2:
              case DSTORE_3:
              case ASTORE_0:
              case ASTORE_1:
              case ASTORE_2:
              case ASTORE_3:
              case IASTORE:
              case LASTORE:
              case FASTORE:
              case DASTORE:
              case AASTORE:
              case BASTORE:
              case CASTORE:
              case SASTORE:
              case POP:
              case POP2:
              case DUP:
              case DUP_X1:
              case DUP_X2:
              case DUP2:
              case DUP2_X1:
              case DUP2_X2:
              case SWAP:
              case IADD:
              case LADD:
              case FADD:
              case DADD:
              case ISUB:
              case LSUB:
              case FSUB:
              case DSUB:
              case IMUL:
              case LMUL:
              case FMUL:
              case DMUL:
              case IDIV:
              case LDIV:
              case FDIV:
              case DDIV:
              case IREM:
              case LREM:
              case FREM:
              case DREM:
              case INEG:
              case LNEG:
              case FNEG:
              case DNEG:
              case ISHL:
              case LSHL:
              case ISHR:
              case LSHR:
              case IUSHR:
              case LUSHR:
              case IAND:
              case LAND:
              case IOR:
              case LOR:
              case IXOR:
              case LXOR:
              case I2L:
              case I2F:
              case I2D:
              case L2I:
              case L2F:
              case L2D:
              case F2I:
              case F2L:
              case F2D:
              case D2I:
              case D2L:
              case D2F:
              case I2B:
              case I2C:
              case I2S:
              case LCMP:
              case FCMPL:
              case FCMPG:
              case DCMPL:
              case DCMPG:
              case IRETURN:
              case LRETURN:
              case FRETURN:
              case DRETURN:
              case ARETURN:
              case RETURN:
              case ARRAYLENGTH:
              case ATHROW:
              case MONITORENTER:
              case MONITOREXIT:
                  ++index;
                  break;
  
              // Two byte instructions.
              case BIPUSH:
              case LDC:
              case NEWARRAY:
                  index += 2;
                  break;
  
              // Instructions that can be used with the WIDE prefix.
              case ILOAD:
              case LLOAD:
              case FLOAD:
              case DLOAD:
              case ALOAD:
              case ISTORE:
              case LSTORE:
              case FSTORE:
              case DSTORE:
              case ASTORE:
              case RET:
                  if (wide) {
                      // Skip opcode and two immediate bytes.
                      index += 3;
                      wide = false;
                  } else {
                      // Skip opcode and one immediate byte.
  