changeset 23141:7d5a2e297409

Support non-static @Fold methods.
author Roland Schatz <roland.schatz@oracle.com>
date Mon, 07 Dec 2015 14:06:22 +0100
parents 28613ae6b05d
children 501f7ef2f1f6
files graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/FoldTest.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/FoldPluginGenerator.java graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/PluginGenerator.java
diffstat 3 files changed, 141 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/FoldTest.java	Mon Dec 07 14:06:22 2015 +0100
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.test;
+
+import org.junit.Test;
+
+import com.oracle.graal.api.directives.GraalDirectives;
+import com.oracle.graal.api.replacements.ClassSubstitution;
+import com.oracle.graal.api.replacements.Fold;
+import com.oracle.graal.api.replacements.MethodSubstitution;
+import com.oracle.graal.compiler.test.GraalCompilerTest;
+import com.oracle.graal.nodes.ReturnNode;
+import com.oracle.graal.nodes.StartNode;
+import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import com.oracle.graal.nodes.graphbuilderconf.NodeIntrinsicPluginFactory.InjectionProvider;
+import com.oracle.graal.replacements.NodeIntrinsificationProvider;
+
+public class FoldTest extends GraalCompilerTest {
+
+    private static class TestMethod {
+
+        public static int test() {
+            return 42;
+        }
+    }
+
+    static class FoldUtils {
+
+        private int number;
+
+        FoldUtils(int number) {
+            this.number = number;
+        }
+
+        @Fold
+        static int multiply(int a, int b) {
+            // we want to test whether @Fold works, so prevent automatic constant folding
+            return a * GraalDirectives.opaque(b);
+        }
+
+        @Fold
+        int getNumber() {
+            // we want to test whether @Fold works, so prevent automatic constant folding
+            return GraalDirectives.opaque(number);
+        }
+    }
+
+    @ClassSubstitution(TestMethod.class)
+    private static class TestMethodSubstitution {
+
+        private static final FoldUtils utils = new FoldUtils(21);
+
+        @MethodSubstitution
+        public static int test() {
+            return FoldUtils.multiply(utils.getNumber(), 2);
+        }
+    }
+
+    private static boolean substitutionsInstalled;
+
+    public FoldTest() {
+        if (!substitutionsInstalled) {
+            getProviders().getReplacements().registerSubstitutions(TestMethod.class, TestMethodSubstitution.class);
+            substitutionsInstalled = true;
+        }
+    }
+
+    public static int callTest() {
+        return TestMethod.test();
+    }
+
+    @Override
+    protected Plugins getDefaultGraphBuilderPlugins() {
+        Plugins ret = super.getDefaultGraphBuilderPlugins();
+        // manually register generated factories, jvmci service providers don't work from unit tests
+        InjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), null);
+        new FoldFactory_FoldTest_FoldUtils_getNumber().registerPlugin(ret.getInvocationPlugins(), injection);
+        new FoldFactory_FoldTest_FoldUtils_multiply_255f288().registerPlugin(ret.getInvocationPlugins(), injection);
+        return ret;
+    }
+
+    @Override
+    protected boolean checkHighTierGraph(StructuredGraph graph) {
+        // check that folding happened correctly
+        StartNode start = graph.start();
+        assert start.next() instanceof ReturnNode : "expected ReturnNode, got " + start.next();
+
+        ReturnNode ret = (ReturnNode) start.next();
+        assert ret.result().isConstant() : "expected ConstantNode, got " + ret.result();
+        return true;
+    }
+
+    @Test
+    public void snippetTest() {
+        test("callTest");
+    }
+}
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/FoldPluginGenerator.java	Mon Dec 07 11:57:37 2015 +0100
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/FoldPluginGenerator.java	Mon Dec 07 14:06:22 2015 +0100
@@ -32,6 +32,7 @@
 import javax.lang.model.element.ElementKind;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
 import javax.lang.model.type.TypeMirror;
 import javax.tools.Diagnostic.Kind;
@@ -101,19 +102,30 @@
         InjectedDependencies deps = new InjectedDependencies();
         List<? extends VariableElement> params = intrinsicMethod.getParameters();
 
-        int idx = 0;
+        int argCount = 0;
+        Object receiver;
+        if (intrinsicMethod.getModifiers().contains(Modifier.STATIC)) {
+            receiver = intrinsicMethod.getEnclosingElement();
+        } else {
+            receiver = "arg0";
+            TypeElement type = (TypeElement) intrinsicMethod.getEnclosingElement();
+            constantArgument(out, deps, argCount, type.asType(), argCount);
+            argCount++;
+        }
+
+        int firstArg = argCount;
         for (VariableElement param : params) {
-            constantArgument(out, deps, idx, param.asType(), idx);
-            idx++;
+            constantArgument(out, deps, argCount, param.asType(), argCount);
+            argCount++;
         }
 
         if (intrinsicMethod.getAnnotation(Deprecated.class) != null) {
             out.printf("            @SuppressWarnings(\"deprecation\")\n");
         }
-        out.printf("            %s result = %s.%s(", intrinsicMethod.getReturnType(), intrinsicMethod.getEnclosingElement(), intrinsicMethod.getSimpleName());
-        if (idx > 0) {
-            out.printf("arg0");
-            for (int i = 1; i < idx; i++) {
+        out.printf("            %s result = %s.%s(", intrinsicMethod.getReturnType(), receiver, intrinsicMethod.getSimpleName());
+        if (argCount > firstArg) {
+            out.printf("arg%d", firstArg);
+            for (int i = firstArg + 1; i < argCount; i++) {
                 out.printf(", arg%d", i);
             }
         }
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/PluginGenerator.java	Mon Dec 07 11:57:37 2015 +0100
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/PluginGenerator.java	Mon Dec 07 14:06:22 2015 +0100
@@ -29,6 +29,7 @@
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ElementKind;
 import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
@@ -186,6 +187,9 @@
         out.printf("    public void registerPlugin(InvocationPlugins plugins, InjectionProvider injection) {\n");
         out.printf("        Plugin plugin = new Plugin(%s);\n", deps.isEmpty() ? "" : "injection");
         out.printf("        plugins.register(plugin, %s.class, \"%s\"", intrinsicMethod.getEnclosingElement(), intrinsicMethod.getSimpleName());
+        if (!intrinsicMethod.getModifiers().contains(Modifier.STATIC)) {
+            out.printf(", InvocationPlugin.Receiver.class");
+        }
         for (VariableElement arg : intrinsicMethod.getParameters()) {
             out.printf(", %s.class", getErasedType(arg.asType()));
         }