changeset 5399:c976c744c802

Merge.
author Doug Simon <doug.simon@oracle.com>
date Mon, 14 May 2012 22:07:14 +0200
parents 17cddac1f2da (diff) 9b44497fef98 (current diff)
children 028c9ce0fc0f
files
diffstat 9 files changed, 175 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Fri May 11 16:38:22 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Mon May 14 22:07:14 2012 +0200
@@ -259,10 +259,10 @@
 
     /**
      * Use HIR lowering instead of LIR lowering for checkcast instructions.
-     * Only checkcasts in methods in a class whose name contains this option will be HIR lowered.
-     * TDOD (dnsimon) remove once HIR checkcast lowering works reliably
+     * Only checkcasts in methods whose fully qualified name contains this option will be HIR lowered.
+     * TODO (dnsimon) remove once HIR checkcast lowering works reliably
      */
-    public static String HIRLowerCheckcast;
+    public static String HIRLowerCheckcast = "";
 
     /**
      * The profiling info cache directory.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Fri May 11 16:38:22 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Mon May 14 22:07:14 2012 +0200
@@ -44,9 +44,56 @@
         this.runtime = runtime;
         this.assumptions = assumptions;
     }
-
     @Override
     protected void run(final StructuredGraph graph) {
+        // Step 1: repeatedly lower fixed nodes until no new ones are created
+        NodeBitMap processed = graph.createNodeBitMap();
+        while (true) {
+            int mark = graph.getMark();
+            ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, true);
+            processBlock(cfg.getStartBlock(), graph.createNodeBitMap(), processed, null);
+
+            if (graph.getNewNodes(mark).filter(FixedNode.class).isEmpty()) {
+                break;
+            }
+            graph.verify();
+            processed.grow();
+        }
+
+        // Step 2: lower the floating nodes
+        processed.negate();
+        final CiLoweringTool loweringTool = new CiLoweringTool() {
+
+            @Override
+            public Node getGuardAnchor() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public GraalRuntime getRuntime() {
+                return runtime;
+            }
+
+            @Override
+            public Node createGuard(Node condition, RiDeoptReason deoptReason, RiDeoptAction action, long leafGraphId) {
+                // TODO (thomaswue): Document why this must not be called on floating nodes.
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public CiAssumptions assumptions() {
+                return assumptions;
+            }
+        };
+        for (Node node : processed) {
+            if (node instanceof Lowerable) {
+                assert !(node instanceof FixedNode) || node.predecessor() == null : node;
+                ((Lowerable) node).lower(loweringTool);
+            }
+        }
+    }
+
+    protected void run0(final StructuredGraph graph) {
         ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, true);
 
         NodeBitMap processed = graph.createNodeBitMap();
@@ -138,7 +185,7 @@
                 FixedNode guardAnchor = (FixedNode) getGuardAnchor();
                 if (GraalOptions.OptEliminateGuards) {
                     for (Node usage : condition.usages()) {
-                        if (activeGuards.isMarked(usage)) {
+                        if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage)) {
                             return usage;
                         }
                     }
@@ -157,9 +204,11 @@
 
         // Lower the instructions of this block.
         for (Node node : b.getNodes()) {
-            processed.mark(node);
-            if (node instanceof Lowerable) {
-                ((Lowerable) node).lower(loweringTool);
+            if (!processed.isMarked(node)) {
+                processed.mark(node);
+                if (node instanceof Lowerable) {
+                    ((Lowerable) node).lower(loweringTool);
+                }
             }
         }
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Fri May 11 16:38:22 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Mon May 14 22:07:14 2012 +0200
@@ -40,7 +40,6 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
-import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.max.cri.ci.*;
@@ -909,7 +908,6 @@
 
     /**
      * Performs replacement of a node with a snippet graph.
-     *
      * @param replacee the node that will be replaced
      * @param anchor the control flow replacee
      * @param snippetGraph the graph that the replacee will be replaced with
@@ -922,12 +920,11 @@
                     final StructuredGraph snippetGraph,
                     final boolean explodeLoops,
                     final IsImmutablePredicate immutabilityPredicate,
-                    final CiLoweringTool tool,
                     final Object... args) {
         Debug.scope("InliningSnippet", snippetGraph.method(), new Runnable() {
             @Override
             public void run() {
-                inlineSnippet0(runtime, replacee, anchor, snippetGraph, explodeLoops, immutabilityPredicate, tool, args);
+                inlineSnippet0(runtime, replacee, anchor, snippetGraph, explodeLoops, immutabilityPredicate, args);
             }
         });
     }
@@ -937,7 +934,7 @@
                     StructuredGraph snippetGraph,
                     boolean explodeLoops,
                     IsImmutablePredicate immutabilityPredicate,
-                    CiLoweringTool tool, Object... args) {
+                    Object... args) {
 
         Debug.dump(replacee.graph(), "Before lowering %s", replacee);
 
@@ -1016,22 +1013,22 @@
         Map<Node, Node> duplicates = graph.addDuplicates(nodes, replacements);
         Debug.dump(graph, "After inlining snippet %s", snippetCopy.method());
 
+//        if (tool != null) {
+//            boolean innerLowering = false;
+//            for (Node node : duplicates.values()) {
+//                if (node instanceof Lowerable) {
+//                    innerLowering = true;
+//                    ((Lowerable) node).lower(tool);
+//
+//                }
+//            }
+//            if (innerLowering) {
+//                Debug.dump(graph, "After inner lowering");
+//            }
+//        }
+
         // Remove all frame states from the inlined snippet graph. Snippets must be atomic (i.e. free
         // of side-effects that prevent deoptimizing to a point before the snippet).
-        if (tool != null) {
-            boolean innerLowering = false;
-            for (Node node : duplicates.values()) {
-                if (node instanceof Lowerable) {
-                    innerLowering = true;
-                    ((Lowerable) node).lower(tool);
-
-                }
-            }
-            if (innerLowering) {
-                Debug.dump(graph, "After inner lowering");
-            }
-        }
-
         for (Node node : graph.getNewNodes(mark)) {
             if (node instanceof StateSplit) {
                 StateSplit stateSplit = (StateSplit) node;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TypeCheckSlowPath.java	Fri May 11 16:38:22 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TypeCheckSlowPath.java	Mon May 14 22:07:14 2012 +0200
@@ -25,6 +25,7 @@
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.target.amd64.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.type.*;
@@ -48,7 +49,7 @@
     }
 
     public TypeCheckSlowPath(ValueNode objectHub, ValueNode hub) {
-        super(StampFactory.forKind(CiKind.Object));
+        super(StampFactory.forKind(CiKind.Boolean));
         this.objectHub = objectHub;
         this.hub = hub;
     }
@@ -56,14 +57,20 @@
     @Override
     public void generate(LIRGenerator gen) {
         CiValue objectHubOpr = gen.operand(objectHub);
-        AMD64TypeCheckSlowPathOp op = new AMD64TypeCheckSlowPathOp(objectHubOpr, gen.operand(hub));
+        Variable result = gen.newVariable(CiKind.Boolean);
+        AMD64TypeCheckSlowPathOp op = new AMD64TypeCheckSlowPathOp(result, objectHubOpr, gen.operand(hub));
         gen.append(op);
-        gen.setResult(this, objectHubOpr);
+        gen.setResult(this, result);
     }
 
+    /**
+     * Checks if {@code objectHub} is a subclass of {@code hub}.
+     *
+     * @return {@code true} if {@code objectHub} is a subclass of {@code hub}, {@code false} otherwise
+     */
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static Object check(Object objectHub, Object hub) {
+    public static boolean check(Object objectHub, Object hub) {
         throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler");
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Fri May 11 16:38:22 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Mon May 14 22:07:14 2012 +0200
@@ -412,7 +412,7 @@
             memoryRead.dependencies().add(tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, StructuredGraph.INVALID_GRAPH_ID));
             graph.replaceFixed(objectClassNode, memoryRead);
         } else if (n instanceof CheckCastNode) {
-            if (GraalOptions.HIRLowerCheckcast != null && graph.method() != null && graph.method().holder().name().contains(GraalOptions.HIRLowerCheckcast)) {
+            if (shouldLowerCheckcast(graph)) {
                 final Map<CiConstant, CiConstant> hintHubsSet = new IdentityHashMap<>();
                 IsImmutablePredicate immutabilityPredicate = new IsImmutablePredicate() {
                     public boolean apply(CiConstant constant) {
@@ -433,7 +433,7 @@
                 hintHubsSet.put(hintHubsConst, hintHubsConst);
                 Debug.log("Lowering checkcast in %s: node=%s, hintsHubs=%s, exact=%b", graph, checkcast, Arrays.toString(hints.types), hints.exact);
 
-                InliningUtil.inlineSnippet(this, checkcast, checkcast, snippetGraph, true, immutabilityPredicate, tool, hub, object, hintHubsConst, CiConstant.forBoolean(hints.exact));
+                InliningUtil.inlineSnippet(this, checkcast, checkcast, snippetGraph, true, immutabilityPredicate, hub, object, hintHubsConst, CiConstant.forBoolean(hints.exact));
                 new DeadCodeEliminationPhase().apply(graph);
             }
         } else {
@@ -441,6 +441,18 @@
         }
     }
 
+    private static boolean shouldLowerCheckcast(StructuredGraph graph) {
+        String option = GraalOptions.HIRLowerCheckcast;
+        if (option != null) {
+            if (option.length() == 0) {
+                return true;
+            }
+            RiResolvedMethod method = graph.method();
+            return method != null && CiUtil.format("%H.%n", method).contains(option);
+        }
+        return false;
+    }
+
     private IndexedLocationNode createArrayLocation(Graph graph, CiKind elementKind, ValueNode index) {
         return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), index, graph);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Fri May 11 16:38:22 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Mon May 14 22:07:14 2012 +0200
@@ -46,7 +46,7 @@
                 return object;
             }
         }
