# HG changeset patch # User Lukas Stadler # Date 1340208770 -7200 # Node ID 13166af0809ee4d2b7819ef86f31b5f991b10dfa # Parent 28dea025b221f53d02b39bbd6f1a2b392b540d13 added TypeSwitchNode for polymorphic inlining diff -r 28dea025b221 -r 13166af0809e graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Jun 20 16:59:43 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Jun 20 18:12:50 2012 +0200 @@ -1029,6 +1029,17 @@ } @Override + public void emitTypeSwitch(TypeSwitchNode x) { + Variable tag = load(operand(x.value())); + int len = x.numberOfCases(); + for (int i = 0; i < len; i++) { + ResolvedJavaType type = x.keyAt(i); + emitBranch(tag, type.getEncoding(Representation.ObjectHub), Condition.EQ, false, getLIRBlock(x.blockSuccessor(i)), null); + } + emitJump(getLIRBlock(x.defaultSuccessor()), null); + } + + @Override public void emitTableSwitch(TableSwitchNode x) { Variable value = load(operand(x.value())); // TODO: tune the defaults for the controls used to determine what kind of translation to use diff -r 28dea025b221 -r 13166af0809e graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Wed Jun 20 16:59:43 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Wed Jun 20 18:12:50 2012 +0200 @@ -398,41 +398,28 @@ private FixedNode createDispatchOnType(StructuredGraph graph, ReadHubNode objectClassNode, BeginNode[] calleeEntryNodes, FixedNode unknownTypeSux) { assert ptypes.length > 1; - int lastIndex = ptypes.length - 1; - double[] branchProbabilities = convertTypeToBranchProbabilities(ptypes, notRecordedTypeProbability); - double nodeProbability = ptypes[lastIndex].probability; - IfNode nextNode = createTypeCheck(graph, objectClassNode, ptypes[lastIndex].type, calleeEntryNodes[typesToConcretes[lastIndex]], unknownTypeSux, branchProbabilities[lastIndex], invoke.probability() * nodeProbability); - for (int i = lastIndex - 1; i >= 0; i--) { - nodeProbability += ptypes[i].probability; - nextNode = createTypeCheck(graph, objectClassNode, ptypes[i].type, calleeEntryNodes[typesToConcretes[i]], nextNode, branchProbabilities[i], invoke.probability() * nodeProbability); - } - - return nextNode; - } + ResolvedJavaType[] types = new ResolvedJavaType[ptypes.length]; + double[] probabilities = new double[ptypes.length + 1]; + BeginNode[] successors = new BeginNode[ptypes.length + 1]; - private static IfNode createTypeCheck(StructuredGraph graph, ReadHubNode objectClassNode, ResolvedJavaType type, BeginNode tsux, FixedNode nextNode, double tsuxProbability, double probability) { - IfNode result; - IsTypeNode isTypeNode = graph.unique(new IsTypeNode(objectClassNode, type)); - if (tsux instanceof MergeNode) { - EndNode endNode = graph.add(new EndNode()); - result = graph.add(new IfNode(isTypeNode, endNode, nextNode, tsuxProbability)); - ((MergeNode) tsux).addForwardEnd(endNode); - } else { - result = graph.add(new IfNode(isTypeNode, tsux, nextNode, tsuxProbability)); + for (int i = 0; i < ptypes.length; i++) { + types[i] = ptypes[i].type; + probabilities[i] = ptypes[i].probability; + FixedNode entry = calleeEntryNodes[typesToConcretes[i]]; + if (entry instanceof MergeNode) { + EndNode endNode = graph.add(new EndNode()); + ((MergeNode) entry).addForwardEnd(endNode); + entry = endNode; + } + successors[i] = BeginNode.begin(entry); } - result.setProbability(probability); - return result; - } + assert !(unknownTypeSux instanceof MergeNode); + successors[successors.length - 1] = BeginNode.begin(unknownTypeSux); + probabilities[successors.length - 1] = notRecordedTypeProbability; - private static double[] convertTypeToBranchProbabilities(ProfiledType[] ptypes, double notRecordedTypeProbability) { - double[] result = new double[ptypes.length]; - double total = notRecordedTypeProbability; - for (int i = ptypes.length - 1; i >= 0; i--) { - total += ptypes[i].probability; - result[i] = ptypes[i].probability / total; - } - assert total > 0.99 && total < 1.01; - return result; + TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(objectClassNode, successors, types, probabilities)); + + return typeSwitch; } private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, diff -r 28dea025b221 -r 13166af0809e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Wed Jun 20 18:12:50 2012 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009, 2011, 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.java; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; + +/** + * The {@code TypeSwitchNode} performs a lookup based on the type of the input value. + * The type comparison is an exact type comparison, not an instanceof. + */ +public final class TypeSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable { + + private final ResolvedJavaType[] keys; + + public TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] probability) { + super(value, successors, probability); + assert successors.length == keys.length + 1; + assert successors.length == probability.length; + this.keys = keys; + } + + public TypeSwitchNode(ValueNode value, ResolvedJavaType[] keys, double[] switchProbability) { + this(value, new BeginNode[switchProbability.length], keys, switchProbability); + } + + public ResolvedJavaType keyAt(int i) { + return keys[i]; + } + + public int keysLength() { + return keys.length; + } + + @Override + public void generate(LIRGeneratorTool gen) { + gen.emitTypeSwitch(this); + } + + @Override + public void simplify(SimplifierTool tool) { + // TODO(ls) perform simplifications based on the type of value + } +} diff -r 28dea025b221 -r 13166af0809e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Wed Jun 20 16:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Wed Jun 20 18:12:50 2012 +0200 @@ -94,6 +94,7 @@ public abstract void emitLookupSwitch(LookupSwitchNode i); public abstract void emitTableSwitch(TableSwitchNode i); + public abstract void emitTypeSwitch(TypeSwitchNode i); public abstract void emitInvoke(Invoke i); public abstract void emitRuntimeCall(RuntimeCallNode i);