# HG changeset patch # User Christian Humer # Date 1390224176 -3600 # Node ID 0fbe961a32dfcff785069ed94aa36592d493733b # Parent 40fd9958cdf56c6d8b103be456a40faa6de1b40f# Parent 0e8c22aa6ec3ae1388661fab573cd56be30213df Merge. diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Mon Jan 20 14:22:56 2014 +0100 @@ -70,13 +70,17 @@ /** * Encodes a deoptimization action and a deoptimization reason in an integer value. * - * @param speculationId a speculation ID returned by SpeculationLog.addSpeculation + * @param debugId an integer that can be used to track the origin of a deoptimization at + * runtime. There is no guarantee that the runtime will use this value. The runtime + * may even keep fewer than 32 bits. * * @return the encoded value as an integer */ - Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int speculationId); + Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId); DeoptimizationReason decodeDeoptReason(Constant constant); DeoptimizationAction decodeDeoptAction(Constant constant); + + int decodeDebugId(Constant constant); } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java --- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Mon Jan 20 14:22:56 2014 +0100 @@ -700,4 +700,7 @@ bra(str); } + public void nullCheck(Register r) { + // setp(....); + } } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -43,15 +43,15 @@ test("staticIntKernel", 'a', 42); } + public static int staticIntKernel(char p0, int p1) { + return p1 + p0; + } + @Test public void testVirtualIntKernel() { test("virtualIntKernel", 'a', 42); } - public static int staticIntKernel(char p0, int p1) { - return p1 + p0; - } - public int virtualIntKernel(char p0, int p1) { return p1 + p0; } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Mon Jan 20 14:22:56 2014 +0100 @@ -827,7 +827,8 @@ @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { - throw GraalInternalError.unimplemented("PTXLIRGenerator.emitNullCheck()"); + assert v.kind() == Kind.Object; + append(new PTXMove.NullCheckOp(load(operand(v)), state(deopting))); } @Override diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -299,8 +299,8 @@ final ValueNode getResult(String snippet) { processMethod(snippet); - assertEquals(1, graph.getNodes().filter(ReturnNode.class).count()); - return graph.getNodes().filter(ReturnNode.class).first().result(); + assertEquals(1, graph.getNodes(ReturnNode.class).count()); + return graph.getNodes(ReturnNode.class).first().result(); } private void processMethod(final String snippet) { diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -98,11 +98,9 @@ for (int i = 1; i <= 4; i++) { StructuredGraph graph = getCanonicalizedGraph("integerTest" + i); - ValueNode result = getResult(graph); - assertTrue(result instanceof ConditionalNode); - ConditionalNode mat = (ConditionalNode) result; - assertTrue(mat.condition() instanceof IntegerTestNode); - IntegerTestNode test = (IntegerTestNode) mat.condition(); + ReturnNode returnNode = (ReturnNode) graph.start().next(); + ConditionalNode conditional = (ConditionalNode) returnNode.result(); + IntegerTestNode test = (IntegerTestNode) conditional.condition(); ParameterNode param0 = graph.getParameter(0); ParameterNode param1 = graph.getParameter(1); assertTrue((test.x() == param0 && test.y() == param1) || (test.x() == param1 && test.y() == param0)); @@ -133,8 +131,9 @@ assertTrue(result.isConstant() && result.asConstant().asLong() == 1); result = getResult(getCanonicalizedGraph("integerTestCanonicalization2")); assertTrue(result.isConstant() && result.asConstant().asLong() == 1); - result = getResult(getCanonicalizedGraph("integerTestCanonicalization3")); - assertTrue(result instanceof ConditionalNode); + StructuredGraph graph = getCanonicalizedGraph("integerTestCanonicalization3"); + assertEquals(1, graph.getNodes(ReturnNode.class).count()); + assertTrue(graph.getNodes(ReturnNode.class).first().result() instanceof ConditionalNode); } public static int integerTestCanonicalization1(boolean b) { diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -154,14 +154,18 @@ @SuppressWarnings("unused") public static int testDisjunctionSnippet(Object a) { - if (a instanceof Integer) { - if (a == null) { - return -1; + try { + if (a instanceof Integer) { + if (a == null) { + return -1; + } else { + return 2; + } } else { - return 2; + return 3; } - } else { - return 3; + } finally { + field = null; } } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -68,6 +68,7 @@ for (Node n : graph.getNodes()) { if (n instanceof ReturnNode) { + assert returnNode == null; returnNode = (ReturnNode) n; } else if (n instanceof MonitorExit) { monitorexit = (MonitorExit) n; diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -172,8 +172,8 @@ protected void assertConstantReturn(StructuredGraph graph, int value) { String graphString = getCanonicalGraphString(graph, false); - Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes().filter(ReturnNode.class).count(), 1); - ValueNode result = graph.getNodes().filter(ReturnNode.class).first().result(); + Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes(ReturnNode.class).count(), 1); + ValueNode result = graph.getNodes(ReturnNode.class).first().result(); Assert.assertTrue("unexpected ReturnNode result node: " + graphString, result.isConstant()); Assert.assertEquals("unexpected ReturnNode result kind: " + graphString, result.asConstant().getKind(), Kind.Int); Assert.assertEquals("unexpected ReturnNode result: " + graphString, result.asConstant().asInt(), value); diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -115,7 +115,7 @@ for (TestMode mode : TestMode.values()) { SchedulePhase schedule = getFinalSchedule("testSplit1Snippet", mode); assertReadWithinStartBlock(schedule, true); - assertReadWithinReturnBlock(schedule, false); + assertReadWithinAllReturnBlocks(schedule, false); } } @@ -131,6 +131,7 @@ } else { container.b = 15; } + container.obj = null; } } @@ -138,7 +139,7 @@ public void testSplit2() { SchedulePhase schedule = getFinalSchedule("testSplit2Snippet", TestMode.WITHOUT_FRAMESTATES); assertReadWithinStartBlock(schedule, false); - assertReadWithinReturnBlock(schedule, true); + assertReadWithinAllReturnBlocks(schedule, true); } /** @@ -163,7 +164,7 @@ SchedulePhase schedule = getFinalSchedule("testLoop1Snippet", TestMode.WITHOUT_FRAMESTATES); assertEquals(6, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, true); - assertReadWithinReturnBlock(schedule, false); + assertReadWithinAllReturnBlocks(schedule, false); } /** @@ -188,7 +189,7 @@ SchedulePhase schedule = getFinalSchedule("testLoop2Snippet", TestMode.WITHOUT_FRAMESTATES); assertEquals(6, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, false); - assertReadWithinReturnBlock(schedule, true); + assertReadWithinAllReturnBlocks(schedule, true); } /** @@ -208,9 +209,9 @@ @Test public void testLoop3() { SchedulePhase schedule = getFinalSchedule("testLoop3Snippet", TestMode.WITHOUT_FRAMESTATES); - assertEquals(7, schedule.getCFG().getBlocks().length); + assertEquals(6, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, true); - assertReadWithinReturnBlock(schedule, false); + assertReadWithinAllReturnBlocks(schedule, false); } public String testStringReplaceSnippet(String input) { @@ -246,7 +247,7 @@ SchedulePhase schedule = getFinalSchedule("testLoop5Snippet", TestMode.WITHOUT_FRAMESTATES); assertEquals(7, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, false); - assertReadWithinReturnBlock(schedule, false); + assertReadWithinAllReturnBlocks(schedule, false); } /** @@ -261,10 +262,11 @@ public void testArrayCopy() { SchedulePhase schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES); StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph(); - ReturnNode ret = graph.getNodes().filter(ReturnNode.class).first(); + assertEquals(1, graph.getNodes(ReturnNode.class).count()); + ReturnNode ret = graph.getNodes(ReturnNode.class).first(); assertTrue(ret.result() instanceof FloatingReadNode); assertEquals(schedule.getCFG().blockFor(ret), schedule.getCFG().blockFor(ret.result())); - assertReadWithinReturnBlock(schedule, true); + assertReadWithinAllReturnBlocks(schedule, true); } /** @@ -281,7 +283,7 @@ @Test public void testIfRead1() { SchedulePhase schedule = getFinalSchedule("testIfRead1Snippet", TestMode.WITHOUT_FRAMESTATES); - assertEquals(4, schedule.getCFG().getBlocks().length); + assertEquals(3, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, true); assertReadAndWriteInSameBlock(schedule, false); } @@ -302,10 +304,10 @@ @Test public void testIfRead2() { SchedulePhase schedule = getFinalSchedule("testIfRead2Snippet", TestMode.WITHOUT_FRAMESTATES); - assertEquals(4, schedule.getCFG().getBlocks().length); + assertEquals(3, schedule.getCFG().getBlocks().length); assertEquals(1, schedule.getCFG().graph.getNodes().filter(FloatingReadNode.class).count()); assertReadWithinStartBlock(schedule, false); - assertReadWithinReturnBlock(schedule, false); + assertReadWithinAllReturnBlocks(schedule, false); assertReadAndWriteInSameBlock(schedule, false); } @@ -326,7 +328,7 @@ SchedulePhase schedule = getFinalSchedule("testIfRead3Snippet", TestMode.WITHOUT_FRAMESTATES); assertEquals(4, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, false); - assertReadWithinReturnBlock(schedule, true); + assertReadWithinAllReturnBlocks(schedule, true); } /** @@ -345,9 +347,9 @@ @Test public void testIfRead4() { SchedulePhase schedule = getFinalSchedule("testIfRead4Snippet", TestMode.WITHOUT_FRAMESTATES); - assertEquals(4, schedule.getCFG().getBlocks().length); + assertEquals(3, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, false); - assertReadWithinReturnBlock(schedule, false); + assertReadWithinAllReturnBlocks(schedule, false); assertReadAndWriteInSameBlock(schedule, true); } @@ -366,7 +368,7 @@ SchedulePhase schedule = getFinalSchedule("testIfRead5Snippet", TestMode.WITHOUT_FRAMESTATES); assertEquals(4, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, false); - assertReadWithinReturnBlock(schedule, true); + assertReadWithinAllReturnBlocks(schedule, true); assertReadAndWriteInSameBlock(schedule, false); } @@ -432,7 +434,7 @@ public void testBlockSchedule2() { SchedulePhase schedule = getFinalSchedule("testBlockSchedule2Snippet", TestMode.WITHOUT_FRAMESTATES, MemoryScheduling.OPTIMAL, SchedulingStrategy.LATEST); assertReadWithinStartBlock(schedule, false); - assertReadWithinReturnBlock(schedule, false); + assertReadWithinAllReturnBlocks(schedule, false); assertReadAndWriteInSameBlock(schedule, false); } @@ -454,7 +456,7 @@ * read of container.b for increment operation should be in return block. TODO: not sure * though, could be replaced by read of container.b of the loop header... */ - assertReadWithinReturnBlock(schedule, true); + assertReadWithinAllReturnBlocks(schedule, true); } public static void testProxy2Snippet() { @@ -476,7 +478,7 @@ public void testProxy2() { SchedulePhase schedule = getFinalSchedule("testProxy2Snippet", TestMode.WITHOUT_FRAMESTATES); assertReadWithinStartBlock(schedule, false); - assertReadWithinReturnBlock(schedule, false); + assertReadWithinAllReturnBlocks(schedule, false); } private int hash = 0; @@ -499,7 +501,7 @@ public void testStringHashCode() { SchedulePhase schedule = getFinalSchedule("testStringHashCodeSnippet", TestMode.WITHOUT_FRAMESTATES); assertReadWithinStartBlock(schedule, true); - assertReadWithinReturnBlock(schedule, false); + assertReadWithinAllReturnBlocks(schedule, false); hash = 0x1337; value[0] = 'a'; @@ -531,30 +533,26 @@ public void testLoop4() { SchedulePhase schedule = getFinalSchedule("testLoop4Snippet", TestMode.WITHOUT_FRAMESTATES); assertReadWithinStartBlock(schedule, false); - assertReadWithinReturnBlock(schedule, false); + assertReadWithinAllReturnBlocks(schedule, false); } - private void assertReadWithinReturnBlock(SchedulePhase schedule, boolean withinReturnBlock) { + private void assertReadWithinAllReturnBlocks(SchedulePhase schedule, boolean withinReturnBlock) { StructuredGraph graph = schedule.getCFG().graph; - assertEquals(graph.getNodes().filter(ReturnNode.class).count(), 1); + assertTrue(graph.getNodes(ReturnNode.class).isNotEmpty()); - Block end = null; - outer: for (Block b : schedule.getCFG().getBlocks()) { - for (Node n : b.getNodes()) { - if (n instanceof ReturnNode) { - end = b; - break outer; + int withRead = 0; + int returnBlocks = 0; + for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) { + Block block = schedule.getCFG().getNodeToBlock().get(returnNode); + for (Node node : schedule.getBlockToNodesMap().get(block)) { + if (node instanceof FloatingReadNode) { + withRead++; + break; } } + returnBlocks++; } - assertNotNull("no block with ReturnNode found", end); - boolean readEncountered = false; - for (Node node : schedule.getBlockToNodesMap().get(end)) { - if (node instanceof FloatingReadNode) { - readEncountered = true; - } - } - assertEquals(readEncountered, withinReturnBlock); + assertEquals(withRead == returnBlocks, withinReturnBlock); } private void assertReadWithinStartBlock(SchedulePhase schedule, boolean withinStartBlock) { diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -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.graal.compiler.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; + +public class MergeCanonicalizerTest extends GraalCompilerTest { + + public static int staticField; + + private int field; + + @Test + public void testSplitReturn() { + test("testSplitReturnSnippet", 2); + testReturnCount("testSplitReturnSnippet", 2); + } + + public int testSplitReturnSnippet(int b) { + int v; + if (b < 0) { + staticField = 1; + v = 10; + } else { + staticField = 2; + v = 20; + } + int i = field; + i = field + i; + return v; + } + + private void testReturnCount(String snippet, int returnCount) { + StructuredGraph graph = parse(snippet); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); + Debug.dump(graph, "Graph"); + assertEquals(returnCount, graph.getNodes(ReturnNode.class).count()); + } +} diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -86,7 +86,7 @@ PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); - new OptimizeGuardAnchors().apply(graph); + new OptimizeGuardAnchorsPhase().apply(graph); new ReadEliminationPhase().apply(graph); new CanonicalizerPhase(true).apply(graph, context); diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -167,7 +167,6 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); new ConditionalEliminationPhase(getMetaAccess()).apply(graph); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); StructuredGraph referenceGraph = parse(referenceSnippet); diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -76,7 +76,6 @@ test("test1Snippet"); } - @Test(expected = AssertionError.class) public void test2() { test("test2Snippet"); } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -98,13 +98,11 @@ test("test4Snippet", "referenceSnippet3"); } - public static final Object constantObject1 = "1"; - public static final Object constantObject2 = "2"; - public static final Object constantObject3 = "3"; - + @SuppressWarnings("unused") public static int test4Snippet(Object o) { if (o == null) { - if (o == constantObject1) { + Object o2 = Integer.class; + if (o == o2) { return 3; } else { return 1; @@ -121,40 +119,41 @@ public static int referenceSnippet5(Object o, Object a) { if (o == null) { - if (a == constantObject1 || a == constantObject2) { + if (a == Integer.class || a == Double.class) { return 1; } } else { - if (a == constantObject2 || a == constantObject3) { + if (a == Double.class || a == Long.class) { return 11; } } - if (a == constantObject1) { + if (a == Integer.class) { return 3; } return 5; } + @SuppressWarnings("unused") public static int test5Snippet(Object o, Object a) { if (o == null) { - if (a == constantObject1 || a == constantObject2) { + if (a == Integer.class || a == Double.class) { if (a == null) { return 10; } return 1; } } else { - if (a == constantObject2 || a == constantObject3) { + if (a == Double.class || a == Long.class) { if (a != null) { return 11; } return 2; } } - if (a == constantObject1) { + if (a == Integer.class) { return 3; } - if (a == constantObject2) { + if (a == Double.class) { return 4; } return 5; @@ -185,7 +184,6 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); new ConditionalEliminationPhase(getMetaAccess()).apply(graph); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); // a second canonicalizer is needed to process nested MaterializeNodes @@ -198,8 +196,8 @@ @Override protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { if (getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { - outputGraph(expected, "expected"); - outputGraph(graph, "actual"); + Debug.dump(expected, "expected (node count)"); + Debug.dump(graph, "graph (node count)"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount()); } } @@ -239,12 +237,11 @@ private void testHelper(String snippet, Class clazz) { StructuredGraph graph = parse(snippet); - Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); new ConditionalEliminationPhase(getMetaAccess()).apply(graph); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); - Debug.dump(graph, "Graph"); + Debug.dump(graph, "Graph " + snippet); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext()); } } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EAMergingTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EAMergingTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EAMergingTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -33,8 +33,9 @@ @Test public void testSimpleMerge() { testEscapeAnalysis("simpleMergeSnippet", null, false); - assertTrue(returnNode.result() instanceof PhiNode); - PhiNode phi = (PhiNode) returnNode.result(); + assertEquals(1, returnNodes.size()); + assertTrue(returnNodes.get(0).result() instanceof PhiNode); + PhiNode phi = (PhiNode) returnNodes.get(0).result(); assertTrue(phi.valueAt(0) instanceof ParameterNode); assertTrue(phi.valueAt(1) instanceof ParameterNode); } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Mon Jan 20 14:22:56 2014 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.compiler.test.ea; +import java.util.*; + import org.junit.*; import com.oracle.graal.api.code.*; @@ -119,7 +121,7 @@ protected StructuredGraph graph; protected HighTierContext context; - protected ReturnNode returnNode; + protected List returnNodes; /** * Runs Escape Analysis on the given snippet and makes sure that no allocations remain in the @@ -134,8 +136,10 @@ protected void testEscapeAnalysis(String snippet, final Constant expectedConstantResult, final boolean iterativeEscapeAnalysis) { prepareGraph(snippet, iterativeEscapeAnalysis); if (expectedConstantResult != null) { - Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant()); - Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); + for (ReturnNode returnNode : returnNodes) { + Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant()); + Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); + } } int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() + graph.getNodes().filter(CommitAllocationNode.class).count(); @@ -153,8 +157,7 @@ new DeadCodeEliminationPhase().apply(graph); new CanonicalizerPhase(true).apply(graph, context); new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(true)).apply(graph, context); - Assert.assertEquals(1, graph.getNodes().filter(ReturnNode.class).count()); - returnNode = graph.getNodes().filter(ReturnNode.class).first(); + returnNodes = graph.getNodes(ReturnNode.class).snapshot(); } catch (Throwable e) { throw Debug.handle(e); } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -213,8 +213,9 @@ prepareGraph("testFullyUnrolledLoopSnippet", false); new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(graph, context); new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context); - Assert.assertTrue(returnNode.result() instanceof AllocatedObjectNode); - CommitAllocationNode commit = ((AllocatedObjectNode) returnNode.result()).getCommit(); + Assert.assertEquals(1, returnNodes.size()); + Assert.assertTrue(returnNodes.get(0).result() instanceof AllocatedObjectNode); + CommitAllocationNode commit = ((AllocatedObjectNode) returnNodes.get(0).result()).getCommit(); Assert.assertEquals(2, commit.getValues().size()); Assert.assertEquals(1, commit.getVirtualObjects().size()); Assert.assertTrue("non-cyclic data structure expected", commit.getVirtualObjects().get(0) != commit.getValues().get(0)); diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -79,8 +79,8 @@ final ReturnNode getReturn(String snippet) { processMethod(snippet); - assertEquals(1, graph.getNodes().filter(ReturnNode.class).count()); - return graph.getNodes().filter(ReturnNode.class).first(); + assertEquals(1, graph.getNodes(ReturnNode.class).count()); + return graph.getNodes(ReturnNode.class).first(); } private void processMethod(final String snippet) { diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -24,6 +24,8 @@ import static org.junit.Assert.*; +import java.util.*; + import org.junit.*; import com.oracle.graal.api.code.*; @@ -194,14 +196,14 @@ @Test public void testPhi() { - ValueNode result = getReturn("testPhiSnippet").result(); + processMethod("testPhiSnippet"); assertTrue(graph.getNodes().filter(LoadFieldNode.class).isEmpty()); - assertTrue(result instanceof PhiNode); - PhiNode phi = (PhiNode) result; - assertTrue(phi.valueAt(0).isConstant()); - assertTrue(phi.valueAt(1).isConstant()); - assertEquals(1, phi.valueAt(0).asConstant().asInt()); - assertEquals(2, phi.valueAt(1).asConstant().asInt()); + List returnNodes = graph.getNodes(ReturnNode.class).snapshot(); + assertEquals(2, returnNodes.size()); + assertTrue(returnNodes.get(0).predecessor() instanceof StoreFieldNode); + assertTrue(returnNodes.get(1).predecessor() instanceof StoreFieldNode); + assertTrue(returnNodes.get(0).result().isConstant()); + assertTrue(returnNodes.get(1).result().isConstant()); } @SuppressWarnings("all") @@ -236,8 +238,8 @@ final ReturnNode getReturn(String snippet) { processMethod(snippet); - assertEquals(1, graph.getNodes().filter(ReturnNode.class).count()); - return graph.getNodes().filter(ReturnNode.class).first(); + assertEquals(1, graph.getNodes(ReturnNode.class).count()); + return graph.getNodes(ReturnNode.class).first(); } protected void processMethod(final String snippet) { diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java Mon Jan 20 14:22:56 2014 +0100 @@ -86,8 +86,9 @@ @Test public void testMergedDouble() { testEscapeAnalysis("testMergedDoubleSnippet", null, false); - Assert.assertTrue(returnNode.result() instanceof PhiNode); - PhiNode phi = (PhiNode) returnNode.result(); + Assert.assertEquals(1, returnNodes.size()); + Assert.assertTrue(returnNodes.get(0).result() instanceof PhiNode); + PhiNode phi = (PhiNode) returnNodes.get(0).result(); Assert.assertTrue(phi.valueAt(0) instanceof LoadFieldNode); Assert.assertTrue(phi.valueAt(1) instanceof LoadFieldNode); } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Mon Jan 20 14:22:56 2014 +0100 @@ -65,7 +65,7 @@ } if (OptEliminatePartiallyRedundantGuards.getValue()) { - appendPhase(new OptimizeGuardAnchors()); + appendPhase(new OptimizeGuardAnchorsPhase()); } if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) { @@ -73,7 +73,7 @@ } if (OptEliminatePartiallyRedundantGuards.getValue()) { - appendPhase(new OptimizeGuardAnchors()); + appendPhase(new OptimizeGuardAnchorsPhase()); } if (OptCanonicalizer.getValue()) { diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Mon Jan 20 14:22:56 2014 +0100 @@ -94,6 +94,8 @@ public PTXHotSpotBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) { super(runtime, providers); + CompilerToGPU compilerToGPU = getRuntime().getCompilerToGPU(); + deviceInitialized = OmitDeviceInit || compilerToGPU.deviceInit(); } @Override @@ -110,7 +112,6 @@ public void completeInitialization() { HotSpotHostForeignCallsProvider hostForeignCalls = (HotSpotHostForeignCallsProvider) getRuntime().getHostProviders().getForeignCalls(); CompilerToGPU compilerToGPU = getRuntime().getCompilerToGPU(); - deviceInitialized = OmitDeviceInit || compilerToGPU.deviceInit(); if (deviceInitialized) { long launchKernel = compilerToGPU.getLaunchKernelAddress(); hostForeignCalls.registerForeignCall(LAUNCH_KERNEL, launchKernel, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotCodeCacheProvider.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotCodeCacheProvider.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotCodeCacheProvider.java Mon Jan 20 14:22:56 2014 +0100 @@ -25,12 +25,18 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; +import java.util.Arrays; public class PTXHotSpotCodeCacheProvider extends HotSpotCodeCacheProvider { public PTXHotSpotCodeCacheProvider(HotSpotGraalRuntime runtime, TargetDescription target) { super(runtime, target); + } + @Override + public String disassemble(CompilationResult compResult, InstalledCode installedCode) { + byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode(); + return new String(code); } @Override diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java Mon Jan 20 14:22:56 2014 +0100 @@ -33,10 +33,12 @@ throw GraalInternalError.unimplemented(); } + @Override public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) { throw GraalInternalError.unimplemented(); } + @Override public boolean canDeoptimize(ForeignCallDescriptor descriptor) { throw GraalInternalError.unimplemented(); } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Jan 20 14:22:56 2014 +0100 @@ -556,8 +556,9 @@ int id = allocateCompileTaskId(method, entryBCI); HotSpotBackend backend = runtime.getHostBackend(); CompilationTask task = new CompilationTask(backend, method, entryBCI, id); + boolean isLambdaMethod = (method.getName().contains("lambda$main$") & method.isSynthetic()); - if (blocking) { + if (blocking || isLambdaMethod) { task.runCompilation(true); } else { try { diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Mon Jan 20 14:22:56 2014 +0100 @@ -130,12 +130,12 @@ } @Override - public Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int speculationId) { + public Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId) { HotSpotVMConfig config = runtime.getConfig(); int actionValue = convertDeoptAction(action); int reasonValue = convertDeoptReason(reason); - int speculationValue = speculationId & intMaskRight(config.deoptimizationDebugIdBits); - Constant c = Constant.forInt(~((speculationValue << config.deoptimizationDebugIdShift) | (reasonValue << config.deoptimizationReasonShift) | (actionValue << config.deoptimizationActionShift))); + int debugValue = debugId & intMaskRight(config.deoptimizationDebugIdBits); + Constant c = Constant.forInt(~((debugValue << config.deoptimizationDebugIdShift) | (reasonValue << config.deoptimizationReasonShift) | (actionValue << config.deoptimizationActionShift))); assert c.asInt() < 0; return c; } @@ -154,9 +154,9 @@ return action; } - public short decodeSpeculationId(Constant constant) { + public int decodeDebugId(Constant constant) { HotSpotVMConfig config = runtime.getConfig(); - return (short) (((~constant.asInt()) >> config.deoptimizationDebugIdShift) & intMaskRight(config.deoptimizationDebugIdBits)); + return ((~constant.asInt()) >> config.deoptimizationDebugIdShift) & intMaskRight(config.deoptimizationDebugIdBits); } public int convertDeoptAction(DeoptimizationAction action) { diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Mon Jan 20 14:22:56 2014 +0100 @@ -118,8 +118,8 @@ @MacroSubstitution(macro = ClassIsInstanceNode.class, isStatic = false) @MethodSubstitution(isStatic = false) - public static boolean isInstance(final Class thisObj, Object obj) { - return !isPrimitive(thisObj) && ConditionalNode.materializeIsInstance(thisObj, obj); + public static boolean isInstance(Class thisObj, Object obj) { + return ConditionalNode.materializeIsInstance(thisObj, obj); } @MacroSubstitution(macro = ClassCastNode.class, isStatic = false) diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Mon Jan 20 14:22:56 2014 +0100 @@ -187,7 +187,7 @@ BeginNode anchorNode = BeginNode.anchor(); Word hub = loadWordFromObject(mirror, klassOffset()); Word objectHub = loadHubIntrinsic(object, getWordKind(), anchorNode); - if (!checkUnknownSubType(hub, objectHub)) { + if (hub.equal(0) || !checkUnknownSubType(hub, objectHub)) { return falseValue; } return trueValue; diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Mon Jan 20 14:22:56 2014 +0100 @@ -521,7 +521,7 @@ StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod()); InliningUtil.inline(invoke, inlineeGraph, false); - List rets = graph.getNodes().filter(ReturnNode.class).snapshot(); + List rets = graph.getNodes(ReturnNode.class).snapshot(); for (ReturnNode ret : rets) { returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass()); String msg = "unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d"; diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Jan 20 14:22:56 2014 +0100 @@ -120,7 +120,6 @@ private ValueNode methodSynchronizedObject; private ExceptionDispatchBlock unwindBlock; - private Block returnBlock; private FixedWithNextNode lastInstr; // the last instruction added @@ -198,7 +197,6 @@ this.stream = new BytecodeStream(method.getCode()); this.constantPool = method.getConstantPool(); unwindBlock = null; - returnBlock = null; methodSynchronizedObject = null; this.currentGraph = graph; this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving()); @@ -270,7 +268,6 @@ for (Block block : blockMap.blocks) { processBlock(block); } - processBlock(returnBlock); processBlock(unwindBlock); Debug.dump(currentGraph, "After bytecode parsing"); @@ -305,16 +302,6 @@ return unwindBlock; } - private Block returnBlock(int bci) { - if (returnBlock == null) { - returnBlock = new Block(); - returnBlock.startBci = bci; - returnBlock.endBci = bci; - returnBlock.blockID = Integer.MAX_VALUE; - } - return returnBlock; - } - public BytecodeStream stream() { return stream; } @@ -1264,11 +1251,18 @@ } private void genReturn(ValueNode x) { + frameState.setRethrowException(false); frameState.clearStack(); - if (x != null) { - frameState.push(x.kind(), x); + if (graphBuilderConfig.eagerInfopointMode()) { + append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci()))); } - appendGoto(createTarget(returnBlock(bci()), frameState)); + + synchronizedEpilogue(FrameState.AFTER_BCI, x); + if (frameState.lockDepth() != 0) { + throw new BailoutException("unbalanced monitors"); + } + + append(new ReturnNode(x)); } private MonitorEnterNode genMonitorEnter(ValueNode x) { @@ -1648,10 +1642,7 @@ ((MergeNode) lastInstr).setStateAfter(frameState.create(bci)); } - if (block == returnBlock) { - frameState.setRethrowException(false); - createReturn(); - } else if (block == unwindBlock) { + if (block == unwindBlock) { frameState.setRethrowException(false); createUnwind(); } else if (block instanceof ExceptionDispatchBlock) { @@ -1692,26 +1683,12 @@ append(new UnwindNode(exception)); } - private void createReturn() { - Kind returnKind = method.getSignature().getReturnKind().getStackKind(); - ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind); - assert frameState.stackSize() == 0; - - if (graphBuilderConfig.eagerInfopointMode()) { - append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci()))); - } - - synchronizedEpilogue(FrameState.AFTER_BCI, x); - if (frameState.lockDepth() != 0) { - throw new BailoutException("unbalanced monitors"); - } - - append(new ReturnNode(x)); - } - private void synchronizedEpilogue(int bci, ValueNode returnValue) { if (Modifier.isSynchronized(method.getModifiers())) { MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, returnValue); + if (returnValue != null) { + frameState.push(returnValue.kind(), returnValue); + } monitorExit.setStateAfter(frameState.create(bci)); assert !frameState.rethrowException(); } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Mon Jan 20 14:22:56 2014 +0100 @@ -32,7 +32,7 @@ import com.oracle.graal.asm.ptx.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.MoveOp; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.asm.*; public class PTXMove { @@ -239,4 +239,29 @@ protected static void compareAndSwap(CompilationResultBuilder crb, PTXAssembler masm, AllocatableValue result, PTXAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { throw new InternalError("NYI"); } + + public static class NullCheckOp extends PTXLIRInstruction implements NullCheck { + + @Use({REG}) protected AllocatableValue input; + @State protected LIRFrameState state; + + public NullCheckOp(Variable input, LIRFrameState state) { + this.input = input; + this.state = state; + } + + @Override + public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) { + crb.recordImplicitException(masm.codeBuffer.position(), state); + masm.nullCheck(asRegister(input)); + } + + public Value getCheckedValue() { + return input; + } + + public LIRFrameState getState() { + return state; + } + } } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Mon Jan 20 14:22:56 2014 +0100 @@ -60,9 +60,12 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (actionAndReason.isConstant()) { + if (actionAndReason.isConstant() && speculation.isConstant()) { Constant constant = actionAndReason.asConstant(); - DeoptimizeNode newDeopt = graph().add(new DeoptimizeNode(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant))); + Constant speculationConstant = speculation.asConstant(); + DeoptimizeNode newDeopt = graph().add( + new DeoptimizeNode(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant), tool.getMetaAccess().decodeDebugId(constant), + speculationConstant)); newDeopt.setDeoptimizationState(getDeoptimizationState()); return newDeopt; } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Mon Jan 20 14:22:56 2014 +0100 @@ -371,6 +371,29 @@ } } } + if (trueSuccessor().next() instanceof ReturnNode && falseSuccessor().next() instanceof ReturnNode) { + ReturnNode trueEnd = (ReturnNode) trueSuccessor().next(); + ReturnNode falseEnd = (ReturnNode) falseSuccessor().next(); + ValueNode trueValue = trueEnd.result(); + ValueNode falseValue = falseEnd.result(); + ConditionalNode conditional = null; + if (trueValue != null) { + if (trueValue.kind() != falseValue.kind()) { + return false; + } + if (trueValue.kind() != Kind.Int && trueValue.kind() != Kind.Long) { + return false; + } + conditional = canonicalizeConditionalCascade(trueValue, falseValue); + if (conditional == null) { + return false; + } + } + ReturnNode newReturn = graph().add(new ReturnNode(conditional)); + replaceAtPredecessor(newReturn); + GraphUtil.killCFG(this); + return true; + } return false; } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Mon Jan 20 14:22:56 2014 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes; +import java.util.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -34,4 +36,6 @@ } public abstract MemoryNode getLastLocationAccess(LocationIdentity locationIdentity); + + public abstract Set getLocations(); } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Mon Jan 20 14:22:56 2014 +0100 @@ -24,6 +24,8 @@ import static com.oracle.graal.graph.iterators.NodePredicates.*; +import java.util.*; + import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; @@ -194,6 +196,35 @@ tool.addToWorkList(newEnd.predecessor()); // ? } graph().reduceTrivialMerge(this); + } else if (next instanceof ReturnNode) { + ReturnNode returnNode = (ReturnNode) next; + if (anchored().isNotEmpty() || returnNode.getMemoryMap() != null) { + return; + } + List phis = phis().snapshot(); + for (PhiNode phi : phis) { + for (Node usage : phi.usages().filter(isNotA(FrameState.class))) { + if (usage != returnNode) { + return; + } + } + } + + PhiNode returnValuePhi = returnNode.result() == null || !isPhiAtMerge(returnNode.result()) ? null : (PhiNode) returnNode.result(); + List endNodes = forwardEnds().snapshot(); + for (AbstractEndNode end : endNodes) { + ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end))); + end.replaceAtPredecessor(newReturn); + } + GraphUtil.killCFG(this); + for (AbstractEndNode end : endNodes) { + end.safeDelete(); + } + for (PhiNode phi : phis) { + if (phi.isAlive() && phi.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(phi); + } + } } } } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java Mon Jan 20 14:22:56 2014 +0100 @@ -28,7 +28,7 @@ /** * The {@code Parameter} instruction is a placeholder for an incoming argument to a function call. */ -@NodeInfo(nameTemplate = "Local({p#index})") +@NodeInfo(nameTemplate = "Param({p#index})") public final class ParameterNode extends AbstractLocalNode implements IterableNodeType { public ParameterNode(int index, Stamp stamp) { diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java Mon Jan 20 14:22:56 2014 +0100 @@ -22,10 +22,11 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public final class ReturnNode extends ControlSinkNode implements LIRLowerable { +public final class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType { @Input private ValueNode result; @Input private MemoryMapNode memoryMap; diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Mon Jan 20 14:22:56 2014 +0100 @@ -62,7 +62,11 @@ if (mirror().isConstant()) { Class clazz = (Class) mirror().asConstant().asObject(); ResolvedJavaType t = tool.getMetaAccess().lookupJavaType(clazz); - return graph().unique(new InstanceOfNode(t, object(), null)); + if (t.isPrimitive()) { + return LogicConstantNode.contradiction(graph()); + } else { + return graph().unique(new InstanceOfNode(t, object(), null)); + } } return this; } diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Mon Jan 20 14:22:56 2014 +0100 @@ -60,6 +60,9 @@ @Override public Node canonical(CanonicalizerTool tool) { + if (usages().isEmpty() && (isStatic() || ObjectStamp.isObjectNonNull(object().stamp()))) { + return null; + } MetaAccessProvider metaAccess = tool.getMetaAccess(); if (tool.canonicalizeReads() && metaAccess != null) { ConstantNode constant = asConstant(metaAccess); diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Mon Jan 20 14:22:56 2014 +0100 @@ -84,6 +84,7 @@ return false; } + @Override public Set getLocations() { return lastMemorySnapshot.keySet(); } @@ -111,6 +112,46 @@ } } + public static MemoryMapImpl mergeMemoryMaps(MergeNode merge, List states) { + MemoryMapImpl newState = new MemoryMapImpl(); + + Set keys = new HashSet<>(); + for (MemoryMapNode other : states) { + keys.addAll(other.getLocations()); + } + assert !keys.contains(FINAL_LOCATION); + + for (LocationIdentity key : keys) { + int mergedStatesCount = 0; + boolean isPhi = false; + MemoryNode merged = null; + for (MemoryMapNode state : states) { + MemoryNode last = state.getLastLocationAccess(key); + if (isPhi) { + merged.asMemoryPhi().addInput(ValueNodeUtil.asNode(last)); + } else { + if (merged == last) { + // nothing to do + } else if (merged == null) { + merged = last; + } else { + MemoryPhiNode phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key)); + for (int j = 0; j < mergedStatesCount; j++) { + phi.addInput(ValueNodeUtil.asNode(merged)); + } + phi.addInput(ValueNodeUtil.asNode(last)); + merged = phi; + isPhi = true; + } + } + mergedStatesCount++; + } + newState.lastMemorySnapshot.put(key, merged); + } + return newState; + + } + private static class CollectMemoryCheckpointsClosure extends NodeIteratorClosure> { private final Map> modifiedInLoops; @@ -238,42 +279,7 @@ @Override protected MemoryMapImpl merge(MergeNode merge, List states) { - MemoryMapImpl newState = new MemoryMapImpl(); - - Set keys = new HashSet<>(); - for (MemoryMapImpl other : states) { - keys.addAll(other.lastMemorySnapshot.keySet()); - } - assert !keys.contains(FINAL_LOCATION); - - for (LocationIdentity key : keys) { - int mergedStatesCount = 0; - boolean isPhi = false; - MemoryNode merged = null; - for (MemoryMapImpl state : states) { - MemoryNode last = state.getLastLocationAccess(key); - if (isPhi) { - merged.asMemoryPhi().addInput(ValueNodeUtil.asNode(last)); - } else { - if (merged == last) { - // nothing to do - } else if (merged == null) { - merged = last; - } else { - MemoryPhiNode phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key)); - for (int j = 0; j < mergedStatesCount; j++) { - phi.addInput(ValueNodeUtil.asNode(merged)); - } - phi.addInput(ValueNodeUtil.asNode(last)); - merged = phi; - isPhi = true; - } - } - mergedStatesCount++; - } - newState.lastMemorySnapshot.put(key, merged); - } - return newState; + return mergeMemoryMaps(merge, states); } @Override diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Jan 20 14:22:56 2014 +0100 @@ -1295,8 +1295,10 @@ */ public static Map inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) { final NodeInputList parameters = invoke.callTarget().arguments(); - StructuredGraph graph = invoke.asNode().graph(); + FixedNode invokeNode = invoke.asNode(); + StructuredGraph graph = invokeNode.graph(); assert inlineGraph.getGuardsStage().ordinal() >= graph.getGuardsStage().ordinal(); + Kind returnKind = invokeNode.kind(); FrameState stateAfter = invoke.stateAfter(); assert stateAfter == null || stateAfter.isAlive(); @@ -1305,7 +1307,7 @@ } ArrayList nodes = new ArrayList<>(inlineGraph.getNodes().count()); - ReturnNode returnNode = null; + ArrayList returnNodes = new ArrayList<>(4); UnwindNode unwindNode = null; final StartNode entryPointNode = inlineGraph.start(); FixedNode firstCFGNode = entryPointNode.next(); @@ -1318,8 +1320,7 @@ } else { nodes.add(node); if (node instanceof ReturnNode) { - assert returnNode == null; - returnNode = (ReturnNode) node; + returnNodes.add((ReturnNode) node); } else if (node instanceof UnwindNode) { assert unwindNode == null; unwindNode = (UnwindNode) node; @@ -1327,7 +1328,7 @@ } } - final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invoke.asNode()); + final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invokeNode); DuplicationReplacement localReplacement = new DuplicationReplacement() { public Node replacement(Node node) { @@ -1340,12 +1341,12 @@ } }; - assert invoke.asNode().successors().first() != null : invoke; - assert invoke.asNode().predecessor() != null; + assert invokeNode.successors().first() != null : invoke; + assert invokeNode.predecessor() != null; Map duplicates = graph.addDuplicates(nodes, inlineGraph, inlineGraph.getNodeCount(), localReplacement); FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); - invoke.asNode().replaceAtPredecessor(firstCFGNodeDuplicate); + invokeNode.replaceAtPredecessor(firstCFGNodeDuplicate); FrameState stateAtExceptionEdge = null; if (invoke instanceof InvokeWithExceptionNode) { @@ -1400,7 +1401,8 @@ if (frameState != null) { assert frameState.bci != FrameState.BEFORE_BCI : frameState; if (frameState.bci == FrameState.AFTER_BCI) { - frameState.replaceAndDelete(stateAfter); + frameState.replaceAndDelete(returnKind == Kind.Void ? stateAfter : stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), returnKind, + frameState.stackAt(0))); } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) { if (frameState.isAlive()) { assert stateAtExceptionEdge != null; @@ -1413,7 +1415,7 @@ if (frameState.outerFrameState() == null) { assert frameState.bci == FrameState.INVALID_FRAMESTATE_BCI || frameState.method() == inlineGraph.method(); if (outerFrameState == null) { - outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.asNode().kind()); + outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invokeNode.kind()); outerFrameState.setDuringCall(true); } frameState.setOuterFrameState(outerFrameState); @@ -1430,27 +1432,55 @@ } else { assert checkContainsOnlyInvalidOrAfterFrameState(duplicates); } - Node returnValue = null; - if (returnNode != null) { - if (returnNode.result() instanceof ParameterNode) { - returnValue = localReplacement.replacement(returnNode.result()); - } else if (returnNode.result() != null) { - returnValue = duplicates.get(returnNode.result()); + if (!returnNodes.isEmpty()) { + FixedNode n = invoke.next(); + invoke.setNext(null); + if (returnNodes.size() == 1) { + ReturnNode returnNode = (ReturnNode) duplicates.get(returnNodes.get(0)); + Node returnValue = returnNode.result(); + invokeNode.replaceAtUsages(returnValue); + returnNode.clearInputs(); + returnNode.replaceAndDelete(n); + } else { + ArrayList returnDuplicates = new ArrayList<>(returnNodes.size()); + for (ReturnNode returnNode : returnNodes) { + returnDuplicates.add((ReturnNode) duplicates.get(returnNode)); + } + MergeNode merge = graph.add(new MergeNode()); + merge.setStateAfter(stateAfter); + ValueNode returnValue = mergeReturns(merge, returnDuplicates); + invokeNode.replaceAtUsages(returnValue); + merge.setNext(n); } - invoke.asNode().replaceAtUsages(returnValue); - Node returnDuplicate = duplicates.get(returnNode); - returnDuplicate.clearInputs(); - Node n = invoke.next(); - invoke.setNext(null); - returnDuplicate.replaceAndDelete(n); } - invoke.asNode().replaceAtUsages(null); - GraphUtil.killCFG(invoke.asNode()); + invokeNode.replaceAtUsages(null); + GraphUtil.killCFG(invokeNode); return duplicates; } + public static ValueNode mergeReturns(MergeNode merge, List returnNodes) { + PhiNode returnValuePhi = null; + + for (ReturnNode returnNode : returnNodes) { + // create and wire up a new EndNode + EndNode endNode = merge.graph().add(new EndNode()); + merge.addForwardEnd(endNode); + + if (returnNode.result() != null) { + if (returnValuePhi == null) { + returnValuePhi = merge.graph().addWithoutUnique(new PhiNode(returnNode.result().kind(), merge)); + } + returnValuePhi.addInput(returnNode.result()); + } + returnNode.clearInputs(); + returnNode.replaceAndDelete(endNode); + + } + return returnValuePhi; + } + private static boolean checkContainsOnlyInvalidOrAfterFrameState(Map duplicates) { for (Node node : duplicates.values()) { if (node instanceof FrameState) { diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java Fri Jan 17 17:10:46 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common; - -import java.util.*; - -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.NodeClass.NodeClassIterator; -import com.oracle.graal.graph.iterators.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.cfg.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.phases.*; - -public class OptimizeGuardAnchors extends Phase { - private static final DebugMetric metricGuardsAnchorOptimized = Debug.metric("GuardsAnchorOptimized"); - private static final DebugMetric metricGuardsOptimizedAtSplit = Debug.metric("GuardsOptimizedAtSplit"); - - private static class LazyCFG { - private ControlFlowGraph cfg; - private StructuredGraph graph; - - public LazyCFG(StructuredGraph graph) { - this.graph = graph; - } - - public ControlFlowGraph get() { - if (cfg == null) { - cfg = ControlFlowGraph.compute(graph, true, false, true, true); - } - return cfg; - } - } - - @Override - protected void run(StructuredGraph graph) { - LazyCFG cfg = new LazyCFG(graph); - for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) { - if (!(begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode)) { - NodeIterable guards = begin.guards(); - if (guards.isNotEmpty()) { - AbstractBeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin); - // newAnchor == begin is possible because postdominator computation assumes that - // loops never end - if (newAnchor != begin) { - for (GuardNode guard : guards.snapshot()) { - guard.setGuard(newAnchor); - } - metricGuardsAnchorOptimized.increment(); - } - } - } - } - for (ControlSplitNode controlSplit : graph.getNodes(ControlSplitNode.class)) { - optimizeAtControlSplit(controlSplit, cfg); - } - } - - private static AbstractBeginNode computeOptimalAnchor(ControlFlowGraph cfg, AbstractBeginNode begin) { - Block anchor = cfg.blockFor(begin); - while (anchor.getDominator() != null && anchor.getDominator().getPostdominator() == anchor) { - anchor = anchor.getDominator(); - } - return anchor.getBeginNode(); - } - - private static void optimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) { - AbstractBeginNode successor = findMinimumUsagesSuccessor(controlSplit); - int successorCount = controlSplit.successors().count(); - List otherGuards = new ArrayList<>(successorCount - 1); - for (GuardNode guard : successor.guards().snapshot()) { - if (guard.isDeleted() || guard.condition().usages().count() < successorCount) { - continue; - } - for (GuardNode conditonGuard : guard.condition().usages().filter(GuardNode.class)) { - if (conditonGuard != guard) { - GuardingNode conditonGuardAnchor = conditonGuard.getGuard(); - if (conditonGuardAnchor.asNode().predecessor() == controlSplit && compatibleGuards(guard, conditonGuard)) { - otherGuards.add(conditonGuard); - } - } - } - - if (otherGuards.size() == successorCount - 1) { - AbstractBeginNode anchor = computeOptimalAnchor(cfg.get(), AbstractBeginNode.prevBegin(controlSplit)); - GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated(), guard.getSpeculation())); - for (GuardNode otherGuard : otherGuards) { - otherGuard.replaceAndDelete(newGuard); - } - guard.replaceAndDelete(newGuard); - metricGuardsOptimizedAtSplit.increment(); - } - otherGuards.clear(); - } - } - - private static boolean compatibleGuards(GuardNode guard, GuardNode conditonGuard) { - return conditonGuard.negated() == guard.negated() && conditonGuard.action() == guard.action() && conditonGuard.reason() == guard.reason() && - conditonGuard.getSpeculation().equals(guard.getSpeculation()); - } - - private static AbstractBeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) { - NodeClassIterator successors = controlSplit.successors().iterator(); - AbstractBeginNode min = (AbstractBeginNode) successors.next(); - int minUsages = min.usages().count(); - while (successors.hasNext()) { - AbstractBeginNode successor = (AbstractBeginNode) successors.next(); - int count = successor.usages().count(); - if (count < minUsages) { - minUsages = count; - min = successor; - } - } - return min; - } -} diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java Mon Jan 20 14:22:56 2014 +0100 @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common; + +import java.util.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.NodeClass.NodeClassIterator; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.phases.*; + +public class OptimizeGuardAnchorsPhase extends Phase { + private static final DebugMetric metricGuardsAnchorOptimized = Debug.metric("GuardsAnchorOptimized"); + private static final DebugMetric metricGuardsOptimizedAtSplit = Debug.metric("GuardsOptimizedAtSplit"); + + public static class LazyCFG { + private ControlFlowGraph cfg; + private StructuredGraph graph; + + public LazyCFG(StructuredGraph graph) { + this.graph = graph; + } + + public ControlFlowGraph get() { + if (cfg == null) { + cfg = ControlFlowGraph.compute(graph, true, false, true, true); + } + return cfg; + } + } + + @Override + protected void run(StructuredGraph graph) { + LazyCFG cfg = new LazyCFG(graph); + for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) { + if (!(begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode)) { + NodeIterable guards = begin.guards(); + if (guards.isNotEmpty()) { + AbstractBeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin); + // newAnchor == begin is possible because postdominator computation assumes that + // loops never end + if (newAnchor != begin) { + for (GuardNode guard : guards.snapshot()) { + guard.setGuard(newAnchor); + } + metricGuardsAnchorOptimized.increment(); + } + } + } + } + for (ControlSplitNode controlSplit : graph.getNodes(ControlSplitNode.class)) { + optimizeAtControlSplit(controlSplit, cfg); + } + } + + public static AbstractBeginNode getOptimalAnchor(LazyCFG cfg, AbstractBeginNode begin) { + if (begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode) { + return begin; + } + return computeOptimalAnchor(cfg.get(), begin); + } + + private static AbstractBeginNode computeOptimalAnchor(ControlFlowGraph cfg, AbstractBeginNode begin) { + Block anchor = cfg.blockFor(begin); + while (anchor.getDominator() != null && anchor.getDominator().getPostdominator() == anchor) { + anchor = anchor.getDominator(); + } + return anchor.getBeginNode(); + } + + private static void optimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) { + AbstractBeginNode successor = findMinimumUsagesSuccessor(controlSplit); + int successorCount = controlSplit.successors().count(); + List otherGuards = new ArrayList<>(successorCount - 1); + for (GuardNode guard : successor.guards().snapshot()) { + if (guard.isDeleted() || guard.condition().usages().count() < successorCount) { + continue; + } + for (GuardNode conditonGuard : guard.condition().usages().filter(GuardNode.class)) { + if (conditonGuard != guard) { + GuardingNode conditonGuardAnchor = conditonGuard.getGuard(); + if (conditonGuardAnchor.asNode().predecessor() == controlSplit && compatibleGuards(guard, conditonGuard)) { + otherGuards.add(conditonGuard); + } + } + } + + if (otherGuards.size() == successorCount - 1) { + AbstractBeginNode anchor = computeOptimalAnchor(cfg.get(), AbstractBeginNode.prevBegin(controlSplit)); + GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated(), guard.getSpeculation())); + for (GuardNode otherGuard : otherGuards) { + otherGuard.replaceAndDelete(newGuard); + } + guard.replaceAndDelete(newGuard); + metricGuardsOptimizedAtSplit.increment(); + } + otherGuards.clear(); + } + } + + private static boolean compatibleGuards(GuardNode guard, GuardNode conditonGuard) { + return conditonGuard.negated() == guard.negated() && conditonGuard.action() == guard.action() && conditonGuard.reason() == guard.reason() && + conditonGuard.getSpeculation().equals(guard.getSpeculation()); + } + + private static AbstractBeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) { + NodeClassIterator successors = controlSplit.successors().iterator(); + AbstractBeginNode min = (AbstractBeginNode) successors.next(); + int minUsages = min.usages().count(); + while (successors.hasNext()) { + AbstractBeginNode successor = (AbstractBeginNode) successors.next(); + int count = successor.usages().count(); + if (count < minUsages) { + minUsages = count; + min = successor; + } + } + return min; + } +} diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java Mon Jan 20 14:22:56 2014 +0100 @@ -50,7 +50,7 @@ if (deopt.reason() != DeoptimizationReason.NullCheckException) { return; } - if (deopt.getSpeculation() != null && deopt.getSpeculation() != Constant.NULL_OBJECT) { + if (deopt.getSpeculation() != null && !deopt.getSpeculation().equals(Constant.NULL_OBJECT)) { return; } Node predecessor = deopt.predecessor(); diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java Mon Jan 20 14:22:56 2014 +0100 @@ -153,7 +153,7 @@ } private static boolean doesNotAlwaysDeopt(StructuredGraph graph) { - return graph.getNodes().filter(ReturnNode.class).iterator().hasNext(); + return graph.getNodes(ReturnNode.class).isNotEmpty(); } private void computeLoopFactors() { diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Mon Jan 20 14:22:56 2014 +0100 @@ -36,9 +36,8 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.Graph.Mark; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.iterators.*; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; @@ -623,43 +622,49 @@ assert checkAllVarargPlaceholdersAreDeleted(parameterCount, placeholders); new FloatingReadPhase(FloatingReadPhase.ExecutionMode.ANALYSIS_ONLY).apply(snippetCopy); - this.memoryMap = null; this.snippet = snippetCopy; - ReturnNode retNode = null; + List returnNodes = new ArrayList<>(4); + List memMaps = new ArrayList<>(4); StartNode entryPointNode = snippet.start(); - nodes = new ArrayList<>(snippet.getNodeCount()); - boolean seenReturn = false; - boolean containsMemoryMap = false; - for (Node node : snippet.getNodes()) { - if (node == entryPointNode || node == entryPointNode.stateAfter()) { - // Do nothing. - } else { - nodes.add(node); - if (node instanceof ReturnNode) { - retNode = (ReturnNode) node; - NodeIterable memstates = retNode.inputs().filter(MemoryMapNode.class); - assert memstates.count() == 1; - memoryMap = memstates.first(); - retNode.replaceFirstInput(memoryMap, null); - memoryMap.safeDelete(); - - assert !seenReturn : "can handle only one ReturnNode"; - seenReturn = true; - } else if (node instanceof MemoryMapNode) { - containsMemoryMap = true; - } + for (ReturnNode retNode : snippet.getNodes(ReturnNode.class)) { + MemoryMapNode memMap = retNode.getMemoryMap(); + memMaps.add(memMap); + retNode.setMemoryMap(null); + returnNodes.add(retNode); + if (memMap.usages().isEmpty()) { + memMap.safeDelete(); } } - assert !containsMemoryMap; + assert snippet.getNodes().filter(MemoryMapNode.class).isEmpty(); + if (returnNodes.isEmpty()) { + this.returnNode = null; + this.memoryMap = null; + } else if (returnNodes.size() == 1) { + this.returnNode = returnNodes.get(0); + this.memoryMap = memMaps.get(0); + } else { + MergeNode merge = snippet.add(new MergeNode()); + ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes); + this.returnNode = snippet.add(new ReturnNode(returnValue)); + this.memoryMap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps); + merge.setNext(this.returnNode); + } this.sideEffectNodes = curSideEffectNodes; this.deoptNodes = curDeoptNodes; this.stampNodes = curStampNodes; - this.returnNode = retNode; + + nodes = new ArrayList<>(snippet.getNodeCount()); + for (Node node : snippet.getNodes()) { + if (node != entryPointNode && node != entryPointNode.stateAfter()) { + nodes.add(node); + } + } Debug.metric(debugValueName("SnippetTemplateNodeCount", args)).add(nodes.size()); args.info.notifyNewTemplate(); + Debug.dump(snippet, "SnippetTemplate final state"); } private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, VarargsPlaceholderNode[] placeholders) { @@ -720,7 +725,7 @@ /** * Nodes that inherit the {@link DeoptimizingNode#getDeoptimizationState()} from the replacee - * during insantiation. + * during instantiation. */ private final ArrayList deoptNodes; @@ -737,7 +742,7 @@ /** * map of killing locations to memory checkpoints (nodes). */ - private MemoryMapNode memoryMap; + private final MemoryMapNode memoryMap; /** * Times instantiations of this template. @@ -876,7 +881,7 @@ // MemoryCheckPoint inside the snippet graph MemoryNode lastAccess = mmap.getLastLocationAccess(identity); - assert lastAccess != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kill the same location as the lowerable node?)"; + assert lastAccess != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kills the same location as the lowerable node?)"; if (usage instanceof MemoryAccess) { MemoryAccess access = (MemoryAccess) usage; if (access.getLastLocationAccess() == oldNode) { @@ -961,6 +966,11 @@ return (MemoryNode) duplicates.get(ValueNodeUtil.asNode(lastLocationAccess)); } } + + @Override + public Set getLocations() { + return memoryMap.getLocations(); + } } /** @@ -1014,25 +1024,18 @@ } } - for (ValueNode stampNode : stampNodes) { - Node stampDup = duplicates.get(stampNode); - ((ValueNode) stampDup).setStamp(((ValueNode) replacee).stamp()); - } + updateStamps(replacee, duplicates); // Replace all usages of the replacee with the value returned by the snippet ValueNode returnValue = null; if (returnNode != null && !(replacee instanceof ControlSinkNode)) { - if (returnNode.result() instanceof ParameterNode) { - returnValue = (ValueNode) replacements.get(returnNode.result()); - } else if (returnNode.result() != null) { - returnValue = (ValueNode) duplicates.get(returnNode.result()); - } - Node returnDuplicate = duplicates.get(returnNode); + ReturnNode returnDuplicate = (ReturnNode) duplicates.get(returnNode); + returnValue = returnDuplicate.result(); MemoryMapNode mmap = new DuplicateMapper(duplicates, replaceeGraph.start()); if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) { replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor(), mmap); } else { - assert returnValue != null || replacee.usages().isEmpty() : this + " " + returnValue + " " + returnNode + " " + replacee.usages(); + assert returnValue != null || replacee.usages().isEmpty(); replacer.replace(replacee, returnValue, mmap); } if (returnDuplicate.isAlive()) { @@ -1051,6 +1054,30 @@ } } + private void propagateStamp(Node node) { + if (node instanceof PhiNode) { + PhiNode phi = (PhiNode) node; + if (phi.inferPhiStamp()) { + for (Node usage : node.usages()) { + propagateStamp(usage); + } + } + } + } + + private void updateStamps(ValueNode replacee, Map duplicates) { + for (ValueNode stampNode : stampNodes) { + Node stampDup = duplicates.get(stampNode); + ((ValueNode) stampDup).setStamp(replacee.stamp()); + } + for (ParameterNode paramNode : snippet.getNodes(ParameterNode.class)) { + for (Node usage : paramNode.usages()) { + Node usageDup = duplicates.get(usage); + propagateStamp(usageDup); + } + } + } + /** * Gets a copy of the specialized graph. */ @@ -1097,23 +1124,14 @@ ((StateSplit) sideEffectDup).setStateAfter(((StateSplit) replacee).stateAfter()); } } - for (ValueNode stampNode : stampNodes) { - Node stampDup = duplicates.get(stampNode); - ((ValueNode) stampDup).setStamp(((ValueNode) replacee).stamp()); - } + updateStamps(replacee, duplicates); // Replace all usages of the replacee with the value returned by the snippet - assert returnNode != null : replaceeGraph; - ValueNode returnValue = null; - if (returnNode.result() instanceof ParameterNode) { - returnValue = (ValueNode) replacements.get(returnNode.result()); - } else { - returnValue = (ValueNode) duplicates.get(returnNode.result()); - } + ReturnNode returnDuplicate = (ReturnNode) duplicates.get(returnNode); + ValueNode returnValue = returnDuplicate.result(); assert returnValue != null || replacee.usages().isEmpty(); replacer.replace(replacee, returnValue, new DuplicateMapper(duplicates, replaceeGraph.start())); - Node returnDuplicate = duplicates.get(returnNode); if (returnDuplicate.isAlive()) { returnDuplicate.clearInputs(); returnDuplicate.replaceAndDelete(next); diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Jan 20 14:22:56 2014 +0100 @@ -70,7 +70,7 @@ protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, Arguments arguments) { Assumptions assumptions = new Assumptions(true); StructuredGraph actual = partialEval(root, arguments, assumptions, true); - InstalledCode result = new TruffleCompilerImpl().compileMethodHelper(actual, GraphBuilderConfiguration.getDefault(), assumptions); + InstalledCode result = new TruffleCompilerImpl().compileMethodHelper(actual, GraphBuilderConfiguration.getDefault(), assumptions, root.toString()); StructuredGraph expected = parseForComparison(methodName); removeFrameStates(actual); Assert.assertEquals(getCanonicalGraphString(expected, true), getCanonicalGraphString(actual, true)); diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Mon Jan 20 14:22:56 2014 +0100 @@ -156,7 +156,7 @@ } long timePartialEvaluationFinished = System.nanoTime(); int nodeCountPartialEval = graph.getNodeCount(); - InstalledCode compiledMethod = compileMethodHelper(graph, config, assumptions); + InstalledCode compiledMethod = compileMethodHelper(graph, config, assumptions, compilable.toString()); long timeCompilationFinished = System.nanoTime(); int nodeCountLowered = graph.getNodeCount(); @@ -208,7 +208,7 @@ } } - public InstalledCode compileMethodHelper(StructuredGraph graph, GraphBuilderConfiguration config, Assumptions assumptions) { + public InstalledCode compileMethodHelper(StructuredGraph graph, GraphBuilderConfiguration config, Assumptions assumptions, String name) { try (Scope s = Debug.scope("TruffleFinal")) { Debug.dump(graph, "After TruffleTier"); } catch (Throwable e) { @@ -219,7 +219,7 @@ try (TimerCloseable a = CompilationTime.start(); Scope s = Debug.scope("TruffleGraal.GraalCompiler", graph, providers.getCodeCache())) { CodeCacheProvider codeCache = providers.getCodeCache(); CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false); - CompilationResult compilationResult = new CompilationResult(graph.method().toString()); + CompilationResult compilationResult = new CompilationResult(name); result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, createGraphBuilderSuite(config), OptimisticOptimizations.ALL, getProfilingInfo(graph), new SpeculationLog(), suites, false, compilationResult, CompilationResultBuilderFactory.Default); } catch (Throwable e) { diff -r 40fd9958cdf5 -r 0fbe961a32df graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Fri Jan 17 17:10:46 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Mon Jan 20 14:22:56 2014 +0100 @@ -32,31 +32,53 @@ */ public class TruffleOptions { - /** Enables/disables the rewriting of traces in the truffle runtime to stdout. */ - public static boolean TraceRewrites = false; + /** + * Enables/disables the rewriting of traces in the truffle runtime to stdout. + *