-        if (hintsAreExact || TypeCheckSlowPath.check(objectHub, hub) == null) {
+        if (hintsAreExact || !TypeCheckSlowPath.check(objectHub, hub)) {
             DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException);
         }
         return object;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TypeCheckSlowPathOp.java	Fri May 11 16:38:22 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TypeCheckSlowPathOp.java	Mon May 14 22:07:14 2012 +0200
@@ -38,8 +38,8 @@
  */
 public class AMD64TypeCheckSlowPathOp extends AMD64LIRInstruction {
 
-    public AMD64TypeCheckSlowPathOp(CiValue objectHub, CiValue hub) {
-        super("TYPECHECK_SLOW", new CiValue[] {objectHub}, null, new CiValue[] {objectHub, hub}, NO_OPERANDS, NO_OPERANDS);
+    public AMD64TypeCheckSlowPathOp(CiValue result, CiValue objectHub, CiValue hub) {
+        super("TYPECHECK_SLOW", new CiValue[] {result}, null, new CiValue[] {objectHub, hub}, NO_OPERANDS, NO_OPERANDS);
     }
 
     @Override
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/LowerCheckCastTest.java	Fri May 11 16:38:22 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/LowerCheckCastTest.java	Mon May 14 22:07:14 2012 +0200
@@ -30,28 +30,18 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.max.cri.ri.RiTypeProfile.*;
+import com.oracle.max.cri.ri.RiTypeProfile.ProfiledType;
 
 public class LowerCheckCastTest extends GraphTest {
 
-    static {
-        // Ensure that the methods to be compiled and executed are fully resolved
-        asNumber(0);
-        asString("0");
-        asNumberExt(0);
-        asStringExt("0");
-    }
-
-    private RiCompiledMethod compile(String name, RiTypeProfile profile) {
-        //System.out.println("compiling: " + name + ", hints=" + Arrays.toString(hintClasses) + ", exact=" + exact);
-
-        Method method = getMethod(name);
+    private RiCompiledMethod compile(Method method, RiTypeProfile profile) {
         final StructuredGraph graph = parse(method);
 
         CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first();
-        assert ccn != null;
-        CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.targetClassInstruction(), ccn.targetClass(), ccn.object(), profile));
-        graph.replaceFixedWithFixed(ccn, ccnNew);
+        if (ccn != null) {
+            CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.targetClassInstruction(), ccn.targetClass(), ccn.object(), profile));
+            graph.replaceFixedWithFixed(ccn, ccnNew);
+        }
 
         final RiResolvedMethod riMethod = runtime.getRiMethod(method);
         CiTargetMethod targetMethod = runtime.compile(riMethod, graph);
@@ -69,50 +59,78 @@
         return new RiTypeProfile(0.0D, ptypes);
     }
 
