# HG changeset patch # User Doug Simon # Date 1411736003 -7200 # Node ID 58f1d1335ef4c4d0976e42f32412e4b560a54b63 # Parent 627b11398fdd8e816cf5fadad10b13c1cb290670 force inline Fields.getObject(Object, int, Class) so that a constant value bound to its last parameter is connected with the DeferredPiNode used in Fields.getObject(Object, long, Class) diff -r 627b11398fdd -r 58f1d1335ef4 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/Fields.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/Fields.java Fri Sep 26 14:45:10 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/Fields.java Fri Sep 26 14:53:23 2014 +0200 @@ -120,7 +120,13 @@ return types[index]; } - private boolean checkAssignable(int index, Object value) { + /** + * Checks that a given field is assignable from a given value. + * + * @param index the index of the field to check + * @param value a value that will be assigned to the field + */ + private boolean checkAssignableFrom(int index, Object value) { assert value == null || getType(index).isAssignableFrom(value.getClass()) : String.format("%s.%s of type %s is not assignable from %s", clazz.getSimpleName(), getName(index), getType(index).getSimpleName(), value.getClass().getSimpleName()); return true; @@ -150,7 +156,7 @@ assert false : "unhandled property type: " + type; } } else { - assert checkAssignable(index, value); + assert checkAssignableFrom(index, value); unsafe.putObject(object, dataOffset, value); } } @@ -211,10 +217,23 @@ * * @param object the object whose field is to be read * @param index the index of the field (between 0 and {@link #getCount()}) + * @return the value of the specified field cast to {@code c} + */ + public Object getObject(Object object, int index) { + return getObject(object, offsets[index], Object.class); + } + + /** + * Gets the value of an object field and casts it to a given type. + * + * NOTE: All callers of this method should use a class literal for the last argument. + * + * @param object the object whose field is to be read + * @param index the index of the field (between 0 and {@link #getCount()}) * @param asType the type to which the returned object is cast * @return the value of the specified field cast to {@code c} */ - public T getObject(Object object, int index, Class asType) { + protected T getObject(Object object, int index, Class asType) { return getObject(object, offsets[index], asType); } @@ -230,12 +249,11 @@ * @param value the value to be written to the field */ protected void putObject(Object object, int index, Object value) { - assert checkAssignable(index, value); + assert checkAssignableFrom(index, value); putObject(object, offsets[index], value); } private static void putObject(Object object, long offset, Object value) { unsafe.putObject(object, offset, value); } - } diff -r 627b11398fdd -r 58f1d1335ef4 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Sep 26 14:45:10 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Sep 26 14:53:23 2014 +0200 @@ -284,7 +284,7 @@ * *
      *     if (node.getNodeClass().is(BeginNode.class)) { ... }
-     *
+     * 
      *     // Due to generated Node classes, the test below
      *     // is *not* the same as the test above:
      *     if (node.getClass() == BeginNode.class) { ... }
@@ -471,7 +471,7 @@
                         assert false : "unhandled property type: " + type;
                     }
                 } else {
-                    Object o = properties.getObject(n, i, Object.class);
+                    Object o = properties.getObject(n, i);
                     number += deepHashCode0(o);
                 }
                 number *= 13;
