changeset 5650:8d420cfd2a6f

added unit tests for the Word type
author Doug Simon <doug.simon@oracle.com>
date Tue, 19 Jun 2012 11:37:39 +0200
parents 14505f3e6b4c
children d05664608cb7
files graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/TypeCheckTest.java
diffstat 8 files changed, 279 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java	Tue Jun 19 11:37:39 2012 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2011, 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.snippets;
+
+import static com.oracle.graal.nodes.calc.Condition.*;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.*;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.tests.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+
+/**
+ * Tests for the {@link Word} type.
+ */
+public class WordTest extends GraalCompilerTest implements SnippetsInterface {
+
+    private final SnippetInstaller installer;
+
+    public WordTest() {
+        TargetDescription target = Graal.getRequiredCapability(GraalCompiler.class).target;
+        installer = new SnippetInstaller(runtime, target);
+    }
+
+    @Override
+    protected StructuredGraph parse(Method m) {
+        ResolvedJavaMethod resolvedMethod = runtime.getResolvedJavaMethod(m);
+        return installer.makeGraph(resolvedMethod, null);
+    }
+
+    @Test
+    public void test_arithmetic() {
+        long[] words = new long[] {Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE};
+        for (long word : words) {
+            for (int addend = -1000; addend < 1000; addend++) {
+                test("plus_int", word, addend);
+                test("plus_int", word, -addend);
+                test("minus_int", word, addend);
+                test("minus_int", word, -addend);
+            }
+            for (long addend : words) {
+                test("plus_int", word, (int) addend);
+                test("minus_int", word, (int) addend);
+                test("plus_int", word, -((int) addend));
+                test("minus_int", word, -((int) addend));
+            }
+        }
+    }
+
+    @Test
+    public void test_compare() {
+        long[] words = new long[] {Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE};
+        for (long word1 : words) {
+            for (long word2 : words) {
+                for (Condition cond : new Condition[] {AE, AT, EQ, NE, BE, BT}) {
+                    test("compare" + cond.name(), word1, word2);
+                    test("compare" + cond.name(), word2, word1);
+                }
+            }
+        }
+    }
+
+    @Snippet
+    public static long plus_int(long word, int addend) {
+        return Word.fromLong(word).plus(addend).toLong();
+    }
+
+    @Snippet
+    public static long minus_int(long word, int addend) {
+        return Word.fromLong(word).plus(addend).toLong();
+    }
+
+    @Snippet
+    public static boolean compareAE(long word1, long word2) {
+        return Word.fromLong(word1).cmp(Condition.AE, Word.fromLong(word2));
+    }
+    @Snippet
+    public static boolean compareAT(long word1, long word2) {
+        return Word.fromLong(word1).cmp(Condition.AT, Word.fromLong(word2));
+    }
+    @Snippet
+    public static boolean compareEQ(long word1, long word2) {
+        return Word.fromLong(word1).cmp(Condition.EQ, Word.fromLong(word2));
+    }
+    @Snippet
+    public static boolean compareNE(long word1, long word2) {
+        return Word.fromLong(word1).cmp(Condition.NE, Word.fromLong(word2));
+    }
+    @Snippet
+    public static boolean compareBE(long word1, long word2) {
+        return Word.fromLong(word1).cmp(Condition.BE, Word.fromLong(word2));
+    }
+    @Snippet
+    public static boolean compareBT(long word1, long word2) {
+        return Word.fromLong(word1).cmp(Condition.BT, Word.fromLong(word2));
+    }
+
+}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java	Tue Jun 19 11:36:27 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java	Tue Jun 19 11:37:39 2012 +0200
@@ -27,6 +27,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.snippets.Word.Operation;
 import com.oracle.graal.snippets.nodes.*;
 
 /**
@@ -67,6 +68,9 @@
                         return false;
                     }
                 }
+                if (method.getAnnotation(Operation.class) != null) {
+                    return false;
+                }
                 return true;
             }
         };
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Tue Jun 19 11:36:27 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Tue Jun 19 11:37:39 2012 +0200
@@ -134,10 +134,10 @@
         }
     }
 
-    private StructuredGraph makeGraph(final ResolvedJavaMethod method, final InliningPolicy policy) {
+    public StructuredGraph makeGraph(final ResolvedJavaMethod method, final InliningPolicy policy) {
         StructuredGraph graph = graphCache.get(method);
         if (graph == null) {
-            graph = buildGraph(method, policy);
+            graph = buildGraph(method, policy == null ? inliningPolicy(method) : policy);
             //System.out.println("built " + graph);
             graphCache.put(method, graph);
         }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java	Tue Jun 19 11:36:27 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java	Tue Jun 19 11:37:39 2012 +0200
@@ -26,6 +26,7 @@
 
 import java.lang.annotation.*;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 
 /**
@@ -46,32 +47,83 @@
      * The canonical {@link Operation} represented by a method in the {@link Word} class.
      */
     public enum Opcode {
+        L2W,
+        I2W,
+        W2L,
+        W2I,
         PLUS,
         MINUS,
         COMPARE;
     }
 
