# HG changeset patch # User Christian Haeubl # Date 1327646671 28800 # Node ID 9e8e92c3ff172b9ca543a1348d2d9b5748428596 # Parent 00a04b57a046c2a82ca7d428b457032bdd0d02b9 first parts for inlining multiple methods, added Simplifiable to switch nodes, some documentation diff -r 00a04b57a046 -r 9e8e92c3ff17 graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java Tue Jan 24 14:23:40 2012 -0800 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java Thu Jan 26 22:44:31 2012 -0800 @@ -25,6 +25,8 @@ /** * Represents profiling information for one specific method. + * Every accessor method returns the information that is available at the time of its invocation. + * If a method is invoked multiple times, it may return a significantly different results for every invocation. */ public interface RiProfilingInfo { /** @@ -55,7 +57,8 @@ boolean getImplicitExceptionSeen(int bci); /** - * Returns an estimate how often the current BCI was executed. + * Returns an estimate how often the current BCI was executed. Avoid comparing execution counts to each other, + * as the returned value highly depends on the time of invocation. * @return the estimated execution count or -1 if not available. */ int getExecutionCount(int bci); diff -r 00a04b57a046 -r 9e8e92c3ff17 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Tue Jan 24 14:23:40 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Thu Jan 26 22:44:31 2012 -0800 @@ -719,7 +719,6 @@ emitXir(typeCheck, node, info, method, false); } - public void emitBranch(BooleanNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) { if (node instanceof NullCheckNode) { emitNullCheckBranch((NullCheckNode) node, trueSuccessor, falseSuccessor, info); @@ -1034,6 +1033,21 @@ } @Override + public void emitTypeSwitch(TypeSwitchNode x) { + Variable tag = load(operand(x.value())); + LIRDebugInfo info = state(); + + int len = x.typesLength(); + for (int i = 0; i < len; i++) { + CiConstant type = x.typeAt(i).getEncoding(Representation.ObjectHub); + emitBranch(tag, type, Condition.EQ, false, getLIRBlock(x.blockSuccessor(i)), null); + } + + LabelRef stubEntry = createDeoptStub(DeoptAction.InvalidateReprofile, info, x); + emitJump(stubEntry, info); + } + + @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 00a04b57a046 -r 9e8e92c3ff17 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HOTSPOTMETHODDATAACCESSOR.JAVA --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HOTSPOTMETHODDATAACCESSOR.JAVA Tue Jan 24 14:23:40 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HOTSPOTMETHODDATAACCESSOR.JAVA Thu Jan 26 22:44:31 2012 -0800 @@ -24,18 +24,33 @@ import com.oracle.max.cri.ri.*; +/** + * Interface for accessor objects that encapsulate the logic for accessing the different kinds of data in a HotSpot methodDataOop. + * This interface is similar to the interface {@link RiProfilingInfo}, but most methods require a MethodDataObject and the + * exact position within the methodData. + */ public interface HotSpotMethodDataAccessor { + /** + * Returns the tag stored in the LayoutData header. + * @return An integer >= 0 or -1 if not supported. + */ int getTag(); + + /** + * Returns the BCI stored in the LayoutData header. + * @return An integer >= 0 and <= Short.MAX_VALUE, or -1 if not supported. + */ int getBCI(HotSpotMethodData data, int position); + + /** + * Computes the size for the specific data at the given position. + * @return An integer > 0. + */ int getSize(HotSpotMethodData data, int position); RiTypeProfile getTypeProfile(HotSpotMethodData data, int position); - double getBranchTakenProbability(HotSpotMethodData data, int position); - double[] getSwitchProbabilities(HotSpotMethodData data, int position); - boolean getImplicitExceptionSeen(HotSpotMethodData data, int position); - int getExecutionCount(HotSpotMethodData data, int position); } diff -r 00a04b57a046 -r 9e8e92c3ff17 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodData.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodData.java Tue Jan 24 14:23:40 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodData.java Thu Jan 26 22:44:31 2012 -0800 @@ -44,6 +44,7 @@ private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final HotSpotMethodDataAccessor NO_DATA_ACCESSOR = new NoMethodData(); private static final HotSpotVMConfig config; + // sorted by tag private static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = { null, new BitData(), new CounterData(), new JumpData(), new TypeCheckData(), new VirtualCallData(), new RetData(), @@ -164,7 +165,6 @@ this.staticSize = staticSize; } - @Override public int getTag() { return tag; } diff -r 00a04b57a046 -r 9e8e92c3ff17 graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/LookupSwitchNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/LookupSwitchNode.java Tue Jan 24 14:23:40 2012 -0800 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/LookupSwitchNode.java Thu Jan 26 22:44:31 2012 -0800 @@ -29,7 +29,7 @@ * The {@code LookupSwitchNode} represents a lookup switch bytecode, which has a sorted * array of key values. */ -public final class LookupSwitchNode extends SwitchNode implements LIRLowerable { +public final class LookupSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable { @Data private final int[] keys; @@ -65,4 +65,32 @@ public void generate(LIRGeneratorTool gen) { gen.emitLookupSwitch(this); } + + @Override + public void simplify(SimplifierTool tool) { + if (value() instanceof ConstantNode) { + ConstantNode constant = (ConstantNode) value(); + int value = constant.value.asInt(); + + BeginNode remainingSux = (BeginNode) defaultSuccessor(); + int remainingSuxIndex = blockSuccessorCount() - 1; + for (int i = 0; i < keys.length; i++) { + if (value == keys[i]) { + remainingSux = blockSuccessor(i); + remainingSuxIndex = i; + break; + } + } + + for (int i = 0; i < blockSuccessorCount(); i++) { + BeginNode sux = blockSuccessor(i); + if (sux != remainingSux) { + tool.deleteBranch(sux); + } + } + + tool.addToWorkList(remainingSux); + ((StructuredGraph) graph()).removeSplit(this, remainingSuxIndex); + } + } } diff -r 00a04b57a046 -r 9e8e92c3ff17 graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/TableSwitchNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/TableSwitchNode.java Tue Jan 24 14:23:40 2012 -0800 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/TableSwitchNode.java Thu Jan 26 22:44:31 2012 -0800 @@ -28,7 +28,7 @@ /** * The {@code TableSwitchNode} represents a table switch. */ -public final class TableSwitchNode extends SwitchNode implements LIRLowerable { +public final class TableSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable { @Data private final int lowKey; @@ -67,4 +67,30 @@ public void generate(LIRGeneratorTool gen) { gen.emitTableSwitch(this); } + + @Override + public void simplify(SimplifierTool tool) { + if (value() instanceof ConstantNode) { + ConstantNode constant = (ConstantNode) value(); + int value = constant.value.asInt(); + + int remainingSuxIndex; + if (value >= lowKey() && value <= highKey()) { + remainingSuxIndex = value - lowKey(); + } else { + remainingSuxIndex = blockSuccessorCount() - 1; + } + + BeginNode remainingSux = blockSuccessor(remainingSuxIndex); + for (int i = 0; i < blockSuccessorCount(); i++) { + BeginNode sux = blockSuccessor(i); + if (sux != remainingSux) { + tool.deleteBranch(sux); + } + } + + tool.addToWorkList(remainingSux); + ((StructuredGraph) graph()).removeSplit(this, remainingSuxIndex); + } + } } diff -r 00a04b57a046 -r 9e8e92c3ff17 graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/TypeSwitchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/TypeSwitchNode.java Thu Jan 26 22:44:31 2012 -0800 @@ -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.max.graal.nodes.extended; + +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.nodes.spi.*; + +/** + * The {@code TypeSwitchNode} is a switch node that dispatches to a successor based on a given type. + */ +public final class TypeSwitchNode extends SwitchNode implements LIRLowerable { + + @Data private final RiResolvedType[] types; + + /** + * Constructs a new TypeSwitchNode instruction. + * @param object the instruction producing the value which type should be tested + * @param successors the list of successors (default successor is last entry) + * @param types the list of types, same order as successors but no value for default successor + * @param probability the list of probabilities, same order as successors + */ + public TypeSwitchNode(ValueNode object, BeginNode[] successors, RiResolvedType[] types, double[] probability) { + super(object, successors, probability); + assert object.exactType() == null : "emitting useless guard"; + this.types = types; + } + + /** + * Gets the type at the specified index. + * @param i the index + * @return the type at that index + */ + public RiResolvedType typeAt(int i) { + return types[i]; + } + + public int typesLength() { + return types.length; + } + + @Override + public void generate(LIRGeneratorTool gen) { + gen.emitTypeSwitch(this); + } +} diff -r 00a04b57a046 -r 9e8e92c3ff17 graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/LIRGeneratorTool.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/LIRGeneratorTool.java Tue Jan 24 14:23:40 2012 -0800 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/LIRGeneratorTool.java Thu Jan 26 22:44:31 2012 -0800 @@ -88,6 +88,7 @@ public abstract void emitLookupSwitch(LookupSwitchNode i); public abstract void emitTableSwitch(TableSwitchNode i); + public abstract void emitTypeSwitch(TypeSwitchNode x); public abstract void emitInvoke(Invoke i); public abstract void emitRuntimeCall(RuntimeCallNode i);