1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.nabla.forward.analysis;
18
19 import java.util.Iterator;
20 import java.util.List;
21
22 import org.apache.commons.nabla.DifferentiationException;
23 import org.apache.commons.nabla.NablaMessages;
24 import org.objectweb.asm.Handle;
25 import org.objectweb.asm.Opcodes;
26 import org.objectweb.asm.Type;
27 import org.objectweb.asm.tree.AbstractInsnNode;
28 import org.objectweb.asm.tree.FieldInsnNode;
29 import org.objectweb.asm.tree.IntInsnNode;
30 import org.objectweb.asm.tree.InvokeDynamicInsnNode;
31 import org.objectweb.asm.tree.LdcInsnNode;
32 import org.objectweb.asm.tree.MethodInsnNode;
33 import org.objectweb.asm.tree.MultiANewArrayInsnNode;
34 import org.objectweb.asm.tree.TypeInsnNode;
35 import org.objectweb.asm.tree.analysis.AnalyzerException;
36 import org.objectweb.asm.tree.analysis.Interpreter;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 public class TrackingInterpreter extends Interpreter<TrackingValue> {
76
77
78
79 public TrackingInterpreter() {
80 super(Opcodes.ASM4);
81 }
82
83
84 @Override
85 public TrackingValue newValue(final Type type) {
86 return (type == null) ? TrackingValue.UNINITIALIZED_VALUE : new TrackingValue(type);
87 }
88
89
90 @Override
91 public TrackingValue newOperation(final AbstractInsnNode insn) throws AnalyzerException {
92 switch (insn.getOpcode()) {
93 case Opcodes.ACONST_NULL:
94 return new TrackingValue(Type.getObjectType("null"), insn);
95 case Opcodes.ICONST_M1:
96 case Opcodes.ICONST_0:
97 case Opcodes.ICONST_1:
98 case Opcodes.ICONST_2:
99 case Opcodes.ICONST_3:
100 case Opcodes.ICONST_4:
101 case Opcodes.ICONST_5:
102 return new TrackingValue(Type.INT_TYPE, insn);
103 case Opcodes.LCONST_0:
104 case Opcodes.LCONST_1:
105 return new TrackingValue(Type.LONG_TYPE, insn);
106 case Opcodes.FCONST_0:
107 case Opcodes.FCONST_1:
108 case Opcodes.FCONST_2:
109 return new TrackingValue(Type.FLOAT_TYPE, insn);
110 case Opcodes.DCONST_0:
111 case Opcodes.DCONST_1:
112 return new TrackingValue(Type.DOUBLE_TYPE, insn);
113 case Opcodes.BIPUSH:
114 case Opcodes.SIPUSH:
115 return new TrackingValue(Type.INT_TYPE, insn);
116 case Opcodes.LDC:
117 final Object cst = ((LdcInsnNode) insn).cst;
118 if (cst instanceof Integer) {
119 return new TrackingValue(Type.INT_TYPE, insn);
120 } else if (cst instanceof Float) {
121 return new TrackingValue(Type.FLOAT_TYPE, insn);
122 } else if (cst instanceof Long) {
123 return new TrackingValue(Type.LONG_TYPE, insn);
124 } else if (cst instanceof Double) {
125 return new TrackingValue(Type.DOUBLE_TYPE, insn);
126 } else if (cst instanceof String) {
127 return new TrackingValue(Type.getType(String.class), insn);
128 } else if (cst instanceof Type) {
129 final int sort = ((Type) cst).getSort();
130 if (sort == Type.OBJECT || sort == Type.ARRAY) {
131 return new TrackingValue(Type.getType(Class.class), insn);
132 } else if (sort == Type.METHOD) {
133 return new TrackingValue(Type.getObjectType("java/lang/invoke/MethodType"), insn);
134 } else {
135 throw DifferentiationException.createIllegalArgumentException(NablaMessages.ILLEGAL_LDC_CONSTANT,
136 cst);
137 }
138 } else if (cst instanceof Handle) {
139 return new TrackingValue(Type.getObjectType("java/lang/invoke/MethodHandle"), insn);
140 } else {
141 throw DifferentiationException.createIllegalArgumentException(NablaMessages.ILLEGAL_LDC_CONSTANT,
142 cst);
143 }
144 case Opcodes.JSR:
145 return new TrackingValue(Type.VOID_TYPE, insn);
146 case Opcodes.GETSTATIC:
147 return new TrackingValue(Type.getType(((FieldInsnNode) insn).desc), insn);
148 case Opcodes.NEW:
149 return new TrackingValue(Type.getObjectType(((TypeInsnNode) insn).desc), insn);
150 default:
151 throw DifferentiationException.createInternalError(null);
152 }
153 }
154
155
156 public TrackingValue unaryOperation(final AbstractInsnNode insn, final TrackingValue value)
157 throws AnalyzerException {
158 ((TrackingValue) value).addConsumer(insn);
159 switch (insn.getOpcode()) {
160 case Opcodes.INEG:
161 case Opcodes.IINC:
162 case Opcodes.L2I:
163 case Opcodes.F2I:
164 case Opcodes.D2I:
165 case Opcodes.I2B:
166 case Opcodes.I2C:
167 case Opcodes.I2S:
168 return new TrackingValue(Type.INT_TYPE, insn);
169 case Opcodes.FNEG:
170 case Opcodes.I2F:
171 case Opcodes.L2F:
172 case Opcodes.D2F:
173 return new TrackingValue(Type.FLOAT_TYPE, insn);
174 case Opcodes.LNEG:
175 case Opcodes.I2L:
176 case Opcodes.F2L:
177 case Opcodes.D2L:
178 return new TrackingValue(Type.LONG_TYPE, insn);
179 case Opcodes.DNEG:
180 case Opcodes.I2D:
181 case Opcodes.L2D:
182 case Opcodes.F2D:
183 return new TrackingValue(Type.DOUBLE_TYPE, insn);
184 case Opcodes.IFEQ:
185 case Opcodes.IFNE:
186 case Opcodes.IFLT:
187 case Opcodes.IFGE:
188 case Opcodes.IFGT:
189 case Opcodes.IFLE:
190 case Opcodes.TABLESWITCH:
191 case Opcodes.LOOKUPSWITCH:
192 case Opcodes.IRETURN:
193 case Opcodes.LRETURN:
194 case Opcodes.FRETURN:
195 case Opcodes.DRETURN:
196 case Opcodes.ARETURN:
197 case Opcodes.PUTSTATIC:
198 return null;
199 case Opcodes.GETFIELD:
200 return new TrackingValue(Type.getType(((FieldInsnNode) insn).desc), insn);
201 case Opcodes.NEWARRAY:
202 switch (((IntInsnNode) insn).operand) {
203 case Opcodes.T_BOOLEAN:
204 return new TrackingValue(Type.getType("[Z"), insn);
205 case Opcodes.T_CHAR:
206 return new TrackingValue(Type.getType("[C"), insn);
207 case Opcodes.T_BYTE:
208 return new TrackingValue(Type.getType("[B"), insn);
209 case Opcodes.T_SHORT:
210 return new TrackingValue(Type.getType("[S"), insn);
211 case Opcodes.T_INT:
212 return new TrackingValue(Type.getType("[I"), insn);
213 case Opcodes.T_FLOAT:
214 return new TrackingValue(Type.getType("[F"), insn);
215 case Opcodes.T_DOUBLE:
216 return new TrackingValue(Type.getType("[D"), insn);
217 case Opcodes.T_LONG:
218 return new TrackingValue(Type.getType("[J"), insn);
219 default:
220 throw new AnalyzerException(insn, "Invalid array type");
221 }
222 case Opcodes.ANEWARRAY: {
223 final String desc = ((TypeInsnNode) insn).desc;
224 return new TrackingValue(Type.getType("[" + Type.getObjectType(desc)), insn);
225 }
226 case Opcodes.ARRAYLENGTH:
227 return new TrackingValue(Type.INT_TYPE, insn);
228 case Opcodes.ATHROW:
229 return null;
230 case Opcodes.CHECKCAST: {
231 final String desc = ((TypeInsnNode) insn).desc;
232 return new TrackingValue(Type.getObjectType(desc), insn);
233 }
234 case Opcodes.INSTANCEOF:
235 return new TrackingValue(Type.INT_TYPE, insn);
236 case Opcodes.MONITORENTER:
237 case Opcodes.MONITOREXIT:
238 case Opcodes.IFNULL:
239 case Opcodes.IFNONNULL:
240 return null;
241 default:
242 throw DifferentiationException.createInternalError(null);
243 }
244 }
245
246
247 public TrackingValue binaryOperation(final AbstractInsnNode insn,
248 final TrackingValue value1, final TrackingValue value2)
249 throws AnalyzerException {
250 ((TrackingValue) value1).addConsumer(insn);
251 ((TrackingValue) value2).addConsumer(insn);
252 switch (insn.getOpcode()) {
253 case Opcodes.IALOAD:
254 case Opcodes.BALOAD:
255 case Opcodes.CALOAD:
256 case Opcodes.SALOAD:
257 case Opcodes.IADD:
258 case Opcodes.ISUB:
259 case Opcodes.IMUL:
260 case Opcodes.IDIV:
261 case Opcodes.IREM:
262 case Opcodes.ISHL:
263 case Opcodes.ISHR:
264 case Opcodes.IUSHR:
265 case Opcodes.IAND:
266 case Opcodes.IOR:
267 case Opcodes.IXOR:
268 return new TrackingValue(Type.INT_TYPE, insn);
269 case Opcodes.FALOAD:
270 case Opcodes.FADD:
271 case Opcodes.FSUB:
272 case Opcodes.FMUL:
273 case Opcodes.FDIV:
274 case Opcodes.FREM:
275 return new TrackingValue(Type.FLOAT_TYPE, insn);
276 case Opcodes.LALOAD:
277 case Opcodes.LADD:
278 case Opcodes.LSUB:
279 case Opcodes.LMUL:
280 case Opcodes.LDIV:
281 case Opcodes.LREM:
282 case Opcodes.LSHL:
283 case Opcodes.LSHR:
284 case Opcodes.LUSHR:
285 case Opcodes.LAND:
286 case Opcodes.LOR:
287 case Opcodes.LXOR:
288 return new TrackingValue(Type.LONG_TYPE, insn);
289 case Opcodes.DALOAD:
290 case Opcodes.DADD:
291 case Opcodes.DSUB:
292 case Opcodes.DMUL:
293 case Opcodes.DDIV:
294 case Opcodes.DREM:
295 return new TrackingValue(Type.DOUBLE_TYPE, insn);
296 case Opcodes.AALOAD:
297 return new TrackingValue(Type.getType(Object.class), insn);
298 case Opcodes.LCMP:
299 case Opcodes.FCMPL:
300 case Opcodes.FCMPG:
301 case Opcodes.DCMPL:
302 case Opcodes.DCMPG:
303 return new TrackingValue(Type.INT_TYPE, insn);
304 case Opcodes.IF_ICMPEQ:
305 case Opcodes.IF_ICMPNE:
306 case Opcodes.IF_ICMPLT:
307 case Opcodes.IF_ICMPGE:
308 case Opcodes.IF_ICMPGT:
309 case Opcodes.IF_ICMPLE:
310 case Opcodes.IF_ACMPEQ:
311 case Opcodes.IF_ACMPNE:
312 case Opcodes.PUTFIELD:
313 return null;
314 default:
315 throw DifferentiationException.createInternalError(null);
316 }
317 }
318
319
320 public TrackingValue ternaryOperation(final AbstractInsnNode insn,
321 final TrackingValue value1, final TrackingValue value2,
322 final TrackingValue value3)
323 throws AnalyzerException {
324 value1.addConsumer(insn);
325 value2.addConsumer(insn);
326 value3.addConsumer(insn);
327 return new TrackingValue(null, insn);
328 }
329
330
331 public TrackingValue naryOperation(final AbstractInsnNode insn, final List<? extends TrackingValue> values)
332 throws AnalyzerException {
333 for (final Iterator<?> iterator = values.iterator(); iterator.hasNext();) {
334 ((TrackingValue) iterator.next()).addConsumer(insn);
335 }
336 final int opcode = insn.getOpcode();
337 if (opcode == Opcodes.MULTIANEWARRAY) {
338 return new TrackingValue(Type.getType(((MultiANewArrayInsnNode) insn).desc), insn);
339 } else if (opcode == Opcodes.INVOKEDYNAMIC) {
340 return new TrackingValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc), insn);
341 } else {
342 return new TrackingValue(Type.getReturnType(((MethodInsnNode) insn).desc), insn);
343 }
344 }
345
346
347 public TrackingValue copyOperation(final AbstractInsnNode insn, final TrackingValue value)
348 throws AnalyzerException {
349
350
351 value.addConsumer(insn);
352 value.addProducer(insn);
353 return value;
354 }
355
356
357 public TrackingValue merge(final TrackingValue v, final TrackingValue w) {
358 TrackingValue.merge(v, w);
359 return v;
360 }
361
362
363 public void returnOperation(final AbstractInsnNode insn,
364 final TrackingValue value, final TrackingValue expected) {
365
366 }
367
368 }