+ * Can be set with {@code -Dtruffle.TraceRewrites=true}. + */ + public static boolean TraceRewrites = Boolean.getBoolean("truffle.TraceRewrites"); /** * Enables the generation of detailed rewrite reasons. Enabling this may introduce some overhead * for rewriting nodes. + *

+ * Can be set with {@code -Dtruffle.DetailedRewriteReasons=true}. */ - public static final boolean DetailedRewriteReasons = false; + public static final boolean DetailedRewriteReasons = Boolean.getBoolean("truffle.DetailedRewriteReasons"); /** * Filters rewrites that do not contain the given string in the qualified name of the source or * target class hierarchy. + *

+ * Can be set with {@code -Dtruffle.TraceRewritesFilterClass=name}. */ - public static String TraceRewritesFilterClass = null; + public static String TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass"); /** * Filters rewrites which does not contain the {@link Kind} in its source {@link NodeInfo}. If * no {@link NodeInfo} is defined the element is filtered if the filter value is set. + *

+ * Can be set with + * {@code -Dtruffle.TraceRewritesFilterFromKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}. */ - public static NodeInfo.Kind TraceRewritesFilterFromKind = null; + public static NodeInfo.Kind TraceRewritesFilterFromKind = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromKind")); /** * Filters rewrites which does not contain the {@link Kind} in its target {@link NodeInfo}. If * no {@link NodeInfo} is defined the element is filtered if the filter value is set. + *

