[debugger] use optimized allLineLocationsSync to reduce number of sync debugger commands

GitOrigin-RevId: 9d0735eb837b705456872ff5f11cbd3c4587f012
This commit is contained in:
Egor Ushakov
2024-10-04 10:48:22 +00:00
committed by intellij-monorepo-bot
parent e45924a30e
commit 87b49d65b2
7 changed files with 37 additions and 12 deletions
@@ -11,6 +11,7 @@ import com.intellij.debugger.engine.evaluation.expression.Modifier;
import com.intellij.debugger.engine.events.DebuggerCommandImpl;
import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.impl.DebuggerUtilsAsync;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.MethodBytecodeUtil;
import com.intellij.debugger.memory.agent.MemoryAgent;
@@ -773,7 +774,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
Location location = lambdaMethod != null ? ContainerUtil.getFirstItem(DebuggerUtilsEx.allLineLocations(lambdaMethod)) : null;
if (location == null) {
location = ContainerUtil.getFirstItem(clsType.allLineLocations());
location = ContainerUtil.getFirstItem(DebuggerUtilsAsync.allLineLocationsSync(clsType));
}
if (location != null) {
@@ -175,7 +175,30 @@ public final class DebuggerUtilsAsync {
return type.locationsOfLine(stratum, sourceName, lineNumber);
}
public static CompletableFuture<List<Location>> allLineLocationsAsync(Method method) {
public static List<Location> allLineLocationsSync(ReferenceType type) throws AbsentInformationException {
return allLineLocationsSync(type, type.virtualMachine().getDefaultStratum(), null);
}
/**
* Drop-in replacement for the standard jdi version, but "parallel" inside, so a lot faster when type has lots of methods
*/
public static List<Location> allLineLocationsSync(ReferenceType type, String stratum, String sourceName)
throws AbsentInformationException {
if (type instanceof ReferenceTypeImpl && isAsyncEnabled()) {
try {
return ((ReferenceTypeImpl)type).allLineLocationsAsync(stratum, sourceName).get();
}
catch (Exception e) {
if (e.getCause() instanceof AbsentInformationException) {
throw (AbsentInformationException)e.getCause();
}
LOG.warn(e);
}
}
return type.allLineLocations(stratum, sourceName);
}
public static CompletableFuture<List<Location>> allLineLocations(Method method) {
if (method instanceof MethodImpl && isAsyncEnabled()) {
return reschedule(((MethodImpl)method).allLineLocationsAsync());
}
@@ -559,7 +559,7 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils {
@Nullable
public static List<Location> allLineLocations(ReferenceType cls) {
try {
return cls.allLineLocations();
return DebuggerUtilsAsync.allLineLocationsSync(cls);
}
catch (AbsentInformationException ignored) {
return null;
@@ -86,7 +86,7 @@ public final class SourceCodeChecker {
DebuggerUtilsEx.isLambda(method)) {
return CompletableFuture.completedFuture(ThreeState.UNSURE);
}
return DebuggerUtilsAsync.allLineLocationsAsync(method).thenApply(locations -> {
return DebuggerUtilsAsync.allLineLocations(method).thenApply(locations -> {
if (ContainerUtil.isEmpty(locations)) {
return ThreeState.UNSURE;
}
@@ -171,7 +171,7 @@ public final class SourceCodeChecker {
for (ReferenceType type : types) {
i++;
try {
for (Location loc : type.allLineLocations()) {
for (Location loc : DebuggerUtilsAsync.allLineLocationsSync(type)) {
SourcePosition position =
ReadAction.compute(() -> {
try {
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.groovy.debugger;
@@ -464,8 +464,7 @@ public class GroovyPositionManager extends PositionManagerEx {
if (!DebuggerUtilsAsync.locationsOfLineSync(fromClass, lineNumber).isEmpty()) {
return fromClass;
}
//noinspection LoopStatementThatDoesntLoop
for (Location location : fromClass.allLineLocations()) {
for (Location location : DebuggerUtilsAsync.allLineLocationsSync(fromClass)) {
final SourcePosition candidateFirstPosition = SourcePosition.createFromLine(
toFind.getContainingFile(), location.lineNumber() - 1
);
@@ -1,7 +1,8 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.eval4j.jdi.test
import com.intellij.debugger.impl.DebuggerUtilsAsync
import com.sun.jdi.*
import com.sun.jdi.event.BreakpointEvent
import com.sun.jdi.event.ClassPrepareEvent
@@ -55,7 +56,7 @@ fun suite(): TestSuite {
is ClassPrepareEvent -> {
val _class = event.referenceType()!!
if (_class.name() == debugeeName) {
for (l in _class.allLineLocations()) {
for (l in DebuggerUtilsAsync.allLineLocationsSync(_class)) {
if (l.method().name() == "main") {
classLoader = l.method().declaringType().classLoader()
val breakpointRequest = vm.eventRequestManager().createBreakpointRequest(l)
@@ -1,7 +1,8 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.debugger.test
import com.intellij.debugger.impl.DebuggerUtilsAsync
import com.intellij.openapi.application.runReadAction
import com.sun.jdi.ThreadReference
import org.jetbrains.kotlin.config.JvmClosureGenerationScheme
@@ -70,7 +71,7 @@ abstract class AbstractFileRankingTest : LowLevelDebuggerTestBase() {
val jdiClass = mainThread.virtualMachine().classesByName(className).singleOrNull()
?: error("Class '$className' was not found in the debuggee process class loader")
val locations = jdiClass.allLineLocations()
val locations = DebuggerUtilsAsync.allLineLocationsSync(jdiClass)
assert(locations.isNotEmpty()) { "There are no locations for class $className" }
val allFilesWithSameName = files.filter { it.name == expectedFile.name }