# HG changeset patch # User Lukas Stadler # Date 1309963861 -7200 # Node ID ce7e5b3798f761bd4e609ef9e43c2b4e2bf6c089 # Parent 2b1eace223b0c15ecfd4e477432b4693f10969ea# Parent 8044bdfaab06c7e9d77032467d55315e992bfb4f merge diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java Wed Jul 06 16:51:01 2011 +0200 @@ -52,10 +52,9 @@ public final RiMethod method; public final RiRegisterConfig registerConfig; public final CiStatistics stats; - public final CiAssumptions assumptions = new CiAssumptions(); public final FrameState placeholderState; - public CompilerGraph graph = new CompilerGraph(this); + public final CompilerGraph graph; private boolean hasExceptionHandlers; private final GraalCompilation parent; @@ -92,6 +91,7 @@ this.compiler = compiler; this.target = compiler.target; this.runtime = compiler.runtime; + this.graph = new CompilerGraph(runtime); this.method = method; this.stats = stats == null ? new CiStatistics() : stats; this.registerConfig = method == null ? compiler.globalStubRegisterConfig : runtime.getRegisterConfig(method); @@ -139,16 +139,6 @@ } /** - * Records an assumption that the specified type has no finalizable subclasses. - * - * @param receiverType the type that is assumed to have no finalizable subclasses - * @return {@code true} if the assumption was recorded and can be assumed; {@code false} otherwise - */ - public boolean recordNoFinalizableSubclassAssumption(RiType receiverType) { - return false; - } - - /** * Converts this compilation to a string. * * @return a string representation of this compilation @@ -285,8 +275,8 @@ lirAssembler.emitTraps(); CiTargetMethod targetMethod = assembler().finishTargetMethod(method, runtime, lirAssembler.registerRestoreEpilogueOffset, false); - if (assumptions.count() > 0) { - targetMethod.setAssumptions(assumptions); + if (graph.assumptions().count() > 0) { + targetMethod.setAssumptions(graph.assumptions()); } if (compiler.isObserved()) { diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Wed Jul 06 16:51:01 2011 +0200 @@ -153,8 +153,10 @@ public static boolean CommentedAssembly = ____; public static boolean PrintLIRWithAssembly = ____; + public static boolean OptReadElimination = ____; public static boolean OptGVN = ____; public static boolean OptCanonicalizer = true; public static boolean OptLoops = ____; + public static boolean OptOptimisticSchedule = ____; public static boolean LoopPeeling = ____; } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Wed Jul 06 16:51:01 2011 +0200 @@ -203,6 +203,10 @@ this.operands = new OperandPool(compilation.target); } + public CiTarget target() { + return compilation.target; + } + public LIRList lir() { return lir; } @@ -476,19 +480,14 @@ } public void emitBooleanBranch(Node node, LIRBlock trueSuccessor, LIRBlock falseSuccessor, LIRDebugInfo info) { - if (node instanceof Compare) { + if (node instanceof NegateBooleanNode) { + emitBooleanBranch(((NegateBooleanNode) node).value(), falseSuccessor, trueSuccessor, info); + } else if (node instanceof Compare) { emitCompare((Compare) node, trueSuccessor, falseSuccessor); } else if (node instanceof InstanceOf) { emitInstanceOf((TypeCheck) node, trueSuccessor, falseSuccessor, info); - } else if (node instanceof NotInstanceOf) { - emitInstanceOf((TypeCheck) node, falseSuccessor, trueSuccessor, info); } else if (node instanceof Constant) { - CiConstant constant = ((Constant) node).asConstant(); - assert constant.kind == CiKind.Boolean; - LIRBlock target = constant.asBoolean() ? trueSuccessor : falseSuccessor; - if (target != null) { - lir.jump(target); - } + emitConstantBranch(((Constant) node).asConstant().asBoolean(), trueSuccessor, falseSuccessor, info); } else { throw Util.unimplemented(node.toString()); } @@ -503,6 +502,21 @@ instr.setFalseSuccessor(falseSuccessor); } + + public void emitConstantBranch(boolean value, LIRBlock trueSuccessorBlock, LIRBlock falseSuccessorBlock, LIRDebugInfo info) { + if (value) { + emitConstantBranch(trueSuccessorBlock, info); + } else { + emitConstantBranch(falseSuccessorBlock, info); + } + } + + private void emitConstantBranch(LIRBlock block, LIRDebugInfo info) { + if (block != null) { + lir.jump(block); + } + } + public void emitCompare(Compare compare, LIRBlock trueSuccessorBlock, LIRBlock falseSuccessorBlock) { CiKind kind = compare.x().kind; @@ -585,20 +599,11 @@ } protected FrameState stateBeforeInvokeReturn(Invoke invoke) { - return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.stateAfter().rethrowException(), invoke.kind); + return invoke.stateAfter().duplicateModified(invoke.bci, invoke.stateAfter().rethrowException(), invoke.kind); } protected FrameState stateBeforeInvokeWithArguments(Invoke invoke) { - Value[] args = new Value[invoke.argumentCount()]; - for (int i = 0; i < invoke.argumentCount(); i++) { - args[i] = invoke.argument(i); - } - return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.stateAfter().rethrowException(), invoke.kind, args); - } - - private int getBeforeInvokeBci(Invoke invoke) { - // Cannot calculate BCI, because the invoke can have changed from e.g. invokeinterface to invokespecial because of optimizations. - return invoke.bci; + return invoke.stateAfter().duplicateModified(invoke.bci, invoke.stateAfter().rethrowException(), invoke.kind, invoke.arguments().toArray(new Value[0])); } @Override @@ -751,8 +756,11 @@ @Override public void visitFixedGuard(FixedGuard fixedGuard) { - BooleanNode comp = fixedGuard.node(); - emitGuardComp(comp); + for (Node n : fixedGuard.inputs()) { + if (n != null) { + emitGuardComp((BooleanNode) n); + } + } } public void emitGuardComp(BooleanNode comp) { @@ -772,14 +780,18 @@ FrameState state = lastState; assert state != null : "deoptimize instruction always needs a state"; + if (comp instanceof Constant && comp.asConstant().asBoolean()) { + // Nothing to emit. + } else { if (deoptimizationStubs == null) { deoptimizationStubs = new ArrayList(); } + DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state); deoptimizationStubs.add(stub); - emitBooleanBranch(comp, null, new LIRBlock(stub.label, stub.info), stub.info); } + } } @Override @@ -1103,7 +1115,7 @@ * @return the operand that is guaranteed to be a stack location when it is * initially defined a by move from {@code value} */ - CiValue forceToSpill(CiValue value, CiKind kind, boolean mustStayOnStack) { + public CiValue forceToSpill(CiValue value, CiKind kind, boolean mustStayOnStack) { assert value.isLegal() : "value should not be illegal"; assert kind.jvmSlots == value.kind.jvmSlots : "size mismatch"; if (!value.isVariableOrRegister()) { @@ -1470,8 +1482,11 @@ @Override public void visitEndNode(EndNode end) { setNoResult(end); + assert end.merge() != null; moveToPhi(end.merge(), end); - lir.jump(getLIRBlock(end.merge())); + LIRBlock lirBlock = getLIRBlock(end.merge()); + assert lirBlock != null : end; + lir.jump(lirBlock); } @Override @@ -1584,7 +1599,7 @@ x.clearOperand(); } - protected CiValue setResult(Value x, CiVariable operand) { + public CiValue setResult(Value x, CiVariable operand) { x.setOperand(operand); if (GraalOptions.DetailedAsserts) { operands.recordResult(operand, x); @@ -1653,10 +1668,9 @@ List visitInvokeArguments(CiCallingConvention cc, Invoke x, List pointerSlots) { // for each argument, load it into the correct location - List argList = new ArrayList(x.argumentCount()); + List argList = new ArrayList(); int j = 0; - for (int i = 0; i < x.argumentCount(); i++) { - Value arg = x.argument(i); + for (Value arg : x.arguments()) { if (arg != null) { CiValue operand = cc.locations[j++]; if (operand.isRegister()) { diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java Wed Jul 06 16:51:01 2011 +0200 @@ -126,7 +126,7 @@ final HashSet successors = new LinkedHashSet(); private boolean visited; private boolean active; - private int loops; + private long loops; } public static class ExceptionBlock extends Block { @@ -485,7 +485,7 @@ } private void computeBlockOrder() { - int loop = computeBlockOrder(blockMap[0]); + long loop = computeBlockOrder(blockMap[0]); if (loop != 0) { // There is a path from a loop end to the method entry that does not pass the loop header. @@ -501,7 +501,7 @@ /** * The next available loop number. */ - private int nextLoop = 0; + private int nextLoop; /** * Mark the block as a loop header, using the next available loop number. @@ -516,7 +516,7 @@ // Don't compile such methods for now, until we see a concrete case that allows checking for correctness. throw new CiBailout("Loop formed by an exception handler"); } - if (nextLoop >= Integer.SIZE) { + if (nextLoop >= Long.SIZE) { // This restriction can be removed by using a fall-back to a BitSet in case we have more than 32 loops // Don't compile such methods for now, until we see a concrete case that allows checking for correctness. throw new CiBailout("Too many loops in method"); @@ -526,7 +526,7 @@ block.loops = 1 << nextLoop; nextLoop++; } - assert Integer.bitCount(block.loops) == 1; + assert Long.bitCount(block.loops) == 1; } /** @@ -534,7 +534,7 @@ * visit every block only once. The flag {@linkplain Block#active} is used to detect cycles (backward * edges). */ - private int computeBlockOrder(Block block) { + private long computeBlockOrder(Block block) { if (block.visited) { if (block.active) { // Reached block via backward branch. @@ -557,7 +557,7 @@ processLoopBlock(block); } if (block.isLoopHeader) { - assert Integer.bitCount(block.loops) == 1; + assert Long.bitCount(block.loops) == 1; loops &= ~block.loops; } @@ -694,6 +694,6 @@ } out.println(); - out.print("loop_depth ").println(Integer.bitCount(block.loops)); + out.print("loop_depth ").println(Long.bitCount(block.loops)); } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/CompilerGraph.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/CompilerGraph.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/CompilerGraph.java Wed Jul 06 16:51:01 2011 +0200 @@ -22,21 +22,22 @@ */ package com.oracle.max.graal.compiler.graph; -import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; import com.sun.cri.ri.*; public class CompilerGraph extends Graph { + private RiRuntime runtime; private Return returnSingleton; private Unwind unwindSingleton; - private GraalCompilation compilation; + private CiAssumptions assumptions = new CiAssumptions(); - public CompilerGraph(GraalCompilation compilation) { - this.compilation = compilation; + public CompilerGraph(RiRuntime runtime) { + this.runtime = runtime; } public void setReturn(Return returnNode) { @@ -58,10 +59,10 @@ } public RiRuntime runtime() { - return compilation.runtime; + return runtime; } - public GraalCompilation getCompilation() { - return compilation; + public CiAssumptions assumptions() { + return assumptions; } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Wed Jul 06 16:51:01 2011 +0200 @@ -76,18 +76,15 @@ // replacements.put(duplicate.start(), compilation.graph.start()); // compilation.graph.addDuplicate(duplicate.getNodes(), replacements); // } else { - new GraphBuilderPhase(compilation, compilation.method, false, false).apply(compilation.graph); + new GraphBuilderPhase(compilation, compilation.method, false).apply(compilation.graph); // } - //printGraph("After GraphBuilding", compilation.graph); if (GraalOptions.TestGraphDuplication) { new DuplicationPhase().apply(compilation.graph); - //printGraph("After Duplication", compilation.graph); } new DeadCodeEliminationPhase().apply(compilation.graph); - //printGraph("After DeadCodeElimination", compilation.graph); if (GraalOptions.Inline) { new InliningPhase(compilation, this, null).apply(compilation.graph); @@ -104,9 +101,8 @@ new LoopPhase().apply(graph); } - if (GraalOptions.EscapeAnalysis /*&& compilation.method.toString().contains("simplify")*/) { + if (GraalOptions.EscapeAnalysis) { new EscapeAnalysisPhase(compilation, this).apply(graph); - // new DeadCodeEliminationPhase().apply(graph); new CanonicalizerPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); } @@ -115,17 +111,20 @@ new GlobalValueNumberingPhase().apply(graph); } + new LoweringPhase(compilation.runtime).apply(graph); if (GraalOptions.Lower) { - new LoweringPhase(compilation.runtime).apply(graph); new MemoryPhase().apply(graph); if (GraalOptions.OptGVN) { new GlobalValueNumberingPhase().apply(graph); } - new ReadEliminationPhase().apply(graph); + if (GraalOptions.OptReadElimination) { + new ReadEliminationPhase().apply(graph); + } } IdentifyBlocksPhase schedule = new IdentifyBlocksPhase(true); schedule.apply(graph); + compilation.stats.loopCount = schedule.loopCount(); List blocks = schedule.getBlocks(); @@ -136,6 +135,8 @@ map.put(b, block); block.setInstructions(b.getInstructions()); block.setLinearScanNumber(b.blockID()); + block.setLoopDepth(b.loopDepth()); + block.setLoopIndex(b.loopIndex()); block.setFirstInstruction(b.firstNode()); block.setLastInstruction(b.lastNode()); @@ -170,7 +171,6 @@ ComputeLinearScanOrder clso = new ComputeLinearScanOrder(lirBlocks.size(), startBlock); orderedBlocks = clso.linearScanOrder(); - this.compilation.stats.loopCount = clso.numLoops(); int z = 0; for (LIRBlock b : orderedBlocks) { diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java Wed Jul 06 16:51:01 2011 +0200 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.ir; + +import java.util.*; + +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public abstract class AbstractVectorNode extends StateSplit { + + private static final int INPUT_COUNT = 1; + private static final int INPUT_VECTOR = 0; + private static final int SUCCESSOR_COUNT = 0; + + @Override + protected int inputCount() { + return super.inputCount() + INPUT_COUNT; + } + + @Override + protected int successorCount() { + return super.successorCount() + SUCCESSOR_COUNT; + } + + public void setVector(AbstractVectorNode length) { + inputs().set(super.inputCount() + INPUT_VECTOR, length); + } + + public AbstractVectorNode vector() { + return (AbstractVectorNode) inputs().get(super.inputCount() + INPUT_VECTOR); + } + + public AbstractVectorNode(CiKind kind, int inputCount, int successorCount, AbstractVectorNode vector, Graph graph) { + super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph); + setVector(vector); + } + + protected static AbstractVectorNode findCommonNode(AbstractVectorNode left, AbstractVectorNode right, List leftList, List rightList) { + Set occured = new HashSet(); + AbstractVectorNode common = null; + AbstractVectorNode cur = left; + while (cur != null) { + occured.add(cur); + cur = cur.vector(); + } + + cur = right; + while (cur != null) { + if (occured.contains(cur)) { + common = cur; + break; + } + cur = cur.vector(); + } + + fillUntil(left, cur, leftList); + fillUntil(right, cur, rightList); + return common; + } + + private static void fillUntil(AbstractVectorNode left, AbstractVectorNode until, List leftList) { + AbstractVectorNode cur = left; + while (cur != null && cur != until) { + leftList.add(cur); + cur = cur.vector(); + } + } + + public void addToLoop(LoopBegin loop, IdentityHashMap nodes) { + throw new IllegalStateException("unimplemented"); + } +} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessVectorNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessVectorNode.java Wed Jul 06 16:51:01 2011 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.ir; + +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public abstract class AccessVectorNode extends AbstractVectorNode { + private static final int INPUT_COUNT = 2; + private static final int INPUT_OBJECT = 0; + private static final int INPUT_LOCATION = 1; + private static final int SUCCESSOR_COUNT = 0; + + @Override + protected int inputCount() { + return super.inputCount() + INPUT_COUNT; + } + + @Override + protected int successorCount() { + return super.successorCount() + SUCCESSOR_COUNT; + } + + public void setObject(Value object) { + inputs().set(super.inputCount() + INPUT_OBJECT, object); + } + + public Value object() { + return (Value) inputs().get(super.inputCount() + INPUT_OBJECT); + } + + public void setLocation(LocationNode object) { + inputs().set(super.inputCount() + INPUT_LOCATION, object); + } + + public LocationNode location() { + return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION); + } + + public AccessVectorNode(CiKind kind, int inputCount, int successorCount, AbstractVectorNode vector, Value object, LocationNode location, Graph graph) { + super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, vector, graph); + setObject(object); + setLocation(location); + } +} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java Wed Jul 06 16:51:01 2011 +0200 @@ -95,8 +95,7 @@ @Override public Node copy(Graph into) { - ArrayLength x = new ArrayLength(null, into); - return x; + return new ArrayLength(null, into); } @SuppressWarnings("unchecked") @@ -128,7 +127,7 @@ if (constantValue != null && constantValue.isNonNull()) { Graph graph = node.graph(); if (graph instanceof CompilerGraph) { - RiRuntime runtime = ((CompilerGraph) graph).getCompilation().runtime; + RiRuntime runtime = ((CompilerGraph) graph).runtime(); return Constant.forInt(runtime.getArrayLength(constantValue), graph); } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java Wed Jul 06 16:51:01 2011 +0200 @@ -31,9 +31,4 @@ public BooleanNode(CiKind kind, int inputCount, int successorCount, Graph graph) { super(kind, inputCount, successorCount, graph); } - - - public BooleanNode negate() { - throw new IllegalStateException(); - } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CastNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CastNode.java Wed Jul 06 16:51:01 2011 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.ir; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class CastNode extends FloatingNode { + private static final int INPUT_COUNT = 1; + private static final int INPUT_NODE = 0; + + private static final int SUCCESSOR_COUNT = 0; + + /** + * The instruction that produces the object tested against null. + */ + public Value value() { + return (Value) inputs().get(super.inputCount() + INPUT_NODE); + } + + public void setValue(Value n) { + inputs().set(super.inputCount() + INPUT_NODE, n); + } + + public CastNode(CiKind kind, Value n, Graph graph) { + super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph); + setValue(n); + } + + @Override + public void accept(ValueVisitor v) { + } + + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return (T) new LIRGenerator.LIRGeneratorOp() { + @Override + public void generate(Node n, LIRGenerator generator) { + CastNode conv = (CastNode) n; + conv.setOperand(generator.load(conv.value())); + } + }; + } + return super.lookup(clazz); + } + + @Override + public void print(LogStream out) { + out.print("cast node ").print(value().toString()); + } + + @Override + public Node copy(Graph into) { + return new CastNode(kind, null, into); + } +} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java Wed Jul 06 16:51:01 2011 +0200 @@ -43,7 +43,7 @@ * @param object the instruction producing the object * @param graph */ - public CheckCast(Constant targetClassInstruction, Value object, Graph graph) { + public CheckCast(Value targetClassInstruction, Value object, Graph graph) { super(targetClassInstruction, object, CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph); } @@ -92,8 +92,7 @@ @Override public Node copy(Graph into) { - CheckCast x = new CheckCast(null, null, into); - return x; + return new CheckCast(null, null, into); } private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java Wed Jul 06 16:51:01 2011 +0200 @@ -157,11 +157,6 @@ return x; } - @Override - public BooleanNode negate() { - return new Compare(x(), condition.negate(), y(), graph()); - } - private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override public Node canonical(Node node) { @@ -197,7 +192,7 @@ } BooleanNode result = materializeNode.value(); if (isFalseCheck) { - result = result.negate(); + result = new NegateBooleanNode(result, compare.graph()); } if (GraalOptions.TraceCanonicalizer) { TTY.println("Removed materialize replacing with " + result); diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java Wed Jul 06 16:51:01 2011 +0200 @@ -28,16 +28,12 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; -import com.sun.cri.ci.*; public final class ComputeLinearScanOrder { private final int maxBlockId; // the highest blockId of a block private int numBlocks; // total number of blocks (smaller than maxBlockId) - private int numLoops; // total number of loops - private boolean iterativeDominators; // method requires iterative computation of dominators List linearScanOrder; // the resulting list of blocks in correct order @@ -45,8 +41,6 @@ final BitMap activeBlocks; // used for recursive processing of blocks final BitMap dominatorBlocks; // temporary BitMap used for computation of dominator final int[] forwardBranches; // number of incoming forward branches for each block - final List loopEndBlocks; // list of all loop end blocks collected during countEdges - BitMap2D loopMap; // two-dimensional bit set: a bit is set if a block is contained in a loop final List workList; // temporary list (used in markLoops and computeOrder) // accessors for visitedBlocks and activeBlocks @@ -87,28 +81,11 @@ return --forwardBranches[b.blockID()]; } - // accessors for loopMap - boolean isBlockInLoop(int loopIdx, LIRBlock b) { - return loopMap.at(loopIdx, b.blockID()); - } - - void setBlockInLoop(int loopIdx, LIRBlock b) { - loopMap.setBit(loopIdx, b.blockID()); - } - - void clearBlockInLoop(int loopIdx, int blockId) { - loopMap.clearBit(loopIdx, blockId); - } - // accessors for final result public List linearScanOrder() { return linearScanOrder; } - public int numLoops() { - return numLoops; - } - public ComputeLinearScanOrder(int maxBlockId, LIRBlock startBlock) { this.maxBlockId = maxBlockId; @@ -116,27 +93,11 @@ activeBlocks = new BitMap(maxBlockId); dominatorBlocks = new BitMap(maxBlockId); forwardBranches = new int[maxBlockId]; - loopEndBlocks = new ArrayList(8); workList = new ArrayList(8); - splitCriticalEdges(); - countEdges(startBlock, null); - - if (numLoops > 0) { - markLoops(); - clearNonNaturalLoops(startBlock); - assignLoopDepth(startBlock); - } - computeOrder(startBlock); - printBlocks(); - assert verify(); - } - - void splitCriticalEdges() { - // TODO: move critical edge splitting from IR to here } /** @@ -153,16 +114,6 @@ } if (isActive(cur)) { - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("backward branch"); - } - assert isVisited(cur) : "block must be visited when block is active"; - assert parent != null : "must have parent"; - - cur.setLinearScanLoopHeader(); - parent.setLinearScanLoopEnd(); - - loopEndBlocks.add(parent); return; } @@ -188,137 +139,11 @@ clearActive(cur); - // Each loop has a unique number. - // When multiple loops are nested, assignLoopDepth assumes that the - // innermost loop has the lowest number. This is guaranteed by setting - // the loop number after the recursive calls for the successors above - // have returned. - if (cur.isLinearScanLoopHeader()) { - assert cur.loopIndex() == -1 : "cannot set loop-index twice"; - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("Block B%d is loop header of loop %d", cur.blockID(), numLoops); - } - - cur.setLoopIndex(numLoops); - numLoops++; - } - if (GraalOptions.TraceLinearScanLevel >= 3) { TTY.println("Finished counting edges for block B%d", cur.blockID()); } } - void markLoops() { - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("----- marking loops"); - } - - loopMap = new BitMap2D(numLoops, maxBlockId); - - for (int i = loopEndBlocks.size() - 1; i >= 0; i--) { - LIRBlock loopEnd = loopEndBlocks.get(i); - LIRBlock loopStart = loopEnd.suxAt(0); - int loopIdx = loopStart.loopIndex(); - - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("Processing loop from B%d to B%d (loop %d):", loopStart.blockID(), loopEnd.blockID(), loopIdx); - } - assert loopEnd.isLinearScanLoopEnd() : "loop end flag must be set"; -// assert loopEnd.numberOfSux() == 1 : "incorrect number of successors"; - assert loopStart.isLinearScanLoopHeader() : "loop header flag must be set"; - assert loopIdx >= 0 && loopIdx < numLoops : "loop index not set"; - assert workList.isEmpty() : "work list must be empty before processing"; - - // add the end-block of the loop to the working list - workList.add(loopEnd); - setBlockInLoop(loopIdx, loopEnd); - do { - LIRBlock cur = workList.remove(workList.size() - 1); - - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println(" processing B%d", cur.blockID()); - } - assert isBlockInLoop(loopIdx, cur) : "bit in loop map must be set when block is in work list"; - - // recursive processing of all predecessors ends when start block of loop is reached - if (cur != loopStart) { - for (int j = cur.numberOfPreds() - 1; j >= 0; j--) { - LIRBlock pred = cur.predAt(j); - - if (!isBlockInLoop(loopIdx, pred)) { - // this predecessor has not been processed yet, so add it to work list - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println(" pushing B%d", pred.blockID()); - } - workList.add(pred); - setBlockInLoop(loopIdx, pred); - } - } - } - } while (!workList.isEmpty()); - } - } - - // check for non-natural loops (loops where the loop header does not dominate - // all other loop blocks = loops with multiple entries). - // such loops are ignored - void clearNonNaturalLoops(LIRBlock startBlock) { - for (int i = numLoops - 1; i >= 0; i--) { - if (isBlockInLoop(i, startBlock)) { - // loop i contains the entry block of the method. - // this is not a natural loop, so ignore it - if (GraalOptions.TraceLinearScanLevel >= 2) { - TTY.println("Loop %d is non-natural, so it is ignored", i); - } - - for (int blockId = maxBlockId - 1; blockId >= 0; blockId--) { - clearBlockInLoop(i, blockId); - } - iterativeDominators = true; - } - } - } - - void assignLoopDepth(LIRBlock startBlock) { - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("----- computing loop-depth and weight"); - } - initVisited(); - - assert workList.isEmpty() : "work list must be empty before processing"; - workList.add(startBlock); - - do { - LIRBlock cur = workList.remove(workList.size() - 1); - - if (!isVisited(cur)) { - setVisited(cur); - if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("Computing loop depth for block B%d", cur.blockID()); - } - - // compute loop-depth and loop-index for the block - assert cur.loopDepth() == 0 : "cannot set loop-depth twice"; - int i; - int loopDepth = 0; - int minLoopIdx = -1; - for (i = numLoops - 1; i >= 0; i--) { - if (isBlockInLoop(i, cur)) { - loopDepth++; - minLoopIdx = i; - } - } - cur.setLoopDepth(loopDepth); - cur.setLoopIndex(minLoopIdx); - - // append all unvisited successors to work list - for (i = cur.numberOfSux() - 1; i >= 0; i--) { - workList.add(cur.suxAt(i)); - } - } - } while (!workList.isEmpty()); - } - int computeWeight(LIRBlock cur) { // limit loop-depth to 15 bit (only for security reason, it will never be so big) @@ -329,10 +154,10 @@ // this is necessary for the (very rare) case that two successive blocks have // the same loop depth, but a different loop index (can happen for endless loops // with exception handlers) - if (!cur.isLinearScanLoopHeader()) { - weight |= 1 << curBit; - } - curBit--; +// if (!cur.isLinearScanLoopHeader()) { +// weight |= 1 << curBit; +// } +// curBit--; // loop end blocks (blocks that end with a backward branch) are added // after all other blocks of the loop. @@ -360,10 +185,10 @@ // curBit--; // exceptions handlers are added as late as possible -// if (!cur.isExceptionEntry()) { -// weight |= 1 << curBit; -// } -// curBit--; + if (!cur.isExceptionEntry()) { + weight |= 1 << curBit; + } + curBit--; // guarantee that weight is > 0 weight |= 1; @@ -374,7 +199,7 @@ return weight; } - boolean readyForProcessing(LIRBlock cur) { + private boolean readyForProcessing(LIRBlock cur) { // Discount the edge just traveled. // When the number drops to zero, all forward branches were processed if (decForwardBranches(cur) != 0) { @@ -386,7 +211,7 @@ return true; } - void sortIntoWorkList(LIRBlock cur) { + private void sortIntoWorkList(LIRBlock cur) { assert !workList.contains(cur) : "block already in work list"; int curWeight = computeWeight(cur); @@ -421,7 +246,7 @@ } } - void appendBlock(LIRBlock cur) { + private void appendBlock(LIRBlock cur) { if (GraalOptions.TraceLinearScanLevel >= 3) { TTY.println("appending block B%d (weight 0x%06x) to linear-scan order", cur.blockID(), cur.linearScanNumber()); } @@ -434,29 +259,22 @@ linearScanOrder.add(cur); } - void computeOrder(LIRBlock startBlock) { + private void computeOrder(LIRBlock startBlock) { if (GraalOptions.TraceLinearScanLevel >= 3) { TTY.println("----- computing final block order"); } // the start block is always the first block in the linear scan order linearScanOrder = new ArrayList(numBlocks); -// appendBlock(startBlock); - - LIRBlock stdEntry = startBlock; //.suxAt(0); // start processing with standard entry block assert workList.isEmpty() : "list must be empty before processing"; - if (readyForProcessing(stdEntry)) { - sortIntoWorkList(stdEntry); - } else { - throw new CiBailout("the stdEntry must be ready for processing (otherwise, the method has no start block)"); - } + assert readyForProcessing(startBlock); + sortIntoWorkList(startBlock); do { LIRBlock cur = workList.remove(workList.size() - 1); - appendBlock(cur); int i; @@ -476,9 +294,6 @@ TTY.println("----- loop information:"); for (LIRBlock cur : linearScanOrder) { TTY.print(String.format("%4d: B%02d: ", cur.linearScanNumber(), cur.blockID())); - for (int loopIdx = 0; loopIdx < numLoops; loopIdx++) { - TTY.print(String.format("%d = %b ", loopIdx, isBlockInLoop(loopIdx, cur))); - } TTY.println(String.format(" . loopIndex: %2d, loopDepth: %2d", cur.loopIndex(), cur.loopDepth())); } } @@ -512,76 +327,4 @@ } } } - - boolean verify() { - /* assert linearScanOrder.size() == numBlocks : "wrong number of blocks in list"; - - if (GraalOptions.StressLinearScan) { - // blocks are scrambled when StressLinearScan is used - return true; - } - - // check that all successors of a block have a higher linear-scan-number - // and that all predecessors of a block have a lower linear-scan-number - // (only backward branches of loops are ignored) - int i; - for (i = 0; i < linearScanOrder.size(); i++) { - BlockBegin cur = linearScanOrder.get(i); - - assert cur.linearScanNumber() == i : "incorrect linearScanNumber"; - assert cur.linearScanNumber() >= 0 && cur.linearScanNumber() == linearScanOrder.indexOf(cur) : "incorrect linearScanNumber"; - - for (BlockBegin sux : cur.end().successors()) { - assert sux.linearScanNumber() >= 0 && sux.linearScanNumber() == linearScanOrder.indexOf(sux) : "incorrect linearScanNumber"; - if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd)) { - assert cur.linearScanNumber() < sux.linearScanNumber() : "invalid order"; - } - if (cur.loopDepth() == sux.loopDepth()) { - assert cur.loopIndex() == sux.loopIndex() || sux.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index"; - } - } - - for (BlockBegin pred : cur.predecessors()) { - assert pred.linearScanNumber() >= 0 && pred.linearScanNumber() == linearScanOrder.indexOf(pred) : "incorrect linearScanNumber"; - if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) { - assert cur.linearScanNumber() > pred.linearScanNumber() : "invalid order"; - } - if (cur.loopDepth() == pred.loopDepth()) { - assert cur.loopIndex() == pred.loopIndex() || cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index"; - } - - assert cur.dominator().linearScanNumber() <= pred.linearScanNumber() : "dominator must be before predecessors"; - } - - // check dominator - if (i == 0) { - assert cur.dominator() == null : "first block has no dominator"; - } else { - assert cur.dominator() != null : "all but first block must have dominator"; - } - assert cur.numberOfPreds() != 1 || cur.dominator() == cur.predAt(0) || cur.isExceptionEntry() : "Single predecessor must also be dominator"; - } - - // check that all loops are continuous - for (int loopIdx = 0; loopIdx < numLoops; loopIdx++) { - int blockIdx = 0; - assert !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx)) : "the first block must not be present in any loop"; - - // skip blocks before the loop - while (blockIdx < numBlocks && !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx))) { - blockIdx++; - } - // skip blocks of loop - while (blockIdx < numBlocks && isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx))) { - blockIdx++; - } - // after the first non-loop block : there must not be another loop-block - while (blockIdx < numBlocks) { - assert !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx)) : "loop not continuous in linear-scan order"; - blockIdx++; - } - } -*/ - return true; - } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java Wed Jul 06 16:51:01 2011 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.max.graal.compiler.ir; -import com.sun.cri.bytecode.Bytecodes.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -173,10 +172,10 @@ case LE: return x <= y; case GT: return x > y; case GE: return x >= y; - case AE: return UnsignedComparisons.aboveOrEqual(x, y); - case BE: return UnsignedComparisons.belowOrEqual(x, y); - case AT: return UnsignedComparisons.aboveThan(x, y); - case BT: return UnsignedComparisons.belowThan(x, y); + case AE: return toUnsigned(x) >= toUnsigned(y); + case BE: return toUnsigned(x) <= toUnsigned(y); + case AT: return toUnsigned(x) > toUnsigned(y); + case BT: return toUnsigned(x) < toUnsigned(y); } break; } @@ -204,4 +203,11 @@ } return null; } + + private long toUnsigned(int x) { + if (x < 0) { + return ((long) (x & 0x7FFFFFFF)) + ((long) Integer.MAX_VALUE) + 1; + } + return x; + } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java Wed Jul 06 16:51:01 2011 +0200 @@ -55,14 +55,6 @@ v.visitConstant(this); } - @Override - public BooleanNode negate() { - if (value.kind != CiKind.Boolean) { - throw new IllegalStateException("boolean expected, actual: " + kind); - } - return Constant.forBoolean(!value.asBoolean(), graph()); - } - /** * Creates an instruction for a double constant. * @param d the double value for which to create the instruction @@ -179,7 +171,7 @@ public RiType declaredType() { RiRuntime runtime = compilation().runtime; if (kind.isPrimitive()) { - runtime.asRiType(kind); + return runtime.asRiType(kind); } return runtime.getTypeOf(asConstant()); } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java Wed Jul 06 16:51:01 2011 +0200 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.ir; + +import java.util.*; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.ir.Phi.PhiType; +import com.oracle.max.graal.compiler.phases.LoweringPhase.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class CreateVectorNode extends AbstractVectorNode { + private static final int INPUT_COUNT = 1; + private static final int INPUT_LENGTH = 0; + private static final int SUCCESSOR_COUNT = 0; + + private boolean reversed; + + public void setLength(Value length) { + assert length == null || length.kind == CiKind.Int; + inputs().set(super.inputCount() + INPUT_LENGTH, length); + } + + public boolean reversed() { + return reversed; + } + + public void setReversed(boolean r) { + reversed = r; + } + + public Value length() { + return (Value) inputs().get(super.inputCount() + INPUT_LENGTH); + } + + public CreateVectorNode(boolean reversed, Value length, Graph graph) { + super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, null, graph); + setLength(length); + setReversed(reversed); + } + + @Override + public Map getDebugProperties() { + Map debugProperties = super.getDebugProperties(); + debugProperties.put("reversed", reversed); + return debugProperties; + } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return null; + } else if (clazz == LoweringOp.class) { + return (T) LOWERING_OP; + } + return super.lookup(clazz); + } + + @Override + public void print(LogStream out) { + out.print("vector with length ").print(length().toString()); + } + + @Override + public Node copy(Graph into) { + return new CreateVectorNode(reversed, null, into); + } + + @Override + public boolean valueEqual(Node i) { + return (i instanceof CreateVectorNode); + } + + private LoopBegin createLoop(Map map) { + EndNode end = new EndNode(graph()); + LoopBegin loopBegin = new LoopBegin(graph()); + loopBegin.addEnd(end); + Phi loopVariable = new Phi(CiKind.Int, loopBegin, PhiType.Value, graph()); + + if (reversed) { + IntegerSub add = new IntegerSub(CiKind.Int, loopVariable, Constant.forInt(1, graph()), graph()); + loopVariable.addInput(new IntegerSub(CiKind.Int, length(), Constant.forInt(1, graph()), graph())); + loopVariable.addInput(add); + } else { + IntegerAdd add = new IntegerAdd(CiKind.Int, loopVariable, Constant.forInt(1, graph()), graph()); + loopVariable.addInput(Constant.forInt(0, graph())); + loopVariable.addInput(add); + } + + LoopEnd loopEnd = new LoopEnd(graph()); + loopEnd.setLoopBegin(loopBegin); + Compare condition; + if (reversed) { + condition = new Compare(loopVariable, Condition.GE, Constant.forInt(0, graph()), graph()); + } else { + condition = new Compare(loopVariable, Condition.LT, length(), graph()); + } + If ifNode = new If(condition, graph()); + loopBegin.setNext(ifNode); + ifNode.setTrueSuccessor(loopEnd); + this.replaceAtPredecessors(end); + ifNode.setFalseSuccessor(this); + map.put(this, loopVariable); + return loopBegin; + } + + private static final LoweringOp LOWERING_OP = new LoweringOp() { + @Override + public void lower(Node n, CiLoweringTool tool) { + CreateVectorNode vectorNode = (CreateVectorNode) n; + + IdentityHashMap nodes = new IdentityHashMap(); + LoopBegin begin = vectorNode.createLoop(nodes); + for (Node use : vectorNode.usages()) { + processUse(begin, use, nodes); + } + } + + private void processUse(LoopBegin loop, Node use, IdentityHashMap nodes) { + AbstractVectorNode vectorNode = (AbstractVectorNode) use; + if (nodes.containsKey(vectorNode)) { + return; + } + nodes.put(vectorNode, null); + + // Make sure inputs are evaluated. + for (Node input : use.inputs()) { + if (input instanceof AbstractVectorNode) { + AbstractVectorNode abstractVectorNodeInput = (AbstractVectorNode) input; + processUse(loop, abstractVectorNodeInput, nodes); + } + } + + vectorNode.addToLoop(loop, nodes); + + // Go on to usages. + for (Node usage : use.usages()) { + processUse(loop, usage, nodes); + } + } + }; +} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java Wed Jul 06 16:31:18 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.ir; - -import com.oracle.max.graal.compiler.debug.*; -import com.oracle.max.graal.graph.*; -import com.sun.cri.ci.*; -import com.sun.cri.ri.*; - -/** - * This instruction takes an exception object and has two successors: - * The catchSuccessor is called whenever the exception matches the given type, otherwise otherSuccessor is called. - */ -public final class ExceptionDispatch extends ControlSplit { - - private static final int INPUT_COUNT = 1; - private static final int INPUT_EXCEPTION = 0; - - private static final int SUCCESSOR_COUNT = 0; - - @Override - protected int inputCount() { - return super.inputCount() + INPUT_COUNT; - } - - @Override - protected int successorCount() { - return super.successorCount() + SUCCESSOR_COUNT; - } - - /** - * The instruction producing the exception object. - */ - public Value exception() { - return (Value) inputs().get(super.inputCount() + INPUT_EXCEPTION); - } - - public Value setException(Value n) { - return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n); - } - - private final RiType catchType; - - /** - * Constructs a new ExceptionDispatch instruction. - */ - public ExceptionDispatch(Value exception, FixedNode catchSuccessor, FixedNode otherSuccessor, RiType catchType, Graph graph) { - super(CiKind.Int, 2, INPUT_COUNT, SUCCESSOR_COUNT, graph); - setException(exception); - setBlockSuccessor(0, otherSuccessor); - setBlockSuccessor(1, catchSuccessor); - this.catchType = catchType; - } - - public RiType catchType() { - return catchType; - } - - /** - * Gets the block corresponding to the catch block. - * @return the true successor - */ - public FixedNode catchSuccessor() { - return blockSuccessor(1); - } - - /** - * Gets the block corresponding to the rest of the dispatch chain. - * @return the false successor - */ - public FixedNode otherSuccessor() { - return blockSuccessor(0); - } - - /** - * Gets the block corresponding to the specified outcome of the branch. - * @param istrue {@code true} if the true successor is requested, {@code false} otherwise - * @return the corresponding successor - */ - public FixedNode successor(boolean istrue) { - return blockSuccessor(istrue ? 1 : 0); - } - - @Override - public void accept(ValueVisitor v) { - v.visitExceptionDispatch(this); - } - - @Override - public void print(LogStream out) { - out.print("exception_dispatch "). - print(exception()). - print(' '). - print("instanceof"). - print(' '). - print(catchType().name()). - print(" then "). - print(catchSuccessor().toString()). - print(" else B"). - print(otherSuccessor().toString()); - } - - @Override - public String shortName() { - return "Dispatch " + catchType().name(); - } - - @Override - public Node copy(Graph into) { - ExceptionDispatch x = new ExceptionDispatch(null, null, null, catchType, into); - return x; - } -} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java Wed Jul 06 16:51:01 2011 +0200 @@ -31,25 +31,16 @@ public final class FixedGuard extends FixedNodeWithNext { - private static final int INPUT_COUNT = 1; - private static final int INPUT_NODE = 0; - + private static final int INPUT_COUNT = 0; private static final int SUCCESSOR_COUNT = 0; - /** - * The instruction that produces the object tested against null. - */ - public BooleanNode node() { - return (BooleanNode) inputs().get(super.inputCount() + INPUT_NODE); + public FixedGuard(BooleanNode node, Graph graph) { + this(graph); + addNode(node); } - public void setNode(BooleanNode n) { - inputs().set(super.inputCount() + INPUT_NODE, n); - } - - public FixedGuard(BooleanNode node, Graph graph) { + public FixedGuard(Graph graph) { super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); - setNode(node); } @Override @@ -59,12 +50,16 @@ @Override public void print(LogStream out) { - out.print("clip node ").print(node()); + out.print("clip node ").print(inputs().toString()); + } + + public void addNode(BooleanNode node) { + inputs().add(node); } @Override public Node copy(Graph into) { - return new FixedGuard(null, into); + return new FixedGuard(into); } @SuppressWarnings("unchecked") @@ -80,20 +75,26 @@ @Override public Node canonical(Node node) { FixedGuard fixedGuard = (FixedGuard) node; - if (fixedGuard.node() instanceof Constant) { - Constant c = (Constant) fixedGuard.node(); - if (c.asConstant().asBoolean()) { - if (GraalOptions.TraceCanonicalizer) { - TTY.println("Removing redundant fixed guard " + fixedGuard); + for (Node n : fixedGuard.inputs()) { + if (n instanceof Constant) { + Constant c = (Constant) n; + if (c.asConstant().asBoolean()) { + if (GraalOptions.TraceCanonicalizer) { + TTY.println("Removing redundant fixed guard " + fixedGuard); + } + fixedGuard.inputs().remove(c); + } else { + if (GraalOptions.TraceCanonicalizer) { + TTY.println("Replacing fixed guard " + fixedGuard + " with deoptimization node"); + } + return new Deoptimize(DeoptAction.InvalidateRecompile, fixedGuard.graph()); } - return fixedGuard.next(); - } else { - if (GraalOptions.TraceCanonicalizer) { - TTY.println("Replacing fixed guard " + fixedGuard + " with deoptimization node"); - } - return new Deoptimize(DeoptAction.InvalidateRecompile, fixedGuard.graph()); } } + + if (fixedGuard.inputs().size() == 0) { + return fixedGuard.next(); + } return fixedGuard; } }; diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java Wed Jul 06 16:51:01 2011 +0200 @@ -55,8 +55,9 @@ inputs().set(super.inputCount() + INPUT_NODE, n); } - public GuardNode(Graph graph) { + public GuardNode(BooleanNode node, Graph graph) { super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); + setNode(node); } @Override @@ -71,7 +72,7 @@ @Override public Node copy(Graph into) { - return new GuardNode(into); + return new GuardNode(null, into); } @SuppressWarnings("unchecked") diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java Wed Jul 06 16:51:01 2011 +0200 @@ -81,6 +81,16 @@ return blockSuccessor(1); } + + public void setTrueSuccessor(FixedNode node) { + setBlockSuccessor(0, node); + } + + + public void setFalseSuccessor(FixedNode node) { + setBlockSuccessor(1, node); + } + /** * Gets the block corresponding to the specified outcome of the branch. * @param istrue {@code true} if the true successor is requested, {@code false} otherwise diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java Wed Jul 06 16:51:01 2011 +0200 @@ -38,13 +38,15 @@ private static final int INPUT_COUNT = 0; private static final int SUCCESSOR_COUNT = 0; + private boolean nullIsTrue; + /** * Constructs a new InstanceOf instruction. * @param targetClass the target class of the instanceof check * @param object the instruction producing the object input to this instruction * @param graph */ - public InstanceOf(Constant targetClassInstruction, Value object, Graph graph) { + public InstanceOf(Constant targetClassInstruction, Value object, boolean nullIsTrue, Graph graph) { super(targetClassInstruction, object, CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); } @@ -68,13 +70,8 @@ } @Override - public BooleanNode negate() { - return new NotInstanceOf(targetClassInstruction(), object(), graph()); - } - - @Override public Node copy(Graph into) { - return new InstanceOf(null, null, into); + return new InstanceOf(null, null, nullIsTrue, into); } @SuppressWarnings("unchecked") diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAddVectorNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAddVectorNode.java Wed Jul 06 16:51:01 2011 +0200 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.ir; + +import java.util.*; + +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class IntegerAddVectorNode extends AbstractVectorNode { + private static final int INPUT_COUNT = 1; + private static final int INPUT_VALUE = 0; + private static final int SUCCESSOR_COUNT = 0; + + public Value value() { + return (Value) inputs().get(super.inputCount() + INPUT_VALUE); + } + + public void setValue(Value v) { + inputs().set(super.inputCount() + INPUT_VALUE, v); + } + + public IntegerAddVectorNode(AbstractVectorNode vector, Value value, Graph graph) { + super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, graph); + setValue(value); + } + + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return null; + } + return super.lookup(clazz); + } + + @Override + public Node copy(Graph into) { + return new IntegerAddVectorNode(null, null, into); + } + + @Override + public void addToLoop(LoopBegin loop, IdentityHashMap nodes) { + nodes.put(this, new IntegerAdd(CiKind.Int, nodes.get(vector()), value(), graph())); + } +} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java Wed Jul 06 16:51:01 2011 +0200 @@ -51,21 +51,24 @@ return super.successorCount() + SUCCESSOR_COUNT; } - /** - * The list of instructions that produce input for this instruction. - */ - public Value argument(int index) { - assert index >= 0 && index < argumentCount; - return (Value) inputs().get(super.inputCount() + index); - } + public List arguments() { + return new AbstractList() { + @Override + public int size() { + return argumentCount; + } - public Value setArgument(int index, Value n) { - assert index >= 0 && index < argumentCount; - return (Value) inputs().set(super.inputCount() + index, n); - } + @Override + public Value get(int index) { + return (Value) inputs().get(Invoke.super.inputCount() + index); + } - public int argumentCount() { - return argumentCount; + @Override + public Value set(int index, Value node) { + return (Value) inputs().set(Invoke.super.inputCount() + index, node); + } + }; + } /** @@ -103,7 +106,7 @@ this.argumentCount = args.length; for (int i = 0; i < args.length; i++) { - setArgument(i, args[i]); + arguments().set(i, args[i]); } } @@ -135,7 +138,7 @@ */ public Value receiver() { assert !isStatic(); - return argument(0); + return arguments().get(0); } /** @@ -179,7 +182,7 @@ if (i > argStart) { out.print(", "); } - out.print(argument(i)); + out.print(arguments().get(i)); } out.print(CiUtil.format(") [method: %H.%n(%p):%r]", target, false)); } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java Wed Jul 06 16:51:01 2011 +0200 @@ -23,7 +23,6 @@ package com.oracle.max.graal.compiler.ir; import com.oracle.max.graal.compiler.debug.*; -import com.oracle.max.graal.compiler.graph.*; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; import com.oracle.max.graal.compiler.phases.*; import com.oracle.max.graal.compiler.phases.LoweringPhase.LoweringOp; @@ -130,13 +129,9 @@ LoadField loadField = (LoadField) node; Graph graph = node.graph(); CiConstant constant = null; - if (graph instanceof CompilerGraph) { - RiMethod method = ((CompilerGraph) graph).getCompilation().method; - if (loadField.isStatic() && !method.isClassInitializer()) { + if (loadField.isStatic()) { constant = loadField.field().constantValue(null); - } - } - if (!loadField.isStatic()) { + } else { Value object = loadField.object(); if (object.isConstant()) { constant = loadField.field().constantValue(object.asConstant()); diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java Wed Jul 06 16:51:01 2011 +0200 @@ -23,6 +23,8 @@ package com.oracle.max.graal.compiler.ir; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.*; +import com.oracle.max.graal.compiler.phases.LoweringPhase.LoweringOp; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -85,6 +87,16 @@ return false; } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LoweringOp.class) { + return (T) LoweringPhase.DELEGATE_TO_RUNTIME; + } + return super.lookup(clazz); + } + @Override public Node copy(Graph into) { LoadIndexed x = new LoadIndexed(null, null, null, elementKind(), into); diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java Wed Jul 06 16:51:01 2011 +0200 @@ -64,10 +64,10 @@ private final int index; private RiType declaredType; - public Local(CiKind kind, int javaIndex, StartNode start, Graph graph) { + public Local(CiKind kind, int javaIndex, Graph graph) { super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph); this.index = javaIndex; - setStart(start); + setStart(graph.start()); } /** @@ -114,7 +114,7 @@ @Override public Node copy(Graph into) { - Local x = new Local(kind, index, null, into); + Local x = new Local(kind, index, into); x.setDeclaredType(declaredType()); return x; } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java Wed Jul 06 16:51:01 2011 +0200 @@ -26,16 +26,36 @@ import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; +import com.sun.cri.ci.CiAddress.*; public final class LocationNode extends FloatingNode { - private static final int INPUT_COUNT = 0; + private static final int INPUT_COUNT = 1; + private static final int INPUT_INDEX = 0; private static final int SUCCESSOR_COUNT = 0; + public static final Object FINAL_LOCATION = new Object(); + + public static Object getArrayLocation(CiKind elementKind) { + return elementKind; + } + private int displacement; private CiKind valueKind; private Object locationIdentity; + public int displacement() { + return displacement; + } + + public Value index() { + return (Value) inputs().get(super.inputCount() + INPUT_INDEX); + } + + public void setIndex(Value index) { + inputs().set(super.inputCount() + INPUT_INDEX, index); + } + public static LocationNode create(Object identity, CiKind kind, int displacement, Graph graph) { LocationNode result = new LocationNode(identity, kind, displacement, graph); return graph.ideal(result); @@ -71,7 +91,13 @@ } public CiValue createAddress(LIRGenerator lirGenerator, Value object) { - return new CiAddress(valueKind, lirGenerator.load(object), displacement); + CiValue indexValue = CiValue.IllegalValue; + Scale indexScale = Scale.Times1; + if (this.index() != null) { + indexValue = lirGenerator.load(this.index()); + indexScale = Scale.fromInt(valueKind.sizeInBytes(lirGenerator.target().wordSize)); + } + return new CiAddress(valueKind, lirGenerator.load(object), indexValue, indexScale, displacement); } public Object locationIdentity() { diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java Wed Jul 06 16:51:01 2011 +0200 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.ir; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + +/** + * The {@code ArrayLength} instruction gets the length of an array. + */ +public final class NegateBooleanNode extends BooleanNode { + private static final int INPUT_COUNT = 1; + private static final int INPUT_NODE = 0; + + private static final int SUCCESSOR_COUNT = 0; + + @Override + protected int inputCount() { + return super.inputCount() + INPUT_COUNT; + } + + @Override + protected int successorCount() { + return super.successorCount() + SUCCESSOR_COUNT; + } + + /** + * The instruction that produces the array object. + */ + public Value value() { + return (Value) inputs().get(super.inputCount() + INPUT_NODE); + } + + public Value setValue(Value n) { + return (Value) inputs().set(super.inputCount() + INPUT_NODE, n); + } + + /** + * Constructs a new ArrayLength instruction. + * @param array the instruction producing the array + * @param newFrameState the state after executing this instruction + */ + public NegateBooleanNode(Value value, Graph graph) { + super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph); + setValue(value); + } + + @Override + public void accept(ValueVisitor v) { + } + + @Override + public boolean valueEqual(Node i) { + return i instanceof NegateBooleanNode; + } + + @Override + public void print(LogStream out) { + out.print(value()).print("!"); + } + + @Override + public Node copy(Graph into) { + return new NegateBooleanNode(null, into); + } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == CanonicalizerOp.class) { + return (T) CANONICALIZER; + } + return super.lookup(clazz); + } + + private static final CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { + @Override + public Node canonical(Node node) { + NegateBooleanNode negateNode = (NegateBooleanNode) node; + Value value = negateNode.value(); + if (value instanceof NegateBooleanNode) { + return ((NegateBooleanNode) value).value(); + } else if (value instanceof Constant) { + return Constant.forBoolean(!value.asConstant().asBoolean(), node.graph()); + } + return negateNode; + } + }; +} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NotInstanceOf.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NotInstanceOf.java Wed Jul 06 16:31:18 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.ir; - -import com.oracle.max.graal.compiler.debug.*; -import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.graph.*; -import com.sun.cri.bytecode.*; -import com.sun.cri.ci.*; -import com.sun.cri.ri.*; - -/** - * The {@code InstanceOf} instruction represents an instanceof test. - */ -public final class NotInstanceOf extends TypeCheck { - - private static final int INPUT_COUNT = 0; - private static final int SUCCESSOR_COUNT = 0; - - /** - * Constructs a new InstanceOf instruction. - * @param targetClass the target class of the instanceof check - * @param object the instruction producing the object input to this instruction - * @param graph - */ - public NotInstanceOf(Constant targetClassInstruction, Value object, Graph graph) { - super(targetClassInstruction, object, CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); - } - - @Override - public void accept(ValueVisitor v) { - } - - @Override - public int valueNumber() { - return Util.hash1(Bytecodes.INSTANCEOF, object()); - } - - @Override - public boolean valueEqual(Node i) { - return i instanceof NotInstanceOf; - } - - @Override - public void print(LogStream out) { - out.print("instanceof(").print(object()).print(") ").print(CiUtil.toJavaName(targetClass())); - } - - @Override - public BooleanNode negate() { - return new InstanceOf(targetClassInstruction(), object(), graph()); - } - - @Override - public Node copy(Graph into) { - return new NotInstanceOf(null, null, into); - } - - @SuppressWarnings("unchecked") - @Override - public T lookup(Class clazz) { - if (clazz == CanonicalizerOp.class) { - return (T) CANONICALIZER; - } - return super.lookup(clazz); - } - - private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { - @Override - public Node canonical(Node node) { - NotInstanceOf notIsInstance = (NotInstanceOf) node; - Value object = notIsInstance.object(); - RiType exactType = object.exactType(); - if (exactType != null) { - return Constant.forBoolean(!exactType.isSubtypeOf(notIsInstance.targetClass()), node.graph()); - } - CiConstant constant = object.asConstant(); - if (constant != null) { - assert constant.kind == CiKind.Object; - if (constant.isNull()) { - return Constant.forBoolean(true, node.graph()); - } else { - // this should never happen - non-null constants are always expected to provide an exactType - assert false; - } - } - return notIsInstance; - } - }; -} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadVectorNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadVectorNode.java Wed Jul 06 16:51:01 2011 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.ir; + +import java.util.*; + +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class ReadVectorNode extends AccessVectorNode { + private static final int INPUT_COUNT = 0; + private static final int SUCCESSOR_COUNT = 0; + + public ReadVectorNode(AbstractVectorNode vector, Value object, LocationNode location, Graph graph) { + super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, object, location, graph); + } + + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return null; + } + return super.lookup(clazz); + } + + @Override + public Node copy(Graph into) { + return new ReadVectorNode(null, null, null, into); + } + + + @Override + public void addToLoop(LoopBegin loop, IdentityHashMap nodes) { + LocationNode newLocation = LocationNode.create(LocationNode.getArrayLocation(location().getValueKind()), location().getValueKind(), location().displacement(), graph()); + Value index = nodes.get(vector()); + assert index != null; + newLocation.setIndex(index); + ReadNode readNode = new ReadNode(location().getValueKind().stackKind(), object(), newLocation, graph()); + loop.loopEnd().replaceAtPredecessors(readNode); + readNode.setNext(loop.loopEnd()); + nodes.put(this, readNode); + } +} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java Wed Jul 06 16:51:01 2011 +0200 @@ -93,7 +93,6 @@ exactType = declaredType.exactType(); } - GraalCompilation compilation = ((CompilerGraph) node.graph()).getCompilation(); boolean needsCheck = true; if (exactType != null) { // we have an exact type @@ -101,7 +100,7 @@ } else { // if either the declared type of receiver or the holder can be assumed to have no finalizers if (declaredType != null && !declaredType.hasFinalizableSubclass()) { - if (compilation.recordNoFinalizableSubclassAssumption(declaredType)) { + if (((CompilerGraph) node.graph()).assumptions().recordNoFinalizableSubclassAssumption(declaredType)) { needsCheck = false; } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java Wed Jul 06 16:51:01 2011 +0200 @@ -56,8 +56,8 @@ return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_AFTER); } - public FrameState setStateAfter(FrameState n) { - return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_AFTER, n); + public void setStateAfter(FrameState n) { + inputs().set(super.inputCount() + INPUT_STATE_AFTER, n); } /** @@ -76,6 +76,17 @@ } @Override + public void delete() { + FrameState stateAfter = stateAfter(); + super.delete(); + if (stateAfter != null) { + if (stateAfter.usages().isEmpty()) { + stateAfter.delete(); + } + } + } + + @Override public Iterable< ? extends Node> dataInputs() { final Iterator< ? extends Node> dataInputs = super.dataInputs().iterator(); return new Iterable() { diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java Wed Jul 06 16:51:01 2011 +0200 @@ -23,6 +23,8 @@ package com.oracle.max.graal.compiler.ir; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.*; +import com.oracle.max.graal.compiler.phases.LoweringPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -82,6 +84,15 @@ out.print(array()).print('[').print(index()).print("] := ").print(value()).print(" (").print(kind.typeChar).print(')'); } + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LoweringOp.class) { + return (T) LoweringPhase.DELEGATE_TO_RUNTIME; + } + return super.lookup(clazz); + } + @Override public Node copy(Graph into) { StoreIndexed x = new StoreIndexed(null, null, null, elementKind(), null, into); diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java Wed Jul 06 16:51:01 2011 +0200 @@ -61,11 +61,11 @@ /** * The instruction that loads the target class object that is used by this checkcast. */ - public Constant targetClassInstruction() { - return (Constant) inputs().get(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION); + public Value targetClassInstruction() { + return (Value) inputs().get(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION); } - private void setTargetClassInstruction(Constant n) { + private void setTargetClassInstruction(Value n) { inputs().set(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION, n); } @@ -75,7 +75,7 @@ * @return the target class */ public RiType targetClass() { - return (RiType) targetClassInstruction().asConstant().asObject(); + return targetClassInstruction() instanceof Constant ? (RiType) targetClassInstruction().asConstant().asObject() : null; } /** @@ -87,7 +87,7 @@ * @param successorCount * @param graph */ - public TypeCheck(Constant targetClassInstruction, Value object, CiKind kind, int inputCount, int successorCount, Graph graph) { + public TypeCheck(Value targetClassInstruction, Value object, CiKind kind, int inputCount, int successorCount, Graph graph) { super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph); setObject(object); setTargetClassInstruction(targetClassInstruction); diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java Wed Jul 06 16:51:01 2011 +0200 @@ -53,7 +53,7 @@ */ public Value(CiKind kind, int inputCount, int successorCount, Graph graph) { super(inputCount, successorCount, graph); - assert kind == kind.stackKind() : kind + " != " + kind.stackKind(); + assert kind != null && kind == kind.stackKind() : kind + " != " + kind.stackKind(); this.kind = kind; } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java Wed Jul 06 16:51:01 2011 +0200 @@ -69,7 +69,6 @@ public abstract void visitStoreIndexed(StoreIndexed i); public abstract void visitTableSwitch(TableSwitch i); public abstract void visitDeoptimize(Deoptimize deoptimize); - public abstract void visitExceptionDispatch(ExceptionDispatch exceptionDispatch); public abstract void visitUnwind(Unwind unwind); public abstract void visitLoopBegin(LoopBegin loopBegin); public abstract void visitLoopEnd(LoopEnd loopEnd); diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteVectorNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteVectorNode.java Wed Jul 06 16:51:01 2011 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.ir; + +import java.util.*; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class WriteVectorNode extends AccessVectorNode { + private static final int INPUT_COUNT = 1; + private static final int INPUT_VALUES = 0; + private static final int SUCCESSOR_COUNT = 0; + + public void setValues(AbstractVectorNode length) { + inputs().set(super.inputCount() + INPUT_VALUES, length); + } + + public AbstractVectorNode values() { + return (AbstractVectorNode) inputs().get(super.inputCount() + INPUT_VALUES); + } + + public WriteVectorNode(AbstractVectorNode vector, Value object, LocationNode location, AbstractVectorNode values, Graph graph) { + super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, object, location, graph); + setValues(values); + } + + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return null; + } + return super.lookup(clazz); + } + + @Override + public void print(LogStream out) { + out.print("write vector node " + values()); + } + + @Override + public Node copy(Graph into) { + return new WriteVectorNode(null, null, null, null, into); + } + + + @Override + public void addToLoop(LoopBegin loop, IdentityHashMap nodes) { + LocationNode newLocation = LocationNode.create(LocationNode.getArrayLocation(location().getValueKind()), location().getValueKind(), location().displacement(), graph()); + Value index = nodes.get(vector()); + Value value = nodes.get(values()); + assert index != null; + assert value != null; + newLocation.setIndex(index); + WriteNode writeNode = new WriteNode(location().getValueKind().stackKind(), object(), value, newLocation, graph()); + loop.loopEnd().replaceAtPredecessors(writeNode); + writeNode.setNext(loop.loopEnd()); + } +} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java Wed Jul 06 16:51:01 2011 +0200 @@ -27,6 +27,7 @@ import com.oracle.max.asm.*; import com.oracle.max.graal.compiler.alloc.*; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; @@ -174,8 +175,7 @@ } public int loopDepth() { - // TODO(tw): Set correct loop depth. - return 0; + return loopDepth; } public int loopIndex() { @@ -284,4 +284,8 @@ LIROpcode code = lirInstruction.code; return code == LIROpcode.Branch || code == LIROpcode.TableSwitch; } + + public boolean isExceptionEntry() { + return firstInstruction() instanceof ExceptionObject; + } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java Wed Jul 06 16:51:01 2011 +0200 @@ -73,6 +73,12 @@ flood.add(successor); } } + + if (current instanceof AbstractVectorNode) { + for (Node usage : current.usages()) { + flood.add(usage); + } + } } } @@ -147,17 +153,6 @@ } for (Node node : graph.getNodes()) { if (!flood.isMarked(node)) { - if (node.predecessors().size() > 0) { - for (Node pred : node.predecessors()) { - TTY.println("!PRED! " + pred + " (" + flood.isMarked(pred) + ")"); - for (int i = 0; i < pred.successors().size(); i++) { - TTY.println("pred=>succ: " + pred.successors().get(i)); - } - for (int i = 0; i < pred.usages().size(); i++) { - TTY.println("pred=>usage: " + pred.usages().get(i)); - } - } - } node.delete(); } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DuplicationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DuplicationPhase.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DuplicationPhase.java Wed Jul 06 16:51:01 2011 +0200 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.graph.*; import com.oracle.max.graal.graph.*; @@ -36,13 +35,8 @@ @Override protected void run(Graph graph) { - GraalCompilation compilation = null; - if (graph instanceof CompilerGraph) { - compilation = ((CompilerGraph) graph).getCompilation(); - } - // Create duplicate graph. - CompilerGraph duplicate = new CompilerGraph(compilation); + CompilerGraph duplicate = new CompilerGraph(((CompilerGraph) graph).runtime()); Map replacements = new HashMap(); replacements.put(graph.start(), duplicate.start()); duplicate.addDuplicate(graph.getNodes(), replacements); diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java Wed Jul 06 16:51:01 2011 +0200 @@ -106,8 +106,6 @@ private final Set blocksOnWorklist = new HashSet(); private final Set blocksVisited = new HashSet(); - private final boolean createUnwind; - public static final Map cachedGraphs = new WeakHashMap(); /** @@ -117,10 +115,12 @@ * @param ir the IR to build the graph into * @param graph */ - public GraphBuilderPhase(GraalCompilation compilation, RiMethod method, boolean createUnwind, boolean inline) { + public GraphBuilderPhase(GraalCompilation compilation, RiMethod method, boolean inline) { super(inline ? "BuildInlineGraph" : "BuildGraph"); this.compilation = compilation; + setDetailedName(getName() + " " + method.holder().name() + "." + method.name() + method.signature().asString()); + this.runtime = compilation.runtime; this.method = method; this.stats = compilation.stats; @@ -128,7 +128,6 @@ this.stream = new BytecodeStream(method.code()); this.constantPool = runtime.getConstantPool(method); - this.createUnwind = createUnwind; this.storeResultGraph = GraalOptions.CacheGraphs; } @@ -172,25 +171,17 @@ Block startBlock = nextBlock(FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI); markOnWorkList(startBlock); lastInstr = (FixedNodeWithNext) createTarget(startBlock, frameState); - graph.start().setStart(lastInstr); + graph.start().setNext(lastInstr); if (isSynchronized(method.accessFlags())) { // 4A.1 add a monitor enter to the start block methodSynchronizedObject = synchronizedObject(frameState, method); genMonitorEnter(methodSynchronizedObject, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI); - // 4A.2 finish the start block - finishStartBlock(startBlock); + } - // 4A.3 setup an exception handler to unlock the root method synchronized object - unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null); - } else { - // 4B.1 simply finish the start block - finishStartBlock(startBlock); - - if (createUnwind) { - unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null); - } - } + // 4B.1 simply finish the start block + finishStartBlock(startBlock); + unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null); // 5. SKIPPED: look for intrinsics @@ -732,21 +723,22 @@ if (entry != null) { append(entry); } else { - frameState.clearStack(); - frameState.apush(exception); - appendGoto(createTarget(unwindBlock(bci), frameState)); + appendGoto(createTarget(unwindBlock(bci), frameState.duplicateWithException(bci, exception))); } } private void genCheckCast() { int cpi = stream().readCPI(); RiType type = constantPool.lookupType(cpi, CHECKCAST); - boolean isInitialized = type.isResolved(); - Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi); + Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, type.isResolved()); Value object = frameState.apop(); if (typeInstruction != null) { -// append(new FixedGuard(new InstanceOf(typeInstruction, object, graph), graph)); -// frameState.apush(object); +// InstanceOf instanceOf = new InstanceOf(typeInstruction, object, true, graph); +// FixedGuard fixedGuard = new FixedGuard(instanceOf, graph); +// append(fixedGuard); +// CastNode castNode = new CastNode(object.kind, object, graph); +// castNode.inputs().add(fixedGuard); +// frameState.apush(castNode); frameState.apush(new CheckCast(typeInstruction, object, graph)); } else { frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); @@ -756,11 +748,10 @@ private void genInstanceOf() { int cpi = stream().readCPI(); RiType type = constantPool.lookupType(cpi, INSTANCEOF); - boolean isInitialized = type.isResolved(); - Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi); + Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, type.isResolved()); Value object = frameState.apop(); if (typeInstruction != null) { - frameState.ipush(append(new MaterializeNode(new InstanceOf(typeInstruction, object, graph), graph))); + frameState.ipush(append(new MaterializeNode(new InstanceOf(typeInstruction, object, false, graph), graph))); } else { frameState.ipush(appendConstant(CiConstant.INT_0)); } @@ -851,7 +842,7 @@ if (constantValue != null) { frameState.push(constantValue.kind.stackKind(), appendConstant(constantValue)); } else { - Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi); + Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized); CiKind kind = field.kind(); if (container != null) { LoadField load = new LoadField(container, field, graph); @@ -865,7 +856,7 @@ private void genPutStatic(int cpi, RiField field) { RiType holder = field.holder(); - Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, field.isResolved() && field.holder().isInitialized(), cpi); + Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, field.isResolved() && field.holder().isInitialized()); Value value = frameState.pop(field.kind().stackKind()); if (container != null) { StoreField store = new StoreField(container, field, value, graph); @@ -875,7 +866,7 @@ } } - private Constant genTypeOrDeopt(RiType.Representation representation, RiType holder, boolean initialized, int cpi) { + private Constant genTypeOrDeopt(RiType.Representation representation, RiType holder, boolean initialized) { if (initialized) { return appendConstant(holder.getEncoding(representation)); } else { @@ -902,7 +893,7 @@ // Re-use the same resolution code as for accessing a static field. Even though // the result of resolution is not used by the invocation (only the side effect // of initialization is required), it can be commoned with static field accesses. - genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi); + genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized); } Value[] args = frameState.popArguments(target.signature().argumentSlots(false)); appendInvoke(INVOKESTATIC, target, args, cpi, constantPool); @@ -972,6 +963,9 @@ Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), graph); Value result = appendWithBCI(invoke); invoke.setExceptionEdge(handleException(null, bci())); + if (invoke.exceptionEdge() == null) { + TTY.println("no exception edge" + unwindHandler); + } frameState.pushReturn(resultType, result); } } @@ -1334,14 +1328,18 @@ assert frameState.stackSize() == 1 : frameState; Block nextBlock = block.next == null ? unwindBlock(block.deoptBci) : block.next; - if (block.handler.catchType().isResolved()) { + + + RiType catchType = block.handler.catchType(); + Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, catchType, catchType.isResolved()); + if (typeInstruction != null) { FixedNode catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState); FixedNode nextDispatch = createTarget(nextBlock, frameState); - append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph)); - } else { - Deoptimize deopt = new Deoptimize(DeoptAction.InvalidateRecompile, graph); - deopt.setMessage("unresolved " + block.handler.catchType().name()); - append(deopt); + Value exception = frameState.stackAt(0); + If ifNode = new If(new InstanceOf(typeInstruction, exception, false, graph), graph); + append(ifNode); + ifNode.setTrueSuccessor(catchSuccessor); + ifNode.setFalseSuccessor(nextDispatch); } } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Wed Jul 06 16:51:01 2011 +0200 @@ -54,11 +54,11 @@ } private Queue newInvokes = new ArrayDeque(); - private Graph graph; + private CompilerGraph graph; @Override protected void run(Graph graph) { - this.graph = graph; + this.graph = (CompilerGraph) graph; float ratio = GraalOptions.MaximumInlineRatio; inliningSize = compilation.method.codeSize(); @@ -118,13 +118,13 @@ private RiMethod inlineInvoke(Invoke invoke, int iterations, float ratio) { RiMethod parent = invoke.stateAfter().method(); RiTypeProfile profile = parent.typeProfile(invoke.bci); + if (GraalOptions.Intrinsify && compilation.runtime.intrinsicGraph(invoke.target, invoke.arguments()) != null) { + // Always intrinsify. + return invoke.target; + } if (!checkInvokeConditions(invoke)) { return null; } - if (invoke.target.hasIntrinsicGraph() && GraalOptions.Intrinsify) { - // Always intrinsify. - return invoke.target; - } if (invoke.opcode() == Bytecodes.INVOKESPECIAL || invoke.target.canBeStaticallyBound()) { if (checkTargetConditions(invoke.target, iterations) && checkSizeConditions(invoke.target, invoke, profile, ratio)) { return invoke.target; @@ -159,7 +159,7 @@ String concreteName = CiUtil.format("%H.%n(%p):%r", concrete, false); TTY.println("recording concrete method assumption: %s -> %s", targetName, concreteName); } - compilation.assumptions.recordConcreteMethod(invoke.target, concrete); + graph.assumptions().recordConcreteMethod(invoke.target, concrete); return concrete; } return null; @@ -323,40 +323,42 @@ exceptionEdge = ((Placeholder) exceptionEdge).next(); } - boolean withReceiver = !Modifier.isStatic(method.accessFlags()); + boolean withReceiver = !invoke.isStatic(); int argumentCount = method.signature().argumentCount(false); Value[] parameters = new Value[argumentCount + (withReceiver ? 1 : 0)]; int slot = withReceiver ? 1 : 0; int param = withReceiver ? 1 : 0; for (int i = 0; i < argumentCount; i++) { - parameters[param++] = invoke.argument(slot); + parameters[param++] = invoke.arguments().get(slot); slot += method.signature().argumentKindAt(i).sizeInSlots(); } if (withReceiver) { - parameters[0] = invoke.argument(0); + parameters[0] = invoke.arguments().get(0); } CompilerGraph graph = null; if (GraalOptions.Intrinsify) { - graph = (CompilerGraph) method.intrinsicGraph(parameters); + graph = (CompilerGraph) compilation.runtime.intrinsicGraph(method, invoke.arguments()); } if (graph != null) { - TTY.println("Using intrinsic graph"); + if (GraalOptions.TraceInlining) { + TTY.println("Using intrinsic graph"); + } } else { graph = GraphBuilderPhase.cachedGraphs.get(method); } if (graph != null) { if (GraalOptions.TraceInlining) { - TTY.println("Reusing graph for %s, locals: %d, stack: %d", methodName(method, invoke), method.maxLocals(), method.maxStackSize()); + TTY.println("Reusing graph for %s", methodName(method, invoke)); } } else { if (GraalOptions.TraceInlining) { TTY.println("Building graph for %s, locals: %d, stack: %d", methodName(method, invoke), method.maxLocals(), method.maxStackSize()); } graph = new CompilerGraph(null); - new GraphBuilderPhase(compilation, method, true, true).apply(graph); + new GraphBuilderPhase(compilation, method, true).apply(graph); } invoke.inputs().clearAll(); @@ -396,14 +398,25 @@ } else { pred = new Placeholder(compilation.graph); } - invoke.predecessors().get(0).successors().replace(invoke, pred); + invoke.replaceAtPredecessors(pred); replacements.put(startNode, pred); Map duplicates = compilation.graph.addDuplicate(nodes, replacements); + FrameState stateBefore = null; for (Node node : duplicates.values()) { if (node instanceof Invoke) { newInvokes.add((Invoke) node); + } else if (node instanceof FrameState) { + FrameState frameState = (FrameState) node; + if (frameState.bci == FrameState.BEFORE_BCI) { + if (stateBefore == null) { + stateBefore = stateAfter.duplicateModified(invoke.bci, false, invoke.kind, parameters); + } + frameState.replaceAndDelete(stateBefore); + } else if (frameState.bci == FrameState.AFTER_BCI) { + frameState.replaceAndDelete(stateAfter); + } } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java Wed Jul 06 16:51:01 2011 +0200 @@ -57,11 +57,13 @@ } private void process(final Block b) { + + final Node anchor = b.javaBlock().createAnchor(); final CiLoweringTool loweringTool = new CiLoweringTool() { @Override public Node getGuardAnchor() { - return b.createAnchor(); + return anchor; } @Override @@ -72,19 +74,13 @@ @Override public Node createGuard(Node condition) { Anchor anchor = (Anchor) getGuardAnchor(); - for (GuardNode guard : anchor.happensAfterGuards()) { - if (guard.node().valueEqual(condition)) { - condition.delete(); - return guard; - } - } - GuardNode newGuard = new GuardNode(anchor.graph()); + GuardNode newGuard = new GuardNode((BooleanNode) condition, anchor.graph()); newGuard.setAnchor(anchor); - newGuard.setNode((BooleanNode) condition); return newGuard; } }; + // Lower the instructions of this block. for (final Node n : b.getInstructions()) { if (n instanceof FixedNode) { diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java Wed Jul 06 16:51:01 2011 +0200 @@ -72,8 +72,8 @@ StartNode startNode = b.firstNode().graph().start(); if (b.firstNode() == startNode) { WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(startNode.graph()); - checkpoint.setNext((FixedNode) startNode.start()); - startNode.setStart(checkpoint); + checkpoint.setNext((FixedNode) startNode.next()); + startNode.setNext(checkpoint); mergeForWrite = checkpoint; mergeForRead = checkpoint; } @@ -315,6 +315,8 @@ LoopBegin begin = end.loopBegin(); Block beginBlock = nodeMap.get(begin); MemoryMap memoryMap = memoryMaps[beginBlock.blockID()]; + assert memoryMap != null : beginBlock.name(); + assert memoryMap.getLoopEntryMap() != null; memoryMap.getLoopEntryMap().resetMergeOperationCount(); memoryMap.getLoopEntryMap().mergeWith(map, beginBlock); Node loopCheckPoint = memoryMap.getLoopCheckPoint(); diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java Wed Jul 06 16:51:01 2011 +0200 @@ -30,12 +30,14 @@ public abstract class Phase { private final String name; + private String detailedName; private static final ThreadLocal currentPhase = new ThreadLocal(); private final boolean shouldVerify; public Phase() { this.name = this.getClass().getSimpleName(); this.shouldVerify = true; + this.detailedName = name; } public Phase(String name) { @@ -45,6 +47,11 @@ public Phase(String name, boolean shouldVerify) { this.name = name; this.shouldVerify = shouldVerify; + this.detailedName = name; + } + + protected void setDetailedName(String detailedName) { + this.detailedName = detailedName; } public final void apply(Graph graph) { @@ -71,13 +78,13 @@ } catch (AssertionError t) { GraalCompilation compilation = GraalCompilation.compilation(); if (compilation.compiler.isObserved() && plotOnError) { - compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "AssertionError in " + getName(), graph, true, false, true)); + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "AssertionError in " + detailedName, graph, true, false, true)); } throw t; } catch (RuntimeException t) { GraalCompilation compilation = GraalCompilation.compilation(); if (compilation.compiler.isObserved() && plotOnError) { - compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in " + getName(), graph, true, false, true)); + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in " + detailedName, graph, true, false, true)); } throw t; } @@ -98,7 +105,7 @@ } GraalCompilation compilation = GraalCompilation.compilation(); if (compilation.compiler.isObserved() && this.getClass() != IdentifyBlocksPhase.class) { - compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + getName(), graph, true, false)); + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + detailedName, graph, true, false)); } assert !shouldVerify || graph.verify(); diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java Wed Jul 06 16:51:01 2011 +0200 @@ -35,14 +35,16 @@ @Override protected void run(Graph graph) { for (ReadNode n : graph.getNodes(ReadNode.class)) { - Node memoryInput = n.inputs().variablePart().get(0); - if (memoryInput instanceof WriteNode) { - WriteNode other = (WriteNode) memoryInput; - if (other.object() == n.object() && other.location() == n.location()) { - if (GraalOptions.TraceReadElimination) { - TTY.println("Eliminated memory read " + n + "and replaced with node " + other.value()); + if (n.inputs().variablePart().size() > 0) { + Node memoryInput = n.inputs().variablePart().get(0); + if (memoryInput instanceof WriteNode) { + WriteNode other = (WriteNode) memoryInput; + if (other.object() == n.object() && other.location() == n.location()) { + if (GraalOptions.TraceReadElimination) { + TTY.println("Eliminated memory read " + n + "and replaced with node " + other.value()); + } + n.replaceAndDelete(other.value()); } - n.replaceAndDelete(other.value()); } } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java Wed Jul 06 16:51:01 2011 +0200 @@ -38,6 +38,8 @@ private Block javaBlock; private final List dominators = new ArrayList(); private Anchor anchor; + private int loopDepth = 0; + private int loopIndex = -1; private Node firstNode; private Node lastNode; @@ -63,18 +65,34 @@ return lastNode; } + public int loopDepth() { + return loopDepth; + } + + public void setLoopDepth(int i) { + loopDepth = i; + } + + public int loopIndex() { + return loopIndex; + } + + public void setLoopIndex(int i) { + loopIndex = i; + } + public Anchor createAnchor() { if (anchor == null) { if (firstNode instanceof Anchor) { this.anchor = (Anchor) firstNode; } else if (firstNode == firstNode.graph().start()) { StartNode start = (StartNode) firstNode; - if (start.start() instanceof Anchor) { - this.anchor = (Anchor) start.start(); + if (start.next() instanceof Anchor) { + this.anchor = (Anchor) start.next(); } else { Anchor a = new Anchor(firstNode.graph()); - a.setNext((FixedNode) firstNode.graph().start().start()); - firstNode.graph().start().setStart(a); + a.setNext((FixedNode) firstNode.graph().start().next()); + firstNode.graph().start().setNext(a); this.anchor = a; } } else if (firstNode instanceof Merge) { @@ -175,6 +193,10 @@ return firstNode instanceof LoopBegin; } + public boolean isLoopEnd() { + return lastNode instanceof LoopEnd; + } + public Block dominator() { return dominator; } @@ -224,4 +246,8 @@ } } } + + public String name() { + return "B" + blockID; + } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Wed Jul 06 16:51:01 2011 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.compiler.phases.*; @@ -36,6 +37,7 @@ private NodeMap nodeToBlock; private Graph graph; private boolean scheduleAllNodes; + private int loopCount; public IdentifyBlocksPhase(boolean scheduleAllNodes) { super(scheduleAllNodes ? "FullSchedule" : "PartSchedule", false); @@ -64,6 +66,10 @@ return b; } + public int loopCount() { + return loopCount; + } + private Block assignBlockNew(Node n, Block b) { if (b == null) { b = createBlock(); @@ -71,6 +77,20 @@ assert nodeToBlock.get(n) == null; nodeToBlock.set(n, b); + + if (n instanceof Merge) { + for (Node usage : n.usages()) { + + if (usage instanceof Phi) { + nodeToBlock.set(usage, b); + } + + if (usage instanceof LoopCounter) { + nodeToBlock.set(usage, b); + } + + } + } if (b.lastNode() == null) { b.setFirstNode(n); b.setLastNode(n); @@ -154,17 +174,7 @@ if (scheduleAllNodes) { - - // Add successors of loop end nodes. Makes the graph cyclic. - for (Block block : blocks) { - Node n = block.lastNode(); - if (n instanceof LoopEnd) { - LoopEnd loopEnd = (LoopEnd) n; - assert loopEnd.loopBegin() != null; - block.addSuccessor(nodeToBlock.get(loopEnd.loopBegin())); - } - } - + computeLoopInformation(); // Will make the graph cyclic. assignLatestPossibleBlockToNodes(); sortNodesWithinBlocks(); } else { @@ -172,6 +182,47 @@ } } + private void computeLoopInformation() { + + // Add successors of loop end nodes. Makes the graph cyclic. + for (Block block : blocks) { + Node n = block.lastNode(); + if (n instanceof LoopEnd) { + LoopEnd loopEnd = (LoopEnd) n; + assert loopEnd.loopBegin() != null; + Block loopBeginBlock = nodeToBlock.get(loopEnd.loopBegin()); + block.addSuccessor(loopBeginBlock); + BitMap map = new BitMap(blocks.size()); + markBlocks(block, loopBeginBlock, map, loopCount++, block.loopDepth()); + } + } + +// for (Block block : blocks) { +// TTY.println("Block B" + block.blockID() + " loopIndex=" + block.loopIndex() + ", loopDepth=" + block.loopDepth()); +// } + } + + private void markBlocks(Block block, Block endBlock, BitMap map, int loopIndex, int initialDepth) { + if (map.get(block.blockID())) { + return; + } + + map.set(block.blockID()); + if (block.loopDepth() <= initialDepth) { + assert block.loopDepth() == initialDepth; + block.setLoopIndex(loopIndex); + } + block.setLoopDepth(block.loopDepth() + 1); + + if (block == endBlock) { + return; + } + + for (Block pred : block.getPredecessors()) { + markBlocks(pred, endBlock, map, loopIndex, initialDepth); + } + } + private void computeJavaBlocks() { for (Block b : blocks) { @@ -240,16 +291,6 @@ assert !n.isDeleted(); - if (n instanceof Phi) { - Block block = nodeToBlock.get(((Phi) n).merge()); - nodeToBlock.set(n, block); - } - - if (n instanceof LoopCounter) { - Block block = nodeToBlock.get(((LoopCounter) n).loopBegin()); - nodeToBlock.set(n, block); - } - Block prevBlock = nodeToBlock.get(n); if (prevBlock != null) { return prevBlock; @@ -294,13 +335,76 @@ } } - nodeToBlock.set(n, block); + if (block != null) { + if (GraalOptions.OptOptimisticSchedule) { + block = scheduleOutOfLoops(n, block); + } + nodeToBlock.set(n, block); block.getInstructions().add(n); } return block; } + private Block scheduleOutOfLoops(Node n, Block latestBlock) { + Block cur = latestBlock; + while (cur.loopDepth() != 0) { + if (cur.isLoopHeader()) { + assert cur.getPredecessors().size() == 2 : cur.getPredecessors().size(); + if (canSchedule(n, cur.getPredecessors().get(0))) { + // TTY.println("can schedule out of loop!" + n); + return scheduleOutOfLoops(n, cur.getPredecessors().get(0)); + } else { + break; + } + } + Block prev = cur; + cur = cur.dominator(); + + // This must be a loop exit. + if (cur.loopDepth() > prev.loopDepth()) { +// TTY.println("break out because of different loop depth"); + break; + } + } + return latestBlock; + } + + private boolean canSchedule(Node n, Block block) { + Set allowedBlocks = new HashSet(); + Block cur = block; + while (cur != null) { + allowedBlocks.add(cur); + cur = cur.dominator(); + } + // Now we know the allowed blocks for inputs and predecessors. + return checkNodesAbove(allowedBlocks, n); + } + + private boolean checkNodesAbove(Set allowedBlocks, Node n) { + if (n == null) { + return true; + } + + if (nodeToBlock.get(n) != null) { + return allowedBlocks.contains(nodeToBlock.get(n)); + } else { + assert !(n instanceof Phi) : ((Phi) n).merge(); + for (Node input : n.inputs()) { + if (!checkNodesAbove(allowedBlocks, input)) { + return false; + } + } + for (Node pred : n.predecessors()) { + if (!checkNodesAbove(allowedBlocks, pred)) { + return false; + } + } + return true; + } + } + + private Block getCommonDominator(Block a, Block b) { if (a == null) { return b; @@ -323,15 +427,11 @@ List sortedInstructions = new ArrayList(instructions.size() + 2); assert !map.isMarked(b.firstNode()) && nodeToBlock.get(b.firstNode()) == b; -// assert !instructions.contains(b.firstNode()); -// assert !instructions.contains(b.lastNode()); assert !map.isMarked(b.lastNode()) && nodeToBlock.get(b.lastNode()) == b; - //addToSorting(b, b.firstNode(), sortedInstructions, map); for (Node i : instructions) { addToSorting(b, i, sortedInstructions, map); } - //addToSorting(b, b.lastNode(), sortedInstructions, map); // Make sure that last node gets really last (i.e. when a frame state successor hangs off it). Node lastSorted = sortedInstructions.get(sortedInstructions.size() - 1); @@ -366,7 +466,7 @@ } if (i instanceof WriteNode) { - // Make sure every ReadNode that is connected to the same memory state is executed before every write node. + // TODO(tw): Make sure every ReadNode that is connected to the same memory state is executed before every write node. WriteNode wn = (WriteNode) i; // TODO: Iterate over variablePart. wn.inputs().variablePart(); diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java Wed Jul 06 16:51:01 2011 +0200 @@ -554,6 +554,8 @@ case GT : acond = ConditionFlag.greater; break; case BE : acond = ConditionFlag.belowEqual; break; case AE : acond = ConditionFlag.aboveEqual; break; + case AT : acond = ConditionFlag.above; break; + case BT : acond = ConditionFlag.below; break; default : throw Util.shouldNotReachHere(); } // Checkstyle: on @@ -1298,11 +1300,11 @@ default : throw Util.shouldNotReachHere(); } } else { - throw Util.shouldNotReachHere(); + throw Util.shouldNotReachHere("opr1=" + opr1.toString() + " opr2=" + opr2); } } else { - throw Util.shouldNotReachHere(opr1.toString() + " opr2 = " + opr2); + throw Util.shouldNotReachHere("opr1=" + opr1.toString() + " opr2=" + opr2); } // Checkstyle: on } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Wed Jul 06 16:51:01 2011 +0200 @@ -33,9 +33,6 @@ import com.oracle.max.graal.compiler.util.*; import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; -import com.sun.cri.ri.*; -import com.sun.cri.ri.RiType.*; -import com.sun.cri.xir.*; /** * This class implements the X86-specific portion of the LIR generator. @@ -466,30 +463,11 @@ } @Override - public void visitExceptionDispatch(ExceptionDispatch x) { - // TODO ls: this needs some more work... - - RiType riType = x.catchType(); - assert riType.isResolved(); - - XirArgument obj = toXirArgument(x.exception()); - XirArgument clazz = toXirArgument(riType.getEncoding(Representation.ObjectHub)); - XirSnippet snippet = xir.genInstanceOf(site(x), obj, clazz, riType); - emitXir(snippet, x, stateFor(x), null, false); - - LIRXirInstruction instr = (LIRXirInstruction) lir.instructionsList().get(lir.instructionsList().size() - 1); - instr.setTrueSuccessor(getLIRBlock(x.catchSuccessor())); - lir.jump(getLIRBlock(x.otherSuccessor())); - } - - @Override public void visitLoopBegin(LoopBegin x) { - } @Override public void visitValueAnchor(ValueAnchor valueAnchor) { // nothing to do for ValueAnchors } - } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java Wed Jul 06 16:51:01 2011 +0200 @@ -54,6 +54,9 @@ private static final int SUCCESSOR_COUNT = 0; + public static final int BEFORE_BCI = -2; + public static final int AFTER_BCI = -3; + @Override protected int inputCount() { return super.inputCount() + localsSize + stackSize + locksSize; diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java Wed Jul 06 16:51:01 2011 +0200 @@ -43,6 +43,7 @@ private final ArrayList locks; private int stackIndex; + private boolean rethrowException; private final RiMethod method; @@ -59,7 +60,7 @@ int index = 0; if (!isStatic(method.accessFlags())) { // add the receiver and assume it is non null - Local local = new Local(method.holder().kind(), javaIndex, graph.start(), graph); + Local local = new Local(method.holder().kind(), javaIndex, graph); local.setDeclaredType(method.holder()); storeLocal(javaIndex, local); javaIndex = 1; @@ -71,7 +72,7 @@ for (int i = 0; i < max; i++) { RiType type = sig.argumentTypeAt(i, accessingClass); CiKind kind = type.kind().stackKind(); - Local local = new Local(kind, index, graph.start(), graph); + Local local = new Local(kind, index, graph); if (type.isResolved()) { local.setDeclaredType(type); } @@ -102,10 +103,11 @@ for (int i = 0; i < other.locksSize(); i++) { locks.add(other.lockAt(i)); } + this.rethrowException = other.rethrowException(); } public FrameState create(int bci) { - return new FrameState(method, bci, locals, stack, stackIndex, locks, false, graph); + return new FrameState(method, bci, locals, stack, stackIndex, locks, rethrowException, graph); } public FrameState duplicateWithException(int bci, Value exceptionObject) { diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java Wed Jul 06 16:51:01 2011 +0200 @@ -223,14 +223,4 @@ } } } - - @Override - public Graph intrinsicGraph(Node[] parameters) { - return null; - } - - @Override - public boolean hasIntrinsicGraph() { - return false; - } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java Wed Jul 06 16:51:01 2011 +0200 @@ -177,14 +177,4 @@ public int branchProbability(int bci) { return -1; } - - @Override - public Graph intrinsicGraph(Node[] parameters) { - return null; - } - - @Override - public boolean hasIntrinsicGraph() { - return false; - } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java Wed Jul 06 16:51:01 2011 +0200 @@ -26,7 +26,10 @@ import java.lang.reflect.*; import java.util.*; +import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.graph.*; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.runtime.nodes.*; import com.sun.cri.ci.*; @@ -34,6 +37,7 @@ import com.sun.cri.ci.CiTargetMethod.DataPatch; import com.sun.cri.ci.CiTargetMethod.Safepoint; import com.sun.cri.ri.*; +import com.sun.cri.ri.RiType.Representation; import com.sun.max.asm.dis.*; import com.sun.max.lang.*; @@ -46,6 +50,7 @@ final HotSpotRegisterConfig regConfig; final HotSpotRegisterConfig globalStubRegConfig; private final Compiler compiler; + private IdentityHashMap intrinsicGraphs = new IdentityHashMap(); public HotSpotRuntime(HotSpotVMConfig config, Compiler compiler) { @@ -243,6 +248,10 @@ @Override public void lower(Node n, CiLoweringTool tool) { + if (!GraalOptions.Lower) { + return; + } + if (n instanceof LoadField) { LoadField field = (LoadField) n; if (field.isVolatile()) { @@ -274,6 +283,217 @@ memoryWrite.setNext(field.next()); } field.replaceAndDelete(memoryWrite); + } else if (n instanceof LoadIndexed) { + LoadIndexed loadIndexed = (LoadIndexed) n; + Graph graph = loadIndexed.graph(); + GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool); + + CiKind elementKind = loadIndexed.elementKind(); + LocationNode arrayLocation = createArrayLocation(graph, elementKind); + arrayLocation.setIndex(loadIndexed.index()); + ReadNode memoryRead = new ReadNode(elementKind.stackKind(), loadIndexed.array(), arrayLocation, graph); + memoryRead.setGuard(boundsCheck); + memoryRead.setNext(loadIndexed.next()); + loadIndexed.replaceAndDelete(memoryRead); + } else if (n instanceof StoreIndexed) { + StoreIndexed storeIndexed = (StoreIndexed) n; + Graph graph = storeIndexed.graph(); + Anchor anchor = new Anchor(graph); + GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool); + anchor.inputs().add(boundsCheck); + + + CiKind elementKind = storeIndexed.elementKind(); + LocationNode arrayLocation = createArrayLocation(graph, elementKind); + arrayLocation.setIndex(storeIndexed.index()); + Value value = storeIndexed.value(); + if (elementKind == CiKind.Object) { + // Store check! + if (storeIndexed.array().exactType() != null) { + RiType elementType = storeIndexed.array().exactType().componentType(); + if (elementType.superType() != null) { + Constant type = new Constant(elementType.getEncoding(Representation.ObjectHub), graph); + value = new CheckCast(type, value, graph); + } else { + assert elementType.name().equals("Ljava/lang/Object;") : elementType.name(); + } + } else { + ReadNode arrayKlass = new ReadNode(CiKind.Object, storeIndexed.array(), LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), graph); + ReadNode arrayElementKlass = new ReadNode(CiKind.Object, arrayKlass, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph), graph); + value = new CheckCast(arrayElementKlass, value, graph); + } + } + WriteNode memoryWrite = new WriteNode(elementKind.stackKind(), storeIndexed.array(), value, arrayLocation, graph); + memoryWrite.setGuard(boundsCheck); + memoryWrite.setStateAfter(storeIndexed.stateAfter()); + anchor.setNext(memoryWrite); + if (elementKind == CiKind.Object && !value.isNullConstant()) { + ArrayWriteBarrier writeBarrier = new ArrayWriteBarrier(storeIndexed.array(), arrayLocation, graph); + memoryWrite.setNext(writeBarrier); + writeBarrier.setNext(storeIndexed.next()); + } else { + memoryWrite.setNext(storeIndexed.next()); + } + storeIndexed.replaceAtPredecessors(anchor); + storeIndexed.delete(); } } + + private LocationNode createArrayLocation(Graph graph, CiKind elementKind) { + return LocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), graph); + } + + private GuardNode createBoundsCheck(AccessIndexed n, CiLoweringTool tool) { + return (GuardNode) tool.createGuard(new Compare(n.index(), Condition.BT, n.length(), n.graph())); + } + + @Override + public Graph intrinsicGraph(RiMethod method, List parameters) { + if (!intrinsicGraphs.containsKey(method)) { + RiType holder = method.holder(); + String fullName = method.name() + method.signature().asString(); + String holderName = holder.name(); + if (holderName.equals("Ljava/lang/Object;")) { + if (fullName.equals("getClass()Ljava/lang/Class;")) { + CompilerGraph graph = new CompilerGraph(this); + Local receiver = new Local(CiKind.Object, 0, graph); + ReadNode klassOop = new ReadNode(CiKind.Object, receiver, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), graph); + Return ret = new Return(new ReadNode(CiKind.Object, klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), graph), graph); + graph.start().setNext(ret); + graph.setReturn(ret); + intrinsicGraphs.put(method, graph); + } + } else if (holderName.equals("Ljava/lang/System;")) { + if (fullName.equals("arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V")) { + CompilerGraph graph = new CompilerGraph(this); + Local src = new Local(CiKind.Object, 0, graph); + Local srcPos = new Local(CiKind.Int, 1, graph); + Local dest = new Local(CiKind.Object, 2, graph); + Local destPos = new Local(CiKind.Int, 3, graph); + Value length = new Local(CiKind.Int, 4, graph); + src.setDeclaredType(((Value) parameters.get(0)).declaredType()); + dest.setDeclaredType(((Value) parameters.get(2)).declaredType()); + + if (src.declaredType() == null || dest.declaredType() == null) { + return null; + } + + if (src.declaredType() != dest.declaredType()) { + return null; + } + + if (!src.declaredType().isArrayClass()) { + return null; + } + + CiKind componentType = src.declaredType().componentType().kind(); + + if (componentType == CiKind.Object) { + return null; + } + + FrameState stateBefore = new FrameState(method, FrameState.BEFORE_BCI, 0, 0, 0, false, graph); + FrameState stateAfter = new FrameState(method, FrameState.AFTER_BCI, 0, 0, 0, false, graph); + + // Add preconditions. + FixedGuard guard = new FixedGuard(graph); + ArrayLength srcLength = new ArrayLength(src, graph); + ArrayLength destLength = new ArrayLength(dest, graph); + IntegerAdd upperLimitSrc = new IntegerAdd(CiKind.Int, srcPos, length, graph); + IntegerAdd upperLimitDest = new IntegerAdd(CiKind.Int, destPos, length, graph); + guard.addNode(new Compare(srcPos, Condition.BE, srcLength, graph)); + guard.addNode(new Compare(destPos, Condition.BE, destLength, graph)); + guard.addNode(new Compare(length, Condition.GE, Constant.forInt(0, graph), graph)); + guard.addNode(new Compare(upperLimitSrc, Condition.LE, srcLength, graph)); + guard.addNode(new Compare(upperLimitDest, Condition.LE, destLength, graph)); + graph.start().setNext(guard); + + LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, componentType, config.getArrayOffset(componentType), graph); + + // Build normal vector instruction. + CreateVectorNode normalVector = new CreateVectorNode(false, length, graph); + ReadVectorNode values = new ReadVectorNode(new IntegerAddVectorNode(normalVector, srcPos, graph), src, location, graph); + new WriteVectorNode(new IntegerAddVectorNode(normalVector, destPos, graph), dest, location, values, graph); + normalVector.setStateAfter(stateAfter); + + // Build reverse vector instruction. + CreateVectorNode reverseVector = new CreateVectorNode(true, length, graph); + ReadVectorNode reverseValues = new ReadVectorNode(new IntegerAddVectorNode(reverseVector, srcPos, graph), src, location, graph); + new WriteVectorNode(new IntegerAddVectorNode(reverseVector, destPos, graph), dest, location, reverseValues, graph); + reverseVector.setStateAfter(stateAfter); + + If ifNode = new If(new Compare(src, Condition.EQ, dest, graph), graph); + guard.setNext(ifNode); + + If secondIf = new If(new Compare(srcPos, Condition.LT, destPos, graph), graph); + ifNode.setTrueSuccessor(secondIf); + + secondIf.setTrueSuccessor(reverseVector); + + Merge merge1 = new Merge(graph); + merge1.addEnd(new EndNode(graph)); + merge1.addEnd(new EndNode(graph)); + merge1.setStateAfter(stateBefore); + + ifNode.setFalseSuccessor(merge1.endAt(0)); + secondIf.setFalseSuccessor(merge1.endAt(1)); + merge1.setNext(normalVector); + + Merge merge2 = new Merge(graph); + merge2.addEnd(new EndNode(graph)); + merge2.addEnd(new EndNode(graph)); + merge2.setStateAfter(stateAfter); + + normalVector.setNext(merge2.endAt(0)); + reverseVector.setNext(merge2.endAt(1)); + + Return ret = new Return(null, graph); + merge2.setNext(ret); + graph.setReturn(ret); + return graph; + } + } else if (holderName.equals("Ljava/lang/Float;")) { + if (fullName.equals("floatToRawIntBits(F)I") || fullName.equals("floatToIntBits(F)I")) { + CompilerGraph graph = new CompilerGraph(this); + Return ret = new Return(new FPConversionNode(CiKind.Int, new Local(CiKind.Float, 0, graph), graph), graph); + graph.start().setNext(ret); + graph.setReturn(ret); + intrinsicGraphs.put(method, graph); + } else if (fullName.equals("intBitsToFloat(I)F")) { + CompilerGraph graph = new CompilerGraph(this); + Return ret = new Return(new FPConversionNode(CiKind.Float, new Local(CiKind.Int, 0, graph), graph), graph); + graph.start().setNext(ret); + graph.setReturn(ret); + intrinsicGraphs.put(method, graph); + } + } else if (holderName.equals("Ljava/lang/Double;")) { + if (fullName.equals("doubleToRawLongBits(D)J") || fullName.equals("doubleToLongBits(D)J")) { + CompilerGraph graph = new CompilerGraph(this); + Return ret = new Return(new FPConversionNode(CiKind.Long, new Local(CiKind.Double, 0, graph), graph), graph); + graph.start().setNext(ret); + graph.setReturn(ret); + intrinsicGraphs.put(method, graph); + } else if (fullName.equals("longBitsToDouble(J)D")) { + CompilerGraph graph = new CompilerGraph(this); + Return ret = new Return(new FPConversionNode(CiKind.Double, new Local(CiKind.Long, 0, graph), graph), graph); + graph.start().setNext(ret); + graph.setReturn(ret); + intrinsicGraphs.put(method, graph); + } + } else if (holderName.equals("Ljava/lang/Thread;")) { + if (fullName.equals("currentThread()Ljava/lang/Thread;")) { + CompilerGraph graph = new CompilerGraph(this); + Return ret = new Return(new CurrentThread(config.threadObjectOffset, graph), graph); + graph.start().setNext(ret); + graph.setReturn(ret); + intrinsicGraphs.put(method, graph); + } + } + + if (!intrinsicGraphs.containsKey(method)) { + intrinsicGraphs.put(method, null); + } + } + return intrinsicGraphs.get(method); + } } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java Wed Jul 06 16:51:01 2011 +0200 @@ -1179,7 +1179,6 @@ @Override public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { - assert type.isResolved(); return new XirSnippet(checkCastTemplates.get(site), receiver, hub); } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/ArrayWriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/ArrayWriteBarrier.java Wed Jul 06 16:51:01 2011 +0200 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.runtime.nodes; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class ArrayWriteBarrier extends WriteBarrier { + private static final int INPUT_COUNT = 2; + private static final int INPUT_OBJECT = 0; + private static final int INPUT_LOCATION = 1; + + private static final int SUCCESSOR_COUNT = 0; + + @Override + protected int inputCount() { + return super.inputCount() + INPUT_COUNT; + } + + /** + * The instruction that produces the object tested against null. + */ + public Value object() { + return (Value) inputs().get(super.inputCount() + INPUT_OBJECT); + } + + public void setObject(Value n) { + inputs().set(super.inputCount() + INPUT_OBJECT, n); + } + + /** + * The instruction that produces the object tested against null. + */ + public LocationNode location() { + return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION); + } + + public void setLocation(LocationNode n) { + inputs().set(super.inputCount() + INPUT_LOCATION, n); + } + + public ArrayWriteBarrier(Value object, LocationNode index, Graph graph) { + super(INPUT_COUNT, SUCCESSOR_COUNT, graph); + this.setObject(object); + this.setLocation(index); + } + + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return (T) new LIRGenerator.LIRGeneratorOp() { + @Override + public void generate(Node n, LIRGenerator generator) { + assert n == ArrayWriteBarrier.this; + CiVariable temp = generator.newVariable(CiKind.Word); + generator.lir().lea(location().createAddress(generator, object()), temp); + ArrayWriteBarrier.this.generateBarrier(temp, generator); + } + }; + } + return super.lookup(clazz); + } + + @Override + public void print(LogStream out) { + out.print("field write barrier ").print(object()); + } + + @Override + public Node copy(Graph into) { + return new ArrayWriteBarrier(null, null, into); + } +} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/CurrentThread.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/CurrentThread.java Wed Jul 06 16:51:01 2011 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.runtime.nodes; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class CurrentThread extends FloatingNode { + private static final int INPUT_COUNT = 0; + private static final int SUCCESSOR_COUNT = 0; + private int threadObjectOffset; + + public CurrentThread(int threadObjectOffset, Graph graph) { + super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph); + this.threadObjectOffset = threadObjectOffset; + } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return (T) new LIRGenerator.LIRGeneratorOp() { + @Override + public void generate(Node n, LIRGenerator generator) { + CurrentThread conv = (CurrentThread) n; + CiValue result = generator.createResultVariable(conv); + generator.lir().move(new CiAddress(CiKind.Object, AMD64.r15.asValue(CiKind.Word), threadObjectOffset), result); + } + }; + } + return super.lookup(clazz); + } + + @Override + public boolean valueEqual(Node i) { + return i instanceof CurrentThread; + } + + @Override + public void print(LogStream out) { + out.print("currentThread"); + } + + @Override + public Node copy(Graph into) { + return new CurrentThread(threadObjectOffset, into); + } +} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java Wed Jul 06 16:51:01 2011 +0200 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.runtime.nodes; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class FPConversionNode extends FloatingNode { + private static final int INPUT_COUNT = 1; + private static final int INPUT_OBJECT = 0; + + private static final int SUCCESSOR_COUNT = 0; + + @Override + protected int inputCount() { + return super.inputCount() + INPUT_COUNT; + } + + /** + * The instruction that produces the object tested against null. + */ + public Value value() { + return (Value) inputs().get(super.inputCount() + INPUT_OBJECT); + } + + public void setValue(Value n) { + inputs().set(super.inputCount() + INPUT_OBJECT, n); + } + + public FPConversionNode(CiKind kind, Value value, Graph graph) { + super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph); + this.setValue(value); + } + + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return (T) new LIRGenerator.LIRGeneratorOp() { + @Override + public void generate(Node n, LIRGenerator generator) { + FPConversionNode conv = (FPConversionNode) n; + CiValue reg = generator.createResultVariable(conv); + CiValue value = generator.load(conv.value()); + CiValue tmp = generator.forceToSpill(value, conv.kind, false); + generator.lir().move(tmp, reg); + } + }; + } + return super.lookup(clazz); + } + + @Override + public boolean valueEqual(Node i) { + return i instanceof FPConversionNode && ((FPConversionNode) i).kind == kind; + } + + @Override + public void print(LogStream out) { + out.print("fp conversion node ").print(value()); + } + + @Override + public Node copy(Graph into) { + return new FPConversionNode(kind, null, into); + } +} diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java Wed Jul 06 16:31:18 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java Wed Jul 06 16:51:01 2011 +0200 @@ -25,13 +25,11 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.ir.*; -import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.runtime.*; import com.sun.cri.ci.*; -public final class FieldWriteBarrier extends FixedNodeWithNext { +public final class FieldWriteBarrier extends WriteBarrier { private static final int INPUT_COUNT = 1; private static final int INPUT_OBJECT = 0; @@ -54,7 +52,7 @@ } public FieldWriteBarrier(Value object, Graph graph) { - super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); + super(INPUT_COUNT, SUCCESSOR_COUNT, graph); this.setObject(object); } @@ -68,18 +66,8 @@ public void generate(Node n, LIRGenerator generator) { assert n == FieldWriteBarrier.this; CiVariable temp = generator.newVariable(CiKind.Word); - HotSpotVMConfig config = CompilerImpl.getInstance().getConfig(); generator.lir().move(generator.makeOperand(object()), temp); - generator.lir().unsignedShiftRight(temp, CiConstant.forInt(config.cardtableShift), temp, CiValue.IllegalValue); - - long startAddress = config.cardtableStartAddress; - int displacement = 0; - if (((int) startAddress) == startAddress) { - displacement = (int) startAddress; - } else { - generator.lir().add(temp, CiConstant.forLong(config.cardtableStartAddress), temp); - } - generator.lir().move(CiConstant.FALSE, new CiAddress(CiKind.Boolean, temp, displacement), (LIRDebugInfo) null); + FieldWriteBarrier.this.generateBarrier(temp, generator); } }; } diff -r 2b1eace223b0 -r ce7e5b3798f7 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/WriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/WriteBarrier.java Wed Jul 06 16:51:01 2011 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.runtime.nodes; + +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.runtime.*; +import com.sun.cri.ci.*; + + +public abstract class WriteBarrier extends FixedNodeWithNext { + private static final int INPUT_COUNT = 0; + private static final int SUCCESSOR_COUNT = 0; + + public WriteBarrier(int inputCount, int successorCount, Graph graph) { + super(CiKind.Illegal, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph); + } + + + protected void generateBarrier(CiValue temp, LIRGenerator generator) { + HotSpotVMConfig config = CompilerImpl.getInstance().getConfig(); + generator.lir().unsignedShiftRight(temp, CiConstant.forInt(config.cardtableShift), temp, CiValue.IllegalValue); + + long startAddress = config.cardtableStartAddress; + int displacement = 0; + if (((int) startAddress) == startAddress) { + displacement = (int) startAddress; + } else { + generator.lir().add(temp, CiConstant.forLong(config.cardtableStartAddress), temp); + } + generator.lir().move(CiConstant.FALSE, new CiAddress(CiKind.Boolean, temp, displacement), (LIRDebugInfo) null); + } +} diff -r 2b1eace223b0 -r ce7e5b3798f7 src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java --- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java Wed Jul 06 16:31:18 2011 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java Wed Jul 06 16:51:01 2011 +0200 @@ -50,7 +50,7 @@ for (Group g : groups) { List children = new ArrayList(); children.add(g); - if(g.getGraphs().size() == 1) { + if(false && g.getGraphs().size() == 1) { //g.getGraphs().get(0).setName(g.getName() + " / " + g.getGraphs().get(0).getName()); result.add(new Pair>("", children)); } else { diff -r 2b1eace223b0 -r ce7e5b3798f7 src/share/vm/interpreter/interpreterRuntime.cpp --- a/src/share/vm/interpreter/interpreterRuntime.cpp Wed Jul 06 16:31:18 2011 +0200 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Wed Jul 06 16:51:01 2011 +0200 @@ -459,6 +459,7 @@ } while (should_repeat == true); if (h_method->method_data() != NULL) { + ResourceMark rm(thread); ProfileData* pdata = h_method->method_data()->allocate_bci_to_data(current_bci); if (pdata != NULL) { int tstate0 = pdata->trap_state(); diff -r 2b1eace223b0 -r ce7e5b3798f7 src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Wed Jul 06 16:31:18 2011 +0200 +++ b/src/share/vm/runtime/deoptimization.cpp Wed Jul 06 16:51:01 2011 +0200 @@ -1244,7 +1244,7 @@ if (trap_scope->rethrow_exception()) { if (TraceDeoptimization) { - tty->print_cr("Exception to be rethrown in the interpreter"); + tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", instanceKlass::cast(trap_method->method_holder())->name()->as_C_string(), trap_method->name()->as_C_string(), trap_bci); } GrowableArray* expressions = trap_scope->expressions(); ScopeValue* topOfStack = expressions->top(); diff -r 2b1eace223b0 -r ce7e5b3798f7 src/share/vm/runtime/vframeArray.cpp --- a/src/share/vm/runtime/vframeArray.cpp Wed Jul 06 16:31:18 2011 +0200 +++ b/src/share/vm/runtime/vframeArray.cpp Wed Jul 06 16:51:01 2011 +0200 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" +#include "code/scopeDesc.hpp" #include "interpreter/interpreter.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" @@ -62,7 +63,7 @@ _method = vf->method(); _bci = vf->raw_bci(); _reexecute = vf->should_reexecute(); - + int index; // Get the monitors off-stack @@ -126,28 +127,37 @@ // Now the expressions off-stack // Same silliness as above - - StackValueCollection *exprs = vf->expressions(); - _expressions = new StackValueCollection(exprs->size()); - for(index = 0; index < exprs->size(); index++) { - StackValue* value = exprs->at(index); - switch(value->type()) { - case T_OBJECT: - assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); - // preserve object type - _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT )); - break; - case T_CONFLICT: - // A dead stack element. Will be initialized to null/zero. - // This can occur when the compiler emits a state in which stack - // elements are known to be dead (because of an imminent exception). - _expressions->add( new StackValue()); - break; - case T_INT: - _expressions->add( new StackValue(value->get_int())); - break; - default: - ShouldNotReachHere(); + bool rethrow_exception = vf->scope()->rethrow_exception(); + if (rethrow_exception) { + // (tw) Make sure there are only null pointers on the stack, because the stack values do not correspond to the GC map at the bytecode at which the exception is rethrown. + _expressions = new StackValueCollection(vf->method()->max_stack()); + assert(Thread::current()->has_pending_exception(), "just checking"); + for (int i=0; imethod()->max_stack(); ++i) { + _expressions->add( new StackValue()); + } + } else { + StackValueCollection *exprs = vf->expressions(); + _expressions = new StackValueCollection(exprs->size()); + for(index = 0; index < exprs->size(); index++) { + StackValue* value = exprs->at(index); + switch(value->type()) { + case T_OBJECT: + assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); + // preserve object type + _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT )); + break; + case T_CONFLICT: + // A dead stack element. Will be initialized to null/zero. + // This can occur when the compiler emits a state in which stack + // elements are known to be dead (because of an imminent exception). + _expressions->add( new StackValue()); + break; + case T_INT: + _expressions->add( new StackValue(value->get_int())); + break; + default: + ShouldNotReachHere(); + } } } } @@ -314,8 +324,7 @@ // only unpacks the part of the expression stack not used by callee // as parameters. The callee parameters are unpacked as part of the // callee locals. - int i; - for(i = 0; i < expressions()->size(); i++) { + for(int i = 0; i < expressions()->size(); i++) { StackValue *value = expressions()->at(i); intptr_t* addr = iframe()->interpreter_frame_expression_stack_at(i); switch(value->type()) { @@ -352,7 +361,7 @@ // Unpack the locals - for(i = 0; i < locals()->size(); i++) { + for(int i = 0; i < locals()->size(); i++) { StackValue *value = locals()->at(i); intptr_t* addr = iframe()->interpreter_frame_local_at(i); switch(value->type()) {