View Javadoc

1   package serp.bytecode;
2   
3   import java.io.*;
4   import java.util.*;
5   
6   import serp.bytecode.lowlevel.*;
7   import serp.bytecode.visitor.*;
8   
9   /***
10   * An opcode in a method of a class.
11   *
12   * @author Abe White
13   */
14  public class Instruction extends CodeEntry implements BCEntity, VisitAcceptor {
15      private Code _owner = null;
16      private int _opcode = Constants.NOP;
17  
18      Instruction(Code owner) {
19          _owner = owner;
20      }
21  
22      Instruction(Code owner, int opcode) {
23          _owner = owner;
24          _opcode = opcode;
25      }
26  
27      /***
28       * Return the code block that owns this instruction.
29       */
30      public Code getCode() {
31          return _owner;
32      }
33  
34      /***
35       * Return the name of this instruction.
36       */
37      public String getName() {
38          return Constants.OPCODE_NAMES[_opcode];
39      }
40  
41      /***
42       * Return the opcode this instruction represents.
43       */
44      public int getOpcode() {
45          return _opcode;
46      }
47  
48      /***
49       * Set the opcode this instruction represents. For internal use only.
50       *
51       * @return this instruction, for method chaining
52       */
53      Instruction setOpcode(int opcode) {
54          _opcode = opcode;
55          return this;
56      }
57  
58      /***
59       * Return the index in the method code byte block at which this opcode
60       * starts. Note that this information may be out of date if the code
61       * block has been modified since last read/written.
62       */
63      public int getByteIndex() {
64          if (_owner != null)
65              return _owner.getByteIndex(this);
66          return 0;
67      }
68  
69      /***
70       * Notification that a change has been made to this instruction that
71       * alters the structure of the code block, invalidating byte indexes.
72       */
73      void invalidateByteIndexes() {
74          if (_owner != null)
75              _owner.invalidateByteIndexes();
76      }
77  
78      /***
79       * Return the line number of this instruction, or null if none. This
80       * method is subject to the validity constraints of {@link #getByteIndex}.
81       *
82       * @see LineNumberTable#getLineNumber(Instruction)
83       */
84      public LineNumber getLineNumber() {
85          LineNumberTable table = _owner.getLineNumberTable(false);
86          if (table == null)
87              return null;
88          return table.getLineNumber(this);
89      }
90  
91      /***
92       * Return the length in bytes of this opcode, including all arguments.
93       * For many opcodes this method relies on an up-to-date byte index.
94       */
95      int getLength() {
96          return 1;
97      }
98  
99      /***
100      * Return the logical number of stack positions changed by this
101      * instruction. In other words, ignore weirdness with longs and doubles
102      * taking two stack positions.
103      */
104     public int getLogicalStackChange() {
105         return getStackChange();
106     }
107 
108     /***
109      * Return the number of stack positions this instruction pushes
110      * or pops during its execution.
111      *
112      * @return 0 if the stack is not affected by this instruction, a
113      * positive number if it pushes onto the stack, and a negative
114      * number if it pops from the stack
115      */
116     public int getStackChange() {
117         return 0;
118     }
119 
120     /***
121      * Instructions are equal if their opcodes are the same. Subclasses
122      * should override this method to perform a template comparison:
123      * instructions should compare equal to other instructions of the same
124      * type where the data is either the same or the data is unset.
125      */
126     public boolean equalsInstruction(Instruction other) {
127         if (other == this)
128             return true;
129         return other.getOpcode() == getOpcode();
130     }
131 
132     public Project getProject() {
133         return _owner.getProject();
134     }
135 
136     public ConstantPool getPool() {
137         return _owner.getPool();
138     }
139 
140     public ClassLoader getClassLoader() {
141         return _owner.getClassLoader();
142     }
143 
144     public boolean isValid() {
145         return _owner != null;
146     }
147 
148     public void acceptVisit(BCVisitor visit) {
149     }
150 
151     void invalidate() {
152         _owner = null;
153     }
154 
155     /***
156      * Copy the given instruction data.
157      */
158     void read(Instruction orig) {
159     }
160 
161     /***
162      * Read the arguments for this opcode from the given stream.
163      * This method should be overridden by opcodes that take arguments.
164      */
165     void read(DataInput in) throws IOException {
166     }
167 
168     /***
169      * Write the arguments for this opcode to the given stream.
170      * This method should be overridden by opcodes that take arguments.
171      */
172     void write(DataOutput out) throws IOException {
173     }
174 }