# HG changeset patch # User Doug Simon # Date 1427386000 -3600 # Node ID 01290be48def5da7c6b4614eea9399aa2dc1925b # Parent f137f1974f60d8b72d388f3e460947dbef3f885f# Parent 66dbc66d560908237dbbb476aa638bf3facb5fe0 Merge. diff -r f137f1974f60 -r 01290be48def graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Thu Mar 26 17:06:08 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Thu Mar 26 17:06:40 2015 +0100 @@ -70,7 +70,7 @@ plugins.setLoadFieldPlugin(new HotSpotLoadFieldPlugin(metaAccess, constantReflection)); plugins.setLoadIndexedPlugin(new HotSpotLoadIndexedPlugin(wordTypes)); plugins.setInlineInvokePlugin(new DefaultInlineInvokePlugin(replacements)); - plugins.setGenericInvocationPlugin(new DefaultGenericInvocationPlugin(nodeIntrinsification, wordOperationPlugin)); + plugins.setGenericInvocationPlugin(new DefaultGenericInvocationPlugin(metaAccess, nodeIntrinsification, wordOperationPlugin)); registerObjectPlugins(invocationPlugins); registerSystemPlugins(invocationPlugins, foreignCalls); diff -r f137f1974f60 -r 01290be48def graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/StructuralInput.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/StructuralInput.java Thu Mar 26 17:06:40 2015 +0100 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2015, 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.graal.nodeinfo; + +import java.lang.annotation.*; + +/** + * Marker type for describing node inputs in snippets that are not of type {@link InputType#Value}. + */ +public abstract class StructuralInput { + + private StructuralInput() { + throw new Error("Illegal instance of StructuralInput. This class should be used in snippets only."); + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface MarkerType { + InputType value(); + } + + /** + * Marker type for {@link InputType#Memory} edges in snippets. + */ + @MarkerType(InputType.Memory) + public abstract static class Memory extends StructuralInput { + } + + /** + * Marker type for {@link InputType#Condition} edges in snippets. + */ + @MarkerType(InputType.Condition) + public abstract static class Condition extends StructuralInput { + } + + /** + * Marker type for {@link InputType#State} edges in snippets. + */ + @MarkerType(InputType.State) + public abstract static class State extends StructuralInput { + } + + /** + * Marker type for {@link InputType#Guard} edges in snippets. + */ + @MarkerType(InputType.Guard) + public abstract static class Guard extends StructuralInput { + } + + /** + * Marker type for {@link InputType#Anchor} edges in snippets. + */ + @MarkerType(InputType.Anchor) + public abstract static class Anchor extends StructuralInput { + } + + /** + * Marker type for {@link InputType#Association} edges in snippets. + */ + @MarkerType(InputType.Association) + public abstract static class Association extends StructuralInput { + } + + /** + * Marker type for {@link InputType#Extension} edges in snippets. + */ + @MarkerType(InputType.Extension) + public abstract static class Extension extends StructuralInput { + } +} diff -r f137f1974f60 -r 01290be48def graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAnchorNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAnchorNode.java Thu Mar 26 17:06:40 2015 +0100 @@ -0,0 +1,53 @@ +/* + * 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 + * 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.extended; + +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.nodeinfo.StructuralInput.Memory; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +@NodeInfo(allowedUsageTypes = {InputType.Memory}) +public final class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode, Canonicalizable { + + public static final NodeClass TYPE = NodeClass.create(MemoryAnchorNode.class); + + public MemoryAnchorNode() { + super(TYPE, StampFactory.forVoid()); + } + + public void generate(NodeLIRBuilderTool generator) { + // Nothing to emit, since this node is used for structural purposes only. + } + + @Override + public Node canonical(CanonicalizerTool tool) { + return hasNoUsages() ? null : this; + } + + @NodeIntrinsic + public static native Memory anchor(); +} diff -r f137f1974f60 -r 01290be48def graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Thu Mar 26 17:06:08 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Thu Mar 26 17:06:40 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -255,6 +255,11 @@ @Override protected MemoryMapImpl processNode(FixedNode node, MemoryMapImpl state) { + if (node instanceof MemoryAnchorNode) { + processAnchor((MemoryAnchorNode) node, state); + return state; + } + if (node instanceof MemoryAccess) { processAccess((MemoryAccess) node, state); } @@ -274,6 +279,28 @@ return state; } + /** + * Improve the memory graph by re-wiring all usages of a {@link MemoryAnchorNode} to the + * real last access location. + */ + private static void processAnchor(MemoryAnchorNode anchor, MemoryMapImpl state) { + for (Node node : anchor.usages().snapshot()) { + if (node instanceof MemoryAccess) { + MemoryAccess access = (MemoryAccess) node; + if (access.getLastLocationAccess() == anchor) { + MemoryNode lastLocationAccess = state.getLastLocationAccess(access.getLocationIdentity()); + if (lastLocationAccess != null) { + access.setLastLocationAccess(lastLocationAccess); + } + } + } + } + + if (anchor.hasNoUsages()) { + anchor.graph().removeFixed(anchor); + } + } + private static void processAccess(MemoryAccess access, MemoryMapImpl state) { LocationIdentity locationIdentity = access.getLocationIdentity(); if (!locationIdentity.equals(LocationIdentity.any())) { diff -r f137f1974f60 -r 01290be48def graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/SubstitutionsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/SubstitutionsTest.java Thu Mar 26 17:06:40 2015 +0100 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2015, 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.graal.replacements.test; + +import static com.oracle.graal.nodeinfo.InputType.*; +import static org.hamcrest.CoreMatchers.*; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodeinfo.StructuralInput.Guard; +import com.oracle.graal.nodeinfo.StructuralInput.Memory; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; + +public class SubstitutionsTest extends GraalCompilerTest { + + @NodeInfo(allowedUsageTypes = {Memory}) + private static class TestMemory extends FixedWithNextNode implements MemoryNode { + private static final NodeClass TYPE = NodeClass.create(TestMemory.class); + + public TestMemory() { + super(TYPE, StampFactory.forVoid()); + } + + @NodeIntrinsic + public static native Memory memory(); + } + + @NodeInfo(allowedUsageTypes = {Guard}) + private static class TestGuard extends FloatingNode implements GuardingNode { + private static final NodeClass TYPE = NodeClass.create(TestGuard.class); + + @Input(Memory) MemoryNode memory; + + public TestGuard(ValueNode memory) { + super(TYPE, StampFactory.forVoid()); + this.memory = (MemoryNode) memory; + } + + @NodeIntrinsic + public static native Guard guard(Memory memory); + } + + @NodeInfo + private static class TestValue extends FloatingNode { + private static final NodeClass TYPE = NodeClass.create(TestValue.class); + + @Input(Guard) GuardingNode guard; + + public TestValue(ValueNode guard) { + super(TYPE, StampFactory.forKind(Kind.Int)); + this.guard = (GuardingNode) guard; + } + + @NodeIntrinsic + public static native int value(Guard guard); + } + + private static class TestMethod { + + public static int test() { + return 42; + } + } + + @ClassSubstitution(TestMethod.class) + private static class TestMethodSubstitution { + + @MethodSubstitution + public static int test() { + Memory memory = TestMemory.memory(); + Guard guard = TestGuard.guard(memory); + return TestValue.value(guard); + } + } + + private static boolean substitutionsInstalled; + + public SubstitutionsTest() { + if (!substitutionsInstalled) { + getProviders().getReplacements().registerSubstitutions(TestMethod.class, TestMethodSubstitution.class); + substitutionsInstalled = true; + } + } + + public static int callTest() { + return TestMethod.test(); + } + + @Override + protected boolean checkHighTierGraph(StructuredGraph graph) { + // Check that the graph contains the expected test nodes. + NodeIterable retNodes = graph.getNodes().filter(ReturnNode.class); + Assert.assertTrue("expected exactly one ReturnNode", retNodes.count() == 1); + ReturnNode ret = retNodes.first(); + + Assert.assertThat(ret.result(), instanceOf(TestValue.class)); + TestValue value = (TestValue) ret.result(); + + Assert.assertThat(value.guard, instanceOf(TestGuard.class)); + TestGuard guard = (TestGuard) value.guard; + + Assert.assertThat(guard.memory, instanceOf(TestMemory.class)); + TestMemory memory = (TestMemory) guard.memory; + + // Remove the test nodes, replacing them by the constant 42. + // This implicitly makes sure that the rest of the graph is valid. + ret.replaceFirstInput(value, graph.unique(ConstantNode.forInt(42))); + value.safeDelete(); + guard.safeDelete(); + graph.removeFixed(memory); + + return true; + } + + @Test + public void snippetTest() { + test("callTest"); + } +} diff -r f137f1974f60 -r 01290be48def graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java --- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Thu Mar 26 17:06:08 2015 +0100 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Thu Mar 26 17:06:40 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 @@ -34,6 +34,8 @@ import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.InjectedNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodeinfo.StructuralInput.MarkerType; public final class NodeIntrinsicVerifier extends AbstractVerifier { @@ -55,6 +57,10 @@ return env.getElementUtils().getTypeElement("com.oracle.graal.api.meta.ResolvedJavaType").asType(); } + private TypeMirror structuralInputType() { + return env.getElementUtils().getTypeElement("com.oracle.graal.nodeinfo.StructuralInput").asType(); + } + public NodeIntrinsicVerifier(ProcessingEnvironment env) { super(env); } @@ -100,6 +106,11 @@ if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) { env.getMessager().printMessage(Kind.ERROR, String.format("Cannot make @NodeIntrinsic for abstract node class %s.", nodeClass.getSimpleName()), element, annotation); } else { + TypeMirror ret = intrinsicMethod.getReturnType(); + if (env.getTypeUtils().isAssignable(ret, structuralInputType())) { + checkInputType(nodeClass, ret, element, annotation); + } + TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod); findConstructor(nodeClass, constructorSignature, intrinsicMethod, annotation); } @@ -108,6 +119,39 @@ } } + private void checkInputType(TypeElement nodeClass, TypeMirror returnType, Element element, AnnotationMirror annotation) { + InputType inputType = getInputType(returnType, element, annotation); + if (inputType != InputType.Value) { + boolean allowed = false; + InputType[] allowedTypes = nodeClass.getAnnotation(NodeInfo.class).allowedUsageTypes(); + for (InputType allowedType : allowedTypes) { + if (inputType == allowedType) { + allowed = true; + break; + } + } + if (!allowed) { + env.getMessager().printMessage(Kind.ERROR, String.format("@NodeIntrinsic returns input type %s, but only %s is allowed.", inputType, Arrays.toString(allowedTypes)), element, + annotation); + } + } + } + + private InputType getInputType(TypeMirror type, Element element, AnnotationMirror annotation) { + TypeElement current = (TypeElement) env.getTypeUtils().asElement(type); + while (current != null) { + MarkerType markerType = current.getAnnotation(MarkerType.class); + if (markerType != null) { + return markerType.value(); + } + + current = (TypeElement) env.getTypeUtils().asElement(current.getSuperclass()); + } + + env.getMessager().printMessage(Kind.ERROR, String.format("The class %s is a subclass of StructuralInput, but isn't annotated with @MarkerType.", type), element, annotation); + return InputType.Value; + } + private boolean isNodeType(TypeElement nodeClass) { return env.getTypeUtils().isSubtype(nodeClass.asType(), nodeType()); } diff -r f137f1974f60 -r 01290be48def graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java Thu Mar 26 17:06:08 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java Thu Mar 26 17:06:40 2015 +0100 @@ -29,9 +29,12 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.graphbuilderconf.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodeinfo.StructuralInput.MarkerType; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.word.*; @@ -44,9 +47,13 @@ protected final NodeIntrinsificationPhase nodeIntrinsification; protected final WordOperationPlugin wordOperationPlugin; - public DefaultGenericInvocationPlugin(NodeIntrinsificationPhase nodeIntrinsification, WordOperationPlugin wordOperationPlugin) { + private final ResolvedJavaType structuralInputType; + + public DefaultGenericInvocationPlugin(MetaAccessProvider metaAccess, NodeIntrinsificationPhase nodeIntrinsification, WordOperationPlugin wordOperationPlugin) { this.nodeIntrinsification = nodeIntrinsification; this.wordOperationPlugin = wordOperationPlugin; + + this.structuralInputType = metaAccess.lookupJavaType(StructuralInput.class); } public boolean apply(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { @@ -91,6 +98,24 @@ return false; } + private InputType getInputType(ObjectStamp stamp) { + ResolvedJavaType type = stamp.type(); + if (type != null && structuralInputType.isAssignableFrom(type)) { + while (type != null) { + MarkerType markerType = type.getAnnotation(MarkerType.class); + if (markerType != null) { + return markerType.value(); + } + + type = type.getSuperclass(); + } + + throw GraalInternalError.shouldNotReachHere(String.format("%s extends StructuralInput, but is not annotated with @MarkerType", stamp.type())); + } else { + return InputType.Value; + } + } + protected boolean processNodeIntrinsic(GraphBuilderContext b, ResolvedJavaMethod method, NodeIntrinsic intrinsic, List args, Kind returnKind, Stamp stamp) { ValueNode res = createNodeIntrinsic(b, method, intrinsic, args, stamp); if (res == null) { @@ -107,7 +132,16 @@ } res = b.append(res); - if (returnKind != Kind.Void) { + + InputType inputType = InputType.Value; + if (returnKind == Kind.Object && stamp instanceof ObjectStamp) { + inputType = getInputType((ObjectStamp) stamp); + } + + if (inputType != InputType.Value) { + assert res.isAllowedUsageType(inputType); + b.push(Kind.Object, res); + } else if (returnKind != Kind.Void) { assert res.getKind().getStackKind() != Kind.Void; b.push(returnKind.getStackKind(), res); } else { diff -r f137f1974f60 -r 01290be48def graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java Thu Mar 26 17:06:08 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * 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 - * 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; - -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.extended.*; -import com.oracle.graal.nodes.spi.*; - -@NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode, Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(MemoryAnchorNode.class); - - public MemoryAnchorNode() { - super(TYPE, StampFactory.forVoid()); - } - - public void generate(NodeLIRBuilderTool generator) { - // Nothing to emit, since this node is used for structural purposes only. - } - - @Override - public Node canonical(CanonicalizerTool tool) { - return hasNoUsages() ? null : this; - } -}