changeset 5575:eddf8a51be38

added support for a flexible inlining policy during snippet installation
author Doug Simon <doug.simon@oracle.com>
date Tue, 12 Jun 2012 23:11:13 +0200
parents 13624e51918a
children a4d0ded32ddd
files graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java
diffstat 2 files changed, 71 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java	Tue Jun 12 23:05:42 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java	Tue Jun 12 23:11:13 2012 +0200
@@ -25,6 +25,7 @@
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.snippets.nodes.*;
 
@@ -41,6 +42,51 @@
 public @interface Snippet {
 
     /**
+     * Specifies the class defining the inlining policy for this snippet.
+     * A {@linkplain InliningPolicy#Default default} policy is used if none is supplied.
+     */
+    Class<? extends InliningPolicy> inlining() default InliningPolicy.class;
+
+    /**
+     * Guides inlining decisions used when installing a snippet.
+     */
+    public interface InliningPolicy {
+        /**
+         * Determines if {@code method} should be inlined into {@code caller}.
+         */
+        boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller);
+
+        /**
+         * The default inlining policy which inlines everything except for
+         * constructors of {@link Throwable} classes.
+         */
+        InliningPolicy Default = new InliningPolicy() {
+            public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) {
+                if (Throwable.class.isAssignableFrom(method.holder().toJava())) {
+                    if (method.name().equals("<init>")) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+        };
+    }
+
+
+    /**
+     * Annotates a method replaced by a compile-time constant.
+     * A (resolved) call to the annotated method is replaced
+     * with a constant obtained by calling the annotated method via reflection.
+     *
+     * All arguments to such a method (including the receiver if applicable)
+     * must be compile-time constants.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    public static @interface Fold {
+    }
+
+    /**
      * Denotes a snippet parameter that will be bound during snippet
      * template {@linkplain SnippetTemplate#instantiate instantiation}.
      */
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java	Tue Jun 12 23:05:42 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java	Tue Jun 12 23:11:13 2012 +0200
@@ -37,6 +37,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.snippets.Snippet.InliningPolicy;
 
 /**
  * Utilities for snippet installation and management.
@@ -63,12 +64,28 @@
                 }
                 ResolvedJavaMethod snippetRiMethod = runtime.getResolvedJavaMethod(snippet);
                 if (snippetRiMethod.compilerStorage().get(Graph.class) == null) {
-                    buildSnippetGraph(snippetRiMethod, runtime, target, pool);
+                    buildSnippetGraph(snippetRiMethod, runtime, target, pool, inliningPolicy(snippetRiMethod));
                 }
             }
         }
     }
 
+    private static InliningPolicy inliningPolicy(ResolvedJavaMethod method) {
+        Class<? extends InliningPolicy> policyClass = InliningPolicy.class;
+        Snippet snippet = method.getAnnotation(Snippet.class);
+        if (snippet != null) {
+            policyClass = snippet.inlining();
+        }
+        if (policyClass == InliningPolicy.class) {
+            return InliningPolicy.Default;
+        }
+        try {
+            return policyClass.getConstructor().newInstance();
+        } catch (Exception e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
     private static void installSubstitution(ExtendedRiRuntime runtime, TargetDescription target, Class< ? extends SnippetsInterface> clazz,
                     BoxingMethodPool pool, Class<?> original) throws GraalInternalError {
         for (Method snippet : clazz.getDeclaredMethods()) {
@@ -82,7 +99,7 @@
                     throw new RuntimeException("Snippet must not be abstract or native");
                 }
                 ResolvedJavaMethod snippetRiMethod = runtime.getResolvedJavaMethod(snippet);
-                StructuredGraph graph = buildSnippetGraph(snippetRiMethod, runtime, target, pool);
+                StructuredGraph graph = buildSnippetGraph(snippetRiMethod, runtime, target, pool, inliningPolicy(snippetRiMethod));
                 runtime.getResolvedJavaMethod(method).compilerStorage().put(Graph.class, graph);
             } catch (NoSuchMethodException e) {
                 throw new RuntimeException("Could not resolve method to substitute with: " + snippet.getName(), e);
@@ -90,7 +107,7 @@
         }
     }
 
-    private static StructuredGraph buildSnippetGraph(final ResolvedJavaMethod snippetRiMethod, final ExtendedRiRuntime runtime, final TargetDescription target, final BoxingMethodPool pool) {
+    private static StructuredGraph buildSnippetGraph(final ResolvedJavaMethod snippetRiMethod, final ExtendedRiRuntime runtime, final TargetDescription target, final BoxingMethodPool pool, final InliningPolicy policy) {
         final StructuredGraph graph = new StructuredGraph(snippetRiMethod);
         return Debug.scope("BuildSnippetGraph", new Object[] {snippetRiMethod, graph}, new Callable<StructuredGraph>() {
             @Override
@@ -105,15 +122,14 @@
 
                 for (Invoke invoke : graph.getInvokes()) {
                     MethodCallTargetNode callTarget = invoke.callTarget();
-                    ResolvedJavaMethod targetMethod = callTarget.targetMethod();
-                    ResolvedJavaType holder = targetMethod.holder();
-                    if (enclosedInSnippetsClass(holder)) {
-                        StructuredGraph targetGraph = (StructuredGraph) targetMethod.compilerStorage().get(Graph.class);
+                    ResolvedJavaMethod method = callTarget.targetMethod();
+                    if (policy.shouldInline(method, snippetRiMethod)) {
+                        StructuredGraph targetGraph = (StructuredGraph) method.compilerStorage().get(Graph.class);
                         if (targetGraph == null) {
-                            targetGraph = buildSnippetGraph(targetMethod, runtime, target, pool);
+                            targetGraph = buildSnippetGraph(method, runtime, target, pool, policy);
                         }
                         InliningUtil.inline(invoke, targetGraph, true);
-                        Debug.dump(graph, "after inlining %s", targetMethod);
+                        Debug.dump(graph, "after inlining %s", method);
                         if (GraalOptions.OptCanonicalizer) {
                             new WordTypeRewriterPhase(target).apply(graph);
                             new CanonicalizerPhase(target, runtime, null).apply(graph);
@@ -142,17 +158,6 @@
 
                 return graph;
             }
-
-            private boolean enclosedInSnippetsClass(ResolvedJavaType holder) {
-                Class enclosingClass = holder.toJava();
-                while (enclosingClass != null) {
-                    if (SnippetsInterface.class.isAssignableFrom(enclosingClass)) {
-                        return true;
-                    }
-                    enclosingClass = enclosingClass.getEnclosingClass();
-                }
-                return false;
-            }
         });
 
     }