# HG changeset patch
# User Thomas Wuerthinger
# Date 1371829939 -7200
# Node ID 55827d611da7eabad22d2c732c6b9589901e9159
# Parent 0d40e1cf70dbdc1b3bee70c87d31a04747350934# Parent e4dd840a39de94a613a353b382e5e3a15c6e58d9
Merge.
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierAdditionTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierAdditionTest.java Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 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.compiler.test;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.hotspot.phases.*;
-import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.tiers.*;
-
-public class WriteBarrierAdditionTest extends GraalCompilerTest {
-
- public static class Container {
-
- public Container a;
- public Container b;
- }
-
- public static void test1Snippet() {
- Container main = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- main.a = temp1;
- main.b = temp2;
- }
-
- public static void test2Snippet(boolean test) {
- Container main = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- for (int i = 0; i < 10; i++) {
- if (test) {
- main.a = temp1;
- main.b = temp2;
- } else {
- main.a = temp2;
- main.b = temp1;
- }
- }
- }
-
- public static void test3Snippet() {
- Container[] main = new Container[10];
- Container temp1 = new Container();
- Container temp2 = new Container();
- for (int i = 0; i < 10; i++) {
- main[i].a = main[i].b = temp1;
- }
-
- for (int i = 0; i < 10; i++) {
- main[i].a = main[i].b = temp2;
- }
-
- }
-
- @Test
- public void test1() {
- test("test1Snippet", 2);
- }
-
- @Test
- public void test2() {
- test("test2Snippet", 4);
- }
-
- @Test
- public void test3() {
- test("test3Snippet", 4);
- }
-
- private void test(final String snippet, final int expectedBarriers) {
- Debug.scope("WriteBarrierAditionTest", new DebugDumpScope(snippet), new Runnable() {
-
- public void run() {
- StructuredGraph graph = parse(snippet);
- HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
- new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
- new WriteBarrierAdditionPhase().apply(graph);
- Debug.dump(graph, "After Write Barrier Addition");
- final int barriers = graph.getNodes(SerialWriteBarrier.class).count();
- Assert.assertTrue(barriers == expectedBarriers);
- for (WriteNode write : graph.getNodes(WriteNode.class)) {
- if (write.getWriteBarrierType() != WriteBarrierType.NONE) {
- Assert.assertTrue(write.successors().count() == 1);
- Assert.assertTrue(write.next() instanceof SerialWriteBarrier);
- }
- }
- }
- });
- }
-}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,712 +0,0 @@
-/*
- * Copyright (c) 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.compiler.test;
-
-import java.util.*;
-import java.util.concurrent.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.internal.*;
-import com.oracle.graal.hotspot.phases.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.graph.*;
-import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
-import com.oracle.graal.phases.tiers.*;
-
-/**
- * The following tests validate the write barrier verification phase. For every tested snippet, an
- * array of write barrier indices and the total write barrier number are passed as parameters. The
- * indices denote the barriers that will be manually removed. The write barrier verification phase
- * runs after the write barrier removal and depending on the result an assertion might be generated.
- * The tests anticipate the presence or not of an assertion generated by the verification phase.
- */
-public class WriteBarrierVerificationTest extends GraalCompilerTest {
-
- public static int barrierIndex;
-
- public static class Container {
-
- public Container a;
- public Container b;
- }
-
- private static native void safepoint();
-
- public static void test1Snippet() {
- Container main = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- barrierIndex = 0;
- safepoint();
- barrierIndex = 1;
- main.a = temp1;
- safepoint();
- barrierIndex = 2;
- main.b = temp2;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test1() {
- test("test1Snippet", 2, new int[]{1});
- }
-
- @Test(expected = AssertionError.class)
- public void test2() {
- test("test1Snippet", 2, new int[]{2});
- }
-
- public static void test2Snippet() {
- Container main = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- barrierIndex = 0;
- safepoint();
- barrierIndex = 1;
- main.a = temp1;
- barrierIndex = 2;
- main.b = temp2;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test3() {
- test("test2Snippet", 2, new int[]{1});
- }
-
- @Test
- public void test4() {
- test("test2Snippet", 2, new int[]{2});
- }
-
- public static void test3Snippet(boolean test) {
- Container main = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- barrierIndex = 0;
- safepoint();
- for (int i = 0; i < 10; i++) {
- if (test) {
- barrierIndex = 1;
- main.a = temp1;
- barrierIndex = 2;
- main.b = temp2;
- } else {
- barrierIndex = 3;
- main.a = temp1;
- barrierIndex = 4;
- main.b = temp2;
- }
- }
- }
-
- @Test(expected = AssertionError.class)
- public void test5() {
- test("test3Snippet", 4, new int[]{1, 2});
- }
-
- @Test(expected = AssertionError.class)
- public void test6() {
- test("test3Snippet", 4, new int[]{3, 4});
- }
-
- @Test(expected = AssertionError.class)
- public void test7() {
- test("test3Snippet", 4, new int[]{1});
- }
-
- @Test
- public void test8() {
- test("test3Snippet", 4, new int[]{2});
- }
-
- @Test(expected = AssertionError.class)
- public void test9() {
- test("test3Snippet", 4, new int[]{3});
- }
-
- @Test
- public void test10() {
- test("test3Snippet", 4, new int[]{4});
- }
-
- public static void test4Snippet(boolean test) {
- Container main = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- barrierIndex = 1;
- main.a = temp1;
- for (int i = 0; i < 10; i++) {
- if (test) {
- barrierIndex = 2;
- main.a = temp1;
- barrierIndex = 3;
- main.b = temp2;
- } else {
- barrierIndex = 4;
- main.a = temp2;
- barrierIndex = 5;
- main.b = temp1;
- }
- }
- }
-
- @Test(expected = AssertionError.class)
- public void test11() {
- test("test4Snippet", 5, new int[]{2, 3});
- }
-
- @Test(expected = AssertionError.class)
- public void test12() {
- test("test4Snippet", 5, new int[]{4, 5});
- }
-
- @Test(expected = AssertionError.class)
- public void test13() {
- test("test4Snippet", 5, new int[]{1});
- }
-
- public static void test5Snippet() {
- Container main = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- barrierIndex = 1;
- main.a = temp1;
- if (main.a == main.b) {
- barrierIndex = 2;
- main.a = temp1;
- barrierIndex = 3;
- main.b = temp2;
- } else {
- barrierIndex = 4;
- main.a = temp2;
- barrierIndex = 5;
- main.b = temp1;
- }
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test14() {
- test("test5Snippet", 5, new int[]{1});
- }
-
- @Test
- public void test15() {
- test("test5Snippet", 5, new int[]{2});
- }
-
- @Test
- public void test16() {
- test("test5Snippet", 5, new int[]{4});
- }
-
- @Test
- public void test17() {
- test("test5Snippet", 5, new int[]{3});
- }
-
- @Test
- public void test18() {
- test("test5Snippet", 5, new int[]{5});
- }
-
- @Test
- public void test19() {
- test("test5Snippet", 5, new int[]{2, 3});
- }
-
- @Test
- public void test20() {
- test("test5Snippet", 5, new int[]{4, 5});
- }
-
- public static void test6Snippet(boolean test) {
- Container main = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- barrierIndex = 1;
- main.a = temp1;
- if (test) {
- barrierIndex = 2;
- main.a = temp1;
- barrierIndex = 3;
- main.b = temp1.a.a;
- } else {
- barrierIndex = 4;
- main.a = temp2;
- barrierIndex = 5;
- main.b = temp2.a.a;
- }
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test21() {
- test("test6Snippet", 5, new int[]{1});
- }
-
- @Test(expected = AssertionError.class)
- public void test22() {
- test("test6Snippet", 5, new int[]{1, 2});
- }
-
- @Test(expected = AssertionError.class)
- public void test23() {
- test("test6Snippet", 5, new int[]{3});
- }
-
- @Test
- public void test24() {
- test("test6Snippet", 5, new int[]{4});
- }
-
- public static void test7Snippet(boolean test) {
- Container main = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- barrierIndex = 1;
- main.a = temp1;
- if (test) {
- barrierIndex = 2;
- main.a = temp1;
- }
- barrierIndex = 3;
- main.b = temp2;
- safepoint();
- }
-
- @Test
- public void test25() {
- test("test7Snippet", 3, new int[]{2});
- }
-
- @Test
- public void test26() {
- test("test7Snippet", 3, new int[]{3});
- }
-
- @Test
- public void test27() {
- test("test7Snippet", 3, new int[]{2, 3});
- }
-
- @Test(expected = AssertionError.class)
- public void test28() {
- test("test7Snippet", 3, new int[]{1});
- }
-
- public static void test8Snippet(boolean test) {
- Container main = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- if (test) {
- barrierIndex = 1;
- main.a = temp1;
- }
- barrierIndex = 2;
- main.b = temp2;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test29() {
- test("test8Snippet", 2, new int[]{1});
- }
-
- @Test(expected = AssertionError.class)
- public void test30() {
- test("test8Snippet", 2, new int[]{2});
- }
-
- @Test(expected = AssertionError.class)
- public void test31() {
- test("test8Snippet", 2, new int[]{1, 2});
- }
-
- public static void test9Snippet(boolean test) {
- Container main1 = new Container();
- Container main2 = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- if (test) {
- barrierIndex = 1;
- main1.a = temp1;
- } else {
- barrierIndex = 2;
- main2.a = temp1;
- }
- barrierIndex = 3;
- main1.b = temp2;
- barrierIndex = 4;
- main2.b = temp2;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test32() {
- test("test9Snippet", 4, new int[]{1});
- }
-
- @Test(expected = AssertionError.class)
- public void test33() {
- test("test9Snippet", 4, new int[]{2});
- }
-
- @Test(expected = AssertionError.class)
- public void test34() {
- test("test9Snippet", 4, new int[]{3});
- }
-
- @Test(expected = AssertionError.class)
- public void test35() {
- test("test9Snippet", 4, new int[]{4});
- }
-
- @Test(expected = AssertionError.class)
- public void test36() {
- test("test9Snippet", 4, new int[]{1, 2});
- }
-
- @Test(expected = AssertionError.class)
- public void test37() {
- test("test9Snippet", 4, new int[]{3, 4});
- }
-
- public static void test10Snippet(boolean test) {
- Container main1 = new Container();
- Container main2 = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- if (test) {
- barrierIndex = 1;
- main1.a = temp1;
- barrierIndex = 2;
- main2.a = temp2;
- } else {
- barrierIndex = 3;
- main2.a = temp1;
- }
- barrierIndex = 4;
- main1.b = temp2;
- barrierIndex = 5;
- main2.b = temp2;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test38() {
- test("test10Snippet", 5, new int[]{1});
- }
-
- @Test(expected = AssertionError.class)
- public void test39() {
- test("test10Snippet", 5, new int[]{2});
- }
-
- @Test(expected = AssertionError.class)
- public void test40() {
- test("test10Snippet", 5, new int[]{3});
- }
-
- @Test(expected = AssertionError.class)
- public void test41() {
- test("test10Snippet", 5, new int[]{4});
- }
-
- @Test
- public void test42() {
- test("test10Snippet", 5, new int[]{5});
- }
-
- @Test(expected = AssertionError.class)
- public void test43() {
- test("test10Snippet", 5, new int[]{1, 2});
- }
-
- @Test(expected = AssertionError.class)
- public void test44() {
- test("test10Snippet", 5, new int[]{1, 2, 3});
- }
-
- @Test(expected = AssertionError.class)
- public void test45() {
- test("test10Snippet", 5, new int[]{3, 4});
- }
-
- public static void test11Snippet(boolean test) {
- Container main1 = new Container();
- Container main2 = new Container();
- Container main3 = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- if (test) {
- barrierIndex = 1;
- main1.a = temp1;
- barrierIndex = 2;
- main3.a = temp1;
- if (!test) {
- barrierIndex = 3;
- main2.a = temp2;
- } else {
- barrierIndex = 4;
- main1.a = temp2;
- barrierIndex = 5;
- main3.a = temp2;
- }
- } else {
- barrierIndex = 6;
- main1.b = temp2;
- for (int i = 0; i < 10; i++) {
- barrierIndex = 7;
- main3.a = temp1;
- }
- barrierIndex = 8;
- main3.b = temp2;
- }
- barrierIndex = 9;
- main1.b = temp2;
- barrierIndex = 10;
- main2.b = temp2;
- barrierIndex = 11;
- main3.b = temp2;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test46() {
- test("test11Snippet", 11, new int[]{1});
- }
-
- @Test(expected = AssertionError.class)
- public void test47() {
- test("test11Snippet", 11, new int[]{2});
- }
-
- @Test(expected = AssertionError.class)
- public void test48() {
- test("test11Snippet", 11, new int[]{3});
- }
-
- @Test(expected = AssertionError.class)
- public void test49() {
- test("test11Snippet", 11, new int[]{6});
- }
-
- @Test(expected = AssertionError.class)
- public void test50() {
- test("test11Snippet", 11, new int[]{7});
- }
-
- @Test(expected = AssertionError.class)
- public void test51() {
- test("test11Snippet", 11, new int[]{8});
- }
-
- @Test(expected = AssertionError.class)
- public void test52() {
- test("test11Snippet", 11, new int[]{9});
- }
-
- @Test(expected = AssertionError.class)
- public void test53() {
- test("test11Snippet", 11, new int[]{10});
- }
-
- @Test
- public void test54() {
- test("test11Snippet", 11, new int[]{4});
- }
-
- @Test
- public void test55() {
- test("test11Snippet", 11, new int[]{5});
- }
-
- @Test
- public void test56() {
- test("test11Snippet", 11, new int[]{11});
- }
-
- public static void test12Snippet(boolean test) {
- Container main = new Container();
- Container main1 = new Container();
- Container temp1 = new Container();
- Container temp2 = new Container();
- barrierIndex = 0;
- safepoint();
- barrierIndex = 7;
- main1.a = temp1;
- for (int i = 0; i < 10; i++) {
- if (test) {
- barrierIndex = 1;
- main.a = temp1;
- barrierIndex = 2;
- main.b = temp2;
- } else {
- barrierIndex = 3;
- main.a = temp1;
- barrierIndex = 4;
- main.b = temp2;
- }
- }
- barrierIndex = 5;
- main.a = temp1;
- barrierIndex = 6;
- main.b = temp1;
- barrierIndex = 8;
- main1.b = temp1;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test57() {
- test("test12Snippet", 8, new int[]{5});
- }
-
- @Test
- public void test58() {
- test("test12Snippet", 8, new int[]{6});
- }
-
- @Test(expected = AssertionError.class)
- public void test59() {
- test("test12Snippet", 8, new int[]{7});
- }
-
- @Test(expected = AssertionError.class)
- public void test60() {
- test("test12Snippet", 8, new int[]{8});
- }
-
- private void test(final String snippet, final int expectedBarriers, final int... removedBarrierIndices) {
-
- AssertionError expectedError = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet), new Callable() {
-
- public AssertionError call() {
- final StructuredGraph graph = parse(snippet);
- HighTierContext highTierContext = new HighTierContext(runtime(), new Assumptions(false), replacements);
- MidTierContext midTierContext = new MidTierContext(runtime(), new Assumptions(false), replacements, runtime().getTarget(), OptimisticOptimizations.ALL);
-
- new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, highTierContext);
- new GuardLoweringPhase().apply(graph, midTierContext);
- new SafepointInsertionPhase().apply(graph);
- new WriteBarrierAdditionPhase().apply(graph);
-
- // First, the total number of expected barriers is checked.
- final int barriers = graph.getNodes(SerialWriteBarrier.class).count();
- Assert.assertTrue(expectedBarriers == barriers);
-
- // Iterate over all write nodes and remove barriers according to input indices.
- NodeIteratorClosure closure = new NodeIteratorClosure() {
-
- @Override
- protected Boolean processNode(FixedNode node, Boolean currentState) {
- if (node instanceof WriteNode) {
- WriteNode write = (WriteNode) node;
- LocationIdentity obj = write.getLocationIdentity();
- if (obj instanceof ResolvedJavaField) {
- if (((ResolvedJavaField) obj).getName().equals("barrierIndex")) {
- /*
- * A "barrierIndex" variable was found and is checked against
- * the input barrier array.
- */
- if (eliminateBarrier(write.value().asConstant().asInt(), removedBarrierIndices)) {
- return true;
- }
- }
- }
- } else if (node instanceof SerialWriteBarrier) {
- // Remove flagged write barriers.
- if (currentState) {
- graph.removeFixed(((SerialWriteBarrier) node));
- return false;
- }
- }
- return currentState;
- }
-
- private boolean eliminateBarrier(int index, int[] map) {
- for (int i = 0; i < map.length; i++) {
- if (map[i] == index) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- protected Map processLoop(LoopBeginNode loop, Boolean initialState) {
- return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates;
- }
-
- @Override
- protected Boolean merge(MergeNode merge, List states) {
- return false;
- }
-
- @Override
- protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) {
- return false;
- }
- };
-
- DebugConfig config = DebugScope.getConfig();
- try {
- ReentrantNodeIterator.apply(closure, graph.start(), false, null);
- Debug.setConfig(Debug.fixedConfig(false, false, false, false, config.dumpHandlers(), config.output()));
- new WriteBarrierVerificationPhase().apply(graph);
- } catch (AssertionError error) {
- /*
- * Catch assertion, test for expected one and re-throw in order to validate unit
- * test.
- */
- Assert.assertTrue(error.getMessage().equals("Write barrier must be present"));
- return error;
- } finally {
- Debug.setConfig(config);
- }
- return null;
- }
- });
- if (expectedError != null) {
- throw expectedError;
- }
- }
-}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Fri Jun 21 17:52:19 2013 +0200
@@ -37,5 +37,7 @@
appendPhase(new ExpandLogicPhase());
appendPhase(new DeadCodeEliminationPhase());
+
+ appendPhase(new RemoveValueProxyPhase());
}
}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64TailcallOp.java
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 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.hotspot.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.hotspot.phases.*;
+import com.oracle.graal.nodes.HeapAccess.WriteBarrierType;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class WriteBarrierAdditionTest extends GraalCompilerTest {
+
+ public static class Container {
+
+ public Container a;
+ public Container b;
+ }
+
+ public static void test1Snippet() {
+ Container main = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ main.a = temp1;
+ main.b = temp2;
+ }
+
+ public static void test2Snippet(boolean test) {
+ Container main = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ for (int i = 0; i < 10; i++) {
+ if (test) {
+ main.a = temp1;
+ main.b = temp2;
+ } else {
+ main.a = temp2;
+ main.b = temp1;
+ }
+ }
+ }
+
+ public static void test3Snippet() {
+ Container[] main = new Container[10];
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ for (int i = 0; i < 10; i++) {
+ main[i].a = main[i].b = temp1;
+ }
+
+ for (int i = 0; i < 10; i++) {
+ main[i].a = main[i].b = temp2;
+ }
+
+ }
+
+ @Test
+ public void test1() {
+ test("test1Snippet", 2);
+ }
+
+ @Test
+ public void test2() {
+ test("test2Snippet", 4);
+ }
+
+ @Test
+ public void test3() {
+ test("test3Snippet", 4);
+ }
+
+ private void test(final String snippet, final int expectedBarriers) {
+ Debug.scope("WriteBarrierAditionTest", new DebugDumpScope(snippet), new Runnable() {
+
+ public void run() {
+ StructuredGraph graph = parse(snippet);
+ HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
+ new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+ new WriteBarrierAdditionPhase().apply(graph);
+ Debug.dump(graph, "After Write Barrier Addition");
+ final int barriers = graph.getNodes(SerialWriteBarrier.class).count();
+ Assert.assertTrue(barriers == expectedBarriers);
+ for (WriteNode write : graph.getNodes(WriteNode.class)) {
+ if (write.getWriteBarrierType() != WriteBarrierType.NONE) {
+ Assert.assertTrue(write.successors().count() == 1);
+ Assert.assertTrue(write.next() instanceof SerialWriteBarrier);
+ }
+ }
+ }
+ });
+ }
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,713 @@
+/*
+ * Copyright (c) 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.hotspot.test;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.hotspot.phases.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
+import com.oracle.graal.phases.tiers.*;
+
+/**
+ * The following tests validate the write barrier verification phase. For every tested snippet, an
+ * array of write barrier indices and the total write barrier number are passed as parameters. The
+ * indices denote the barriers that will be manually removed. The write barrier verification phase
+ * runs after the write barrier removal and depending on the result an assertion might be generated.
+ * The tests anticipate the presence or not of an assertion generated by the verification phase.
+ */
+public class WriteBarrierVerificationTest extends GraalCompilerTest {
+
+ public static int barrierIndex;
+
+ public static class Container {
+
+ public Container a;
+ public Container b;
+ }
+
+ private static native void safepoint();
+
+ public static void test1Snippet() {
+ Container main = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ barrierIndex = 0;
+ safepoint();
+ barrierIndex = 1;
+ main.a = temp1;
+ safepoint();
+ barrierIndex = 2;
+ main.b = temp2;
+ safepoint();
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test1() {
+ test("test1Snippet", 2, new int[]{1});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test2() {
+ test("test1Snippet", 2, new int[]{2});
+ }
+
+ public static void test2Snippet() {
+ Container main = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ barrierIndex = 0;
+ safepoint();
+ barrierIndex = 1;
+ main.a = temp1;
+ barrierIndex = 2;
+ main.b = temp2;
+ safepoint();
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test3() {
+ test("test2Snippet", 2, new int[]{1});
+ }
+
+ @Test
+ public void test4() {
+ test("test2Snippet", 2, new int[]{2});
+ }
+
+ public static void test3Snippet(boolean test) {
+ Container main = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ barrierIndex = 0;
+ safepoint();
+ for (int i = 0; i < 10; i++) {
+ if (test) {
+ barrierIndex = 1;
+ main.a = temp1;
+ barrierIndex = 2;
+ main.b = temp2;
+ } else {
+ barrierIndex = 3;
+ main.a = temp1;
+ barrierIndex = 4;
+ main.b = temp2;
+ }
+ }
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test5() {
+ test("test3Snippet", 4, new int[]{1, 2});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test6() {
+ test("test3Snippet", 4, new int[]{3, 4});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test7() {
+ test("test3Snippet", 4, new int[]{1});
+ }
+
+ @Test
+ public void test8() {
+ test("test3Snippet", 4, new int[]{2});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test9() {
+ test("test3Snippet", 4, new int[]{3});
+ }
+
+ @Test
+ public void test10() {
+ test("test3Snippet", 4, new int[]{4});
+ }
+
+ public static void test4Snippet(boolean test) {
+ Container main = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ safepoint();
+ barrierIndex = 1;
+ main.a = temp1;
+ for (int i = 0; i < 10; i++) {
+ if (test) {
+ barrierIndex = 2;
+ main.a = temp1;
+ barrierIndex = 3;
+ main.b = temp2;
+ } else {
+ barrierIndex = 4;
+ main.a = temp2;
+ barrierIndex = 5;
+ main.b = temp1;
+ }
+ }
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test11() {
+ test("test4Snippet", 5, new int[]{2, 3});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test12() {
+ test("test4Snippet", 5, new int[]{4, 5});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test13() {
+ test("test4Snippet", 5, new int[]{1});
+ }
+
+ public static void test5Snippet() {
+ Container main = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ safepoint();
+ barrierIndex = 1;
+ main.a = temp1;
+ if (main.a == main.b) {
+ barrierIndex = 2;
+ main.a = temp1;
+ barrierIndex = 3;
+ main.b = temp2;
+ } else {
+ barrierIndex = 4;
+ main.a = temp2;
+ barrierIndex = 5;
+ main.b = temp1;
+ }
+ safepoint();
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test14() {
+ test("test5Snippet", 5, new int[]{1});
+ }
+
+ @Test
+ public void test15() {
+ test("test5Snippet", 5, new int[]{2});
+ }
+
+ @Test
+ public void test16() {
+ test("test5Snippet", 5, new int[]{4});
+ }
+
+ @Test
+ public void test17() {
+ test("test5Snippet", 5, new int[]{3});
+ }
+
+ @Test
+ public void test18() {
+ test("test5Snippet", 5, new int[]{5});
+ }
+
+ @Test
+ public void test19() {
+ test("test5Snippet", 5, new int[]{2, 3});
+ }
+
+ @Test
+ public void test20() {
+ test("test5Snippet", 5, new int[]{4, 5});
+ }
+
+ public static void test6Snippet(boolean test) {
+ Container main = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ safepoint();
+ barrierIndex = 1;
+ main.a = temp1;
+ if (test) {
+ barrierIndex = 2;
+ main.a = temp1;
+ barrierIndex = 3;
+ main.b = temp1.a.a;
+ } else {
+ barrierIndex = 4;
+ main.a = temp2;
+ barrierIndex = 5;
+ main.b = temp2.a.a;
+ }
+ safepoint();
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test21() {
+ test("test6Snippet", 5, new int[]{1});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test22() {
+ test("test6Snippet", 5, new int[]{1, 2});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test23() {
+ test("test6Snippet", 5, new int[]{3});
+ }
+
+ @Test
+ public void test24() {
+ test("test6Snippet", 5, new int[]{4});
+ }
+
+ public static void test7Snippet(boolean test) {
+ Container main = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ safepoint();
+ barrierIndex = 1;
+ main.a = temp1;
+ if (test) {
+ barrierIndex = 2;
+ main.a = temp1;
+ }
+ barrierIndex = 3;
+ main.b = temp2;
+ safepoint();
+ }
+
+ @Test
+ public void test25() {
+ test("test7Snippet", 3, new int[]{2});
+ }
+
+ @Test
+ public void test26() {
+ test("test7Snippet", 3, new int[]{3});
+ }
+
+ @Test
+ public void test27() {
+ test("test7Snippet", 3, new int[]{2, 3});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test28() {
+ test("test7Snippet", 3, new int[]{1});
+ }
+
+ public static void test8Snippet(boolean test) {
+ Container main = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ safepoint();
+ if (test) {
+ barrierIndex = 1;
+ main.a = temp1;
+ }
+ barrierIndex = 2;
+ main.b = temp2;
+ safepoint();
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test29() {
+ test("test8Snippet", 2, new int[]{1});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test30() {
+ test("test8Snippet", 2, new int[]{2});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test31() {
+ test("test8Snippet", 2, new int[]{1, 2});
+ }
+
+ public static void test9Snippet(boolean test) {
+ Container main1 = new Container();
+ Container main2 = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ safepoint();
+ if (test) {
+ barrierIndex = 1;
+ main1.a = temp1;
+ } else {
+ barrierIndex = 2;
+ main2.a = temp1;
+ }
+ barrierIndex = 3;
+ main1.b = temp2;
+ barrierIndex = 4;
+ main2.b = temp2;
+ safepoint();
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test32() {
+ test("test9Snippet", 4, new int[]{1});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test33() {
+ test("test9Snippet", 4, new int[]{2});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test34() {
+ test("test9Snippet", 4, new int[]{3});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test35() {
+ test("test9Snippet", 4, new int[]{4});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test36() {
+ test("test9Snippet", 4, new int[]{1, 2});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test37() {
+ test("test9Snippet", 4, new int[]{3, 4});
+ }
+
+ public static void test10Snippet(boolean test) {
+ Container main1 = new Container();
+ Container main2 = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ safepoint();
+ if (test) {
+ barrierIndex = 1;
+ main1.a = temp1;
+ barrierIndex = 2;
+ main2.a = temp2;
+ } else {
+ barrierIndex = 3;
+ main2.a = temp1;
+ }
+ barrierIndex = 4;
+ main1.b = temp2;
+ barrierIndex = 5;
+ main2.b = temp2;
+ safepoint();
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test38() {
+ test("test10Snippet", 5, new int[]{1});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test39() {
+ test("test10Snippet", 5, new int[]{2});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test40() {
+ test("test10Snippet", 5, new int[]{3});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test41() {
+ test("test10Snippet", 5, new int[]{4});
+ }
+
+ @Test
+ public void test42() {
+ test("test10Snippet", 5, new int[]{5});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test43() {
+ test("test10Snippet", 5, new int[]{1, 2});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test44() {
+ test("test10Snippet", 5, new int[]{1, 2, 3});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test45() {
+ test("test10Snippet", 5, new int[]{3, 4});
+ }
+
+ public static void test11Snippet(boolean test) {
+ Container main1 = new Container();
+ Container main2 = new Container();
+ Container main3 = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ safepoint();
+ if (test) {
+ barrierIndex = 1;
+ main1.a = temp1;
+ barrierIndex = 2;
+ main3.a = temp1;
+ if (!test) {
+ barrierIndex = 3;
+ main2.a = temp2;
+ } else {
+ barrierIndex = 4;
+ main1.a = temp2;
+ barrierIndex = 5;
+ main3.a = temp2;
+ }
+ } else {
+ barrierIndex = 6;
+ main1.b = temp2;
+ for (int i = 0; i < 10; i++) {
+ barrierIndex = 7;
+ main3.a = temp1;
+ }
+ barrierIndex = 8;
+ main3.b = temp2;
+ }
+ barrierIndex = 9;
+ main1.b = temp2;
+ barrierIndex = 10;
+ main2.b = temp2;
+ barrierIndex = 11;
+ main3.b = temp2;
+ safepoint();
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test46() {
+ test("test11Snippet", 11, new int[]{1});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test47() {
+ test("test11Snippet", 11, new int[]{2});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test48() {
+ test("test11Snippet", 11, new int[]{3});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test49() {
+ test("test11Snippet", 11, new int[]{6});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test50() {
+ test("test11Snippet", 11, new int[]{7});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test51() {
+ test("test11Snippet", 11, new int[]{8});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test52() {
+ test("test11Snippet", 11, new int[]{9});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test53() {
+ test("test11Snippet", 11, new int[]{10});
+ }
+
+ @Test
+ public void test54() {
+ test("test11Snippet", 11, new int[]{4});
+ }
+
+ @Test
+ public void test55() {
+ test("test11Snippet", 11, new int[]{5});
+ }
+
+ @Test
+ public void test56() {
+ test("test11Snippet", 11, new int[]{11});
+ }
+
+ public static void test12Snippet(boolean test) {
+ Container main = new Container();
+ Container main1 = new Container();
+ Container temp1 = new Container();
+ Container temp2 = new Container();
+ barrierIndex = 0;
+ safepoint();
+ barrierIndex = 7;
+ main1.a = temp1;
+ for (int i = 0; i < 10; i++) {
+ if (test) {
+ barrierIndex = 1;
+ main.a = temp1;
+ barrierIndex = 2;
+ main.b = temp2;
+ } else {
+ barrierIndex = 3;
+ main.a = temp1;
+ barrierIndex = 4;
+ main.b = temp2;
+ }
+ }
+ barrierIndex = 5;
+ main.a = temp1;
+ barrierIndex = 6;
+ main.b = temp1;
+ barrierIndex = 8;
+ main1.b = temp1;
+ safepoint();
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test57() {
+ test("test12Snippet", 8, new int[]{5});
+ }
+
+ @Test
+ public void test58() {
+ test("test12Snippet", 8, new int[]{6});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test59() {
+ test("test12Snippet", 8, new int[]{7});
+ }
+
+ @Test(expected = AssertionError.class)
+ public void test60() {
+ test("test12Snippet", 8, new int[]{8});
+ }
+
+ private void test(final String snippet, final int expectedBarriers, final int... removedBarrierIndices) {
+
+ AssertionError expectedError = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet), new Callable() {
+
+ public AssertionError call() {
+ final StructuredGraph graph = parse(snippet);
+ HighTierContext highTierContext = new HighTierContext(runtime(), new Assumptions(false), replacements);
+ MidTierContext midTierContext = new MidTierContext(runtime(), new Assumptions(false), replacements, runtime().getTarget(), OptimisticOptimizations.ALL);
+
+ new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, highTierContext);
+ new GuardLoweringPhase().apply(graph, midTierContext);
+ new SafepointInsertionPhase().apply(graph);
+ new WriteBarrierAdditionPhase().apply(graph);
+
+ // First, the total number of expected barriers is checked.
+ final int barriers = graph.getNodes(SerialWriteBarrier.class).count();
+ Assert.assertTrue(expectedBarriers == barriers);
+
+ // Iterate over all write nodes and remove barriers according to input indices.
+ NodeIteratorClosure closure = new NodeIteratorClosure() {
+
+ @Override
+ protected Boolean processNode(FixedNode node, Boolean currentState) {
+ if (node instanceof WriteNode) {
+ WriteNode write = (WriteNode) node;
+ LocationIdentity obj = write.getLocationIdentity();
+ if (obj instanceof ResolvedJavaField) {
+ if (((ResolvedJavaField) obj).getName().equals("barrierIndex")) {
+ /*
+ * A "barrierIndex" variable was found and is checked against
+ * the input barrier array.
+ */
+ if (eliminateBarrier(write.value().asConstant().asInt(), removedBarrierIndices)) {
+ return true;
+ }
+ }
+ }
+ } else if (node instanceof SerialWriteBarrier) {
+ // Remove flagged write barriers.
+ if (currentState) {
+ graph.removeFixed(((SerialWriteBarrier) node));
+ return false;
+ }
+ }
+ return currentState;
+ }
+
+ private boolean eliminateBarrier(int index, int[] map) {
+ for (int i = 0; i < map.length; i++) {
+ if (map[i] == index) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected Map processLoop(LoopBeginNode loop, Boolean initialState) {
+ return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates;
+ }
+
+ @Override
+ protected Boolean merge(MergeNode merge, List states) {
+ return false;
+ }
+
+ @Override
+ protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) {
+ return false;
+ }
+ };
+
+ DebugConfig config = DebugScope.getConfig();
+ try {
+ ReentrantNodeIterator.apply(closure, graph.start(), false, null);
+ Debug.setConfig(Debug.fixedConfig(false, false, false, false, config.dumpHandlers(), config.output()));
+ new WriteBarrierVerificationPhase().apply(graph);
+ } catch (AssertionError error) {
+ /*
+ * Catch assertion, test for expected one and re-throw in order to validate unit
+ * test.
+ */
+ Assert.assertTrue(error.getMessage().equals("Write barrier must be present"));
+ return error;
+ } finally {
+ Debug.setConfig(config);
+ }
+ return null;
+ }
+ });
+ if (expectedError != null) {
+ throw expectedError;
+ }
+ }
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Jun 21 17:52:19 2013 +0200
@@ -51,6 +51,8 @@
import static com.oracle.graal.phases.GraalOptions.*;
import static com.oracle.graal.replacements.Log.*;
import static com.oracle.graal.replacements.MathSubstitutionsX86.*;
+import static com.oracle.graal.hotspot.nodes.G1PostWriteBarrierStubCall.*;
+import static com.oracle.graal.hotspot.nodes.G1PreWriteBarrierStubCall.*;
import java.lang.reflect.*;
import java.util.*;
@@ -294,7 +296,8 @@
linkForeignCall(r, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
linkForeignCall(r, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
linkForeignCall(r, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, NOT_REEXECUTABLE, NO_LOCATIONS);
-
+ linkForeignCall(r, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
+ linkForeignCall(r, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
if (IntrinsifyObjectMethods.getValue()) {
r.registerSubstitutions(ObjectSubstitutions.class);
}
@@ -325,6 +328,8 @@
writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, r, graalRuntime.getTarget());
boxingSnippets = new BoxingSnippets.Templates(this, r, graalRuntime.getTarget());
exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, r, graalRuntime.getTarget());
+
+ r.registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(this, r, graalRuntime.getTarget()));
}
public HotSpotGraalRuntime getGraalRuntime() {
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrierStubCall.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrierStubCall.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 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.hotspot.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.word.*;
+
+public class G1PostWriteBarrierStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
+
+ @Input private ValueNode cardAddress;
+ public static final ForeignCallDescriptor G1WBPOSTCALL = new ForeignCallDescriptor("write_barrier_post", void.class, Word.class);
+
+ public G1PostWriteBarrierStubCall(ValueNode cardAddress) {
+ super(StampFactory.forVoid());
+ this.cardAddress = cardAddress;
+ }
+
+ @Override
+ public void generate(LIRGenerator gen) {
+ ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(G1PostWriteBarrierStubCall.G1WBPOSTCALL);
+ gen.emitForeignCall(linkage, this, gen.operand(cardAddress));
+ }
+
+ @NodeIntrinsic
+ public static native void call(Word cardAddress);
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrierStubCall.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrierStubCall.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 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.hotspot.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+public class G1PreWriteBarrierStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
+
+ @Input private ValueNode object;
+ public static final ForeignCallDescriptor G1WBPRECALL = new ForeignCallDescriptor("write_barrier_pre", void.class, Object.class);
+
+ public G1PreWriteBarrierStubCall(ValueNode object) {
+ super(StampFactory.forVoid());
+ this.object = object;
+ }
+
+ @Override
+ public void generate(LIRGenerator gen) {
+ ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(G1PreWriteBarrierStubCall.G1WBPRECALL);
+ gen.emitForeignCall(linkage, this, gen.operand(object));
+ }
+
+ @NodeIntrinsic
+ public static native void call(Object hub);
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Fri Jun 21 17:52:19 2013 +0200
@@ -41,8 +41,10 @@
for (CompareAndSwapNode node : graph.getNodes(CompareAndSwapNode.class)) {
addCASBarriers(node, graph);
}
- for (GenericArrayRangeWriteBarrier node : graph.getNodes(GenericArrayRangeWriteBarrier.class)) {
- addArrayRangeBarriers(node, graph);
+ for (ArrayRangeWriteNode node : graph.getNodes(ArrayRangeWriteNode.class)) {
+ if (node.isObjectArray()) {
+ addArrayRangeBarriers(node, graph);
+ }
}
}
@@ -69,9 +71,9 @@
}
}
- private static void addArrayRangeBarriers(GenericArrayRangeWriteBarrier node, StructuredGraph graph) {
- SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getDstObject(), node.getDstPos(), node.getLength()));
- graph.replaceFixedWithFixed(node, serialArrayRangeWriteBarrier);
+ private static void addArrayRangeBarriers(ArrayRangeWriteNode node, StructuredGraph graph) {
+ SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
+ graph.addAfterFixed(node, serialArrayRangeWriteBarrier);
}
}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Fri Jun 21 17:52:19 2013 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -76,35 +76,11 @@
private static final Kind VECTOR_KIND = Kind.Long;
private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
- private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
+ private static void checkedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
checkNonNull(src);
checkNonNull(dest);
checkLimits(src, srcPos, dest, destPos, length);
- int header = arrayBaseOffset(baseKind);
- int elementSize = arrayIndexScale(baseKind);
- long byteLength = (long) length * elementSize;
- long nonVectorBytes = byteLength % VECTOR_SIZE;
- long srcOffset = (long) srcPos * elementSize;
- long destOffset = (long) destPos * elementSize;
- if (probability(NOT_FREQUENT_PROBABILITY, src == dest) && probability(NOT_FREQUENT_PROBABILITY, srcPos < destPos)) {
- // bad aliased case
- for (long i = byteLength - elementSize; i >= byteLength - nonVectorBytes; i -= elementSize) {
- UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
- }
- long vectorLength = byteLength - nonVectorBytes;
- for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
- Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
- UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
- }
- } else {
- for (long i = 0; i < nonVectorBytes; i += elementSize) {
- UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
- }
- for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
- Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
- UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
- }
- }
+ UnsafeArrayCopyNode.arraycopy(src, srcPos, dest, destPos, length, baseKind);
}
public static void checkNonNull(Object obj) {
@@ -149,85 +125,49 @@
@Snippet
public static void arraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
byteCounter.inc();
- vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+ checkedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
}
@Snippet
public static void arraycopy(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) {
booleanCounter.inc();
- vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+ checkedCopy(src, srcPos, dest, destPos, length, Kind.Boolean);
}
@Snippet
public static void arraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) {
charCounter.inc();
- vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Char);
+ checkedCopy(src, srcPos, dest, destPos, length, Kind.Char);
}
@Snippet
public static void arraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) {
shortCounter.inc();
- vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Short);
+ checkedCopy(src, srcPos, dest, destPos, length, Kind.Short);
}
@Snippet
public static void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) {
intCounter.inc();
- vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Int);
+ checkedCopy(src, srcPos, dest, destPos, length, Kind.Int);
}
@Snippet
public static void arraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) {
floatCounter.inc();
- vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Float);
+ checkedCopy(src, srcPos, dest, destPos, length, Kind.Float);
}
@Snippet
public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) {
longCounter.inc();
- checkNonNull(src);
- checkNonNull(dest);
- checkLimits(src, srcPos, dest, destPos, length);
- Kind baseKind = Kind.Long;
- int header = arrayBaseOffset(baseKind);
- long byteLength = (long) length * arrayIndexScale(baseKind);
- long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
- long destOffset = (long) destPos * arrayIndexScale(baseKind);
- if (src == dest && srcPos < destPos) { // bad aliased case
- for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
- Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
- UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
- }
- } else {
- for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
- Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
- UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
- }
- }
+ checkedCopy(src, srcPos, dest, destPos, length, Kind.Long);
}
@Snippet
public static void arraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) {
doubleCounter.inc();
- checkNonNull(src);
- checkNonNull(dest);
- checkLimits(src, srcPos, dest, destPos, length);
- Kind baseKind = Kind.Double;
- int header = arrayBaseOffset(baseKind);
- long byteLength = (long) length * arrayIndexScale(baseKind);
- long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
- long destOffset = (long) destPos * arrayIndexScale(baseKind);
- if (src == dest && srcPos < destPos) { // bad aliased case
- for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
- Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
- UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
- }
- } else {
- for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
- Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
- UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
- }
- }
+ checkedCopy(src, srcPos, dest, destPos, length, Kind.Double);
}
@Snippet
@@ -239,48 +179,25 @@
@Snippet
public static void arrayObjectCopy(Object src, int srcPos, Object dest, int destPos, int length) {
objectCounter.inc();
- checkNonNull(src);
- checkNonNull(dest);
- checkLimits(src, srcPos, dest, destPos, length);
- final int scale = arrayIndexScale(Kind.Object);
- int header = arrayBaseOffset(Kind.Object);
- if (src == dest && srcPos < destPos) { // bad aliased case
- long start = (long) (length - 1) * scale;
- for (long i = start; i >= 0; i -= scale) {
- Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
- DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a);
- }
- } else {
- long end = (long) length * scale;
- for (long i = 0; i < end; i += scale) {
- Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
- DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a);
-
- }
- }
- if (length > 0) {
- GenericArrayRangeWriteBarrier.insertWriteBarrier(dest, destPos, length);
- }
+ checkedCopy(src, srcPos, dest, destPos, length, Kind.Object);
}
@Snippet
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) {
-
// loading the hubs also checks for nullness
Word srcHub = loadHub(src);
Word destHub = loadHub(dest);
- int layoutHelper = checkArrayType(srcHub);
- int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
- final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) == 0);
+ if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, src != dest)) {
+ int layoutHelper = checkArrayType(srcHub);
+ final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) == 0);
- if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, src != dest)) {
checkLimits(src, srcPos, dest, destPos, length);
if (probability(FAST_PATH_PROBABILITY, isObjectArray)) {
genericObjectExactCallCounter.inc();
arrayObjectCopy(src, srcPos, dest, destPos, length);
} else {
genericPrimitiveCallCounter.inc();
- arraycopyInnerloop(src, srcPos, dest, destPos, length, layoutHelper);
+ UnsafeArrayCopyNode.arraycopyPrimitive(src, srcPos, dest, destPos, length, layoutHelper);
}
} else {
genericObjectCallCounter.inc();
@@ -288,33 +205,6 @@
}
}
- public static void arraycopyInnerloop(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper) {
- int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
- int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
-
- Word memory = (Word) Word.fromObject(src);
-
- Word srcOffset = (Word) Word.fromObject(src).add(headerSize).add(srcPos << log2ElementSize);
- Word destOffset = (Word) Word.fromObject(dest).add(headerSize).add(destPos << log2ElementSize);
- Word destStart = destOffset;
- long sizeInBytes = ((long) length) << log2ElementSize;
- Word destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize));
-
- int nonVectorBytes = (int) (sizeInBytes % VECTOR_SIZE);
- Word destNonVectorEnd = destStart.add(nonVectorBytes);
-
- while (destOffset.belowThan(destNonVectorEnd)) {
- destOffset.writeByte(0, srcOffset.readByte(0, ANY_LOCATION), ANY_LOCATION);
- destOffset = destOffset.add(1);
- srcOffset = srcOffset.add(1);
- }
- while (destOffset.belowThan(destEnd)) {
- destOffset.writeWord(0, srcOffset.readWord(0, ANY_LOCATION), ANY_LOCATION);
- destOffset = destOffset.add(wordSize());
- srcOffset = srcOffset.add(wordSize());
- }
- }
-
private static final SnippetCounter.Group checkCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy checkInputs") : null;
private static final SnippetCounter checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess");
private static final SnippetCounter checkNPECounter = new SnippetCounter(checkCounters, "checkNPE", "checkNPE");
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Jun 21 17:52:19 2013 +0200
@@ -126,7 +126,7 @@
Word hub = loadWordFromObject(elementType, arrayKlassOffset());
if (hub.equal(Word.zero())) {
// the array class is not yet loaded
- DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.Unresolved);
+ DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved);
}
int layoutHelper = readLayoutHelper(hub);
@@ -143,8 +143,8 @@
// esz is the element size in bytes
//@formatter:on
- int headerSize = (layoutHelper >> 16) & 0xFF;
- int log2ElementSize = layoutHelper & 0xFF;
+ int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
+ int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
return allocateArray(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents);
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 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.hotspot.replacements;
+
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+
+public final class UnsafeArrayCopyNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single {
+
+ @Input private ValueNode src;
+ @Input private ValueNode srcPos;
+ @Input private ValueNode dest;
+ @Input private ValueNode destPos;
+ @Input private ValueNode length;
+ @Input private ValueNode layoutHelper;
+
+ private Kind elementKind;
+
+ private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper, Kind elementKind) {
+ super(StampFactory.forVoid());
+ assert layoutHelper == null || elementKind == null;
+ this.src = src;
+ this.srcPos = srcPos;
+ this.dest = dest;
+ this.destPos = destPos;
+ this.length = length;
+ this.layoutHelper = layoutHelper;
+ this.elementKind = elementKind;
+ }
+
+ private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind) {
+ this(src, srcPos, dest, destPos, length, null, elementKind);
+ }
+
+ private UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper) {
+ this(src, srcPos, dest, destPos, length, layoutHelper, null);
+ }
+
+ @Override
+ public ValueNode getArray() {
+ return dest;
+ }
+
+ @Override
+ public ValueNode getIndex() {
+ return destPos;
+ }
+
+ @Override
+ public ValueNode getLength() {
+ return length;
+ }
+
+ @Override
+ public boolean isObjectArray() {
+ return elementKind == Kind.Object;
+ }
+
+ public Kind getElementKind() {
+ return elementKind;
+ }
+
+ @Override
+ public void lower(LoweringTool tool, LoweringType loweringType) {
+ if (loweringType == LoweringType.AFTER_GUARDS) {
+ UnsafeArrayCopySnippets.Templates templates = tool.getReplacements().getSnippetTemplateCache(UnsafeArrayCopySnippets.Templates.class);
+ templates.lower(this);
+ }
+ }
+
+ public void addSnippetArguments(Arguments args) {
+ args.add("src", src);
+ args.add("srcPos", srcPos);
+ args.add("dest", dest);
+ args.add("destPos", destPos);
+ args.add("length", length);
+ if (layoutHelper != null) {
+ args.add("layoutHelper", layoutHelper);
+ }
+ }
+
+ @Override
+ public LocationIdentity getLocationIdentity() {
+ if (elementKind == null) {
+ return ANY_LOCATION;
+ } else {
+ return NamedLocationIdentity.getArrayLocation(elementKind);
+ }
+ }
+
+ @NodeIntrinsic
+ public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind);
+
+ @NodeIntrinsic
+ public static native void arraycopyPrimitive(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper);
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 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.hotspot.replacements;
+
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.replacements.SnippetTemplate.*;
+import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
+import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
+import com.oracle.graal.replacements.nodes.*;
+import com.oracle.graal.word.*;
+
+public class UnsafeArrayCopySnippets implements Snippets {
+
+ private static final Kind VECTOR_KIND = Kind.Long;
+ private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
+
+ private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
+ int header = arrayBaseOffset(baseKind);
+ int elementSize = arrayIndexScale(baseKind);
+ long byteLength = (long) length * elementSize;
+ long nonVectorBytes = byteLength % VECTOR_SIZE;
+ long srcOffset = (long) srcPos * elementSize;
+ long destOffset = (long) destPos * elementSize;
+ if (probability(NOT_FREQUENT_PROBABILITY, src == dest) && probability(NOT_FREQUENT_PROBABILITY, srcPos < destPos)) {
+ // bad aliased case
+ for (long i = byteLength - elementSize; i >= byteLength - nonVectorBytes; i -= elementSize) {
+ UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
+ }
+ long vectorLength = byteLength - nonVectorBytes;
+ for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
+ Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+ UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+ }
+ } else {
+ for (long i = 0; i < nonVectorBytes; i += elementSize) {
+ UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
+ }
+ for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) {
+ Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+ UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+ }
+ }
+ }
+
+ @Snippet
+ public static void arraycopyByte(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
+ vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+ }
+
+ @Snippet
+ public static void arraycopyBoolean(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) {
+ vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Byte);
+ }
+
+ @Snippet
+ public static void arraycopyChar(char[] src, int srcPos, char[] dest, int destPos, int length) {
+ vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Char);
+ }
+
+ @Snippet
+ public static void arraycopyShort(short[] src, int srcPos, short[] dest, int destPos, int length) {
+ vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Short);
+ }
+
+ @Snippet
+ public static void arraycopyInt(int[] src, int srcPos, int[] dest, int destPos, int length) {
+ vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Int);
+ }
+
+ @Snippet
+ public static void arraycopyFloat(float[] src, int srcPos, float[] dest, int destPos, int length) {
+ vectorizedCopy(src, srcPos, dest, destPos, length, Kind.Float);
+ }
+
+ @Snippet
+ public static void arraycopyLong(long[] src, int srcPos, long[] dest, int destPos, int length) {
+ Kind baseKind = Kind.Long;
+ int header = arrayBaseOffset(baseKind);
+ long byteLength = (long) length * arrayIndexScale(baseKind);
+ long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
+ long destOffset = (long) destPos * arrayIndexScale(baseKind);
+ if (src == dest && srcPos < destPos) { // bad aliased case
+ for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
+ Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+ UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+ }
+ } else {
+ for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
+ Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+ UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+ }
+ }
+ }
+
+ @Snippet
+ public static void arraycopyDouble(double[] src, int srcPos, double[] dest, int destPos, int length) {
+ Kind baseKind = Kind.Double;
+ int header = arrayBaseOffset(baseKind);
+ long byteLength = (long) length * arrayIndexScale(baseKind);
+ long srcOffset = (long) srcPos * arrayIndexScale(baseKind);
+ long destOffset = (long) destPos * arrayIndexScale(baseKind);
+ if (src == dest && srcPos < destPos) { // bad aliased case
+ for (long i = byteLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) {
+ Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+ UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+ }
+ } else {
+ for (long i = 0; i < byteLength; i += VECTOR_SIZE) {
+ Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND);
+ UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND);
+ }
+ }
+ }
+
+ /**
+ * Does NOT perform store checks.
+ */
+ @Snippet
+ public static void arraycopyObject(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
+ final int scale = arrayIndexScale(Kind.Object);
+ int header = arrayBaseOffset(Kind.Object);
+ if (src == dest && srcPos < destPos) { // bad aliased case
+ long start = (long) (length - 1) * scale;
+ for (long i = start; i >= 0; i -= scale) {
+ Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
+ DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a);
+ }
+ } else {
+ long end = (long) length * scale;
+ for (long i = 0; i < end; i += scale) {
+ Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object);
+ DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a);
+ }
+ }
+ }
+
+ @Snippet
+ public static void arraycopyPrimitive(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper) {
+ int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
+ int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
+
+ Word srcOffset = (Word) Word.fromObject(src).add(headerSize).add(srcPos << log2ElementSize);
+ Word destOffset = (Word) Word.fromObject(dest).add(headerSize).add(destPos << log2ElementSize);
+ Word destStart = destOffset;
+ long sizeInBytes = ((long) length) << log2ElementSize;
+ Word destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize));
+
+ int nonVectorBytes = (int) (sizeInBytes % VECTOR_SIZE);
+ Word destNonVectorEnd = destStart.add(nonVectorBytes);
+
+ while (destOffset.belowThan(destNonVectorEnd)) {
+ destOffset.writeByte(0, srcOffset.readByte(0, ANY_LOCATION), ANY_LOCATION);
+ destOffset = destOffset.add(1);
+ srcOffset = srcOffset.add(1);
+ }
+ while (destOffset.belowThan(destEnd)) {
+ destOffset.writeWord(0, srcOffset.readWord(0, ANY_LOCATION), ANY_LOCATION);
+ destOffset = destOffset.add(wordSize());
+ srcOffset = srcOffset.add(wordSize());
+ }
+ }
+
+ public static class Templates extends AbstractTemplates {
+
+ private final SnippetInfo[] arraycopySnippets;
+ private final SnippetInfo genericPrimitiveSnippet;
+
+ public Templates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) {
+ super(runtime, replacements, target);
+
+ arraycopySnippets = new SnippetInfo[Kind.values().length];
+ arraycopySnippets[Kind.Boolean.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyBoolean");
+ arraycopySnippets[Kind.Byte.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyByte");
+ arraycopySnippets[Kind.Short.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyShort");
+ arraycopySnippets[Kind.Char.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyChar");
+ arraycopySnippets[Kind.Int.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyInt");
+ arraycopySnippets[Kind.Long.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyLong");
+ arraycopySnippets[Kind.Float.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyFloat");
+ arraycopySnippets[Kind.Double.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyDouble");
+ arraycopySnippets[Kind.Object.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyObject");
+
+ genericPrimitiveSnippet = snippet(UnsafeArrayCopySnippets.class, "arraycopyPrimitive");
+ }
+
+ public void lower(UnsafeArrayCopyNode node) {
+ Kind elementKind = node.getElementKind();
+ SnippetInfo snippet;
+ if (elementKind == null) {
+ // primitive array of unknown kind
+ snippet = genericPrimitiveSnippet;
+ } else {
+ snippet = arraycopySnippets[elementKind.ordinal()];
+ assert snippet != null : "arraycopy snippet for " + elementKind.name() + " not found";
+ }
+
+ Arguments args = new Arguments(snippet);
+ node.addSnippetArguments(args);
+
+ SnippetTemplate template = template(args);
+ template.instantiate(runtime, node, DEFAULT_REPLACER, args);
+ }
+ }
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PostWriteBarrier.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PostWriteBarrier.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 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.nodes;
+
+import com.oracle.graal.nodes.extended.*;
+
+public class G1PostWriteBarrier extends WriteBarrier {
+
+ @Input private ValueNode value;
+
+ public ValueNode getValue() {
+ return value;
+ }
+
+ public G1PostWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) {
+ super(object, location, precise);
+ this.value = value;
+ }
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PreWriteBarrier.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PreWriteBarrier.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 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.nodes;
+
+import com.oracle.graal.nodes.extended.*;
+
+public class G1PreWriteBarrier extends WriteBarrier {
+
+ @Input private ValueNode expectedObject;
+ private final boolean doLoad;
+
+ public ValueNode getExpectedObject() {
+ return expectedObject;
+ }
+
+ public boolean doLoad() {
+ return doLoad;
+ }
+
+ public G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) {
+ super(object, location, true);
+ this.doLoad = doLoad;
+ this.expectedObject = expectedObject;
+ }
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GenericArrayRangeWriteBarrier.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GenericArrayRangeWriteBarrier.java Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 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.nodes;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
-
-public final class GenericArrayRangeWriteBarrier extends FixedWithNextNode implements Node.IterableNodeType {
-
- @Input private ValueNode dstObject;
- @Input private ValueNode dstPos;
- @Input private ValueNode length;
-
- public ValueNode getDstObject() {
- return dstObject;
- }
-
- public ValueNode getDstPos() {
- return dstPos;
- }
-
- public ValueNode getLength() {
- return length;
- }
-
- public GenericArrayRangeWriteBarrier(ValueNode dstObject, ValueNode dstPos, ValueNode length) {
- super(StampFactory.forVoid());
- this.dstObject = dstObject;
- this.dstPos = dstPos;
- this.length = length;
-
- }
-
- @NodeIntrinsic
- public static native void insertWriteBarrier(Object dstObject, int dstPos, int length);
-}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java Fri Jun 21 17:52:19 2013 +0200
@@ -22,39 +22,11 @@
*/
package com.oracle.graal.nodes;
-import com.oracle.graal.graph.*;
import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-public final class SerialWriteBarrier extends FixedWithNextNode implements Lowerable, Node.IterableNodeType {
-
- @Input private ValueNode object;
- @Input private LocationNode location;
- private final boolean precise;
- public ValueNode getObject() {
- return object;
- }
-
- public LocationNode getLocation() {
- return location;
- }
-
- public boolean usePrecise() {
- return precise;
- }
+public class SerialWriteBarrier extends WriteBarrier {
public SerialWriteBarrier(ValueNode object, LocationNode location, boolean precise) {
- super(StampFactory.forVoid());
- this.object = object;
- this.location = location;
- this.precise = precise;
- }
-
- @Override
- public void lower(LoweringTool generator, LoweringType loweringType) {
- assert loweringType == LoweringType.AFTER_GUARDS;
- generator.getRuntime().lower(this, generator);
+ super(object, location, precise);
}
}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 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.nodes;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class WriteBarrier extends FixedWithNextNode implements Lowerable, Node.IterableNodeType {
+
+ @Input private ValueNode object;
+ @Input private LocationNode location;
+ private final boolean precise;
+
+ public ValueNode getObject() {
+ return object;
+ }
+
+ public LocationNode getLocation() {
+ return location;
+ }
+
+ public boolean usePrecise() {
+ return precise;
+ }
+
+ public WriteBarrier(ValueNode object, LocationNode location, boolean precise) {
+ super(StampFactory.forVoid());
+ this.object = object;
+ this.location = location;
+ this.precise = precise;
+ }
+
+ @Override
+ public void lower(LoweringTool generator, LoweringType loweringType) {
+ assert loweringType == LoweringType.AFTER_GUARDS;
+ generator.getRuntime().lower(this, generator);
+ }
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 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.nodes.extended;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Base class for nodes that modify a range of an array.
+ */
+public abstract class ArrayRangeWriteNode extends AbstractStateSplit implements Node.IterableNodeType {
+
+ protected ArrayRangeWriteNode(Stamp stamp) {
+ super(stamp);
+ }
+
+ /**
+ * The array that is written to.
+ */
+ public abstract ValueNode getArray();
+
+ /**
+ * The first modified index.
+ */
+ public abstract ValueNode getIndex();
+
+ /**
+ * The length of the modified range.
+ */
+ public abstract ValueNode getLength();
+
+ /**
+ * Return true if the written array is an object array, false if it is a primitive array.
+ */
+ public abstract boolean isObjectArray();
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/CreateCast.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/CreateCast.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Specifies a factory method that creates a {@link Node} which is used to cast this child.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface CreateCast {
+
+ String[] value();
+
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExecuteChildren.java
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExecuteChildren.java Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.codegen;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface ExecuteChildren {
-
- String[] value();
-
-}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExtensionAnnotation.java
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExtensionAnnotation.java Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.codegen;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.ANNOTATION_TYPE})
-public @interface ExtensionAnnotation {
-
- String processorClassName();
-
-}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java Fri Jun 21 17:52:19 2013 +0200
@@ -26,6 +26,10 @@
import com.oracle.truffle.api.nodes.*;
+/**
+ * A {@link NodeChild} element defines an executable child for the enclosing {@link Node}. A
+ * {@link Node} contains multiple {@link NodeChildren} specified in linear execution order.
+ */
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE})
public @interface NodeChild {
@@ -35,13 +39,13 @@
Class> type() default NodeClass.InheritNode.class;
/**
- * Executes the {@link NodeChild} with values from other defined {@link NodeChild} elements.
- * These referenced children must be defined before the current node in the execution order. The
- * current node {@link #type()} attribute must be set to a {@link Node} which supports the
- * evaluated execution with the number of {@link #executeWith()} arguments that are defined. For
- * example if this child is executed with one argument, the {@link #type()} attribute must
- * define a node which publicly declares a method with the signature
- * Object execute*(VirtualFrame, Object)
.
+ * The {@link #executeWith()} property allows a node to pass the result of one child's
+ * executable as an input to another child's executable. These referenced children must be
+ * defined before the current node in the execution order. The current node {@link #type()}
+ * attribute must be set to a {@link Node} which supports the evaluated execution with the
+ * number of {@link #executeWith()} arguments that are defined. For example if this child is
+ * executed with one argument, the {@link #type()} attribute must define a node which publicly
+ * declares a method with the signature Object execute*(VirtualFrame, Object)
.
*/
String[] executeWith() default {};
}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java Fri Jun 21 17:52:19 2013 +0200
@@ -24,42 +24,56 @@
import java.lang.annotation.*;
+import com.oracle.truffle.api.nodes.*;
+
/**
*
- * Annotates a type system class that represents type information for a node. Generates code for
- * converting and managing types. Methods contained in the type system may be annotated with
- * {@link TypeCast} or {@link TypeCheck}. These methods alter the default behavior of the type
- * system.
+ * Each {@link Node} has one {@link TypeSystem} at its root to define the types that can be used
+ * throughout the system. Multiple {@link TypeSystem}s are allowed, but they cannot be mixed inside
+ * a single {@link Node} hierarchy. A {@link TypeSystem} defines a list of types as its child
+ * elements, in which every type precedes its super types.The latter condition ensures that the most
+ * concrete type is found first when searching the list sequentially for the type of a given generic
+ * value.
*
*
- *
- * Example:
*
- * Shows a @TypeSystem
definition with three types. In this example BigIntegers can be
- * also treated as integers if their bit width is less than 32.
+ * Each {@link #value()} is represented as a java type. A type can specify two annotations:
+ * {@link TypeCheck} and {@link TypeCast}. The {@link TypeCheck} checks whether a given generic
+ * value matches to the current type. The {@link TypeCast} casts a generic type value to the current
+ * type. If the {@link TypeCheck} and {@link TypeCast} annotations are not declared in the
+ * {@link TypeSystem} the a default implementation is provided. The default implementation of
+ * {@link TypeCheck} returns true
only on an exact type match and {@link TypeCast} is
+ * only a cast to this type. Specified methods with {@link TypeCheck} and {@link TypeCast} may be
+ * used to extend the definition of a type in the language. In our example, the
+ * isInteger
and asInteger
methods are defined in a way so that they
+ * accept also {@link Integer} values, implicitly converting them to {@link Double} . This example
+ * points out how we express implicit type conversions.
*
*
+ *
+ * Example: The {@link TypeSystem} contains the types {@link Boolean}, {@link Integer}, and
+ * {@link Double}. The type {@link Object} is always used implicitly as the generic type represent
+ * all values.
+ *
*
*
- * {@literal @}TypeSystem(types = {int.class, BigInteger.class, String.class}, nodeBaseClass = TypedNode.class)
- * public abstract class Types {
+ * {@literal @}TypeSystem(types = {boolean.class, int.class, double.class})
+ * public abstract class ExampleTypeSystem {
*
* {@literal @}TypeCheck
* public boolean isInteger(Object value) {
- * return value instanceof Integer || (value instanceof BigInteger && ((BigInteger) value).bitLength() < Integer.SIZE);
+ * return value instanceof Integer || value instanceof Double;
* }
*
* {@literal @}TypeCast
- * public int asInteger(Object value) {
- * if (value instanceof Integer) {
- * return (int) value;
- * } else {
- * return ((BigInteger) value).intValue();
- * }
+ * public double asInteger(Object value) {
+ * return ((Number)value).doubleValue();
* }
* }
*
*
+ *
+ *
* @see TypeCast
* @see TypeCheck
*/
@@ -68,8 +82,7 @@
public @interface TypeSystem {
/**
- * Sets the types contained by this type system. The order of types also determines the order of
- * specialization.
+ * The list of types as child elements of the {@link TypeSystem}. Each precedes its super type.
*/
Class[] value();
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystemReference.java
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystemReference.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystemReference.java Fri Jun 21 17:52:19 2013 +0200
@@ -24,10 +24,20 @@
import java.lang.annotation.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * References a {@link TypeSystem} on a node. Must be applied on a {@link Node} class. At least one
+ * {@link TypeSystem} must be referenced in a {@link Node}'s type hierarchy.
+ *
+ * @see TypeSystem
+ * @see Node
+ */
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE})
public @interface TypeSystemReference {
+ /** The {@link TypeSystem} java type. */
Class> value();
}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Fri Jun 21 17:52:19 2013 +0200
@@ -583,8 +583,13 @@
List extends AnnotationValue> values = getAnnotationValue(List.class, mirror, name);
List result = new ArrayList<>();
- for (AnnotationValue value : values) {
- result.add(resolveAnnotationValue(expectedListType, value));
+ if (values != null) {
+ for (AnnotationValue value : values) {
+ T annotationValue = resolveAnnotationValue(expectedListType, value);
+ if (annotationValue != null) {
+ result.add(annotationValue);
+ }
+ }
}
return result;
}
@@ -595,6 +600,10 @@
@SuppressWarnings({"unchecked"})
private static T resolveAnnotationValue(Class expectedType, AnnotationValue value) {
+ if (value == null) {
+ return null;
+ }
+
Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null);
if (unboxedValue != null) {
if (expectedType == TypeMirror.class && unboxedValue instanceof String) {
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Fri Jun 21 17:52:19 2013 +0200
@@ -563,7 +563,7 @@
public ExecutableElement findMethod() {
Element element = currentElement;
- while (element != null && (element.getKind() != ElementKind.METHOD)) {
+ while (element != null && (element.getKind() != ElementKind.METHOD && (element.getKind() != ElementKind.CONSTRUCTOR))) {
element = element.getEnclosingElement();
}
ExecutableElement found = element != null ? (ExecutableElement) element : null;
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionCodeElementFactory.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionCodeElementFactory.java Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.codegen.processor.ext;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.api.element.*;
-import com.oracle.truffle.codegen.processor.ast.*;
-
-final class ExtensionCodeElementFactory implements WritableElementFactory {
-
- private final ProcessorContext context;
-
- Element generatorElement;
- AnnotationMirror generatorAnnotationMirror;
-
- public ExtensionCodeElementFactory(ProcessorContext context) {
- this.context = context;
- }
-
- @Override
- public WritableExecutableElement cloneExecutableElement(ExecutableElement method) {
- return updateGenerators(CodeExecutableElement.clone(context.getEnvironment(), method));
- }
-
- @Override
- public WritableVariableElement cloneVariableElement(VariableElement var) {
- return updateGenerators(CodeVariableElement.clone(var));
- }
-
- @Override
- public WritableAnnotationMirror cloneAnnotationMirror(AnnotationMirror mirror) {
- return CodeAnnotationMirror.clone(mirror);
- }
-
- @Override
- public WritableVariableElement createParameter(TypeMirror type, String simpleName) {
- return updateGenerators(new CodeVariableElement(Utils.modifiers(), type, simpleName));
- }
-
- @Override
- public WritableExecutableElement createExecutableElement(TypeMirror returnType, String methodName) {
- return updateGenerators(new CodeExecutableElement(returnType, methodName));
- }
-
- @Override
- public TypeMirror createTypeMirror(Class> javaClass) {
- return context.getType(javaClass);
- }
-
- @Override
- public WritableAnnotationMirror createAnnotationMirror(DeclaredType typeMirror) {
- return new CodeAnnotationMirror(typeMirror);
- }
-
- @Override
- public Name createName(String name) {
- return CodeNames.of(name);
- }
-
- @Override
- public AnnotationValue createAnnotationValue(Object value) {
- return new CodeAnnotationValue(value);
- }
-
- private E updateGenerators(E element) {
- element.setGeneratorElement(generatorElement);
- element.setGeneratorAnnotationMirror(generatorAnnotationMirror);
- return element;
- }
-
-}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionContextImpl.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionContextImpl.java Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.codegen.processor.ext;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-
-import com.oracle.truffle.codegen.processor.api.*;
-import com.oracle.truffle.codegen.processor.api.element.*;
-
-public class ExtensionContextImpl implements ExtensionContext {
-
- private final ProcessingEnvironment env;
- private final RoundEnvironment round;
- private final WritableElementFactory factory;
-
- private final List elements = new ArrayList<>();
-
- public ExtensionContextImpl(ProcessingEnvironment env, RoundEnvironment round, WritableElementFactory factory) {
- this.env = env;
- this.round = round;
- this.factory = factory;
- }
-
- List returnElements() {
- List returnElements = new ArrayList<>(this.elements);
- this.elements.clear();
- return returnElements;
- }
-
- @Override
- public ProcessingEnvironment getProcessingEnvironment() {
- return env;
- }
-
- @Override
- public RoundEnvironment getRoundEnvironment() {
- return round;
- }
-
- @Override
- public WritableElementFactory getElementFactory() {
- return factory;
- }
-
- @Override
- public void addGeneratedElement(WritableElement element) {
- elements.add(element);
- }
-
- @Override
- public void removeGeneratedElement(WritableElement element) {
- elements.remove(element);
- }
-
-}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java Fri Jun 21 17:52:08 2013 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.codegen.processor.ext;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.api.codegen.*;
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.api.*;
-import com.oracle.truffle.codegen.processor.api.element.*;
-import com.oracle.truffle.codegen.processor.template.*;
-
-public class ExtensionParser {
-
- private final Map extensions = new HashMap<>();
- private final ProcessorContext context;
- private final ExtensionCodeElementFactory factory;
- private final ExtensionContextImpl extensionContext;
-
- public ExtensionParser(ProcessorContext context) {
- this.context = context;
- this.factory = new ExtensionCodeElementFactory(context);
- this.extensionContext = new ExtensionContextImpl(context.getEnvironment(), null, factory);
- }
-
- public List parseAll(Template template, List extends Element> elements) {
- List generatedMethods = new ArrayList<>();
- parseElement(template, generatedMethods, template.getTemplateType());
-
- List extends ExecutableElement> methods = ElementFilter.methodsIn(elements);
- for (ExecutableElement method : methods) {
- for (VariableElement var : method.getParameters()) {
- parseElement(template, generatedMethods, var);
- }
- parseElement(template, generatedMethods, method);
- }
-
- return generatedMethods;
- }
-
- private void parseElement(Template template, List elements, Element element) {
- List extends AnnotationMirror> mirrors = element.getAnnotationMirrors();
- for (AnnotationMirror mirror : mirrors) {
- ExtensionProcessor processor = findProcessor(template, mirror);
- if (processor != null) {
- try {
- factory.generatorAnnotationMirror = mirror;
- factory.generatorElement = element;
- processor.process(extensionContext, mirror, element);
- elements.addAll(extensionContext.returnElements());
- } catch (Throwable e) {
- template.addError("Processor for '%s' failed with exception: \n\n%s.", Utils.getQualifiedName(mirror.getAnnotationType()), Utils.printException(e));
- } finally {
- factory.generatorAnnotationMirror = null;
- factory.generatorElement = null;
- }
- }
- }
- }
-
- private ExtensionProcessor findProcessor(Template template, AnnotationMirror mirror) {
- String processorName = Utils.getQualifiedName(mirror.getAnnotationType());
- ExtensionProcessor processor = null;
- if (extensions.containsKey(processorName)) {
- processor = extensions.get(processorName);
- } else {
- AnnotationMirror foundExtension = Utils.findAnnotationMirror(context.getEnvironment(), mirror.getAnnotationType().asElement(), ExtensionAnnotation.class);
- if (foundExtension != null) {
- String className = Utils.getAnnotationValue(String.class, foundExtension, "processorClassName");
- Class> processorClass;
- try {
- processorClass = Class.forName(className);
- } catch (ClassNotFoundException e) {
- template.addError("Could not find processor class '%s' configured in '@%s'.", className, processorName);
- return null;
- }
- try {
- processor = (ExtensionProcessor) processorClass.newInstance();
- } catch (InstantiationException e) {
- template.addError("Could not instantiate processor class '%s' configured in '@%s'.", className, processorName);
- return null;
- } catch (IllegalAccessException e) {
- template.addError("Could not access processor class '%s' configured in '@%s'.", className, processorName);
- return null;
- } catch (ClassCastException e) {
- template.addError("Processor class '%s' configured in '@%s' does not implement '%s'.", className, processorName, ExtensionProcessor.class.getName());
- return null;
- }
- }
- extensions.put(processorName, processor);
- }
- return processor;
- }
-
-}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastData.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastData.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.node;
+
+import java.util.*;
+
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class CreateCastData extends TemplateMethod {
+
+ private final List childNames;
+
+ public CreateCastData(TemplateMethod method, List childNames) {
+ super(method);
+ this.childNames = childNames;
+ }
+
+ public List getChildNames() {
+ return childNames;
+ }
+
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastParser.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastParser.java Fri Jun 21 17:52:19 2013 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.node;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class CreateCastParser extends NodeMethodParser {
+
+ public CreateCastParser(ProcessorContext context, NodeData operation) {
+ super(context, operation);
+ }
+
+ @Override
+ public Class extends Annotation> getAnnotationType() {
+ return CreateCast.class;
+ }
+
+ @Override
+ public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+ List childNames = Utils.getAnnotationValueList(String.class, mirror, "value");
+ TypeMirror baseType = getContext().getTruffleTypes().getNode();
+ for (String childName : childNames) {
+ NodeChildData child = getNode().findChild(childName);
+ if (child != null) {
+ baseType = child.getOriginalType();
+ break;
+ }
+ }
+ MethodSpec spec = new MethodSpec(new InheritsParameterSpec(getContext(), "child", baseType));
+ addDefaultFieldMethodSpec(method, spec);
+ spec.addRequired(new ParameterSpec("castedChild", baseType)).setSignature(true);
+ return spec;
+ }
+
+ @Override
+ public CreateCastData create(TemplateMethod method) {
+ AnnotationMirror mirror = method.getMarkerAnnotation();
+ List childNames = Utils.getAnnotationValueList(String.class, mirror, "value");
+ CreateCastData cast = new CreateCastData(method, childNames);
+ AnnotationValue value = Utils.getAnnotationValue(mirror, "value");
+ TypeMirror type = null;
+ if (childNames == null || childNames.isEmpty()) {
+ cast.addError(value, "No value specified but required.");
+ return cast;
+ }
+
+ for (String childName : childNames) {
+ NodeChildData child = getNode().findChild(childName);
+ if (child == null) {
+ // error
+ cast.addError(value, "Specified child '%s' not found.", childName);
+ continue;
+ }
+ if (type == null) {
+ type = child.getNodeType();
+ } else if (!Utils.typeEquals(type, child.getNodeType())) {
+ cast.addError(value, "All child nodes for a cast must have the same node type.");
+ continue;
+ }
+ }
+ return cast;
+ }
+
+ private static class InheritsParameterSpec extends ParameterSpec {
+
+ private final ProcessorContext context;
+
+ public InheritsParameterSpec(ProcessorContext context, String name, TypeMirror... allowedTypes) {
+ super(name, Arrays.asList(allowedTypes));
+ this.context = context;
+ }
+
+ @Override
+ public boolean matches(TypeMirror actualType) {
+ boolean found = false;
+ for (TypeMirror specType : getAllowedTypes()) {
+ if (Utils.isAssignable(context, actualType, specType)) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+ }
+ }
+}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java Fri Jun 21 17:52:19 2013 +0200
@@ -54,6 +54,7 @@
private final String name;
private final TypeMirror type;
+ private final TypeMirror originalType;
private final Element accessElement;
private final Cardinality cardinality;
@@ -63,11 +64,13 @@
private NodeData nodeData;
- public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, Element accessElement, Cardinality cardinality, ExecutionKind executionKind) {
+ public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality,
+ ExecutionKind executionKind) {
this.sourceElement = sourceElement;
this.sourceAnnotationMirror = sourceMirror;
this.name = name;
this.type = nodeType;
+ this.originalType = originalNodeType;
this.accessElement = accessElement;
this.cardinality = cardinality;
this.executionKind = executionKind;
@@ -101,6 +104,10 @@
return nodeData.getExecutableTypes(getExecuteWith().size());
}
+ public TypeMirror getOriginalType() {
+ return originalType;
+ }
+
@Override
public Element getMessageElement() {
return sourceElement;
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Fri Jun 21 17:52:19 2013 +0200
@@ -143,7 +143,8 @@
}
}
- private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) {
+ private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName,
+ String... customSignatureValueNames) {
CodeTreeBuilder builder = parent.create();
boolean castedValues = sourceMethod != targetMethod;
@@ -199,8 +200,13 @@
}
builder.startCall(method.getSimpleName().toString());
+ int signatureIndex = 0;
+
for (ActualParameter targetParameter : targetMethod.getParameters()) {
- ActualParameter valueParameter = sourceMethod.findParameter(targetParameter.getLocalName());
+ ActualParameter valueParameter = null;
+ if (sourceMethod != null) {
+ valueParameter = sourceMethod.findParameter(targetParameter.getLocalName());
+ }
if (valueParameter == null) {
valueParameter = targetParameter;
}
@@ -215,7 +221,10 @@
valueType = valueParameter.getTypeSystemType();
}
- if (targetParameter.getSpecification().isLocal()) {
+ if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) {
+ builder.string(customSignatureValueNames[signatureIndex]);
+ signatureIndex++;
+ } else if (targetParameter.getSpecification().isLocal()) {
builder.startGroup();
if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) {
builder.string(THIS_NODE_LOCAL_VAR_NAME).string(".");
@@ -522,8 +531,25 @@
return builder.getRoot();
}
- private void emitEncounteredSynthetic(CodeTreeBuilder builder) {
- builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end();
+ private void emitEncounteredSynthetic(CodeTreeBuilder builder, SpecializationData current) {
+ builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class));
+ builder.startGroup();
+ String sep = null;
+ for (ActualParameter parameters : current.getParameters()) {
+ if (parameters.getSpecification().isSignature()) {
+ if (sep == null) {
+ builder.doubleQuote("Unsupported values: " + parameters.getLocalName() + " = ");
+ sep = ", ";
+ } else {
+ builder.string(" + ");
+ builder.doubleQuote(sep + parameters.getLocalName() + " = ");
+ }
+ builder.string(" + ");
+ builder.string(parameters.getLocalName());
+ }
+ }
+ builder.end();
+ builder.end().end();
}
private static List findUserConstructors(TypeMirror nodeType) {
@@ -669,7 +695,12 @@
}
for (VariableElement var : type.getFields()) {
- method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
+ NodeChildData child = getModel().findChild(var.getSimpleName().toString());
+ if (child != null) {
+ method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
+ } else {
+ method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
+ }
}
if (superConstructor != null) {
@@ -682,14 +713,25 @@
for (VariableElement var : type.getFields()) {
builder.startStatement();
- String varName = var.getSimpleName().toString();
- builder.string("this.").string(varName);
+ String fieldName = var.getSimpleName().toString();
+
+ CodeTree fieldInit = CodeTreeBuilder.singleString(var.getSimpleName().toString());
+ builder.string("this.").string(var.getSimpleName().toString());
+
+ NodeChildData child = getModel().findChild(fieldName);
+ if (child != null) {
+ CreateCastData createCast = getModel().findCast(child.getName());
+ if (createCast != null) {
+ fieldInit = createTemplateMethodCall(builder, null, getModel().getGenericSpecialization(), createCast, null, child.getName());
+ }
+ }
+
if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
- builder.string(" = adoptChild(").string(varName).string(")");
+ builder.string(" = adoptChild(").tree(fieldInit).string(")");
} else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
- builder.string(" = adoptChildren(").string(varName).string(")");
+ builder.string(" = adoptChildren(").tree(fieldInit).string(")");
} else {
- builder.string(" = ").string(varName);
+ builder.string(" = ").tree(fieldInit);
}
builder.end();
}
@@ -832,7 +874,7 @@
unreachableSpecializations.add(specialization);
} else {
filteredSpecializations.add(specialization);
- if (!specialization.isUninitialized() && !specialization.hasRewrite(getContext())) {
+ if (!specialization.isUninitialized() && specialization.isGenericSpecialization(getContext())) {
unreachable = true;
}
}
@@ -877,7 +919,7 @@
}
if (specialize && executeCall == null && !current.getNode().getGenericSpecialization().isUseSpecializationsForGeneric()) {
- emitEncounteredSynthetic(builder);
+ emitEncounteredSynthetic(builder, current);
} else if (specialize) {
if (current.getNode().getGenericSpecialization().isUseSpecializationsForGeneric()) {
@@ -890,7 +932,7 @@
}
builder.statement("resultIsSet = true");
} else {
- emitEncounteredSynthetic(builder);
+ emitEncounteredSynthetic(builder, current);
}
builder.end();
}
@@ -922,7 +964,7 @@
}
} else {
if (executeCall == null) {
- emitEncounteredSynthetic(builder);
+ emitEncounteredSynthetic(builder, current);
} else {
builder.startReturn().tree(executeCall).end();
}
@@ -1165,7 +1207,7 @@
CodeTreeBuilder builder = method.createBuilder();
if (!node.needsRewrites(getContext())) {
- builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end();
+ builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).doubleQuote("No specialized version.").end().end();
} else {
builder.startIf();
builder.string("types.length == 1");
@@ -1668,7 +1710,7 @@
returnBuilder.doubleQuote("Uninitialized");
returnBuilder.end();
} else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
- emitEncounteredSynthetic(builder);
+ emitEncounteredSynthetic(builder, specialization);
} else if (specialization.isGeneric()) {
returnBuilder.startCall("super", EXECUTE_GENERIC_NAME);
addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Fri Jun 21 17:52:19 2013 +0200
@@ -50,6 +50,7 @@
private Map> executableTypes;
private List shortCircuits;
private List assumptions;
+ private List casts;
private String shortName;
@@ -74,6 +75,14 @@
this.assumptions = splitSource.assumptions;
}
+ public List getCasts() {
+ return casts;
+ }
+
+ void setCasts(List casts) {
+ this.casts = casts;
+ }
+
void setShortName(String shortName) {
this.shortName = shortName;
}
@@ -133,6 +142,9 @@
if (fields != null) {
containerChildren.addAll(fields);
}
+ if (casts != null) {
+ containerChildren.addAll(casts);
+ }
return containerChildren;
}
@@ -230,6 +242,9 @@
methods.addAll(getSpecializationListeners());
methods.addAll(getExecutableTypes());
methods.addAll(getShortCircuits());
+ if (getCasts() != null) {
+ methods.addAll(getCasts());
+ }
return methods;
}
@@ -367,6 +382,7 @@
dumpProperty(builder, indent, "executableTypes", getExecutableTypes());
dumpProperty(builder, indent, "specializations", getSpecializations());
dumpProperty(builder, indent, "assumptions", getAssumptions());
+ dumpProperty(builder, indent, "casts", getCasts());
dumpProperty(builder, indent, "messages", collectMessages());
if (getDeclaredNodes().size() > 0) {
builder.append(String.format("\n%s children = [", indent));
@@ -489,4 +505,15 @@
return getClass().getSimpleName() + "[" + getNodeId() + "]";
}
+ public CreateCastData findCast(String name) {
+ if (getCasts() != null) {
+ for (CreateCastData cast : getCasts()) {
+ if (cast.getChildNames().contains(name)) {
+ return cast;
+ }
+ }
+ }
+ return null;
+ }
+
}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Fri Jun 21 17:52:19 2013 +0200
@@ -78,20 +78,15 @@
protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) {
MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec());
- if (getNode().supportsFrame()) {
- methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame()));
- }
-
- resolveAndAddImplicitThis(methodSpec, method);
+ addDefaultFrame(methodSpec);
+ addDefaultImplicitThis(method, methodSpec);
+ addDefaultFieldMethodSpec(method, methodSpec);
+ addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec);
- for (NodeFieldData field : getNode().getFields()) {
- if (!Utils.isFieldAccessible(method, field.getVariable())) {
- ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
- spec.setLocal(true);
- methodSpec.addOptional(spec);
- }
- }
+ return methodSpec;
+ }
+ private void addDefaultChildren(boolean shortCircuitsEnabled, String shortCircuitName, MethodSpec methodSpec) {
// children are null when parsing executable types
if (getNode().getChildren() != null) {
for (NodeChildData child : getNode().getChildren()) {
@@ -117,11 +112,25 @@
}
}
}
+ }
- return methodSpec;
+ private void addDefaultFrame(MethodSpec methodSpec) {
+ if (getNode().supportsFrame()) {
+ methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame()));
+ }
}
- protected void resolveAndAddImplicitThis(MethodSpec methodSpec, ExecutableElement method) {
+ protected void addDefaultFieldMethodSpec(ExecutableElement method, MethodSpec methodSpec) {
+ for (NodeFieldData field : getNode().getFields()) {
+ if (!Utils.isFieldAccessible(method, field.getVariable())) {
+ ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
+ spec.setLocal(true);
+ methodSpec.addOptional(spec);
+ }
+ }
+ }
+
+ protected void addDefaultImplicitThis(ExecutableElement method, MethodSpec methodSpec) {
TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType();
if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(getContext(), declaredType, getContext().getTruffleTypes().getNode())) {
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Fri Jun 21 17:52:19 2013 +0200
@@ -42,7 +42,7 @@
public class NodeParser extends TemplateParser {
public static final List> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class,
- ExecuteChildren.class, NodeClass.class, NodeChild.class, NodeChildren.class, NodeId.class);
+ NodeClass.class, NodeChild.class, NodeChildren.class, NodeId.class);
private Map parsedNodes;
@@ -211,6 +211,7 @@
private static List splitNodeData(NodeData node) {
SortedMap> groupedSpecializations = groupByNodeId(node.getSpecializations());
SortedMap> groupedListeners = groupByNodeId(node.getSpecializationListeners());
+ SortedMap> groupedCasts = groupByNodeId(node.getCasts());
Set ids = new TreeSet<>();
ids.addAll(groupedSpecializations.keySet());
@@ -220,6 +221,7 @@
for (String id : ids) {
List specializations = groupedSpecializations.get(id);
List listeners = groupedListeners.get(id);
+ List casts = groupedCasts.get(id);
if (specializations == null) {
specializations = new ArrayList<>();
@@ -238,12 +240,14 @@
copy.setSpecializations(specializations);
copy.setSpecializationListeners(listeners);
+ copy.setCasts(casts);
splitted.add(copy);
}
node.setSpecializations(new ArrayList());
node.setSpecializationListeners(new ArrayList());
+ node.setCasts(new ArrayList());
return splitted;
}
@@ -266,6 +270,7 @@
node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements));
List generics = new GenericParser(context, node).parse(elements);
List specializations = new SpecializationMethodParser(context, node).parse(elements);
+ node.setCasts(new CreateCastParser(context, node).parse(elements));
List allSpecializations = new ArrayList<>();
allSpecializations.addAll(generics);
@@ -736,6 +741,18 @@
shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
}
}
+ Map castNodeTypes = new HashMap<>();
+ for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+ AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, CreateCast.class);
+ if (mirror != null) {
+ List children = (Utils.getAnnotationValueList(String.class, mirror, "value"));
+ if (children != null) {
+ for (String child : children) {
+ castNodeTypes.put(child, method.getReturnType());
+ }
+ }
+ }
+ }
List parsedChildren = new ArrayList<>();
List typeHierarchyReversed = new ArrayList<>(typeHierarchy);
@@ -754,8 +771,12 @@
}
List children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
+ int index = 0;
for (AnnotationMirror childMirror : children) {
String name = Utils.getAnnotationValue(String.class, childMirror, "value");
+ if (name.equals("")) {
+ name = "child" + index;
+ }
Cardinality cardinality = Cardinality.ONE;
@@ -764,6 +785,12 @@
cardinality = Cardinality.MANY;
}
+ TypeMirror originalChildType = childType;
+ TypeMirror castNodeType = castNodeTypes.get(name);
+ if (castNodeType != null) {
+ childType = castNodeType;
+ }
+
Element getter = findGetter(elements, name, childType);
ExecutionKind kind = ExecutionKind.DEFAULT;
@@ -771,7 +798,7 @@
kind = ExecutionKind.SHORT_CIRCUIT;
}
- NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, getter, cardinality, kind);
+ NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality, kind);
parsedChildren.add(nodeChild);
@@ -785,7 +812,9 @@
if (fieldNodeData == null) {
nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(childType));
}
+
}
+ index++;
}
List filteredChildren = new ArrayList<>();
@@ -877,7 +906,7 @@
}
for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
- if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.typeEquals(method.getReturnType(), type)) {
+ if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.isAssignable(context, type, method.getReturnType())) {
return method;
}
}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Fri Jun 21 17:52:19 2013 +0200
@@ -74,6 +74,24 @@
return sinks;
}
+ public boolean isGenericSpecialization(ProcessorContext context) {
+ if (hasRewrite(context)) {
+ return false;
+ }
+
+ for (ActualParameter parameter : getParameters()) {
+ NodeChildData child = getNode().findChild(parameter.getSpecification().getName());
+ if (child == null) {
+ continue;
+ }
+ if (!parameter.getTypeSystemType().isGeneric()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
public boolean hasRewrite(ProcessorContext context) {
if (!getExceptions().isEmpty()) {
return true;
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java Fri Jun 21 17:52:19 2013 +0200
@@ -28,19 +28,11 @@
import javax.lang.model.util.*;
import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.ext.*;
public abstract class TemplateParser extends AbstractParser {
- private final ExtensionParser extensionParser;
-
public TemplateParser(ProcessorContext c) {
super(c);
- extensionParser = new ExtensionParser(c);
- }
-
- public ExtensionParser getExtensionParser() {
- return extensionParser;
}
protected void verifyExclusiveMethodAnnotation(Template template, Class>... annotationTypes) {
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java Fri Jun 21 17:52:19 2013 +0200
@@ -103,8 +103,6 @@
}
}
- clazz.getEnclosedElements().addAll(typeSystem.getExtensionElements());
-
return clazz;
}
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java Fri Jun 21 17:52:19 2013 +0200
@@ -84,10 +84,6 @@
verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
- typeSystem.setExtensionElements(getExtensionParser().parseAll(typeSystem, elements));
- if (typeSystem.getExtensionElements() != null) {
- elements.addAll(typeSystem.getExtensionElements());
- }
List casts = new TypeCastParser(context, typeSystem).parse(elements);
List checks = new TypeCheckParser(context, typeSystem).parse(elements);
diff -r 0d40e1cf70db -r 55827d611da7 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java Fri Jun 21 17:52:08 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java Fri Jun 21 17:52:19 2013 +0200
@@ -26,7 +26,7 @@
import com.oracle.truffle.api.codegen.*;
-@NodeChild(value = "expression", type = TypedNode.class)
+@NodeChild(type = TypedNode.class)
public abstract class PrintNode extends StatementNode {
private final PrintStream output;
diff -r 0d40e1cf70db -r 55827d611da7 mx/commands.py
--- a/mx/commands.py Fri Jun 21 17:52:08 2013 +0200
+++ b/mx/commands.py Fri Jun 21 17:52:19 2013 +0200
@@ -54,6 +54,8 @@
_jacoco = 'off'
+_workdir = None
+
_native_dbg = None
_make_eclipse_launch = False
@@ -645,6 +647,11 @@
if vm is None:
vm = _vm
+ if cwd is None:
+ cwd = _workdir
+ elif _workdir is not None:
+ mx.abort("conflicting working directories: do not set --workdir for this command")
+
build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product'
jdk = _jdk(build, vmToCheck=vm)
mx.expand_project_in_args(args)
@@ -1267,7 +1274,6 @@
'--dot-output-base', 'projects'] + args)
def mx_init():
- _vmbuild = 'product'
commands = {
'build': [build, '[-options]'],
'buildvars': [buildvars, ''],
@@ -1298,6 +1304,7 @@
}
mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append'])
+ mx.add_argument('--workdir', help='runs the VM in the given directory', default=None)
if (_vmSourcesAvailable):
mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=_vmChoices, help='the VM to build/run (default: ' + _vmChoices[0] + ')')
@@ -1330,6 +1337,8 @@
_make_eclipse_launch = getattr(opts, 'make_eclipse_launch', False)
global _jacoco
_jacoco = opts.jacoco
+ global _workdir
+ _workdir = opts.workdir
global _native_dbg
_native_dbg = opts.native_dbg
diff -r 0d40e1cf70db -r 55827d611da7 mx/projects
--- a/mx/projects Fri Jun 21 17:52:08 2013 +0200
+++ b/mx/projects Fri Jun 21 17:52:19 2013 +0200
@@ -141,7 +141,7 @@
# graal.hotspot.test
project@com.oracle.graal.hotspot.test@subDir=graal
project@com.oracle.graal.hotspot.test@sourceDirs=src
-project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test
+project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test,com.oracle.graal.hotspot
project@com.oracle.graal.hotspot.test@checkstyle=com.oracle.graal.graph
project@com.oracle.graal.hotspot.test@javaCompliance=1.7
project@com.oracle.graal.hotspot.test@workingSets=Graal,HotSpot,Test
@@ -260,7 +260,7 @@
# graal.replacements.test
project@com.oracle.graal.replacements.test@subDir=graal
project@com.oracle.graal.replacements.test@sourceDirs=src
-project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.compiler.test
+project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.compiler.test,com.oracle.graal.replacements
project@com.oracle.graal.replacements.test@checkstyle=com.oracle.graal.graph
project@com.oracle.graal.replacements.test@javaCompliance=1.7
project@com.oracle.graal.replacements.test@workingSets=Graal,Replacements,Test
@@ -404,7 +404,7 @@
# graal.compiler.test
project@com.oracle.graal.compiler.test@subDir=graal
project@com.oracle.graal.compiler.test@sourceDirs=src
-project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.hotspot
+project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.printer
project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph
project@com.oracle.graal.compiler.test@javaCompliance=1.7
project@com.oracle.graal.compiler.test@workingSets=Graal,Test
diff -r 0d40e1cf70db -r 55827d611da7 src/share/vm/graal/graalCompilerToVM.cpp
--- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Jun 21 17:52:08 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp Fri Jun 21 17:52:19 2013 +0200
@@ -871,6 +871,8 @@
set_int("g1SATBQueueMarkingOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()));
set_int("g1SATBQueueIndexOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_index()));
set_int("g1SATBQueueBufferOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_buf()));
+ set_address("writeBarrierPreAddress", GraalRuntime::write_barrier_pre);
+ set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post);
BarrierSet* bs = Universe::heap()->barrier_set();
switch (bs->kind()) {
diff -r 0d40e1cf70db -r 55827d611da7 src/share/vm/graal/graalRuntime.cpp
--- a/src/share/vm/graal/graalRuntime.cpp Fri Jun 21 17:52:08 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp Fri Jun 21 17:52:19 2013 +0200
@@ -358,6 +358,14 @@
}
JRT_END
+JRT_LEAF(void, GraalRuntime::write_barrier_pre(JavaThread* thread, oopDesc* obj))
+ thread->satb_mark_queue().enqueue(obj);
+JRT_END
+
+JRT_LEAF(void, GraalRuntime::write_barrier_post(JavaThread* thread, void* card_addr))
+ thread->dirty_card_queue().enqueue(card_addr);
+JRT_END
+
JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, oop where, oop format, jlong value))
ResourceMark rm;
assert(where == NULL || java_lang_String::is_instance(where), "must be");
diff -r 0d40e1cf70db -r 55827d611da7 src/share/vm/graal/graalRuntime.hpp
--- a/src/share/vm/graal/graalRuntime.hpp Fri Jun 21 17:52:08 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp Fri Jun 21 17:52:19 2013 +0200
@@ -52,6 +52,8 @@
LOG_OBJECT_ADDRESS = 0x04
};
static void log_object(JavaThread* thread, oop msg, jint flags);
+ static void write_barrier_pre(JavaThread* thread, oopDesc* obj);
+ static void write_barrier_post(JavaThread* thread, void* card);
};
#endif // SHARE_VM_GRAAL_GRAAL_RUNTIME_HPP