1
2
3
4 package org.softevo.jdynpur.runtime;
5
6 import org.objectweb.asm.MethodAdapter;
7 import org.objectweb.asm.MethodVisitor;
8 import org.objectweb.asm.Opcodes;
9 import org.softevo.util.ObjectIdMapper;
10 import org.softevo.util.asm.FieldIdentifier;
11
12 public class FieldWriteTracingVisitor extends MethodAdapter implements Opcodes {
13
14 protected boolean isConstructor = false;
15
16 protected boolean isAfterConstructorCall = false;
17
18 protected String className = null;
19
20 protected String superClassName = null;
21
22 private ObjectIdMapper<FieldIdentifier> fieldIdentifierMap;
23
24 public FieldWriteTracingVisitor(MethodVisitor mv, String methodName,
25 String className, String superClassName,
26 ObjectIdMapper<FieldIdentifier> fieldIdentifierMap) {
27 super(mv);
28 isConstructor = methodName.equals("<init>");
29 this.className = className;
30 this.superClassName = superClassName;
31 this.fieldIdentifierMap = fieldIdentifierMap;
32 }
33
34 @Override
35 public void visitMethodInsn(int opCode, String owner, String name, String desc) {
36 if (isConstructor && (opCode == INVOKESPECIAL) && name.equals("<init>")
37 && (owner.equals(className) || owner.equals(superClassName))) {
38 isAfterConstructorCall = true;
39 }
40 super.visitMethodInsn(opCode, owner, name, desc);
41 }
42
43 @Override
44 public void visitFieldInsn(int opCode, String className, String fieldName, String typeDesc) {
45 if (!isConstructor || isAfterConstructorCall) {
46 FieldIdentifier identifier = new FieldIdentifier(className, fieldName, typeDesc);
47 int id;
48 if (!fieldIdentifierMap.contains(identifier)) {
49 id = fieldIdentifierMap.add(identifier);
50 } else {
51 id = fieldIdentifierMap.getId(identifier);
52 }
53
54 if ((opCode == PUTFIELD) || (opCode == PUTSTATIC)) {
55 if (opCode == PUTFIELD) {
56
57 if (!identifier.isComplexType()) {
58 if (typeDesc.equals("D") || typeDesc.equals("J")) {
59 super.visitInsn(DUP2_X1);
60 super.visitInsn(POP2);
61 super.visitInsn(DUP_X2);
62 } else {
63 super.visitInsn(SWAP);
64 super.visitInsn(DUP_X1);
65 }
66 super.visitMethodInsn(INVOKESTATIC, OnTheFlyInstrumenter.TRACECLASSNAME, "fieldWritten",
67 "(Ljava/lang/Object;)V");
68 } else {
69 super.visitInsn(DUP2);
70 super.visitLdcInsn(new Integer(id));
71 super.visitMethodInsn(INVOKESTATIC, OnTheFlyInstrumenter.TRACECLASSNAME, "objectFieldWritten",
72 "(Ljava/lang/Object;Ljava/lang/Object;I)V");
73 }
74 } else {
75
76 super.visitMethodInsn(INVOKESTATIC, OnTheFlyInstrumenter.TRACECLASSNAME, "staticFieldWritten", "()V");
77 }
78
79 super.visitFieldInsn(opCode, className, fieldName, typeDesc);
80 } else {
81 super.visitFieldInsn(opCode, className, fieldName, typeDesc);
82 }
83 } else {
84 super.visitFieldInsn(opCode, className, fieldName, typeDesc);
85 }
86 }
87
88
89 }