# HG changeset patch # User Lukas Stadler # Date 1307456828 -7200 # Node ID 7f14e6b48a9c65f24eb055beeaa402541bf48bfd # Parent e55543ff91fd79148b678e4d48ab1b3c610ff084 added dead code elimination added ValueAnchor (temp workaround) more inlining logic (now uses DCE) IdealGraphPrinter: print even if Scheduler fails added inlining and DCE tracing options to C1XOptions diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java --- a/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java Tue Jun 07 16:27:08 2011 +0200 @@ -81,7 +81,7 @@ return b; } - private static boolean isCFG(Node n) { + public static boolean isCFG(Node n) { return n != null && ((n instanceof Instruction) || n == n.graph().start()); } diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java --- a/graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java Tue Jun 07 16:27:08 2011 +0200 @@ -39,6 +39,7 @@ // Checkstyle: resume // inlining settings + public static boolean Inline = ____; public static int MaximumInstructionCount = 37000; public static float MaximumInlineRatio = 0.90f; public static int MaximumInlineSize = 35; @@ -68,7 +69,7 @@ // DOT output settings public static boolean PrintDOTGraphToFile = ____; public static boolean PrintDOTGraphToPdf = ____; - public static boolean OmitDOTFrameStates = true; + public static boolean OmitDOTFrameStates = ____; // Ideal graph visualizer output settings public static int PrintIdealGraphLevel = 0; @@ -91,6 +92,7 @@ public static boolean TraceLIRVisit = ____; public static boolean TraceAssembler = ____; public static boolean TraceInlining = ____; + public static boolean TraceDeadCodeElimination = ____; public static int TraceBytecodeParserLevel = 0; public static boolean QuietBailout = ____; diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java --- a/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java Tue Jun 07 16:27:08 2011 +0200 @@ -1898,7 +1898,8 @@ values[valueIndex++] = monitorAddress; assert frameRefMap != null; CiStackSlot objectAddress = frameMap.toMonitorObjectStackAddress(i); - LIRDebugInfo.setBit(frameRefMap, objectAddress.index()); +// LIRDebugInfo.setBit(frameRefMap, objectAddress.index()); + frameRefMap.set(objectAddress.index()); } else { Value lock = state.lockAt(i); if (lock.isConstant() && compilation.runtime.asJavaClass(lock.asConstant()) != null) { diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java --- a/graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java Tue Jun 07 16:27:08 2011 +0200 @@ -112,10 +112,15 @@ public void print(Graph graph, String title, boolean shortNames) { stream.printf(" %n", escape(title)); - Schedule schedule = new Schedule(graph); + Schedule schedule = null; + try { + schedule = new Schedule(graph); + } catch (Throwable t) { + // nothing to do here... + } stream.println(" "); - List edges = printNodes(graph.getNodes(), shortNames, schedule.getNodeToBlock()); + List edges = printNodes(graph.getNodes(), shortNames, schedule == null ? null : schedule.getNodeToBlock()); stream.println(" "); stream.println(" "); @@ -125,10 +130,12 @@ stream.println(" "); stream.println(" "); - for (Block block : schedule.getBlocks()) { - printBlock(graph, block); + if (schedule != null) { + for (Block block : schedule.getBlocks()) { + printBlock(graph, block); + } + printNoBlock(); } - printNoBlock(); stream.println(" "); stream.println(" "); @@ -155,12 +162,14 @@ } stream.printf("

%s

%n", escape(name)); } - Block block = nodeToBlock.get(node); - if (block != null) { - stream.printf("

%d

%n", block.blockID()); - } else { - stream.printf("

noBlock

%n"); - noBlockNodes.add(node); + if (nodeToBlock != null) { + Block block = nodeToBlock.get(node); + if (block != null) { + stream.printf("

%d

%n", block.blockID()); + } else { + stream.printf("

noBlock

