1
2
3
4 package org.softevo.jdynpur.runtime;
5
6 import org.objectweb.asm.Label;
7 import org.objectweb.asm.MethodAdapter;
8 import org.objectweb.asm.MethodVisitor;
9 import org.objectweb.asm.Opcodes;
10
11 public class ObjectCreationTracingVisitor extends MethodAdapter implements Opcodes {
12
13 /**
14 * The class is in this state if, during bytecode processing, we did not
15 * recently encounter a new instruction.
16 */
17 public static final int ST_DEFAULT = 0;
18
19 /**
20 * Last visited instruction was a new instruction.
21 */
22 public static final int ST_NEW = 1;
23
24 /**
25 * Last but one instruction was new, last instruction <code>dup_x1</code>.
26 */
27 public static final int ST_DUPX1 = 2;
28
29 /**
30 * Current state of the visitor.
31 */
32 private int state = ST_DEFAULT;
33
34 protected int newInstructionCounter = 0;
35
36 public ObjectCreationTracingVisitor(MethodVisitor visitor) {
37 super(visitor);
38 }
39
40 @Override
41 public void visitFieldInsn(int arg0, String arg1, String arg2, String arg3) {
42 handleStateReset();
43 super.visitFieldInsn(arg0, arg1, arg2, arg3);
44 }
45
46 @Override
47 public void visitIincInsn(int arg0, int arg1) {
48 handleStateReset();
49 super.visitIincInsn(arg0, arg1);
50 }
51
52 @Override
53 public void visitInsn(int opCode) {
54 if (state == ST_NEW) {
55 if (opCode == DUP_X1) {
56 state = ST_DUPX1;
57 } else {
58 handleStateReset();
59 super.visitInsn(opCode);
60 }
61 } else if (state == ST_DUPX1) {
62 if (opCode == SWAP) {
63 super.visitInsn(DUP_X1);
64 super.visitInsn(DUP_X1);
65 super.visitInsn(SWAP);
66 state = ST_DEFAULT;
67 } else {
68 handleStateReset();
69 super.visitInsn(opCode);
70 }
71 } else {
72
73 super.visitInsn(opCode);
74 }
75 }
76
77 @Override
78 public void visitIntInsn(int arg0, int arg1) {
79 handleStateReset();
80 super.visitIntInsn(arg0, arg1);
81 }
82
83 @Override
84 public void visitJumpInsn(int arg0, Label arg1) {
85 handleStateReset();
86 super.visitJumpInsn(arg0, arg1);
87 }
88
89 @Override
90 public void visitLdcInsn(Object arg0) {
91 handleStateReset();
92 super.visitLdcInsn(arg0);
93 }
94
95 @Override
96 public void visitLookupSwitchInsn(Label arg0, int[] arg1, Label[] arg2) {
97 handleStateReset();
98 super.visitLookupSwitchInsn(arg0, arg1, arg2);
99 }
100
101 @Override
102 public void visitMethodInsn(int access, String className, String methodName, String desc) {
103 handleStateReset();
104 super.visitMethodInsn(access, className, methodName, desc);
105 if (methodName.equals("<init>")) {
106 if (newInstructionCounter > 0) {
107 newInstructionCounter--;
108 super.visitMethodInsn(INVOKESTATIC, OnTheFlyInstrumenter.TRACECLASSNAME, "objectCreated",
109 "(Ljava/lang/Object;)V");
110 }
111 }
112 }
113
114 @Override
115 public void visitMultiANewArrayInsn(String arg0, int arg1) {
116 handleStateReset();
117 super.visitMultiANewArrayInsn(arg0, arg1);
118 }
119
120 @Override
121 public void visitTableSwitchInsn(int arg0, int arg1, Label arg2, Label[] arg3) {
122 handleStateReset();
123 super.visitTableSwitchInsn(arg0, arg1, arg2, arg3);
124 }
125
126 @Override
127 public void visitTypeInsn(int opCode, String typeDesc) {
128 if (opCode == NEW) {
129 newInstructionCounter++;
130 handleStateReset();
131 state = ST_NEW;
132 } else {
133 handleStateReset();
134 }
135 super.visitTypeInsn(opCode, typeDesc);
136 }
137
138 @Override
139 public void visitVarInsn(int arg0, int arg1) {
140 handleStateReset();
141 super.visitVarInsn(arg0, arg1);
142 }
143
144 protected void handleStateReset() {
145 if (state == ST_NEW) {
146 super.visitInsn(DUP);
147 } else if (state == ST_DUPX1) {
148 super.visitInsn(DUP);
149 super.visitInsn(DUP_X1);
150 }
151 state = ST_DEFAULT;
152 }
153
154 protected void superVisitMethodInsn(int access, String className, String methodName, String desc) {
155 super.visitMethodInsn(access, className, methodName, desc);
156 }
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171 }