# HG changeset patch # User Thomas Wuerthinger # Date 1307514698 -7200 # Node ID d704eb52660355e447621a7cb2793b4531f6758d # Parent 9075634c8d114df2c8d667119ec034657ed3a4c2# Parent fc75fd3fa5e4e97540fffe6b5c2c114f41166f1e Merge. diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/oracle/max/graal/opt/CanonicalizerPhase.java --- a/graal/GraalCompiler/src/com/oracle/max/graal/opt/CanonicalizerPhase.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/oracle/max/graal/opt/CanonicalizerPhase.java Wed Jun 08 08:31:38 2011 +0200 @@ -22,15 +22,47 @@ */ package com.oracle.max.graal.opt; +import java.util.*; + import com.oracle.graal.graph.*; +import com.sun.c1x.*; public class CanonicalizerPhase extends Phase { @Override protected void run(Graph graph) { - // TODO Auto-generated method stub + NodeBitMap visited = graph.createNodeBitMap(); + List nodes = new ArrayList(graph.getNodes()); + for (Node n : nodes) { + if (n == null) { + continue; + } + if (!visited.isMarked(n)) { + this.canonicalize(n, visited); + } + } + } + private void canonicalize(Node n, NodeBitMap visited) { + visited.mark(n); + for (Node input : n.inputs()) { + if (input == null) { + continue; + } + if (!visited.isNew(input) && !visited.isMarked(input)) { + canonicalize(input, visited); + } + } + + CanonicalizerOp op = n.lookup(CanonicalizerOp.class); + if (op != null) { + Node canonical = op.canonical(n); + if (canonical != n) { + n.replace(canonical); + C1XMetrics.NodesCanonicalized++; + } + } } public interface CanonicalizerOp extends Op { diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java --- a/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java Wed Jun 08 08:31:38 2011 +0200 @@ -81,7 +81,7 @@ return b; } - private static boolean isCFG(Node n) { + public static boolean isFixed(Node n) { return n != null && ((n instanceof FixedNode) || n == n.graph().start()); } @@ -95,7 +95,7 @@ NodeIterator.iterate(EdgeType.SUCCESSORS, graph.start(), null, new NodeVisitor() { @Override public boolean visit(Node n) { - if (!isCFG(n)) { + if (!isFixed(n)) { return false; } @@ -108,7 +108,7 @@ Node singlePred = null; for (Node pred : n.predecessors()) { - if (isCFG(pred)) { + if (isFixed(pred)) { if (singlePred == null) { singlePred = pred; } else { @@ -141,7 +141,7 @@ for (Node n : blockBeginNodes) { Block block = nodeToBlock.get(n); for (Node pred : n.predecessors()) { - if (isCFG(pred)) { + if (isFixed(pred)) { Block predBlock = nodeToBlock.get(pred); predBlock.addSuccessor(block); } @@ -229,7 +229,7 @@ } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) { Merge merge = ((FrameState) usage).block(); for (Node pred : merge.predecessors()) { - if (isCFG(pred)) { + if (isFixed(pred)) { block = getCommonDominator(block, nodeToBlock.get(pred)); } } @@ -437,7 +437,7 @@ } int i = 0; for (Node s : n.successors()) { - if (isCFG(s)) { + if (isFixed(s)) { i++; } } @@ -450,7 +450,7 @@ } int i = 0; for (Node s : n.predecessors()) { - if (isCFG(s)) { + if (isFixed(s)) { i++; } } diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/C1XMetrics.java --- a/graal/GraalCompiler/src/com/sun/c1x/C1XMetrics.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/C1XMetrics.java Wed Jun 08 08:31:38 2011 +0200 @@ -62,6 +62,7 @@ public static int UniqueValueIdsAssigned; public static int FrameStatesCreated; public static int FrameStateValuesCreated; + public static int NodesCanonicalized; public static void print() { printClassFields(C1XMetrics.class); diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java --- a/graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java Wed Jun 08 08:31:38 2011 +0200 @@ -45,7 +45,7 @@ public static int MaximumInlineSize = 35; public static int MaximumTrivialSize = 6; public static int MaximumInlineLevel = 9; - public static int MaximumRecursiveInlineLevel = 1; + public static int MaximumRecursiveInlineLevel = 2; public static int MaximumDesiredSize = 8000; public static int MaximumShortLoopSize = 5; @@ -69,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; @@ -92,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 = ____; @@ -127,4 +128,6 @@ // Assembler settings public static boolean CommentedAssembly = ____; public static boolean PrintLIRWithAssembly = ____; + + public static boolean OptCanonicalizer = true; } diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java --- a/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java Wed Jun 08 08:31:38 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 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java --- a/graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/debug/IdealGraphPrinter.java Wed Jun 08 08:31:38 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 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java --- a/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java Wed Jun 08 08:31:38 2011 +0200 @@ -1377,7 +1377,7 @@ } private CiValue operandForPhi(Phi phi) { - assert !phi.isDead(); + assert !phi.isDead() : "dead phi: " + phi.id(); if (phi.operand().isIllegal()) { // allocate a variable for this phi CiVariable operand = newVariable(phi.kind); diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/gen/PhiSimplifier.java --- a/graal/GraalCompiler/src/com/sun/c1x/gen/PhiSimplifier.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/gen/PhiSimplifier.java Wed Jun 08 08:31:38 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 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/graph/DeadCodeElimination.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/DeadCodeElimination.java Wed Jun 08 08:31:38 2011 +0200 @@ -0,0 +1,133 @@ +/* + * 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.graph; + +import com.oracle.graal.graph.*; +import com.sun.c1x.*; +import com.sun.c1x.gen.*; +import com.sun.c1x.ir.*; + + +public class DeadCodeElimination extends Phase { + + private NodeBitMap alive; + private NodeWorklist worklist; + private Graph graph; + + public int deletedNodeCount; + + @Override + protected void run(Graph graph) { + this.graph = graph; + this.alive = graph.createNodeBitMap(); + this.worklist = graph.createNodeWorklist(); + + worklist.add(graph.start()); + + iterateSuccessors(); + disconnectCFGNodes(); + + iterateInputs(); + disconnectNonCFGNodes(); + + deleteCFGNodes(); + deleteNonCFGNodes(); + + new PhiSimplifier(graph); + + if (C1XOptions.TraceDeadCodeElimination) { + System.out.printf("dead code elimination: deleted %d nodes\n", deletedNodeCount); + } + } + + private static boolean isCFG(Node n) { + return n != null && ((n instanceof Instruction) || n == n.graph().start()); + } + + private void iterateSuccessors() { + for (Node current : worklist) { + for (Node successor : current.successors()) { + worklist.add(successor); + } + } + } + + private void disconnectCFGNodes() { + for (Node node : graph.getNodes()) { + if (node != Node.Null && !worklist.isMarked(node) && isCFG(node)) { + // iterate backwards so that the predecessor indexes in removePhiPredecessor are correct + for (int i = node.successors().size() - 1; i >= 0; i--) { + Node successor = node.successors().get(i); + if (successor != Node.Null && worklist.isMarked(successor)) { + if (successor instanceof Merge) { + ((Merge) successor).removePhiPredecessor(node); + } + } + } + node.successors().clearAll(); + node.inputs().clearAll(); + } + } + } + + private void deleteCFGNodes() { + for (Node node : graph.getNodes()) { + if (node != Node.Null && !worklist.isMarked(node) && isCFG(node)) { + node.delete(); + deletedNodeCount++; + } + } + } + + private void iterateInputs() { + for (Node node : graph.getNodes()) { + if (node != Node.Null && worklist.isMarked(node)) { + for (Node input : node.inputs()) { + worklist.add(input); + } + } + } + for (Node current : worklist) { + for (Node input : current.inputs()) { + worklist.add(input); + } + } + } + + private void disconnectNonCFGNodes() { + for (Node node : graph.getNodes()) { + if (node != Node.Null && !worklist.isMarked(node) && !isCFG(node)) { + node.inputs().clearAll(); + } + } + } + + private void deleteNonCFGNodes() { + for (Node node : graph.getNodes()) { + if (node != Node.Null && !worklist.isMarked(node) && !isCFG(node)) { + node.delete(); + deletedNodeCount++; + } + } + } +} diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java --- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Wed Jun 08 08:31:38 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,9 @@ Value yValue = frameState.pop(y); Value xValue = frameState.pop(x); Value result1 = append(new Arithmetic(opcode, result, xValue, yValue, isStrict(method.accessFlags()), canTrap, graph)); + if (canTrap) { + append(new ValueAnchor(result1, graph)); + } frameState.push(result, result1); } @@ -554,7 +563,18 @@ private void genShiftOp(CiKind kind, int opcode) { Value s = frameState.ipop(); Value x = frameState.pop(kind); - frameState.push(kind, append(new Shift(opcode, x, s, graph))); + Shift v; + switch(opcode){ + case ISHL: + case LSHL: v = new LeftShift(kind, x, s, graph); break; + case ISHR: + case LSHR: v = new RightShift(kind, x, s, graph); break; + case IUSHR: + case LUSHR: v = new UnsignedRightShift(kind, x, s, graph); break; + default: + throw new CiBailout("should not reach"); + } + frameState.push(kind, append(v)); } private void genLogicOp(CiKind kind, int opcode) { diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/graph/IR.java --- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java Wed Jun 08 08:31:38 2011 +0200 @@ -26,10 +26,10 @@ import java.util.*; import com.oracle.graal.graph.*; +import com.oracle.max.graal.opt.*; import com.oracle.max.graal.schedule.*; import com.sun.c1x.*; import com.sun.c1x.debug.*; -import com.sun.c1x.gen.*; import com.sun.c1x.ir.*; import com.sun.c1x.lir.*; import com.sun.c1x.observer.*; @@ -83,16 +83,12 @@ C1XTimers.HIR_OPTIMIZE.start(); } - new PhiSimplifier(this); + Graph graph = compilation.graph; -// 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; + if (C1XOptions.OptCanonicalizer) { + new CanonicalizerPhase().apply(graph); + verifyAndPrint("After canonicalization"); + } // Split critical edges. List nodes = graph.getNodes(); @@ -102,7 +98,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,54 +160,24 @@ 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); + +// CompilerGraph duplicate = new CompilerGraph(); +// Map replacements = new HashMap(); +// replacements.put(compilation.graph.start(), duplicate.start()); +// duplicate.addDuplicate(compilation.graph.getNodes(), replacements); +// compilation.graph = duplicate; verifyAndPrint("After graph building"); - if (C1XOptions.Inline) { - 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) { + new Inlining(compilation, this).apply(compilation.graph); } if (C1XOptions.PrintCompilation) { @@ -219,177 +185,6 @@ } } - private boolean inlineMethod(Invoke invoke, RiMethod method) { - String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)"; - - if (method.code().length > 50) { - if (C1XOptions.TraceInlining) { - System.out.println("not inlining " + name + " because of code size"); - } - 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"); - } - return false; - } - - if (C1XOptions.TraceInlining) { - System.out.println("building graph: " + name); - } - CompilerGraph graph = new CompilerGraph(); - new GraphBuilder(compilation, method, graph).build(); - - boolean withReceiver = !Modifier.isStatic(method.accessFlags()); - - 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); - slot += method.signature().argumentKindAt(i).sizeInSlots(); - } - if (withReceiver) { - parameters[0] = invoke.argument(0); - } - - HashMap replacements = new HashMap(); - ArrayList nodes = new ArrayList(); - ArrayList frameStates = new ArrayList(); - Return returnNode = null; - Unwind unwindNode = null; - StartNode startNode = null; - boolean invokes = false; - for (Node node : graph.getNodes()) { - if (node != null) { - if (node instanceof StartNode) { - startNode = (StartNode) node; - } else if (node instanceof Local) { - replacements.put(node, parameters[((Local) node).index()]); - } else { - nodes.add(node); - if (node instanceof Return) { - returnNode = (Return) node; - } else if (node instanceof Unwind) { - unwindNode = (Unwind) node; - } else if (node instanceof FrameState) { - frameStates.add(node); - } - } - } - } - 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) { - System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes"); - } - - 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); - - Map duplicates = compilation.graph.addDuplicate(nodes, replacements); - - if (returnNode != null) { - List usages = new ArrayList(invoke.usages()); - for (Node usage : usages) { - if (returnNode.result() instanceof Local) { - usage.inputs().replace(invoke, replacements.get(returnNode.result())); - } else { - usage.inputs().replace(invoke, duplicates.get(returnNode.result())); - } - } - Node returnDuplicate = duplicates.get(returnNode); - returnDuplicate.inputs().clearAll(); - - assert returnDuplicate.predecessors().size() == 1; - 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 (frameStates.size() > 0) { - FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, invoke.kind); - for (Node frameState : frameStates) { - ((FrameState) duplicates.get(frameState)).setOuterFrameState(outerFrameState); - } - } - - invoke.successors().clearAll(); - invoke.inputs().clearAll(); - invoke.delete(); - - stateAfter.delete(); - - deleteUnused(exceptionEdge); - - 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 @@ -422,6 +217,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 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/graph/Inlining.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/Inlining.java Wed Jun 08 08:31:38 2011 +0200 @@ -0,0 +1,288 @@ +/* + * 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.graph; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.graph.*; +import com.sun.c1x.*; +import com.sun.c1x.ir.*; +import com.sun.c1x.value.*; +import com.sun.cri.ci.*; +import com.sun.cri.ri.*; + + +public class Inlining extends Phase { + + private final C1XCompilation compilation; + private final IR ir; + + private final Queue invokes = new ArrayDeque(); + private final Queue methods = new ArrayDeque(); + private int inliningSize; + + public Inlining(C1XCompilation compilation, IR ir) { + this.compilation = compilation; + this.ir = ir; + } + + private void addToQueue(Invoke invoke, RiMethod method) { + invokes.add(invoke); + methods.add(method); + inliningSize += method.code().length; + } + + @Override + protected void run(Graph graph) { + if (!C1XOptions.Inline) { + return; + } + + inliningSize = compilation.method.code().length; + int iterations = C1XOptions.MaximumRecursiveInlineLevel; + do { + for (Node node : graph.getNodes()) { + if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + RiMethod target = invoke.target; + if (!checkInliningConditions(invoke) || !target.isResolved() || Modifier.isNative(target.accessFlags())) { + continue; + } + if (target.canBeStaticallyBound()) { + if (checkInliningConditions(invoke.target)) { + addToQueue(invoke, invoke.target); + } + } else { + RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target); + if (concrete != null && concrete.isResolved() && !Modifier.isNative(concrete.accessFlags())) { + if (checkInliningConditions(concrete)) { + if (C1XOptions.TraceInlining) { + System.out.println("registering concrete method assumption..."); + } + compilation.assumptions.recordConcreteMethod(invoke.target, concrete); + addToQueue(invoke, concrete); + } + } + } + if (inliningSize > C1XOptions.MaximumInstructionCount) { + break; + } + } + } + + assert invokes.size() == methods.size(); + if (invokes.isEmpty()) { + break; + } + + Invoke invoke; + while ((invoke = invokes.poll()) != null) { + RiMethod method = methods.remove(); + inlineMethod(invoke, method); + } + DeadCodeElimination dce = new DeadCodeElimination(); + dce.apply(graph); + if (dce.deletedNodeCount > 0) { + ir.verifyAndPrint("After dead code elimination"); + } + ir.verifyAndPrint("After inlining iteration"); + + if (inliningSize > C1XOptions.MaximumInstructionCount) { + if (C1XOptions.TraceInlining) { + System.out.println("inlining stopped: MaximumInstructionCount reached"); + } + break; + } + } while(--iterations > 0); + } + + private boolean checkInliningConditions(Invoke invoke) { + String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", invoke.target, false); + if (invoke.predecessors().size() == 0) { + if (C1XOptions.TraceInlining) { + System.out.println("not inlining " + name + " because the invoke is dead code"); + } + return false; + } + return true; + } + + private boolean checkInliningConditions(RiMethod method) { + String name = null; + if (C1XOptions.TraceInlining) { + name = CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)"; + } + if (method.code().length > C1XOptions.MaximumInlineSize) { + if (C1XOptions.TraceInlining) { + System.out.println("not inlining " + name + " because of code size"); + } + return false; + } + if (!method.holder().isInitialized()) { + if (C1XOptions.TraceInlining) { + System.out.println("not inlining " + name + " because of non-initialized class"); + } + return false; + } + return true; + } + + private void 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(); + Instruction exceptionEdge = invoke.exceptionEdge(); + + if (C1XOptions.TraceInlining) { + 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(true); + + boolean withReceiver = !Modifier.isStatic(method.accessFlags()); + + 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); + slot += method.signature().argumentKindAt(i).sizeInSlots(); + } + if (withReceiver) { + parameters[0] = invoke.argument(0); + } + + HashMap replacements = new HashMap(); + ArrayList nodes = new ArrayList(); + ArrayList frameStates = new ArrayList(); + Return returnNode = null; + Unwind unwindNode = null; + StartNode startNode = graph.start(); + for (Node node : graph.getNodes()) { + if (node != null) { + if (node instanceof StartNode) { + assert startNode == node; + } else if (node instanceof Local) { + replacements.put(node, parameters[((Local) node).index()]); + } else { + nodes.add(node); + if (node instanceof Return) { + returnNode = (Return) node; + } else if (node instanceof Unwind) { + unwindNode = (Unwind) node; + } else if (node instanceof FrameState) { + frameStates.add(node); + } + } + } + } + + if (C1XOptions.TraceInlining) { + ir.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); + } + invoke.predecessors().get(0).successors().replace(invoke, pred); + replacements.put(startNode, pred); + + Map duplicates = compilation.graph.addDuplicate(nodes, replacements); + + if (returnNode != null) { + List usages = new ArrayList(invoke.usages()); + for (Node usage : usages) { + if (returnNode.result() instanceof Local) { + usage.inputs().replace(invoke, replacements.get(returnNode.result())); + } else { + usage.inputs().replace(invoke, duplicates.get(returnNode.result())); + } + } + Node returnDuplicate = duplicates.get(returnNode); + returnDuplicate.inputs().clearAll(); + + assert returnDuplicate.predecessors().size() == 1; + Node returnPred = returnDuplicate.predecessors().get(0); + int index = returnDuplicate.predecessorsIndex().get(0); + returnPred.successors().setAndClear(index, invoke, 0); + returnDuplicate.delete(); + } + +// 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) { + ((FrameState) duplicates.get(frameState)).setOuterFrameState(outerFrameState); + } + } + + if (C1XOptions.TraceInlining) { + ir.verifyAndPrint("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false)); + } + } +} diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/ir/Anchor.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Anchor.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Anchor.java Wed Jun 08 08:31:38 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); return x; } } diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/ir/And.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/And.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/And.java Wed Jun 08 08:31:38 2011 +0200 @@ -47,7 +47,7 @@ @Override public Node copy(Graph into) { - And x = new And(kind, null, null, graph()); + And x = new And(kind, null, null, into); return x; } diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/ir/Deoptimize.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Deoptimize.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Deoptimize.java Wed Jun 08 08:31:38 2011 +0200 @@ -57,7 +57,7 @@ @Override public String shortName() { - return "Deopt " + message; + return message == null ? "Deopt " : "Deopt " + message; } @Override diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/ir/LeftShift.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LeftShift.java Wed Jun 08 08:31:38 2011 +0200 @@ -0,0 +1,54 @@ +/* + * 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.cri.bytecode.*; +import com.sun.cri.ci.*; + + +public final class LeftShift extends Shift { + + /** + * @param opcode + * @param kind + * @param x + * @param y + * @param graph + */ + public LeftShift(CiKind kind, Value x, Value y, Graph graph) { + super(kind, kind == CiKind.Int ? Bytecodes.ISHL : Bytecodes.LSHL, x, y, graph); + } + + @Override + public String shortName() { + return "<<"; + } + + @Override + public Node copy(Graph into) { + LeftShift ls = new LeftShift(kind, null, null, graph()); + return ls; + } + +} diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java Wed Jun 08 08:31:38 2011 +0200 @@ -267,15 +267,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 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/ir/Or.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Or.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Or.java Wed Jun 08 08:31:38 2011 +0200 @@ -23,6 +23,7 @@ package com.sun.c1x.ir; import com.oracle.graal.graph.*; +import com.oracle.max.graal.opt.CanonicalizerPhase.CanonicalizerOp; import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; @@ -31,6 +32,7 @@ * */ public final class Or extends Logic { + private static final OrCanonicalizerOp CANONICALIZER = new OrCanonicalizerOp(); /** * @param opcode @@ -50,8 +52,65 @@ @Override public Node copy(Graph into) { - Or x = new Or(kind, null, null, graph()); + Or x = new Or(kind, null, null, into); return x; } + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == CanonicalizerOp.class) { + return (T) CANONICALIZER; + } + return super.lookup(clazz); + } + + private static class OrCanonicalizerOp implements CanonicalizerOp { + @Override + public Node canonical(Node node) { + assert node instanceof Or; + Or or = (Or) node; + CiKind kind = or.kind; + Graph graph = or.graph(); + Value x = or.x(); + Value y = or.y(); + if (x == y) { + return x; + } + if (x.isConstant() && !y.isConstant()) { + or.swapOperands(); + Value t = y; + y = x; + x = t; + } + if (x.isConstant()) { + if (kind == CiKind.Int) { + return Constant.forInt(x.asConstant().asInt() | y.asConstant().asInt(), graph); + } else { + assert kind == CiKind.Long; + return Constant.forLong(x.asConstant().asLong() | y.asConstant().asLong(), graph); + } + } else if (y.isConstant()) { + if (kind == CiKind.Int) { + int c = y.asConstant().asInt(); + if (c == -1) { + return Constant.forInt(-1, graph); + } + if (c == 0) { + return x; + } + } else { + assert kind == CiKind.Long; + long c = y.asConstant().asLong(); + if (c == -1) { + return Constant.forLong(-1, graph); + } + if (c == 0) { + return x; + } + } + } + return or; + } + } } diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java Wed Jun 08 08:31:38 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 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/ir/RightShift.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/RightShift.java Wed Jun 08 08:31:38 2011 +0200 @@ -0,0 +1,54 @@ +/* + * 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.cri.bytecode.*; +import com.sun.cri.ci.*; + + +public final class RightShift extends Shift { + + /** + * @param opcode + * @param kind + * @param x + * @param y + * @param graph + */ + public RightShift(CiKind kind, Value x, Value y, Graph graph) { + super(kind, kind == CiKind.Int ? Bytecodes.ISHR : Bytecodes.LSHR, x, y, graph); + } + + @Override + public String shortName() { + return ">>"; + } + + @Override + public Node copy(Graph into) { + RightShift rs = new RightShift(kind, null, null, graph()); + return rs; + } + +} diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/ir/Shift.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Shift.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Shift.java Wed Jun 08 08:31:38 2011 +0200 @@ -24,13 +24,12 @@ import com.oracle.graal.graph.*; import com.sun.c1x.debug.*; -import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; /** * The {@code ShiftOp} class represents shift operations. */ -public final class Shift extends Binary { +public abstract class Shift extends Binary { private static final int INPUT_COUNT = 0; private static final int SUCCESSOR_COUNT = 0; @@ -41,12 +40,8 @@ * @param x the first input value * @param y the second input value */ - public Shift(int opcode, Value x, Value y, Graph graph) { - super(x.kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph); - } - - private Shift(CiKind kind, int opcode, Graph graph) { - super(kind, opcode, null, null, INPUT_COUNT, SUCCESSOR_COUNT, graph); + public Shift(CiKind kind, int opcode, Value x, Value y, Graph graph) { + super(kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph); } @Override @@ -56,12 +51,9 @@ @Override public void print(LogStream out) { - out.print(x()).print(' ').print(Bytecodes.operator(opcode)).print(' ').print(y()); + out.print(x()).print(' ').print(this.shortName()).print(' ').print(y()); } @Override - public Node copy(Graph into) { - Shift x = new Shift(kind, opcode, into); - return x; - } + public abstract String shortName(); } diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/ir/UnsignedRightShift.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/UnsignedRightShift.java Wed Jun 08 08:31:38 2011 +0200 @@ -0,0 +1,54 @@ +/* + * 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.cri.bytecode.*; +import com.sun.cri.ci.*; + + +public final class UnsignedRightShift extends Shift { + + /** + * @param opcode + * @param kind + * @param x + * @param y + * @param graph + */ + public UnsignedRightShift(CiKind kind, Value x, Value y, Graph graph) { + super(kind, kind == CiKind.Int ? Bytecodes.IUSHR : Bytecodes.LUSHR, x, y, graph); + } + + @Override + public String shortName() { + return ">>>"; + } + + @Override + public Node copy(Graph into) { + UnsignedRightShift x = new UnsignedRightShift(kind, null, null, graph()); + return x; + } + +} diff -r 9075634c8d11 -r d704eb526603 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 Wed Jun 08 08:31:38 2011 +0200 @@ -0,0 +1,85 @@ +/* + * 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); + return x; + } +} diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java Wed Jun 08 08:31:38 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 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/ir/Xor.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Xor.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Xor.java Wed Jun 08 08:31:38 2011 +0200 @@ -23,10 +23,12 @@ package com.sun.c1x.ir; import com.oracle.graal.graph.*; +import com.oracle.max.graal.opt.CanonicalizerPhase.CanonicalizerOp; import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; public final class Xor extends Logic { + private static final XorCanonicalizerOp CANONICALIZER = new XorCanonicalizerOp(); /** * @param opcode @@ -46,8 +48,64 @@ @Override public Node copy(Graph into) { - Xor x = new Xor(kind, null, null, graph()); + Xor x = new Xor(kind, null, null, into); return x; } + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == CanonicalizerOp.class) { + return (T) CANONICALIZER; + } + return super.lookup(clazz); + } + + private static class XorCanonicalizerOp implements CanonicalizerOp { + @Override + public Node canonical(Node node) { + assert node instanceof Xor; + Xor xor = (Xor) node; + CiKind kind = xor.kind; + Graph graph = xor.graph(); + Value x = xor.x(); + Value y = xor.y(); + if (x == y) { + if (kind == CiKind.Int) { + return Constant.forInt(0, graph); + } else { + assert kind == CiKind.Long; + return Constant.forLong(0L, graph); + } + } + if (x.isConstant() && !y.isConstant()) { + xor.swapOperands(); + Value t = y; + y = x; + x = t; + } + if (x.isConstant()) { + if (kind == CiKind.Int) { + return Constant.forInt(x.asConstant().asInt() ^ y.asConstant().asInt(), graph); + } else { + assert kind == CiKind.Long; + return Constant.forLong(x.asConstant().asLong() ^ y.asConstant().asLong(), graph); + } + } else if (y.isConstant()) { + if (kind == CiKind.Int) { + int c = y.asConstant().asInt(); + if (c == 0) { + return x; + } + } else { + assert kind == CiKind.Long; + long c = y.asConstant().asLong(); + if (c == 0) { + return x; + } + } + } + return xor; + } + } } diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java Wed Jun 08 08:31:38 2011 +0200 @@ -551,4 +551,9 @@ lir.jump(getLIRBlock(x.loopBegin())); } + @Override + public void visitValueAnchor(ValueAnchor valueAnchor) { + // nothing to do for ValueAnchors + } + } diff -r 9075634c8d11 -r d704eb526603 graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java --- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java Wed Jun 08 08:31:38 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; @@ -81,8 +83,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 9075634c8d11 -r d704eb526603 graal/GraalGraph/src/com/oracle/graal/graph/Graph.java --- a/graal/GraalGraph/src/com/oracle/graal/graph/Graph.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalGraph/src/com/oracle/graal/graph/Graph.java Wed Jun 08 08:31:38 2011 +0200 @@ -36,6 +36,14 @@ private final StartNode start; int nextId; + static int nextGraphId = 0; + int id = nextGraphId++; + + @Override + public String toString() { + return "Graph " + id; + } + public Graph() { nodes = new ArrayList(); start = new StartNode(this); @@ -67,6 +75,10 @@ return new NodeMap(this); } + public NodeWorklist createNodeWorklist() { + return new NodeWorklist(this); + } + public Map addDuplicate(Collection nodes, Map replacements) { Map newNodes = new HashMap(); // create node duplicates diff -r 9075634c8d11 -r d704eb526603 graal/GraalGraph/src/com/oracle/graal/graph/Node.java --- a/graal/GraalGraph/src/com/oracle/graal/graph/Node.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalGraph/src/com/oracle/graal/graph/Node.java Wed Jun 08 08:31:38 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); diff -r 9075634c8d11 -r d704eb526603 graal/GraalGraph/src/com/oracle/graal/graph/NodeArray.java diff -r 9075634c8d11 -r d704eb526603 graal/GraalGraph/src/com/oracle/graal/graph/NodeBitMap.java --- a/graal/GraalGraph/src/com/oracle/graal/graph/NodeBitMap.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalGraph/src/com/oracle/graal/graph/NodeBitMap.java Wed Jun 08 08:31:38 2011 +0200 @@ -35,6 +35,10 @@ bitMap = new CiBitMap(graph.nextId); } + public Graph graph() { + return graph; + } + public boolean setIntersect(NodeBitMap other) { return bitMap.setIntersect(other.bitMap); } @@ -48,6 +52,10 @@ return bitMap.get(node.id()); } + public boolean isNew(Node node) { + return node.id() >= bitMap.size(); + } + public void mark(Node node) { check(node); bitMap.set(node.id()); @@ -60,7 +68,7 @@ private void check(Node node) { assert node.graph == graph : "this node is not part of the graph"; - assert node.id() < bitMap.size() : "this node (" + node.id() + ") was added to the graph after creating the node bitmap (" + bitMap.length() + ")"; + assert !isNew(node) : "this node (" + node.id() + ") was added to the graph after creating the node bitmap (" + bitMap.length() + ")"; } @Override diff -r 9075634c8d11 -r d704eb526603 graal/GraalGraph/src/com/oracle/graal/graph/NodeWorklist.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalGraph/src/com/oracle/graal/graph/NodeWorklist.java Wed Jun 08 08:31:38 2011 +0200 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2011, 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.graal.graph; + +import java.util.ArrayDeque; +import java.util.Iterator; +import java.util.Queue; + + +public class NodeWorklist implements Iterable { + private final NodeBitMap visited; + private final Queue worklist; + + NodeWorklist(Graph graph) { + visited = graph.createNodeBitMap(); + worklist = new ArrayDeque(); + } + + public void add(Node node) { + if (node != null && !visited.isMarked(node)) { + visited.mark(node); + worklist.add(node); + } + } + + public boolean isMarked(Node node) { + return visited.isMarked(node); + } + + private static class QueueConsumingIterator implements Iterator { + private final Queue queue; + + public QueueConsumingIterator(Queue queue) { + this.queue = queue; + } + + @Override + public boolean hasNext() { + return !queue.isEmpty(); + } + + @Override + public Node next() { + return queue.remove(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + @Override + public Iterator iterator() { + return new QueueConsumingIterator(worklist); + } + + private static class UnmarkedNodeIterator implements Iterator { + private final NodeBitMap visited; + private Iterator nodes; + private Node nextNode; + + public UnmarkedNodeIterator(NodeBitMap visited, Iterator nodes) { + this.visited = visited; + this.nodes = nodes; + forward(); + } + + private void forward() { + do { + if (!nodes.hasNext()) { + nextNode = null; + return; + } + nextNode = nodes.next(); + } while (visited.isMarked(nextNode)); + } + + @Override + public boolean hasNext() { + return nextNode != null; + } + + @Override + public Node next() { + try { + return nextNode; + } finally { + forward(); + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + } + + public Iterable unmarkedNodes() { + return new Iterable() { + @Override + public Iterator iterator() { + return new UnmarkedNodeIterator(visited, visited.graph().getNodes().iterator()); + } + }; + } +} diff -r 9075634c8d11 -r d704eb526603 graal/GraalGraph/src/com/oracle/graal/graph/Op.java --- a/graal/GraalGraph/src/com/oracle/graal/graph/Op.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalGraph/src/com/oracle/graal/graph/Op.java Wed Jun 08 08:31:38 2011 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 diff -r 9075634c8d11 -r d704eb526603 graal/GraalRuntime/src/com/oracle/graal/runtime/VMExitsNative.java --- a/graal/GraalRuntime/src/com/oracle/graal/runtime/VMExitsNative.java Tue Jun 07 16:34:38 2011 +0200 +++ b/graal/GraalRuntime/src/com/oracle/graal/runtime/VMExitsNative.java Wed Jun 08 08:31:38 2011 +0200 @@ -112,7 +112,7 @@ } catch (Throwable t) { StringWriter out = new StringWriter(); t.printStackTrace(new PrintWriter(out)); - TTY.println("Compilation interrupted:\n" + out.toString()); + TTY.println("Compilation interrupted: (" + name + ")\n" + out.toString()); throw t; } } diff -r 9075634c8d11 -r d704eb526603 src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java --- a/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java Tue Jun 07 16:34:38 2011 +0200 +++ b/src/share/tools/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java Wed Jun 08 08:31:38 2011 +0200 @@ -542,7 +542,10 @@ for (Node n : nodes) { InputNode inputNode = n.inputNode; - if (inputNode.getProperties().get("name").equals("Root")) { + if(inputNode.getProperties().get("name") == null) { + System.out.println("NO name !! " + inputNode); + } + if (inputNode != null && inputNode.getProperties().get("name") != null && inputNode.getProperties().get("name").equals("Root")) { return n; } else if (inputNode.getId() == 0) { // use as fallback in case no root node is found