Mercurial > hg > graal-compiler
view graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java @ 5760:87e8baf5447c
added snippets for lowering array creation and initialization (in NewObjectSnippets)
made it possible to use node intrinsics with arguments that may only be constant when a snippet template is created
rename: NewTypeArrayNode -> NewPrimitiveArrayNode
removed HotSpotVMConfig.getArrayOffset() - Kind.arrayBaseOffset() is used instead
renamed field prototypeHeader to initialMarkWord in HotSpotResolvedJavaType
rename: NewInstanceSnippets -> NewObjectSnippets
renamed node intrinsics in DirectObjectStoreNode to include the type of the value being stored (to avoid accidental misuse)
extended WordTypeRewriterPhase such that ObjectEqualsNodes are replaced with IntegerEqualsNodes when the values being compared are words (which allows '==' and '!=' to be used between Word values in Java source code)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Tue, 03 Jul 2012 23:49:01 +0200 |
parents | 0ca242de9383 |
children | a3d71693e0ce |
line wrap: on
line source
/* * Copyright (c) 2012, 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.snippets; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.snippets.Word.Opcode; import com.oracle.graal.snippets.Word.Operation; /** * Transforms all uses of the {@link Word} class into unsigned * operations on {@code int} or {@code long} values, depending * on the word kind of the underlying platform. */ public class WordTypeRewriterPhase extends Phase { private final Kind wordKind; private final ResolvedJavaType wordType; public WordTypeRewriterPhase(Kind wordKind, ResolvedJavaType wordType) { this.wordKind = wordKind; this.wordType = wordType; } @Override protected void run(StructuredGraph graph) { for (Node n : graph.getNodes()) { if (n instanceof ValueNode) { ValueNode valueNode = (ValueNode) n; if (isWord(valueNode)) { changeToWord(valueNode); } } } // Remove unnecessary/redundant unsafe casts for (UnsafeCastNode unsafeCastNode : graph.getNodes().filter(UnsafeCastNode.class).snapshot()) { if (!unsafeCastNode.isDeleted() && unsafeCastNode.object().stamp() == unsafeCastNode.stamp()) { graph.replaceFloating(unsafeCastNode, unsafeCastNode.object()); } } // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words for (ObjectEqualsNode objectEqualsNode : graph.getNodes().filter(ObjectEqualsNode.class).snapshot()) { ValueNode x = objectEqualsNode.x(); ValueNode y = objectEqualsNode.y(); if (x.kind() == wordKind || y.kind() == wordKind) { assert x.kind() == wordKind; assert y.kind() == wordKind; graph.replaceFloating(objectEqualsNode, graph.unique(new IntegerEqualsNode(x, y))); } } for (MethodCallTargetNode callTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) { ResolvedJavaMethod targetMethod = callTargetNode.targetMethod(); Operation operation = targetMethod.getAnnotation(Word.Operation.class); if (operation != null) { NodeInputList<ValueNode> arguments = callTargetNode.arguments(); Invoke invoke = (Invoke) callTargetNode.usages().first(); assert invoke != null : callTargetNode.targetMethod(); Opcode opcode = operation.value(); switch (opcode) { case ZERO: { assert arguments.size() == 0; invoke.intrinsify(wordKind.isLong() ? ConstantNode.forLong(0L, graph) : ConstantNode.forInt(0, graph)); break; } case ABOVE: { assert arguments.size() == 2; invoke.intrinsify(compare(Condition.AT, graph, arguments.first(), arguments.last())); break; } case ABOVE_EQUAL: { assert arguments.size() == 2; invoke.intrinsify(compare(Condition.AE, graph, arguments.first(), arguments.last())); break; } case BELOW: { assert arguments.size() == 2; invoke.intrinsify(compare(Condition.BT, graph, arguments.first(), arguments.last())); break; } case BELOW_EQUAL: { assert arguments.size() == 2; invoke.intrinsify(compare(Condition.BE, graph, arguments.first(), arguments.last())); break; } case PLUS: { ValueNode addend = asWordKind(graph, arguments.last()); IntegerAddNode op = graph.unique(new IntegerAddNode(wordKind, arguments.first(), addend)); invoke.intrinsify(op); break; } case W2A: { assert arguments.size() == 1; ValueNode value = arguments.first(); ResolvedJavaType targetType = (ResolvedJavaType) targetMethod.signature().returnType(targetMethod.holder()); UnsafeCastNode cast = graph.unique(new UnsafeCastNode(value, targetType)); invoke.intrinsify(cast); break; } case W2I: { assert arguments.size() == 1; ValueNode value = arguments.first(); ValueNode intValue = fromWordKindTo(graph, value, Kind.Int); invoke.intrinsify(intValue); break; } case W2L: { assert arguments.size() == 1; ValueNode value = arguments.first(); ValueNode longValue = fromWordKindTo(graph, value, Kind.Long); invoke.intrinsify(longValue); break; } case A2W: { assert arguments.size() == 1; ValueNode value = arguments.first(); assert value.kind() == Kind.Object : value + ", " + targetMethod; UnsafeCastNode cast = graph.unique(new UnsafeCastNode(value, wordType)); invoke.intrinsify(cast); break; } case L2W: { assert arguments.size() == 1; ValueNode value = arguments.first(); assert value.kind() == Kind.Long; ValueNode wordValue = asWordKind(graph, value); invoke.intrinsify(wordValue); break; } case I2W: { assert arguments.size() == 1; ValueNode value = arguments.first(); assert value.kind() == Kind.Int; invoke.intrinsify(asWordKind(graph, value)); break; } default: { throw new GraalInternalError("Unknown opcode: %s", opcode); } } } } } /** * Creates comparison node for a given condition and two input values. */ private ValueNode compare(Condition condition, StructuredGraph graph, ValueNode left, ValueNode right) { assert condition.isUnsigned() : condition; assert left.kind() == wordKind; assert right.kind() == wordKind; // mirroring gets the condition into canonical form boolean mirror = condition.canonicalMirror(); ValueNode a = mirror ? right : left; ValueNode b = mirror ? left : right; MaterializeNode materialize = MaterializeNode.create(graph.unique(new IntegerBelowThanNode(a, b)), graph); ValueNode op; if (condition.canonicalNegate()) { op = (ValueNode) materialize.negate(); } else { op = materialize; } return op; } /** * Adds a node if necessary to convert a given value into the word kind. * * @return the node for {@code value} producing a value of word kind */ private ValueNode asWordKind(StructuredGraph graph, ValueNode value) { if (value.kind() != wordKind) { Op op; if (wordKind.isLong()) { assert value.kind().isInt(); op = Op.I2L; } else { assert wordKind.isInt(); assert value.kind().isLong(); op = Op.L2I; } return graph.unique(new ConvertNode(op, value)); } return value; } private static ValueNode fromWordKindTo(StructuredGraph graph, ValueNode value, Kind to) { Kind from = value.kind(); if (from != to) { Op op; if (from.isLong()) { op = Op.L2I; } else { assert from.isInt(); op = Op.I2L; } return graph.unique(new ConvertNode(op, value)); } return value; } public static boolean isWord(ValueNode node) { if (node.kind().isObject()) { return isWord(node.objectStamp().type()); } return false; } public static boolean isWord(ResolvedJavaType type) { if (type != null && type.toJava() == Word.class) { return true; } return false; } private void changeToWord(ValueNode valueNode) { assert !(valueNode instanceof ConstantNode); valueNode.setStamp(StampFactory.forKind(wordKind)); // Propagate word kind. for (Node n : valueNode.usages()) { if (n instanceof PhiNode) { changeToWord((ValueNode) n); PhiNode phi = (PhiNode) n; assert phi.type() == PhiType.Value; } else if (n instanceof ReturnNode) { changeToWord((ValueNode) n); } } } }