--- old/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java 2017-08-08 16:05:55.315507276 -0700 +++ new/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java 2017-08-08 16:05:55.211502071 -0700 @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -18,176 +17,205 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.sun.org.apache.bcel.internal.generic; -import java.io.*; +import java.io.DataOutputStream; +import java.io.IOException; + +import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.util.ByteSequence; -import com.sun.org.apache.bcel.internal.classfile.Utility; -import com.sun.org.apache.bcel.internal.Constants; /** * Abstract super class for instructions dealing with local variables. * - * @author M. Dahm + * @version $Id: LocalVariableInstruction.java 1747278 2016-06-07 17:28:43Z + * britter $ */ -public abstract class LocalVariableInstruction extends Instruction - implements TypedInstruction, IndexedInstruction { - protected int n = -1; // index of referenced variable - private short c_tag = -1; // compact version, such as ILOAD_0 - private short canon_tag = -1; // canonical tag such as ILOAD - - private final boolean wide() { return n > Constants.MAX_BYTE; } - - /** - * Empty constructor needed for the Class.newInstance() statement in - * Instruction.readInstruction(). Not to be used otherwise. - * tag and length are defined in readInstruction and initFromFile, respectively. - */ - LocalVariableInstruction(short canon_tag, short c_tag) { - super(); - this.canon_tag = canon_tag; - this.c_tag = c_tag; - } - - /** - * Empty constructor needed for the Class.newInstance() statement in - * Instruction.readInstruction(). Also used by IINC()! - */ - LocalVariableInstruction() { - } - - /** - * @param opcode Instruction opcode - * @param c_tag Instruction number for compact version, ALOAD_0, e.g. - * @param n local variable index (unsigned short) - */ - protected LocalVariableInstruction(short opcode, short c_tag, int n) { - super(opcode, (short)2); - - this.c_tag = c_tag; - canon_tag = opcode; - - setIndex(n); - } - - /** - * Dump instruction as byte code to stream out. - * @param out Output stream - */ - public void dump(DataOutputStream out) throws IOException { - if(wide()) // Need WIDE prefix ? - out.writeByte(Constants.WIDE); - - out.writeByte(opcode); - - if(length > 1) { // Otherwise ILOAD_n, instruction, e.g. - if(wide()) - out.writeShort(n); - else - out.writeByte(n); - } - } - - /** - * Long output format: - * - * <name of opcode> "["<opcode number>"]" - * "("<length of instruction>")" "<"< local variable index>">" - * - * @param verbose long/short format switch - * @return mnemonic for instruction - */ - public String toString(boolean verbose) { - if(((opcode >= Constants.ILOAD_0) && - (opcode <= Constants.ALOAD_3)) || - ((opcode >= Constants.ISTORE_0) && - (opcode <= Constants.ASTORE_3))) - return super.toString(verbose); - else - return super.toString(verbose) + " " + n; - } - - /** - * Read needed data (e.g. index) from file. - * PRE: (ILOAD <= tag <= ALOAD_3) || (ISTORE <= tag <= ASTORE_3) - */ - protected void initFromFile(ByteSequence bytes, boolean wide) - throws IOException - { - if(wide) { - n = bytes.readUnsignedShort(); - length = 4; - } else if(((opcode >= Constants.ILOAD) && - (opcode <= Constants.ALOAD)) || - ((opcode >= Constants.ISTORE) && - (opcode <= Constants.ASTORE))) { - n = bytes.readUnsignedByte(); - length = 2; - } else if(opcode <= Constants.ALOAD_3) { // compact load instruction such as ILOAD_2 - n = (opcode - Constants.ILOAD_0) % 4; - length = 1; - } else { // Assert ISTORE_0 <= tag <= ASTORE_3 - n = (opcode - Constants.ISTORE_0) % 4; - length = 1; - } - } - - /** - * @return local variable index referred by this instruction. - */ - public final int getIndex() { return n; } - - /** - * Set the local variable index - */ - public void setIndex(int n) { - if((n < 0) || (n > Constants.MAX_SHORT)) - throw new ClassGenException("Illegal value: " + n); - - this.n = n; - - if(n >= 0 && n <= 3) { // Use more compact instruction xLOAD_n - opcode = (short)(c_tag + n); - length = 1; - } else { - opcode = canon_tag; - - if(wide()) // Need WIDE prefix ? - length = 4; - else - length = 2; - } - } - - /** @return canonical tag for instruction, e.g., ALOAD for ALOAD_0 - */ - public short getCanonicalTag() { - return canon_tag; - } - - /** - * Returns the type associated with the instruction - - * in case of ALOAD or ASTORE Type.OBJECT is returned. - * This is just a bit incorrect, because ALOAD and ASTORE - * may work on every ReferenceType (including Type.NULL) and - * ASTORE may even work on a ReturnaddressType . - * @return type associated with the instruction - */ - public Type getType(ConstantPoolGen cp) { - switch(canon_tag) { - case Constants.ILOAD: case Constants.ISTORE: - return Type.INT; - case Constants.LLOAD: case Constants.LSTORE: - return Type.LONG; - case Constants.DLOAD: case Constants.DSTORE: - return Type.DOUBLE; - case Constants.FLOAD: case Constants.FSTORE: - return Type.FLOAT; - case Constants.ALOAD: case Constants.ASTORE: - return Type.OBJECT; +public abstract class LocalVariableInstruction extends Instruction implements TypedInstruction, + IndexedInstruction { + + private int n = -1; // index of referenced variable + private short c_tag = -1; // compact version, such as ILOAD_0 + private short canon_tag = -1; // canonical tag such as ILOAD + + private boolean wide() { + return n > Const.MAX_BYTE; + } + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. tag and length + * are defined in readInstruction and initFromFile, respectively. + */ + LocalVariableInstruction(final short canon_tag, final short c_tag) { + super(); + this.canon_tag = canon_tag; + this.c_tag = c_tag; + } + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Also used by IINC()! + */ + LocalVariableInstruction() { + } + + /** + * @param opcode Instruction opcode + * @param c_tag Instruction number for compact version, ALOAD_0, e.g. + * @param n local variable index (unsigned short) + */ + protected LocalVariableInstruction(final short opcode, final short c_tag, final int n) { + super(opcode, (short) 2); + this.c_tag = c_tag; + canon_tag = opcode; + setIndex(n); + } + + /** + * Dump instruction as byte code to stream out. + * + * @param out Output stream + */ + @Override + public void dump(final DataOutputStream out) throws IOException { + if (wide()) { + out.writeByte(Const.WIDE); + } + out.writeByte(super.getOpcode()); + if (super.getLength() > 1) { // Otherwise ILOAD_n, instruction, e.g. + if (wide()) { + out.writeShort(n); + } else { + out.writeByte(n); + } + } + } + + /** + * Long output format: + * + * <name of opcode> "["<opcode number>"]" "("<length of + * instruction>")" "<"< local variable index>">" + * + * @param verbose long/short format switch + * @return mnemonic for instruction + */ + @Override + public String toString(final boolean verbose) { + final short _opcode = super.getOpcode(); + if (((_opcode >= Const.ILOAD_0) && (_opcode <= Const.ALOAD_3)) + || ((_opcode >= Const.ISTORE_0) && (_opcode <= Const.ASTORE_3))) { + return super.toString(verbose); + } + return super.toString(verbose) + " " + n; + } + + /** + * Read needed data (e.g. index) from file. + *
+     * (ILOAD <= tag <= ALOAD_3) || (ISTORE <= tag <= ASTORE_3)
+     * 
+ */ + @Override + protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { + if (wide) { + n = bytes.readUnsignedShort(); + super.setLength(4); + } else { + final short _opcode = super.getOpcode(); + if (((_opcode >= Const.ILOAD) && (_opcode <= Const.ALOAD)) + || ((_opcode >= Const.ISTORE) && (_opcode <= Const.ASTORE))) { + n = bytes.readUnsignedByte(); + super.setLength(2); + } else if (_opcode <= Const.ALOAD_3) { // compact load instruction such as ILOAD_2 + n = (_opcode - Const.ILOAD_0) % 4; + super.setLength(1); + } else { // Assert ISTORE_0 <= tag <= ASTORE_3 + n = (_opcode - Const.ISTORE_0) % 4; + super.setLength(1); + } + } + } + + /** + * @return local variable index (n) referred by this instruction. + */ + @Override + public final int getIndex() { + return n; + } + + /** + * Set the local variable index. also updates opcode and length TODO Why? + * + * @see #setIndexOnly(int) + */ + @Override + public void setIndex(final int n) { // TODO could be package-protected? + if ((n < 0) || (n > Const.MAX_SHORT)) { + throw new ClassGenException("Illegal value: " + n); + } + this.n = n; + // Cannot be < 0 as this is checked above + if (n <= 3) { // Use more compact instruction xLOAD_n + super.setOpcode((short) (c_tag + n)); + super.setLength(1); + } else { + super.setOpcode(canon_tag); + if (wide()) { + super.setLength(4); + } else { + super.setLength(2); + } + } + } + + /** + * @return canonical tag for instruction, e.g., ALOAD for ALOAD_0 + */ + public short getCanonicalTag() { + return canon_tag; + } + + /** + * Returns the type associated with the instruction - in case of ALOAD or + * ASTORE Type.OBJECT is returned. This is just a bit incorrect, because + * ALOAD and ASTORE may work on every ReferenceType (including Type.NULL) + * and ASTORE may even work on a ReturnaddressType . + * + * @return type associated with the instruction + */ + @Override + public Type getType(final ConstantPoolGen cp) { + switch (canon_tag) { + case Const.ILOAD: + case Const.ISTORE: + return Type.INT; + case Const.LLOAD: + case Const.LSTORE: + return Type.LONG; + case Const.DLOAD: + case Const.DSTORE: + return Type.DOUBLE; + case Const.FLOAD: + case Const.FSTORE: + return Type.FLOAT; + case Const.ALOAD: + case Const.ASTORE: + return Type.OBJECT; + default: + throw new ClassGenException("Oops: unknown case in switch" + canon_tag); + } + } - default: throw new ClassGenException("Oops: unknown case in switch" + canon_tag); + /** + * Sets the index of the referenced variable (n) only + * + * @since 6.0 + * @see #setIndex(int) + */ + final void setIndexOnly(final int n) { + this.n = n; } - } }