Mercurial > hg > graal-compiler
changeset 17230:58f1d1335ef4
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)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Fri, 26 Sep 2014 14:53:23 +0200 |
parents | 627b11398fdd |
children | be6f5fad74c6 |
files | graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/Fields.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeferredPiNode.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/FieldsSubstitutions.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java |
diffstat | 6 files changed, 238 insertions(+), 80 deletions(-) [+] |
line wrap: on
line diff
--- 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> T getObject(Object object, int index, Class<T> asType) { + protected <T> T getObject(Object object, int index, Class<T> 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); } - }
--- 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 @@ * * <pre> * 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)) {
--- 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> T piCast(Class<T> type, Object object); -}
--- /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<ValueNode> 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); + } + } +}
--- 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> T getObject(Fields thisObj, Object object, int index, Class<T> asType) { + return getObject(thisObj, object, index, asType); + } + @MethodSubstitution private static <T> T getObject(Object object, long offset, Class<T> c) { return DeferredPiNode.piCast(c, UnsafeLoadNode.load(object, offset, Kind.Object, LocationIdentity.ANY_LOCATION));
--- /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 <b>must</b> 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> T piCast(Class<T> type, Object object); +}