# HG changeset patch # User Doug Simon # Date 1368560586 -7200 # Node ID b2ba1c6f9bf8e9e11ec62ffbe17e3503afc894da # Parent d049444414544ef1b76c73a00b71efe8bc3796ca# Parent bd5c6b3dedc5248d837f221f99aa22006d34ffa6 Merge. diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Tue May 14 21:43:06 2013 +0200 @@ -198,7 +198,19 @@ } } + /** + * Determine whether a kind can be stored in a register of a given category. + * + * @param category the category of the register + * @param kind the kind that should be stored in the register + */ public abstract boolean canStoreValue(RegisterCategory category, PlatformKind kind); + /** + * Return the largest kind that can be stored in a register of a given category. + * + * @param category the category of the register + * @return the largest kind that can be stored in a register {@code category} + */ public abstract PlatformKind getLargestStorableKind(RegisterCategory category); } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Tue May 14 21:43:06 2013 +0200 @@ -206,7 +206,7 @@ return new AMD64AddressValue(target().wordKind, baseRegister, indexRegister, scaleEnum, displacementInt); } - private AMD64AddressValue asAddress(Value address) { + protected AMD64AddressValue asAddressValue(Value address) { if (address instanceof AMD64AddressValue) { return (AMD64AddressValue) address; } else { @@ -216,7 +216,7 @@ @Override public Variable emitLoad(Kind kind, Value address, DeoptimizingNode deopting) { - AMD64AddressValue loadAddress = asAddress(address); + AMD64AddressValue loadAddress = asAddressValue(address); Variable result = newVariable(kind); append(new LoadOp(kind, result, loadAddress, deopting != null ? state(deopting) : null)); return result; @@ -224,7 +224,7 @@ @Override public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) { - AMD64AddressValue storeAddress = asAddress(address); + AMD64AddressValue storeAddress = asAddressValue(address); LIRFrameState state = deopting != null ? state(deopting) : null; if (isConstant(inputVal)) { @@ -366,9 +366,7 @@ @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deoping) { assert v.kind() == Kind.Object; - Variable obj = newVariable(Kind.Object); - emitMove(obj, operand(v)); - append(new AMD64Move.NullCheckOp(obj, state(deoping))); + append(new AMD64Move.NullCheckOp(load(operand(v)), state(deoping))); } @Override diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Tue May 14 21:43:06 2013 +0200 @@ -77,8 +77,8 @@ protected final Backend backend; public GraalCompilerTest() { + this.replacements = Graal.getRequiredCapability(Replacements.class); this.runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class); - this.replacements = Graal.getRequiredCapability(Replacements.class); this.backend = Graal.getRequiredCapability(Backend.class); } @@ -247,12 +247,17 @@ this.returnValue = returnValue; this.exception = exception; } + + @Override + public String toString() { + return exception == null ? returnValue == null ? "null" : returnValue.toString() : "!" + exception; + } } /** * Called before a test is executed. */ - protected void before() { + protected void before(@SuppressWarnings("unused") Method method) { } /** @@ -262,7 +267,7 @@ } protected Result executeExpected(Method method, Object receiver, Object... args) { - before(); + before(method); try { // This gives us both the expected return value as well as ensuring that the method to // be compiled is fully resolved @@ -277,7 +282,7 @@ } protected Result executeActual(Method method, Object receiver, Object... args) { - before(); + before(method); Object[] executeArgs = argsWithReceiver(receiver, args); ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); @@ -347,11 +352,24 @@ } protected void test(Method method, Result expect, Object receiver, Object... args) { + test(method, expect, Collections. emptySet(), receiver, args); + } + + protected void test(Method method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { + Map deoptCounts = new EnumMap<>(DeoptimizationReason.class); + ProfilingInfo profile = runtime.lookupJavaMethod(method).getProfilingInfo(); + for (DeoptimizationReason reason : shouldNotDeopt) { + deoptCounts.put(reason, profile.getDeoptimizationCount(reason)); + } Result actual = executeActual(method, receiver, args); + for (DeoptimizationReason reason : shouldNotDeopt) { + Assert.assertEquals((int) deoptCounts.get(reason), profile.getDeoptimizationCount(reason)); + } if (expect.exception != null) { Assert.assertTrue("expected " + expect.exception, actual.exception != null); Assert.assertEquals(expect.exception.getClass(), actual.exception.getClass()); + Assert.assertEquals(expect.exception.getMessage(), actual.exception.getMessage()); } else { if (actual.exception != null) { actual.exception.printStackTrace(); diff -r d04944441454 -r b2ba1c6f9bf8 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 Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue May 14 21:43:06 2013 +0200 @@ -169,11 +169,10 @@ @Override public Value setResult(ValueNode x, Value operand) { - assert (!isVariable(operand) || x.kind() == operand.getKind()) : operand.getKind() + " for node " + x; assert (!isRegister(operand) || !attributes(asRegister(operand)).isAllocatable()); assert operand(x) == null : "operand cannot be set twice"; assert operand != null && isLegal(operand) : "operand must be legal"; - assert operand.getKind().getStackKind() == x.kind() : operand.getKind().getStackKind() + " must match " + x.kind(); + assert operand.getKind().getStackKind() == x.kind() || x.kind() == Kind.Illegal : operand.getKind().getStackKind() + " must match " + x.kind(); assert !(x instanceof VirtualObjectNode); nodeOperands.set(x, operand); return operand; diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Tue May 14 21:43:06 2013 +0200 @@ -72,5 +72,9 @@ addPhase(new SafepointInsertionPhase()); addPhase(new GuardLoweringPhase()); + + if (GraalOptions.OptCanonicalizer) { + addPhase(new CanonicalizerPhase()); + } } } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Tue May 14 21:43:06 2013 +0200 @@ -358,6 +358,9 @@ @Override public boolean canBeInlined() { + if (dontInline) { + return false; + } return graalRuntime().getCompilerToVM().isMethodCompilable(metaspaceMethod); } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue May 14 21:43:06 2013 +0200 @@ -285,15 +285,15 @@ replacements.registerSubstitutions(ReflectionSubstitutions.class); } - TargetDescription target = graalRuntime.getTarget(); - checkcastSnippets = new CheckCastSnippets.Templates(this, replacements, target); - instanceofSnippets = new InstanceOfSnippets.Templates(this, replacements, target); - newObjectSnippets = new NewObjectSnippets.Templates(this, replacements, target, config.useTLAB); - monitorSnippets = new MonitorSnippets.Templates(this, replacements, target, config.useFastLocking); - writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, replacements, target); - boxingSnippets = new BoxingSnippets.Templates(this, replacements, target); - exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, replacements, target); + checkcastSnippets = new CheckCastSnippets.Templates(this, replacements, graalRuntime.getTarget()); + instanceofSnippets = new InstanceOfSnippets.Templates(this, replacements, graalRuntime.getTarget()); + newObjectSnippets = new NewObjectSnippets.Templates(this, replacements, graalRuntime.getTarget()); + monitorSnippets = new MonitorSnippets.Templates(this, replacements, graalRuntime.getTarget(), config.useFastLocking); + writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, replacements, graalRuntime.getTarget()); + boxingSnippets = new BoxingSnippets.Templates(this, replacements, graalRuntime.getTarget()); + exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, replacements, graalRuntime.getTarget()); + TargetDescription target = getTarget(); link(new NewInstanceStub(this, replacements, target, runtimeCalls.get(NEW_INSTANCE))); link(new NewArrayStub(this, replacements, target, runtimeCalls.get(NEW_ARRAY))); link(new NewMultiArrayStub(this, replacements, target, runtimeCalls.get(NEW_MULTI_ARRAY))); @@ -670,7 +670,9 @@ if (value instanceof VirtualObjectNode) { value = allocations[commit.getVirtualObjects().indexOf(value)]; } - graph.addBeforeFixed(commit, graph.add(new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) instance.field(i)), WriteBarrierType.NONE))); + if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { + graph.addBeforeFixed(commit, graph.add(new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) instance.field(i)), WriteBarrierType.NONE))); + } } } else { VirtualArrayNode array = (VirtualArrayNode) virtual; @@ -682,7 +684,10 @@ assert indexOf != -1 : commit + " " + value; value = allocations[indexOf]; } - graph.addBeforeFixed(commit, graph.add(new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)), WriteBarrierType.NONE))); + if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { + graph.addBeforeFixed(commit, + graph.add(new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)), WriteBarrierType.NONE))); + } } } } @@ -736,9 +741,9 @@ } else if (n instanceof InstanceOfDynamicNode) { instanceofSnippets.lower((InstanceOfDynamicNode) n, tool); } else if (n instanceof NewInstanceNode) { - newObjectSnippets.lower((NewInstanceNode) n, tool); + newObjectSnippets.lower((NewInstanceNode) n); } else if (n instanceof NewArrayNode) { - newObjectSnippets.lower((NewArrayNode) n, tool); + newObjectSnippets.lower((NewArrayNode) n); } else if (n instanceof MonitorEnterNode) { monitorSnippets.lower((MonitorEnterNode) n, tool); } else if (n instanceof MonitorExitNode) { @@ -747,14 +752,8 @@ writeBarrierSnippets.lower((SerialWriteBarrier) n, tool); } else if (n instanceof SerialArrayRangeWriteBarrier) { writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool); - } else if (n instanceof TLABAllocateNode) { - newObjectSnippets.lower((TLABAllocateNode) n, tool); - } else if (n instanceof InitializeObjectNode) { - newObjectSnippets.lower((InitializeObjectNode) n, tool); - } else if (n instanceof InitializeArrayNode) { - newObjectSnippets.lower((InitializeArrayNode) n, tool); } else if (n instanceof NewMultiArrayNode) { - newObjectSnippets.lower((NewMultiArrayNode) n, tool); + newObjectSnippets.lower((NewMultiArrayNode) n); } else if (n instanceof LoadExceptionObjectNode) { exceptionObjectSnippets.lower((LoadExceptionObjectNode) n); } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java Tue May 14 21:33:37 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * 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.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * Initializes the header and body of an uninitialized array cell. This node calls out to a stub to - * do both the allocation and formatting if the memory address it is given is zero/null (e.g. due to - * {@linkplain TLABAllocateNode TLAB allocation} failing). - */ -public final class InitializeArrayNode extends FixedWithNextNode implements Lowerable, ArrayLengthProvider { - - @Input private final ValueNode memory; - @Input private final ValueNode length; - @Input private final ValueNode allocationSize; - private final ResolvedJavaType type; - private final boolean fillContents; - - public InitializeArrayNode(ValueNode memory, ValueNode length, ValueNode allocationSize, ResolvedJavaType type, boolean fillContents) { - super(StampFactory.exactNonNull(type)); - this.memory = memory; - this.type = type; - this.length = length; - this.allocationSize = allocationSize; - this.fillContents = fillContents; - } - - public ValueNode memory() { - return memory; - } - - @Override - public ValueNode length() { - return length; - } - - /** - * Gets the size (in bytes) of the memory chunk allocated for the array. - */ - public ValueNode allocationSize() { - return allocationSize; - } - - public ResolvedJavaType type() { - return type; - } - - public boolean fillContents() { - // We fill contents when G1 GC is used since we want to record - // the original field values prior to stores - return fillContents; - } - - @Override - public void lower(LoweringTool tool, LoweringType loweringType) { - tool.getRuntime().lower(this, tool); - } - - @NodeIntrinsic - public static native Object initialize(Object memory, int length, int allocationSize, @ConstantNodeParameter ResolvedJavaType type, @ConstantNodeParameter boolean fillContents); -} diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java Tue May 14 21:33:37 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * 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.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * Initializes the header and body of an uninitialized object cell. This node calls out to a stub to - * do both the allocation and formatting if the memory address it is given is zero/null (e.g. due to - * {@linkplain TLABAllocateNode TLAB allocation} failing). - */ -public final class InitializeObjectNode extends FixedWithNextNode implements Lowerable { - - @Input private final ValueNode memory; - private final ResolvedJavaType type; - private final boolean fillContents; - - public InitializeObjectNode(ValueNode memory, ResolvedJavaType type, boolean fillContents) { - super(StampFactory.exactNonNull(type)); - this.memory = memory; - this.type = type; - this.fillContents = fillContents; - } - - public ValueNode memory() { - return memory; - } - - public ResolvedJavaType type() { - return type; - } - - public boolean fillContents() { - return fillContents; - } - - @Override - public void lower(LoweringTool tool, LoweringType loweringType) { - tool.getRuntime().lower(this, tool); - } -} diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java Tue May 14 21:33:37 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * 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.hotspot.nodes; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.word.*; - -/** - * Allocates some uninitialized area. This is used for TLAB allocation only. If allocation fails, - * zero/null is produced by this node. - */ -public final class TLABAllocateNode extends FixedWithNextNode implements Lowerable { - - @Input private ValueNode size; - - public TLABAllocateNode(ValueNode size) { - super(StampFactory.forWord()); - this.size = size; - } - - public ValueNode size() { - return size; - } - - @Override - public void lower(LoweringTool tool, LoweringType loweringType) { - tool.getRuntime().lower(this, tool); - } - - /** - * @return null if allocation fails - */ - @NodeIntrinsic - public static native Word allocateVariableSize(int size); -} diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java Tue May 14 21:43:06 2013 +0200 @@ -0,0 +1,283 @@ +/* + * 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.hotspot.replacements; + +import java.lang.reflect.Modifier; +import java.util.Arrays; + +import com.oracle.graal.api.meta.Constant; +import com.oracle.graal.api.meta.JavaType; +import com.oracle.graal.api.meta.ResolvedJavaField; +import com.oracle.graal.api.meta.ResolvedJavaMethod; +import com.oracle.graal.api.meta.ResolvedJavaType; +import com.oracle.graal.graph.GraalInternalError; +import com.oracle.graal.graph.NodeInputList; +import com.oracle.graal.hotspot.meta.HotSpotResolvedJavaMethod; +import com.oracle.graal.hotspot.meta.HotSpotResolvedObjectType; +import com.oracle.graal.hotspot.meta.HotSpotSignature; +import com.oracle.graal.nodes.CallTargetNode; +import com.oracle.graal.nodes.Invoke; +import com.oracle.graal.nodes.InvokeNode; +import com.oracle.graal.nodes.PiNode; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.java.MethodCallTargetNode; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.java.SelfReplacingMethodCallTargetNode; +import com.oracle.graal.nodes.spi.Canonicalizable; +import com.oracle.graal.nodes.type.StampFactory; +import com.oracle.graal.replacements.nodes.MacroNode; + +/** + * Common base class for method handle invoke nodes. + */ +public abstract class AbstractMethodHandleNode extends MacroNode implements Canonicalizable { + + private static final ResolvedJavaField methodHandleFormField; + private static final ResolvedJavaField lambdaFormVmentryField; + private static final ResolvedJavaField memberNameClazzField; + private static final ResolvedJavaField memberNameVmtargetField; + + // Replacement method data + private ResolvedJavaMethod replacementTargetMethod; + private JavaType replacementReturnType; + @Input private NodeInputList replacementArguments; + + /** + * Search for an instance field with the given name in a class. + * + * @param className name of the class to search in + * @param fieldName name of the field to be searched + * @return resolved java field + * @throws ClassNotFoundException + */ + private static ResolvedJavaField findFieldInClass(String className, String fieldName) throws ClassNotFoundException { + Class clazz = Class.forName(className); + ResolvedJavaType type = HotSpotResolvedObjectType.fromClass(clazz); + ResolvedJavaField[] fields = type.getInstanceFields(false); + for (ResolvedJavaField field : fields) { + if (field.getName().equals(fieldName)) { + return field; + } + } + return null; + } + + static { + try { + methodHandleFormField = findFieldInClass("java.lang.invoke.MethodHandle", "form"); + lambdaFormVmentryField = findFieldInClass("java.lang.invoke.LambdaForm", "vmentry"); + memberNameClazzField = findFieldInClass("java.lang.invoke.MemberName", "clazz"); + memberNameVmtargetField = findFieldInClass("java.lang.invoke.MemberName", "vmtarget"); + } catch (ClassNotFoundException | SecurityException ex) { + throw GraalInternalError.shouldNotReachHere(); + } + } + + public AbstractMethodHandleNode(Invoke invoke) { + super(invoke); + + // See if we need to save some replacement method data. + CallTargetNode callTarget = invoke.callTarget(); + if (callTarget instanceof SelfReplacingMethodCallTargetNode) { + SelfReplacingMethodCallTargetNode selfReplacingMethodCallTargetNode = (SelfReplacingMethodCallTargetNode) callTarget; + replacementTargetMethod = selfReplacingMethodCallTargetNode.replacementTargetMethod(); + replacementReturnType = selfReplacingMethodCallTargetNode.replacementReturnType(); + replacementArguments = selfReplacingMethodCallTargetNode.replacementArguments(); + } else { + // NodeInputList can't be null. + replacementArguments = new NodeInputList<>(this); + } + } + + /** + * Get the receiver of a MethodHandle.invokeBasic call. + * + * @return the receiver argument node + */ + private ValueNode getReceiver() { + return arguments.first(); + } + + /** + * Get the MemberName argument of a MethodHandle.linkTo* call. + * + * @return the MemberName argument node (which is the last argument) + */ + private ValueNode getMemberName() { + return arguments.last(); + } + + /** + * Used from {@link MethodHandleInvokeBasicNode} to get the target {@link InvokeNode} if the + * method handle receiver is constant. + * + * @return invoke node for the {@link java.lang.invoke.MethodHandle} target + */ + protected InvokeNode getInvokeBasicTarget() { + ValueNode methodHandleNode = getReceiver(); + if (methodHandleNode.isConstant() && !methodHandleNode.isNullConstant()) { + // Get the data we need from MethodHandle.LambdaForm.MemberName + Constant methodHandle = methodHandleNode.asConstant(); + Constant lambdaForm = methodHandleFormField.readValue(methodHandle); + Constant memberName = lambdaFormVmentryField.readValue(lambdaForm); + return getTargetInvokeNode(memberName); + } + return null; + } + + /** + * Used from {@link MethodHandleLinkToStaticNode}, {@link MethodHandleLinkToSpecialNode}, + * {@link MethodHandleLinkToVirtualNode}, and {@link MethodHandleLinkToInterfaceNode} to get the + * target {@link InvokeNode} if the member name argument is constant. + * + * @return invoke node for the member name target + */ + protected InvokeNode getLinkToTarget() { + ValueNode memberNameNode = getMemberName(); + if (memberNameNode.isConstant() && !memberNameNode.isNullConstant()) { + Constant memberName = memberNameNode.asConstant(); + return getTargetInvokeNode(memberName); + } + return null; + } + + /** + * Helper function to get the {@link InvokeNode} for the vmtarget of a + * java.lang.invoke.MemberName. + * + * @param memberName constant member name node + * @return invoke node for the member name target + */ + private InvokeNode getTargetInvokeNode(Constant memberName) { + // Get the data we need from MemberName + Constant clazz = memberNameClazzField.readValue(memberName); + Constant vmtarget = memberNameVmtargetField.readValue(memberName); + + // Create a method from the vmtarget pointer + Class c = (Class) clazz.asObject(); + HotSpotResolvedObjectType holderClass = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c); + HotSpotResolvedJavaMethod targetMethod = holderClass.createMethod(vmtarget.asLong()); + + // In lamda forms we erase signature types to avoid resolving issues + // involving class loaders. When we optimize a method handle invoke + // to a direct call we must cast the receiver and arguments to its + // actual types. + HotSpotSignature signature = targetMethod.getSignature(); + final boolean isStatic = Modifier.isStatic(targetMethod.getModifiers()); + final int receiverSkip = isStatic ? 0 : 1; + + // Cast receiver to its type. + if (!isStatic) { + JavaType receiverType = holderClass; + maybeCastArgument(0, receiverType); + } + + // Cast reference arguments to its type. + for (int index = 0; index < signature.getParameterCount(false); index++) { + JavaType parameterType = signature.getParameterType(index, holderClass); + maybeCastArgument(receiverSkip + index, parameterType); + } + + // Try to get the most accurate receiver type + if (this instanceof MethodHandleLinkToVirtualNode || this instanceof MethodHandleLinkToInterfaceNode) { + ResolvedJavaType receiverType = getReceiver().objectStamp().type(); + if (receiverType != null) { + ResolvedJavaMethod concreteMethod = receiverType.findUniqueConcreteMethod(targetMethod); + if (concreteMethod != null) { + return createTargetInvokeNode(concreteMethod); + } + } + } + + if (targetMethod.canBeStaticallyBound()) { + return createTargetInvokeNode(targetMethod); + } + + ResolvedJavaMethod concreteMethod = targetMethod.uniqueConcreteMethod(); + if (concreteMethod != null) { + return createTargetInvokeNode(concreteMethod); + } + + return null; + } + + /** + * Inserts a node to cast the argument at index to the given type if the given type is more + * concrete than the argument type. + * + * @param index of the argument to be cast + * @param type the type the argument should be cast to + */ + private void maybeCastArgument(int index, JavaType type) { + if (type instanceof ResolvedJavaType) { + ResolvedJavaType targetType = (ResolvedJavaType) type; + if (!targetType.isPrimitive()) { + ValueNode argument = arguments.get(index); + ResolvedJavaType argumentType = argument.objectStamp().type(); + if (argumentType == null || (argumentType.isAssignableFrom(targetType) && !argumentType.equals(targetType))) { + PiNode piNode = graph().unique(new PiNode(argument, StampFactory.declared(targetType))); + arguments.set(index, piNode); + } + } + } + } + + /** + * Creates an {@link InvokeNode} for the given target method. The {@link CallTargetNode} passed + * to the InvokeNode is in fact a {@link SelfReplacingMethodCallTargetNode}. + * + * @param targetMethod the method the be called + * @return invoke node for the member name target + */ + private InvokeNode createTargetInvokeNode(ResolvedJavaMethod targetMethod) { + InvokeKind invokeKind = Modifier.isStatic(targetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special; + JavaType returnType = targetMethod.getSignature().getReturnType(null); + + // MethodHandleLinkTo* nodes have a trailing MemberName argument which + // needs to be popped. + ValueNode[] originalArguments = arguments.toArray(new ValueNode[arguments.size()]); + ValueNode[] targetArguments; + if (this instanceof MethodHandleInvokeBasicNode) { + targetArguments = originalArguments; + } else { + assert this instanceof MethodHandleLinkToStaticNode || this instanceof MethodHandleLinkToSpecialNode || this instanceof MethodHandleLinkToVirtualNode || + this instanceof MethodHandleLinkToInterfaceNode : this; + targetArguments = Arrays.copyOfRange(originalArguments, 0, arguments.size() - 1); + } + + // If there is already replacement information, use that instead. + MethodCallTargetNode callTarget; + if (replacementTargetMethod == null) { + callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, getTargetMethod(), originalArguments, getReturnType()); + } else { + ValueNode[] args = replacementArguments.toArray(new ValueNode[replacementArguments.size()]); + callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, replacementTargetMethod, args, replacementReturnType); + } + + graph().add(callTarget); + InvokeNode invoke = graph().add(new InvokeNode(callTarget, getBci())); + invoke.setStateAfter(stateAfter()); + return invoke; + } + +} diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java Tue May 14 21:43:06 2013 +0200 @@ -22,17 +22,29 @@ */ package com.oracle.graal.hotspot.replacements; -import java.lang.invoke.*; +import java.lang.invoke.MethodHandle; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.nodes.Invoke; +import com.oracle.graal.nodes.InvokeNode; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.spi.CanonicalizerTool; /** * Macro node for {@link MethodHandle}{@code .invokeBasic(Object...)}. */ -public class MethodHandleInvokeBasicNode extends MacroNode { +public class MethodHandleInvokeBasicNode extends AbstractMethodHandleNode { public MethodHandleInvokeBasicNode(Invoke invoke) { super(invoke); } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + InvokeNode invoke = getInvokeBasicTarget(); + if (invoke != null) { + return invoke; + } + return this; + } + } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java Tue May 14 21:43:06 2013 +0200 @@ -22,17 +22,29 @@ */ package com.oracle.graal.hotspot.replacements; -import java.lang.invoke.*; +import java.lang.invoke.MethodHandle; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.nodes.Invoke; +import com.oracle.graal.nodes.InvokeNode; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.spi.CanonicalizerTool; /** * Macro node for {@link MethodHandle}{@code .linkToInterface(Object...)}. */ -public class MethodHandleLinkToInterfaceNode extends MacroNode { +public class MethodHandleLinkToInterfaceNode extends AbstractMethodHandleNode { public MethodHandleLinkToInterfaceNode(Invoke invoke) { super(invoke); } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + InvokeNode invoke = getLinkToTarget(); + if (invoke != null) { + return invoke; + } + return this; + } + } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java Tue May 14 21:43:06 2013 +0200 @@ -22,17 +22,29 @@ */ package com.oracle.graal.hotspot.replacements; -import java.lang.invoke.*; +import java.lang.invoke.MethodHandle; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.nodes.Invoke; +import com.oracle.graal.nodes.InvokeNode; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.spi.CanonicalizerTool; /** * Macro node for {@link MethodHandle}{@code .linkToSpecial(Object...)}. */ -public class MethodHandleLinkToSpecialNode extends MacroNode { +public class MethodHandleLinkToSpecialNode extends AbstractMethodHandleNode { public MethodHandleLinkToSpecialNode(Invoke invoke) { super(invoke); } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + InvokeNode invoke = getLinkToTarget(); + if (invoke != null) { + return invoke; + } + return this; + } + } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java Tue May 14 21:43:06 2013 +0200 @@ -22,17 +22,29 @@ */ package com.oracle.graal.hotspot.replacements; -import java.lang.invoke.*; +import java.lang.invoke.MethodHandle; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.nodes.Invoke; +import com.oracle.graal.nodes.InvokeNode; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.spi.CanonicalizerTool; /** * Macro node for {@link MethodHandle}{@code .linkToStatic(Object...)}. */ -public class MethodHandleLinkToStaticNode extends MacroNode { +public class MethodHandleLinkToStaticNode extends AbstractMethodHandleNode { public MethodHandleLinkToStaticNode(Invoke invoke) { super(invoke); } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + InvokeNode invoke = getLinkToTarget(); + if (invoke != null) { + return invoke; + } + return this; + } + } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java Tue May 14 21:43:06 2013 +0200 @@ -22,17 +22,29 @@ */ package com.oracle.graal.hotspot.replacements; -import java.lang.invoke.*; +import java.lang.invoke.MethodHandle; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.nodes.Invoke; +import com.oracle.graal.nodes.InvokeNode; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.spi.CanonicalizerTool; /** * Macro node for {@link MethodHandle}{@code .linkToVirtual(Object...)}. */ -public class MethodHandleLinkToVirtualNode extends MacroNode { +public class MethodHandleLinkToVirtualNode extends AbstractMethodHandleNode { public MethodHandleLinkToVirtualNode(Invoke invoke) { super(invoke); } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + InvokeNode invoke = getLinkToTarget(); + if (invoke != null) { + return invoke; + } + return this; + } + } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Tue May 14 21:43:06 2013 +0200 @@ -72,54 +72,52 @@ } @Snippet - public static Object initializeObject(Word memory, Word hub, Word prototypeMarkWord, @ConstantParameter int size, @ConstantParameter boolean fillContents) { - + public static Object allocateInstance(@ConstantParameter int size, Word hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents) { Object result; - if (probability(SLOW_PATH_PROBABILITY, memory.equal(0))) { + Word thread = thread(); + Word top = readTlabTop(thread); + Word end = readTlabEnd(thread); + Word newTop = top.add(size); + if (useTLAB() && probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { + writeTlabTop(thread, newTop); + result = formatObject(hub, size, top, prototypeMarkWord, fillContents); + } else { new_stub.inc(); result = NewInstanceStubCall.call(hub); - } else { - formatObject(hub, size, memory, prototypeMarkWord, fillContents); - result = memory.toObject(); } - /* - * make sure that the unsafeCast is anchored after initialization, see ReadAfterCheckCast - * and CheckCastSnippets - */ BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic(), anchorNode); } - @Snippet - public static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter boolean fillContents) { - Object result; - if (probability(SLOW_PATH_PROBABILITY, memory.equal(0))) { - newarray_stub.inc(); - result = NewArrayStubCall.call(hub, length); - } else { - newarray_loopInit.inc(); - formatArray(hub, allocationSize, length, headerSize, memory, prototypeMarkWord, fillContents); - result = memory.toObject(); - } - BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); - return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic(), anchorNode); - } - /** * Maximum array length for which fast path allocation is used. */ public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF; @Snippet - public static Object allocateArrayAndInitialize(int length, @ConstantParameter int alignment, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter ResolvedJavaType type) { + public static Object allocateArray(Word hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, @ConstantParameter boolean fillContents) { if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { // This handles both negative array sizes and very large array sizes DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } + + Object result; + int alignment = wordSize(); int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); - Word memory = TLABAllocateNode.allocateVariableSize(allocationSize); - return InitializeArrayNode.initialize(memory, length, allocationSize, type, fillContents); + Word thread = thread(); + Word top = readTlabTop(thread); + Word end = readTlabEnd(thread); + Word newTop = top.add(allocationSize); + if (useTLAB() && probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { + writeTlabTop(thread, newTop); + newarray_loopInit.inc(); + result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents); + } else { + newarray_stub.inc(); + result = NewArrayStubCall.call(hub, length); + } + BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); + return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic(), anchorNode); } /** @@ -160,7 +158,7 @@ /** * Formats some allocated memory with an object header zeroes out the rest. */ - private static void formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents) { + private static Object formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents) { Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { @@ -177,12 +175,13 @@ } } } + return memory.toObject(); } /** - * Formats some allocated memory with an object header zeroes out the rest. + * Formats some allocated memory with an object header and zeroes out the rest. */ - public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) { + public static Object formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) { memory.writeInt(arrayLengthOffset(), length, ANY_LOCATION); /* * store hub last as the concurrent garbage collectors assume length is valid if hub field @@ -194,151 +193,66 @@ memory.writeWord(offset, Word.zero(), ANY_LOCATION); } } + return memory.toObject(); } public static class Templates extends AbstractTemplates { - private final SnippetInfo allocate = snippet(NewObjectSnippets.class, "allocate"); - private final SnippetInfo initializeObject = snippet(NewObjectSnippets.class, "initializeObject"); - private final SnippetInfo initializeArray = snippet(NewObjectSnippets.class, "initializeArray"); - private final SnippetInfo allocateArrayAndInitialize = snippet(NewObjectSnippets.class, "allocateArrayAndInitialize"); + private final SnippetInfo allocateInstance = snippet(NewObjectSnippets.class, "allocateInstance"); + private final SnippetInfo allocateArray = snippet(NewObjectSnippets.class, "allocateArray"); private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray"); - private final boolean useTLAB; - - public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useTLAB) { + public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { super(runtime, replacements, target); - this.useTLAB = useTLAB; } /** * Lowers a {@link NewInstanceNode}. */ - @SuppressWarnings("unused") - public void lower(NewInstanceNode newInstanceNode, LoweringTool tool) { + public void lower(NewInstanceNode newInstanceNode) { StructuredGraph graph = newInstanceNode.graph(); HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newInstanceNode.instanceClass(); + assert !type.isArray(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); int size = instanceSize(type); - ValueNode memory; - if (!useTLAB) { - memory = ConstantNode.defaultForKind(target.wordKind, graph); - } else { - ConstantNode sizeNode = ConstantNode.forInt(size, graph); - TLABAllocateNode tlabAllocateNode = graph.add(new TLABAllocateNode(sizeNode)); - graph.addBeforeFixed(newInstanceNode, tlabAllocateNode); - memory = tlabAllocateNode; - } - InitializeObjectNode initializeNode = graph.add(new InitializeObjectNode(memory, type, newInstanceNode.fillContents())); - graph.replaceFixedWithFixed(newInstanceNode, initializeNode); + Arguments args = new Arguments(allocateInstance); + args.addConst("size", size); + args.add("hub", hub); + args.add("prototypeMarkWord", type.prototypeMarkWord()); + args.addConst("fillContents", newInstanceNode.fillContents()); + + SnippetTemplate template = template(args); + Debug.log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args); + template.instantiate(runtime, newInstanceNode, DEFAULT_REPLACER, args); } /** * Lowers a {@link NewArrayNode}. */ - @SuppressWarnings("unused") - public void lower(NewArrayNode newArrayNode, LoweringTool tool) { + public void lower(NewArrayNode newArrayNode) { StructuredGraph graph = newArrayNode.graph(); - ValueNode lengthNode = newArrayNode.length(); - TLABAllocateNode tlabAllocateNode; ResolvedJavaType elementType = newArrayNode.elementType(); - ResolvedJavaType arrayType = elementType.getArrayClass(); + HotSpotResolvedObjectType arrayType = (HotSpotResolvedObjectType) elementType.getArrayClass(); Kind elementKind = elementType.getKind(); - final int alignment = target.wordSize; + ConstantNode hub = ConstantNode.forConstant(arrayType.klass(), runtime, graph); final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind); - final Integer length = lengthNode.isConstant() ? Integer.valueOf(lengthNode.asConstant().asInt()) : null; int log2ElementSize = CodeUtil.log2(target.arch.getSizeInBytes(elementKind)); - if (!useTLAB) { - ConstantNode zero = ConstantNode.defaultForKind(target.wordKind, graph); - /* - * value for 'size' doesn't matter as it isn't used since a stub call will be made - * anyway for both allocation and initialization - it just needs to be non-null - */ - ConstantNode size = ConstantNode.forInt(-1, graph); - InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType, newArrayNode.fillContents())); - graph.replaceFixedWithFixed(newArrayNode, initializeNode); - } else if (length != null && belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { - // Calculate aligned size - int size = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); - ConstantNode sizeNode = ConstantNode.forInt(size, graph); - tlabAllocateNode = graph.add(new TLABAllocateNode(sizeNode)); - graph.addBeforeFixed(newArrayNode, tlabAllocateNode); - InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType, newArrayNode.fillContents())); - graph.replaceFixedWithFixed(newArrayNode, initializeNode); - } else { - Arguments args = new Arguments(allocateArrayAndInitialize); - args.add("length", lengthNode); - args.addConst("alignment", alignment); - args.addConst("headerSize", headerSize); - args.addConst("log2ElementSize", log2ElementSize); - args.addConst("fillContents", newArrayNode.fillContents()); - args.addConst("type", arrayType); - SnippetTemplate template = template(args); - Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); - template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args); - } - } - - @SuppressWarnings("unused") - public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) { - StructuredGraph graph = tlabAllocateNode.graph(); - ValueNode size = tlabAllocateNode.size(); - Arguments args = new Arguments(allocate).add("size", size); + Arguments args = new Arguments(allocateArray); + args.add("hub", hub); + args.add("length", newArrayNode.length()); + args.add("prototypeMarkWord", arrayType.prototypeMarkWord()); + args.addConst("headerSize", headerSize); + args.addConst("log2ElementSize", log2ElementSize); + args.addConst("fillContents", newArrayNode.fillContents()); SnippetTemplate template = template(args); - Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, args); - template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, args); - } - - @SuppressWarnings("unused") - public void lower(InitializeObjectNode initializeNode, LoweringTool tool) { - StructuredGraph graph = initializeNode.graph(); - HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) initializeNode.type(); - assert !type.isArray(); - ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); - int size = instanceSize(type); - ValueNode memory = initializeNode.memory(); - - Arguments args = new Arguments(initializeObject); - args.add("memory", memory); - args.add("hub", hub); - args.add("prototypeMarkWord", type.prototypeMarkWord()); - args.addConst("size", size).addConst("fillContents", initializeNode.fillContents()); - - SnippetTemplate template = template(args); - Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args); - template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args); + Debug.log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); + template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args); } - @SuppressWarnings("unused") - public void lower(InitializeArrayNode initializeNode, LoweringTool tool) { - StructuredGraph graph = initializeNode.graph(); - HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) initializeNode.type(); - ResolvedJavaType elementType = type.getComponentType(); - assert elementType != null; - ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); - Kind elementKind = elementType.getKind(); - final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind); - ValueNode memory = initializeNode.memory(); - - Arguments args = new Arguments(initializeArray); - args.add("memory", memory); - args.add("hub", hub); - args.add("length", initializeNode.length()); - args.add("allocationSize", initializeNode.allocationSize()); - args.add("prototypeMarkWord", type.prototypeMarkWord()); - args.addConst("headerSize", headerSize); - args.addConst("fillContents", initializeNode.fillContents()); - - SnippetTemplate template = template(args); - Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args); - template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args); - } - - @SuppressWarnings("unused") - public void lower(NewMultiArrayNode newmultiarrayNode, LoweringTool tool) { + public void lower(NewMultiArrayNode newmultiarrayNode) { StructuredGraph graph = newmultiarrayNode.graph(); int rank = newmultiarrayNode.dimensionCount(); ValueNode[] dims = new ValueNode[rank]; diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Tue May 14 21:43:06 2013 +0200 @@ -52,11 +52,10 @@ private static Object instanceClone(Object src, Word hub, int layoutHelper) { int instanceSize = layoutHelper; - Pointer memory = NewObjectSnippets.allocate(instanceSize); Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - Object result = NewObjectSnippets.initializeObject((Word) memory, hub, prototypeMarkWord, instanceSize, false); + Object result = NewObjectSnippets.allocateInstance(instanceSize, hub, prototypeMarkWord, false); - memory = Word.fromObject(result); + Pointer memory = Word.fromObject(result); for (int offset = 2 * wordSize(); offset < instanceSize; offset += wordSize()) { memory.writeWord(offset, Word.fromObject(src).readWord(offset, ANY_LOCATION), ANY_LOCATION); } @@ -70,11 +69,10 @@ int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); int sizeInBytes = NewObjectSnippets.computeArrayAllocationSize(arrayLength, wordSize(), headerSize, log2ElementSize); - Pointer memory = NewObjectSnippets.allocate(sizeInBytes); Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - Object result = NewObjectSnippets.initializeArray((Word) memory, hub, arrayLength, sizeInBytes, prototypeMarkWord, headerSize, false); + Object result = NewObjectSnippets.allocateArray(hub, arrayLength, prototypeMarkWord, headerSize, log2ElementSize, false); - memory = Word.fromObject(result); + Pointer memory = Word.fromObject(result); for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) { memory.writeWord(offset, Word.fromObject(src).readWord(offset, ANY_LOCATION), ANY_LOCATION); } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java Tue May 14 21:43:06 2013 +0200 @@ -73,7 +73,7 @@ if (logging()) { printf("handling exception %p (", Word.fromObject(exception).rawValue()); decipher(Word.fromObject(exception).rawValue()); - printf(") at %p (", Word.fromObject(exception).rawValue(), exceptionPc.rawValue()); + printf(") at %p (", exceptionPc.rawValue()); decipher(exceptionPc.rawValue()); printf(")\n"); } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Tue May 14 21:43:06 2013 +0200 @@ -108,8 +108,7 @@ if (logging()) { printf("newArray: allocated new array at %p\n", memory.rawValue()); } - formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord()), true); - return verifyObject(memory.toObject()); + return verifyObject(formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord()), true)); } } if (logging()) { diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/RuntimeCallStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/RuntimeCallStub.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/RuntimeCallStub.java Tue May 14 21:43:06 2013 +0200 @@ -33,13 +33,13 @@ import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; @@ -150,19 +150,19 @@ final StructuredGraph graph; private FixedWithNextNode lastFixedNode; - T add(T node) { + T add(T node) { + return graph.unique(node); + } + + T append(T node) { T result = graph.add(node); - assert node == result; - if (result instanceof FixedNode) { - assert lastFixedNode != null; - FixedNode fixed = (FixedNode) result; - assert fixed.predecessor() == null; - graph.addAfterFixed(lastFixedNode, fixed); - if (fixed instanceof FixedWithNextNode) { - lastFixedNode = (FixedWithNextNode) fixed; - } else { - lastFixedNode = null; - } + assert lastFixedNode != null; + assert result.predecessor() == null; + graph.addAfterFixed(lastFixedNode, result); + if (result instanceof FixedWithNextNode) { + lastFixedNode = (FixedWithNextNode) result; + } else { + lastFixedNode = null; } return result; } @@ -172,19 +172,17 @@ protected StructuredGraph getGraph() { Class[] args = linkage.getDescriptor().getArgumentTypes(); boolean isObjectResult = linkage.getCallingConvention().getReturn().getKind() == Kind.Object; - GraphBuilder builder = new GraphBuilder(this); - LocalNode[] locals = createLocals(builder, args); - ReadRegisterNode thread = prependThread || isObjectResult ? builder.add(new ReadRegisterNode(runtime.threadRegister(), true, false)) : null; + ReadRegisterNode thread = prependThread || isObjectResult ? builder.append(new ReadRegisterNode(runtime.threadRegister(), true, false)) : null; ValueNode result = createTargetCall(builder, locals, thread); createInvoke(builder, StubUtil.class, "handlePendingException", ConstantNode.forBoolean(isObjectResult, builder.graph)); if (isObjectResult) { InvokeNode object = createInvoke(builder, HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread); result = createInvoke(builder, StubUtil.class, "verifyObject", object); } - builder.add(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result)); + builder.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result)); if (Debug.isDumpEnabled()) { Debug.dump(builder.graph, "Initial stub graph"); @@ -230,8 +228,8 @@ } assert method != null : "did not find method in " + declaringClass + " named " + name; JavaType returnType = method.getSignature().getReturnType(null); - MethodCallTargetNode callTarget = builder.add(new MethodCallTargetNode(InvokeKind.Static, method, hpeArgs, returnType)); - InvokeNode invoke = builder.add(new InvokeNode(callTarget, FrameState.UNKNOWN_BCI)); + MethodCallTargetNode callTarget = builder.graph.add(new MethodCallTargetNode(InvokeKind.Static, method, hpeArgs, returnType)); + InvokeNode invoke = builder.append(new InvokeNode(callTarget, FrameState.UNKNOWN_BCI)); return invoke; } @@ -240,9 +238,9 @@ ValueNode[] targetArguments = new ValueNode[1 + locals.length]; targetArguments[0] = thread; System.arraycopy(locals, 0, targetArguments, 1, locals.length); - return builder.add(new CRuntimeCall(target.getDescriptor(), targetArguments)); + return builder.append(new CRuntimeCall(target.getDescriptor(), targetArguments)); } else { - return builder.add(new CRuntimeCall(target.getDescriptor(), locals)); + return builder.append(new CRuntimeCall(target.getDescriptor(), locals)); } } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java Tue May 14 21:43:06 2013 +0200 @@ -66,7 +66,7 @@ if (logging()) { printf("unwinding exception %p (", exceptionOop.rawValue()); decipher(exceptionOop.rawValue()); - printf(") at %p (", exceptionOop.rawValue(), returnAddress.rawValue()); + printf(") at %p (", returnAddress.rawValue()); decipher(returnAddress.rawValue()); printf(")\n"); } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Tue May 14 21:43:06 2013 +0200 @@ -26,6 +26,7 @@ import static java.lang.reflect.Modifier.*; import java.lang.reflect.*; +import java.util.*; import org.junit.*; @@ -93,15 +94,19 @@ } protected void runTest(String name, Object... args) { + runTest(Collections. emptySet(), name, args); + } + + protected void runTest(Set shoutNotDeopt, String name, Object... args) { Method method = getMethod(name); Object receiver = Modifier.isStatic(method.getModifiers()) ? null : this; Result expect = executeExpected(method, receiver, args); - test(method, expect, receiver, args); + test(method, expect, shoutNotDeopt, receiver, args); if (args.length > 0) { this.argsToBind = args; - test(method, expect, receiver, args); + test(method, expect, shoutNotDeopt, receiver, args); this.argsToBind = null; } } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field01.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field01.java Tue May 14 21:43:06 2013 +0200 @@ -23,6 +23,8 @@ // Checkstyle: stop package com.oracle.graal.jtt.hotpath; +import java.lang.reflect.*; + import com.oracle.graal.jtt.*; import org.junit.*; @@ -48,7 +50,7 @@ } @Override - public void before() { + public void before(Method m) { a = 0; b = 0; c = 0; diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field03.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field03.java Tue May 14 21:43:06 2013 +0200 @@ -23,6 +23,8 @@ // Checkstyle: stop package com.oracle.graal.jtt.hotpath; +import java.lang.reflect.*; + import com.oracle.graal.jtt.*; import org.junit.*; @@ -52,7 +54,7 @@ } @Override - public void before() { + public void before(Method m) { b = 0; c = 0; s = 0; diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/Unsafe_compareAndSwap.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/Unsafe_compareAndSwap.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/Unsafe_compareAndSwap.java Tue May 14 21:43:06 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.jtt.jdk; +import java.lang.reflect.*; + import org.junit.*; import com.oracle.graal.jtt.*; @@ -54,7 +56,7 @@ private static final Unsafe_compareAndSwap instance = new Unsafe_compareAndSwap(); @Override - protected void before() { + protected void before(Method m) { instance.value = "a"; } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopNewInstance.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopNewInstance.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopNewInstance.java Tue May 14 21:43:06 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.jtt.loop; +import java.lang.reflect.*; + import com.oracle.graal.jtt.*; import org.junit.*; @@ -54,7 +56,7 @@ } @Override - protected void before() { + protected void before(Method m) { count = 0; } diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Tue May 14 21:43:06 2013 +0200 @@ -0,0 +1,84 @@ +/* + * 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.nodes.java; + +import java.lang.reflect.Modifier; + +import com.oracle.graal.api.meta.JavaType; +import com.oracle.graal.api.meta.ResolvedJavaMethod; +import com.oracle.graal.graph.GraalInternalError; +import com.oracle.graal.graph.NodeInputList; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.spi.LIRGeneratorTool; +import com.oracle.graal.nodes.spi.Lowerable; +import com.oracle.graal.nodes.spi.LoweringTool; + +/** + * A SelfReplacingMethodCallTargetNode replaces itself in the graph when being lowered with a + * {@link MethodCallTargetNode} that calls the stored replacement target method. + * + * This node is used for method handle call nodes which have a constant call target but are not + * inlined. + */ +public class SelfReplacingMethodCallTargetNode extends MethodCallTargetNode implements Lowerable { + + // Replacement method data + private final ResolvedJavaMethod replacementTargetMethod; + private final JavaType replacementReturnType; + @Input private final NodeInputList replacementArguments; + + public SelfReplacingMethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType, ResolvedJavaMethod replacementTargetMethod, + ValueNode[] replacementArguments, JavaType replacementReturnType) { + super(invokeKind, targetMethod, arguments, returnType); + this.replacementTargetMethod = replacementTargetMethod; + this.replacementReturnType = replacementReturnType; + this.replacementArguments = new NodeInputList<>(this, replacementArguments); + } + + public ResolvedJavaMethod replacementTargetMethod() { + return replacementTargetMethod; + } + + public JavaType replacementReturnType() { + return replacementReturnType; + } + + public NodeInputList replacementArguments() { + return replacementArguments; + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + InvokeKind invokeKind = Modifier.isStatic(replacementTargetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special; + MethodCallTargetNode replacement = graph().add( + new MethodCallTargetNode(invokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType)); + + // Replace myself... + this.replaceAndDelete(replacement); + } + + @Override + public void generate(LIRGeneratorTool gen) { + throw GraalInternalError.shouldNotReachHere("should have replaced itself"); + } +} diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Tue May 14 21:43:06 2013 +0200 @@ -33,6 +33,7 @@ import com.oracle.graal.api.meta.ResolvedJavaType.Representation; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -1267,6 +1268,8 @@ monitor.setLockDepth(monitor.getLockDepth() + callerLockDepth); } } + } else { + assert checkContainsOnlyInvalidOrAfterFrameState(duplicates); } Node returnValue = null; if (returnNode != null) { @@ -1289,6 +1292,16 @@ return duplicates; } + private static boolean checkContainsOnlyInvalidOrAfterFrameState(Map duplicates) { + for (Node node : duplicates.values()) { + if (node instanceof FrameState) { + FrameState frameState = (FrameState) node; + assert frameState.bci == FrameState.AFTER_BCI || frameState.bci == FrameState.INVALID_FRAMESTATE_BCI : node.toString(Verbosity.Debugger); + } + } + return true; + } + public static void receiverNullCheck(Invoke invoke) { MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); StructuredGraph graph = callTarget.graph(); diff -r d04944441454 -r b2ba1c6f9bf8 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue May 14 21:33:37 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue May 14 21:43:06 2013 +0200 @@ -204,7 +204,7 @@ ((Virtualizable) node).virtualize(tool); } if (tool.isDeleted()) { - if (!(node instanceof VirtualizableAllocation)) { + if (!(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode)) { changed = true; } return true;