8011210: fix reporting of call site locations; print them on -tcs=miss
authorattila
Mon, 15 Jul 2013 16:58:23 +0200
changeset 18880 89eafd5b9ff7
parent 18879 382986b34105
child 18881 3198876c1f4f
8011210: fix reporting of call site locations; print them on -tcs=miss Reviewed-by: jlaskey, hannesw
nashorn/src/jdk/internal/dynalink/DynamicLinker.java
nashorn/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java
--- a/nashorn/src/jdk/internal/dynalink/DynamicLinker.java	Mon Jul 15 16:35:38 2013 +0200
+++ b/nashorn/src/jdk/internal/dynalink/DynamicLinker.java	Mon Jul 15 16:58:23 2013 +0200
@@ -144,6 +144,9 @@
     private static final String CLASS_NAME = DynamicLinker.class.getName();
     private static final String RELINK_METHOD_NAME = "relink";
 
+    private static final String INITIAL_LINK_CLASS_NAME = "java.lang.invoke.MethodHandleNatives";
+    private static final String INITIAL_LINK_METHOD_NAME = "linkCallSite";
+
     private final LinkerServices linkerServices;
     private final int runtimeContextArgCount;
     private final boolean syncOnRelink;
@@ -262,20 +265,54 @@
     }
 
     /**
-     * Returns a stack trace element describing the location of the call site currently being relinked on the current
+     * Returns a stack trace element describing the location of the call site currently being linked on the current
      * thread. The operation internally creates a Throwable object and inspects its stack trace, so it's potentially
      * expensive. The recommended usage for it is in writing diagnostics code.
-     * @return a stack trace element describing the location of the call site currently being relinked, or null if it is
-     * not invoked while a call site is being relinked.
+     * @return a stack trace element describing the location of the call site currently being linked, or null if it is
+     * not invoked while a call site is being linked.
      */
-    public static StackTraceElement getRelinkedCallSiteLocation() {
+    public static StackTraceElement getLinkedCallSiteLocation() {
         final StackTraceElement[] trace = new Throwable().getStackTrace();
         for(int i = 0; i < trace.length - 1; ++i) {
             final StackTraceElement frame = trace[i];
-            if(RELINK_METHOD_NAME.equals(frame.getMethodName()) && CLASS_NAME.equals(frame.getClassName())) {
+            if(isRelinkFrame(frame) || isInitialLinkFrame(frame)) {
                 return trace[i + 1];
             }
         }
         return null;
     }
+
+    /**
+     * Deprecated because of not precise name.
+     * @deprecated Use {@link #getLinkedCallSiteLocation()} instead.
+     * @return see non-deprecated method
+     */
+    @Deprecated
+    public static StackTraceElement getRelinkedCallSiteLocation() {
+        return getLinkedCallSiteLocation();
+    }
+
+    /**
+     * Returns true if the frame represents {@code MethodHandleNatives.linkCallSite()}, the frame immediately on top of
+     * the call site frame when the call site is being linked for the first time.
+     * @param frame the frame
+     * @return true if this frame represents {@code MethodHandleNatives.linkCallSite()}
+     */
+    private static boolean isInitialLinkFrame(final StackTraceElement frame) {
+        return testFrame(frame, INITIAL_LINK_METHOD_NAME, INITIAL_LINK_CLASS_NAME);
+    }
+
+    /**
+     * Returns true if the frame represents {@code DynamicLinker.relink()}, the frame immediately on top of the call
+     * site frame when the call site is being relinked (linked for second and subsequent times).
+     * @param frame the frame
+     * @return true if this frame represents {@code DynamicLinker.relink()}
+     */
+    private static boolean isRelinkFrame(final StackTraceElement frame) {
+        return testFrame(frame, RELINK_METHOD_NAME, CLASS_NAME);
+    }
+
+    private static boolean testFrame(final StackTraceElement frame, final String methodName, final String className) {
+        return methodName.equals(frame.getMethodName()) && className.equals(frame.getClassName());
+    }
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java	Mon Jul 15 16:35:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java	Mon Jul 15 16:58:23 2013 +0200
@@ -133,7 +133,7 @@
     }
 
     private static String getScriptLocation() {
-        final StackTraceElement caller = DynamicLinker.getRelinkedCallSiteLocation();
+        final StackTraceElement caller = DynamicLinker.getLinkedCallSiteLocation();
         return caller == null ? "unknown location" : (caller.getFileName() + ":" + caller.getLineNumber());
     }
 
@@ -317,7 +317,7 @@
 
         private static final MethodHandle TRACEOBJECT = findOwnMH("traceObject", Object.class, MethodHandle.class, Object[].class);
         private static final MethodHandle TRACEVOID   = findOwnMH("traceVoid", void.class, MethodHandle.class, Object[].class);
-        private static final MethodHandle TRACEMISS   = findOwnMH("traceMiss", void.class, Object[].class);
+        private static final MethodHandle TRACEMISS   = findOwnMH("traceMiss", void.class, String.class, Object[].class);
 
         TracingLinkerCallSite(final NashornCallSiteDescriptor desc) {
            super(desc);
@@ -363,7 +363,7 @@
                 return relink;
             }
             final MethodType type = relink.type();
-            return MH.foldArguments(relink, MH.asType(MH.asCollector(MH.bindTo(TRACEMISS, this), Object[].class, type.parameterCount()), type.changeReturnType(void.class)));
+            return MH.foldArguments(relink, MH.asType(MH.asCollector(MH.insertArguments(TRACEMISS, 0, this, "MISS " + getScriptLocation() + " "), Object[].class, type.parameterCount()), type.changeReturnType(void.class)));
         }
 
         private void printObject(final PrintWriter out, final Object arg) {
@@ -482,8 +482,8 @@
          * @throws Throwable if invocation failes or throws exception/error
          */
         @SuppressWarnings("unused")
-        public void traceMiss(final Object... args) throws Throwable {
-            tracePrint(Context.getCurrentErr(), "MISS ", args, null);
+        public void traceMiss(final String desc, final Object... args) throws Throwable {
+            tracePrint(Context.getCurrentErr(), desc, args, null);
         }
 
         private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {