do not invoke methods for instanceof evaluation

This commit is contained in:
Egor Ushakov
2018-11-06 19:39:04 +03:00
parent 400a837a4f
commit c7b6c69442
3 changed files with 31 additions and 36 deletions
@@ -10,10 +10,11 @@ import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.impl.DebuggerUtilsImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.sun.jdi.*;
import java.util.Collections;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.Value;
class InstanceofEvaluator implements Evaluator {
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.evaluation.expression.InstanceofEvaluator");
@@ -35,13 +36,8 @@ class InstanceofEvaluator implements Evaluator {
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.object.reference.expected"));
}
try {
ReferenceType refType = (ReferenceType)myTypeEvaluator.evaluate(context);
ClassObjectReference classObject = refType.classObject();
ClassType classRefType = (ClassType)classObject.referenceType();
//noinspection HardCodedStringLiteral
Method method = classRefType.concreteMethodByName("isAssignableFrom", "(Ljava/lang/Class;)Z");
return context.getDebugProcess().invokeMethod(context, classObject, method,
Collections.singletonList(((ObjectReference)value).referenceType().classObject()));
return context.getDebugProcess().getVirtualMachineProxy().mirrorOf(
DebuggerUtilsImpl.instanceOf(((ObjectReference)value).referenceType(), (ReferenceType)myTypeEvaluator.evaluate(context)));
}
catch (Exception e) {
LOG.debug(e);
@@ -36,19 +36,18 @@ import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
import com.intellij.util.xmlb.XmlSerializer;
import com.intellij.xdebugger.XExpression;
import com.intellij.xdebugger.impl.breakpoints.XExpressionState;
import com.sun.jdi.InternalException;
import com.sun.jdi.ObjectCollectedException;
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.Value;
import com.sun.jdi.*;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
import com.sun.jdi.connect.ListeningConnector;
import one.util.streamex.StreamEx;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.Map;
import java.util.stream.Stream;
public class DebuggerUtilsImpl extends DebuggerUtilsEx{
public static final Key<PsiType> PSI_TYPE_KEY = Key.create("PSI_TYPE_KEY");
@@ -269,4 +268,23 @@ public class DebuggerUtilsImpl extends DebuggerUtilsEx{
String transportName = DebuggerBundle.getTransportName(connection);
return DebuggerBundle.message("string.connection", addressDisplayName, transportName);
}
public static boolean instanceOf(@Nullable ReferenceType type, @NotNull ReferenceType superType) {
if (type == null) {
return false;
}
if (superType.equals(type)) {
return true;
}
return supertypes(type).anyMatch(t -> instanceOf(t, superType));
}
public static Stream<? extends ReferenceType> supertypes(ReferenceType type) {
if (type instanceof InterfaceType) {
return ((InterfaceType)type).superinterfaces().stream();
} else if (type instanceof ClassType) {
return StreamEx.<ReferenceType>ofNullable(((ClassType)type).superclass()).prepend(((ClassType)type).interfaces());
}
return StreamEx.empty();
}
}
@@ -17,6 +17,7 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.engine.requests.RequestManagerImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.impl.DebuggerUtilsImpl;
import com.intellij.debugger.impl.PositionUtil;
import com.intellij.debugger.jdi.ClassesByNameProvider;
import com.intellij.debugger.jdi.MethodBytecodeUtil;
@@ -62,7 +63,6 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.stream.Stream;
public class MethodBreakpoint extends BreakpointWithHighlighter<JavaMethodBreakpointProperties> implements MethodBreakpointBase {
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.breakpoints.MethodBreakpoint");
@@ -121,7 +121,7 @@ public class MethodBreakpoint extends BreakpointWithHighlighter<JavaMethodBreakp
DebuggerManagerThreadImpl.assertIsManagerThread();
RequestManagerImpl requestsManager = debugProcess.getRequestsManager();
ClassPrepareRequest request = requestsManager.createClassPrepareRequest((debuggerProcess, referenceType) -> {
if (instanceOf(referenceType, baseType)) {
if (DebuggerUtilsImpl.instanceOf(referenceType, baseType)) {
createRequestForPreparedClassEmulated(breakpoint, debugProcess, referenceType, false);
}
}, null);
@@ -546,25 +546,6 @@ public class MethodBreakpoint extends BreakpointWithHighlighter<JavaMethodBreakp
int methodLine;
}
private static boolean instanceOf(@Nullable ReferenceType type, @NotNull ReferenceType superType) {
if (type == null) {
return false;
}
if (superType.equals(type)) {
return true;
}
return supertypes(type).anyMatch(t -> instanceOf(t, superType));
}
private static Stream<? extends ReferenceType> supertypes(ReferenceType type) {
if (type instanceof InterfaceType) {
return ((InterfaceType)type).superinterfaces().stream();
} else if (type instanceof ClassType) {
return StreamEx.<ReferenceType>ofNullable(((ClassType)type).superclass()).prepend(((ClassType)type).interfaces());
}
return StreamEx.empty();
}
private static void processPreparedSubTypes(ReferenceType classType,
BiConsumer<ReferenceType, ClassesByNameProvider> consumer,
ProgressIndicator progressIndicator) {
@@ -585,7 +566,7 @@ public class MethodBreakpoint extends BreakpointWithHighlighter<JavaMethodBreakp
ReferenceType type = allTypes.get(i);
if (type.isPrepared()) {
try {
supertypes(type).forEach(st -> inheritance.putValue(st, type));
DebuggerUtilsImpl.supertypes(type).forEach(st -> inheritance.putValue(st, type));
}
catch (ObjectCollectedException ignored) {
}