Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/techtrader/modules/tools/bytecode/JumpInstruction.java


1   package com.techtrader.modules.tools.bytecode;
2   
3   
4   import java.util.List;
5   import java.util.Iterator;
6   import java.io.IOException;
7   import java.io.DataInput;
8   import java.io.DataOutput;
9   
10  import com.techtrader.modules.tools.bytecode.visitor.BCVisitor;
11  
12  
13  /**
14   *  Represents an IF, GOTO, JSR, or similar instruction that specifies as
15   *  its argument a position in the code block to jump to.
16   *
17   *  @author    Abe White
18   */
19  public class JumpInstruction
20    extends Instruction
21    implements InstructionPtr
22  {
23    protected int       _offset = 0;
24    protected Instruction  _target = null;
25  
26  
27    protected JumpInstruction (Code owner, int opcode)
28    {
29      super (owner);
30      _opcode = opcode;
31    }
32  
33  
34    /**
35     *  Set the byte offset for the jump instruction.
36     */
37    public void setOffset (int offset)
38    {
39      _offset = offset;
40      _target = null;
41    }
42  
43  
44    /**
45     *  Get the byte offset for the jump instruction.
46     */
47    public int getOffset ()
48    {
49      if (_target != null)
50        return _target.getByteIndex () - getByteIndex ();
51  
52      return _offset;
53    }
54  
55  
56    /**
57      *  Set the instruction to jump to; the instruction must already be
58     *  added to the code block.  WARNING: if this instruction is later
59     *  deleted from the code block, the results are undefined.
60      *  
61     *  @return    this Instruction, for method chaining
62     */
63    public JumpInstruction setTarget (Instruction instruction)
64    {
65      _target = instruction;
66      return this;
67    }
68  
69  
70    /**
71      *  Get the current target instruction to jump to, if it has been set.
72     *  WARNING: if this instruction is later
73     *  deleted from the code block, the results are undefined.
74     */
75    public Instruction getTarget ()
76    {
77      return _target;
78    }  
79  
80  
81    public void setMarkers (List instructions)
82    {
83      int jumpByteIndex = getByteIndex () + _offset;
84  
85      Instruction ins;
86      for (Iterator i = instructions.iterator (); i.hasNext ();)
87      {
88        ins = (Instruction) i.next ();
89  
90        if (ins.getByteIndex () == jumpByteIndex)
91        {
92          setTarget (ins);
93          break;
94        }
95      }
96    }
97  
98  
99    /**
100     *  JumpInstructions are equal if they represent the same operation and 
101    *  the Instruction they jump to is the
102    *  same, or if the jump Instruction of either is unset.
103    */
104   public boolean equals (Object other)
105   {
106     if (this == other)
107       return true;
108     if (!(other instanceof JumpInstruction))
109       return false;
110     if (!super.equals (other))
111       return false;
112 
113     Instruction target = ((JumpInstruction) other).getTarget ();
114     return (target == null || _target == null || target == _target);
115   }
116 
117 
118   public int getLength ()
119   {
120     switch (_opcode)
121     {
122     case GOTO_W:
123     case JSR_W:
124       return super.getLength () + 4;
125     default:
126       return super.getLength () + 2;
127     }
128   }
129 
130 
131   public int getStackChange ()
132   {
133     switch (_opcode)
134     {
135     case IF_ACMPEQ:
136     case IF_ACMPNE:
137     case IF_ICMPEQ:
138     case IF_ICMPNE:
139     case IF_ICMPLT:
140     case IF_ICMPGT:
141     case IF_ICMPLE:
142     case IF_ICMPGE:
143       return -2;
144 
145     case IF_EQ:
146     case IF_NE:
147     case IF_LT:
148     case IF_GT:
149     case IF_LE:
150     case IF_GE:
151     case IF_NULL:
152     case IF_NONNULL:
153       return -1;
154 
155     case JSR:
156       return 1;
157 
158     default:
159       return 0;
160     }
161   }
162 
163 
164   protected void copy (Instruction orig)
165   {
166     super.copy (orig);
167     setOffset (((JumpInstruction) orig).getOffset ());
168   }
169 
170 
171   protected void readData (DataInput in)
172     throws IOException
173   {
174     switch (_opcode)
175     {
176     case GOTO_W:
177     case JSR_W:
178       _offset = in.readInt ();
179       break;
180     default:
181       _offset = in.readShort ();
182     }
183   }
184 
185 
186   protected void writeData (DataOutput out)
187     throws IOException
188   {
189     switch (_opcode)
190     {
191     case GOTO_W:
192     case JSR_W:
193       out.writeInt (getOffset ());
194       break;
195     default:
196       out.writeShort (getOffset ());
197     }
198   }
199 
200 
201   public void acceptVisit (BCVisitor visit)
202   {
203     visit.enterJumpInstruction (this);
204     visit.exitJumpInstruction (this);
205   }
206 }