capture speedup - cache evaluators

This commit is contained in:
Egor.Ushakov
2017-03-01 20:06:10 +03:00
parent 6ffe60b95e
commit f108afebe1
3 changed files with 44 additions and 14 deletions
@@ -34,6 +34,7 @@ import com.intellij.debugger.settings.DebuggerSettings;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.ui.breakpoints.BreakpointManager;
import com.intellij.debugger.ui.breakpoints.RunToCursorBreakpoint;
import com.intellij.debugger.ui.breakpoints.StackCapturingLineBreakpoint;
import com.intellij.debugger.ui.breakpoints.StepIntoBreakpoint;
import com.intellij.debugger.ui.tree.ValueDescriptor;
import com.intellij.debugger.ui.tree.render.ArrayRenderer;
@@ -1400,6 +1401,11 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
}
}
public void onHotSwapFinished() {
getPositionManager().clearCache();
StackCapturingLineBreakpoint.clearCaches(this);
}
@NotNull
public SuspendManager getSuspendManager() {
return mySuspendManager;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,10 @@ package com.intellij.debugger.impl;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.DebuggerManagerEx;
import com.intellij.debugger.engine.*;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
import com.intellij.debugger.engine.JavaExecutionStack;
import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.debugger.ui.breakpoints.BreakpointManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -165,7 +168,7 @@ class ReloadClassesWorker {
processException(e);
}
debugProcess.getPositionManager().clearCache();
debugProcess.onHotSwapFinished();
DebuggerContextImpl context = myDebuggerSession.getContextManager().getContext();
SuspendContextImpl suspendContext = context.getSuspendContext();
@@ -43,6 +43,7 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.WeakHashMap;
import com.sun.jdi.*;
import com.sun.jdi.event.LocatableEvent;
import one.util.streamex.StreamEx;
@@ -84,8 +85,8 @@ public class StackCapturingLineBreakpoint extends WildcardMethodBreakpoint {
myProperties.myClassPattern = myCapturePoint.myClassName;
myProperties.myMethodName = myCapturePoint.myMethodName;
myCaptureEvaluator = new MyEvaluator(myCapturePoint.myCaptureKeyExpression, false);
myInsertEvaluator = new MyEvaluator(myCapturePoint.myInsertKeyExpression, false);
myCaptureEvaluator = new MyEvaluator(myCapturePoint.myCaptureKeyExpression);
myInsertEvaluator = new MyEvaluator(myCapturePoint.myInsertKeyExpression);
}
@NotNull
@@ -162,6 +163,17 @@ public class StackCapturingLineBreakpoint extends WildcardMethodBreakpoint {
}
}
public static void clearCaches(DebugProcessImpl debugProcess) {
DebuggerManagerThreadImpl.assertIsManagerThread();
List<StackCapturingLineBreakpoint> bpts = debugProcess.getUserData(CAPTURE_BREAKPOINTS);
if (!ContainerUtil.isEmpty(bpts)) {
bpts.forEach(b -> {
b.myCaptureEvaluator.clearCache();
b.myInsertEvaluator.clearCache();
});
}
}
@Override
public void createRequest(DebugProcessImpl debugProcess) {
if (!StringUtil.isEmpty(getClassName())) {
@@ -238,11 +250,11 @@ public class StackCapturingLineBreakpoint extends WildcardMethodBreakpoint {
private static class MyEvaluator {
private final String myExpression;
private final boolean myCached;
private ExpressionEvaluator myEvaluator;
private final boolean myNeedKeepValue;
private final WeakHashMap<Location, ExpressionEvaluator> myEvaluatorCache = new WeakHashMap<>();
public MyEvaluator(String expression, boolean cached) {
public MyEvaluator(String expression) {
myExpression = expression;
int paramId = DecompiledLocalVariable.getParamId(myExpression);
boolean paramEvaluator = paramId > -1;
@@ -258,25 +270,29 @@ public class StackCapturingLineBreakpoint extends WildcardMethodBreakpoint {
return argumentValues.get(paramId);
}
});
cached = true;
}
myNeedKeepValue = !paramEvaluator;
myCached = cached;
}
@Nullable
Value evaluate(final EvaluationContext context) throws EvaluateException {
if ((!myCached || myEvaluator == null) && !StringUtil.isEmpty(myExpression)) {
myEvaluator = ApplicationManager.getApplication().runReadAction(
(ThrowableComputable<ExpressionEvaluator, EvaluateException>)() -> {
ExpressionEvaluator evaluator = myEvaluator;
if (evaluator == null) {
@SuppressWarnings("ConstantConditions")
Location location = context.getFrameProxy().location();
evaluator = myEvaluatorCache.get(location);
if (evaluator == null && !StringUtil.isEmpty(myExpression)) {
evaluator = ApplicationManager.getApplication().runReadAction((ThrowableComputable<ExpressionEvaluator, EvaluateException>)() -> {
SourcePosition sourcePosition = ContextUtil.getSourcePosition(context);
PsiElement contextElement = ContextUtil.getContextElement(sourcePosition);
return EvaluatorBuilderImpl.build(
new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, myExpression), contextElement, sourcePosition, context.getProject());
});
myEvaluatorCache.put(location, evaluator);
}
}
if (myEvaluator != null) {
Value value = myEvaluator.evaluate(context);
if (evaluator != null) {
Value value = evaluator.evaluate(context);
if (myNeedKeepValue) {
DebuggerUtilsEx.keep(value, context);
}
@@ -284,5 +300,10 @@ public class StackCapturingLineBreakpoint extends WildcardMethodBreakpoint {
}
return null;
}
void clearCache() {
DebuggerManagerThreadImpl.assertIsManagerThread();
myEvaluatorCache.clear();
}
}
}