# HG changeset patch # User Christian Wimmer # Date 1363660765 25200 # Node ID a69eb5f539d903efac7b1d1f69f3a6fab890cb4a # Parent 5fbb2df2b47fddc158ecbc0e6f8f53464482d30b# Parent 65ba93f118d41bcece3cb9c23d00d9d813f2764a Merge diff -r 65ba93f118d4 -r a69eb5f539d9 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Mon Mar 18 21:33:34 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Mon Mar 18 19:39:25 2013 -0700 @@ -1051,8 +1051,7 @@ static RegisterPriority registerPriorityOfOutputOperand(LIRInstruction op) { if (op instanceof MoveOp) { MoveOp move = (MoveOp) op; - if (isStackSlot(move.getInput()) && move.getInput().getKind() != Kind.Object) { - // method argument (condition must be equal to handleMethodArguments) + if (optimizeMethodArgument(move.getInput())) { return RegisterPriority.None; } } @@ -1073,6 +1072,10 @@ return RegisterPriority.MustHaveRegister; } + private static boolean optimizeMethodArgument(Value value) { + return isStackSlot(value) && asStackSlot(value).isInCallerFrame() && (GraalOptions.IncomingMethodArgumentsGCSafe || value.getKind() != Kind.Object); + } + /** * Optimizes moves related to incoming stack based arguments. The interval for the destination * of such moves is assigned the stack slot (which is in the caller's frame) as its spill slot. @@ -1080,8 +1083,8 @@ void handleMethodArguments(LIRInstruction op) { if (op instanceof MoveOp) { MoveOp move = (MoveOp) op; - if (isStackSlot(move.getInput()) && move.getInput().getKind() != Kind.Object) { - StackSlot slot = (StackSlot) move.getInput(); + if (optimizeMethodArgument(move.getInput())) { + StackSlot slot = asStackSlot(move.getInput()); if (GraalOptions.DetailedAsserts) { assert op.id() > 0 : "invalid id"; assert blockForId(op.id()).getPredecessorCount() == 0 : "move from stack must be in first block"; diff -r 65ba93f118d4 -r a69eb5f539d9 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 Mon Mar 18 21:33:34 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Mar 18 19:39:25 2013 -0700 @@ -467,7 +467,7 @@ } } - append(new ParametersOp(params)); + emitIncomingValues(params); for (LocalNode local : graph.getNodes(LocalNode.class)) { Value param = params[local.index()]; @@ -476,6 +476,10 @@ } } + public void emitIncomingValues(Value[] params) { + append(new ParametersOp(params)); + } + /** * Increases the number of currently locked monitors and makes sure that a lock data slot is * available for the new lock. diff -r 65ba93f118d4 -r a69eb5f539d9 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 Mon Mar 18 21:33:34 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Mar 18 19:39:25 2013 -0700 @@ -740,6 +740,8 @@ } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { // Nothing to do for division nodes. The HotSpot signal handler catches divisions by // zero and the MIN_VALUE / -1 cases. + } else if (n instanceof UnwindNode || n instanceof ExceptionObjectNode) { + // Nothing to do, using direct LIR lowering for these nodes. } else { assert false : "Node implementing Lowerable not handled: " + n; throw GraalInternalError.shouldNotReachHere(); diff -r 65ba93f118d4 -r a69eb5f539d9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java Mon Mar 18 21:33:34 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +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.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * Access the value of a specific register. - */ -@NodeInfo(nameTemplate = "Register %{p#register}") -public final class RegisterNode extends FixedWithNextNode implements LIRLowerable { - - private final Register register; - - public RegisterNode(Register register, Kind kind) { - super(StampFactory.forKind(kind)); - this.register = register; - } - - public RegisterNode(Register register) { - super(StampFactory.object()); - this.register = register; - } - - @Override - public void generate(LIRGeneratorTool generator) { - Value result; - if (generator.attributes(register).isAllocatable()) { - // The register allocator would prefer us not to tie up an allocatable - // register for the complete lifetime of this node. - result = generator.newVariable(kind()); - generator.emitMove(result, register.asValue(kind())); - } else { - result = register.asValue(kind()); - } - generator.setResult(this, result); - } - - @Override - public String toString(Verbosity verbosity) { - if (verbosity == Verbosity.Name) { - return super.toString(Verbosity.Name) + "%" + register; - } else { - return super.toString(verbosity); - } - } -} diff -r 65ba93f118d4 -r a69eb5f539d9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Mon Mar 18 21:33:34 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Mon Mar 18 19:39:25 2013 -0700 @@ -34,6 +34,7 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.snippets.Snippet.Fold; +import com.oracle.graal.snippets.nodes.*; import com.oracle.graal.word.*; //JaCoCo Exclude @@ -338,22 +339,22 @@ * Gets the value of the stack pointer register as a Word. */ public static Word stackPointer() { - return HotSpotSnippetUtils.registerAsWord(stackPointerRegister()); + return HotSpotSnippetUtils.registerAsWord(stackPointerRegister(), true, false); } /** * Gets the value of the thread register as a Word. */ public static Word thread() { - return HotSpotSnippetUtils.registerAsWord(threadRegister()); + return HotSpotSnippetUtils.registerAsWord(threadRegister(), true, false); } public static Word loadWordFromObject(Object object, int offset) { return loadWordFromObjectIntrinsic(object, 0, offset, wordKind()); } - @NodeIntrinsic(value = RegisterNode.class, setStampFromReturnType = true) - public static native Word registerAsWord(@ConstantNodeParameter Register register); + @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true) + public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming); @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) private static native Word loadWordFromObjectIntrinsic(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind wordKind); diff -r 65ba93f118d4 -r a69eb5f539d9 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Mar 18 21:33:34 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Mar 18 19:39:25 2013 -0700 @@ -962,7 +962,7 @@ } } - private void emitExplicitExceptions(ValueNode receiver, ValueNode outOfBoundsIndex) { + protected void emitExplicitExceptions(ValueNode receiver, ValueNode outOfBoundsIndex) { assert receiver != null; if (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == ExceptionSeen.FALSE) { return; diff -r 65ba93f118d4 -r a69eb5f539d9 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Mar 18 21:33:34 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Mar 18 19:39:25 2013 -0700 @@ -45,7 +45,7 @@ protected final ResolvedJavaMethod callTarget; - protected DirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + public DirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { this.callTarget = callTarget; this.result = result; this.parameters = parameters; @@ -123,7 +123,7 @@ protected final InvokeTarget callTarget; - protected IndirectCallOp(InvokeTarget callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) { + public IndirectCallOp(InvokeTarget callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) { this.callTarget = callTarget; this.result = result; this.parameters = parameters; diff -r 65ba93f118d4 -r a69eb5f539d9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Mon Mar 18 21:33:34 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Mon Mar 18 19:39:25 2013 -0700 @@ -31,7 +31,7 @@ * Unwind takes an exception object, destroys the current stack frame and passes the exception * object to the system's exception dispatch code. */ -public final class UnwindNode extends FixedNode implements LIRLowerable, Node.IterableNodeType { +public final class UnwindNode extends FixedNode implements Lowerable, LIRLowerable, Node.IterableNodeType { @Input private ValueNode exception; @@ -49,4 +49,9 @@ public void generate(LIRGeneratorTool gen) { gen.emitUnwind(gen.operand(exception())); } + + @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } } diff -r 65ba93f118d4 -r a69eb5f539d9 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon Mar 18 21:33:34 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon Mar 18 19:39:25 2013 -0700 @@ -32,7 +32,7 @@ * The {@code ExceptionObject} instruction represents the incoming exception object to an exception * handler. */ -public class ExceptionObjectNode extends AbstractStateSplit implements StateSplit, LIRLowerable, MemoryCheckpoint { +public class ExceptionObjectNode extends AbstractStateSplit implements StateSplit, Lowerable, LIRLowerable, MemoryCheckpoint { /** * Constructs a new ExceptionObject instruction. @@ -52,6 +52,11 @@ } @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @Override public boolean verify() { assertTrue(stateAfter() != null, "an exception handler needs a frame state"); return super.verify(); diff -r 65ba93f118d4 -r a69eb5f539d9 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Mar 18 21:33:34 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Mar 18 19:39:25 2013 -0700 @@ -212,6 +212,12 @@ public static boolean IntrinsifyAESMethods = true; /** + * Method arguments that are passed on the stack can be optimized by the register allocator to avoid spilling + * and reloading. However, this requires that the runtime visits method arguments during stack walking. + */ + public static boolean IncomingMethodArgumentsGCSafe = true; + + /** * Counts the various paths taken through snippets. */ public static boolean SnippetCounters = false; diff -r 65ba93f118d4 -r a69eb5f539d9 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Mon Mar 18 21:33:34 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Mon Mar 18 19:39:25 2013 -0700 @@ -560,7 +560,7 @@ * @param args the arguments to be bound to the flattened positional parameters of the snippet * @return the map of duplicated nodes (original -> duplicate) */ - public Map instantiate(MetaAccessProvider runtime, FixedWithNextNode replacee, UsageReplacer replacer, SnippetTemplate.Arguments args) { + public Map instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, SnippetTemplate.Arguments args) { // Inline the snippet nodes, replacing parameters with the given args in the process String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; @@ -575,8 +575,12 @@ // Re-wire the control flow graph around the replacee FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); replacee.replaceAtPredecessor(firstCFGNodeDuplicate); - FixedNode next = replacee.next(); - replacee.setNext(null); + FixedNode next = null; + if (replacee instanceof FixedWithNextNode) { + FixedWithNextNode fwn = (FixedWithNextNode) replacee; + next = fwn.next(); + fwn.setNext(null); + } if (replacee instanceof StateSplit) { for (StateSplit sideEffectNode : sideEffectNodes) { diff -r 65ba93f118d4 -r a69eb5f539d9 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/ReadRegisterNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/ReadRegisterNode.java Mon Mar 18 19:39:25 2013 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2012, 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.snippets.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + +/** + * Access the value of a specific register. + */ +@NodeInfo(nameTemplate = "ReadRegister %{p#register}") +public final class ReadRegisterNode extends FixedWithNextNode implements LIRGenLowerable { + + /** + * The fixed register to access. + */ + private final Register register; + + /** + * When true, subsequent uses of this node use the fixed register; when false, the value is + * moved into a new virtual register so that the fixed register is not seen by uses. + */ + private final boolean directUse; + + /** + * When true, this node is also an implicit definition of the value for the register allocator, + * i.e., the register is an implicit incoming value; when false, the register must be defined in + * the same method or must be an register excluded from register allocation. + */ + private final boolean incoming; + + public ReadRegisterNode(Register register, Kind kind, boolean directUse, boolean incoming) { + super(StampFactory.forKind(kind)); + this.register = register; + this.directUse = directUse; + this.incoming = incoming; + } + + /** + * Constructor to be used by node intrinsics where the stamp is inferred from the intrinsic + * definition. + */ + public ReadRegisterNode(Register register, boolean directUse, boolean incoming) { + super(StampFactory.forNodeIntrinsic()); + this.register = register; + this.directUse = directUse; + this.incoming = incoming; + } + + @Override + public void generate(LIRGenerator generator) { + Value result = register.asValue(kind()); + if (incoming) { + generator.emitIncomingValues(new Value[]{result}); + } + if (!directUse) { + result = generator.emitMove(result); + } + generator.setResult(this, result); + } + + @Override + public String toString(Verbosity verbosity) { + if (verbosity == Verbosity.Name) { + return super.toString(Verbosity.Name) + "%" + register; + } else { + return super.toString(verbosity); + } + } +} diff -r 65ba93f118d4 -r a69eb5f539d9 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/WriteRegisterNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/WriteRegisterNode.java Mon Mar 18 19:39:25 2013 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013, 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.snippets.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Changes the value of a specific register. + */ +@NodeInfo(nameTemplate = "WriteRegister %{p#register}") +public final class WriteRegisterNode extends FixedWithNextNode implements LIRLowerable { + + /** + * The fixed register to access. + */ + private final Register register; + + /** + * The new value assigned to the register. + */ + @Input private ValueNode value; + + public WriteRegisterNode(Register register, ValueNode value) { + super(StampFactory.forVoid()); + this.register = register; + this.value = value; + } + + @Override + public void generate(LIRGeneratorTool generator) { + Value val = generator.operand(value); + generator.emitMove(val, register.asValue(val.getKind())); + } + + @Override + public String toString(Verbosity verbosity) { + if (verbosity == Verbosity.Name) { + return super.toString(Verbosity.Name) + "%" + register; + } else { + return super.toString(verbosity); + } + } +}