8295537: Enhance TRACE_METHOD_LINKAGE to show the target MethodHandle

Reviewed-by: jvernee, redestad, mchung
This commit is contained in:
Ioi Lam 2022-10-27 22:07:54 +00:00
parent 182c215888
commit fd668dc44f
5 changed files with 75 additions and 14 deletions

@ -158,21 +158,29 @@ abstract non-sealed class BoundMethodHandle extends MethodHandle {
final int fieldCount() { return speciesData().fieldCount(); }
@Override
Object internalProperties() {
return "\n& BMH="+internalValues();
Object internalProperties(int indentLevel) {
return "\n" + debugPrefix(indentLevel) + "& BMH=" + internalValues(indentLevel);
}
@Override
final String internalValues() {
final String internalValues(int indentLevel) {
String prefix = debugPrefix(indentLevel);
int count = fieldCount();
if (count == 1) {
if (count == 1 && indentLevel < 0) {
return "[" + arg(0) + "]";
}
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < count; ++i) {
sb.append("\n ").append(i).append(": ( ").append(arg(i)).append(" )");
Object theArg = arg(i);
sb.append("\n ").append(prefix).append(i);
if (indentLevel >= 0 && theArg instanceof MethodHandle) {
sb.append(": MethodHandle = {").append(((MethodHandle)theArg).debugString(indentLevel+1));
sb.append("\n ").append(prefix).append("}");
} else {
sb.append(": ( ").append(theArg).append(" )");
}
}
return sb.append("\n]").toString();
return sb.append("\n").append(prefix).append("]").toString();
}
/*non-public*/

@ -170,8 +170,8 @@ sealed class DirectMethodHandle extends MethodHandle {
}
@Override
String internalProperties() {
return "\n& DMH.MN="+internalMemberName();
String internalProperties(int indentLevel) {
return "\n" + debugPrefix(indentLevel) + "& DMH.MN=" + internalMemberName();
}
//// Implementation methods.

@ -1029,12 +1029,18 @@ class LambdaForm {
}
public String toString() {
return debugString(-1);
}
String debugString(int indentLevel) {
String prefix = MethodHandle.debugPrefix(indentLevel);
String lambdaName = lambdaName();
StringBuilder buf = new StringBuilder(lambdaName + "=Lambda(");
StringBuilder buf = new StringBuilder(lambdaName);
buf.append("=Lambda(");
for (int i = 0; i < names.length; i++) {
if (i == arity) buf.append(")=>{");
Name n = names[i];
if (i >= arity) buf.append("\n ");
if (i >= arity) buf.append("\n ").append(prefix);
buf.append(n.paramString());
if (i < arity) {
if (i+1 < arity) buf.append(",");

@ -1688,9 +1688,19 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
}
/** Return a string with a several lines describing the method handle structure.
* This string would be suitable for display in an IDE debugger.
* @param indentLevel If negative, return only information about this MethodHandle.
* Otherwise, return information about this MethodHandle and (recursively) all other
* MethodHandles, if any, that are invoked directly or indirectly by this MethodHandle.
* During the recursion, `indentLevel` is incremented (see
* BoundMethodHandle.internalValues()) to improve readability of
* the nested structure.
*/
String debugString(int indentLevel) {
return type + " : " + internalForm().debugString(indentLevel) +
internalProperties(indentLevel);
}
String debugString() {
return type+" : "+internalForm()+internalProperties();
return debugString(-1);
}
//// Implementation methods.
@ -1787,12 +1797,29 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
}
/*non-public*/
Object internalValues() {
Object internalValues(int indentLevel) {
return null;
}
/**
* Various debugging methods in MethodHandle (and subclasses thereof) and LambdaForm
* take an `indentLevel` argument, so that {@link java.lang.invoke.MethodHandle.debugString(int)}
* can return nested structures in a readable fashion. This method returns a string to be
* prepended to each line at the specified level.
*/
static String debugPrefix(int indentLevel) {
if (indentLevel <= 0) {
return "";
}
return " ".repeat(indentLevel);
}
/*non-public*/
Object internalProperties() {
return internalProperties(-1);
}
Object internalProperties(int indentLevel) {
// Override to something to follow this.form, like "\n& FOO=bar"
return "";
}

@ -281,6 +281,12 @@ class MethodHandleNatives {
type,
staticArguments,
caller);
if (TRACE_METHOD_LINKAGE) {
MethodHandle target = callSite.getTarget();
System.out.println("linkCallSite target class => " + target.getClass().getName());
System.out.println("linkCallSite target => " + target.debugString(0));
}
if (callSite instanceof ConstantCallSite) {
appendixResult[0] = callSite.dynamicInvoker();
return Invokers.linkToTargetMethod(type);
@ -298,13 +304,13 @@ class MethodHandleNatives {
Object bsmReference = bootstrapMethod.internalMemberName();
if (bsmReference == null) bsmReference = bootstrapMethod;
String staticArglist = staticArglistForTrace(staticArguments);
System.out.println("linkCallSite "+caller.getName()+" "+
System.out.println("linkCallSite "+getCallerInfo(caller)+" "+
bsmReference+" "+
name+type+"/"+staticArglist);
try {
MemberName res = linkCallSiteImpl(caller, bootstrapMethod, name, type,
staticArguments, appendixResult);
System.out.println("linkCallSite => "+res+" + "+appendixResult[0]);
System.out.println("linkCallSite linkage => "+res+" + "+appendixResult[0]);
return res;
} catch (Throwable ex) {
ex.printStackTrace(); // print now in case exception is swallowed
@ -313,6 +319,20 @@ class MethodHandleNatives {
}
}
/**
* Return a human-readable description of the caller. Something like
* "java.base/java.security.Security.<clinit>(Security.java:82)"
*/
private static String getCallerInfo(Class<?> caller) {
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
if (e.getClassName().equals(caller.getName())) {
return e.toString();
}
}
// fallback if the caller is somehow missing from the stack.
return caller.getName();
}
// this implements the upcall from the JVM, MethodHandleNatives.linkDynamicConstant:
static Object linkDynamicConstant(Object callerObj,
Object bootstrapMethodObj,