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

View File

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

View File

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

View File

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

View File

@ -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. /** Return a string with a several lines describing the method handle structure.
* This string would be suitable for display in an IDE debugger. * 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() { String debugString() {
return type+" : "+internalForm()+internalProperties(); return debugString(-1);
} }
//// Implementation methods. //// Implementation methods.
@ -1787,12 +1797,29 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
} }
/*non-public*/ /*non-public*/
Object internalValues() { Object internalValues(int indentLevel) {
return null; 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*/ /*non-public*/
Object internalProperties() { Object internalProperties() {
return internalProperties(-1);
}
Object internalProperties(int indentLevel) {
// Override to something to follow this.form, like "\n& FOO=bar" // Override to something to follow this.form, like "\n& FOO=bar"
return ""; return "";
} }

View File

@ -281,6 +281,12 @@ class MethodHandleNatives {
type, type,
staticArguments, staticArguments,
caller); 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) { if (callSite instanceof ConstantCallSite) {
appendixResult[0] = callSite.dynamicInvoker(); appendixResult[0] = callSite.dynamicInvoker();
return Invokers.linkToTargetMethod(type); return Invokers.linkToTargetMethod(type);
@ -298,13 +304,13 @@ class MethodHandleNatives {
Object bsmReference = bootstrapMethod.internalMemberName(); Object bsmReference = bootstrapMethod.internalMemberName();
if (bsmReference == null) bsmReference = bootstrapMethod; if (bsmReference == null) bsmReference = bootstrapMethod;
String staticArglist = staticArglistForTrace(staticArguments); String staticArglist = staticArglistForTrace(staticArguments);
System.out.println("linkCallSite "+caller.getName()+" "+ System.out.println("linkCallSite "+getCallerInfo(caller)+" "+
bsmReference+" "+ bsmReference+" "+
name+type+"/"+staticArglist); name+type+"/"+staticArglist);
try { try {
MemberName res = linkCallSiteImpl(caller, bootstrapMethod, name, type, MemberName res = linkCallSiteImpl(caller, bootstrapMethod, name, type,
staticArguments, appendixResult); staticArguments, appendixResult);
System.out.println("linkCallSite => "+res+" + "+appendixResult[0]); System.out.println("linkCallSite linkage => "+res+" + "+appendixResult[0]);
return res; return res;
} catch (Throwable ex) { } catch (Throwable ex) {
ex.printStackTrace(); // print now in case exception is swallowed 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: // this implements the upcall from the JVM, MethodHandleNatives.linkDynamicConstant:
static Object linkDynamicConstant(Object callerObj, static Object linkDynamicConstant(Object callerObj,
Object bootstrapMethodObj, Object bootstrapMethodObj,