-    private Word() {
+    private Word(long value) {
+        this.value = value;
+    }
+
+    private final long value;
+
+    @Operation(L2W)
+    public static Word fromLong(long value) {
+        return new Word(value);
+    }
+
+    @Operation(I2W)
+    public static Word fromInt(int value) {
+        return new Word(value);
+    }
+
+    @Operation(W2I)
+    public int toInt() {
+        return (int) value;
+    }
+
+    @Operation(W2L)
+    public long toLong() {
+        return value;
     }
 
     @Operation(COMPARE)
-    public native boolean cmp(Condition condition, Word other);
+    public boolean cmp(Condition condition, Word other) {
+        long a = value;
+        long b = other.value;
+        switch (condition) {
+            case AE: return (a >= b) ^ ((a < 0) != (b < 0));
+            case AT: return (a > b) ^ ((a < 0) != (b < 0));
+            case BE: return (a <= b) ^ ((a < 0) != (b < 0));
+            case BT: return (a < b) ^ ((a < 0) != (b < 0));
+            case EQ: return a == b;
+            case NE: return a != b;
+            default: throw new GraalInternalError("Unexpected operation on word: " + condition);
+        }
+    }
 
     @Operation(PLUS)
-    public native Word plus(int addend);
-
-    @Operation(PLUS)
-    public native Word plus(long addend);
+    public Word plus(int addend) {
+        return new Word(value + addend);
+    }
 
     @Operation(PLUS)
-    public native Word plus(Word addend);
+    public Word plus(long addend) {
+        return new Word(value + addend);
+    }
 
-    @Operation(MINUS)
-    public native Word minus(int addend);
+    @Operation(PLUS)
+    public Word plus(Word addend) {
+        return new Word(value + addend.value);
+    }
 
     @Operation(MINUS)
-    public native Word minus(long addend);
+    public Word minus(int addend) {
+        return new Word(value - addend);
+    }
 
     @Operation(MINUS)
-    public native Word minus(Word addend);
+    public Word minus(long addend) {
+        return new Word(value - addend);
+    }
+
+    @Operation(MINUS)
+    public Word minus(Word addend) {
+        return new Word(value - addend.value);
+    }
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Tue Jun 19 11:36:27 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Tue Jun 19 11:37:39 2012 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.*;
+import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.ConvertNode.Op;
 import com.oracle.graal.nodes.extended.*;
@@ -81,7 +81,7 @@
             if (operation != null) {
                 NodeInputList<ValueNode> arguments = callTargetNode.arguments();
                 Invoke invoke = (Invoke) callTargetNode.usages().first();
-                assert invoke != null;
+                assert invoke != null : callTargetNode.targetMethod();
 
                 Opcode opcode = operation.value();
                 switch (opcode) {
@@ -99,6 +99,40 @@
                         invoke.intrinsify(op);
                         break;
                     }
+
+                    case W2I: {
+                        assert arguments.size() == 1;
+                        ValueNode value = arguments.last();
+                        ValueNode intValue = fromWordKindTo(graph, value, Kind.Int);
+                        invoke.intrinsify(intValue);
+                        break;
+                    }
+
+                    case W2L: {
+                        assert arguments.size() == 1;
+                        ValueNode value = arguments.last();
+                        ValueNode longValue = fromWordKindTo(graph, value, Kind.Long);
+                        invoke.intrinsify(longValue);
+                        break;
+                    }
+
+                    case L2W: {
+                        assert arguments.size() == 1;
+                        ValueNode value = arguments.last();
+                        assert value.kind() == Kind.Long;
+                        ValueNode wordValue = asWordKind(graph, value);
+                        invoke.intrinsify(wordValue);
+                        break;
+                    }
+
+                    case I2W: {
+                        assert arguments.size() == 1;
+                        ValueNode value = arguments.last();
+                        assert value.kind() == Kind.Int;
+                        invoke.intrinsify(asWordKind(graph, value));
+                        break;
+                    }
+
                     default: {
                         throw new GraalInternalError("Unknown opcode: %s", opcode);
                     }
@@ -111,7 +145,7 @@
      * Creates comparison node for a given condition and two input values.
      */
     private ValueNode compare(Condition condition, StructuredGraph graph, ValueNode left, ValueNode right) {
-        assert condition.isUnsigned();
+        assert condition.isUnsigned() || condition == Condition.EQ || condition == Condition.NE : condition;
         assert left.kind() == wordKind;
         assert right.kind() == wordKind;
 
@@ -158,6 +192,21 @@
         return value;
     }
 
+    private static ValueNode fromWordKindTo(StructuredGraph graph, ValueNode value, Kind to) {
+        Kind from = value.kind();
+        if (from != to) {
+            Op op;
+            if (from.isLong()) {
+                op = Op.L2I;
+            } else {
+                assert from.isInt();
+                op = Op.I2L;
+            }
+            return graph.unique(new ConvertNode(op, value));
+        }
+        return value;
+    }
+
     public boolean isWord(ValueNode node) {
         return isWord(node.stamp().declaredType());
     }
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java	Tue Jun 19 11:36:27 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java	Tue Jun 19 11:37:39 2012 +0200
@@ -67,7 +67,7 @@
         }
 
         final ResolvedJavaMethod riMethod = runtime.getResolvedJavaMethod(method);
-        InstalledCode compiledMethod = compile(riMethod, graph);
+        InstalledCode compiledMethod = getCode(riMethod, graph);
         try {
             Object result = compiledMethod.execute("1", "2", "3");
             Assert.assertEquals("1-2-3", result);
@@ -81,7 +81,7 @@
         Method method = getMethod("testMethod");
         final StructuredGraph graph = parse(method);
         final ResolvedJavaMethod riMethod = runtime.getResolvedJavaMethod(method);
-        InstalledCode compiledMethod = compile(riMethod, graph);
+        InstalledCode compiledMethod = getCode(riMethod, graph);
         try {
             Object result = compiledMethod.executeVarargs("1", "2", "3");
             Assert.assertEquals("1 2 3", result);
@@ -95,7 +95,7 @@
         Method method = getMethod("testMethodVirtual");
         final StructuredGraph graph = parse(method);
         final ResolvedJavaMethod riMethod = runtime.getResolvedJavaMethod(method);
-        InstalledCode compiledMethod = compile(riMethod, graph);
+        InstalledCode compiledMethod = getCode(riMethod, graph);
         try {
             f1 = "0";
             Object result = compiledMethod.executeVarargs(this, "1", "2", "3");
@@ -123,7 +123,7 @@
             }
         }
 
-        InstalledCode compiledMethod = compile(riMethod, graph);
+        InstalledCode compiledMethod = getCode(riMethod, graph);
         final CompilableObject compilableObject = new CompilableObjectImpl(0);
 
         Object result;
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java	Tue Jun 19 11:36:27 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java	Tue Jun 19 11:37:39 2012 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.tests;
 
 import java.lang.reflect.*;
+import java.util.*;
 import java.util.concurrent.*;
 
 import junit.framework.*;
@@ -163,8 +164,7 @@
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
-        InstalledCode compiledMethod = compile(runtime.getResolvedJavaMethod(method), parse(method));
-        compiledMethod.method();
+        InstalledCode compiledMethod = getCode(runtime.getResolvedJavaMethod(method), parse(method));
 
         if (exception != null) {
             try {
@@ -179,13 +179,35 @@
         }
     }
 
-    protected InstalledCode compile(final ResolvedJavaMethod method, final StructuredGraph graph) {
-        return Debug.scope("Compiling", new DebugDumpScope(String.valueOf(compilationId++), true), new Callable<InstalledCode>() {
+    private Map<ResolvedJavaMethod, InstalledCode> cache = new HashMap<>();
+
+    /**
+     * Gets installed code for a given method and graph, compiling it first if necessary.
+     */
+    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) {
+        return getCode(method, graph, false);
+    }
+
+    /**
+     * Gets installed code for a given method and graph, compiling it first if necessary.
+     *
+     * @param forceCompile specifies whether to ignore any previous code cached for the (method, key) pair
+     */
+    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph, boolean forceCompile) {
+        if (!forceCompile) {
+            InstalledCode cached = cache.get(method);
+            if (cached != null && cached.isValid()) {
+                return cached;
+            }
+        }
+        InstalledCode installedCode = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(compilationId++), true), new Callable<InstalledCode>() {
             public InstalledCode call() throws Exception {
                 CompilationResult targetMethod = runtime.compile(method, graph);
                 return addMethod(method, targetMethod);
             }
         });
+        cache.put(method, installedCode);
+        return installedCode;
     }
 
     protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult tm) {
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/TypeCheckTest.java	Tue Jun 19 11:36:27 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/TypeCheckTest.java	Tue Jun 19 11:37:39 2012 +0200
@@ -36,11 +36,13 @@
     protected JavaTypeProfile currentProfile;
 
     @Override
-    protected InstalledCode compile(final ResolvedJavaMethod method, final StructuredGraph graph) {
+    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) {
+        boolean forceCompile = false;
         if (currentProfile != null) {
             replaceProfile(graph, currentProfile);
+            forceCompile = true;
         }
-        return super.compile(method, graph);
+        return super.getCode(method, graph, forceCompile);
     }
 
     protected JavaTypeProfile profile(Class... types) {