# HG changeset patch # User Andreas Woess # Date 1379006548 -7200 # Node ID 3f706be38bf913b468182523afde7c5b53c9da68 # Parent 57674ff0f7e2f32686122688ef7eff8c833a5f4c Truffle: compilation final array support. diff -r 57674ff0f7e2 -r 3f706be38bf9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Sep 12 19:01:40 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Sep 12 19:22:28 2013 +0200 @@ -66,7 +66,6 @@ public class PartialEvaluator { private final MetaAccessProvider metaAccessProvider; - private final ResolvedJavaType nodeClass; private final ResolvedJavaMethod executeHelperMethod; private final CanonicalizerPhase canonicalizer; private final ResolvedJavaType[] skippedExceptionTypes; @@ -77,8 +76,7 @@ public PartialEvaluator(MetaAccessProvider metaAccessProvider, Replacements replacements, TruffleCache truffleCache) { this.metaAccessProvider = metaAccessProvider; - this.nodeClass = metaAccessProvider.lookupJavaType(com.oracle.truffle.api.nodes.Node.class); - CustomCanonicalizer customCanonicalizer = new PartialEvaluatorCanonicalizer(metaAccessProvider, nodeClass); + CustomCanonicalizer customCanonicalizer = new PartialEvaluatorCanonicalizer(metaAccessProvider); this.canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue(), customCanonicalizer); this.skippedExceptionTypes = TruffleCompilerImpl.getSkippedExceptionTypes(metaAccessProvider); this.replacements = replacements; diff -r 57674ff0f7e2 -r 3f706be38bf9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Thu Sep 12 19:01:40 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Thu Sep 12 19:22:28 2013 +0200 @@ -27,7 +27,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.Node.Child; @@ -35,40 +34,30 @@ final class PartialEvaluatorCanonicalizer implements CanonicalizerPhase.CustomCanonicalizer { private final MetaAccessProvider metaAccessProvider; - private final ResolvedJavaType nodeClass; - PartialEvaluatorCanonicalizer(MetaAccessProvider metaAccessProvider, ResolvedJavaType nodeClass) { + PartialEvaluatorCanonicalizer(MetaAccessProvider metaAccessProvider) { this.metaAccessProvider = metaAccessProvider; - this.nodeClass = nodeClass; } @Override public ValueNode canonicalize(ValueNode node) { if (node instanceof LoadFieldNode) { LoadFieldNode loadFieldNode = (LoadFieldNode) node; - if (!loadFieldNode.isStatic() && - loadFieldNode.object().isConstant() && - !loadFieldNode.object().isNullConstant() && - ((loadFieldNode.kind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) || Modifier.isFinal(loadFieldNode.field().getModifiers()) || loadFieldNode.field().getAnnotation( - CompilerDirectives.CompilationFinal.class) != null)) { - Constant constant = loadFieldNode.field().readValue(loadFieldNode.object().asConstant()); - return ConstantNode.forConstant(constant, metaAccessProvider, node.graph()); - } - } else if (node instanceof LoadIndexedNode) { - LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node; - Stamp stamp = loadIndexedNode.array().stamp(); - if (stamp.kind() == Kind.Object && loadIndexedNode.array().isConstant() && !loadIndexedNode.array().isNullConstant() && loadIndexedNode.index().isConstant()) { - ObjectStamp objectStamp = (ObjectStamp) stamp; - ResolvedJavaType type = objectStamp.type(); - if (type != null && type.isArray() && this.nodeClass.isAssignableFrom(type.getComponentType())) { - Object array = loadIndexedNode.array().asConstant().asObject(); - int index = loadIndexedNode.index().asConstant().asInt(); - Object value = Array.get(array, index); - return ConstantNode.forObject(value, metaAccessProvider, node.graph()); + if (!loadFieldNode.isStatic() && loadFieldNode.object().isConstant() && !loadFieldNode.object().isNullConstant()) { + if (Modifier.isFinal(loadFieldNode.field().getModifiers()) || (loadFieldNode.kind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) || + loadFieldNode.field().getAnnotation(CompilerDirectives.CompilationFinal.class) != null) { + Constant constant = loadFieldNode.field().readValue(loadFieldNode.object().asConstant()); + assert verifyFieldValue(loadFieldNode.field(), constant); + return ConstantNode.forConstant(constant, metaAccessProvider, node.graph()); } } } return node; } + + private static boolean verifyFieldValue(ResolvedJavaField field, Constant constant) { + assert field.getAnnotation(Child.class) == null || constant.isNull() || constant.asObject() instanceof com.oracle.truffle.api.nodes.Node : "@Child field value must be a Node: " + field; + return true; + } } diff -r 57674ff0f7e2 -r 3f706be38bf9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Thu Sep 12 19:01:40 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Thu Sep 12 19:22:28 2013 +0200 @@ -180,6 +180,8 @@ private static void contractGraph(StructuredGraph newGraph, ConditionalEliminationPhase conditionalEliminationPhase, ConvertDeoptimizeToGuardPhase convertDeoptimizeToGuardPhase, CanonicalizerPhase canonicalizerPhase, EarlyReadEliminationPhase readEliminationPhase, PhaseContext context) { + new ReplaceLoadFinalPhase().apply(newGraph); + // Canonicalize / constant propagate. canonicalizerPhase.apply(newGraph, context); diff -r 57674ff0f7e2 -r 3f706be38bf9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java Thu Sep 12 19:22:28 2013 +0200 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 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.truffle.nodes; + +import java.lang.reflect.*; + +import sun.misc.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * @see LoadIndexedNode + */ +public final class LoadIndexedFinalNode extends AccessIndexedNode implements Canonicalizable { + + /** + * Creates a new {@link LoadIndexedFinalNode}. + * + * @param array the instruction producing the array + * @param index the instruction producing the index + * @param elementKind the element type + */ + public LoadIndexedFinalNode(ValueNode array, ValueNode index, Kind elementKind) { + super(createStamp(array, elementKind), array, index, elementKind); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (array().isConstant() && !array().isNullConstant() && index().isConstant()) { + Object array = array().asConstant().asObject(); + long index = index().asConstant().asLong(); + if (index >= 0 && index < Array.getLength(array)) { + int arrayBaseOffset = Unsafe.getUnsafe().arrayBaseOffset(array.getClass()); + int arrayIndexScale = Unsafe.getUnsafe().arrayIndexScale(array.getClass()); + Constant constant = tool.runtime().readUnsafeConstant(elementKind(), array, arrayBaseOffset + index * arrayIndexScale, elementKind() == Kind.Object); + return ConstantNode.forConstant(constant, tool.runtime(), graph()); + } + } + return this; + } + + private static Stamp createStamp(ValueNode array, Kind kind) { + ResolvedJavaType type = ObjectStamp.typeOrNull(array); + if (kind == Kind.Object && type != null) { + return StampFactory.declared(type.getComponentType()); + } else { + return StampFactory.forKind(kind); + } + } + + @Override + public boolean inferStamp() { + return updateStamp(createStamp(array(), elementKind())); + } + + @Override + public void lower(LoweringTool tool) { + LoadIndexedNode loadIndexedNode = graph().add(new LoadIndexedNode(array(), index(), elementKind())); + graph().replaceFixedWithFixed(this, loadIndexedNode); + loadIndexedNode.lower(tool); + } +} diff -r 57674ff0f7e2 -r 3f706be38bf9 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceLoadFinalPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceLoadFinalPhase.java Thu Sep 12 19:22:28 2013 +0200 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 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.truffle.phases; + +import java.lang.reflect.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.Node.Children; + +public class ReplaceLoadFinalPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + for (LoadIndexedNode loadIndexedNode : graph.getNodes(LoadIndexedNode.class)) { + if (loadIndexedNode.array() instanceof LoadFieldNode) { + LoadFieldNode loadFieldNode = (LoadFieldNode) loadIndexedNode.array(); + if (!loadFieldNode.isStatic() && isCompilationFinal(loadFieldNode.field())) { + graph.replaceFixedWithFixed(loadIndexedNode, graph.add(new LoadIndexedFinalNode(loadIndexedNode.array(), loadIndexedNode.index(), loadIndexedNode.elementKind()))); + } + } + } + } + + private static boolean isCompilationFinal(ResolvedJavaField field) { + assert (field.getAnnotation(Children.class) == null && field.getAnnotation(CompilerDirectives.CompilationFinal.class) == null) || Modifier.isFinal(field.getModifiers()) : "field needs to be declared as final"; + return Modifier.isFinal(field.getModifiers()) && (field.getAnnotation(Children.class) != null || field.getAnnotation(CompilerDirectives.CompilationFinal.class) != null); + } +}