@@ -566,8 +566,8 @@
                     assert false : "unhandled type: " + type;
                 }
             } else {
-                Object objectA = properties.getObject(a, i, Object.class);
-                Object objectB = properties.getObject(b, i, Object.class);
+                Object objectA = properties.getObject(a, i);
+                Object objectB = properties.getObject(b, i);
                 if (objectA != objectB) {
                     if (objectA != null && objectB != null) {
                         if (!deepEquals0(objectA, objectB)) {
diff -r 627b11398fdd -r 58f1d1335ef4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeferredPiNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeferredPiNode.java	Fri Sep 26 14:45:10 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, 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.nodes;
-
-//JaCoCo Exclude
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.calc.*;
-
-/**
- * A node that changes the type of its input where the type is not immediately available at node
- * intrinsification time. It is replaced by a {@link PiNode} once the type becomes constant.
- */
-@NodeInfo
-public class DeferredPiNode extends FloatingNode implements Canonicalizable {
-
-    @Input ValueNode object;
-    @Input ValueNode type;
-
-    public ValueNode object() {
-        return object;
-    }
-
-    public static DeferredPiNode create(ValueNode type, ValueNode object) {
-        return USE_GENERATED_NODES ? new DeferredPiNodeGen(type, object) : new DeferredPiNode(type, object);
-    }
-
-    protected DeferredPiNode(ValueNode type, ValueNode object) {
-        super(StampFactory.object());
-        this.type = type;
-        this.object = object;
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (type.isConstant()) {
-            ResolvedJavaType javaType = tool.getConstantReflection().asJavaType(type.asConstant());
-            ObjectStamp objectStamp = (ObjectStamp) stamp();
-            return PiNode.create(object, javaType, objectStamp.isExactType(), objectStamp.nonNull());
-        }
-        return this;
-    }
-
-    @NodeIntrinsic
-    public static native  T piCast(Class type, Object object);
-}
diff -r 627b11398fdd -r 58f1d1335ef4 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java	Fri Sep 26 14:53:23 2014 +0200
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2013, 2014, 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 java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Edges.Type;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.common.inlining.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class EdgesTest extends GraalCompilerTest {
+
+    @NodeInfo
+    static class TestNode extends Node {
+        @Input NodeInputList itail;
+        @Input ConstantNode i1;
+        @Input FloatingNode i2;
+
+        public static TestNode create() {
+            return USE_GENERATED_NODES ? new EdgesTest_TestNodeGen() : new TestNode();
+        }
+    }
+
+    StructuredGraph graph = new StructuredGraph();
+    TestNode node;
+    ConstantNode i1;
+    ConstantNode i2;
+    ConstantNode i3;
+    ConstantNode i4;
+    Edges inputs;
+
+    public EdgesTest() {
+        node = TestNode.create();
+        i1 = ConstantNode.forInt(1, graph);
+        i2 = ConstantNode.forDouble(1.0d, graph);
+        i3 = ConstantNode.forInt(4, graph);
+        i4 = ConstantNode.forInt(14, graph);
+        node.itail = new NodeInputList<>(node, new ValueNode[]{i3, i4});
+        node.i1 = i1;
+        node.i2 = i2;
+        graph.add(node);
+        inputs = node.getNodeClass().getEdges(Type.Inputs);
+    }
+
+    /**
+     * Checks that there are no checkcasts in {@link Edges#getNode(Node, int)}
+     */
+    @Test
+    public void test0() {
+        testMethod(getMethod("getNode", Node.class, int.class), inputs, node, 0);
+    }
+
+    /**
+     * Checks that there are no checkcasts in {@link Edges#getNodeList(Node, int)}
+     */
+    @Test
+    public void test1() {
+        testMethod(getMethod("getNodeList", Node.class, int.class), inputs, node, 2);
+    }
+
+    /**
+     * Checks that there are no checkcasts in {@link Edges#setNode(Node, int, Node)}
+     */
+    @Test
+    public void test2() {
+        testMethod(getMethod("setNode", Node.class, int.class, Node.class), inputs, node, 1, i2);
+    }
+
+    private void testMethod(Method method, Object receiver, Object... args) {
+        try {
+            // Invoke the method to ensure it has a type profile
+            for (int i = 0; i < 5000; i++) {
+                method.invoke(receiver, args);
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        StructuredGraph g = parseProfiled(method);
+        Assumptions assumptions = new Assumptions(false);
+        HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(g, context);
+        new CanonicalizerPhase(false).apply(g, context);
+        Assert.assertTrue(g.getNodes().filter(CheckCastNode.class).isEmpty());
+    }
+
+    private static Method getMethod(final String name, Class... parameters) {
+        try {
+            return Edges.class.getDeclaredMethod(name, parameters);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff -r 627b11398fdd -r 58f1d1335ef4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/FieldsSubstitutions.java
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/FieldsSubstitutions.java	Fri Sep 26 14:45:10 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/FieldsSubstitutions.java	Fri Sep 26 14:53:23 2014 +0200
@@ -25,8 +25,10 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.replacements.nodes.*;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
 /**
  * Substitutions for improving the performance of some critical methods in {@link Fields}. These
@@ -38,6 +40,16 @@
 @ClassSubstitution(Fields.class)
 public class FieldsSubstitutions {
 
+    /**
+     * This substitution exists to force inline {@link Fields#getObject(Object, int, Class)}.
+     */
+    @SuppressWarnings("javadoc")
+    @SuppressFBWarnings
+    @MethodSubstitution(isStatic = false)
+    private static  T getObject(Fields thisObj, Object object, int index, Class asType) {
+        return getObject(thisObj, object, index, asType);
+    }
+
     @MethodSubstitution
     private static  T getObject(Object object, long offset, Class c) {
         return DeferredPiNode.piCast(c, UnsafeLoadNode.load(object, offset, Kind.Object, LocationIdentity.ANY_LOCATION));
diff -r 627b11398fdd -r 58f1d1335ef4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java	Fri Sep 26 14:53:23 2014 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2013, 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.nodes;
+
+//JaCoCo Exclude
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.replacements.*;
+
+/**
+ * A node for use in method substitutions or snippets that changes the type of its input where the
+ * type is not immediately available at {@link NodeIntrinsificationPhase intrinsification} time. It
+ * is replaced by a {@link PiNode} once the type becomes constant (which must happen).
+ */
+@NodeInfo
+public class DeferredPiNode extends FloatingNode implements Canonicalizable {
+
+    @Input ValueNode object;
+    @Input ValueNode type;
+
+    public ValueNode object() {
+        return object;
+    }
+
+    public static DeferredPiNode create(ValueNode type, ValueNode object) {
+        return USE_GENERATED_NODES ? new DeferredPiNodeGen(type, object) : new DeferredPiNode(type, object);
+    }
+
+    protected DeferredPiNode(ValueNode type, ValueNode object) {
+        super(StampFactory.object());
+        this.type = type;
+        this.object = object;
+    }
+
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        if (type.isConstant()) {
+            ResolvedJavaType javaType = tool.getConstantReflection().asJavaType(type.asConstant());
+            ObjectStamp objectStamp = (ObjectStamp) stamp();
+            return PiNode.create(object, javaType, objectStamp.isExactType(), objectStamp.nonNull());
+        }
+        return this;
+    }
+
+    @NodeIntrinsic
+    public static native  T piCast(Class type, Object object);
+}