1 package serp.bytecode;
2
3 import java.io.*;
4
5 import serp.bytecode.visitor.*;
6
7 /***
8 * An instruction to store a value from a local variable onto the stack.
9 *
10 * @author Abe White
11 */
12 public class StoreInstruction extends LocalVariableInstruction {
13 private static final Class[][] _mappings = new Class[][] {
14 { byte.class, int.class },
15 { boolean.class, int.class },
16 { char.class, int.class },
17 { short.class, int.class },
18 { void.class, int.class },
19 };
20 String _type = null;
21
22 StoreInstruction(Code owner) {
23 super(owner);
24 }
25
26 StoreInstruction(Code owner, int opcode) {
27 super(owner, opcode);
28 }
29
30 int getLength() {
31 switch (getOpcode()) {
32 case Constants.ISTORE:
33 case Constants.LSTORE:
34 case Constants.FSTORE:
35 case Constants.DSTORE:
36 case Constants.ASTORE:
37 return super.getLength() + 1;
38 default:
39 return super.getLength();
40 }
41 }
42
43 public int getLogicalStackChange() {
44 switch (getOpcode()) {
45 case Constants.NOP:
46 return 0;
47 default:
48 return -1;
49 }
50 }
51
52 public int getStackChange() {
53 switch (getOpcode()) {
54 case Constants.LSTORE:
55 case Constants.LSTORE0:
56 case Constants.LSTORE1:
57 case Constants.LSTORE2:
58 case Constants.LSTORE3:
59 case Constants.DSTORE:
60 case Constants.DSTORE0:
61 case Constants.DSTORE1:
62 case Constants.DSTORE2:
63 case Constants.DSTORE3:
64 return -2;
65 case Constants.NOP:
66 return 0;
67 default:
68 return -1;
69 }
70 }
71
72 public String getTypeName() {
73 switch (getOpcode()) {
74 case Constants.ISTORE:
75 case Constants.ISTORE0:
76 case Constants.ISTORE1:
77 case Constants.ISTORE2:
78 case Constants.ISTORE3:
79 return int.class.getName();
80 case Constants.LSTORE:
81 case Constants.LSTORE0:
82 case Constants.LSTORE1:
83 case Constants.LSTORE2:
84 case Constants.LSTORE3:
85 return long.class.getName();
86 case Constants.FSTORE:
87 case Constants.FSTORE0:
88 case Constants.FSTORE1:
89 case Constants.FSTORE2:
90 case Constants.FSTORE3:
91 return float.class.getName();
92 case Constants.DSTORE:
93 case Constants.DSTORE0:
94 case Constants.DSTORE1:
95 case Constants.DSTORE2:
96 case Constants.DSTORE3:
97 return double.class.getName();
98 case Constants.ASTORE:
99 case Constants.ASTORE0:
100 case Constants.ASTORE1:
101 case Constants.ASTORE2:
102 case Constants.ASTORE3:
103 return Object.class.getName();
104 default:
105 return _type;
106 }
107 }
108
109 public TypedInstruction setType(String type) {
110 type = mapType(type, _mappings, true);
111 int local = getLocal();
112 int len = getLength();
113
114
115 if ((type == null) || (local < 0)) {
116 _type = type;
117 setOpcode(Constants.NOP);
118 } else {
119
120 _type = null;
121 switch (type.charAt(0)) {
122 case 'i':
123 setOpcode((local > 3) ? Constants.ISTORE
124 : (Constants.ISTORE0 + local));
125 break;
126 case 'l':
127 setOpcode((local > 3) ? Constants.LSTORE
128 : (Constants.LSTORE0 + local));
129 break;
130 case 'f':
131 setOpcode((local > 3) ? Constants.FSTORE
132 : (Constants.FSTORE0 + local));
133 break;
134 case 'd':
135 setOpcode((local > 3) ? Constants.DSTORE
136 : (Constants.DSTORE0 + local));
137 break;
138 default:
139 setOpcode((local > 3) ? Constants.ASTORE
140 : (Constants.ASTORE0 + local));
141 break;
142 }
143 }
144 if (len != getLength())
145 invalidateByteIndexes();
146 return this;
147 }
148
149 /***
150 * StoreInstructions are equal if the type they reference the same
151 * type and locals index or if either is unset.
152 */
153 public boolean equalsInstruction(Instruction other) {
154 if (other == this)
155 return true;
156 if (!super.equalsInstruction(other))
157 return false;
158
159 String type = getTypeName();
160 String otherType = ((StoreInstruction) other).getTypeName();
161 return type == null || otherType == null || type.equals(otherType);
162 }
163
164 public void acceptVisit(BCVisitor visit) {
165 visit.enterStoreInstruction(this);
166 visit.exitStoreInstruction(this);
167 }
168
169 void read(Instruction orig) {
170 super.read(orig);
171 StoreInstruction ins = (StoreInstruction) orig;
172 _type = ins._type;
173 }
174
175 void read(DataInput in) throws IOException {
176 super.read(in);
177 switch (getOpcode()) {
178 case Constants.ISTORE:
179 case Constants.LSTORE:
180 case Constants.FSTORE:
181 case Constants.DSTORE:
182 case Constants.ASTORE:
183 setLocal(in.readUnsignedByte());
184 break;
185 }
186 }
187
188 void write(DataOutput out) throws IOException {
189 super.write(out);
190 switch (getOpcode()) {
191 case Constants.ISTORE:
192 case Constants.LSTORE:
193 case Constants.FSTORE:
194 case Constants.DSTORE:
195 case Constants.ASTORE:
196 out.writeByte(getLocal());
197 }
198 }
199
200 void calculateOpcode() {
201
202 setType(getTypeName());
203 }
204
205 void calculateLocal() {
206 switch (getOpcode()) {
207 case Constants.ISTORE0:
208 case Constants.LSTORE0:
209 case Constants.FSTORE0:
210 case Constants.DSTORE0:
211 case Constants.ASTORE0:
212 setLocal(0);
213 break;
214 case Constants.ISTORE1:
215 case Constants.LSTORE1:
216 case Constants.FSTORE1:
217 case Constants.DSTORE1:
218 case Constants.ASTORE1:
219 setLocal(1);
220 break;
221 case Constants.ISTORE2:
222 case Constants.LSTORE2:
223 case Constants.FSTORE2:
224 case Constants.DSTORE2:
225 case Constants.ASTORE2:
226 setLocal(2);
227 break;
228 case Constants.ISTORE3:
229 case Constants.LSTORE3:
230 case Constants.FSTORE3:
231 case Constants.DSTORE3:
232 case Constants.ASTORE3:
233 setLocal(3);
234 break;
235 }
236 }
237 }