View Javadoc

1   package serp.bytecode;
2   
3   import java.io.*;
4   import java.util.*;
5   
6   import serp.bytecode.visitor.*;
7   
8   /***
9    * An instruction that specifies a position in the code block to jump to.
10   * Examples include <code>go2, jsr</code>, etc.
11   *
12   * @author Abe White
13   */
14  public abstract class JumpInstruction extends Instruction 
15      implements InstructionPtr {
16      private InstructionPtrStrategy _target = new InstructionPtrStrategy(this);
17  
18      JumpInstruction(Code owner, int opcode) {
19          super(owner, opcode);
20      }
21  
22      /***
23       * Get the current target instruction to jump to, if it has been set.
24       */
25      public Instruction getTarget() {
26          return _target.getTargetInstruction();
27      }
28  
29      /***
30       * Set the instruction to jump to; the instruction must already be
31       * added to the code block.
32       *
33       * @return this instruction, for method chaining
34       */
35      public JumpInstruction setTarget(Instruction instruction) {
36          _target.setTargetInstruction(instruction);
37          return this;
38      }
39  
40      /***
41       * JumpInstructions are equal if they represent the same operation and
42       * the instruction they jump to is the
43       * same, or if the jump Instruction of either is unset.
44       */
45      public boolean equalsInstruction(Instruction other) {
46          if (this == other)
47              return true;
48          if (!super.equalsInstruction(other))
49              return false;
50  
51          Instruction target = ((JumpInstruction) other).getTarget();
52          return target == null || getTarget() == null || target == getTarget();
53      }
54  
55      public void updateTargets() {
56          _target.updateTargets();
57      }
58  
59      public void replaceTarget(Instruction oldTarget, Instruction newTarget) {
60          _target.replaceTarget(oldTarget, newTarget);
61      }
62  
63      public void acceptVisit(BCVisitor visit) {
64          visit.enterJumpInstruction(this);
65          visit.exitJumpInstruction(this);
66      }
67  
68      void read(Instruction orig) {
69          super.read(orig);
70          _target.setByteIndex(((JumpInstruction) orig)._target.getByteIndex());
71      }
72  
73      void read(DataInput in) throws IOException {
74          super.read(in);
75          switch (getOpcode()) {
76          case Constants.GOTOW:
77          case Constants.JSRW:
78              _target.setByteIndex(getByteIndex() + in.readInt());
79              break;
80          default:
81              _target.setByteIndex(getByteIndex() + in.readShort());
82          }
83      }
84  
85      void write(DataOutput out) throws IOException {
86          super.write(out);
87          switch (getOpcode()) {
88          case Constants.GOTOW:
89          case Constants.JSRW:
90              out.writeInt(_target.getByteIndex() - getByteIndex());
91              break;
92          default:
93              out.writeShort(_target.getByteIndex() - getByteIndex());
94          }
95      }
96  
97      public void setOffset(int offset) {
98          _target.setByteIndex(getByteIndex() + offset);
99      }
100 
101     public int getOffset() {
102         return _target.getByteIndex() - getByteIndex();
103     }
104 }