-    private void test(String name, RiTypeProfile profile, Object expected, Object... args) {
-        RiCompiledMethod compiledMethod = compile(name, profile);
-        Assert.assertEquals(expected, compiledMethod.executeVarargs(args));
+    private void test(String name, RiTypeProfile profile, Object... args) {
+        Method method = getMethod(name);
+        Object expect = null;
+        Throwable exception = null;
+        try {
+            // This gives us both the expected return value as well as ensuring that the method to be compiled is fully resolved
+            expect = method.invoke(null, args);
+        } catch (InvocationTargetException e) {
+            exception = e.getTargetException();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        RiCompiledMethod compiledMethod = compile(method, profile);
+        compiledMethod.method();
+
+        if (exception != null) {
+            try {
+                compiledMethod.executeVarargs(args);
+                Assert.fail("expected " + exception);
+            } catch (Throwable e) {
+                Assert.assertEquals(exception.getClass(), e.getClass());
+            }
+        } else {
+            Object actual = compiledMethod.executeVarargs(args);
+            Assert.assertEquals(expect, actual);
+        }
     }
 
     @Test
     public void test1() {
-        test("asNumber",    profile(),                        111, 111);
-        test("asNumber",    profile(Integer.class),           111, 111);
-        test("asNumber",    profile(Long.class, Short.class), 111, 111);
-        test("asNumberExt", profile(),                        121, 111);
-        test("asNumberExt", profile(Integer.class),           121, 111);
-        test("asNumberExt", profile(Long.class, Short.class), 121, 111);
+        test("asNumber",    profile(),                        111);
+        test("asNumber",    profile(Integer.class),           111);
+        test("asNumber",    profile(Long.class, Short.class), 111);
+        test("asNumberExt", profile(),                        111);
+        test("asNumberExt", profile(Integer.class),           111);
+        test("asNumberExt", profile(Long.class, Short.class), 111);
     }
 
     @Test
     public void test2() {
-        test("asString",    profile(),             "111", "111");
-        test("asString",    profile(String.class), "111", "111");
-        test("asString",    profile(String.class), "111", "111");
+        test("asString",    profile(),             "111");
+        test("asString",    profile(String.class), "111");
+        test("asString",    profile(String.class), "111");
 
-        test("asStringExt", profile(),             "#111", "111");
-        test("asStringExt", profile(String.class), "#111", "111");
-        test("asStringExt", profile(String.class), "#111", "111");
-    }
+        final String nullString = null;
+        test("asString",    profile(),             nullString);
+        test("asString",    profile(String.class), nullString);
+        test("asString",    profile(String.class), nullString);
 
-    @Test(expected = ClassCastException.class)
-    public void test3() {
-        test("asNumber", profile(), 111, "111");
+        test("asStringExt", profile(),             "111");
+        test("asStringExt", profile(String.class), "111");
+        test("asStringExt", profile(String.class), "111");
     }
 
-    @Test(expected = ClassCastException.class)
-    public void test4() {
-        test("asString", profile(String.class), "111", 111);
+    @Test
+    public void test3() {
+        test("asNumber", profile(), "111");
     }
 
-    @Test(expected = ClassCastException.class)
-    public void test5() {
-        test("asNumberExt", profile(), 111, "111");
+    @Test
+    public void test4() {
+        test("asString", profile(String.class), 111);
     }
 
-    @Test(expected = ClassCastException.class)
+    @Test
+    public void test5() {
+        test("asNumberExt", profile(), "111");
+    }
+
+    @Test
     public void test6() {
-        test("asStringExt", profile(String.class), "111", 111);
+        test("asStringExt", profile(String.class), 111);
     }
 
     public static Number asNumber(Object o) {
@@ -132,4 +150,16 @@
         String s = (String) o;
         return "#" + s;
     }
+
+    @Test
+    public void test7() {
+        test("arrayFill", profile(), new Object[100], "111");
+    }
+
+    public static Object[] arrayFill(Object[] arr, Object value) {
+        for (int i = 0; i < arr.length; i++) {
+            arr[i] = value;
+        }
+        return arr;
+    }
 }
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Fri May 11 16:38:22 2012 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Mon May 14 22:07:14 2012 +0200
@@ -1047,7 +1047,7 @@
 
   if (jap.get_ret_type() == T_VOID) {
     return NULL;
-  } else if (jap.get_ret_type() == T_OBJECT) {
+  } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) {
     return JNIHandles::make_local((oop) result.get_jobject());
   } else {
     oop o = java_lang_boxing_object::create(jap.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL);