--- old/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java 2017-08-08 16:04:48.716172782 -0700
+++ new/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java 2017-08-08 16:04:48.632168576 -0700
@@ -18,216 +18,246 @@
* 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.DataOutputStream;
+import java.io.IOException;
-import java.io.*;
import com.sun.org.apache.bcel.internal.util.ByteSequence;
/**
- * Abstract super class for branching instructions like GOTO, IFEQ, etc..
- * Branch instructions may have a variable length, namely GOTO, JSR,
- * LOOKUPSWITCH and TABLESWITCH.
+ * Abstract super class for branching instructions like GOTO, IFEQ, etc.. Branch
+ * instructions may have a variable length, namely GOTO, JSR, LOOKUPSWITCH and
+ * TABLESWITCH.
*
* @see InstructionList
- * @author M. Dahm
+ * @version $Id: BranchInstruction.java 1749603 2016-06-21 20:50:19Z ggregory $
*/
public abstract class BranchInstruction extends Instruction implements InstructionTargeter {
- protected int index; // Branch target relative to this instruction
- protected InstructionHandle target; // Target object in instruction list
- protected int position; // Byte code offset
-
- /**
- * Empty constructor needed for the Class.newInstance() statement in
- * Instruction.readInstruction(). Not to be used otherwise.
- */
- BranchInstruction() {}
-
- /** Common super constructor
- * @param opcodee Instruction opcode
- * @param target instruction to branch to
- */
- protected BranchInstruction(short opcode, InstructionHandle target) {
- super(opcode, (short)3);
- setTarget(target);
- }
-
- /**
- * Dump instruction as byte code to stream out.
- * @param out Output stream
- */
- @Override
- public void dump(DataOutputStream out) throws IOException {
- out.writeByte(opcode);
-
- index = getTargetOffset();
-
- if(Math.abs(index) >= 32767) // too large for short
- throw new ClassGenException("Branch target offset too large for short");
-
- out.writeShort(index); // May be negative, i.e., point backwards
- }
-
- /**
- * @param target branch target
- * @return the offset to `target' relative to this instruction
- */
- protected int getTargetOffset(InstructionHandle target) {
- if(target == null)
- throw new ClassGenException("Target of " + super.toString(true) +
- " is invalid null handle");
-
- int t = target.getPosition();
-
- if(t < 0)
- throw new ClassGenException("Invalid branch target position offset for " +
- super.toString(true) + ":" + t + ":" + target);
-
- return t - position;
- }
-
- /**
- * @return the offset to this instruction's target
- */
- protected int getTargetOffset() { return getTargetOffset(target); }
-
- /**
- * Called by InstructionList.setPositions when setting the position for every
- * instruction. In the presence of variable length instructions `setPositions'
- * performs multiple passes over the instruction list to calculate the
- * correct (byte) positions and offsets by calling this function.
- *
- * @param offset additional offset caused by preceding (variable length) instructions
- * @param max_offset the maximum offset that may be caused by these instructions
- * @return additional offset caused by possible change of this instruction's length
- */
- protected int updatePosition(int offset, int max_offset) {
- position += offset;
- return 0;
- }
-
- /**
- * Long output format:
- *
- * <position in byte code>
- * <name of opcode> "["<opcode number>"]"
- * "("<length of instruction>")"
- * "<"<target instruction>">" "@"<branch target offset>
- *
- * @param verbose long/short format switch
- * @return mnemonic for instruction
- */
- @Override
- public String toString(boolean verbose) {
- String s = super.toString(verbose);
- String t = "null";
-
- if(verbose) {
- if(target != null) {
- if(target.getInstruction() == this)
- t = "";
- else if(target.getInstruction() == null)
- t = "";
- else
- t = target.getInstruction().toString(false); // Avoid circles
- }
- } else {
- if(target != null) {
+
+ private int index; // Branch target relative to this instruction
+ private InstructionHandle target; // Target object in instruction list
+ private int position; // Byte code offset
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ BranchInstruction() {
+ }
+
+ /**
+ * Common super constructor
+ *
+ * @param opcode Instruction opcode
+ * @param target instruction to branch to
+ */
+ protected BranchInstruction(final short opcode, final InstructionHandle target) {
+ super(opcode, (short) 3);
+ setTarget(target);
+ }
+
+ /**
+ * Dump instruction as byte code to stream out.
+ *
+ * @param out Output stream
+ */
+ @Override
+ public void dump(final DataOutputStream out) throws IOException {
+ out.writeByte(super.getOpcode());
index = getTargetOffset();
- t = "" + (index + position);
- }
+ if (!isValidShort(index)) {
+ throw new ClassGenException("Branch target offset too large for short: " + index);
+ }
+ out.writeShort(index); // May be negative, i.e., point backwards
+ }
+
+ /**
+ * @param _target branch target
+ * @return the offset to `target' relative to this instruction
+ */
+ protected int getTargetOffset(final InstructionHandle _target) {
+ if (_target == null) {
+ throw new ClassGenException("Target of " + super.toString(true)
+ + " is invalid null handle");
+ }
+ final int t = _target.getPosition();
+ if (t < 0) {
+ throw new ClassGenException("Invalid branch target position offset for "
+ + super.toString(true) + ":" + t + ":" + _target);
+ }
+ return t - position;
+ }
+
+ /**
+ * @return the offset to this instruction's target
+ */
+ protected int getTargetOffset() {
+ return getTargetOffset(target);
+ }
+
+ /**
+ * Called by InstructionList.setPositions when setting the position for
+ * every instruction. In the presence of variable length instructions
+ * `setPositions' performs multiple passes over the instruction list to
+ * calculate the correct (byte) positions and offsets by calling this
+ * function.
+ *
+ * @param offset additional offset caused by preceding (variable length)
+ * instructions
+ * @param max_offset the maximum offset that may be caused by these
+ * instructions
+ * @return additional offset caused by possible change of this instruction's
+ * length
+ */
+ protected int updatePosition(final int offset, final int max_offset) {
+ position += offset;
+ return 0;
+ }
+
+ /**
+ * Long output format:
+ *
+ * <position in byte code> <name of opcode> "["<opcode
+ * number>"]" "("<length of instruction>")" "<"<target
+ * instruction>">" "@"<branch target offset>
+ *
+ * @param verbose long/short format switch
+ * @return mnemonic for instruction
+ */
+ @Override
+ public String toString(final boolean verbose) {
+ final String s = super.toString(verbose);
+ String t = "null";
+ if (verbose) {
+ if (target != null) {
+ if (target.getInstruction() == this) {
+ t = "";
+ } else if (target.getInstruction() == null) {
+ t = "";
+ } else {
+ // I'm more interested in the address of the target then
+ // the instruction located there.
+ //t = target.getInstruction().toString(false); // Avoid circles
+ t = "" + target.getPosition();
+ }
+ }
+ } else {
+ if (target != null) {
+ index = target.getPosition();
+ // index = getTargetOffset(); crashes if positions haven't been set
+ // t = "" + (index + position);
+ t = "" + index;
+ }
+ }
+ return s + " -> " + t;
+ }
+
+ /**
+ * Read needed data (e.g. index) from file. Conversion to a
+ * InstructionHandle is done in InstructionList(byte[]).
+ *
+ * @param bytes input stream
+ * @param wide wide prefix?
+ * @see InstructionList
+ */
+ @Override
+ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
+ super.setLength(3);
+ index = bytes.readShort();
+ }
+
+ /**
+ * @return target offset in byte code
+ */
+ public final int getIndex() {
+ return index;
}
- return s + " -> " + t;
- }
+ /**
+ * @return target of branch instruction
+ */
+ public InstructionHandle getTarget() {
+ return target;
+ }
+
+ /**
+ * Set branch target
+ *
+ * @param target branch target
+ */
+ public void setTarget(final InstructionHandle target) {
+ notifyTarget(this.target, target, this);
+ this.target = target;
+ }
+
+ /**
+ * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen,
+ * LineNumberGen
+ */
+ static void notifyTarget(final InstructionHandle old_ih, final InstructionHandle new_ih,
+ final InstructionTargeter t) {
+ if (old_ih != null) {
+ old_ih.removeTargeter(t);
+ }
+ if (new_ih != null) {
+ new_ih.addTargeter(t);
+ }
+ }
+
+ /**
+ * @param old_ih old target
+ * @param new_ih new target
+ */
+ @Override
+ public void updateTarget(final InstructionHandle old_ih, final InstructionHandle new_ih) {
+ if (target == old_ih) {
+ setTarget(new_ih);
+ } else {
+ throw new ClassGenException("Not targeting " + old_ih + ", but " + target);
+ }
+ }
+
+ /**
+ * @return true, if ih is target of this instruction
+ */
+ @Override
+ public boolean containsTarget(final InstructionHandle ih) {
+ return target == ih;
+ }
+
+ /**
+ * Inform target that it's not targeted anymore.
+ */
+ @Override
+ void dispose() {
+ setTarget(null);
+ index = -1;
+ position = -1;
+ }
+
+ /**
+ * @return the position
+ * @since 6.0
+ */
+ protected int getPosition() {
+ return position;
+ }
+
+ /**
+ * @param position the position to set
+ * @since 6.0
+ */
+ protected void setPosition(final int position) {
+ this.position = position;
+ }
+
+ /**
+ * @param index the index to set
+ * @since 6.0
+ */
+ protected void setIndex(final int index) {
+ this.index = index;
+ }
- /**
- * Read needed data (e.g. index) from file. Conversion to a InstructionHandle
- * is done in InstructionList(byte[]).
- *
- * @param bytes input stream
- * @param wide wide prefix?
- * @see InstructionList
- */
- @Override
- protected void initFromFile(ByteSequence bytes, boolean wide) throws IOException
- {
- length = 3;
- index = bytes.readShort();
- }
-
- /**
- * @return target offset in byte code
- */
- public final int getIndex() { return index; }
-
- /**
- * @return target of branch instruction
- */
- public InstructionHandle getTarget() { return target; }
-
- /**
- * Set branch target
- * @param target branch target
- */
- public final void setTarget(InstructionHandle target) {
- notifyTargetChanging(this.target, this);
- this.target = target;
- notifyTargetChanged(this.target, this);
- }
-
- /**
- * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen.
- * Must be called before the target is actually changed in the
- * InstructionTargeter.
- */
- static void notifyTargetChanging(InstructionHandle old_ih,
- InstructionTargeter t) {
- if(old_ih != null) {
- old_ih.removeTargeter(t);
- }
- }
-
- /**
- * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen.
- * Must be called after the target is actually changed in the
- * InstructionTargeter.
- */
- static void notifyTargetChanged(InstructionHandle new_ih,
- InstructionTargeter t) {
- if(new_ih != null) {
- new_ih.addTargeter(t);
- }
- }
-
- /**
- * @param old_ih old target
- * @param new_ih new target
- */
- @Override
- public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
- if(target == old_ih)
- setTarget(new_ih);
- else
- throw new ClassGenException("Not targeting " + old_ih + ", but " + target);
- }
-
- /**
- * @return true, if ih is target of this instruction
- */
- @Override
- public boolean containsTarget(InstructionHandle ih) {
- return (target == ih);
- }
-
- /**
- * Inform target that it's not targeted anymore.
- */
- @Override
- void dispose() {
- setTarget(null);
- index=-1;
- position=-1;
- }
}