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 }