From c7b6c69442f3a60600d240a25d143e85596f8fb6 Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Tue, 6 Nov 2018 19:35:04 +0300 Subject: [PATCH] do not invoke methods for instanceof evaluation --- .../expression/InstanceofEvaluator.java | 16 +++++------- .../debugger/impl/DebuggerUtilsImpl.java | 26 ++++++++++++++++--- .../ui/breakpoints/MethodBreakpoint.java | 25 +++--------------- 3 files changed, 31 insertions(+), 36 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/InstanceofEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/InstanceofEvaluator.java index 08902b03bd6b..71064cd290ef 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/InstanceofEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/InstanceofEvaluator.java @@ -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); diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsImpl.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsImpl.java index 3d4699da3006..c5a579410366 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsImpl.java @@ -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 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 supertypes(ReferenceType type) { + if (type instanceof InterfaceType) { + return ((InterfaceType)type).superinterfaces().stream(); + } else if (type instanceof ClassType) { + return StreamEx.ofNullable(((ClassType)type).superclass()).prepend(((ClassType)type).interfaces()); + } + return StreamEx.empty(); + } } \ No newline at end of file diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java index 7b046f321761..f5579b19652c 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java @@ -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 implements MethodBreakpointBase { private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.breakpoints.MethodBreakpoint"); @@ -121,7 +121,7 @@ public class MethodBreakpoint extends BreakpointWithHighlighter { - if (instanceOf(referenceType, baseType)) { + if (DebuggerUtilsImpl.instanceOf(referenceType, baseType)) { createRequestForPreparedClassEmulated(breakpoint, debugProcess, referenceType, false); } }, null); @@ -546,25 +546,6 @@ public class MethodBreakpoint extends BreakpointWithHighlighter instanceOf(t, superType)); - } - - private static Stream supertypes(ReferenceType type) { - if (type instanceof InterfaceType) { - return ((InterfaceType)type).superinterfaces().stream(); - } else if (type instanceof ClassType) { - return StreamEx.ofNullable(((ClassType)type).superclass()).prepend(((ClassType)type).interfaces()); - } - return StreamEx.empty(); - } - private static void processPreparedSubTypes(ReferenceType classType, BiConsumer consumer, ProgressIndicator progressIndicator) { @@ -585,7 +566,7 @@ public class MethodBreakpoint extends BreakpointWithHighlighter inheritance.putValue(st, type)); + DebuggerUtilsImpl.supertypes(type).forEach(st -> inheritance.putValue(st, type)); } catch (ObjectCollectedException ignored) { }