%n"); + noBlockNodes.add(node); + } } for (Entry entry : props.entrySet()) { String key = entry.getKey().toString(); diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/gen/PhiSimplifier.java --- a/graal/GraalCompiler/src/com/sun/c1x/gen/PhiSimplifier.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/gen/PhiSimplifier.java Tue Jun 07 16:27:08 2011 +0200 @@ -23,7 +23,6 @@ package com.sun.c1x.gen; import com.oracle.graal.graph.*; -import com.sun.c1x.graph.*; import com.sun.c1x.ir.*; /** @@ -34,8 +33,7 @@ private NodeBitMap visited; private NodeBitMap cannotSimplify; - public PhiSimplifier(IR ir) { - Graph graph = ir.compilation.graph; + public PhiSimplifier(Graph graph) { visited = graph.createNodeBitMap(); cannotSimplify = graph.createNodeBitMap(); diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java --- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Tue Jun 07 16:27:08 2011 +0200 @@ -121,9 +121,11 @@ /** * Builds the graph for a the specified {@code IRScope}. - * @param scope the top IRScope + * + * @param createUnwind setting this to true will always generate an unwind block, even if there is no exception + * handler and the method is not synchronized */ - public void build() { + public void build(boolean createUnwind) { if (log != null) { log.println(); log.println("Compiling " + method); @@ -161,6 +163,10 @@ } else { // 4B.1 simply finish the start block finishStartBlock(startBlock); + + if (createUnwind) { + syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null); + } } // 5. SKIPPED: look for intrinsics @@ -544,6 +550,7 @@ Value yValue = frameState.pop(y); Value xValue = frameState.pop(x); Value result1 = append(new ArithmeticOp(opcode, result, xValue, yValue, isStrict(method.accessFlags()), canTrap, graph)); + append(new ValueAnchor(result1, graph)); frameState.push(result, result1); } diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/graph/IR.java --- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java Tue Jun 07 16:27:08 2011 +0200 @@ -83,15 +83,6 @@ C1XTimers.HIR_OPTIMIZE.start(); } - new PhiSimplifier(this); - -// Graph newGraph = new Graph(); -// HashMap replacement = new HashMap(); -// replacement.put(compilation.graph.start(), newGraph.start()); -// replacement.put(compilation.graph.end(), newGraph.end()); -// newGraph.addDuplicate(compilation.graph.getNodes(), replacement); -// compilation.graph = newGraph; - Graph graph = compilation.graph; // Split critical edges. @@ -102,7 +93,7 @@ for (int j = 0; j < n.successors().size(); ++j) { Node succ = n.successors().get(j); if (Schedule.truePredecessorCount(succ) > 1) { - Anchor a = new Anchor(null, graph); + Anchor a = new Anchor(graph); a.successors().setAndClear(1, n, j); n.successors().set(j, a); } @@ -164,52 +155,18 @@ private void buildGraph() { // Graph builder must set the startBlock and the osrEntryBlock - new GraphBuilder(compilation, compilation.method, compilation.graph).build(); + new GraphBuilder(compilation, compilation.method, compilation.graph).build(false); verifyAndPrint("After graph building"); - List trivialInline = new ArrayList(); - List deoptInline = new ArrayList(); - List deoptMethods = new ArrayList(); - for (Node node : compilation.graph.getNodes()) { - if (node instanceof Invoke) { - Invoke invoke = (Invoke) node; - RiMethod target = invoke.target; - if (target.isResolved() && !Modifier.isNative(target.accessFlags())) { - if (target.canBeStaticallyBound()) { - trivialInline.add(invoke); - } else { - RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target); - if (concrete != null) { - deoptInline.add(invoke); - deoptMethods.add(concrete); - } - } - } - } + DeadCodeElimination dce = new DeadCodeElimination(); + dce.apply(compilation.graph); + if (dce.deletedNodeCount > 0) { + verifyAndPrint("After dead code elimination"); } - int allowedInlinings = 50; - for (Invoke invoke : trivialInline) { - if (inlineMethod(invoke, invoke.target)) { - if (--allowedInlinings <= 0) { - break; - } - } - } - - for (int i = 0; i < deoptInline.size(); i++) { - Invoke invoke = deoptInline.get(i); - RiMethod method = deoptMethods.get(i); - if (inlineMethod(invoke, method)) { - if (C1XOptions.TraceInlining) { - System.out.println("registering concrete method assumption..."); - } - compilation.assumptions.recordConcreteMethod(invoke.target, method); - if (--allowedInlinings <= 0) { - break; - } - } + if (C1XOptions.Inline) { + inlineMethods(); } if (C1XOptions.PrintCompilation) { @@ -217,23 +174,100 @@ } } + private void inlineMethods() { + int inliningSize = compilation.method.code().length; + boolean inlined; + int iterations = C1XOptions.MaximumRecursiveInlineLevel; + do { + inlined = false; + + List trivialInline = new ArrayList(); + List deoptInline = new ArrayList(); + List deoptMethods = new ArrayList(); + for (Node node : compilation.graph.getNodes()) { + if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + RiMethod target = invoke.target; + if (target.isResolved() && !Modifier.isNative(target.accessFlags())) { + if (target.canBeStaticallyBound()) { + trivialInline.add(invoke); + } else { + RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target); + if (concrete != null && concrete.isResolved() && !Modifier.isNative(concrete.accessFlags())) { + deoptInline.add(invoke); + deoptMethods.add(concrete); + } + } + } + } + } + + for (Invoke invoke : trivialInline) { + if (inlineMethod(invoke, invoke.target)) { + inlined = true; + inliningSize += invoke.target.code().length; + if (inliningSize > C1XOptions.MaximumInstructionCount) { + break; + } + } + } + + for (int i = 0; i < deoptInline.size(); i++) { + Invoke invoke = deoptInline.get(i); + RiMethod method = deoptMethods.get(i); + if (inlineMethod(invoke, method)) { + if (C1XOptions.TraceInlining) { + System.out.println("registering concrete method assumption..."); + } + compilation.assumptions.recordConcreteMethod(invoke.target, method); + inlined = true; + inliningSize += method.code().length; + if (inliningSize > C1XOptions.MaximumInstructionCount) { + break; + } + } + } + + if (inlined) { + DeadCodeElimination dce = new DeadCodeElimination(); + dce.apply(compilation.graph); + if (dce.deletedNodeCount > 0) { + verifyAndPrint("After dead code elimination"); + } + verifyAndPrint("After inlining iteration"); + } + + if (inliningSize > C1XOptions.MaximumInstructionCount) { + break; + } + } while(inlined && (--iterations > 0)); + } + private boolean inlineMethod(Invoke invoke, RiMethod method) { String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)"; + FrameState stateAfter = invoke.stateAfter(); - if (method.code().length > 50) { + if (method.code().length > C1XOptions.MaximumInlineSize) { if (C1XOptions.TraceInlining) { System.out.println("not inlining " + name + " because of code size"); } return false; } - Instruction exceptionEdge = invoke.exceptionEdge(); - if (exceptionEdge != null) { + if (invoke.predecessors().size() == 0) { if (C1XOptions.TraceInlining) { - System.out.println("not inlining " + name + " because of exceptionEdge"); + System.out.println("not inlining " + name + " because the invoke is dead code"); } return false; } + + Instruction exceptionEdge = invoke.exceptionEdge(); +// if (exceptionEdge != null) { +// if (C1XOptions.TraceInlining) { +// System.out.println("not inlining " + name + " because of exceptionEdge"); +// } +// return false; +// } if (!method.holder().isInitialized()) { if (C1XOptions.TraceInlining) { System.out.println("not inlining " + name + " because of non-initialized class"); @@ -242,10 +276,11 @@ } if (C1XOptions.TraceInlining) { - System.out.println("building graph: " + name); + System.out.printf("Building graph for %s, locals: %d, stack: %d\n", name, method.maxLocals(), method.maxStackSize()); } + CompilerGraph graph = new CompilerGraph(); - new GraphBuilder(compilation, method, graph).build(); + new GraphBuilder(compilation, method, graph).build(true); boolean withReceiver = !Modifier.isStatic(method.accessFlags()); @@ -266,12 +301,11 @@ ArrayList frameStates = new ArrayList(); Return returnNode = null; Unwind unwindNode = null; - StartNode startNode = null; - boolean invokes = false; + StartNode startNode = graph.start(); for (Node node : graph.getNodes()) { if (node != null) { if (node instanceof StartNode) { - startNode = (StartNode) node; + assert startNode == node; } else if (node instanceof Local) { replacements.put(node, parameters[((Local) node).index()]); } else { @@ -286,30 +320,19 @@ } } } - if (unwindNode != null) { - if (C1XOptions.TraceInlining) { - System.out.println("not inlining " + name + " because of unwind node"); - } - return false; - } - if (invokes) { - if (C1XOptions.TraceInlining) { - System.out.println("not inlining " + name + " because of invokes"); - } - return false; - } if (C1XOptions.TraceInlining) { + printGraph("Subgraph " + CiUtil.format("%H.%n(%p):%r", method, false), graph); System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes"); } + assert invoke.predecessors().size() == 1 : "size: " + invoke.predecessors().size(); Instruction pred; if (withReceiver) { pred = new NullCheck(parameters[0], compilation.graph); } else { pred = new Merge(compilation.graph); } - assert invoke.predecessors().size() == 1; invoke.predecessors().get(0).successors().replace(invoke, pred); replacements.put(startNode, pred); @@ -331,10 +354,48 @@ Node returnPred = returnDuplicate.predecessors().get(0); int index = returnDuplicate.predecessorsIndex().get(0); returnPred.successors().setAndClear(index, invoke, 0); - returnDuplicate.delete(); } - FrameState stateAfter = invoke.stateAfter(); + +// if (invoke.next() instanceof Merge) { +// ((Merge) invoke.next()).removePhiPredecessor(invoke); +// } +// invoke.successors().clearAll(); + invoke.inputs().clearAll(); + invoke.setExceptionEdge(null); +// invoke.delete(); + + + if (exceptionEdge != null) { + if (unwindNode != null) { + assert unwindNode.predecessors().size() == 1; + assert exceptionEdge.successors().size() == 1; + ExceptionObject obj = (ExceptionObject) exceptionEdge; + + List usages = new ArrayList(obj.usages()); + for (Node usage : usages) { + if (replacements.containsKey(unwindNode.exception())) { + usage.inputs().replace(obj, replacements.get(unwindNode.exception())); + } else { + usage.inputs().replace(obj, duplicates.get(unwindNode.exception())); + } + } + Node unwindDuplicate = duplicates.get(unwindNode); + unwindDuplicate.inputs().clearAll(); + + assert unwindDuplicate.predecessors().size() == 1; + Node unwindPred = unwindDuplicate.predecessors().get(0); + int index = unwindDuplicate.predecessorsIndex().get(0); + unwindPred.successors().setAndClear(index, obj, 0); + + obj.inputs().clearAll(); + obj.delete(); + unwindDuplicate.delete(); + + } + } + + // adjust all frame states that were copied if (frameStates.size() > 0) { FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, invoke.kind); for (Node frameState : frameStates) { @@ -342,52 +403,12 @@ } } - invoke.successors().clearAll(); - invoke.inputs().clearAll(); - invoke.delete(); - - stateAfter.delete(); - - deleteUnused(exceptionEdge); - - verifyAndPrint("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false)); + if (C1XOptions.TraceInlining) { + verifyAndPrint("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false)); + } return true; } - private void deleteUnused(Node node) { - if (node != null && node.predecessors().size() == 0) { - if (node instanceof ExceptionObject) { - Node successor = node.successors().get(0); - node.successors().clearAll(); - if (successor instanceof ExceptionDispatch) { - ExceptionDispatch dispatch = (ExceptionDispatch) successor; - Node succ1 = dispatch.catchSuccessor(); - Node succ2 = dispatch.otherSuccessor(); - if (succ1 instanceof Merge) { - ((Merge) succ1).removePhiPredecessor(dispatch); - } - if (succ2 instanceof Merge) { - ((Merge) succ2).removePhiPredecessor(dispatch); - } - dispatch.successors().clearAll(); - deleteUnused(succ1); - deleteUnused(succ2); - dispatch.delete(); - } else { - assert successor instanceof Merge; - System.out.println("succ: " + successor.successors().get(0)); - Node next = successor.successors().get(0); - successor.successors().clearAll(); - deleteUnused(next); - successor.delete(); - } - node.delete(); - } else if (node instanceof Unwind) { - node.delete(); - } - } - } - /** * Gets the linear scan ordering of blocks as a list. * @return the blocks in linear scan order @@ -420,6 +441,17 @@ } } + public void printGraph(String phase, Graph graph) { + if (C1XOptions.PrintHIR && !TTY.isSuppressed()) { + TTY.println(phase); + print(false); + } + + if (compilation.compiler.isObserved()) { + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, phase, graph, true, false)); + } + } + public int numLoops() { return compilation.stats.loopCount; } diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/ir/Anchor.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Anchor.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Anchor.java Tue Jun 07 16:27:08 2011 +0200 @@ -27,7 +27,7 @@ import com.sun.cri.ci.*; /** - * The {@code Goto} instruction represents the end of a block with an unconditional jump to another block. + * The {@code Anchor} instruction represents the end of a block with an unconditional jump to another block. */ public final class Anchor extends BlockEnd { @@ -35,14 +35,11 @@ private static final int SUCCESSOR_COUNT = 0; /** - * Constructs a new Goto instruction. - * @param succ the successor block of the goto - * @param stateAfter the frame state at the end of this block + * Constructs a new Anchor instruction. * @param graph */ - public Anchor(Instruction succ, Graph graph) { + public Anchor(Graph graph) { super(CiKind.Illegal, 1, INPUT_COUNT, SUCCESSOR_COUNT, graph); - setBlockSuccessor(0, succ); } @Override @@ -57,7 +54,7 @@ @Override public Node copy(Graph into) { - Anchor x = new Anchor(null, into); + Anchor x = new Anchor(into); x.setNonNull(isNonNull()); return x; } diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/ir/Deoptimize.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Deoptimize.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Deoptimize.java Tue Jun 07 16:27:08 2011 +0200 @@ -57,7 +57,7 @@ @Override public String shortName() { - return "Deopt " + message; + return message == null ? "Deopt " : "Deopt " + message; } @Override diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java Tue Jun 07 16:27:08 2011 +0200 @@ -268,15 +268,15 @@ return x; } - public void removePhiPredecessor(ExceptionDispatch successor) { - int predIndex = predecessors().indexOf(successor); + public void removePhiPredecessor(Node pred) { + int predIndex = predecessors().lastIndexOf(pred); assert predIndex != -1; for (Node usage : usages()) { if (usage instanceof Phi) { Phi phi = (Phi) usage; - assert phi.valueCount() == predecessors().size(); - phi.removeInput(predIndex + 1); +// assert phi.valueCount() == predecessors().size(); + phi.removeInput(predIndex); } } } diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java Tue Jun 07 16:27:08 2011 +0200 @@ -78,7 +78,7 @@ public Phi(CiKind kind, Merge block, int maxValues, Graph graph) { super(kind, INPUT_COUNT + maxValues, SUCCESSOR_COUNT, graph); this.maxValues = maxValues; - usedInputCount = 1; + usedInputCount = 0; setBlock(block); } @@ -89,7 +89,11 @@ * @return the instruction that produced the value in the i'th predecessor */ public Value valueAt(int i) { - return (Value) inputs().get(i + INPUT_COUNT); + return (Value) inputs().get(INPUT_COUNT + i); + } + + public Node setValueAt(int i, Node x) { + return inputs().set(INPUT_COUNT + i, x); } /** @@ -97,7 +101,7 @@ * @return the number of inputs in this phi */ public int valueCount() { - return usedInputCount - 1; + return usedInputCount; } @Override @@ -119,11 +123,11 @@ @Override public void print(LogStream out) { out.print("phi function ("); - for (int i = 0; i < inputs().size(); ++i) { + for (int i = 0; i < valueCount(); ++i) { if (i != 0) { out.print(' '); } - out.print((Value) inputs().get(i)); + out.print(valueAt(i)); } out.print(')'); } @@ -143,23 +147,24 @@ public Phi addInput(Node y) { assert !this.isDeleted() && !y.isDeleted(); Phi phi = this; - if (usedInputCount == inputs().size()) { - phi = new Phi(kind, block(), usedInputCount * 2, graph()); + if (usedInputCount == maxValues) { + phi = new Phi(kind, block(), maxValues * 2, graph()); for (int i = 0; i < valueCount(); ++i) { phi.addInput(valueAt(i)); } phi.addInput(y); this.replace(phi); } else { - phi.inputs().set(usedInputCount++, y); + setValueAt(usedInputCount++, y); } return phi; } public void removeInput(int index) { - inputs().set(index, null); - for (int i = index + 1; i < usedInputCount; ++i) { - inputs().set(i - 1, inputs().get(i)); + assert index < valueCount() : "index: " + index + ", valueCount: " + valueCount() + "@phi " + id(); + setValueAt(index, Node.Null); + for (int i = index + 1; i < valueCount(); ++i) { + setValueAt(i - 1, valueAt(i)); } usedInputCount--; } diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/ir/ValueAnchor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ValueAnchor.java Tue Jun 07 16:27:08 2011 +0200 @@ -0,0 +1,86 @@ +/* + * 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.sun.c1x.ir; + +import com.oracle.graal.graph.*; +import com.sun.c1x.debug.*; +import com.sun.cri.ci.*; + +/** + * The ValueAnchor instruction keeps non-CFG nodes above a certain point in the graph. + */ +public final class ValueAnchor extends Instruction { + + 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; + } + + @Override + protected int successorCount() { + return super.successorCount() + SUCCESSOR_COUNT; + } + + /** + * The instruction that should be scheduled before this anchor. + */ + public Value object() { + return (Value) inputs().get(super.inputCount() + INPUT_OBJECT); + } + + public Value setObject(Value n) { + return (Value) inputs().set(super.inputCount() + INPUT_OBJECT, n); + } + + /** + * Constructs a new Anchor instruction. + * @param succ the successor block of the anchor + * @param graph + */ + public ValueAnchor(Value object, Graph graph) { + super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); + setObject(object); + } + + @Override + public void accept(ValueVisitor v) { + v.visitValueAnchor(this); + } + + @Override + public void print(LogStream out) { + out.print("value_anchor ").print(object()); + } + + @Override + public Node copy(Graph into) { + ValueAnchor x = new ValueAnchor(null, into); + x.setNonNull(isNonNull()); + return x; + } +} diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java Tue Jun 07 16:27:08 2011 +0200 @@ -71,4 +71,5 @@ public abstract void visitUnwind(Unwind unwind); public abstract void visitLoopBegin(LoopBegin loopBegin); public abstract void visitLoopEnd(LoopEnd loopEnd); + public abstract void visitValueAnchor(ValueAnchor valueAnchor); } diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java Tue Jun 07 16:27:08 2011 +0200 @@ -547,4 +547,9 @@ lir.jump(getLIRBlock(x.loopBegin())); } + @Override + public void visitValueAnchor(ValueAnchor valueAnchor) { + // nothing to do for ValueAnchors + } + } diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java --- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java Tue Jun 07 16:27:08 2011 +0200 @@ -49,7 +49,9 @@ this.method = method; this.graph = graph; this.locals = new Value[method.maxLocals()]; - this.stack = new Value[method.maxStackSize()]; + // we always need at least one stack slot (for exceptions) + int stackSize = Math.max(1, method.maxStackSize()); + this.stack = new Value[stackSize]; int javaIndex = 0; int index = 0; @@ -82,8 +84,8 @@ } public void initializeFrom(FrameState other) { - assert locals.length == other.localsSize(); - assert stack.length >= other.stackSize(); + assert locals.length == other.localsSize() : "expected: " + locals.length + ", actual: " + other.localsSize(); + assert stack.length >= other.stackSize() : "expected: <=" + stack.length + ", actual: " + other.stackSize(); this.stackIndex = other.stackSize(); for (int i = 0; i < other.localsSize(); i++) { diff -r e55543ff91fd -r 7f14e6b48a9c graal/GraalGraph/src/com/oracle/graal/graph/Node.java --- a/graal/GraalGraph/src/com/oracle/graal/graph/Node.java Wed Jun 01 16:56:54 2011 +0200 +++ b/graal/GraalGraph/src/com/oracle/graal/graph/Node.java Tue Jun 07 16:27:08 2011 +0200 @@ -118,7 +118,7 @@ public void delete() { assert !isDeleted(); - assert usages.size() == 0 && predecessors.size() == 0 : "usages: " + usages.size() + ", predecessors: " + predecessors().size(); + assert usages.size() == 0 && predecessors.size() == 0 : "id: " + id + ", usages: " + usages.size() + ", predecessors: " + predecessors().size(); assert predecessorsIndex.size() == 0; for (int i = 0; i < inputs.size(); ++i) { inputs.set(i, Null);