speedup method bpts calculation - cache classesByName

This commit is contained in:
Egor.Ushakov
2016-11-08 18:04:15 +03:00
parent 65b392d5dc
commit 7af95c47ff
4 changed files with 17 additions and 8 deletions
@@ -99,7 +99,7 @@ public class JumpToObjectAction extends DebuggerAction{
if (type instanceof ClassType) {
ClassType clsType = (ClassType)type;
Method lambdaMethod = MethodBytecodeUtil.getLambdaMethod(clsType);
Method lambdaMethod = MethodBytecodeUtil.getLambdaMethod(clsType, debugProcess.getVirtualMachineProxy());
Location location = lambdaMethod != null ? ContainerUtil.getFirstItem(DebuggerUtilsEx.allLineLocations(lambdaMethod)) : null;
if (location == null) {
@@ -16,6 +16,7 @@
package com.intellij.debugger.jdi;
import com.intellij.Patches;
import com.intellij.debugger.engine.jdi.VirtualMachineProxy;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.openapi.util.Ref;
import com.intellij.util.ReflectionUtil;
@@ -232,7 +233,7 @@ public class MethodBytecodeUtil {
}
@Nullable
public static Method getLambdaMethod(ReferenceType clsType) {
public static Method getLambdaMethod(ReferenceType clsType, VirtualMachineProxy vm) {
Ref<Method> methodRef = Ref.create();
if (DebuggerUtilsEx.isLambdaClassName(clsType.name())) {
List<Method> applicableMethods = ContainerUtil.filter(clsType.methods(), m -> m.isPublic() && !m.isBridge());
@@ -240,7 +241,7 @@ public class MethodBytecodeUtil {
visit(applicableMethods.get(0), new MethodVisitor(Opcodes.API_VERSION) {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
ReferenceType cls = ContainerUtil.getFirstItem(clsType.virtualMachine().classesByName(owner));
ReferenceType cls = ContainerUtil.getFirstItem(vm.classesByName(owner));
if (cls != null) {
cls.methodsByName(name, desc).stream().findFirst().ifPresent(methodRef::set);
}
@@ -252,7 +253,7 @@ public class MethodBytecodeUtil {
}
@Nullable
public static Method getBridgeTargetMethod(Method method) {
public static Method getBridgeTargetMethod(Method method, VirtualMachineProxy vm) {
Ref<Method> methodRef = Ref.create();
if (method.isBridge()) {
visit(method, new MethodVisitor(Opcodes.API_VERSION) {
@@ -264,7 +265,7 @@ public class MethodBytecodeUtil {
cls = declaringType;
}
else if (!"java/lang/AbstractMethodError".equals(owner)) {
cls = ContainerUtil.getFirstItem(method.virtualMachine().classesByName(owner));
cls = ContainerUtil.getFirstItem(vm.classesByName(owner));
}
if (cls != null) {
StreamEx.of(cls.methodsByName(name, desc)).findFirst().ifPresent(methodRef::set);
@@ -30,6 +30,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.ThreeState;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.MultiMap;
import com.sun.jdi.*;
import com.sun.jdi.event.EventQueue;
import com.sun.jdi.request.EventRequestManager;
@@ -56,6 +57,7 @@ public class VirtualMachineProxyImpl implements JdiTimer, VirtualMachineProxy {
private final Map<ThreadGroupReference, ThreadGroupReferenceProxyImpl> myThreadGroups = new HashMap<>();
private boolean myAllThreadsDirty = true;
private List<ReferenceType> myAllClasses;
private MultiMap<String, ReferenceType> myAllClassesByName;
private Map<ReferenceType, List<ReferenceType>> myNestedClassesCache = new HashMap<>();
public final Throwable mySuspendLogger = new Throwable();
@@ -96,7 +98,11 @@ public class VirtualMachineProxyImpl implements JdiTimer, VirtualMachineProxy {
}
public List<ReferenceType> classesByName(String s) {
return myVirtualMachine.classesByName(s);
if (myAllClassesByName == null) {
myAllClassesByName = new MultiMap<>();
allClasses().forEach(t -> myAllClassesByName.putValue(t.name(), t));
}
return (List<ReferenceType>)myAllClassesByName.get(s);
}
public List<ReferenceType> nestedTypes(ReferenceType refType) {
@@ -641,6 +647,8 @@ public class VirtualMachineProxyImpl implements JdiTimer, VirtualMachineProxy {
LOG.debug("VM cleared");
myAllClasses = null;
myAllClassesByName = null;
if (!myNestedClassesCache.isEmpty()) {
myNestedClassesCache = new HashMap<>(myNestedClassesCache.size());
}
@@ -166,7 +166,7 @@ public class MethodBreakpoint extends BreakpointWithHighlighter<JavaMethodBreakp
return;
}
try {
Method method = MethodBytecodeUtil.getLambdaMethod(classType);
Method method = MethodBytecodeUtil.getLambdaMethod(classType, debugProcess.getVirtualMachineProxy());
if (method == null) {
for (Method m : classType.methods()) {
if (!base && m.isAbstract()) {
@@ -186,7 +186,7 @@ public class MethodBreakpoint extends BreakpointWithHighlighter<JavaMethodBreakp
});
return;
}
Method target = MethodBytecodeUtil.getBridgeTargetMethod(method);
Method target = MethodBytecodeUtil.getBridgeTargetMethod(method, debugProcess.getVirtualMachineProxy());
if (target != null && !DebuggerUtilsEx.allLineLocations(target).isEmpty()) {
method = target;
}