mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
- do not introduce extra variable at initialization of visited methods array
- share visited methods array for particular class between different classloaders
This commit is contained in:
+7
-20
@@ -17,11 +17,11 @@
|
||||
package org.jetbrains.testme.instrumentation;
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
|
||||
public class Instrumenter extends ClassVisitor {
|
||||
private static final int ADDED_CODE_STACK_SIZE = 6;
|
||||
protected final ClassVisitor myClassVisitor;
|
||||
private final String myClassName;
|
||||
private final String myInternalClassName;
|
||||
@@ -88,7 +88,7 @@ public class Instrumenter extends ClassVisitor {
|
||||
mv = new StaticBlockMethodVisitor(mv);
|
||||
mv.visitCode();
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
mv.visitMaxs(myMethodNames.length + 2, 1);
|
||||
mv.visitMaxs(ADDED_CODE_STACK_SIZE, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
super.visitEnd();
|
||||
@@ -102,12 +102,11 @@ public class Instrumenter extends ClassVisitor {
|
||||
public void visitCode() {
|
||||
super.visitCode();
|
||||
|
||||
visitLdcInsn(myClassName);
|
||||
pushInstruction(this, myMethodNames.length);
|
||||
visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BOOLEAN);
|
||||
visitFieldInsn(Opcodes.PUTSTATIC, myInternalClassName, METHODS_VISITED, METHODS_VISITED_CLASS);
|
||||
|
||||
pushInstruction(this, myMethodNames.length);
|
||||
|
||||
visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String");
|
||||
|
||||
for(int i = 0; i < myMethodNames.length; ++i) {
|
||||
@@ -117,28 +116,16 @@ public class Instrumenter extends ClassVisitor {
|
||||
visitInsn(Opcodes.AASTORE);
|
||||
}
|
||||
|
||||
visitVarInsn(Opcodes.ASTORE, 0);
|
||||
visitMethodInsn(Opcodes.INVOKESTATIC, ProjectData.PROJECT_DATA_OWNER, "trace", "(Ljava/lang/String;[Z[Ljava/lang/String;)[Z", false);
|
||||
visitFieldInsn(Opcodes.PUTSTATIC, myInternalClassName, METHODS_VISITED, METHODS_VISITED_CLASS);
|
||||
|
||||
Label startLabel = new Label();
|
||||
visitLabel(startLabel);
|
||||
|
||||
visitLdcInsn(myClassName);
|
||||
visitFieldInsn(Opcodes.GETSTATIC, myInternalClassName, METHODS_VISITED, METHODS_VISITED_CLASS);
|
||||
visitVarInsn(Opcodes.ALOAD, 0);
|
||||
visitMethodInsn(Opcodes.INVOKESTATIC, ProjectData.PROJECT_DATA_OWNER, "trace", "(Ljava/lang/String;[Z[Ljava/lang/String;)V", false);
|
||||
|
||||
Label endLabel = new Label();
|
||||
visitLabel(endLabel);
|
||||
|
||||
visitLocalVariable("methodNames", "[Ljava/lang/String;", null, startLabel, endLabel, 0);
|
||||
// no return here
|
||||
}
|
||||
|
||||
public void visitMaxs(int maxStack, int maxLocals) {
|
||||
final int ourMaxStack = myMethodNames.length + 2;
|
||||
final int ourMaxLocals = 1;
|
||||
final int ourMaxStack = ADDED_CODE_STACK_SIZE;
|
||||
|
||||
super.visitMaxs(Math.max(ourMaxStack, maxStack), Math.max(ourMaxLocals, maxLocals));
|
||||
super.visitMaxs(Math.max(ourMaxStack, maxStack), maxLocals);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-44
@@ -17,42 +17,31 @@ public class ProjectData {
|
||||
myTraceDir = traceDir;
|
||||
}
|
||||
|
||||
private ConcurrentMap<String, Set<String>> myTrace;
|
||||
private final ConcurrentMap<String, boolean[]> myTrace2 = new ConcurrentHashMap<String, boolean[]>();
|
||||
private final ConcurrentMap<String, String[]> myTrace3 = new ConcurrentHashMap<String, String[]>();
|
||||
|
||||
public static ProjectData getProjectData() {
|
||||
return ourData;
|
||||
}
|
||||
|
||||
public static void trace(String className, String methodSignature) {
|
||||
ourData.traceLines(className, methodSignature);
|
||||
}
|
||||
|
||||
// called from instrumented code during class's static init
|
||||
public static void trace(String className, boolean[] methodFlags, String[] methodNames) {
|
||||
ourData.traceLines(className, methodFlags, methodNames);
|
||||
}
|
||||
|
||||
public void traceLines(String className, String methodSignature) {
|
||||
if (myTrace != null) {
|
||||
Set<String> methods = myTrace.get(className);
|
||||
if (methods == null) {
|
||||
methods = new HashSet<String>();
|
||||
Set<String> previousMethods = myTrace.putIfAbsent(className, methods);
|
||||
if (previousMethods != null) methods = previousMethods;
|
||||
}
|
||||
synchronized (methods) {
|
||||
methods.add(methodSignature);
|
||||
}
|
||||
}
|
||||
public static boolean[] trace(String className, boolean[] methodFlags, String[] methodNames) {
|
||||
return ourData.traceLines(className, methodFlags, methodNames);
|
||||
}
|
||||
|
||||
public synchronized void traceLines(String className, boolean[] methodFlags, String[] methodNames) {
|
||||
private synchronized boolean[] traceLines(String className, boolean[] methodFlags, String[] methodNames) {
|
||||
//System.out.println("Registering " + className);
|
||||
assert methodFlags.length == methodNames.length;
|
||||
myTrace2.put(className, methodFlags);
|
||||
myTrace3.put(className, methodNames);
|
||||
final boolean[] previousMethodFlags = myTrace2.putIfAbsent(className, methodFlags);
|
||||
|
||||
if (previousMethodFlags != null) {
|
||||
assert previousMethodFlags.length == methodFlags.length;
|
||||
final String[] previousMethodNames = myTrace3.get(className);
|
||||
assert previousMethodNames != null && previousMethodNames.length == methodNames.length;
|
||||
} else {
|
||||
myTrace3.put(className, methodNames);
|
||||
}
|
||||
return previousMethodFlags != null ? previousMethodFlags : methodFlags;
|
||||
}
|
||||
|
||||
private static final int STRING_LENGTH_THRESHOLD = 255;
|
||||
@@ -163,22 +152,6 @@ public class ProjectData {
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
myTrace = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void saveOldTrace(DataOutputStream os) throws IOException {
|
||||
os.writeInt(myTrace.size());
|
||||
for (Iterator<String> it = myTrace.keySet().iterator(); it.hasNext();) {
|
||||
final String classData = it.next();
|
||||
os.writeUTF(classData);
|
||||
final Set<String> methods = myTrace.get(classData);
|
||||
os.writeInt(methods.size());
|
||||
for (Iterator<String> iterator = methods.iterator(); iterator.hasNext(); ) {
|
||||
os.writeUTF(iterator.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void testStarted(final String name) {
|
||||
@@ -190,8 +163,4 @@ public class ProjectData {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearOldTrace() {
|
||||
myTrace = new ConcurrentHashMap<String, Set<String>>();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user