changeset 19710:e5028947ea79

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sun, 08 Mar 2015 21:58:48 +0100
parents 2fd45bb25118 (current diff) 48eeda5dfdbf (diff)
children 69369fd52245
files graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java
diffstat 11 files changed, 266 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Sun Mar 08 21:58:34 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Sun Mar 08 21:58:48 2015 +0100
@@ -190,7 +190,6 @@
         if (singleImplementor != null && !singleImplementor.equals(declaredReceiverType)) {
             ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveMethod(targetMethod(), invoke().getContextType(), true);
             if (singleImplementorMethod != null) {
-                assert graph().getGuardsStage().allowsFloatingGuards() : "Graph already fixed!";
                 /**
                  * We have an invoke on an interface with a single implementor. We can replace this
                  * with an invoke virtual.
@@ -203,9 +202,8 @@
                  * properties by checking of the receiver is an instance of the single implementor.
                  */
                 LogicNode condition = graph().unique(new InstanceOfNode(singleImplementor, receiver, getProfile()));
-                GuardNode guard = graph().unique(
-                                new GuardNode(condition, AbstractBeginNode.prevBegin(invoke().asNode()), DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile,
-                                                false, JavaConstant.NULL_POINTER));
+                FixedGuardNode guard = graph().add(new FixedGuardNode(condition, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, false));
+                graph().addBeforeFixed(invoke().asNode(), guard);
                 PiNode piNode = graph().unique(new PiNode(receiver, StampFactory.declaredNonNull(singleImplementor), guard));
                 arguments().set(0, piNode);
                 setInvokeKind(InvokeKind.Virtual);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Sun Mar 08 21:58:34 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Sun Mar 08 21:58:48 2015 +0100
@@ -787,6 +787,7 @@
                 if (replacementAnchor == null) {
                     replacementAnchor = AbstractBeginNode.prevBegin(checkCast);
                 }
+                assert !(replacementAnchor instanceof FloatingNode) : "unsafe to mix unlowered Checkcast with floating guards";
                 PiNode piNode;
                 if (isNull) {
                     ConstantNode nullObject = ConstantNode.defaultForKind(Kind.Object, graph);
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Sun Mar 08 21:58:34 2015 +0100
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Sun Mar 08 21:58:48 2015 +0100
@@ -137,6 +137,7 @@
             compilationPolicy = new InterpreterOnlyCompilationPolicy();
         }
         OptimizedCallTarget target = new OptimizedCallTarget(source, rootNode, this, compilationPolicy, new HotSpotSpeculationLog());
+        rootNode.setCallTarget(target);
         callTargets.put(target, null);
 
         return target;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Sun Mar 08 21:58:34 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Sun Mar 08 21:58:48 2015 +0100
@@ -91,7 +91,6 @@
         this.compilationPolicy = compilationPolicy;
         this.rootNode.adoptChildren();
         this.rootNode.applyInstrumentation();
-        this.rootNode.setCallTarget(this);
         this.uninitializedRootNode = sourceCallTarget == null ? cloneRootNode(rootNode) : sourceCallTarget.uninitializedRootNode;
         if (TruffleCallTargetProfiling.getValue()) {
             this.compilationProfile = new TraceCompilationProfile();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MergeSpecializationsTest.java	Sun Mar 08 21:58:48 2015 +0100
@@ -0,0 +1,224 @@
+/*
+ * 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.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.dsl.test.MergeSpecializationsTestFactory.TestCachedNodeFactory;
+import com.oracle.truffle.api.dsl.test.MergeSpecializationsTestFactory.TestNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.nodes.*;
+
+public class MergeSpecializationsTest {
+
+    private static final int THREADS = 8;
+
+    @NodeChild
+    @SuppressWarnings("unused")
+    abstract static class TestNode extends ValueNode {
+
+        @Specialization
+        int s1(int a) {
+            return 1;
+        }
+
+        @Specialization
+        int s2(long a) {
+            return 2;
+        }
+
+        @Specialization
+        int s3(double a) {
+            return 3;
+        }
+    }
+
+    @NodeChild
+    @SuppressWarnings("unused")
+    abstract static class TestCachedNode extends ValueNode {
+
+        @Specialization(guards = "a == cachedA", limit = "3")
+        int s1(int a, @Cached("a") int cachedA) {
+            return 1;
+        }
+
+        @Specialization
+        int s2(long a) {
+            return 2;
+        }
+
+        @Specialization
+        int s3(double a) {
+            return 3;
+        }
+    }
+
+    @Test
+    public void testMultithreadedMergeInOrder() {
+        multithreadedMerge(TestNodeFactory.getInstance(), new Executions(1, 1L << 32, 1.0), 1, 2, 3);
+    }
+
+    @Test
+    public void testMultithreadedMergeReverse() {
+        multithreadedMerge(TestNodeFactory.getInstance(), new Executions(1.0, 1L << 32, 1), 3, 2, 1);
+    }
+
+    @Ignore
+    @Test
+    public void testMultithreadedMergeCachedInOrder() {
+        multithreadedMerge(TestCachedNodeFactory.getInstance(), new Executions(1, 1L << 32, 1.0), 1, 2, 3);
+    }
+
+    @Ignore
+    @Test
+    public void testMultithreadedMergeCachedTwoEntries() {
+        multithreadedMerge(TestCachedNodeFactory.getInstance(), new Executions(1, 2, 1.0), 1, 1, 3);
+    }
+
+    @Ignore
+    @Test
+    public void testMultithreadedMergeCachedThreeEntries() {
+        multithreadedMerge(TestCachedNodeFactory.getInstance(), new Executions(1, 2, 3), 1, 1, 1);
+    }
+
+    private static <T extends ValueNode> void multithreadedMerge(NodeFactory<T> factory, final Executions executions, int... order) {
+        assertEquals(3, order.length);
+        final TestRootNode<T> node = createRoot(factory);
+
+        final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
+
+        final CountDownLatch beforeFirst = new CountDownLatch(1);
+        final CountDownLatch executedFirst = new CountDownLatch(THREADS);
+
+        final CountDownLatch beforeSecond = new CountDownLatch(1);
+        final CountDownLatch executedSecond = new CountDownLatch(THREADS);
+
+        final CountDownLatch beforeThird = new CountDownLatch(1);
+        final CountDownLatch executedThird = new CountDownLatch(THREADS);
+
+        Thread[] threads = new Thread[THREADS];
+        for (int i = 0; i < threads.length; i++) {
+            threads[i] = new Thread(new Runnable() {
+                public void run() {
+                    threadsStarted.countDown();
+
+                    MergeSpecializationsTest.await(beforeFirst);
+                    executeWith(node, executions.firstValue);
+                    executedFirst.countDown();
+
+                    MergeSpecializationsTest.await(beforeSecond);
+                    executeWith(node, executions.secondValue);
+                    executedSecond.countDown();
+
+                    MergeSpecializationsTest.await(beforeThird);
+                    executeWith(node, executions.thirdValue);
+                    executedThird.countDown();
+                }
+            });
+            threads[i].start();
+        }
+
+        final SpecializedNode gen = (SpecializedNode) node.getNode();
+
+        final SpecializationNode start0 = gen.getSpecializationNode();
+        assertEquals("UninitializedNode_", start0.getClass().getSimpleName());
+
+        await(threadsStarted);
+        beforeFirst.countDown();
+        await(executedFirst);
+
+        final SpecializationNode start1 = gen.getSpecializationNode();
+        assertEquals("S" + order[0] + "Node_", start1.getClass().getSimpleName());
+        assertEquals("UninitializedNode_", nthChild(1, start1).getClass().getSimpleName());
+
+        beforeSecond.countDown();
+        await(executedSecond);
+
+        final SpecializationNode start2 = gen.getSpecializationNode();
+        Arrays.sort(order, 0, 2);
+        assertEquals("PolymorphicNode_", start2.getClass().getSimpleName());
+        assertEquals("S" + order[0] + "Node_", nthChild(1, start2).getClass().getSimpleName());
+        assertEquals("S" + order[1] + "Node_", nthChild(2, start2).getClass().getSimpleName());
+        assertEquals("UninitializedNode_", nthChild(3, start2).getClass().getSimpleName());
+
+        beforeThird.countDown();
+        await(executedThird);
+
+        final SpecializationNode start3 = gen.getSpecializationNode();
+        Arrays.sort(order);
+        assertEquals("PolymorphicNode_", start3.getClass().getSimpleName());
+        assertEquals("S" + order[0] + "Node_", nthChild(1, start3).getClass().getSimpleName());
+        assertEquals("S" + order[1] + "Node_", nthChild(2, start3).getClass().getSimpleName());
+        assertEquals("S" + order[2] + "Node_", nthChild(3, start3).getClass().getSimpleName());
+        assertEquals("UninitializedNode_", nthChild(4, start3).getClass().getSimpleName());
+
+        for (Thread thread : threads) {
+            try {
+                thread.join();
+            } catch (InterruptedException e) {
+                fail("interrupted");
+            }
+        }
+    }
+
+    private static class Executions {
+        public final Object firstValue;
+        public final Object secondValue;
+        public final Object thirdValue;
+
+        public Executions(Object firstValue, Object secondValue, Object thirdValue) {
+            this.firstValue = firstValue;
+            this.secondValue = secondValue;
+            this.thirdValue = thirdValue;
+        }
+    }
+
+    private static void await(final CountDownLatch latch) {
+        try {
+            latch.await();
+        } catch (InterruptedException e) {
+            fail("interrupted");
+        }
+    }
+
+    private static Node firstChild(Node node) {
+        return node.getChildren().iterator().next();
+    }
+
+    private static Node nthChild(int n, Node node) {
+        if (n == 0) {
+            return node;
+        } else {
+            return nthChild(n - 1, firstChild(node));
+        }
+    }
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Sun Mar 08 21:58:34 2015 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Sun Mar 08 21:58:48 2015 +0100
@@ -36,11 +36,10 @@
 
     private final RootNode rootNode;
 
-    public DefaultCallTarget(RootNode function) {
+    protected DefaultCallTarget(RootNode function) {
         this.rootNode = function;
         this.rootNode.adoptChildren();
         this.rootNode.applyInstrumentation();
-        this.rootNode.setCallTarget(this);
     }
 
     @Override
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Sun Mar 08 21:58:34 2015 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Sun Mar 08 21:58:48 2015 +0100
@@ -55,6 +55,7 @@
     @Override
     public RootCallTarget createCallTarget(RootNode rootNode) {
         DefaultCallTarget target = new DefaultCallTarget(rootNode);
+        rootNode.setCallTarget(target);
         callTargets.put(target, null);
         return target;
     }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java	Sun Mar 08 21:58:34 2015 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java	Sun Mar 08 21:58:48 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -60,9 +60,12 @@
     String displayCallTargetName(CallTarget callTarget);
 
     /**
-     * Converts a value in the guest language to a display string.
+     * Converts a value in the guest language to a display string. If
+     *
+     * @param trim if {@code > 0}, them limit size of String to either the value of trim or the
+     *            number of characters in the first line, whichever is lower.
      */
-    String displayValue(ExecutionContext context, Object value);
+    String displayValue(ExecutionContext context, Object value, int trim);
 
     /**
      * Converts a slot identifier in the guest language to a display string.
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java	Sun Mar 08 21:58:34 2015 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java	Sun Mar 08 21:58:48 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -70,12 +70,34 @@
         return callTarget.toString();
     }
 
-    public String displayValue(ExecutionContext context, Object value) {
-        return value.toString();
+    public String displayValue(ExecutionContext context, Object value, int trim) {
+        return trim(value.toString(), trim);
     }
 
     public String displayIdentifier(FrameSlot slot) {
         return slot.getIdentifier().toString();
     }
 
+    /**
+     * Trims text if {@code trim > 0} to the shorter of {@code trim} or the length of the first line
+     * of test. Identity if {@code trim <= 0}.
+     */
+    protected String trim(String text, int trim) {
+        if (trim == 0) {
+            return text;
+        }
+        final String[] lines = text.split("\n");
+        String result = lines[0];
+        if (lines.length == 1) {
+            if (result.length() <= trim) {
+                return result;
+            }
+            if (trim <= 3) {
+                return result.substring(0, Math.min(result.length() - 1, trim - 1));
+            } else {
+                return result.substring(0, trim - 4) + "...";
+            }
+        }
+        return (result.length() < trim - 3 ? result : result.substring(0, trim - 4)) + "...";
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/PrimitiveValueProfile.java	Sun Mar 08 21:58:34 2015 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/PrimitiveValueProfile.java	Sun Mar 08 21:58:48 2015 +0100
@@ -175,11 +175,11 @@
     }
 
     public boolean isGeneric() {
-        return getCachedValue() == GENERIC;
+        return cachedValue == GENERIC;
     }
 
     public boolean isUninitialized() {
-        return getCachedValue() == UNINITIALIZED;
+        return cachedValue == UNINITIALIZED;
     }
 
     public Object getCachedValue() {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java	Sun Mar 08 21:58:34 2015 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java	Sun Mar 08 21:58:48 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -73,11 +73,11 @@
     }
 
     @Override
-    public String displayValue(ExecutionContext context, Object value) {
+    public String displayValue(ExecutionContext context, Object value, int trim) {
         if (value == SLNull.SINGLETON) {
             return "null";
         }
-        return value.toString();
+        return trim(value.toString(), trim);
     }
 
     @Override