jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java
changeset 46174 5611d2529b49
parent 45853 bfa06be36a17
equal deleted inserted replaced
46173:5546b5710844 46174:5611d2529b49
    15  * distributed under the License is distributed on an "AS IS" BASIS,
    15  * distributed under the License is distributed on an "AS IS" BASIS,
    16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    17  * See the License for the specific language governing permissions and
    17  * See the License for the specific language governing permissions and
    18  * limitations under the License.
    18  * limitations under the License.
    19  */
    19  */
    20 
       
    21 package com.sun.org.apache.bcel.internal.generic;
    20 package com.sun.org.apache.bcel.internal.generic;
    22 
    21 
    23 
    22 import java.io.DataOutputStream;
    24 import com.sun.org.apache.bcel.internal.Constants;
    23 import java.io.IOException;
       
    24 
       
    25 import com.sun.org.apache.bcel.internal.Const;
    25 import com.sun.org.apache.bcel.internal.classfile.ConstantPool;
    26 import com.sun.org.apache.bcel.internal.classfile.ConstantPool;
    26 import java.io.*;
       
    27 import com.sun.org.apache.bcel.internal.util.ByteSequence;
    27 import com.sun.org.apache.bcel.internal.util.ByteSequence;
    28 
    28 
    29 /**
    29 /**
    30  * Abstract super class for all Java byte codes.
    30  * Abstract super class for all Java byte codes.
    31  *
    31  *
    32  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
    32  * @version $Id: Instruction.java 1750029 2016-06-23 22:14:38Z sebb $
    33  */
    33  */
    34 public abstract class Instruction implements Cloneable, Serializable {
    34 public abstract class Instruction implements Cloneable {
    35   protected short length = 1;  // Length of instruction in bytes
    35 
    36   protected short opcode = -1; // Opcode number
    36     private short length = 1; // Length of instruction in bytes
    37 
    37     private short opcode = -1; // Opcode number
    38   private static InstructionComparator cmp = InstructionComparator.DEFAULT;
    38 
    39 
    39     private static InstructionComparator cmp = InstructionComparator.DEFAULT;
    40   /**
    40 
    41    * Empty constructor needed for the Class.newInstance() statement in
    41     /**
    42    * Instruction.readInstruction(). Not to be used otherwise.
    42      * Empty constructor needed for the Class.newInstance() statement in
    43    */
    43      * Instruction.readInstruction(). Not to be used otherwise.
    44   Instruction() {}
    44      */
    45 
    45     Instruction() {
    46   public Instruction(short opcode, short length) {
    46     }
    47     this.length = length;
    47 
    48     this.opcode = opcode;
    48     public Instruction(final short opcode, final short length) {
    49   }
    49         this.length = length;
    50 
    50         this.opcode = opcode;
    51   /**
    51     }
    52    * Dump instruction as byte code to stream out.
    52 
    53    * @param out Output stream
    53     /**
    54    */
    54      * Dump instruction as byte code to stream out.
    55   public void dump(DataOutputStream out) throws IOException {
    55      *
    56     out.writeByte(opcode); // Common for all instructions
    56      * @param out Output stream
    57   }
    57      */
    58 
    58     public void dump(final DataOutputStream out) throws IOException {
    59   /** @return name of instruction, i.e., opcode name
    59         out.writeByte(opcode); // Common for all instructions
    60    */
    60     }
    61   public String getName() {
    61 
    62     return Constants.OPCODE_NAMES[opcode];
    62     /**
    63   }
    63      * @return name of instruction, i.e., opcode name
    64 
    64      */
    65   /**
    65     public String getName() {
    66    * Long output format:
    66         return Const.getOpcodeName(opcode);
    67    *
    67     }
    68    * &lt;name of opcode&gt; "["&lt;opcode number&gt;"]"
    68 
    69    * "("&lt;length of instruction&gt;")"
    69     /**
    70    *
    70      * Long output format:
    71    * @param verbose long/short format switch
    71      *
    72    * @return mnemonic for instruction
    72      * &lt;name of opcode&gt; "["&lt;opcode number&gt;"]" "("&lt;length of
    73    */
    73      * instruction&gt;")"
    74   public String toString(boolean verbose) {
    74      *
    75     if(verbose)
    75      * @param verbose long/short format switch
    76       return getName() + "[" + opcode + "](" + length + ")";
    76      * @return mnemonic for instruction
    77     else
    77      */
    78       return getName();
    78     public String toString(final boolean verbose) {
    79   }
    79         if (verbose) {
    80 
    80             return getName() + "[" + opcode + "](" + length + ")";
    81   /**
    81         }
    82    * @return mnemonic for instruction in verbose format
    82         return getName();
    83    */
    83     }
    84   public String toString() {
    84 
    85     return toString(true);
    85     /**
    86   }
    86      * @return mnemonic for instruction in verbose format
    87 
    87      */
    88   /**
    88     @Override
    89    * @return mnemonic for instruction with sumbolic references resolved
    89     public String toString() {
    90    */
    90         return toString(true);
    91   public String toString(ConstantPool cp) {
    91     }
    92     return toString(false);
    92 
    93   }
    93     /**
    94 
    94      * @return mnemonic for instruction with sumbolic references resolved
    95   /**
    95      */
    96    * Use with caution, since `BranchInstruction's have a `target' reference which
    96     public String toString(final ConstantPool cp) {
    97    * is not copied correctly (only basic types are). This also applies for
    97         return toString(false);
    98    * `Select' instructions with their multiple branch targets.
    98     }
    99    *
    99 
   100    * @see BranchInstruction
   100     /**
   101    * @return (shallow) copy of an instruction
   101      * Use with caution, since `BranchInstruction's have a `target' reference
   102    */
   102      * which is not copied correctly (only basic types are). This also applies
   103   public Instruction copy() {
   103      * for `Select' instructions with their multiple branch targets.
   104     Instruction i = null;
   104      *
   105 
   105      * @see BranchInstruction
   106     // "Constant" instruction, no need to duplicate
   106      * @return (shallow) copy of an instruction
   107     if(InstructionConstants.INSTRUCTIONS[this.getOpcode()] != null)
   107      */
   108       i = this;
   108     public Instruction copy() {
   109     else {
   109         Instruction i = null;
   110       try {
   110         // "Constant" instruction, no need to duplicate
   111         i = (Instruction)clone();
   111         if (InstructionConst.getInstruction(this.getOpcode()) != null) {
   112       } catch(CloneNotSupportedException e) {
   112             i = this;
   113         System.err.println(e);
   113         } else {
   114       }
   114             try {
   115     }
   115                 i = (Instruction) clone();
   116 
   116             } catch (final CloneNotSupportedException e) {
   117     return i;
   117                 System.err.println(e);
   118   }
   118             }
   119 
   119         }
   120   /**
   120         return i;
   121    * Read needed data (e.g. index) from file.
   121     }
   122    *
   122 
   123    * @param bytes byte sequence to read from
   123     /**
   124    * @param wide "wide" instruction flag
   124      * Read needed data (e.g. index) from file.
   125    */
   125      *
   126   protected void initFromFile(ByteSequence bytes, boolean wide)
   126      * @param bytes byte sequence to read from
   127     throws IOException
   127      * @param wide "wide" instruction flag
   128   {}
   128      * @throws IOException may be thrown if the implementation needs to read
   129 
   129      * data from the file
   130   /**
   130      */
   131    * Read an instruction from (byte code) input stream and return the
   131     protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
   132    * appropiate object.
   132     }
   133    *
   133 
   134    * @param file file to read from
   134     /**
   135    * @return instruction object being read
   135      * Read an instruction from (byte code) input stream and return the
   136    */
   136      * appropiate object.
   137   public static final Instruction readInstruction(ByteSequence bytes)
   137      * <p>
   138     throws IOException
   138      * If the Instruction is defined in {@link InstructionConst}, then the
   139   {
   139      * singleton instance is returned.
   140     boolean     wide   = false;
   140      *
   141     short       opcode = (short)bytes.readUnsignedByte();
   141      * @param bytes input stream bytes
   142     Instruction obj    = null;
   142      * @return instruction object being read
   143 
   143      * @see InstructionConst#getInstruction(int)
   144     if(opcode == Constants.WIDE) { // Read next opcode after wide byte
   144      */
   145       wide = true;
   145     // @since 6.0 no longer final
   146       opcode  = (short)bytes.readUnsignedByte();
   146     public static Instruction readInstruction(final ByteSequence bytes) throws IOException {
   147     }
   147         boolean wide = false;
   148 
   148         short opcode = (short) bytes.readUnsignedByte();
   149     if(InstructionConstants.INSTRUCTIONS[opcode] != null)
   149         Instruction obj = null;
   150       return InstructionConstants.INSTRUCTIONS[opcode]; // Used predefined immutable object, if available
   150         if (opcode == Const.WIDE) { // Read next opcode after wide byte
   151 
   151             wide = true;
   152     /* Find appropiate class, instantiate an (empty) instruction object
   152             opcode = (short) bytes.readUnsignedByte();
   153      * and initialize it by hand.
   153         }
   154      */
   154         final Instruction instruction = InstructionConst.getInstruction(opcode);
   155     Class clazz;
   155         if (instruction != null) {
   156 
   156             return instruction; // Used predefined immutable object, if available
   157     try {
   157         }
   158       clazz = Class.forName(className(opcode));
   158 
   159     } catch (ClassNotFoundException cnfe){
   159         switch (opcode) {
   160       // If a class by that name does not exist, the opcode is illegal.
   160             case Const.BIPUSH:
   161       // Note that IMPDEP1, IMPDEP2, BREAKPOINT are also illegal in a sense.
   161                 obj = new BIPUSH();
   162       throw new ClassGenException("Illegal opcode detected.");
   162                 break;
   163     }
   163             case Const.SIPUSH:
   164 
   164                 obj = new SIPUSH();
   165     try {
   165                 break;
   166       obj = (Instruction)clazz.getConstructor().newInstance();
   166             case Const.LDC:
   167 
   167                 obj = new LDC();
   168       if(wide && !((obj instanceof LocalVariableInstruction) ||
   168                 break;
   169                    (obj instanceof IINC) ||
   169             case Const.LDC_W:
   170                    (obj instanceof RET)))
   170                 obj = new LDC_W();
   171         throw new Exception("Illegal opcode after wide: " + opcode);
   171                 break;
   172 
   172             case Const.LDC2_W:
   173       obj.setOpcode(opcode);
   173                 obj = new LDC2_W();
   174       obj.initFromFile(bytes, wide); // Do further initializations, if any
   174                 break;
   175       // Byte code offset set in InstructionList
   175             case Const.ILOAD:
   176     } catch(Exception e) { throw new ClassGenException(e.toString()); }
   176                 obj = new ILOAD();
   177 
   177                 break;
   178     return obj;
   178             case Const.LLOAD:
   179   }
   179                 obj = new LLOAD();
   180 
   180                 break;
   181   private static final String className(short opcode) {
   181             case Const.FLOAD:
   182     String name = Constants.OPCODE_NAMES[opcode].toUpperCase();
   182                 obj = new FLOAD();
   183 
   183                 break;
   184     /* ICONST_0, etc. will be shortened to ICONST, etc., since ICONST_0 and the like
   184             case Const.DLOAD:
   185      * are not implemented (directly).
   185                 obj = new DLOAD();
   186      */
   186                 break;
   187     try {
   187             case Const.ALOAD:
   188       int  len = name.length();
   188                 obj = new ALOAD();
   189       char ch1 = name.charAt(len - 2), ch2 = name.charAt(len - 1);
   189                 break;
   190 
   190             case Const.ILOAD_0:
   191       if((ch1 == '_') && (ch2 >= '0')  && (ch2 <= '5'))
   191                 obj = new ILOAD(0);
   192         name = name.substring(0, len - 2);
   192                 break;
   193 
   193             case Const.ILOAD_1:
   194       if(name.equals("ICONST_M1")) // Special case
   194                 obj = new ILOAD(1);
   195         name = "ICONST";
   195                 break;
   196     } catch(StringIndexOutOfBoundsException e) { System.err.println(e); }
   196             case Const.ILOAD_2:
   197 
   197                 obj = new ILOAD(2);
   198     return "com.sun.org.apache.bcel.internal.generic." + name;
   198                 break;
   199   }
   199             case Const.ILOAD_3:
   200 
   200                 obj = new ILOAD(3);
   201   /**
   201                 break;
   202    * This method also gives right results for instructions whose
   202             case Const.LLOAD_0:
   203    * effect on the stack depends on the constant pool entry they
   203                 obj = new LLOAD(0);
   204    * reference.
   204                 break;
   205    *  @return Number of words consumed from stack by this instruction,
   205             case Const.LLOAD_1:
   206    * or Constants.UNPREDICTABLE, if this can not be computed statically
   206                 obj = new LLOAD(1);
   207    */
   207                 break;
   208   public int consumeStack(ConstantPoolGen cpg) {
   208             case Const.LLOAD_2:
   209     return Constants.CONSUME_STACK[opcode];
   209                 obj = new LLOAD(2);
   210   }
   210                 break;
   211 
   211             case Const.LLOAD_3:
   212   /**
   212                 obj = new LLOAD(3);
   213    * This method also gives right results for instructions whose
   213                 break;
   214    * effect on the stack depends on the constant pool entry they
   214             case Const.FLOAD_0:
   215    * reference.
   215                 obj = new FLOAD(0);
   216    * @return Number of words produced onto stack by this instruction,
   216                 break;
   217    * or Constants.UNPREDICTABLE, if this can not be computed statically
   217             case Const.FLOAD_1:
   218    */
   218                 obj = new FLOAD(1);
   219   public int produceStack(ConstantPoolGen cpg) {
   219                 break;
   220     return Constants.PRODUCE_STACK[opcode];
   220             case Const.FLOAD_2:
   221   }
   221                 obj = new FLOAD(2);
   222 
   222                 break;
   223   /**
   223             case Const.FLOAD_3:
   224    * @return this instructions opcode
   224                 obj = new FLOAD(3);
   225    */
   225                 break;
   226   public short getOpcode()    { return opcode; }
   226             case Const.DLOAD_0:
   227 
   227                 obj = new DLOAD(0);
   228   /**
   228                 break;
   229    * @return length (in bytes) of instruction
   229             case Const.DLOAD_1:
   230    */
   230                 obj = new DLOAD(1);
   231   public int getLength()   { return length; }
   231                 break;
   232 
   232             case Const.DLOAD_2:
   233   /**
   233                 obj = new DLOAD(2);
   234    * Needed in readInstruction.
   234                 break;
   235    */
   235             case Const.DLOAD_3:
   236   private void setOpcode(short opcode) { this.opcode = opcode; }
   236                 obj = new DLOAD(3);
   237 
   237                 break;
   238   /** Some instructions may be reused, so don't do anything by default.
   238             case Const.ALOAD_0:
   239    */
   239                 obj = new ALOAD(0);
   240   void dispose() {}
   240                 break;
   241 
   241             case Const.ALOAD_1:
   242   /**
   242                 obj = new ALOAD(1);
   243    * Call corresponding visitor method(s). The order is:
   243                 break;
   244    * Call visitor methods of implemented interfaces first, then
   244             case Const.ALOAD_2:
   245    * call methods according to the class hierarchy in descending order,
   245                 obj = new ALOAD(2);
   246    * i.e., the most specific visitXXX() call comes last.
   246                 break;
   247    *
   247             case Const.ALOAD_3:
   248    * @param v Visitor object
   248                 obj = new ALOAD(3);
   249    */
   249                 break;
   250   public abstract void accept(Visitor v);
   250             case Const.ISTORE:
   251 
   251                 obj = new ISTORE();
   252   /** Get Comparator object used in the equals() method to determine
   252                 break;
   253    * equality of instructions.
   253             case Const.LSTORE:
   254    *
   254                 obj = new LSTORE();
   255    * @return currently used comparator for equals()
   255                 break;
   256    */
   256             case Const.FSTORE:
   257   public static InstructionComparator getComparator() { return cmp; }
   257                 obj = new FSTORE();
   258 
   258                 break;
   259   /** Set comparator to be used for equals().
   259             case Const.DSTORE:
   260    */
   260                 obj = new DSTORE();
   261   public static void setComparator(InstructionComparator c) { cmp = c; }
   261                 break;
   262 
   262             case Const.ASTORE:
   263   /** Check for equality, delegated to comparator
   263                 obj = new ASTORE();
   264    * @return true if that is an Instruction and has the same opcode
   264                 break;
   265    */
   265             case Const.ISTORE_0:
   266   public boolean equals(Object that) {
   266                 obj = new ISTORE(0);
   267     return (that instanceof Instruction)?
   267                 break;
   268       cmp.equals(this, (Instruction)that) : false;
   268             case Const.ISTORE_1:
   269   }
   269                 obj = new ISTORE(1);
       
   270                 break;
       
   271             case Const.ISTORE_2:
       
   272                 obj = new ISTORE(2);
       
   273                 break;
       
   274             case Const.ISTORE_3:
       
   275                 obj = new ISTORE(3);
       
   276                 break;
       
   277             case Const.LSTORE_0:
       
   278                 obj = new LSTORE(0);
       
   279                 break;
       
   280             case Const.LSTORE_1:
       
   281                 obj = new LSTORE(1);
       
   282                 break;
       
   283             case Const.LSTORE_2:
       
   284                 obj = new LSTORE(2);
       
   285                 break;
       
   286             case Const.LSTORE_3:
       
   287                 obj = new LSTORE(3);
       
   288                 break;
       
   289             case Const.FSTORE_0:
       
   290                 obj = new FSTORE(0);
       
   291                 break;
       
   292             case Const.FSTORE_1:
       
   293                 obj = new FSTORE(1);
       
   294                 break;
       
   295             case Const.FSTORE_2:
       
   296                 obj = new FSTORE(2);
       
   297                 break;
       
   298             case Const.FSTORE_3:
       
   299                 obj = new FSTORE(3);
       
   300                 break;
       
   301             case Const.DSTORE_0:
       
   302                 obj = new DSTORE(0);
       
   303                 break;
       
   304             case Const.DSTORE_1:
       
   305                 obj = new DSTORE(1);
       
   306                 break;
       
   307             case Const.DSTORE_2:
       
   308                 obj = new DSTORE(2);
       
   309                 break;
       
   310             case Const.DSTORE_3:
       
   311                 obj = new DSTORE(3);
       
   312                 break;
       
   313             case Const.ASTORE_0:
       
   314                 obj = new ASTORE(0);
       
   315                 break;
       
   316             case Const.ASTORE_1:
       
   317                 obj = new ASTORE(1);
       
   318                 break;
       
   319             case Const.ASTORE_2:
       
   320                 obj = new ASTORE(2);
       
   321                 break;
       
   322             case Const.ASTORE_3:
       
   323                 obj = new ASTORE(3);
       
   324                 break;
       
   325             case Const.IINC:
       
   326                 obj = new IINC();
       
   327                 break;
       
   328             case Const.IFEQ:
       
   329                 obj = new IFEQ();
       
   330                 break;
       
   331             case Const.IFNE:
       
   332                 obj = new IFNE();
       
   333                 break;
       
   334             case Const.IFLT:
       
   335                 obj = new IFLT();
       
   336                 break;
       
   337             case Const.IFGE:
       
   338                 obj = new IFGE();
       
   339                 break;
       
   340             case Const.IFGT:
       
   341                 obj = new IFGT();
       
   342                 break;
       
   343             case Const.IFLE:
       
   344                 obj = new IFLE();
       
   345                 break;
       
   346             case Const.IF_ICMPEQ:
       
   347                 obj = new IF_ICMPEQ();
       
   348                 break;
       
   349             case Const.IF_ICMPNE:
       
   350                 obj = new IF_ICMPNE();
       
   351                 break;
       
   352             case Const.IF_ICMPLT:
       
   353                 obj = new IF_ICMPLT();
       
   354                 break;
       
   355             case Const.IF_ICMPGE:
       
   356                 obj = new IF_ICMPGE();
       
   357                 break;
       
   358             case Const.IF_ICMPGT:
       
   359                 obj = new IF_ICMPGT();
       
   360                 break;
       
   361             case Const.IF_ICMPLE:
       
   362                 obj = new IF_ICMPLE();
       
   363                 break;
       
   364             case Const.IF_ACMPEQ:
       
   365                 obj = new IF_ACMPEQ();
       
   366                 break;
       
   367             case Const.IF_ACMPNE:
       
   368                 obj = new IF_ACMPNE();
       
   369                 break;
       
   370             case Const.GOTO:
       
   371                 obj = new GOTO();
       
   372                 break;
       
   373             case Const.JSR:
       
   374                 obj = new JSR();
       
   375                 break;
       
   376             case Const.RET:
       
   377                 obj = new RET();
       
   378                 break;
       
   379             case Const.TABLESWITCH:
       
   380                 obj = new TABLESWITCH();
       
   381                 break;
       
   382             case Const.LOOKUPSWITCH:
       
   383                 obj = new LOOKUPSWITCH();
       
   384                 break;
       
   385             case Const.GETSTATIC:
       
   386                 obj = new GETSTATIC();
       
   387                 break;
       
   388             case Const.PUTSTATIC:
       
   389                 obj = new PUTSTATIC();
       
   390                 break;
       
   391             case Const.GETFIELD:
       
   392                 obj = new GETFIELD();
       
   393                 break;
       
   394             case Const.PUTFIELD:
       
   395                 obj = new PUTFIELD();
       
   396                 break;
       
   397             case Const.INVOKEVIRTUAL:
       
   398                 obj = new INVOKEVIRTUAL();
       
   399                 break;
       
   400             case Const.INVOKESPECIAL:
       
   401                 obj = new INVOKESPECIAL();
       
   402                 break;
       
   403             case Const.INVOKESTATIC:
       
   404                 obj = new INVOKESTATIC();
       
   405                 break;
       
   406             case Const.INVOKEINTERFACE:
       
   407                 obj = new INVOKEINTERFACE();
       
   408                 break;
       
   409             case Const.INVOKEDYNAMIC:
       
   410                 obj = new INVOKEDYNAMIC();
       
   411                 break;
       
   412             case Const.NEW:
       
   413                 obj = new NEW();
       
   414                 break;
       
   415             case Const.NEWARRAY:
       
   416                 obj = new NEWARRAY();
       
   417                 break;
       
   418             case Const.ANEWARRAY:
       
   419                 obj = new ANEWARRAY();
       
   420                 break;
       
   421             case Const.CHECKCAST:
       
   422                 obj = new CHECKCAST();
       
   423                 break;
       
   424             case Const.INSTANCEOF:
       
   425                 obj = new INSTANCEOF();
       
   426                 break;
       
   427             case Const.MULTIANEWARRAY:
       
   428                 obj = new MULTIANEWARRAY();
       
   429                 break;
       
   430             case Const.IFNULL:
       
   431                 obj = new IFNULL();
       
   432                 break;
       
   433             case Const.IFNONNULL:
       
   434                 obj = new IFNONNULL();
       
   435                 break;
       
   436             case Const.GOTO_W:
       
   437                 obj = new GOTO_W();
       
   438                 break;
       
   439             case Const.JSR_W:
       
   440                 obj = new JSR_W();
       
   441                 break;
       
   442             case Const.BREAKPOINT:
       
   443                 obj = new BREAKPOINT();
       
   444                 break;
       
   445             case Const.IMPDEP1:
       
   446                 obj = new IMPDEP1();
       
   447                 break;
       
   448             case Const.IMPDEP2:
       
   449                 obj = new IMPDEP2();
       
   450                 break;
       
   451             default:
       
   452                 throw new ClassGenException("Illegal opcode detected: " + opcode);
       
   453 
       
   454         }
       
   455 
       
   456         if (wide
       
   457                 && !((obj instanceof LocalVariableInstruction) || (obj instanceof IINC) || (obj instanceof RET))) {
       
   458             throw new ClassGenException("Illegal opcode after wide: " + opcode);
       
   459         }
       
   460         obj.setOpcode(opcode);
       
   461         obj.initFromFile(bytes, wide); // Do further initializations, if any
       
   462         return obj;
       
   463     }
       
   464 
       
   465     /**
       
   466      * This method also gives right results for instructions whose effect on the
       
   467      * stack depends on the constant pool entry they reference.
       
   468      *
       
   469      * @return Number of words consumed from stack by this instruction, or
       
   470      * Constants.UNPREDICTABLE, if this can not be computed statically
       
   471      */
       
   472     public int consumeStack(final ConstantPoolGen cpg) {
       
   473         return Const.getConsumeStack(opcode);
       
   474     }
       
   475 
       
   476     /**
       
   477      * This method also gives right results for instructions whose effect on the
       
   478      * stack depends on the constant pool entry they reference.
       
   479      *
       
   480      * @return Number of words produced onto stack by this instruction, or
       
   481      * Constants.UNPREDICTABLE, if this can not be computed statically
       
   482      */
       
   483     public int produceStack(final ConstantPoolGen cpg) {
       
   484         return Const.getProduceStack(opcode);
       
   485     }
       
   486 
       
   487     /**
       
   488      * @return this instructions opcode
       
   489      */
       
   490     public short getOpcode() {
       
   491         return opcode;
       
   492     }
       
   493 
       
   494     /**
       
   495      * @return length (in bytes) of instruction
       
   496      */
       
   497     public int getLength() {
       
   498         return length;
       
   499     }
       
   500 
       
   501     /**
       
   502      * Needed in readInstruction and subclasses in this package
       
   503      */
       
   504     final void setOpcode(final short opcode) {
       
   505         this.opcode = opcode;
       
   506     }
       
   507 
       
   508     /**
       
   509      * Needed in readInstruction and subclasses in this package
       
   510      *
       
   511      * @since 6.0
       
   512      */
       
   513     final void setLength(final int length) {
       
   514         this.length = (short) length; // TODO check range?
       
   515     }
       
   516 
       
   517     /**
       
   518      * Some instructions may be reused, so don't do anything by default.
       
   519      */
       
   520     void dispose() {
       
   521     }
       
   522 
       
   523     /**
       
   524      * Call corresponding visitor method(s). The order is: Call visitor methods
       
   525      * of implemented interfaces first, then call methods according to the class
       
   526      * hierarchy in descending order, i.e., the most specific visitXXX() call
       
   527      * comes last.
       
   528      *
       
   529      * @param v Visitor object
       
   530      */
       
   531     public abstract void accept(Visitor v);
       
   532 
       
   533     /**
       
   534      * Get Comparator object used in the equals() method to determine equality
       
   535      * of instructions.
       
   536      *
       
   537      * @return currently used comparator for equals()
       
   538      * @deprecated (6.0) use the built in comparator, or wrap this class in
       
   539      * another object that implements these methods
       
   540      */
       
   541     @Deprecated
       
   542     public static InstructionComparator getComparator() {
       
   543         return cmp;
       
   544     }
       
   545 
       
   546     /**
       
   547      * Set comparator to be used for equals().
       
   548      *
       
   549      * @deprecated (6.0) use the built in comparator, or wrap this class in
       
   550      * another object that implements these methods
       
   551      */
       
   552     @Deprecated
       
   553     public static void setComparator(final InstructionComparator c) {
       
   554         cmp = c;
       
   555     }
       
   556 
       
   557     /**
       
   558      * Check for equality, delegated to comparator
       
   559      *
       
   560      * @return true if that is an Instruction and has the same opcode
       
   561      */
       
   562     @Override
       
   563     public boolean equals(final Object that) {
       
   564         return (that instanceof Instruction) ? cmp.equals(this, (Instruction) that) : false;
       
   565     }
       
   566 
       
   567     /**
       
   568      * calculate the hashCode of this object
       
   569      *
       
   570      * @return the hashCode
       
   571      * @since 6.0
       
   572      */
       
   573     @Override
       
   574     public int hashCode() {
       
   575         return opcode;
       
   576     }
       
   577 
       
   578     /**
       
   579      * Check if the value can fit in a byte (signed)
       
   580      *
       
   581      * @param value the value to check
       
   582      * @return true if the value is in range
       
   583      * @since 6.0
       
   584      */
       
   585     public static boolean isValidByte(final int value) {
       
   586         return value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE;
       
   587     }
       
   588 
       
   589     /**
       
   590      * Check if the value can fit in a short (signed)
       
   591      *
       
   592      * @param value the value to check
       
   593      * @return true if the value is in range
       
   594      * @since 6.0
       
   595      */
       
   596     public static boolean isValidShort(final int value) {
       
   597         return value >= Short.MIN_VALUE && value <= Short.MAX_VALUE;
       
   598     }
   270 }
   599 }