[debugger] try to avoid using arrays for arguments in helper

GitOrigin-RevId: da29532cf4ab5345a51860cae3d08f0bdf96c3df
This commit is contained in:
Egor Ushakov
2024-11-08 14:22:21 +00:00
committed by intellij-monorepo-bot
parent f5c2141c27
commit 1add664fa3
2 changed files with 161 additions and 16 deletions
@@ -1530,6 +1530,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
invokerArgs.add(objRef); // object
invokerArgs.add(DebuggerUtilsEx.mirrorOfString(method.name() + ";" + method.signature(),
evaluationContext)); // method name and descriptor
invokerArgs.add(method.declaringType().classLoader()); // method's declaring type class loader to be able to resolve parameter types
// argument values
List<Value> args = new ArrayList<>(originalArgs);
@@ -1549,16 +1550,19 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
boxedArgs.add((Value)BoxingEvaluator.box(arg, evaluationContext));
}
ArrayType objectArrayClass = (ArrayType)debugProcess.findClass(
evaluationContext,
CommonClassNames.JAVA_LANG_OBJECT + "[]",
evaluationContext.getClassLoader());
if (boxedArgs.size() < 10) {
invokerArgs.addAll(boxedArgs); // args
return DebuggerUtilsImpl.invokeHelperMethod(evaluationContext, MethodInvoker.class, "invoke" + boxedArgs.size(), invokerArgs, false);
}
else {
ArrayType objectArrayClass = (ArrayType)debugProcess.findClass(
evaluationContext,
CommonClassNames.JAVA_LANG_OBJECT + "[]",
evaluationContext.getClassLoader());
// reserve one extra element for the return value
boxedArgs.add(null);
invokerArgs.add(DebuggerUtilsEx.mirrorOfArray(objectArrayClass, boxedArgs, evaluationContext)); // args
invokerArgs.add(method.declaringType().classLoader()); // method's declaring type class loader to be able to resolve parameter types
return DebuggerUtilsImpl.invokeHelperMethod(evaluationContext, MethodInvoker.class, "invoke", invokerArgs, false);
invokerArgs.add(DebuggerUtilsEx.mirrorOfArray(objectArrayClass, boxedArgs, evaluationContext)); // args
return DebuggerUtilsImpl.invokeHelperMethod(evaluationContext, MethodInvoker.class, "invoke", invokerArgs, false);
}
}
private static ThreadReferenceProxy getEvaluationThread(final EvaluationContext evaluationContext) throws EvaluateException {
@@ -8,14 +8,158 @@ import java.lang.invoke.WrongMethodTypeException;
import java.lang.reflect.Array;
import java.util.Arrays;
@SuppressWarnings({"SSBasedInspection", "unused"})
public final class MethodInvoker {
// TODO: may leak objects here
static ThreadLocal<Object> returnValue = new ThreadLocal<>();
public static Object invoke0(MethodHandles.Lookup lookup, Class<?> cls, Object obj, String nameAndDescriptor, ClassLoader loader)
throws Throwable {
return invoke(lookup, cls, obj, nameAndDescriptor, loader, new Object[]{});
}
public static Object invoke1(MethodHandles.Lookup lookup,
Class<?> cls,
Object obj,
String nameAndDescriptor,
ClassLoader loader,
Object arg1) throws Throwable {
return invoke(lookup, cls, obj, nameAndDescriptor, loader, new Object[]{arg1});
}
public static Object invoke2(MethodHandles.Lookup lookup,
Class<?> cls,
Object obj,
String nameAndDescriptor,
ClassLoader loader,
Object arg1,
Object arg2) throws Throwable {
return invoke(lookup, cls, obj, nameAndDescriptor, loader, new Object[]{arg1, arg2});
}
public static Object invoke3(MethodHandles.Lookup lookup,
Class<?> cls,
Object obj,
String nameAndDescriptor,
ClassLoader loader,
Object arg1,
Object arg2,
Object arg3) throws Throwable {
return invoke(lookup, cls, obj, nameAndDescriptor, loader, new Object[]{arg1, arg2, arg3});
}
public static Object invoke4(MethodHandles.Lookup lookup,
Class<?> cls,
Object obj,
String nameAndDescriptor,
ClassLoader loader,
Object arg1,
Object arg2,
Object arg3,
Object arg4) throws Throwable {
return invoke(lookup, cls, obj, nameAndDescriptor, loader, new Object[]{arg1, arg2, arg3, arg4});
}
public static Object invoke5(MethodHandles.Lookup lookup,
Class<?> cls,
Object obj,
String nameAndDescriptor,
ClassLoader loader,
Object arg1,
Object arg2,
Object arg3,
Object arg4,
Object arg5) throws Throwable {
return invoke(lookup, cls, obj, nameAndDescriptor, loader, new Object[]{arg1, arg2, arg3, arg4, arg5});
}
public static Object invoke6(MethodHandles.Lookup lookup,
Class<?> cls,
Object obj,
String nameAndDescriptor,
ClassLoader loader,
Object arg1,
Object arg2,
Object arg3,
Object arg4,
Object arg5,
Object arg6) throws Throwable {
return invoke(lookup, cls, obj, nameAndDescriptor, loader, new Object[]{arg1, arg2, arg3, arg4, arg5, arg6});
}
public static Object invoke7(MethodHandles.Lookup lookup,
Class<?> cls,
Object obj,
String nameAndDescriptor,
ClassLoader loader,
Object arg1,
Object arg2,
Object arg3,
Object arg4,
Object arg5,
Object arg6,
Object arg7) throws Throwable {
return invoke(lookup, cls, obj, nameAndDescriptor, loader, new Object[]{arg1, arg2, arg3, arg4, arg5, arg6, arg7});
}
public static Object invoke8(MethodHandles.Lookup lookup,
Class<?> cls,
Object obj,
String nameAndDescriptor,
ClassLoader loader,
Object arg1,
Object arg2,
Object arg3,
Object arg4,
Object arg5,
Object arg6,
Object arg7,
Object arg8) throws Throwable {
return invoke(lookup, cls, obj, nameAndDescriptor, loader, new Object[]{arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8});
}
public static Object invoke9(MethodHandles.Lookup lookup,
Class<?> cls,
Object obj,
String nameAndDescriptor,
ClassLoader loader,
Object arg1,
Object arg2,
Object arg3,
Object arg4,
Object arg5,
Object arg6,
Object arg7,
Object arg8,
Object arg9) throws Throwable {
return invoke(lookup, cls, obj, nameAndDescriptor, loader, new Object[]{arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9});
}
public static Object invoke10(MethodHandles.Lookup lookup,
Class<?> cls,
Object obj,
String nameAndDescriptor,
ClassLoader loader,
Object arg1,
Object arg2,
Object arg3,
Object arg4,
Object arg5,
Object arg6,
Object arg7,
Object arg8,
Object arg9,
Object arg10) throws Throwable {
return invoke(lookup, cls, obj, nameAndDescriptor, loader, new Object[]{arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10});
}
public static Object invoke(MethodHandles.Lookup lookup,
Class<?> cls,
Object obj,
String nameAndDescriptor,
Object[] argsArray,
ClassLoader loader)
throws Throwable {
ClassLoader loader,
Object[] args) throws Throwable {
try {
int separatorIndex = nameAndDescriptor.indexOf(';');
String name = nameAndDescriptor.substring(0, separatorIndex);
@@ -33,9 +177,6 @@ public final class MethodInvoker {
method = lookup.findStatic(cls, name, mt);
}
// the last element is always null, it is reserved for the return value
Object[] args = Arrays.copyOf(argsArray, argsArray.length - 1);
Object result;
// handle the case where null is passed as the vararg array
@@ -55,7 +196,7 @@ public final class MethodInvoker {
}
result = method.invokeWithArguments(args);
}
argsArray[argsArray.length - 1] = result; // store the result as the last array element to avoid it being collected
returnValue.set(result);
return result;
}
catch (WrongMethodTypeException | ClassCastException e) {