+ * Can be set with + * {@code -Dtruffle.TraceRewritesFilterToKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}. */ - public static NodeInfo.Kind TraceRewritesFilterToKind = null; + public static NodeInfo.Kind TraceRewritesFilterToKind = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToKind")); + + private static NodeInfo.Kind parseNodeInfoKind(String kind) { + if (kind == null) { + return null; + } + + return NodeInfo.Kind.valueOf(kind); + } } diff -r 40fd9958cdf5 -r 0fbe961a32df mxtool/mx.py --- a/mxtool/mx.py Fri Jan 17 17:10:46 2014 +0100 +++ b/mxtool/mx.py Mon Jan 20 14:22:56 2014 +0100 @@ -2866,23 +2866,24 @@ generate_eclipse_workingsets() -def _check_ide_timestamp(suite, timestamp): - """return True if and only if the projects file, imports file, eclipse-settings files, and mx itself are all older than timestamp""" +def _check_ide_timestamp(suite, configZip, ide): + """return True if and only if the projects file, imports file, eclipse-settings files, and mx itself are all older than configZip""" projectsFile = join(suite.mxDir, 'projects') - if timestamp.isOlderThan(projectsFile): + if configZip.isOlderThan(projectsFile): return False - if timestamp.isOlderThan(suite.import_timestamp()): + if configZip.isOlderThan(suite.import_timestamp()): return False # Assume that any mx change might imply changes to the generated IDE files - if timestamp.isOlderThan(__file__): + if configZip.isOlderThan(__file__): return False - eclipseSettingsDir = join(suite.mxDir, 'eclipse-settings') - if exists(eclipseSettingsDir): - for name in os.listdir(eclipseSettingsDir): - path = join(eclipseSettingsDir, name) - if timestamp.isOlderThan(path): - return False + if ide == 'eclipse': + eclipseSettingsDir = join(suite.mxDir, 'eclipse-settings') + if exists(eclipseSettingsDir): + for name in os.listdir(eclipseSettingsDir): + path = join(eclipseSettingsDir, name) + if configZip.isOlderThan(path): + return False return True def _eclipseinit_suite(args, suite, buildProcessorJars=True, refreshOnly=False): @@ -2891,7 +2892,7 @@ if refreshOnly and not configZip.exists(): return - if _check_ide_timestamp(suite, configZip): + if _check_ide_timestamp(suite, configZip, 'eclipse'): logv('[Eclipse configurations are up to date - skipping]') return @@ -3351,7 +3352,7 @@ if refreshOnly and not configZip.exists(): return - if _check_ide_timestamp(suite, configZip): + if _check_ide_timestamp(suite, configZip, 'netbeans'): logv('[NetBeans configurations are up to date - skipping]') return @@ -3561,11 +3562,10 @@ javacClasspath.append('${' + ref + '}') else: annotationProcessorReferences.append('${' + ref + '}') - annotationProcessorReferences += ":\\\n ${" + ref + "}" print >> out, 'javac.classpath=\\\n ' + (os.pathsep + '\\\n ').join(javacClasspath) - print >> out, 'javac.test.processorpath=${javac.test.classpath}\\\n ' + (os.pathsep + '\\\n ').join(annotationProcessorReferences) - print >> out, 'javac.processorpath=${javac.classpath}\\\n ' + (os.pathsep + '\\\n ').join(annotationProcessorReferences) + print >> out, 'javac.processorpath=' + (os.pathsep + '\\\n ').join(['${javac.classpath}'] + annotationProcessorReferences) + print >> out, 'javac.test.processorpath=' + (os.pathsep + '\\\n ').join(['${javac.test.classpath}'] + annotationProcessorReferences) updated = update_file(join(p.dir, 'nbproject', 'project.properties'), out.getvalue()) or updated out.close() diff -r 40fd9958cdf5 -r 0fbe961a32df src/gpu/ptx/vm/gpu_ptx.cpp --- a/src/gpu/ptx/vm/gpu_ptx.cpp Fri Jan 17 17:10:46 2014 +0100 +++ b/src/gpu/ptx/vm/gpu_ptx.cpp Mon Jan 20 14:22:56 2014 +0100 @@ -331,7 +331,7 @@ } if (TraceGPUInteraction) { - tty->print_cr("[CUDA] Got function handle for %s", name); + tty->print_cr("[CUDA] Got function handle for %s kernel address %p", name, cu_function); } return cu_function; @@ -375,7 +375,9 @@ return 0L; } // Push device_return_value to kernelParams - gpu::Ptx::CUdeviceptr* returnValuePtr = (gpu::Ptx::CUdeviceptr*) (address) parametersAndReturnValueBuffer + parametersAndReturnValueBufferSize - sizeof(device_return_value); + gpu::Ptx::CUdeviceptr* returnValuePtr = (gpu::Ptx::CUdeviceptr*) + ((address) parametersAndReturnValueBuffer + + parametersAndReturnValueBufferSize - sizeof(device_return_value)); *returnValuePtr = device_return_value; } @@ -417,7 +419,7 @@ } thread->set_vm_result(return_val); } else if (returnTypeSize > 0) { - status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&primitiveReturnValue, device_return_value, T_LONG_BYTE_SIZE); + status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&primitiveReturnValue, device_return_value, returnTypeSize); if (status != GRAAL_CUDA_SUCCESS) { tty->print_cr("[CUDA] *** Error (%d) Failed to copy value from device argument", status); SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_Exception(), "[CUDA] Failed to copy value from device argument"); diff -r 40fd9958cdf5 -r 0fbe961a32df src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Fri Jan 17 17:10:46 2014 +0100 +++ b/src/share/vm/oops/method.cpp Mon Jan 20 14:22:56 2014 +0100 @@ -2025,3 +2025,28 @@ guarantee(md == NULL || md->is_methodData(), "should be method data"); } + +#ifdef GRAAL + +// Return true if the name of the method indicates that this is a +// lambda method other than . Lambda method is one with a name +// that starts with lambda$ and is synthetic. + +bool Method::is_lambda() const { + Symbol * klass_name = method_holder()->name(); + Symbol * method_name = name(); + ResourceMark rm; + if (klass_name != NULL) { + if (klass_name != NULL && method_name != NULL) { + const char* lambdaPrefix = "lambda$main$"; + char* methodPrefix = strstr(method_name->as_C_string(), lambdaPrefix); + if (methodPrefix != 0) { + if ((strncmp(lambdaPrefix, methodPrefix, strlen(lambdaPrefix)) == 0) && is_synthetic()) { + return true; + } + } + } + } + return false; +} +#endif diff -r 40fd9958cdf5 -r 0fbe961a32df src/share/vm/oops/method.hpp --- a/src/share/vm/oops/method.hpp Fri Jan 17 17:10:46 2014 +0100 +++ b/src/share/vm/oops/method.hpp Mon Jan 20 14:22:56 2014 +0100 @@ -617,6 +617,11 @@ // simultaneously. Use with caution. bool has_compiled_code() const { return code() != NULL; } +#ifdef GRAAL + // Return true if the name of the method indicates that this is a + // lambda method other than . + bool is_lambda() const; +#endif // sizing static int header_size() { return sizeof(Method)/HeapWordSize; } static int size(bool is_native); diff -r 40fd9958cdf5 -r 0fbe961a32df src/share/vm/runtime/compilationPolicy.cpp --- a/src/share/vm/runtime/compilationPolicy.cpp Fri Jan 17 17:10:46 2014 +0100 +++ b/src/share/vm/runtime/compilationPolicy.cpp Mon Jan 20 14:22:56 2014 +0100 @@ -45,6 +45,9 @@ #include "runtime/vm_operations.hpp" #include "utilities/events.hpp" #include "utilities/globalDefinitions.hpp" +#ifdef GRAAL +#include "runtime/gpu.hpp" +#endif CompilationPolicy* CompilationPolicy::_policy; elapsedTimer CompilationPolicy::_accumulated_time; @@ -101,6 +104,32 @@ if (ReplayCompiles) return false; if (m->has_compiled_code()) return false; // already compiled + +#ifdef GRAAL + // Check if this is a Lambda method that can be compiled to a GPU. + if (m->is_lambda()) { + // If GPU is available and the necessary linkage is available + // rerurn true indicatin that this method must be compiled. + if (gpu::is_available() && gpu::has_gpu_linkage()) { + if (TraceGPUInteraction) { + tty->print("Compiling Lambda method"); + m->print_short_name(); + switch (gpu::get_target_il_type()) { + case gpu::PTX : + tty->print_cr(" to PTX"); + break; + case gpu::HSAIL : + tty->print_cr(" to HSAIL"); + break; + default : + tty->print_cr(" to Unknown GPU!!!"); + } + } + return true; + } + } +#endif + if (!can_be_compiled(m, comp_level)) return false; return !UseInterpreter || // must compile all methods