speedup: lazy request this object (it may be not required at all)

This commit is contained in:
Egor.Ushakov
2017-06-20 12:54:57 +03:00
parent eb597e589a
commit 692e9f3477
12 changed files with 128 additions and 43 deletions
@@ -320,7 +320,7 @@ public class JavaStackFrame extends XStackFrame implements JVMStackFrameInfoProv
else {
superBuildVariables(evaluationContext, children);
}
final EvaluationContextImpl evalContextCopy = evaluationContext.createEvaluationContext(evaluationContext.getThisObject());
final EvaluationContextImpl evalContextCopy = evaluationContext.createEvaluationContext(evaluationContext.computeThisObject());
evalContextCopy.setAutoLoadClasses(false);
if (sourcePosition != null) {
@@ -0,0 +1,66 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.debugger.engine.evaluation;
import com.intellij.debugger.EvaluatingComputable;
import com.sun.jdi.Value;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author egor
*/
public class DebuggerComputableValue {
private boolean myComputed;
@Nullable private Value myValue;
@Nullable private EvaluateException myException;
@NotNull private final EvaluatingComputable<Value> myComputable;
public DebuggerComputableValue(@NotNull EvaluatingComputable<Value> computable) {
myComputable = computable;
}
public DebuggerComputableValue(@Nullable Value value) {
myComputed = true;
myValue = value;
myComputable = () -> value;
}
public static DebuggerComputableValue computed(Value value) {
DebuggerComputableValue res = new DebuggerComputableValue(() -> value);
res.myComputed = true;
res.myValue = value;
return res;
}
@Nullable
public Value getValue() throws EvaluateException {
if (!myComputed) {
try {
myValue = myComputable.compute();
}
catch (EvaluateException e) {
myException = e;
}
myComputed = true;
}
if (myException != null) {
throw myException;
}
return myValue;
}
}
@@ -15,46 +15,65 @@
*/
package com.intellij.debugger.engine.evaluation;
import com.intellij.debugger.EvaluatingComputable;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NullableLazyValue;
import com.sun.jdi.ClassLoaderReference;
import com.sun.jdi.Value;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public final class EvaluationContextImpl implements EvaluationContext{
private final NullableLazyValue<Value> myThisObject;
public final class EvaluationContextImpl implements EvaluationContext {
private static final Logger LOG = Logger.getInstance(EvaluationContextImpl.class);
private final DebuggerComputableValue myThisObject;
private final SuspendContextImpl mySuspendContext;
private final StackFrameProxyImpl myFrameProxy;
private boolean myAutoLoadClasses = true;
private ClassLoaderReference myClassLoader;
public EvaluationContextImpl(@NotNull SuspendContextImpl suspendContext, StackFrameProxyImpl frameProxy, @Nullable Value thisObject) {
myThisObject = NullableLazyValue.createValue(() -> thisObject);
private EvaluationContextImpl(@NotNull SuspendContextImpl suspendContext,
@Nullable StackFrameProxyImpl frameProxy,
@NotNull DebuggerComputableValue thisObjectComputableValue) {
myThisObject = thisObjectComputableValue;
myFrameProxy = frameProxy;
mySuspendContext = suspendContext;
}
public EvaluationContextImpl(@NotNull SuspendContextImpl suspendContext, @NotNull StackFrameProxyImpl frameProxy) {
myThisObject = NullableLazyValue.createValue(() -> {
try {
return frameProxy.thisObject();
}
catch (EvaluateException ignore) {
}
return null;
});
myFrameProxy = frameProxy;
mySuspendContext = suspendContext;
public EvaluationContextImpl(@NotNull SuspendContextImpl suspendContext,
@Nullable StackFrameProxyImpl frameProxy,
@NotNull EvaluatingComputable<Value> thisObjectFactory) {
this(suspendContext, frameProxy, new DebuggerComputableValue(thisObjectFactory));
}
public EvaluationContextImpl(@NotNull SuspendContextImpl suspendContext, @Nullable StackFrameProxyImpl frameProxy, @Nullable Value thisObject) {
this(suspendContext, frameProxy, new DebuggerComputableValue(thisObject));
}
public EvaluationContextImpl(@NotNull SuspendContextImpl suspendContext, @Nullable StackFrameProxyImpl frameProxy) {
this(suspendContext, frameProxy, () -> frameProxy != null ? frameProxy.thisObject() : null);
}
@Nullable
@Override
@Deprecated
public Value getThisObject() {
try {
return computeThisObject();
}
catch (EvaluateException e) {
LOG.info(e);
}
return null;
}
@Nullable
@Override
public Value computeThisObject() throws EvaluateException {
return myThisObject.getValue();
}
@@ -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.
@@ -43,7 +43,7 @@ public class ThisEvaluator implements Evaluator {
}
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
Value objRef = context.getThisObject();
Value objRef = context.computeThisObject();
if(myIterations > 0) {
ObjectReference thisRef = (ObjectReference)objRef;
for (int idx = 0; idx < myIterations && thisRef != null; idx++) {
@@ -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.
@@ -33,7 +33,6 @@ import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.Value;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -127,17 +126,8 @@ public final class DebuggerContextImpl implements DebuggerContext {
@Nullable
public EvaluationContextImpl createEvaluationContext() {
DebuggerManagerThreadImpl.assertIsManagerThread();
StackFrameProxyImpl frameProxy = getFrameProxy();
ObjectReference objectReference;
try {
objectReference = frameProxy != null ? frameProxy.thisObject() : null;
}
catch (EvaluateException e) {
LOG.info(e);
objectReference = null;
}
SuspendContextImpl context = getSuspendContext();
return context != null ? new EvaluationContextImpl(context, frameProxy, objectReference) : null;
return context != null ? new EvaluationContextImpl(context, getFrameProxy()) : null;
}
@NotNull
@@ -33,8 +33,8 @@ import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.debugger.requests.ClassPrepareRequestor;
import com.intellij.debugger.requests.Requestor;
import com.intellij.debugger.settings.DebuggerSettings;
import com.intellij.debugger.ui.impl.watch.CompilingEvaluatorImpl;
import com.intellij.debugger.ui.OverheadTimings;
import com.intellij.debugger.ui.impl.watch.CompilingEvaluatorImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.project.Project;
@@ -241,7 +241,7 @@ public abstract class Breakpoint<P extends JavaBreakpointProperties> implements
return false;
}
EvaluationContextImpl evaluationContext = new EvaluationContextImpl(context, frameProxy, getThisObject(context, event));
EvaluationContextImpl evaluationContext = new EvaluationContextImpl(context, frameProxy, () -> getThisObject(context, event));
if (!evaluateCondition(evaluationContext, event)) {
return false;
@@ -325,7 +325,7 @@ public abstract class Breakpoint<P extends JavaBreakpointProperties> implements
debugProcess.getVirtualMachineProxy().resume();
}
if (isInstanceFiltersEnabled()) {
Value value = context.getThisObject();
Value value = context.computeThisObject();
if (value != null) { // non-static
ObjectReference reference = (ObjectReference)value;
if (!hasObjectID(reference.uniqueID())) {
@@ -317,7 +317,7 @@ public class LineBreakpoint<P extends JavaBreakpointProperties> extends Breakpoi
@Override
protected String calculateEventClass(EvaluationContextImpl context, LocatableEvent event) throws EvaluateException {
String className = null;
final ObjectReference thisObject = (ObjectReference)context.getThisObject();
final ObjectReference thisObject = (ObjectReference)context.computeThisObject();
if (thisObject != null) {
className = thisObject.referenceType().name();
}
@@ -72,7 +72,7 @@ public abstract class CompilingEvaluator implements ExpressionEvaluator {
public Value evaluate(final EvaluationContext evaluationContext) throws EvaluateException {
DebugProcess process = evaluationContext.getDebugProcess();
EvaluationContextImpl autoLoadContext = ((EvaluationContextImpl)evaluationContext).createEvaluationContext(evaluationContext.getThisObject());
EvaluationContextImpl autoLoadContext = ((EvaluationContextImpl)evaluationContext).createEvaluationContext(evaluationContext.computeThisObject());
autoLoadContext.setAutoLoadClasses(true);
ClassLoaderReference classLoader = ClassLoadingUtils.getClassLoader(autoLoadContext, process);
@@ -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.
@@ -32,7 +32,7 @@ public class ThisDescriptorImpl extends ValueDescriptorImpl{
}
public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException {
return evaluationContext != null? evaluationContext.getThisObject() : null;
return evaluationContext != null ? evaluationContext.computeThisObject() : null;
}
public String getName() {
@@ -202,7 +202,10 @@ public class ClassRenderer extends NodeRendererImpl{
final StackFrameProxy frameProxy = context.getFrameProxy();
if (frameProxy != null) {
final Location location = frameProxy.location();
if (location != null && objInstance.equals(context.getThisObject()) && Comparing.equal(objInstance.referenceType(), location.declaringType()) && StringUtil.startsWith(field.name(), FieldDescriptorImpl.OUTER_LOCAL_VAR_FIELD_PREFIX)) {
if (location != null &&
objInstance.equals(context.computeThisObject()) &&
Comparing.equal(objInstance.referenceType(), location.declaringType()) &&
StringUtil.startsWith(field.name(), FieldDescriptorImpl.OUTER_LOCAL_VAR_FIELD_PREFIX)) {
return false;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 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.
@@ -39,6 +39,13 @@ public interface EvaluationContext extends StackFrameContext{
@Nullable
ClassLoaderReference getClassLoader() throws EvaluateException;
/**
* @deprecated Use {@link #computeThisObject()} instead, EvaluationContext now may lazily compute this object
*/
@Deprecated
@Nullable
Value getThisObject();
@Nullable
Value computeThisObject() throws EvaluateException;
}
@@ -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.
@@ -142,7 +142,7 @@ trait DebuggerMethods extends CompilerMethods {
EvaluationContextImpl evaluationContext() {
final SuspendContextImpl suspendContext = debugProcess.suspendManager.pausedContext
new EvaluationContextImpl(suspendContext, suspendContext.frameProxy, suspendContext.frameProxy.thisObject())
new EvaluationContextImpl(suspendContext, suspendContext.frameProxy)
}
void eval(final String codeText, String expected) throws EvaluateException {