changeset 19811:1e27e31aca11

fixed bug in managing replacement scope during bytecode parsing and improved API for querying replacement info from graph builder plugins
author Doug Simon <doug.simon@oracle.com>
date Thu, 12 Mar 2015 15:25:43 +0100
parents 0a3c6e786b40
children 97a72dcdac8d
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java
diffstat 5 files changed, 73 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java	Thu Mar 12 15:20:29 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java	Thu Mar 12 15:25:43 2015 +0100
@@ -27,10 +27,10 @@
 import static java.lang.String.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.java.*;
+import com.oracle.graal.java.GraphBuilderContext.Replacement;
 import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.*;
@@ -69,8 +69,10 @@
 
     public void notifyOfNoninlinedInvoke(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) {
         if (b.parsingReplacement()) {
-            boolean compilingSnippet = b.getRootMethod().getAnnotation(MethodSubstitution.class) == null;
-            assert compilingSnippet : format("All calls in the replacement %s must be inlined or intrinsified: found call to %s", b.getRootMethod().format("%H.%n(%p)"), method.format("%h.%n(%p)"));
+            boolean compilingSnippet = b.getRootMethod().getAnnotation(Snippet.class) != null;
+            Replacement replacement = b.getReplacement();
+            assert compilingSnippet : format("All calls in the replacement %s must be inlined or intrinsified: found call to %s", replacement.getReplacementMethod().format("%H.%n(%p)"),
+                            method.format("%h.%n(%p)"));
         }
     }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Thu Mar 12 15:20:29 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Thu Mar 12 15:25:43 2015 +0100
@@ -38,6 +38,7 @@
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
+import com.oracle.graal.java.GraphBuilderContext.Replacement;
 import com.oracle.graal.java.GraphBuilderPhase.Instance.BytecodeParser;
 import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin;
 import com.oracle.graal.java.GraphBuilderPlugin.LoadIndexedPlugin;
@@ -81,7 +82,7 @@
      * happen when a call to a {@link MethodSubstitution} is encountered or the root of compilation
      * is a {@link MethodSubstitution} or a snippet.
      */
-    static class ReplacementContext {
+    static class ReplacementContext implements Replacement {
         /**
          * The method being replaced.
          */
@@ -97,6 +98,18 @@
             this.replacement = substitute;
         }
 
+        public ResolvedJavaMethod getOriginalMethod() {
+            return method;
+        }
+
+        public ResolvedJavaMethod getReplacementMethod() {
+            return replacement;
+        }
+
+        public boolean isIntrinsic() {
+            return false;
+        }
+
         /**
          * Determines if a call within the compilation scope of a replacement represents a call to
          * the original method.
@@ -112,7 +125,7 @@
 
     /**
      * Context for a replacement being inlined as a compiler intrinsic. Deoptimization within a
-     * compiler intrinic must replay the intrinsified call. This context object retains the
+     * compiler intrinsic must replay the intrinsified call. This context object retains the
      * information required to build a frame state denoting the JVM state just before the
      * intrinsified call.
      */
@@ -137,6 +150,11 @@
             this.invokeBci = invokeBci;
         }
 
+        @Override
+        public boolean isIntrinsic() {
+            return true;
+        }
+
         /**
          * Gets the frame state that will restart the interpreter just before the intrinsified
          * invocation.
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java	Thu Mar 12 15:20:29 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java	Thu Mar 12 15:25:43 2015 +0100
@@ -34,6 +34,30 @@
  */
 public interface GraphBuilderContext {
 
+    /**
+     * Information about a snippet or method substitution currently being processed by the graph
+     * builder.
+     */
+    public interface Replacement {
+
+        /**
+         * Gets the method being replaced.
+         */
+        ResolvedJavaMethod getOriginalMethod();
+
+        /**
+         * Gets the replacement method.
+         */
+        ResolvedJavaMethod getReplacementMethod();
+
+        /**
+         * Determines if this replacement is being inlined as a compiler intrinsic. A compiler
+         * intrinsic is atomic with respect to deoptimization. Deoptimization within a compiler
+         * intrinsic will restart the interpreter at the intrinsified call.
+         */
+        boolean isIntrinsic();
+    }
+
     <T extends ControlSinkNode> T append(T fixed);
 
     <T extends ControlSplitNode> T append(T fixed);
@@ -87,7 +111,15 @@
     /**
      * Determines if the current parsing context is a snippet or method substitution.
      */
-    boolean parsingReplacement();
+    default boolean parsingReplacement() {
+        return getReplacement() == null;
+    }
+
+    /**
+     * Gets the replacement of the current parsing context or {@code null} if not
+     * {@link #parsingReplacement() parsing a replacement}.
+     */
+    Replacement getReplacement();
 
     /**
      * @see GuardingPiNode#nullCheckedValue(ValueNode)
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Mar 12 15:20:29 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Mar 12 15:25:43 2015 +0100
@@ -1212,8 +1212,9 @@
                 if (context != null && context.isCallToOriginal(targetMethod)) {
                     // Self recursive replacement means the original
                     // method should be called.
-                    if (targetMethod.hasBytecodes()) {
-                        parseAndInlineCallee(context.method, args, null);
+                    if (context.method.hasBytecodes()) {
+                        IntrinsicContext intrinsic = context.asIntrinsic();
+                        parseAndInlineCallee(context.method, args, intrinsic);
                     } else {
                         return false;
                     }
@@ -1225,9 +1226,13 @@
                             context = new ReplacementContext(targetMethod, inlinedMethod);
                         }
                     }
-                    parseAndInlineCallee(inlinedMethod, args, context);
-                    if (plugin != null) {
-                        plugin.postInline(inlinedMethod);
+                    if (inlinedMethod.hasBytecodes()) {
+                        parseAndInlineCallee(inlinedMethod, args, context);
+                        if (plugin != null) {
+                            plugin.postInline(inlinedMethod);
+                        }
+                    } else {
+                        return false;
                     }
                 }
                 return true;
@@ -2350,6 +2355,10 @@
                 return parent == null ? 0 : 1 + parent.getDepth();
             }
 
+            public Replacement getReplacement() {
+                return replacementContext;
+            }
+
             public ResolvedJavaMethod getRootMethod() {
                 return rootMethod;
             }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java	Thu Mar 12 15:20:29 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java	Thu Mar 12 15:25:43 2015 +0100
@@ -77,7 +77,7 @@
             /**
              * The method to be inlined. If this is not equal to the {@code method} argument passed
              * to {@link InlineInvokePlugin#getClass()}, the graph builder context interprets it as
-             * a {@linkplain GraphBuilderContext#parsingReplacement() replacement}.
+             * a {@linkplain GraphBuilderContext.Replacement replacement}.
              */
             public final ResolvedJavaMethod methodToInline;