# HG changeset patch # User iveresov # Date 1517621297 28800 # Node ID 47f19ff9903c2a7b4729e2a4213f53886266e6b9 # Parent 5bce1b7e780098d3783a6a0dd925a1a56a98b0d9 8194819: Update Graal Reviewed-by: kvn diff -r 5bce1b7e7800 -r 47f19ff9903c make/CompileJavaModules.gmk --- a/make/CompileJavaModules.gmk Fri Feb 02 10:37:48 2018 -0500 +++ b/make/CompileJavaModules.gmk Fri Feb 02 17:28:17 2018 -0800 @@ -493,6 +493,7 @@ # jdk.internal.vm.compiler_EXCLUDES += \ + org.graalvm.collections.test \ org.graalvm.compiler.core.match.processor \ org.graalvm.compiler.nodeinfo.processor \ org.graalvm.compiler.options.processor \ @@ -511,6 +512,7 @@ org.graalvm.compiler.graph.test \ org.graalvm.compiler.hotspot.amd64.test \ org.graalvm.compiler.hotspot.lir.test \ + org.graalvm.compiler.hotspot.sparc.test \ org.graalvm.compiler.hotspot.test \ org.graalvm.compiler.jtt \ org.graalvm.compiler.lir.jtt \ diff -r 5bce1b7e7800 -r 47f19ff9903c make/CompileToolsHotspot.gmk --- a/make/CompileToolsHotspot.gmk Fri Feb 02 10:37:48 2018 -0500 +++ b/make/CompileToolsHotspot.gmk Fri Feb 02 17:28:17 2018 -0800 @@ -48,6 +48,7 @@ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ $(SRC_DIR)/org.graalvm.word/src \ + $(SRC_DIR)/org.graalvm.collections/src \ $(SRC_DIR)/org.graalvm.compiler.core/src \ $(SRC_DIR)/org.graalvm.compiler.core.common/src \ $(SRC_DIR)/org.graalvm.compiler.core.match.processor/src \ @@ -101,6 +102,7 @@ $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_OPTIONS_PROCESSOR, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ + $(SRC_DIR)/org.graalvm.collections/src \ $(SRC_DIR)/org.graalvm.compiler.options/src \ $(SRC_DIR)/org.graalvm.compiler.options.processor/src \ $(SRC_DIR)/org.graalvm.util/src \ @@ -117,6 +119,7 @@ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ $(SRC_DIR)/org.graalvm.word/src \ + $(SRC_DIR)/org.graalvm.collections/src \ $(SRC_DIR)/org.graalvm.compiler.replacements.verifier/src \ $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \ $(SRC_DIR)/org.graalvm.compiler.code/src \ diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java Fri Feb 02 17:28:17 2018 -0800 @@ -143,7 +143,7 @@ int alignment = data.getAlignment(); byte[] value = new byte[size]; ByteBuffer buffer = ByteBuffer.wrap(value).order(ByteOrder.nativeOrder()); - DataSection.emit(buffer, data, p -> { + DataSection.emit(buffer, data, (p, c) -> { }); String targetSymbol = "data.M" + methodInfo.getCodeId() + "." + dataOffset; Symbol relocationSymbol = binaryContainer.getSymbol(targetSymbol); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/.mx.graal/suite.py --- a/src/jdk.internal.vm.compiler/.mx.graal/suite.py Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/.mx.graal/suite.py Fri Feb 02 17:28:17 2018 -0800 @@ -82,6 +82,24 @@ "javaCompliance" : "1.8", "workingSets" : "API,SDK", }, + "org.graalvm.collections" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "checkstyle" : "org.graalvm.word", + "javaCompliance" : "1.8", + "workingSets" : "API,SDK", + }, + "org.graalvm.collections.test" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "mx:JUNIT", + "org.graalvm.collections", + ], + "checkstyle" : "org.graalvm.word", + "javaCompliance" : "1.8", + "workingSets" : "API,SDK,Test", + }, # ------------- Graal ------------- @@ -190,6 +208,9 @@ "org.graalvm.util" : { "subDir" : "share/classes", "sourceDirs" : ["src"], + "dependencies" : [ + "org.graalvm.collections", + ], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", "workingSets" : "API,Graal", @@ -201,6 +222,7 @@ "dependencies" : [ "mx:JUNIT", "org.graalvm.util", + "org.graalvm.compiler.core.test", ], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", @@ -970,10 +992,11 @@ "workingSets" : "Graal,SPARC", }, - "org.graalvm.compiler.core.sparc.test" : { + "org.graalvm.compiler.hotspot.sparc.test" : { "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ + "org.graalvm.compiler.hotspot", "org.graalvm.compiler.lir.jtt", "JVMCI_HOTSPOT" ], @@ -1007,6 +1030,7 @@ "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ + "org.graalvm.collections", "org.graalvm.compiler.debug", "org.graalvm.word", ], @@ -1037,7 +1061,6 @@ "sourceDirs" : ["src"], "dependencies" : [ "org.graalvm.compiler.debug", - "org.graalvm.util", "mx:JUNIT", ], "checkstyle" : "org.graalvm.compiler.graph", @@ -1225,11 +1248,11 @@ "org.graalvm.compiler.asm.amd64.test", "org.graalvm.compiler.core.aarch64.test", "org.graalvm.compiler.core.amd64.test", - "org.graalvm.compiler.core.sparc.test", "org.graalvm.compiler.debug.test", "org.graalvm.compiler.hotspot.aarch64.test", "org.graalvm.compiler.hotspot.amd64.test", "org.graalvm.compiler.hotspot.lir.test", + "org.graalvm.compiler.hotspot.sparc.test", "org.graalvm.compiler.options.test", "org.graalvm.compiler.jtt", "org.graalvm.compiler.lir.jtt", diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapImplTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapImplTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections.test; + +import java.util.Arrays; +import java.util.Iterator; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.UnmodifiableEconomicSet; +import org.junit.Assert; +import org.junit.Test; + +public class EconomicMapImplTest { + + @Test(expected = UnsupportedOperationException.class) + public void testRemoveNull() { + EconomicMap map = EconomicMap.create(10); + map.removeKey(null); + } + + @Test + public void testInitFromHashSet() { + UnmodifiableEconomicSet set = new UnmodifiableEconomicSet() { + + @Override + public boolean contains(Integer element) { + return element == 0; + } + + @Override + public int size() { + return 1; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Iterator iterator() { + return new Iterator() { + + private boolean visited = false; + + @Override + public boolean hasNext() { + return !visited; + } + + @Override + public Integer next() { + if (visited) { + return null; + } else { + visited = true; + return 1; + } + } + }; + } + }; + + EconomicSet newSet = EconomicSet.create(Equivalence.DEFAULT, set); + Assert.assertEquals(newSet.size(), 1); + } + + @Test + public void testCopyHash() { + EconomicSet set = EconomicSet.create(Equivalence.IDENTITY); + set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); + EconomicSet newSet = EconomicSet.create(Equivalence.IDENTITY, set); + Assert.assertEquals(newSet.size(), 10); + newSet.remove(8); + newSet.remove(9); + Assert.assertEquals(newSet.size(), 8); + } + + @Test + public void testNewEquivalence() { + EconomicSet set = EconomicSet.create(new Equivalence() { + @Override + public boolean equals(Object a, Object b) { + return false; + } + + @Override + public int hashCode(Object o) { + return 0; + } + }); + set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); + Assert.assertTrue(set.add(new Integer(0))); + } + + @Test(expected = UnsupportedOperationException.class) + public void testMapPutNull() { + EconomicMap map = EconomicMap.create(); + map.put(null, null); + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapLargeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapLargeTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections.test; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Objects; +import java.util.Random; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.MapCursor; +import org.graalvm.collections.UnmodifiableMapCursor; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class EconomicMapLargeTest { + + @Parameter(value = 0) public EconomicMap testMap; + @Parameter(value = 1) public EconomicMap referenceMap; + @Parameter(value = 2) public String name; + + @Parameters(name = "{2}") + public static Collection data() { + return Arrays.asList(new Object[]{EconomicMap.create(Equivalence.DEFAULT), EconomicMap.create(Equivalence.DEFAULT), "EconomicMap"}, + new Object[]{EconomicMap.create(Equivalence.IDENTITY), EconomicMap.create(Equivalence.IDENTITY), "EconomicMap(IDENTITY)"}, + new Object[]{EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE), EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE), + "EconomicMap(IDENTITY_WITH_SYSTEM_HASHCODE)"}, + new Object[]{EconomicMap.create(Equivalence.DEFAULT), EconomicMap.wrapMap(new LinkedHashMap<>()), "EconomicMap<->wrapMap"}, + new Object[]{EconomicMap.wrapMap(new LinkedHashMap<>()), EconomicMap.wrapMap(new LinkedHashMap<>()), "wrapMap"}); + } + + private static int[] createRandomRange(Random random, int count) { + int[] result = new int[count]; + for (int i = 0; i < count; ++i) { + int range = random.nextInt(14); + if (range == 0 || range > 10) { + range = Integer.MAX_VALUE; + } else if (range == 10) { + range = 100; + } + result[i] = range; + } + return result; + } + + private static final class BadHashClass { + private int value; + + BadHashClass(int randomInt) { + this.value = randomInt; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public boolean equals(Object other) { + if (other instanceof BadHashClass) { + BadHashClass badHashClass = (BadHashClass) other; + return badHashClass.value == value; + } + return false; + } + } + + interface MapAction { + Object perform(EconomicMap map, int randomInt); + } + + static final Object EXISTING_VALUE = new Object(); + + static final MapAction[] INCREASE_ACTIONS = new MapAction[]{ + (map, randomInt) -> map.put(randomInt, "value"), + (map, randomInt) -> map.get(randomInt) + }; + + static final MapAction[] ACTIONS = new MapAction[]{ + (map, randomInt) -> map.removeKey(randomInt), + (map, randomInt) -> map.put(randomInt, "value"), + (map, randomInt) -> map.put(randomInt, null), + (map, randomInt) -> map.put(EXISTING_VALUE, randomInt), + (map, randomInt) -> { + if (randomInt == 0) { + map.clear(); + } + return map.isEmpty(); + }, + (map, randomInt) -> map.containsKey(randomInt), + (map, randomInt) -> map.get(randomInt), + (map, randomInt) -> map.put(new BadHashClass(randomInt), "unique"), + (map, randomInt) -> { + if (randomInt == 0) { + map.replaceAll((key, value) -> Objects.toString(value) + "!"); + } + return map.isEmpty(); + } + + }; + + @Test + public void testVeryLarge() { + testMap.clear(); + referenceMap.clear(); + + Random random = new Random(0); + for (int i = 0; i < 200000; ++i) { + for (int j = 0; j < INCREASE_ACTIONS.length; ++j) { + int nextInt = random.nextInt(10000000); + MapAction action = INCREASE_ACTIONS[j]; + Object result = action.perform(testMap, nextInt); + Object referenceResult = action.perform(referenceMap, nextInt); + Assert.assertEquals(result, referenceResult); + } + } + } + + /** + * Tests a sequence of random operations on the map. + */ + @Test + public void testAddRemove() { + testMap.clear(); + referenceMap.clear(); + + for (int seed = 0; seed < 10; ++seed) { + Random random = new Random(seed); + int[] ranges = createRandomRange(random, ACTIONS.length); + int value = random.nextInt(10000); + for (int i = 0; i < value; ++i) { + for (int j = 0; j < ACTIONS.length; ++j) { + if (random.nextInt(ranges[j]) == 0) { + int nextInt = random.nextInt(100); + MapAction action = ACTIONS[j]; + Object result = action.perform(testMap, nextInt); + Object referenceResult = action.perform(referenceMap, nextInt); + Assert.assertEquals(result, referenceResult); + if (j % 100 == 0) { + checkEquality(testMap, referenceMap); + } + } + } + + if (random.nextInt(20) == 0) { + removeElement(random.nextInt(100), testMap, referenceMap); + } + } + } + } + + private static void removeElement(int index, EconomicMap map, EconomicMap referenceMap) { + Assert.assertEquals(referenceMap.size(), map.size()); + MapCursor cursor = map.getEntries(); + MapCursor referenceCursor = referenceMap.getEntries(); + int z = 0; + while (cursor.advance()) { + Assert.assertTrue(referenceCursor.advance()); + Assert.assertEquals(referenceCursor.getKey(), cursor.getKey()); + Assert.assertEquals(referenceCursor.getValue(), cursor.getValue()); + if (index == z) { + cursor.remove(); + referenceCursor.remove(); + } + ++z; + } + + Assert.assertFalse(referenceCursor.advance()); + } + + private static void checkEquality(EconomicMap map, EconomicMap referenceMap) { + Assert.assertEquals(referenceMap.size(), map.size()); + + // Check entries. + UnmodifiableMapCursor cursor = map.getEntries(); + UnmodifiableMapCursor referenceCursor = referenceMap.getEntries(); + while (cursor.advance()) { + Assert.assertTrue(referenceCursor.advance()); + Assert.assertEquals(referenceCursor.getKey(), cursor.getKey()); + Assert.assertEquals(referenceCursor.getValue(), cursor.getValue()); + } + + // Check keys. + Iterator iterator = map.getKeys().iterator(); + Iterator referenceIterator = referenceMap.getKeys().iterator(); + while (iterator.hasNext()) { + Assert.assertTrue(referenceIterator.hasNext()); + Assert.assertEquals(iterator.next(), referenceIterator.next()); + } + + // Check values. + iterator = map.getValues().iterator(); + referenceIterator = referenceMap.getValues().iterator(); + while (iterator.hasNext()) { + Assert.assertTrue(referenceIterator.hasNext()); + Assert.assertEquals(iterator.next(), referenceIterator.next()); + } + Assert.assertFalse(referenceIterator.hasNext()); + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections.test; + +import java.util.LinkedHashMap; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.UnmodifiableEconomicMap; +import org.junit.Assert; +import org.junit.Test; + +public class EconomicMapTest { + + @Test + public void testMapGetDefault() { + EconomicMap map = EconomicMap.create(); + map.put(0, 1); + Assert.assertEquals(map.get(0, 2), Integer.valueOf(1)); + Assert.assertEquals(map.get(1, 2), Integer.valueOf(2)); + } + + @Test + public void testMapPutAll() { + EconomicMap map = EconomicMap.create(); + EconomicMap newMap = EconomicMap.wrapMap(new LinkedHashMap<>()); + newMap.put(1, 1); + newMap.put(2, 4); + map.putAll(newMap); + Assert.assertEquals(map.size(), 2); + + UnmodifiableEconomicMap unmodifiableEconomicMap = EconomicMap.create(newMap); + + map.removeKey(1); + map.put(2, 2); + map.put(3, 9); + + map.putAll(unmodifiableEconomicMap); + Assert.assertEquals(map.size(), 3); + Assert.assertEquals(map.get(2), Integer.valueOf(4)); + } + + @Test + public void testToString() { + EconomicMap map = EconomicMap.create(); + map.put(0, 0); + map.put(1, 1); + Assert.assertEquals(map.toString(), "map(size=2, {(0,0),(1,1)})"); + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicSetTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicSetTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections.test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; + +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; +import org.junit.Assert; +import org.junit.Test; + +public class EconomicSetTest { + + @Test + public void testUtilities() { + EconomicSet set = EconomicSet.create(0); + set.add(0); + Assert.assertTrue(set.add(1)); + Assert.assertEquals(set.size(), 2); + Assert.assertFalse(set.add(1)); + Assert.assertEquals(set.size(), 2); + set.remove(1); + Assert.assertEquals(set.size(), 1); + set.remove(2); + Assert.assertEquals(set.size(), 1); + Assert.assertTrue(set.add(1)); + set.clear(); + Assert.assertEquals(set.size(), 0); + } + + @Test + public void testAddAll() { + EconomicSet set = EconomicSet.create(); + set.addAll(Arrays.asList(0, 1, 0)); + Assert.assertEquals(set.size(), 2); + + EconomicSet newSet = EconomicSet.create(); + newSet.addAll(Arrays.asList(1, 2)); + Assert.assertEquals(newSet.size(), 2); + newSet.addAll(set); + Assert.assertEquals(newSet.size(), 3); + } + + @Test + public void testRemoveAll() { + EconomicSet set = EconomicSet.create(); + set.addAll(Arrays.asList(0, 1)); + + set.removeAll(Arrays.asList(1, 2)); + Assert.assertEquals(set.size(), 1); + + set.removeAll(EconomicSet.create(set)); + Assert.assertEquals(set.size(), 0); + } + + @Test + public void testRetainAll() { + EconomicSet set = EconomicSet.create(); + set.addAll(Arrays.asList(0, 1, 2)); + + EconomicSet newSet = EconomicSet.create(); + newSet.addAll(Arrays.asList(2, 3)); + + set.retainAll(newSet); + Assert.assertEquals(set.size(), 1); + } + + @Test + public void testToArray() { + EconomicSet set = EconomicSet.create(); + set.addAll(Arrays.asList(0, 1)); + Assert.assertArrayEquals(set.toArray(new Integer[2]), new Integer[]{0, 1}); + } + + @Test + public void testToString() { + EconomicSet set = EconomicSet.create(); + set.addAll(Arrays.asList(0, 1)); + Assert.assertEquals(set.toString(), "set(size=2, {0,1})"); + } + + @Test(expected = UnsupportedOperationException.class) + public void testToUnalignedArray() { + Assert.assertArrayEquals(EconomicSet.create().toArray(new Integer[2]), new Integer[0]); + } + + @Test + public void testSetRemoval() { + ArrayList initialList = new ArrayList<>(); + ArrayList removalList = new ArrayList<>(); + ArrayList finalList = new ArrayList<>(); + EconomicSet set = EconomicSet.create(Equivalence.IDENTITY); + set.add(1); + set.add(2); + set.add(3); + set.add(4); + set.add(5); + set.add(6); + set.add(7); + set.add(8); + set.add(9); + Iterator i1 = set.iterator(); + while (i1.hasNext()) { + initialList.add(i1.next()); + } + int size = 0; + Iterator i2 = set.iterator(); + while (i2.hasNext()) { + Integer elem = i2.next(); + if (size++ < 8) { + i2.remove(); + } + removalList.add(elem); + } + Iterator i3 = set.iterator(); + while (i3.hasNext()) { + finalList.add(i3.next()); + } + Assert.assertEquals(initialList, removalList); + Assert.assertEquals(1, finalList.size()); + Assert.assertEquals(new Integer(9), finalList.get(0)); + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EquivalenceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EquivalenceTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections.test; + +import org.graalvm.collections.Equivalence; +import org.junit.Assert; +import org.junit.Test; + +public class EquivalenceTest { + + private static final String TEST_STRING = "Graal"; + private static final String TEST_STRING2 = "Graal2"; + + @Test + public void testDEFAULT() { + Assert.assertTrue(Equivalence.DEFAULT.equals(TEST_STRING, new String(TEST_STRING))); + Assert.assertEquals(Equivalence.DEFAULT.hashCode(TEST_STRING), Equivalence.DEFAULT.hashCode(new String(TEST_STRING))); + Assert.assertFalse(Equivalence.DEFAULT.equals(TEST_STRING, TEST_STRING2)); + Assert.assertNotEquals(Equivalence.DEFAULT.hashCode(TEST_STRING), Equivalence.DEFAULT.hashCode(TEST_STRING2)); + } + + @Test + public void testIDENTITY() { + Assert.assertFalse(Equivalence.IDENTITY.equals(TEST_STRING, new String(TEST_STRING))); + Assert.assertEquals(Equivalence.IDENTITY.hashCode(TEST_STRING), Equivalence.IDENTITY.hashCode(new String(TEST_STRING))); + Assert.assertFalse(Equivalence.IDENTITY.equals(TEST_STRING, TEST_STRING2)); + Assert.assertNotEquals(Equivalence.IDENTITY.hashCode(TEST_STRING), Equivalence.IDENTITY.hashCode(TEST_STRING2)); + } + + @Test + public void testIDENTITYWITHSYSTEMHASHCODE() { + Assert.assertFalse(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.equals(TEST_STRING, new String(TEST_STRING))); + Assert.assertNotEquals(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING), Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(new String(TEST_STRING))); + Assert.assertFalse(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.equals(TEST_STRING, TEST_STRING2)); + Assert.assertNotEquals(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING), Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING2)); + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/PairTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/PairTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections.test; + +import org.graalvm.collections.Pair; +import org.junit.Assert; +import org.junit.Test; + +public class PairTest { + + @Test + public void testCreate() { + Assert.assertEquals(Pair.create(null, null), Pair.empty()); + Assert.assertNotEquals(Pair.create(null, null), null); + Assert.assertEquals(Pair.createLeft(null), Pair.empty()); + Assert.assertEquals(Pair.createRight(null), Pair.empty()); + Assert.assertEquals(Pair.create(1, null), Pair.createLeft(1)); + Assert.assertEquals(Pair.create(null, 1), Pair.createRight(1)); + } + + @Test + public void testUtilities() { + Pair pair = Pair.create(1, null); + Assert.assertEquals(pair.getLeft(), Integer.valueOf(1)); + Assert.assertEquals(pair.getRight(), null); + Assert.assertEquals(pair.toString(), "(1, null)"); + Assert.assertEquals(pair.hashCode(), Pair.createLeft(1).hashCode()); + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections; + +import java.util.Iterator; +import java.util.Map; +import java.util.function.BiFunction; + +/** + * Memory efficient map data structure. + * + * @since 1.0 + */ +public interface EconomicMap extends UnmodifiableEconomicMap { + + /** + * Associates {@code value} with {@code key} in this map. If the map previously contained a + * mapping for {@code key}, the old value is replaced by {@code value}. + * + * @return the previous value associated with {@code key}, or {@code null} if there was no + * mapping for {@code key}. + * @since 1.0 + */ + V put(K key, V value); + + /** + * Copies all of the mappings from {@code other} to this map. + * + * @since 1.0 + */ + default void putAll(EconomicMap other) { + MapCursor e = other.getEntries(); + while (e.advance()) { + put(e.getKey(), e.getValue()); + } + } + + /** + * Copies all of the mappings from {@code other} to this map. + * + * @since 1.0 + */ + default void putAll(UnmodifiableEconomicMap other) { + UnmodifiableMapCursor entry = other.getEntries(); + while (entry.advance()) { + put(entry.getKey(), entry.getValue()); + } + } + + /** + * Removes all of the mappings from this map. The map will be empty after this call returns. + * + * @since 1.0 + */ + void clear(); + + /** + * Removes the mapping for {@code key} from this map if it is present. The map will not contain + * a mapping for {@code key} once the call returns. + * + * @return the previous value associated with {@code key}, or {@code null} if there was no + * mapping for {@code key}. + * @since 1.0 + */ + V removeKey(K key); + + /** + * Returns a {@link MapCursor} view of the mappings contained in this map. + * + * @since 1.0 + */ + @Override + MapCursor getEntries(); + + /** + * Replaces each entry's value with the result of invoking {@code function} on that entry until + * all entries have been processed or the function throws an exception. Exceptions thrown by the + * function are relayed to the caller. + * + * @since 1.0 + */ + void replaceAll(BiFunction function); + + /** + * Creates a new map that guarantees insertion order on the key set with the default + * {@link Equivalence#DEFAULT} comparison strategy for keys. + * + * @since 1.0 + */ + static EconomicMap create() { + return EconomicMap.create(Equivalence.DEFAULT); + } + + /** + * Creates a new map that guarantees insertion order on the key set with the default + * {@link Equivalence#DEFAULT} comparison strategy for keys and initializes with a specified + * capacity. + * + * @since 1.0 + */ + static EconomicMap create(int initialCapacity) { + return EconomicMap.create(Equivalence.DEFAULT, initialCapacity); + } + + /** + * Creates a new map that guarantees insertion order on the key set with the given comparison + * strategy for keys. + * + * @since 1.0 + */ + static EconomicMap create(Equivalence strategy) { + return EconomicMapImpl.create(strategy, false); + } + + /** + * Creates a new map that guarantees insertion order on the key set with the default + * {@link Equivalence#DEFAULT} comparison strategy for keys and copies all elements from the + * specified existing map. + * + * @since 1.0 + */ + static EconomicMap create(UnmodifiableEconomicMap m) { + return EconomicMap.create(Equivalence.DEFAULT, m); + } + + /** + * Creates a new map that guarantees insertion order on the key set and copies all elements from + * the specified existing map. + * + * @since 1.0 + */ + static EconomicMap create(Equivalence strategy, UnmodifiableEconomicMap m) { + return EconomicMapImpl.create(strategy, m, false); + } + + /** + * Creates a new map that guarantees insertion order on the key set and initializes with a + * specified capacity. + * + * @since 1.0 + */ + static EconomicMap create(Equivalence strategy, int initialCapacity) { + return EconomicMapImpl.create(strategy, initialCapacity, false); + } + + /** + * Wraps an existing {@link Map} as an {@link EconomicMap}. + * + * @since 1.0 + */ + static EconomicMap wrapMap(Map map) { + return new EconomicMap() { + + @Override + public V get(K key) { + V result = map.get(key); + return result; + } + + @Override + public V put(K key, V value) { + V result = map.put(key, value); + return result; + } + + @Override + public int size() { + int result = map.size(); + return result; + } + + @Override + public boolean containsKey(K key) { + return map.containsKey(key); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public V removeKey(K key) { + V result = map.remove(key); + return result; + } + + @Override + public Iterable getValues() { + return map.values(); + } + + @Override + public Iterable getKeys() { + return map.keySet(); + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + @Override + public MapCursor getEntries() { + Iterator> iterator = map.entrySet().iterator(); + return new MapCursor() { + + private Map.Entry current; + + @Override + public boolean advance() { + boolean result = iterator.hasNext(); + if (result) { + current = iterator.next(); + } + + return result; + } + + @Override + public K getKey() { + return current.getKey(); + } + + @Override + public V getValue() { + return current.getValue(); + } + + @Override + public void remove() { + iterator.remove(); + } + }; + } + + @Override + public void replaceAll(BiFunction function) { + map.replaceAll(function); + } + }; + } +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMapImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMapImpl.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,857 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections; + +import java.util.Iterator; +import java.util.Objects; +import java.util.function.BiFunction; + +/** + * Implementation of a map with a memory-efficient structure that always preserves insertion order + * when iterating over keys. Particularly efficient when number of entries is 0 or smaller equal + * {@link #INITIAL_CAPACITY} or smaller 256. + * + * The key/value pairs are kept in an expanding flat object array with keys at even indices and + * values at odd indices. If the map has smaller or equal to {@link #HASH_THRESHOLD} entries, there + * is no additional hash data structure and comparisons are done via linear checking of the + * key/value pairs. For the case where the equality check is particularly cheap (e.g., just an + * object identity comparison), this limit below which the map is without an actual hash table is + * higher and configured at {@link #HASH_THRESHOLD_IDENTITY_COMPARE}. + * + * When the hash table needs to be constructed, the field {@link #hashArray} becomes a new hash + * array where an entry of 0 means no hit and otherwise denotes the entry number in the + * {@link #entries} array. The hash array is interpreted as an actual byte array if the indices fit + * within 8 bit, or as an array of short values if the indices fit within 16 bit, or as an array of + * integer values in other cases. + * + * Hash collisions are handled by chaining a linked list of {@link CollisionLink} objects that take + * the place of the values in the {@link #entries} array. + * + * Removing entries will put {@code null} into the {@link #entries} array. If the occupation of the + * map falls below a specific threshold, the map will be compressed via the + * {@link #maybeCompress(int)} method. + */ +final class EconomicMapImpl implements EconomicMap, EconomicSet { + + /** + * Initial number of key/value pair entries that is allocated in the first entries array. + */ + private static final int INITIAL_CAPACITY = 4; + + /** + * Maximum number of entries that are moved linearly forward if a key is removed. + */ + private static final int COMPRESS_IMMEDIATE_CAPACITY = 8; + + /** + * Minimum number of key/value pair entries added when the entries array is increased in size. + */ + private static final int MIN_CAPACITY_INCREASE = 8; + + /** + * Number of entries above which a hash table is created. + */ + private static final int HASH_THRESHOLD = 4; + + /** + * Number of entries above which a hash table is created when equality can be checked with + * object identity. + */ + private static final int HASH_THRESHOLD_IDENTITY_COMPARE = 8; + + /** + * Maximum number of entries allowed in the map. + */ + private static final int MAX_ELEMENT_COUNT = Integer.MAX_VALUE >> 1; + + /** + * Number of entries above which more than 1 byte is necessary for the hash index. + */ + private static final int LARGE_HASH_THRESHOLD = ((1 << Byte.SIZE) << 1); + + /** + * Number of entries above which more than 2 bytes are are necessary for the hash index. + */ + private static final int VERY_LARGE_HASH_THRESHOLD = (LARGE_HASH_THRESHOLD << Byte.SIZE); + + /** + * Total number of entries (actual entries plus deleted entries). + */ + private int totalEntries; + + /** + * Number of deleted entries. + */ + private int deletedEntries; + + /** + * Entries array with even indices storing keys and odd indices storing values. + */ + private Object[] entries; + + /** + * Hash array that is interpreted either as byte or short or int array depending on number of + * map entries. + */ + private byte[] hashArray; + + /** + * The strategy used for comparing keys or {@code null} for denoting special strategy + * {@link Equivalence#IDENTITY}. + */ + private final Equivalence strategy; + + /** + * Intercept method for debugging purposes. + */ + private static EconomicMapImpl intercept(EconomicMapImpl map) { + return map; + } + + public static EconomicMapImpl create(Equivalence strategy, boolean isSet) { + return intercept(new EconomicMapImpl<>(strategy, isSet)); + } + + public static EconomicMapImpl create(Equivalence strategy, int initialCapacity, boolean isSet) { + return intercept(new EconomicMapImpl<>(strategy, initialCapacity, isSet)); + } + + public static EconomicMapImpl create(Equivalence strategy, UnmodifiableEconomicMap other, boolean isSet) { + return intercept(new EconomicMapImpl<>(strategy, other, isSet)); + } + + public static EconomicMapImpl create(Equivalence strategy, UnmodifiableEconomicSet other, boolean isSet) { + return intercept(new EconomicMapImpl<>(strategy, other, isSet)); + } + + private EconomicMapImpl(Equivalence strategy, boolean isSet) { + if (strategy == Equivalence.IDENTITY) { + this.strategy = null; + } else { + this.strategy = strategy; + } + this.isSet = isSet; + } + + private EconomicMapImpl(Equivalence strategy, int initialCapacity, boolean isSet) { + this(strategy, isSet); + init(initialCapacity); + } + + private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicMap other, boolean isSet) { + this(strategy, isSet); + if (!initFrom(other)) { + init(other.size()); + putAll(other); + } + } + + private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicSet other, boolean isSet) { + this(strategy, isSet); + if (!initFrom(other)) { + init(other.size()); + addAll(other); + } + } + + @SuppressWarnings("unchecked") + private boolean initFrom(Object o) { + if (o instanceof EconomicMapImpl) { + EconomicMapImpl otherMap = (EconomicMapImpl) o; + // We are only allowed to directly copy if the strategies of the two maps are the same. + if (strategy == otherMap.strategy) { + totalEntries = otherMap.totalEntries; + deletedEntries = otherMap.deletedEntries; + if (otherMap.entries != null) { + entries = otherMap.entries.clone(); + } + if (otherMap.hashArray != null) { + hashArray = otherMap.hashArray.clone(); + } + return true; + } + } + return false; + } + + private void init(int size) { + if (size > INITIAL_CAPACITY) { + entries = new Object[size << 1]; + } + } + + /** + * Links the collisions. Needs to be immutable class for allowing efficient shallow copy from + * other map on construction. + */ + private static final class CollisionLink { + + CollisionLink(Object value, int next) { + this.value = value; + this.next = next; + } + + final Object value; + + /** + * Index plus one of the next entry in the collision link chain. + */ + final int next; + } + + @SuppressWarnings("unchecked") + @Override + public V get(K key) { + Objects.requireNonNull(key); + + int index = find(key); + if (index != -1) { + return (V) getValue(index); + } + return null; + } + + private int find(K key) { + if (hasHashArray()) { + return findHash(key); + } else { + return findLinear(key); + } + } + + private int findLinear(K key) { + for (int i = 0; i < totalEntries; i++) { + Object entryKey = entries[i << 1]; + if (entryKey != null && compareKeys(key, entryKey)) { + return i; + } + } + return -1; + } + + private boolean compareKeys(Object key, Object entryKey) { + if (key == entryKey) { + return true; + } + if (strategy != null && strategy != Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) { + if (strategy == Equivalence.DEFAULT) { + return key.equals(entryKey); + } else { + return strategy.equals(key, entryKey); + } + } + return false; + } + + private int findHash(K key) { + int index = getHashArray(getHashIndex(key)) - 1; + if (index != -1) { + Object entryKey = getKey(index); + if (compareKeys(key, entryKey)) { + return index; + } else { + Object entryValue = getRawValue(index); + if (entryValue instanceof CollisionLink) { + return findWithCollision(key, (CollisionLink) entryValue); + } + } + } + + return -1; + } + + private int findWithCollision(K key, CollisionLink initialEntryValue) { + int index; + Object entryKey; + CollisionLink entryValue = initialEntryValue; + while (true) { + CollisionLink collisionLink = entryValue; + index = collisionLink.next; + entryKey = getKey(index); + if (compareKeys(key, entryKey)) { + return index; + } else { + Object value = getRawValue(index); + if (value instanceof CollisionLink) { + entryValue = (CollisionLink) getRawValue(index); + } else { + return -1; + } + } + } + } + + private int getHashArray(int index) { + if (entries.length < LARGE_HASH_THRESHOLD) { + return (hashArray[index] & 0xFF); + } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) { + int adjustedIndex = index << 1; + return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8); + } else { + int adjustedIndex = index << 2; + return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8) | ((hashArray[adjustedIndex + 2] & 0xFF) << 16) | ((hashArray[adjustedIndex + 3] & 0xFF) << 24); + } + } + + private void setHashArray(int index, int value) { + if (entries.length < LARGE_HASH_THRESHOLD) { + hashArray[index] = (byte) value; + } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) { + int adjustedIndex = index << 1; + hashArray[adjustedIndex] = (byte) value; + hashArray[adjustedIndex + 1] = (byte) (value >> 8); + } else { + int adjustedIndex = index << 2; + hashArray[adjustedIndex] = (byte) value; + hashArray[adjustedIndex + 1] = (byte) (value >> 8); + hashArray[adjustedIndex + 2] = (byte) (value >> 16); + hashArray[adjustedIndex + 3] = (byte) (value >> 24); + } + } + + private int findAndRemoveHash(Object key) { + int hashIndex = getHashIndex(key); + int index = getHashArray(hashIndex) - 1; + if (index != -1) { + Object entryKey = getKey(index); + if (compareKeys(key, entryKey)) { + Object value = getRawValue(index); + int nextIndex = -1; + if (value instanceof CollisionLink) { + CollisionLink collisionLink = (CollisionLink) value; + nextIndex = collisionLink.next; + } + setHashArray(hashIndex, nextIndex + 1); + return index; + } else { + Object entryValue = getRawValue(index); + if (entryValue instanceof CollisionLink) { + return findAndRemoveWithCollision(key, (CollisionLink) entryValue, index); + } + } + } + + return -1; + } + + private int findAndRemoveWithCollision(Object key, CollisionLink initialEntryValue, int initialIndexValue) { + int index; + Object entryKey; + CollisionLink entryValue = initialEntryValue; + int lastIndex = initialIndexValue; + while (true) { + CollisionLink collisionLink = entryValue; + index = collisionLink.next; + entryKey = getKey(index); + if (compareKeys(key, entryKey)) { + Object value = getRawValue(index); + if (value instanceof CollisionLink) { + CollisionLink thisCollisionLink = (CollisionLink) value; + setRawValue(lastIndex, new CollisionLink(collisionLink.value, thisCollisionLink.next)); + } else { + setRawValue(lastIndex, collisionLink.value); + } + return index; + } else { + Object value = getRawValue(index); + if (value instanceof CollisionLink) { + entryValue = (CollisionLink) getRawValue(index); + lastIndex = index; + } else { + return -1; + } + } + } + } + + private int getHashIndex(Object key) { + int hash; + if (strategy != null && strategy != Equivalence.DEFAULT) { + if (strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) { + hash = System.identityHashCode(key); + } else { + hash = strategy.hashCode(key); + } + } else { + hash = key.hashCode(); + } + hash = hash ^ (hash >>> 16); + return hash & (getHashTableSize() - 1); + } + + @SuppressWarnings("unchecked") + @Override + public V put(K key, V value) { + if (key == null) { + throw new UnsupportedOperationException("null not supported as key!"); + } + int index = find(key); + if (index != -1) { + Object oldValue = getValue(index); + setValue(index, value); + return (V) oldValue; + } + + int nextEntryIndex = totalEntries; + if (entries == null) { + entries = new Object[INITIAL_CAPACITY << 1]; + } else if (entries.length == nextEntryIndex << 1) { + grow(); + + assert entries.length > totalEntries << 1; + // Can change if grow is actually compressing. + nextEntryIndex = totalEntries; + } + + setKey(nextEntryIndex, key); + setValue(nextEntryIndex, value); + totalEntries++; + + if (hasHashArray()) { + // Rehash on collision if hash table is more than three quarters full. + boolean rehashOnCollision = (getHashTableSize() < (size() + (size() >> 1))); + putHashEntry(key, nextEntryIndex, rehashOnCollision); + } else if (totalEntries > getHashThreshold()) { + createHash(); + } + + return null; + } + + /** + * Number of entries above which a hash table should be constructed. + */ + private int getHashThreshold() { + if (strategy == null || strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) { + return HASH_THRESHOLD_IDENTITY_COMPARE; + } else { + return HASH_THRESHOLD; + } + } + + private void grow() { + int entriesLength = entries.length; + int newSize = (entriesLength >> 1) + Math.max(MIN_CAPACITY_INCREASE, entriesLength >> 2); + if (newSize > MAX_ELEMENT_COUNT) { + throw new UnsupportedOperationException("map grown too large!"); + } + Object[] newEntries = new Object[newSize << 1]; + System.arraycopy(entries, 0, newEntries, 0, entriesLength); + entries = newEntries; + if ((entriesLength < LARGE_HASH_THRESHOLD && newEntries.length >= LARGE_HASH_THRESHOLD) || + (entriesLength < VERY_LARGE_HASH_THRESHOLD && newEntries.length > VERY_LARGE_HASH_THRESHOLD)) { + // Rehash in order to change number of bits reserved for hash indices. + createHash(); + } + } + + /** + * Compresses the graph if there is a large number of deleted entries and returns the translated + * new next index. + */ + private int maybeCompress(int nextIndex) { + if (entries.length != INITIAL_CAPACITY << 1 && deletedEntries >= (totalEntries >> 1) + (totalEntries >> 2)) { + return compressLarge(nextIndex); + } + return nextIndex; + } + + /** + * Compresses the graph and returns the translated new next index. + */ + private int compressLarge(int nextIndex) { + int size = INITIAL_CAPACITY; + int remaining = totalEntries - deletedEntries; + + while (size <= remaining) { + size += Math.max(MIN_CAPACITY_INCREASE, size >> 1); + } + + Object[] newEntries = new Object[size << 1]; + int z = 0; + int newNextIndex = remaining; + for (int i = 0; i < totalEntries; ++i) { + Object key = getKey(i); + if (i == nextIndex) { + newNextIndex = z; + } + if (key != null) { + newEntries[z << 1] = key; + newEntries[(z << 1) + 1] = getValue(i); + z++; + } + } + + this.entries = newEntries; + totalEntries = z; + deletedEntries = 0; + if (z <= getHashThreshold()) { + this.hashArray = null; + } else { + createHash(); + } + return newNextIndex; + } + + private int getHashTableSize() { + if (entries.length < LARGE_HASH_THRESHOLD) { + return hashArray.length; + } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) { + return hashArray.length >> 1; + } else { + return hashArray.length >> 2; + } + } + + private void createHash() { + int entryCount = size(); + + // Calculate smallest 2^n that is greater number of entries. + int size = getHashThreshold(); + while (size <= entryCount) { + size <<= 1; + } + + // Give extra size to avoid collisions. + size <<= 1; + + if (this.entries.length >= VERY_LARGE_HASH_THRESHOLD) { + // Every entry has 4 bytes. + size <<= 2; + } else if (this.entries.length >= LARGE_HASH_THRESHOLD) { + // Every entry has 2 bytes. + size <<= 1; + } else { + // Entries are very small => give extra size to further reduce collisions. + size <<= 1; + } + + hashArray = new byte[size]; + for (int i = 0; i < totalEntries; i++) { + Object entryKey = getKey(i); + if (entryKey != null) { + putHashEntry(entryKey, i, false); + } + } + } + + private void putHashEntry(Object key, int entryIndex, boolean rehashOnCollision) { + int hashIndex = getHashIndex(key); + int oldIndex = getHashArray(hashIndex) - 1; + if (oldIndex != -1 && rehashOnCollision) { + this.createHash(); + return; + } + setHashArray(hashIndex, entryIndex + 1); + Object value = getRawValue(entryIndex); + if (oldIndex != -1) { + assert entryIndex != oldIndex : "this cannot happend and would create an endless collision link cycle"; + if (value instanceof CollisionLink) { + CollisionLink collisionLink = (CollisionLink) value; + setRawValue(entryIndex, new CollisionLink(collisionLink.value, oldIndex)); + } else { + setRawValue(entryIndex, new CollisionLink(getRawValue(entryIndex), oldIndex)); + } + } else { + if (value instanceof CollisionLink) { + CollisionLink collisionLink = (CollisionLink) value; + setRawValue(entryIndex, collisionLink.value); + } + } + } + + @Override + public int size() { + return totalEntries - deletedEntries; + } + + @Override + public boolean containsKey(K key) { + return find(key) != -1; + } + + @Override + public void clear() { + entries = null; + hashArray = null; + totalEntries = deletedEntries = 0; + } + + private boolean hasHashArray() { + return hashArray != null; + } + + @SuppressWarnings("unchecked") + @Override + public V removeKey(K key) { + if (key == null) { + throw new UnsupportedOperationException("null not supported as key!"); + } + int index; + if (hasHashArray()) { + index = this.findAndRemoveHash(key); + } else { + index = this.findLinear(key); + } + + if (index != -1) { + Object value = getValue(index); + remove(index); + return (V) value; + } + return null; + } + + /** + * Removes the element at the specific index and returns the index of the next element. This can + * be a different value if graph compression was triggered. + */ + private int remove(int indexToRemove) { + int index = indexToRemove; + int entriesAfterIndex = totalEntries - index - 1; + int result = index + 1; + + // Without hash array, compress immediately. + if (entriesAfterIndex <= COMPRESS_IMMEDIATE_CAPACITY && !hasHashArray()) { + while (index < totalEntries - 1) { + setKey(index, getKey(index + 1)); + setRawValue(index, getRawValue(index + 1)); + index++; + } + result--; + } + + setKey(index, null); + setRawValue(index, null); + if (index == totalEntries - 1) { + // Make sure last element is always non-null. + totalEntries--; + while (index > 0 && getKey(index - 1) == null) { + totalEntries--; + deletedEntries--; + index--; + } + } else { + deletedEntries++; + result = maybeCompress(result); + } + + return result; + } + + private abstract class SparseMapIterator implements Iterator { + + protected int current; + + @Override + public boolean hasNext() { + return current < totalEntries; + } + + @Override + public void remove() { + if (hasHashArray()) { + EconomicMapImpl.this.findAndRemoveHash(getKey(current - 1)); + } + current = EconomicMapImpl.this.remove(current - 1); + } + } + + @Override + public Iterable getValues() { + return new Iterable() { + @Override + public Iterator iterator() { + return new SparseMapIterator() { + @SuppressWarnings("unchecked") + @Override + public V next() { + Object result; + while (true) { + result = getValue(current); + if (result == null && getKey(current) == null) { + // values can be null, double-check if key is also null + current++; + } else { + current++; + break; + } + } + return (V) result; + } + }; + } + }; + } + + @Override + public Iterable getKeys() { + return this; + } + + @Override + public boolean isEmpty() { + return this.size() == 0; + } + + @Override + public MapCursor getEntries() { + return new MapCursor() { + int current = -1; + + @Override + public boolean advance() { + current++; + if (current >= totalEntries) { + return false; + } else { + while (EconomicMapImpl.this.getKey(current) == null) { + // Skip over null entries + current++; + } + return true; + } + } + + @SuppressWarnings("unchecked") + @Override + public K getKey() { + return (K) EconomicMapImpl.this.getKey(current); + } + + @SuppressWarnings("unchecked") + @Override + public V getValue() { + return (V) EconomicMapImpl.this.getValue(current); + } + + @Override + public void remove() { + if (hasHashArray()) { + EconomicMapImpl.this.findAndRemoveHash(EconomicMapImpl.this.getKey(current)); + } + current = EconomicMapImpl.this.remove(current) - 1; + } + }; + } + + @SuppressWarnings("unchecked") + @Override + public void replaceAll(BiFunction function) { + for (int i = 0; i < totalEntries; i++) { + Object entryKey = getKey(i); + if (entryKey != null) { + Object newValue = function.apply((K) entryKey, (V) getValue(i)); + setValue(i, newValue); + } + } + } + + private Object getKey(int index) { + return entries[index << 1]; + } + + private void setKey(int index, Object newValue) { + entries[index << 1] = newValue; + } + + private void setValue(int index, Object newValue) { + Object oldValue = getRawValue(index); + if (oldValue instanceof CollisionLink) { + CollisionLink collisionLink = (CollisionLink) oldValue; + setRawValue(index, new CollisionLink(newValue, collisionLink.next)); + } else { + setRawValue(index, newValue); + } + } + + private void setRawValue(int index, Object newValue) { + entries[(index << 1) + 1] = newValue; + } + + private Object getRawValue(int index) { + return entries[(index << 1) + 1]; + } + + private Object getValue(int index) { + Object object = getRawValue(index); + if (object instanceof CollisionLink) { + return ((CollisionLink) object).value; + } + return object; + } + + private final boolean isSet; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(isSet ? "set(size=" : "map(size=").append(size()).append(", {"); + String sep = ""; + MapCursor cursor = getEntries(); + while (cursor.advance()) { + builder.append(sep); + if (isSet) { + builder.append(cursor.getKey()); + } else { + builder.append("(").append(cursor.getKey()).append(",").append(cursor.getValue()).append(")"); + } + sep = ","; + } + builder.append("})"); + return builder.toString(); + } + + @Override + public Iterator iterator() { + return new SparseMapIterator() { + @SuppressWarnings("unchecked") + @Override + public K next() { + Object result; + while ((result = getKey(current++)) == null) { + // skip null entries + } + return (K) result; + } + }; + } + + @Override + public boolean contains(K element) { + return containsKey(element); + } + + @SuppressWarnings("unchecked") + @Override + public boolean add(K element) { + return put(element, (V) element) == null; + } + + @Override + public void remove(K element) { + removeKey(element); + } +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections; + +import java.util.Iterator; + +/** + * Memory efficient set data structure. + * + * @since 1.0 + */ +public interface EconomicSet extends UnmodifiableEconomicSet { + + /** + * Adds {@code element} to this set if it is not already present. + * + * @return {@code true} if this set did not already contain {@code element}. + * @since 1.0 + */ + boolean add(E element); + + /** + * Removes {@code element} from this set if it is present. This set will not contain + * {@code element} once the call returns. + * + * @since 1.0 + */ + void remove(E element); + + /** + * Removes all of the elements from this set. The set will be empty after this call returns. + * + * @since 1.0 + */ + void clear(); + + /** + * Adds all of the elements in {@code other} to this set if they're not already present. + * + * @since 1.0 + */ + default void addAll(EconomicSet other) { + addAll(other.iterator()); + } + + /** + * Adds all of the elements in {@code values} to this set if they're not already present. + * + * @since 1.0 + */ + default void addAll(Iterable values) { + addAll(values.iterator()); + } + + /** + * Adds all of the elements enumerated by {@code iterator} to this set if they're not already + * present. + * + * @since 1.0 + */ + default void addAll(Iterator iterator) { + while (iterator.hasNext()) { + add(iterator.next()); + } + } + + /** + * Removes from this set all of its elements that are contained in {@code other}. + * + * @since 1.0 + */ + default void removeAll(EconomicSet other) { + removeAll(other.iterator()); + } + + /** + * Removes from this set all of its elements that are contained in {@code values}. + * + * @since 1.0 + */ + default void removeAll(Iterable values) { + removeAll(values.iterator()); + } + + /** + * Removes from this set all of its elements that are enumerated by {@code iterator}. + * + * @since 1.0 + */ + default void removeAll(Iterator iterator) { + while (iterator.hasNext()) { + remove(iterator.next()); + } + } + + /** + * Removes from this set all of its elements that are not contained in {@code other}. + * + * @since 1.0 + */ + default void retainAll(EconomicSet other) { + Iterator iterator = iterator(); + while (iterator.hasNext()) { + E key = iterator.next(); + if (!other.contains(key)) { + iterator.remove(); + } + } + } + + /** + * Creates a new set guaranteeing insertion order when iterating over its elements with the + * default {@link Equivalence#DEFAULT} comparison strategy. + * + * @since 1.0 + */ + static EconomicSet create() { + return EconomicSet.create(Equivalence.DEFAULT); + } + + /** + * Creates a new set guaranteeing insertion order when iterating over its elements. + * + * @since 1.0 + */ + static EconomicSet create(Equivalence strategy) { + return EconomicMapImpl.create(strategy, true); + } + + /** + * Creates a new set guaranteeing insertion order when iterating over its elements with the + * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the + * specified collection. + * + * @since 1.0 + */ + static EconomicSet create(int initialCapacity) { + return EconomicSet.create(Equivalence.DEFAULT, initialCapacity); + } + + /** + * Creates a new set guaranteeing insertion order when iterating over its elements with the + * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the + * specified collection. + * + * @since 1.0 + */ + static EconomicSet create(UnmodifiableEconomicSet c) { + return EconomicSet.create(Equivalence.DEFAULT, c); + } + + /** + * Creates a new set guaranteeing insertion order when iterating over its elements and + * initializes with the given capacity. + * + * @since 1.0 + */ + static EconomicSet create(Equivalence strategy, int initialCapacity) { + return EconomicMapImpl.create(strategy, initialCapacity, true); + } + + /** + * Creates a new set guaranteeing insertion order when iterating over its elements and inserts + * all elements of the specified collection. + * + * @since 1.0 + */ + static EconomicSet create(Equivalence strategy, UnmodifiableEconomicSet c) { + return EconomicMapImpl.create(strategy, c, true); + } +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Equivalence.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Equivalence.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections; + +/** + * Strategy for comparing two objects. Default predefined strategies are {@link #DEFAULT}, + * {@link #IDENTITY}, and {@link #IDENTITY_WITH_SYSTEM_HASHCODE}. + * + * @since 1.0 + */ +public abstract class Equivalence { + + /** + * Default equivalence calling {@link #equals(Object)} to check equality and {@link #hashCode()} + * for obtaining hash values. Do not change the logic of this class as it may be inlined in + * other places. + * + * @since 1.0 + */ + public static final Equivalence DEFAULT = new Equivalence() { + + @Override + public boolean equals(Object a, Object b) { + return a.equals(b); + } + + @Override + public int hashCode(Object o) { + return o.hashCode(); + } + }; + + /** + * Identity equivalence using {@code ==} to check equality and {@link #hashCode()} for obtaining + * hash values. Do not change the logic of this class as it may be inlined in other places. + * + * @since 1.0 + */ + public static final Equivalence IDENTITY = new Equivalence() { + + @Override + public boolean equals(Object a, Object b) { + return a == b; + } + + @Override + public int hashCode(Object o) { + return o.hashCode(); + } + }; + + /** + * Identity equivalence using {@code ==} to check equality and + * {@link System#identityHashCode(Object)} for obtaining hash values. Do not change the logic of + * this class as it may be inlined in other places. + * + * @since 1.0 + */ + public static final Equivalence IDENTITY_WITH_SYSTEM_HASHCODE = new Equivalence() { + + @Override + public boolean equals(Object a, Object b) { + return a == b; + } + + @Override + public int hashCode(Object o) { + return System.identityHashCode(o); + } + }; + + /** + * Subclass for creating custom equivalence definitions. + * + * @since 1.0 + */ + protected Equivalence() { + } + + /** + * Returns {@code true} if the non-{@code null} arguments are equal to each other and + * {@code false} otherwise. + * + * @since 1.0 + */ + public abstract boolean equals(Object a, Object b); + + /** + * Returns the hash code of a non-{@code null} argument {@code o}. + * + * @since 1.0 + */ + public abstract int hashCode(Object o); +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/MapCursor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/MapCursor.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections; + +/** + * Cursor to iterate over a mutable map. + * + * @since 1.0 + */ +public interface MapCursor extends UnmodifiableMapCursor { + /** + * Remove the current entry from the map. May only be called once. After calling + * {@link #remove()}, it is no longer valid to call {@link #getKey()} or {@link #getValue()} on + * the current entry. + * + * @since 1.0 + */ + void remove(); +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Pair.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Pair.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections; + +import java.util.Objects; + +/** + * Utility class representing a pair of values. + * + * @since 1.0 + */ +public final class Pair { + + private static final Pair EMPTY = new Pair<>(null, null); + + private final L left; + private final R right; + + /** + * Returns an empty pair. + * + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public static Pair empty() { + return (Pair) EMPTY; + } + + /** + * Constructs a pair with its left value being {@code left}, or returns an empty pair if + * {@code left} is null. + * + * @return the constructed pair or an empty pair if {@code left} is null. + * @since 1.0 + */ + public static Pair createLeft(L left) { + if (left == null) { + return empty(); + } else { + return new Pair<>(left, null); + } + } + + /** + * Constructs a pair with its right value being {@code right}, or returns an empty pair if + * {@code right} is null. + * + * @return the constructed pair or an empty pair if {@code right} is null. + * @since 1.0 + */ + public static Pair createRight(R right) { + if (right == null) { + return empty(); + } else { + return new Pair<>(null, right); + } + } + + /** + * Constructs a pair with its left value being {@code left}, and its right value being + * {@code right}, or returns an empty pair if both inputs are null. + * + * @return the constructed pair or an empty pair if both inputs are null. + * @since 1.0 + */ + public static Pair create(L left, R right) { + if (right == null && left == null) { + return empty(); + } else { + return new Pair<>(left, right); + } + } + + private Pair(L left, R right) { + this.left = left; + this.right = right; + } + + /** + * Returns the left value of this pair. + * + * @since 1.0 + */ + public L getLeft() { + return left; + } + + /** + * Returns the right value of this pair. + * + * @since 1.0 + */ + public R getRight() { + return right; + } + + /** + * {@inheritDoc} + * + * @since 1.0 + */ + @Override + public int hashCode() { + return Objects.hashCode(left) + 31 * Objects.hashCode(right); + } + + /** + * {@inheritDoc} + * + * @since 1.0 + */ + @SuppressWarnings("unchecked") + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (obj instanceof Pair) { + Pair pair = (Pair) obj; + return Objects.equals(left, pair.left) && Objects.equals(right, pair.right); + } + + return false; + } + + /** + * {@inheritDoc} + * + * @since 1.0 + */ + @Override + public String toString() { + return String.format("(%s, %s)", left, right); + } +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicMap.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections; + +/** + * Unmodifiable memory efficient map data structure. + * + * @since 1.0 + */ +public interface UnmodifiableEconomicMap { + + /** + * Returns the value to which {@code key} is mapped, or {@code null} if this map contains no + * mapping for {@code key}. + * + * @since 1.0 + */ + V get(K key); + + /** + * Returns the value to which {@code key} is mapped, or {@code defaultValue} if this map + * contains no mapping for {@code key}. + * + * @since 1.0 + */ + default V get(K key, V defaultValue) { + V v = get(key); + if (v == null) { + return defaultValue; + } + return v; + } + + /** + * Returns {@code true} if this map contains a mapping for {@code key}. + * + * @since 1.0 + */ + boolean containsKey(K key); + + /** + * Returns the number of key-value mappings in this map. + * + * @since 1.0 + */ + int size(); + + /** + * Returns {@code true} if this map contains no key-value mappings. + * + * @since 1.0 + */ + boolean isEmpty(); + + /** + * Returns a {@link Iterable} view of the values contained in this map. + * + * @since 1.0 + */ + Iterable getValues(); + + /** + * Returns a {@link Iterable} view of the keys contained in this map. + * + * @since 1.0 + */ + Iterable getKeys(); + + /** + * Returns a {@link UnmodifiableMapCursor} view of the mappings contained in this map. + * + * @since 1.0 + */ + UnmodifiableMapCursor getEntries(); +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicSet.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections; + +/** + * Unmodifiable memory efficient set data structure. + * + * @since 1.0 + */ +public interface UnmodifiableEconomicSet extends Iterable { + + /** + * Returns {@code true} if this set contains a mapping for the {@code element}. + * + * @since 1.0 + */ + boolean contains(E element); + + /** + * Returns the number of elements in this set. + * + * @since 1.0 + */ + int size(); + + /** + * Returns {@code true} if this set contains no elements. + * + * @since 1.0 + */ + boolean isEmpty(); + + /** + * Stores all of the elements in this set into {@code target}. An + * {@link UnsupportedOperationException} will be thrown if the length of {@code target} does not + * match the size of this set. + * + * @return an array containing all the elements in this set. + * @throws UnsupportedOperationException if the length of {@code target} does not equal the size + * of this set. + * @since 1.0 + */ + default E[] toArray(E[] target) { + if (target.length != size()) { + throw new UnsupportedOperationException("Length of target array must equal the size of the set."); + } + + int index = 0; + for (E element : this) { + target[index++] = element; + } + + return target; + } +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableMapCursor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableMapCursor.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 org.graalvm.collections; + +/** + * Cursor to iterate over a map without changing its contents. + * + * @since 1.0 + */ +public interface UnmodifiableMapCursor { + /** + * Advances to the next entry. + * + * @return {@code true} if a next entry exists, {@code false} if there is no next entry. + * @since 1.0 + */ + boolean advance(); + + /** + * The key of the current entry. + * + * @since 1.0 + */ + K getKey(); + + /** + * The value of the current entry. + * + * @since 1.0 + */ + V getValue(); +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/package-info.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +/** + * The Graal-SDK collections package contains memory efficient data structures. + * + * @see org.graalvm.collections.EconomicMap + * @see org.graalvm.collections.EconomicSet + * + * @since 1.0 + */ +package org.graalvm.collections; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -50,6 +50,21 @@ test("branchProbabilitySnippet", 5); } + public static int branchProbabilitySnippet2(int arg) { + if (!GraalDirectives.injectBranchProbability(0.125, arg <= 0)) { + GraalDirectives.controlFlowAnchor(); // prevent removal of the if + return 2; + } else { + GraalDirectives.controlFlowAnchor(); // prevent removal of the if + return 1; + } + } + + @Test + public void testBranchProbability2() { + test("branchProbabilitySnippet2", 5); + } + @Override protected boolean checkLowTierGraph(StructuredGraph graph) { NodeIterable ifNodes = graph.getNodes(IfNode.TYPE); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java Fri Feb 02 17:28:17 2018 -0800 @@ -50,6 +50,13 @@ } /** + * Directive for the compiler to fall back to the bytecode interpreter at this point, invalidate + * the compiled code, record a speculation and reprofile the method. + */ + public static void deoptimizeAndInvalidateWithSpeculation() { + } + + /** * Returns a boolean value indicating whether the method is executed in Graal-compiled code. */ public static boolean inCompiledCode() { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,15 +26,52 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.reflect.Array; import jdk.vm.ci.meta.Signature; /** * Denotes a method whose body is used by a compiler as the substitute (or intrinsification) of - * another method. The exact method used to do the substitution is compiler dependent but every + * another method. The exact mechanism used to do the substitution is compiler dependent but every * compiler should require substitute methods to be annotated with {@link MethodSubstitution}. In * addition, a compiler is recommended to implement {@link MethodSubstitutionRegistry} to advertise * the mechanism by which it supports registration of method substitutes. + * + * A compiler may support partial intrinsification where only a part of a method is implemented by + * the compiler. The unsupported path is expressed by a call to either the original or substitute + * method from within the substitute method. Such as call is a partial intrinsic exit. + * + * For example, here's a HotSpot specific intrinsic for {@link Array#newInstance(Class, int)} that + * only handles the case where the VM representation of the array class to be instantiated already + * exists: + * + *
+ * @MethodSubstitution
+ * public static Object newInstance(Class componentType, int length) {
+ *     if (componentType == null || loadKlassFromObject(componentType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION).isNull()) {
+ *         // Array class not yet created - exit the intrinsic and call the original method
+ *         return newInstance(componentType, length);
+ *     }
+ *     return DynamicNewArrayNode.newArray(GraalDirectives.guardingNonNull(componentType), length, JavaKind.Object);
+ * }
+ * 
+ * + * Here's the same intrinsification where the exit is expressed as a call to the original method: + * + *
+ * @MethodSubstitution
+ * public static Object newInstance(Class componentType, int length) {
+ *     if (componentType == null || loadKlassFromObject(componentType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION).isNull()) {
+ *         // Array class not yet created - exit the intrinsic and call the original method
+ *         return java.lang.reflect.newInstance(componentType, length);
+ *     }
+ *     return DynamicNewArrayNode.newArray(GraalDirectives.guardingNonNull(componentType), length, JavaKind.Object);
+ * }
+ * 
+ * + * A condition for a partial intrinsic exit is that it is uses the unmodified parameters of the + * substitute as arguments to the partial intrinsic exit call. There must also be no side effecting + * instruction between the start of the substitute method and the partial intrinsic exit. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java Fri Feb 02 17:28:17 2018 -0800 @@ -90,4 +90,12 @@ * if this provider cannot provide a value of the requested type */ T getInjectedNodeIntrinsicParameter(Class type); + + /** + * Get the original Java class corresponding to a {@link ResolvedJavaType}. + * + * @param type the type for which the original Java class is requested + * @return the original Java class corresponding to the {@code type} parameter + */ + Class originalClass(ResolvedJavaType type); } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.runtime/src/org/graalvm/compiler/api/runtime/GraalRuntime.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.runtime/src/org/graalvm/compiler/api/runtime/GraalRuntime.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.runtime/src/org/graalvm/compiler/api/runtime/GraalRuntime.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,9 +22,19 @@ */ package org.graalvm.compiler.api.runtime; +import jdk.vm.ci.common.JVMCIError; + public interface GraalRuntime { String getName(); T getCapability(Class clazz); + + default T getRequiredCapability(Class clazz) { + T ret = getCapability(clazz); + if (ret == null) { + throw new JVMCIError("The VM does not expose the required Graal capability %s.", clazz.getName()); + } + return ret; + } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Fri Feb 02 17:28:17 2018 -0800 @@ -208,7 +208,6 @@ } private static class VexOpcode { - private static final int VEX_OPCODE_NONE = 0x0; private static final int VEX_OPCODE_0F = 0x1; private static final int VEX_OPCODE_0F_38 = 0x2; private static final int VEX_OPCODE_0F_3A = 0x3; @@ -861,9 +860,26 @@ break; } + int opc = 0; + if (isSimd) { + switch (prefix2) { + case P_0F: + opc = VexOpcode.VEX_OPCODE_0F; + break; + case P_0F38: + opc = VexOpcode.VEX_OPCODE_0F_38; + break; + case P_0F3A: + opc = VexOpcode.VEX_OPCODE_0F_3A; + break; + default: + isSimd = false; + break; + } + } + if (isSimd) { int pre; - int opc; boolean rexVexW = (size == QWORD) ? true : false; AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, rexVexW, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target); int curPrefix = size.sizePrefix | prefix1; @@ -881,20 +897,6 @@ pre = VexSimdPrefix.VEX_SIMD_NONE; break; } - switch (prefix2) { - case P_0F: - opc = VexOpcode.VEX_OPCODE_0F; - break; - case P_0F38: - opc = VexOpcode.VEX_OPCODE_0F_38; - break; - case P_0F3A: - opc = VexOpcode.VEX_OPCODE_0F_3A; - break; - default: - opc = VexOpcode.VEX_OPCODE_NONE; - break; - } int encode; if (noNds) { encode = asm.simdPrefixAndEncode(dst, Register.None, src, pre, opc, attributes); @@ -938,9 +940,26 @@ break; } + int opc = 0; + if (isSimd) { + switch (prefix2) { + case P_0F: + opc = VexOpcode.VEX_OPCODE_0F; + break; + case P_0F38: + opc = VexOpcode.VEX_OPCODE_0F_38; + break; + case P_0F3A: + opc = VexOpcode.VEX_OPCODE_0F_3A; + break; + default: + isSimd = false; + break; + } + } + if (isSimd) { int pre; - int opc; boolean rexVexW = (size == QWORD) ? true : false; AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, rexVexW, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target); int curPrefix = size.sizePrefix | prefix1; @@ -958,20 +977,6 @@ pre = VexSimdPrefix.VEX_SIMD_NONE; break; } - switch (prefix2) { - case P_0F: - opc = VexOpcode.VEX_OPCODE_0F; - break; - case P_0F38: - opc = VexOpcode.VEX_OPCODE_0F_38; - break; - case P_0F3A: - opc = VexOpcode.VEX_OPCODE_0F_3A; - break; - default: - opc = VexOpcode.VEX_OPCODE_NONE; - break; - } if (noNds) { asm.simdPrefix(dst, Register.None, src, pre, opc, attributes); } else { @@ -1055,8 +1060,7 @@ opc = VexOpcode.VEX_OPCODE_0F_3A; break; default: - opc = VexOpcode.VEX_OPCODE_NONE; - break; + throw GraalError.shouldNotReachHere("invalid VEX instruction prefix"); } int encode; encode = asm.simdPrefixAndEncode(dst, nds, src, pre, opc, attributes); @@ -1096,8 +1100,7 @@ opc = VexOpcode.VEX_OPCODE_0F_3A; break; default: - opc = VexOpcode.VEX_OPCODE_NONE; - break; + throw GraalError.shouldNotReachHere("invalid VEX instruction prefix"); } asm.simdPrefix(dst, nds, src, pre, opc, attributes); asm.emitByte(op); @@ -1163,9 +1166,26 @@ break; } + int opc = 0; + if (isSimd) { + switch (prefix2) { + case P_0F: + opc = VexOpcode.VEX_OPCODE_0F; + break; + case P_0F38: + opc = VexOpcode.VEX_OPCODE_0F_38; + break; + case P_0F3A: + opc = VexOpcode.VEX_OPCODE_0F_3A; + break; + default: + isSimd = false; + break; + } + } + if (isSimd) { int pre; - int opc; boolean rexVexW = (size == QWORD) ? true : false; AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, rexVexW, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target); int curPrefix = size.sizePrefix | prefix1; @@ -1183,20 +1203,6 @@ pre = VexSimdPrefix.VEX_SIMD_NONE; break; } - switch (prefix2) { - case P_0F: - opc = VexOpcode.VEX_OPCODE_0F; - break; - case P_0F38: - opc = VexOpcode.VEX_OPCODE_0F_38; - break; - case P_0F3A: - opc = VexOpcode.VEX_OPCODE_0F_3A; - break; - default: - opc = VexOpcode.VEX_OPCODE_NONE; - break; - } int encode; if (noNds) { encode = asm.simdPrefixAndEncode(src, Register.None, dst, pre, opc, attributes); @@ -1222,9 +1228,26 @@ break; } + int opc = 0; + if (isSimd) { + switch (prefix2) { + case P_0F: + opc = VexOpcode.VEX_OPCODE_0F; + break; + case P_0F38: + opc = VexOpcode.VEX_OPCODE_0F_38; + break; + case P_0F3A: + opc = VexOpcode.VEX_OPCODE_0F_3A; + break; + default: + isSimd = false; + break; + } + } + if (isSimd) { int pre; - int opc; boolean rexVexW = (size == QWORD) ? true : false; AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, rexVexW, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target); int curPrefix = size.sizePrefix | prefix1; @@ -1242,20 +1265,6 @@ pre = VexSimdPrefix.VEX_SIMD_NONE; break; } - switch (prefix2) { - case P_0F: - opc = VexOpcode.VEX_OPCODE_0F; - break; - case P_0F38: - opc = VexOpcode.VEX_OPCODE_0F_38; - break; - case P_0F3A: - opc = VexOpcode.VEX_OPCODE_0F_3A; - break; - default: - opc = VexOpcode.VEX_OPCODE_NONE; - break; - } asm.simdPrefix(src, Register.None, dst, pre, opc, attributes); asm.emitByte(op); asm.emitOperandHelper(src, dst, 0); @@ -1390,9 +1399,26 @@ break; } + int opc = 0; + if (isSimd) { + switch (prefix2) { + case P_0F: + opc = VexOpcode.VEX_OPCODE_0F; + break; + case P_0F38: + opc = VexOpcode.VEX_OPCODE_0F_38; + break; + case P_0F3A: + opc = VexOpcode.VEX_OPCODE_0F_3A; + break; + default: + isSimd = false; + break; + } + } + if (isSimd) { int pre; - int opc; AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target); int curPrefix = size.sizePrefix | prefix1; switch (curPrefix) { @@ -1409,20 +1435,6 @@ pre = VexSimdPrefix.VEX_SIMD_NONE; break; } - switch (prefix2) { - case P_0F: - opc = VexOpcode.VEX_OPCODE_0F; - break; - case P_0F38: - opc = VexOpcode.VEX_OPCODE_0F_38; - break; - case P_0F3A: - opc = VexOpcode.VEX_OPCODE_0F_3A; - break; - default: - opc = VexOpcode.VEX_OPCODE_NONE; - break; - } int encode; if (noNds) { encode = asm.simdPrefixAndEncode(dst, Register.None, src, pre, opc, attributes); @@ -1453,9 +1465,26 @@ break; } + int opc = 0; + if (isSimd) { + switch (prefix2) { + case P_0F: + opc = VexOpcode.VEX_OPCODE_0F; + break; + case P_0F38: + opc = VexOpcode.VEX_OPCODE_0F_38; + break; + case P_0F3A: + opc = VexOpcode.VEX_OPCODE_0F_3A; + break; + default: + isSimd = false; + break; + } + } + if (isSimd) { int pre; - int opc; AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target); int curPrefix = size.sizePrefix | prefix1; switch (curPrefix) { @@ -1472,21 +1501,6 @@ pre = VexSimdPrefix.VEX_SIMD_NONE; break; } - switch (prefix2) { - case P_0F: - opc = VexOpcode.VEX_OPCODE_0F; - break; - case P_0F38: - opc = VexOpcode.VEX_OPCODE_0F_38; - break; - case P_0F3A: - opc = VexOpcode.VEX_OPCODE_0F_3A; - break; - default: - opc = VexOpcode.VEX_OPCODE_NONE; - break; - } - if (noNds) { asm.simdPrefix(dst, Register.None, src, pre, opc, attributes); } else { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java Fri Feb 02 17:28:17 2018 -0800 @@ -33,9 +33,9 @@ import java.util.List; import java.util.Objects; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.graph.NodeSourcePosition; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.code.StackSlot; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java Fri Feb 02 17:28:17 2018 -0800 @@ -40,7 +40,7 @@ public interface Patches { - void registerPatch(VMConstant c); + void registerPatch(int position, VMConstant c); } public abstract static class Data { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java Fri Feb 02 17:28:17 2018 -0800 @@ -27,7 +27,6 @@ import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.IntegerStamp; -import org.graalvm.compiler.core.common.type.PrimitiveStamp; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; @@ -107,7 +106,9 @@ ret.setBase(add.getX()); ret.setIndex(considerNegation(graph, add.getY(), isBaseNegated)); return true; - } else if (ret.getBase() == null && ret.getIndex() instanceof AddNode) { + } + + if (ret.getBase() == null && ret.getIndex() instanceof AddNode) { AddNode add = (AddNode) ret.getIndex(); ret.setBase(considerNegation(graph, add.getX(), isIndexNegated)); ret.setIndex(add.getY()); @@ -188,7 +189,7 @@ return improveConstDisp(address, node, c, null, shift, negateExtractedDisplacement); } else { if (node.stamp(NodeView.DEFAULT) instanceof IntegerStamp) { - assert PrimitiveStamp.getBits(node.stamp(NodeView.DEFAULT)) == ADDRESS_BITS; + assert IntegerStamp.getBits(node.stamp(NodeView.DEFAULT)) == ADDRESS_BITS; /* * we can't swallow zero-extends because of multiple reasons: diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64CompressAddressLowering.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64CompressAddressLowering.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.core.amd64; + +import jdk.vm.ci.code.Register; +import org.graalvm.compiler.asm.amd64.AMD64Address; +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.CompressionNode; +import org.graalvm.compiler.nodes.NodeView; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.FloatingNode; +import org.graalvm.compiler.nodes.spi.LIRLowerable; +import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; + +public abstract class AMD64CompressAddressLowering extends AMD64AddressLowering { + private static final CounterKey counterFoldedUncompressDuringAddressLowering = DebugContext.counter("FoldedUncompressDuringAddressLowering"); + + @Override + protected final boolean improve(StructuredGraph graph, DebugContext debug, AMD64AddressNode addr, boolean isBaseNegated, boolean isIndexNegated) { + if (super.improve(graph, debug, addr, isBaseNegated, isIndexNegated)) { + return true; + } + + if (!isBaseNegated && !isIndexNegated && addr.getScale() == AMD64Address.Scale.Times1) { + ValueNode base = addr.getBase(); + ValueNode index = addr.getIndex(); + + if (tryToImproveUncompression(addr, index, base) || tryToImproveUncompression(addr, base, index)) { + counterFoldedUncompressDuringAddressLowering.increment(debug); + return true; + } + } + + return false; + } + + private boolean tryToImproveUncompression(AMD64AddressNode addr, ValueNode value, ValueNode other) { + if (value instanceof CompressionNode) { + CompressionNode compression = (CompressionNode) value; + if (compression.getOp() == CompressionNode.CompressionOp.Uncompress && improveUncompression(addr, compression, other)) { + return true; + } + } + + return false; + } + + protected abstract boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other); + + @NodeInfo(cycles = CYCLES_0, size = SIZE_0) + public static class HeapBaseNode extends FloatingNode implements LIRLowerable { + + public static final NodeClass TYPE = NodeClass.create(HeapBaseNode.class); + + private final Register heapBaseRegister; + + public HeapBaseNode(Register heapBaseRegister) { + super(TYPE, StampFactory.pointer()); + this.heapBaseRegister = heapBaseRegister; + } + + @Override + public void generate(NodeLIRBuilderTool generator) { + LIRKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT)); + generator.setResult(this, heapBaseRegister.asValue(kind)); + } + } +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,14 +26,14 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64PushPopStackMove; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Architecture; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java Fri Feb 02 17:28:17 2018 -0800 @@ -44,6 +44,7 @@ import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.gen.NodeMatchRules; @@ -128,7 +129,7 @@ } protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, LIRLowerableAccess access) { - Condition cond = compare.condition(); + Condition cond = compare.condition().asCondition(); AMD64Kind kind = getMemoryKind(access); boolean matchedAsConstant = false; // For assertion checking @@ -303,7 +304,7 @@ @MatchRule("(If (FloatEquals=compare value ValueCompareAndSwap=cas))") @MatchRule("(If (IntegerEquals=compare value ValueCompareAndSwap=cas))") public ComplexMatchResult ifCompareValueCas(IfNode root, CompareNode compare, ValueNode value, ValueCompareAndSwapNode cas) { - assert compare.condition() == Condition.EQ; + assert compare.condition() == CanonicalCondition.EQ; if (value == cas.getExpectedValue() && cas.usages().count() == 1) { return builder -> { LIRKind kind = getLirKind(cas); @@ -326,7 +327,7 @@ @MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))") public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) { JavaConstant constant = value.asJavaConstant(); - assert compare.condition() == Condition.EQ; + assert compare.condition() == CanonicalCondition.EQ; if (constant != null && cas.usages().count() == 1) { long constantValue = constant.asLong(); boolean successIsTrue; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Fri Feb 02 17:28:17 2018 -0800 @@ -233,6 +233,9 @@ public static final OptionKey OptScheduleOutOfLoops = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) + public static final OptionKey GuardPriorities = new OptionKey<>(true); + + @Option(help = "", type = OptionType.Debug) public static final OptionKey OptEliminateGuards = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) @@ -271,4 +274,7 @@ @Option(help = "Enable experimental Trace Register Allocation.", type = OptionType.Debug) public static final OptionKey TraceRA = new OptionKey<>(false); + @Option(help = "How to trace inlining decisions, one of: None, Linear, Tree", type = OptionType.Debug) + public static final OptionKey TraceInlining = new OptionKey<>(TraceInliningMode.None); + } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/TraceInliningMode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/TraceInliningMode.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, 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 org.graalvm.compiler.core.common; + +public enum TraceInliningMode { + None(false), + Linear(true), + Tree(true); + + private final boolean tracing; + + TraceInliningMode(boolean tracing) { + this.tracing = tracing; + } + + public boolean isTracing() { + return tracing; + } +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,9 +22,9 @@ */ package org.graalvm.compiler.core.common.alloc; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.Register.RegisterCategory; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/CanonicalCondition.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/CanonicalCondition.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2009, 2015, 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 org.graalvm.compiler.core.common.calc; + +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.PrimitiveConstant; + +public enum CanonicalCondition { + EQ(Condition.EQ), + LT(Condition.LT), + BT(Condition.BT); + + private final Condition condition; + + CanonicalCondition(Condition condition) { + assert condition.isCanonical(); + this.condition = condition; + } + + public Condition asCondition() { + return condition; + } + + public boolean foldCondition(Constant lt, Constant rt, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) { + return asCondition().foldCondition(lt, rt, constantReflection, unorderedIsTrue); + } + + public boolean foldCondition(PrimitiveConstant lp, PrimitiveConstant rp, boolean unorderedIsTrue) { + return asCondition().foldCondition(lp, rp, unorderedIsTrue); + } +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java Fri Feb 02 17:28:17 2018 -0800 @@ -115,6 +115,55 @@ throw new IllegalArgumentException(this.toString()); } + public static final class CanonicalizedCondition { + private final CanonicalCondition canonicalCondition; + private final boolean mirror; + private final boolean negate; + + private CanonicalizedCondition(CanonicalCondition canonicalCondition, boolean mirror, boolean negate) { + this.canonicalCondition = canonicalCondition; + this.mirror = mirror; + this.negate = negate; + } + + public CanonicalCondition getCanonicalCondition() { + return canonicalCondition; + } + + public boolean mustMirror() { + return mirror; + } + + public boolean mustNegate() { + return negate; + } + } + + public CanonicalizedCondition canonicalize() { + CanonicalCondition canonicalCondition; + switch (this) { + case EQ: + case NE: + canonicalCondition = CanonicalCondition.EQ; + break; + case LT: + case LE: + case GT: + case GE: + canonicalCondition = CanonicalCondition.LT; + break; + case BT: + case BE: + case AT: + case AE: + canonicalCondition = CanonicalCondition.BT; + break; + default: + throw new IllegalArgumentException(this.toString()); + } + return new CanonicalizedCondition(canonicalCondition, canonicalMirror(), canonicalNegate()); + } + /** * Given a condition and its negation, this method returns true for one of the two and false for * the other one. This can be used to keep comparisons in a canonical form. @@ -151,7 +200,7 @@ * Returns true if the condition needs to be mirrored to get to a canonical condition. The * result of the mirroring operation might still need to be negated to achieve a canonical form. */ - public boolean canonicalMirror() { + private boolean canonicalMirror() { switch (this) { case EQ: return false; @@ -181,7 +230,7 @@ * Returns true if the condition needs to be negated to get to a canonical condition. The result * of the negation might still need to be mirrored to achieve a canonical form. */ - public boolean canonicalNegate() { + private boolean canonicalNegate() { switch (this) { case EQ: return false; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ArrayOffsetProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ArrayOffsetProvider.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 2018, 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 org.graalvm.compiler.core.common.spi; + +import jdk.vm.ci.meta.JavaKind; + +public interface ArrayOffsetProvider { + + int arrayBaseOffset(JavaKind elementKind); + + int arrayScalingFactor(JavaKind elementKind); +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/CodeGenProviders.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/CodeGenProviders.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/CodeGenProviders.java Fri Feb 02 17:28:17 2018 -0800 @@ -40,4 +40,5 @@ ConstantReflectionProvider getConstantReflection(); + ArrayOffsetProvider getArrayOffsetProvider(); } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,6 +28,9 @@ import java.util.Objects; import java.util.function.Function; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaKind; + import org.graalvm.compiler.core.common.calc.FloatConvert; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Add; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.And; @@ -51,9 +54,6 @@ import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Sqrt; import org.graalvm.util.CollectionsUtil; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaKind; - /** * Information about arithmetic operations. */ diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,8 +25,8 @@ import java.util.ArrayList; import java.util.List; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; /** * Creates an array of T objects order by the occurrence frequency of each object. The most diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java Fri Feb 02 17:28:17 2018 -0800 @@ -58,6 +58,9 @@ import javax.tools.JavaFileObject; import javax.tools.StandardLocation; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.gen.NodeMatchRules; import org.graalvm.compiler.core.match.ComplexMatchResult; import org.graalvm.compiler.core.match.MatchRule; @@ -70,9 +73,6 @@ import org.graalvm.compiler.graph.Position; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.serviceprovider.ServiceProvider; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; /** * Processes classes annotated with {@link MatchRule}. A {@link MatchStatementSet} service is diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +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 org.graalvm.compiler.core.sparc.test; - -import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure; -import static org.graalvm.compiler.core.common.GraalOptions.TraceRA; -import static org.junit.Assume.assumeTrue; - -import org.junit.Before; -import org.junit.Test; - -import org.graalvm.compiler.core.test.backend.AllocatorTest; - -import jdk.vm.ci.sparc.SPARC; - -public class SPARCAllocatorTest extends AllocatorTest { - - @Before - public void checkSPARC() { - assumeTrue("skipping SPARC specific test", getTarget().arch instanceof SPARC); - assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue(getInitialOptions()) == null); - assumeTrue("TraceRA is set -> skip", !TraceRA.getValue(getInitialOptions())); - } - - @Test - public void test1() { - testAllocation("test1snippet", 2, 0, 0); - } - - public static long test1snippet(long x) { - return x + 41; - } - - @Test - public void test2() { - testAllocation("test2snippet", 2, 0, 0); - } - - public static long test2snippet(long x) { - return x * 41; - } - - @Test - public void test3() { - testAllocation("test3snippet", 4, 0, 0); - } - - public static long test3snippet(long x) { - return x / 41 + x % 41; - } - -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java Fri Feb 02 17:28:17 2018 -0800 @@ -29,6 +29,7 @@ import static jdk.vm.ci.sparc.SPARCKind.XWORD; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.gen.NodeMatchRules; import org.graalvm.compiler.core.match.ComplexMatchResult; @@ -147,7 +148,7 @@ @MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))") public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) { JavaConstant constant = value.asJavaConstant(); - assert compare.condition() == Condition.EQ; + assert compare.condition() == CanonicalCondition.EQ; if (constant != null && cas.usages().count() == 1) { long constantValue = constant.asLong(); boolean successIsTrue; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java Fri Feb 02 17:28:17 2018 -0800 @@ -123,19 +123,19 @@ public static int test6Snippet(int a) { if ((a & 8) != 0) { - GraalDirectives.deoptimizeAndInvalidate(); + GraalDirectives.deoptimize(); } if ((a & 15) != 15) { - GraalDirectives.deoptimizeAndInvalidate(); + GraalDirectives.deoptimize(); } return 0; } public static int reference6Snippet(int a) { if ((a & 8) != 0) { - GraalDirectives.deoptimizeAndInvalidate(); + GraalDirectives.deoptimize(); } - GraalDirectives.deoptimizeAndInvalidate(); + GraalDirectives.deoptimize(); return 0; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Fri Feb 02 17:28:17 2018 -0800 @@ -74,7 +74,6 @@ new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context); canonicalizer.apply(graph, context); canonicalizer.apply(graph, context); - new ConvertDeoptimizeToGuardPhase().apply(graph, context); } catch (Throwable t) { debug.handle(t); } @@ -86,7 +85,6 @@ } canonicalizer.apply(referenceGraph, context); canonicalizer.apply(referenceGraph, context); - new ConvertDeoptimizeToGuardPhase().apply(graph, context); } catch (Throwable t) { debug.handle(t); } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,14 +25,12 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; -import org.graalvm.compiler.nodes.NodeView; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.loop.InductionVariable; import org.graalvm.compiler.loop.LoopsData; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; @@ -42,6 +40,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.junit.Test; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -117,6 +116,21 @@ test("incrementSnippet", 0, 256, 3); } + @Test + public void increment4() { + test("incrementSnippet", -10, Integer.MAX_VALUE, 1); + } + + @Test + public void increment5() { + test("incrementSnippet", 256, 256, 1); + } + + @Test + public void increment6() { + test("incrementSnippet", 257, 256, 1); + } + public static Result incrementEqSnippet(int start, int limit, int step) { int i; int inc = ((step - 1) & 0xFFFF) + 1; // make sure this value is always strictly positive @@ -144,6 +158,21 @@ test("incrementEqSnippet", 0, 256, 3); } + @Test + public void incrementEq4() { + test("incrementEqSnippet", -10, 0, Integer.MAX_VALUE); + } + + @Test + public void incrementEq5() { + test("incrementEqSnippet", 256, 256, 1); + } + + @Test + public void incrementEq6() { + test("incrementEqSnippet", 257, 256, 1); + } + public static Result decrementSnippet(int start, int limit, int step) { int i; int dec = ((step - 1) & 0xFFFF) + 1; // make sure this value is always strictly positive @@ -198,6 +227,11 @@ test("decrementEqSnippet", 256, 0, 3); } + @Test + public void decrementEq4() { + test("decrementEqSnippet", -10, 0, Integer.MAX_VALUE); + } + public static Result twoVariablesSnippet() { Result ret = new Result(); int j = 0; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -27,10 +27,10 @@ import java.nio.file.Files; import java.nio.file.Path; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; import org.junit.Test; /** diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -561,7 +561,7 @@ * @return a scheduled textual dump of {@code graph} . */ protected static String getScheduledGraphString(StructuredGraph graph) { - SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.EARLIEST); + SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); schedule.apply(graph); ScheduleResult scheduleResult = graph.getLastSchedule(); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,14 +22,14 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.debug.DebugOptions; -import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; import org.junit.Assert; import org.junit.Test; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,20 +24,29 @@ import java.util.List; -import org.junit.Assert; - import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.phases.schedule.SchedulePhase; +import org.junit.Assert; + +import jdk.vm.ci.meta.SpeculationLog; public class GraphScheduleTest extends GraalCompilerTest { protected void assertOrderedAfterSchedule(StructuredGraph graph, Node a, Node b) { - SchedulePhase ibp = new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST); + assertOrderedAfterSchedule(graph, SchedulePhase.SchedulingStrategy.LATEST, a, b); + } + + protected void assertOrderedAfterSchedule(StructuredGraph graph, SchedulePhase.SchedulingStrategy strategy, Node a, Node b) { + SchedulePhase ibp = new SchedulePhase(strategy); ibp.apply(graph); + assertOrderedAfterLastSchedule(graph, a, b); + } + + protected void assertOrderedAfterLastSchedule(StructuredGraph graph, Node a, Node b) { assertOrderedAfterSchedule(graph.getLastSchedule(), a, b); } @@ -48,7 +57,7 @@ if (bBlock == aBlock) { List instructions = ibp.nodesFor(bBlock); - Assert.assertTrue(instructions.indexOf(b) > instructions.indexOf(a)); + Assert.assertTrue(a + " should be before " + b, instructions.indexOf(b) > instructions.indexOf(a)); } else { Block block = bBlock; while (block != null) { @@ -60,4 +69,9 @@ Assert.fail("block of A doesn't dominate the block of B"); } } + + @Override + protected SpeculationLog getSpeculationLog() { + return getCodeCache().createSpeculationLog(); + } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.core.test; + +import static org.graalvm.compiler.graph.test.matchers.NodeIterableCount.hasCount; +import static org.graalvm.compiler.graph.test.matchers.NodeIterableIsEmpty.isNotEmpty; +import static org.junit.Assert.assertThat; +import static org.junit.Assume.assumeThat; +import static org.junit.Assume.assumeTrue; + +import java.util.Iterator; + +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.graph.iterators.NodeIterable; +import org.graalvm.compiler.nodes.GuardNode; +import org.graalvm.compiler.nodes.ParameterNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.calc.IntegerLowerThanNode; +import org.graalvm.compiler.nodes.calc.IsNullNode; +import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; +import org.graalvm.compiler.phases.common.FloatingReadPhase; +import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.schedule.SchedulePhase; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Test; + +public class GuardPrioritiesTest extends GraphScheduleTest { + private int[] array; + private int size; + + public void growing(int e) { + if (size >= array.length) { + // grow + GraalDirectives.deoptimizeAndInvalidateWithSpeculation(); + } + array[size++] = e; + } + + @Test + public void growingTest() { + assumeTrue("GuardPriorities must be turned one", GraalOptions.GuardPriorities.getValue(getInitialOptions())); + StructuredGraph graph = prepareGraph("growing"); + + NodeIterable guards = graph.getNodes(GuardNode.TYPE).filter(n -> n.inputs().filter(i -> i instanceof IntegerLowerThanNode).isNotEmpty()); + assertThat(guards, isNotEmpty()); + assumeThat(guards, hasCount(2)); + + Iterator iterator = guards.iterator(); + GuardNode g1 = iterator.next(); + GuardNode g2 = iterator.next(); + assertTrue("There should be one guard with speculation, the other one without", g1.getSpeculation().isNull() ^ g2.getSpeculation().isNull()); + GuardNode withSpeculation = g1.getSpeculation().isNull() ? g2 : g1; + GuardNode withoutSpeculation = g1.getSpeculation().isNull() ? g1 : g2; + + assertOrderedAfterSchedule(graph, SchedulePhase.SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER, withSpeculation, withoutSpeculation); + } + + private StructuredGraph prepareGraph(String method) { + StructuredGraph graph = parseEager(method, StructuredGraph.AllowAssumptions.YES); + HighTierContext highTierContext = getDefaultHighTierContext(); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + new ConvertDeoptimizeToGuardPhase().apply(graph, highTierContext); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext); + new FloatingReadPhase().apply(graph); + return graph; + } + + public int unknownCondition(Integer c, Object o, int[] a, Integer i) { + if (o != null) { + GraalDirectives.deoptimizeAndInvalidate(); + } + if (i > 5560) { + GraalDirectives.deoptimizeAndInvalidate(); + } + if (c >= 10) { + GraalDirectives.deoptimizeAndInvalidateWithSpeculation(); + } + return array[8] + a[i]; + } + + @Test + public void unknownTest() { + assumeTrue("GuardPriorities must be turned one", GraalOptions.GuardPriorities.getValue(getInitialOptions())); + StructuredGraph graph = prepareGraph("unknownCondition"); + + new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER).apply(graph); + for (GuardNode g1 : graph.getNodes(GuardNode.TYPE)) { + for (GuardNode g2 : graph.getNodes(GuardNode.TYPE)) { + if (g1.getSpeculation().isNull() ^ g2.getSpeculation().isNull()) { + GuardNode withSpeculation = g1.getSpeculation().isNull() ? g2 : g1; + GuardNode withoutSpeculation = g1.getSpeculation().isNull() ? g1 : g2; + + if (withoutSpeculation.isNegated() && withoutSpeculation.getCondition() instanceof IsNullNode) { + IsNullNode isNullNode = (IsNullNode) withoutSpeculation.getCondition(); + if (isNullNode.getValue() instanceof ParameterNode && ((ParameterNode) isNullNode.getValue()).index() == 1) { + // this is the null check before the speculative guard, it's the only + // one that should be above + assertOrderedAfterLastSchedule(graph, withoutSpeculation, withSpeculation); + continue; + } + } + + assertOrderedAfterLastSchedule(graph, withSpeculation, withoutSpeculation); + } + } + } + } +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -44,7 +44,7 @@ public static final int N = 10000; - private static final SchedulingStrategy[] Strategies = new SchedulingStrategy[]{SchedulingStrategy.EARLIEST}; + private static final SchedulingStrategy[] Strategies = new SchedulingStrategy[]{SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER}; @Test public void testLongAddChain() { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java Fri Feb 02 17:28:17 2018 -0800 @@ -31,13 +31,13 @@ import java.util.Map; import java.util.Properties; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.MapCursor; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionDescriptor; import org.graalvm.compiler.options.OptionDescriptors; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.MapCursor; /** * An implementation of {@link OptionDescriptor} that uses reflection to create descriptors from a diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java Fri Feb 02 17:28:17 2018 -0800 @@ -70,7 +70,7 @@ returnNode.replaceAtPredecessor(beginNode); beginNode.setNext(returnNode); debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); - SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST); + SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); schedulePhase.apply(graph); ScheduleResult schedule = graph.getLastSchedule(); BlockMap> blockToNodesMap = schedule.getBlockToNodesMap(); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TrivialInliningExplosionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TrivialInliningExplosionTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.core.test; + +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.java.BytecodeParserOptions; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * Tests that the defaults for {@link GraalOptions#TrivialInliningSize} and + * {@link BytecodeParserOptions#InlineDuringParsingMaxDepth} prevent explosive graph growth for code + * with small recursive methods. + */ +public class TrivialInliningExplosionTest extends GraalCompilerTest { + + public static void trivial() { + trivial(); + trivial(); + trivial(); + } + + public static void main() { + trivial(); + trivial(); + trivial(); + trivial(); + trivial(); + trivial(); + trivial(); + trivial(); + trivial(); + } + + private int afterParseSize; + + @Override + protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId, OptionValues options) { + final StructuredGraph graph = super.parseForCompile(method, compilationId, options); + this.afterParseSize = graph.getNodeCount(); + return graph; + } + + @Test + public void test() { + ResolvedJavaMethod methodm0 = getResolvedJavaMethod("trivial"); + Assert.assertTrue(methodm0.getCodeSize() <= GraalOptions.TrivialInliningSize.getValue(getInitialOptions())); + test("main"); + int afterCompileSize = lastCompiledGraph.getNodeCount(); + + // The values of afterParseSize and afterCompileSize when this + // test was written were 849 and 848 respectively. + Assert.assertTrue(afterParseSize < 2000); + Assert.assertTrue(afterCompileSize < 2000); + + } +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,6 +24,7 @@ import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.TTY; @@ -43,7 +44,6 @@ import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; -import org.graalvm.util.EconomicSet; import org.junit.Test; import jdk.vm.ci.meta.ResolvedJavaMethod; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,6 +25,7 @@ import java.util.Collection; import java.util.List; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext; import org.graalvm.compiler.core.common.GraalOptions; @@ -64,7 +65,6 @@ import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.code.TargetDescription; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,6 +26,8 @@ import java.util.Arrays; import java.util.Queue; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; @@ -42,8 +44,6 @@ import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.virtual.nodes.MaterializedObjectState; import org.graalvm.compiler.virtual.nodes.VirtualObjectState; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.VirtualObject; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java Fri Feb 02 17:28:17 2018 -0800 @@ -33,6 +33,8 @@ import java.util.Collection; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.UnmodifiableMapCursor; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; @@ -100,8 +102,6 @@ import org.graalvm.compiler.nodes.spi.NodeValueMap; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.UnmodifiableMapCursor; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.StackSlot; @@ -538,7 +538,8 @@ public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { PlatformKind kind = gen.getLIRKind(compare.getX().stamp(NodeView.DEFAULT)).getPlatformKind(); - gen.emitCompareBranch(kind, operand(compare.getX()), operand(compare.getY()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability); + gen.emitCompareBranch(kind, operand(compare.getX()), operand(compare.getY()), compare.condition().asCondition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, + trueSuccessorProbability); } public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { @@ -566,7 +567,7 @@ } else if (node instanceof CompareNode) { CompareNode compare = (CompareNode) node; PlatformKind kind = gen.getLIRKind(compare.getX().stamp(NodeView.DEFAULT)).getPlatformKind(); - return gen.emitConditionalMove(kind, operand(compare.getX()), operand(compare.getY()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue); + return gen.emitConditionalMove(kind, operand(compare.getX()), operand(compare.getY()), compare.condition().asCondition(), compare.unorderedIsTrue(), trueValue, falseValue); } else if (node instanceof LogicConstantNode) { return gen.emitMove(((LogicConstantNode) node).getValue() ? trueValue : falseValue); } else if (node instanceof IntegerTestNode) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,6 +28,8 @@ import java.util.Arrays; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.match.MatchPattern.Result; import org.graalvm.compiler.debug.DebugContext; @@ -35,8 +37,6 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; /** * Container for state captured during a match. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java Fri Feb 02 17:28:17 2018 -0800 @@ -27,6 +27,9 @@ import java.util.ArrayList; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.MapCursor; import org.graalvm.compiler.core.gen.NodeMatchRules; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; @@ -36,9 +39,6 @@ import org.graalvm.compiler.graph.Position; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.serviceprovider.GraalServices; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; -import org.graalvm.util.MapCursor; public class MatchRuleRegistry { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.core.phases; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Graph.NodeEvent; import org.graalvm.compiler.graph.Graph.NodeEventScope; @@ -32,8 +34,6 @@ import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener; import org.graalvm.compiler.phases.tiers.PhaseContext; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; /** * A utility phase for detecting when a phase would change the graph and reporting extra information diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,6 +24,7 @@ import java.util.ArrayList; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; @@ -44,7 +45,6 @@ import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; @@ -204,31 +204,48 @@ } try (DebugContext.Scope s2 = debug.scope("CodeInstall", debugContext); DebugContext.Activation a = debug.activate()) { - for (CodeInstallationTask task : tasks) { - task.preProcess(compilationResult); + preCodeInstallationTasks(tasks, compilationResult); + + InstalledCode installedCode; + try { + CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult); + installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault); + } catch (Throwable t) { + failCodeInstallationTasks(tasks, t); + throw t; } - CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult); - InstalledCode installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault); + postCodeInstallationTasks(tasks, installedCode); - // Run post-code installation tasks. - try { - for (CodeInstallationTask task : tasks) { - task.postProcess(installedCode); - } - for (CodeInstallationTask task : tasks) { - task.releaseInstallation(installedCode); - } - } catch (Throwable t) { - installedCode.invalidate(); - throw t; - } return installedCode; } catch (Throwable e) { throw debug.handle(e); } } + private static void failCodeInstallationTasks(CodeInstallationTask[] tasks, Throwable t) { + for (CodeInstallationTask task : tasks) { + task.installFailed(t); + } + } + + private static void preCodeInstallationTasks(CodeInstallationTask[] tasks, CompilationResult compilationResult) { + for (CodeInstallationTask task : tasks) { + task.preProcess(compilationResult); + } + } + + private static void postCodeInstallationTasks(CodeInstallationTask[] tasks, InstalledCode installedCode) { + try { + for (CodeInstallationTask task : tasks) { + task.postProcess(installedCode); + } + } catch (Throwable t) { + installedCode.invalidate(); + throw t; + } + } + /** * Installs code based on a given compilation result. * @@ -301,11 +318,10 @@ } /** - * Task to run after all the post-code installation tasks are complete, used to release the - * installed code. + * Invoked after {@link #preProcess} when code installation fails. */ @SuppressWarnings("unused") - public void releaseInstallation(InstalledCode installedCode) { + public void installFailed(Throwable t) { } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -34,6 +34,7 @@ import java.util.Formatter; import java.util.List; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; @@ -46,7 +47,6 @@ import org.graalvm.compiler.debug.DebugVerifyHandler; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; import org.junit.Assert; import org.junit.Assume; import org.junit.Test; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -30,6 +30,7 @@ import java.lang.management.ThreadMXBean; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugOptions; @@ -37,7 +38,6 @@ import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; import org.junit.Assume; import org.junit.Before; import org.junit.Test; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.debug; -import org.graalvm.util.Pair; +import org.graalvm.collections.Pair; class CounterKeyImpl extends AbstractKey implements CounterKey { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java Fri Feb 02 17:28:17 2018 -0800 @@ -56,12 +56,12 @@ import java.util.SortedMap; import java.util.TreeMap; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Pair; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; import org.graalvm.graphio.GraphOutput; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Pair; import jdk.vm.ci.meta.JavaMethod; @@ -1937,10 +1937,17 @@ if (description != null) { printMetrics(description); } - if (metricsEnabled && globalMetrics != null && metricValues != null) { + if (metricsEnabled && metricValues != null && globalMetrics != null) { globalMetrics.add(this); } metricValues = null; + if (sharedChannel != null) { + try { + sharedChannel.realClose(); + } catch (IOException ex) { + // ignore. + } + } } public void closeDumpHandlers(boolean ignoreErrors) { @@ -2022,7 +2029,6 @@ } } } - } /** diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java Fri Feb 02 17:28:17 2018 -0800 @@ -27,11 +27,11 @@ import java.nio.file.Path; import java.nio.file.Paths; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; /** * Options that configure a {@link DebugContext} and related functionality. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java Fri Feb 02 17:28:17 2018 -0800 @@ -29,10 +29,10 @@ import java.util.Collections; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.MapCursor; +import org.graalvm.collections.Pair; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.MapCursor; -import org.graalvm.util.Pair; /** * Metric values that can be {@linkplain #add(DebugContext) updated} by multiple threads. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,7 +25,7 @@ import java.util.ArrayList; import java.util.List; -import org.graalvm.util.EconomicMap; +import org.graalvm.collections.EconomicMap; /** * Registry for allocating a globally unique integer id to each {@link AbstractKey}. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,7 +24,7 @@ import static org.graalvm.compiler.debug.DebugCloseable.VOID_CLOSEABLE; -import org.graalvm.util.Pair; +import org.graalvm.collections.Pair; class MemUseTrackerKeyImpl extends AccumulatedKey implements MemUseTrackerKey { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,7 +24,7 @@ import java.util.Comparator; -import org.graalvm.util.Pair; +import org.graalvm.collections.Pair; /** * A key for a metric. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,7 +26,7 @@ import java.util.concurrent.TimeUnit; -import org.graalvm.util.Pair; +import org.graalvm.collections.Pair; final class TimerKeyImpl extends AccumulatedKey implements TimerKey { static class FlatTimer extends AbstractKey implements TimerKey { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,7 +24,7 @@ import java.util.function.Consumer; -import org.graalvm.util.UnmodifiableEconomicMap; +import org.graalvm.collections.UnmodifiableEconomicMap; /** * This class is a container of a graph that needs to be readonly and optionally a lazily created diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Fri Feb 02 17:28:17 2018 -0800 @@ -30,6 +30,9 @@ import java.util.Iterator; import java.util.function.Consumer; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.UnmodifiableEconomicMap; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; @@ -41,9 +44,6 @@ import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; -import org.graalvm.util.UnmodifiableEconomicMap; /** * This class is a graph container, it contains the set of nodes that belong to this graph. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java Fri Feb 02 17:28:17 2018 -0800 @@ -160,6 +160,12 @@ } } + public void invert() { + for (int i = 0; i < bits.length; i++) { + bits[i] = ~bits[i]; + } + } + public void grow() { nodeCount = Math.max(nodeCount, graph().nodeIdCount()); int newLength = sizeForNodeCount(nodeCount); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Fri Feb 02 17:28:17 2018 -0800 @@ -42,6 +42,8 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.FieldIntrospection; import org.graalvm.compiler.core.common.Fields; import org.graalvm.compiler.core.common.FieldsScanner; @@ -65,8 +67,6 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodeinfo.Verbosity; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; /** * Metadata for every {@link Node} type. The metadata includes: diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,8 +26,8 @@ import java.util.Iterator; import java.util.function.BiFunction; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.MapCursor; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.MapCursor; public class NodeMap extends NodeIdAccessor implements EconomicMap { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java Fri Feb 02 17:28:17 2018 -0800 @@ -74,6 +74,10 @@ return tos == 0; } + public void clear() { + tos = 0; + } + @Override public String toString() { if (tos == 0) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.hotspot.aarch64; -import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; import static java.lang.reflect.Modifier.isStatic; import static jdk.vm.ci.aarch64.AArch64.lr; import static jdk.vm.ci.aarch64.AArch64.r10; @@ -30,7 +29,9 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; +import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Address; @@ -42,11 +43,11 @@ import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotDataBuilder; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotHostBackend; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -64,7 +65,6 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java Fri Feb 02 17:28:17 2018 -0800 @@ -49,6 +49,7 @@ import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.util.Providers; @@ -136,7 +137,7 @@ replacements = createReplacements(graalRuntime.getOptions(), p, snippetReflection, bytecodeProvider); } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { - plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); + plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, lowerer, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); replacements.setGraphBuilderPlugins(plugins); } try (InitTimer rt = timer("create Suites provider")) { @@ -152,9 +153,10 @@ } protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotConstantReflectionProvider constantReflection, - HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, - HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) { - Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); + HotSpotHostForeignCallsProvider foreignCalls, LoweringProvider lowerer, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, + HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) { + Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, lowerer, stampProvider, + replacements); AArch64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider()); return plugins; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/ArrayAccessInLoopToAddressTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/ArrayAccessInLoopToAddressTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018, 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 org.graalvm.compiler.hotspot.amd64.test; + +import jdk.vm.ci.hotspot.HotSpotSpeculationLog; +import jdk.vm.ci.meta.SpeculationLog; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.junit.Test; + +public class ArrayAccessInLoopToAddressTest extends GraalCompilerTest { + + public static int positiveInductionVariable(short[] array) { + int sum = 0; + for (int i = 0; i < array.length - 1; i++) { + sum += array[i + 1]; + } + return sum; + } + + @Test + public void testPositiveInductionVariable() { + test("positiveInductionVariable", new short[]{1, 3, 7, 9}); + } + + public static int negativeInductionVariable(short[] array) { + int sum = 0; + for (int i = -array.length; i < array.length - 4; i++) { + sum += array[i + 4]; + } + return sum; + } + + @Test + public void testNegativeInductionVariable() { + test("negativeInductionVariable", new short[]{1, 3, 7, 9}); + } + + @Override + protected SpeculationLog getSpeculationLog() { + return new HotSpotSpeculationLog(); + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,64 +24,50 @@ package org.graalvm.compiler.hotspot.amd64; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; -import org.graalvm.compiler.core.amd64.AMD64AddressLowering; import org.graalvm.compiler.core.amd64.AMD64AddressNode; +import org.graalvm.compiler.core.amd64.AMD64CompressAddressLowering; import org.graalvm.compiler.core.common.CompressEncoding; -import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.ObjectStamp; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.CounterKey; -import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; -import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.loop.BasicInductionVariable; +import org.graalvm.compiler.loop.CountedLoopInfo; +import org.graalvm.compiler.loop.DerivedInductionVariable; +import org.graalvm.compiler.loop.InductionVariable; +import org.graalvm.compiler.loop.LoopEx; +import org.graalvm.compiler.loop.LoopsData; import org.graalvm.compiler.nodes.CompressionNode; -import org.graalvm.compiler.nodes.CompressionNode.CompressionOp; +import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; +import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.nodes.calc.AddNode; +import org.graalvm.compiler.nodes.calc.SignExtendNode; +import org.graalvm.compiler.nodes.calc.ZeroExtendNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; +import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.JavaKind; -public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { +public class AMD64HotSpotAddressLowering extends AMD64CompressAddressLowering { - private static final CounterKey counterFoldedUncompressDuringAddressLowering = DebugContext.counter("FoldedUncompressDuringAddressLowering"); + private static final int ADDRESS_BITS = 64; + private static final int INT_BITS = 32; private final long heapBase; private final Register heapBaseRegister; private final GraalHotSpotVMConfig config; private final boolean generatePIC; - @NodeInfo(cycles = CYCLES_0, size = SIZE_0) - public static class HeapBaseNode extends FloatingNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(HeapBaseNode.class); - - private final Register heapBaseRegister; - - public HeapBaseNode(Register heapBaseRegister) { - super(TYPE, StampFactory.pointer()); - this.heapBaseRegister = heapBaseRegister; - } - - @Override - public void generate(NodeLIRBuilderTool generator) { - LIRKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT)); - generator.setResult(this, heapBaseRegister.asValue(kind)); - } - } - public AMD64HotSpotAddressLowering(GraalHotSpotVMConfig config, Register heapBaseRegister, OptionValues options) { this.heapBase = config.getOopEncoding().getBase(); this.config = config; @@ -94,35 +80,7 @@ } @Override - protected boolean improve(StructuredGraph graph, DebugContext debug, AMD64AddressNode addr, boolean isBaseNegated, boolean isIndexNegated) { - if (super.improve(graph, debug, addr, isBaseNegated, isIndexNegated)) { - return true; - } - - if (addr.getScale() == Scale.Times1) { - if (addr.getIndex() instanceof CompressionNode) { - if (improveUncompression(addr, (CompressionNode) addr.getIndex(), addr.getBase(), isBaseNegated, isIndexNegated)) { - counterFoldedUncompressDuringAddressLowering.increment(debug); - return true; - } - } - - if (addr.getBase() instanceof CompressionNode) { - if (improveUncompression(addr, (CompressionNode) addr.getBase(), addr.getIndex(), isBaseNegated, isIndexNegated)) { - counterFoldedUncompressDuringAddressLowering.increment(debug); - return true; - } - } - } - - return false; - } - - private boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other, boolean isBaseNegated, boolean isIndexNegated) { - if (isBaseNegated || isIndexNegated || compression.getOp() != CompressionOp.Uncompress) { - return false; - } - + protected final boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other) { CompressEncoding encoding = compression.getEncoding(); Scale scale = Scale.fromShift(encoding.getShift()); if (scale == null) { @@ -147,7 +105,7 @@ return false; } } else { - if (updateDisplacement(addr, encoding.getBase(), isBaseNegated)) { + if (updateDisplacement(addr, encoding.getBase(), false)) { addr.setBase(other); } else { return false; @@ -161,4 +119,117 @@ addr.setIndex(compression.getValue()); return true; } + + @Override + public void preProcess(StructuredGraph graph) { + if (graph.hasLoops()) { + LoopsData loopsData = new LoopsData(graph); + loopsData.detectedCountedLoops(); + for (LoopEx loop : loopsData.countedLoops()) { + for (OffsetAddressNode offsetAdressNode : loop.whole().nodes().filter(OffsetAddressNode.class)) { + tryOptimize(offsetAdressNode, loop); + } + } + } + } + + @Override + public void postProcess(AddressNode lowered) { + // Allow implicit zero extend for always positive input. This + // assumes that the upper bits of the operand is zero out by + // the backend. + AMD64AddressNode address = (AMD64AddressNode) lowered; + address.setBase(tryImplicitZeroExtend(address.getBase())); + address.setIndex(tryImplicitZeroExtend(address.getIndex())); + } + + private static void tryOptimize(OffsetAddressNode offsetAddress, LoopEx loop) { + EconomicMap ivs = loop.getInductionVariables(); + InductionVariable currentIV = ivs.get(offsetAddress.getOffset()); + while (currentIV != null) { + if (!(currentIV instanceof DerivedInductionVariable)) { + break; + } + ValueNode currentValue = currentIV.valueNode(); + if (currentValue.isDeleted()) { + break; + } + + if (currentValue instanceof ZeroExtendNode) { + ZeroExtendNode zeroExtendNode = (ZeroExtendNode) currentValue; + if (applicableToImplicitZeroExtend(zeroExtendNode)) { + ValueNode input = zeroExtendNode.getValue(); + if (input instanceof AddNode) { + AddNode add = (AddNode) input; + if (add.getX().isConstant()) { + optimizeAdd(zeroExtendNode, (ConstantNode) add.getX(), add.getY(), loop); + } else if (add.getY().isConstant()) { + optimizeAdd(zeroExtendNode, (ConstantNode) add.getY(), add.getX(), loop); + } + } + } + } + + currentIV = ((DerivedInductionVariable) currentIV).getBase(); + } + } + + /** + * Given that Add(a, cst) is always positive, performs the following: ZeroExtend(Add(a, cst)) -> + * Add(SignExtend(a), SignExtend(cst)). + */ + private static void optimizeAdd(ZeroExtendNode zeroExtendNode, ConstantNode constant, ValueNode other, LoopEx loop) { + StructuredGraph graph = zeroExtendNode.graph(); + AddNode addNode = graph.unique(new AddNode(signExtend(other, loop), ConstantNode.forLong(constant.asJavaConstant().asInt(), graph))); + zeroExtendNode.replaceAtUsages(addNode); + } + + /** + * Create a sign extend for {@code input}, or zero extend if {@code input} can be proven + * positive. + */ + private static ValueNode signExtend(ValueNode input, LoopEx loop) { + StructuredGraph graph = input.graph(); + if (input instanceof PhiNode) { + EconomicMap ivs = loop.getInductionVariables(); + InductionVariable inductionVariable = ivs.get(input); + if (inductionVariable != null && inductionVariable instanceof BasicInductionVariable) { + CountedLoopInfo countedLoopInfo = loop.counted(); + IntegerStamp initStamp = (IntegerStamp) inductionVariable.initNode().stamp(NodeView.DEFAULT); + if (initStamp.isPositive()) { + if (inductionVariable.isConstantExtremum()) { + long init = inductionVariable.constantInit(); + long stride = inductionVariable.constantStride(); + long extremum = inductionVariable.constantExtremum(); + + if (init >= 0 && extremum >= 0) { + long shortestTrip = (extremum - init) / stride + 1; + if (shortestTrip == countedLoopInfo.constantMaxTripCount()) { + return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true)); + } + } + } + if (countedLoopInfo.getCounter() == inductionVariable && inductionVariable.direction() == InductionVariable.Direction.Up && countedLoopInfo.getOverFlowGuard() != null) { + return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true)); + } + } + } + } + return input.graph().maybeAddOrUnique(SignExtendNode.create(input, ADDRESS_BITS, NodeView.DEFAULT)); + } + + private static boolean applicableToImplicitZeroExtend(ZeroExtendNode zeroExtendNode) { + return zeroExtendNode.isInputAlwaysPositive() && zeroExtendNode.getInputBits() == INT_BITS && zeroExtendNode.getResultBits() == ADDRESS_BITS; + } + + private static ValueNode tryImplicitZeroExtend(ValueNode input) { + if (input instanceof ZeroExtendNode) { + ZeroExtendNode zeroExtendNode = (ZeroExtendNode) input; + if (applicableToImplicitZeroExtend(zeroExtendNode)) { + return zeroExtendNode.getValue(); + } + } + return input; + } + } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java Fri Feb 02 17:28:17 2018 -0800 @@ -30,6 +30,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; @@ -66,7 +67,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Fri Feb 02 17:28:17 2018 -0800 @@ -49,6 +49,7 @@ import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; @@ -137,7 +138,7 @@ replacements = createReplacements(options, p, snippetReflection, bytecodeProvider); } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { - plugins = createGraphBuilderPlugins(compilerConfiguration, config, options, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, + plugins = createGraphBuilderPlugins(compilerConfiguration, config, options, target, constantReflection, foreignCalls, lowerer, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); replacements.setGraphBuilderPlugins(plugins); } @@ -154,9 +155,10 @@ } protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, OptionValues options, TargetDescription target, - HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, + HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, LoweringProvider lowerer, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) { - Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); + Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, lowerer, stampProvider, + replacements); AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue(options)); return plugins; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Feb 02 17:28:17 2018 -0800 @@ -572,7 +572,7 @@ if (inputKind.isReference(0)) { // oop Variable result = newVariable(lirKindTool.getNarrowOopKind()); - append(new AMD64Move.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull, getLIRKindTool())); + append(new AMD64Move.CompressPointerOp(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull, getLIRKindTool())); return result; } else { // metaspace pointer @@ -589,7 +589,7 @@ base = emitLoadConstant(lirKindTool.getWordKind(), JavaConstant.forLong(encoding.getBase())); } } - append(new AMD64Move.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull, getLIRKindTool())); + append(new AMD64Move.CompressPointerOp(result, asAllocatable(pointer), base, encoding, nonNull, getLIRKindTool())); return result; } } @@ -602,7 +602,7 @@ if (inputKind.isReference(0)) { // oop Variable result = newVariable(lirKindTool.getObjectKind()); - append(new AMD64Move.UncompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull, lirKindTool)); + append(new AMD64Move.UncompressPointerOp(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull, lirKindTool)); return result; } else { // metaspace pointer @@ -620,7 +620,7 @@ base = emitLoadConstant(uncompressedKind, JavaConstant.forLong(encoding.getBase())); } } - append(new AMD64Move.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull, lirKindTool)); + append(new AMD64Move.UncompressPointerOp(result, asAllocatable(pointer), base, encoding, nonNull, lirKindTool)); return result; } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java Fri Feb 02 17:28:17 2018 -0800 @@ -67,7 +67,8 @@ public void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config) { convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) - ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget()) : null; + ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget()) + : null; super.initialize(options, factories, providers, config); } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java Fri Feb 02 17:28:17 2018 -0800 @@ -60,6 +60,7 @@ crb.recordMark(invokeKind == InvokeKind.Virtual ? config.MARKID_INVOKEVIRTUAL : config.MARKID_INVOKEINTERFACE); // This must be emitted exactly like this to ensure it's patchable masm.movq(AMD64.rax, config.nonOopBits); - super.emitCode(crb, masm); + int offset = super.emitCall(crb, masm); + crb.recordInvokeVirtualOrInterfaceCallOp(offset, getPosition()); } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java Fri Feb 02 17:28:17 2018 -0800 @@ -70,7 +70,8 @@ crb.recordMark(config.MARKID_INLINE_INVOKE); Register callReg = asRegister(targetAddress); assert !callReg.equals(METHOD); - AMD64Call.indirectCall(crb, masm, callReg, callTarget, state); + int pcOffset = AMD64Call.indirectCall(crb, masm, callReg, callTarget, state); + crb.recordInlineInvokeCallOp(pcOffset, getPosition()); } @Override diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013, 2018, 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 org.graalvm.compiler.core.sparc.test; + +import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure; +import static org.graalvm.compiler.core.common.GraalOptions.TraceRA; +import static org.junit.Assume.assumeTrue; + +import org.graalvm.compiler.core.test.backend.AllocatorTest; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotBackend; +import org.junit.Before; +import org.junit.Test; + +import jdk.vm.ci.sparc.SPARC; + +public class SPARCAllocatorTest extends AllocatorTest { + + private final GraalHotSpotVMConfig config = ((HotSpotBackend) getBackend()).getRuntime().getVMConfig(); + + @Before + public void checkSPARC() { + assumeTrue("skipping SPARC specific test", getTarget().arch instanceof SPARC); + assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue(getInitialOptions()) == null); + assumeTrue("TraceRA is set -> skip", !TraceRA.getValue(getInitialOptions())); + } + + @Test + public void test1() { + testAllocation("test1snippet", config.threadLocalHandshakes ? 1 : 2, 0, 0); + } + + public static long test1snippet(long x) { + return x + 41; + } + + @Test + public void test2() { + testAllocation("test2snippet", config.threadLocalHandshakes ? 1 : 2, 0, 0); + } + + public static long test2snippet(long x) { + return x * 41; + } + + @Test + public void test3() { + testAllocation("test3snippet", config.threadLocalHandshakes ? 3 : 4, 0, 0); + } + + public static long test3snippet(long x) { + return x / 41 + x % 41; + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java Fri Feb 02 17:28:17 2018 -0800 @@ -46,6 +46,9 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.sparc.SPARCAddress; @@ -92,9 +95,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java Fri Feb 02 17:28:17 2018 -0800 @@ -101,7 +101,7 @@ HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes); BytecodeProvider bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(runtime.getOptions(), p, snippetReflection, bytecodeProvider, target); - Plugins plugins = createGraphBuilderPlugins(compilerConfiguration, config, metaAccess, constantReflection, foreignCalls, stampProvider, snippetReflection, replacements, wordTypes); + Plugins plugins = createGraphBuilderPlugins(compilerConfiguration, config, metaAccess, constantReflection, foreignCalls, lowerer, stampProvider, snippetReflection, replacements, wordTypes); replacements.setGraphBuilderPlugins(plugins); HotSpotSuitesProvider suites = createSuites(config, runtime, compilerConfiguration, plugins, replacements); HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, @@ -112,9 +112,10 @@ } protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotMetaAccessProvider metaAccess, - HotSpotConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls, HotSpotStampProvider stampProvider, + HotSpotConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls, LoweringProvider lowerer, HotSpotStampProvider stampProvider, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) { - Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); + Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, lowerer, stampProvider, + replacements); SPARCGraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider()); return plugins; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayNewInstanceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayNewInstanceTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.hotspot.test; + +import java.lang.reflect.Array; +import java.util.ArrayList; + +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class ArrayNewInstanceTest extends GraalCompilerTest { + + @Parameters(name = "{index}: class {0} length {1}") + public static Iterable data() { + ArrayList parameters = new ArrayList<>(); + Class[] classesToTest = new Class[]{ + byte.class, + boolean.class, + short.class, + char.class, + int.class, + long.class, + Void.class, + ArrayNewInstanceTest.class + }; + for (Class clazz : classesToTest) { + // Negative sizes always deopt + parameters.add(new Object[]{clazz, -1, true}); + parameters.add(new Object[]{clazz, 0, false}); + parameters.add(new Object[]{clazz, 42, false}); + } + // The void type always throws an exception where graal deopts + parameters.add(new Object[]{void.class, -1, true}); + parameters.add(new Object[]{void.class, 0, true}); + parameters.add(new Object[]{void.class, 42, true}); + return parameters; + } + + private final Class type; + private final int length; + private final boolean shouldDeopt; + private final DeoptimizationBox box = new DeoptimizationBox(); + + public ArrayNewInstanceTest(Class type, int length, boolean shouldDeopt) { + super(); + this.type = type; + this.length = length; + this.shouldDeopt = shouldDeopt; + } + + public static Object newArray(Class klass, int length, DeoptimizationBox box) { + Object result = Array.newInstance(klass, length); + box.inCompiledCode = GraalDirectives.inCompiledCode(); + return result; + } + + @Test + public void testNewArray() { + test("newArray", type, length, box); + assertTrue(box.inCompiledCode != shouldDeopt); + } + + public static Object newArrayInLoop(Class klass, int length, int iterations, DeoptimizationBox box) { + Object o = null; + for (int i = 0; i < iterations; i++) { + o = Array.newInstance(klass, length); + } + box.inCompiledCode = GraalDirectives.inCompiledCode(); + return o; + } + + @Test + public void testNewArrayInLoop() { + test("newArrayInLoop", type, length, 2, box); + assertTrue(box.inCompiledCode != shouldDeopt); + } + + private static class DeoptimizationBox { + volatile boolean inCompiledCode = false; + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Fri Feb 02 17:28:17 2018 -0800 @@ -32,6 +32,8 @@ import java.util.TreeSet; import java.util.stream.Collectors; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.MapCursor; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; @@ -43,8 +45,6 @@ import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.serviceprovider.JDK9Method; import org.graalvm.compiler.test.GraalTest; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.MapCursor; import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; @@ -416,6 +416,12 @@ "java/lang/StringUTF16.toBytes([CII)[B"); } + if (isJDK10OrHigher()) { + add(TO_BE_INVESTIGATED, + "java/lang/Math.multiplyHigh(JJ)J", + "jdk/internal/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I"); + } + if (!getHostArchitectureName().equals("amd64")) { // Can we implement these on non-AMD64 platforms? C2 seems to. add(TO_BE_INVESTIGATED, @@ -539,6 +545,10 @@ return JDK9Method.JAVA_SPECIFICATION_VERSION >= 9; } + private static boolean isJDK10OrHigher() { + return JDK9Method.JAVA_SPECIFICATION_VERSION >= 10; + } + private static String getHostArchitectureName() { String arch = System.getProperty("os.arch"); if (arch.equals("x86_64")) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Fri Feb 02 17:28:17 2018 -0800 @@ -68,6 +68,8 @@ import java.util.jar.JarFile; import java.util.stream.Collectors; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.UnmodifiableEconomicMap; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.bytecode.Bytecodes; import org.graalvm.compiler.core.CompilerThreadFactory; @@ -85,8 +87,6 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionsParser; import org.graalvm.compiler.serviceprovider.JDK9Method; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.UnmodifiableEconomicMap; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,12 +25,12 @@ import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction; import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -32,6 +32,7 @@ import java.util.HashSet; import java.util.List; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.core.phases.HighTier; import org.graalvm.compiler.debug.DebugContext; @@ -40,13 +41,12 @@ import org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; import org.junit.Test; import jdk.vm.ci.meta.ResolvedJavaMethod; -import org.junit.Assume; -import org.junit.BeforeClass; /** * Test on-stack-replacement with locks. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -31,8 +31,8 @@ import java.lang.management.ManagementFactory; import java.lang.reflect.Field; +import java.util.Arrays; -import java.util.Arrays; import javax.management.Attribute; import javax.management.MBeanAttributeInfo; import javax.management.MBeanInfo; @@ -41,11 +41,11 @@ import javax.management.ObjectInstance; import javax.management.ObjectName; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.hotspot.HotSpotGraalMBean; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.test.GraalTest; -import org.graalvm.util.EconomicMap; import org.junit.Assume; import org.junit.Test; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java Fri Feb 02 17:28:17 2018 -0800 @@ -23,8 +23,10 @@ package org.graalvm.compiler.hotspot.test; import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; + import java.util.List; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.DebugContext; @@ -36,10 +38,9 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding; +import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.runtime.RuntimeProvider; -import org.graalvm.util.EconomicMap; import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,6 +24,7 @@ import java.util.List; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext.Scope; @@ -58,7 +59,6 @@ import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.MidTierContext; -import org.graalvm.util.EconomicMap; import org.graalvm.word.LocationIdentity; import org.junit.Assert; import org.junit.Test; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Fri Feb 02 17:28:17 2018 -0800 @@ -29,6 +29,7 @@ import java.util.List; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.CompilationPrinter; @@ -45,7 +46,6 @@ import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.printer.GraalDebugHandlersFactory; -import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java Fri Feb 02 17:28:17 2018 -0800 @@ -29,6 +29,7 @@ import java.util.List; import java.util.stream.Collectors; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionKey; @@ -36,7 +37,6 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.serviceprovider.GraalServices; -import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.common.InitTimer; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Fri Feb 02 17:28:17 2018 -0800 @@ -64,10 +64,10 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.word.Word; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; -import org.graalvm.util.MapCursor; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.MapCursor; import org.graalvm.word.Pointer; import jdk.vm.ci.code.CompilationRequest; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java Fri Feb 02 17:28:17 2018 -0800 @@ -98,8 +98,8 @@ ByteBuffer buffer = ByteBuffer.wrap(dataSection).order(ByteOrder.nativeOrder()); Builder patchBuilder = Stream.builder(); - data.buildDataSection(buffer, vmConstant -> { - patchBuilder.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant))); + data.buildDataSection(buffer, (position, vmConstant) -> { + patchBuilder.accept(new DataPatch(position, new ConstantReference(vmConstant))); }); int dataSectionAlignment = data.getSectionAlignment(); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,11 +22,13 @@ */ package org.graalvm.compiler.hotspot; +import static jdk.vm.ci.code.ValueUtil.isRegister; import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; -import static jdk.vm.ci.code.ValueUtil.isRegister; import java.util.Arrays; + +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; @@ -34,7 +36,6 @@ import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.TargetDescription; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java Fri Feb 02 17:28:17 2018 -0800 @@ -56,41 +56,30 @@ @Override public Data createDataItem(Constant constant) { - int size; - if (constant instanceof VMConstant) { + if (JavaConstant.isNull(constant)) { + boolean compressed = COMPRESSED_NULL.equals(constant); + int size = compressed ? 4 : target.wordSize; + return ZeroData.create(size, size); + } else if (constant instanceof VMConstant) { VMConstant vmConstant = (VMConstant) constant; - boolean compressed; - if (constant instanceof HotSpotConstant) { - HotSpotConstant c = (HotSpotConstant) vmConstant; - compressed = c.isCompressed(); - } else { + if (!(constant instanceof HotSpotConstant)) { throw new GraalError(String.valueOf(constant)); } - size = compressed ? 4 : target.wordSize; - if (size == 4) { - return new Data(size, size) { - - @Override - protected void emit(ByteBuffer buffer, Patches patches) { - patches.registerPatch(vmConstant); + HotSpotConstant c = (HotSpotConstant) vmConstant; + int size = c.isCompressed() ? 4 : target.wordSize; + return new Data(size, size) { + @Override + protected void emit(ByteBuffer buffer, Patches patches) { + int position = buffer.position(); + if (getSize() == Integer.BYTES) { buffer.putInt(0xDEADDEAD); - } - }; - } else { - return new Data(size, size) { - - @Override - protected void emit(ByteBuffer buffer, Patches patches) { - patches.registerPatch(vmConstant); + } else { buffer.putLong(0xDEADDEADDEADDEADL); } - }; - } - } else if (JavaConstant.isNull(constant)) { - boolean compressed = COMPRESSED_NULL.equals(constant); - size = compressed ? 4 : target.wordSize; - return ZeroData.create(size, size); + patches.registerPatch(position, vmConstant); + } + }; } else if (constant instanceof SerializableConstant) { SerializableConstant s = (SerializableConstant) constant; return new SerializableData(s); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,15 +22,15 @@ */ package org.graalvm.compiler.hotspot; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.word.WordTypes; -import org.graalvm.util.EconomicSet; import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CallingConvention; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java Fri Feb 02 17:28:17 2018 -0800 @@ -44,10 +44,10 @@ import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionsParser; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; -import org.graalvm.util.UnmodifiableEconomicMap; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.UnmodifiableEconomicMap; public final class HotSpotGraalMBean implements javax.management.DynamicMBean { private static Object mBeanServerField; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java Fri Feb 02 17:28:17 2018 -0800 @@ -30,6 +30,7 @@ import java.util.Map; import java.util.Properties; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionDescriptors; import org.graalvm.compiler.options.OptionKey; @@ -37,7 +38,6 @@ import org.graalvm.compiler.options.OptionValuesAccess; import org.graalvm.compiler.options.OptionsParser; import org.graalvm.compiler.serviceprovider.ServiceProvider; -import org.graalvm.util.EconomicMap; import jdk.vm.ci.common.InitTimer; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Fri Feb 02 17:28:17 2018 -0800 @@ -34,6 +34,8 @@ import java.util.List; import java.util.Map; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.runtime.GraalRuntime; import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction; @@ -57,8 +59,6 @@ import org.graalvm.compiler.replacements.SnippetCounter; import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.runtime.RuntimeProvider; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.stack.StackIntrospection; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.hotspot; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.lir.LIR; @@ -29,8 +31,6 @@ import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; import org.graalvm.compiler.lir.gen.LIRGenerationResult; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.StackSlot; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java Fri Feb 02 17:28:17 2018 -0800 @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.List; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; @@ -42,7 +43,6 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; -import org.graalvm.util.EconomicMap; import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CallingConvention; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Fri Feb 02 17:28:17 2018 -0800 @@ -31,6 +31,7 @@ import java.lang.invoke.ConstantCallSite; import java.lang.invoke.MutableCallSite; import java.lang.invoke.VolatileCallSite; +import java.lang.reflect.Array; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.math.BigInteger; @@ -39,17 +40,20 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode; import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions; import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions; +import org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions; import org.graalvm.compiler.hotspot.replacements.CRC32Substitutions; -import org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions; import org.graalvm.compiler.hotspot.replacements.CallSiteTargetNode; import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions; import org.graalvm.compiler.hotspot.replacements.ClassGetHubNode; +import org.graalvm.compiler.hotspot.replacements.HotSpotArraySubstitutions; import org.graalvm.compiler.hotspot.replacements.HotSpotClassSubstitutions; import org.graalvm.compiler.hotspot.replacements.IdentityHashCodeNode; import org.graalvm.compiler.hotspot.replacements.ObjectCloneNode; @@ -68,7 +72,6 @@ import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.IntegerConvertNode; @@ -83,8 +86,10 @@ import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory; import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; +import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; +import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; @@ -123,12 +128,12 @@ * @param stampProvider */ public static Plugins create(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, - ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, - ReplacementsImpl replacements) { + ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, LoweringProvider lowerer, + StampProvider stampProvider, ReplacementsImpl replacements) { InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, compilerConfiguration); Plugins plugins = new Plugins(invocationPlugins); - NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes); + NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, lowerer, wordTypes); HotSpotWordOperationPlugin wordOperationPlugin = new HotSpotWordOperationPlugin(snippetReflection, wordTypes); HotSpotNodePlugin nodePlugin = new HotSpotNodePlugin(wordOperationPlugin); @@ -171,6 +176,7 @@ registerSHAPlugins(invocationPlugins, config, replacementBytecodeProvider); registerUnsafePlugins(invocationPlugins, replacementBytecodeProvider); StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, snippetReflection, invocationPlugins, replacementBytecodeProvider, true); + registerArrayPlugins(invocationPlugins, replacementBytecodeProvider); for (NodeIntrinsicPluginFactory factory : GraalServices.load(NodeIntrinsicPluginFactory.class)) { factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider); @@ -401,19 +407,23 @@ }); } + private static void registerArrayPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { + Registration r = new Registration(plugins, Array.class, bytecodeProvider); + r.setAllowOverwrite(true); + r.registerMethodSubstitution(HotSpotArraySubstitutions.class, "newInstance", Class.class, int.class); + } + private static void registerThreadPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, WordTypes wordTypes, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { Registration r = new Registration(plugins, Thread.class, bytecodeProvider); r.register0("currentThread", new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { CurrentJavaThreadNode thread = b.add(new CurrentJavaThreadNode(wordTypes.getWordKind())); - boolean compressible = false; ValueNode offset = b.add(ConstantNode.forLong(config.threadObjectOffset)); AddressNode address = b.add(new OffsetAddressNode(thread, offset)); - ValueNode javaThread = WordOperationPlugin.readOp(b, JavaKind.Object, address, JAVA_THREAD_THREAD_OBJECT_LOCATION, BarrierType.NONE, compressible); - boolean exactType = false; - boolean nonNull = true; - b.addPush(JavaKind.Object, new PiNode(javaThread, metaAccess.lookupJavaType(Thread.class), exactType, nonNull)); + // JavaThread::_threadObj is never compressed + ObjectStamp stamp = StampFactory.objectNonNull(TypeReference.create(b.getAssumptions(), metaAccess.lookupJavaType(Thread.class))); + b.addPush(JavaKind.Object, new ReadNode(address, JAVA_THREAD_THREAD_OBJECT_LOCATION, stamp, BarrierType.NONE)); return true; } }); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Fri Feb 02 17:28:17 2018 -0800 @@ -101,6 +101,7 @@ import java.util.EnumMap; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.debug.GraalError; @@ -123,7 +124,6 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; -import org.graalvm.util.EconomicMap; import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CodeCacheProvider; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java Fri Feb 02 17:28:17 2018 -0800 @@ -27,6 +27,7 @@ import java.lang.reflect.Type; import java.util.Set; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; @@ -42,7 +43,6 @@ import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.replacements.nodes.MacroNode; import org.graalvm.compiler.serviceprovider.JDK9Method; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; import jdk.vm.ci.meta.JavaKind; @@ -122,7 +122,7 @@ * of its module dependencies are trusted. */ @Override - protected boolean canBeIntrinsified(ResolvedJavaType declaringClass) { + public boolean canBeIntrinsified(ResolvedJavaType declaringClass) { if (declaringClass instanceof HotSpotResolvedJavaType) { Class javaClass = ((HotSpotResolvedJavaType) declaringClass).mirror(); if (Java8OrEarlier) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.meta; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -104,4 +105,9 @@ } return null; } + + @Override + public Class originalClass(ResolvedJavaType type) { + return ((HotSpotResolvedJavaType) type).mirror(); + } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ArrayRangeWriteBarrier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ArrayRangeWriteBarrier.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ArrayRangeWriteBarrier.java Fri Feb 02 17:28:17 2018 -0800 @@ -23,34 +23,37 @@ package org.graalvm.compiler.hotspot.nodes; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.spi.Lowerable; @NodeInfo public abstract class ArrayRangeWriteBarrier extends WriteBarrier implements Lowerable { public static final NodeClass TYPE = NodeClass.create(ArrayRangeWriteBarrier.class); - @Input ValueNode object; - @Input ValueNode startIndex; + @Input(InputType.Association) AddressNode address; @Input ValueNode length; - protected ArrayRangeWriteBarrier(NodeClass c, ValueNode object, ValueNode startIndex, ValueNode length) { + private final int elementStride; + + protected ArrayRangeWriteBarrier(NodeClass c, AddressNode address, ValueNode length, int elementStride) { super(c); - this.object = object; - this.startIndex = startIndex; + this.address = address; this.length = length; + this.elementStride = elementStride; } - public ValueNode getObject() { - return object; - } - - public ValueNode getStartIndex() { - return startIndex; + public AddressNode getAddress() { + return address; } public ValueNode getLength() { return length; } + + public int getElementStride() { + return elementStride; + } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,13 +28,14 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; @NodeInfo(cycles = CYCLES_64, size = SIZE_64) public class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier { public static final NodeClass TYPE = NodeClass.create(G1ArrayRangePostWriteBarrier.class); - public G1ArrayRangePostWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { - super(TYPE, object, startIndex, length); + public G1ArrayRangePostWriteBarrier(AddressNode address, ValueNode length, int elementStride) { + super(TYPE, address, length, elementStride); } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,13 +28,14 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; @NodeInfo(cycles = CYCLES_64, size = SIZE_64) public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier { public static final NodeClass TYPE = NodeClass.create(G1ArrayRangePreWriteBarrier.class); - public G1ArrayRangePreWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { - super(TYPE, object, startIndex, length); + public G1ArrayRangePreWriteBarrier(AddressNode address, ValueNode length, int elementStride) { + super(TYPE, address, length, elementStride); } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,14 +28,14 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; @NodeInfo(cycles = CYCLES_8, size = SIZE_8) public final class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier { - public static final NodeClass TYPE = NodeClass.create(SerialArrayRangeWriteBarrier.class); - public SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { - super(TYPE, object, startIndex, length); + public SerialArrayRangeWriteBarrier(AddressNode address, ValueNode length, int elementStride) { + super(TYPE, address, length, elementStride); } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -34,7 +34,7 @@ import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.ArrayRangeWriteNode; +import org.graalvm.compiler.nodes.extended.ArrayRangeWrite; import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode; import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; @@ -65,9 +65,9 @@ addAtomicReadWriteNodeBarriers(loweredAtomicReadAndWriteNode, graph); } else if (n instanceof AbstractCompareAndSwapNode) { addCASBarriers((AbstractCompareAndSwapNode) n, graph); - } else if (n instanceof ArrayRangeWriteNode) { - ArrayRangeWriteNode node = (ArrayRangeWriteNode) n; - if (node.isObjectArray()) { + } else if (n instanceof ArrayRangeWrite) { + ArrayRangeWrite node = (ArrayRangeWrite) n; + if (node.writesObjectArray()) { addArrayRangeBarriers(node, graph); } } @@ -171,17 +171,17 @@ } } - private void addArrayRangeBarriers(ArrayRangeWriteNode node, StructuredGraph graph) { + private void addArrayRangeBarriers(ArrayRangeWrite write, StructuredGraph graph) { if (config.useG1GC) { - if (!node.isInitialization()) { - G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(node.getArray(), node.getIndex(), node.getLength())); - graph.addBeforeFixed(node, g1ArrayRangePreWriteBarrier); + if (!write.isInitialization()) { + G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride())); + graph.addBeforeFixed(write.asNode(), g1ArrayRangePreWriteBarrier); } - G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(new G1ArrayRangePostWriteBarrier(node.getArray(), node.getIndex(), node.getLength())); - graph.addAfterFixed(node, g1ArrayRangePostWriteBarrier); + G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(new G1ArrayRangePostWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride())); + graph.addAfterFixed(write.asNode(), g1ArrayRangePostWriteBarrier); } else { - SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getArray(), node.getIndex(), node.getLength())); - graph.addAfterFixed(node, serialArrayRangeWriteBarrier); + SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride())); + graph.addAfterFixed(write.asNode(), serialArrayRangeWriteBarrier); } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -39,7 +39,7 @@ import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.ArrayRangeWriteNode; +import org.graalvm.compiler.nodes.extended.ArrayRangeWrite; import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode; import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; @@ -122,7 +122,7 @@ private boolean hasAttachedBarrier(FixedWithNextNode node) { final Node next = node.next(); final Node previous = node.predecessor(); - boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWriteNode) node).isInitialization()); + boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWrite) node).isInitialization()); if (node instanceof WriteNode) { WriteNode writeNode = (WriteNode) node; if (writeNode.getLocationIdentity().isInit()) { @@ -143,7 +143,7 @@ } private static boolean isArrayBarrier(FixedWithNextNode node, final Node next) { - return (next instanceof ArrayRangeWriteBarrier) && ((ArrayRangeWriteNode) node).getArray() == ((ArrayRangeWriteBarrier) next).getObject(); + return (next instanceof ArrayRangeWriteBarrier) && ((ArrayRangeWrite) node).getAddress() == ((ArrayRangeWriteBarrier) next).getAddress(); } private static boolean isObjectWrite(Node node) { @@ -152,7 +152,7 @@ } private static boolean isObjectArrayRangeWrite(Node node) { - return node instanceof ArrayRangeWriteNode && ((ArrayRangeWriteNode) node).isObjectArray(); + return node instanceof ArrayRangeWrite && ((ArrayRangeWrite) node).writesObjectArray(); } private static void expandFrontier(NodeFlood frontier, Node node) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,6 +28,11 @@ import java.util.Iterator; import java.util.List; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ResolvedJavaType; + +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; @@ -40,11 +45,6 @@ import org.graalvm.compiler.phases.graph.MergeableState; import org.graalvm.compiler.phases.graph.PostOrderNodeIterator; import org.graalvm.compiler.phases.tiers.PhaseContext; -import org.graalvm.util.EconomicSet; - -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.ResolvedJavaType; public class EliminateRedundantInitializationPhase extends BasePhase { /** diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -29,6 +29,7 @@ import java.util.HashSet; import java.util.List; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; @@ -64,7 +65,6 @@ import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.PhaseContext; -import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,10 +25,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -56,7 +53,9 @@ import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; /** @@ -169,8 +168,8 @@ } @Override - public boolean preservesOrder(Condition op, Constant value, ConstantReflectionProvider constantReflection) { - assert op == Condition.EQ || op == Condition.NE; + public boolean preservesOrder(CanonicalCondition op, Constant value, ConstantReflectionProvider constantReflection) { + assert op == CanonicalCondition.EQ; ResolvedJavaType exactType = constantReflection.asJavaType(value); return !exactType.isPrimitive(); } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotArraySubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotArraySubstitutions.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.hotspot.replacements; + +import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_ARRAY_KLASS_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayKlassOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadKlassFromObject; + +import java.lang.reflect.Array; + +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.api.replacements.ClassSubstitution; +import org.graalvm.compiler.api.replacements.MethodSubstitution; +import org.graalvm.compiler.nodes.java.DynamicNewArrayNode; + +// JaCoCo Exclude + +/** + * Substitutions for {@link Array} methods. + */ +@ClassSubstitution(Array.class) +public class HotSpotArraySubstitutions { + + @MethodSubstitution + public static Object newInstance(Class componentType, int length) { + if (componentType == null || loadKlassFromObject(componentType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION).isNull()) { + // Exit the intrinsic here for the case where the array class does not exist + return newInstance(componentType, length); + } + return DynamicNewArrayNode.newArray(GraalDirectives.guardingNonNull(componentType), length); + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Fri Feb 02 17:28:17 2018 -0800 @@ -303,7 +303,11 @@ return result; } - public static final LocationIdentity JAVA_THREAD_THREAD_OBJECT_LOCATION = NamedLocationIdentity.mutable("JavaThread::_threadObj"); + /* + * As far as Java code is concerned this can be considered immutable: it is set just after the + * JavaThread is created, before it is published. After that, it is never changed. + */ + public static final LocationIdentity JAVA_THREAD_THREAD_OBJECT_LOCATION = NamedLocationIdentity.immutable("JavaThread::_threadObj"); @Fold public static int threadObjectOffset(@InjectedParameter GraalHotSpotVMConfig config) { @@ -565,9 +569,20 @@ return WordFactory.unsigned(ComputeObjectAddressNode.get(a, getArrayBaseOffset(JavaKind.Int))); } + /** + * Idiom for making {@link GraalHotSpotVMConfig} a constant. + */ @Fold - public static int objectAlignment(@InjectedParameter GraalHotSpotVMConfig config) { - return config.objectAlignment; + public static GraalHotSpotVMConfig getConfig(@InjectedParameter GraalHotSpotVMConfig config) { + return config; + } + + /** + * Calls {@link #arrayAllocationSize(int, int, int, GraalHotSpotVMConfig)} using an injected VM + * configuration object. + */ + public static int arrayAllocationSize(int length, int headerSize, int log2ElementSize) { + return arrayAllocationSize(length, headerSize, log2ElementSize, getConfig(INJECTED_VMCONFIG)); } /** @@ -578,10 +593,12 @@ * @param length the number of elements in the array * @param headerSize the size of the array header * @param log2ElementSize log2 of the size of an element in the array + * @param config the VM configuration providing the + * {@linkplain GraalHotSpotVMConfig#objectAlignment object alignment requirement} * @return the size of the memory chunk */ - public static int arrayAllocationSize(int length, int headerSize, int log2ElementSize) { - int alignment = objectAlignment(INJECTED_VMCONFIG); + public static int arrayAllocationSize(int length, int headerSize, int log2ElementSize, GraalHotSpotVMConfig config) { + int alignment = config.objectAlignment; int size = (length << log2ElementSize) + headerSize + (alignment - 1); int mask = ~(alignment - 1); return size & mask; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Fri Feb 02 17:28:17 2018 -0800 @@ -62,6 +62,7 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; import static org.graalvm.compiler.replacements.ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED; +import static org.graalvm.compiler.replacements.ReplacementsUtil.runtimeAssert; import static org.graalvm.compiler.replacements.ReplacementsUtil.staticAssert; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring; @@ -378,7 +379,13 @@ if (length < 0) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - int layoutHelper = knownElementKind != JavaKind.Illegal ? knownLayoutHelper : readLayoutHelper(nonNullKlass); + int layoutHelper; + if (knownElementKind == JavaKind.Illegal) { + layoutHelper = readLayoutHelper(nonNullKlass); + } else { + runtimeAssert(knownLayoutHelper == readLayoutHelper(nonNullKlass), "layout mismatch"); + layoutHelper = knownLayoutHelper; + } //@formatter:off // from src/share/vm/oops/klass.hpp: // diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,7 +24,6 @@ import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayBaseOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayIndexScale; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.cardTableShift; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.dirtyCardValue; @@ -59,7 +58,6 @@ import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier; -import org.graalvm.compiler.hotspot.nodes.GetObjectAddressNode; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; @@ -152,18 +150,14 @@ } @Snippet - public static void serialArrayRangeWriteBarrier(Object object, int startIndex, int length) { + public static void serialArrayRangeWriteBarrier(Address address, int length, @ConstantParameter int elementStride) { if (length == 0) { return; } - Object dest = FixedValueAnchorNode.getObject(object); int cardShift = cardTableShift(INJECTED_VMCONFIG); final long cardStart = GraalHotSpotVMConfigNode.cardTableAddress(); - final int scale = arrayIndexScale(JavaKind.Object); - int header = arrayBaseOffset(JavaKind.Object); - long dstAddr = GetObjectAddressNode.get(dest); - long start = (dstAddr + header + (long) startIndex * scale) >>> cardShift; - long end = (dstAddr + header + ((long) startIndex + length - 1) * scale) >>> cardShift; + long start = getPointerToFirstArrayElement(address, length, elementStride) >>> cardShift; + long end = getPointerToLastArrayElement(address, length, elementStride) >>> cardShift; long count = end - start + 1; while (count-- > 0) { DirectStoreNode.storeBoolean((start + cardStart) + count, false, JavaKind.Boolean); @@ -305,24 +299,22 @@ } @Snippet - public static void g1ArrayRangePreWriteBarrier(Object object, int startIndex, int length, @ConstantParameter Register threadRegister) { + public static void g1ArrayRangePreWriteBarrier(Address address, int length, @ConstantParameter int elementStride, @ConstantParameter Register threadRegister) { Word thread = registerAsWord(threadRegister); byte markingValue = thread.readByte(g1SATBQueueMarkingOffset(INJECTED_VMCONFIG)); // If the concurrent marker is not enabled or the vector length is zero, return. if (markingValue == (byte) 0 || length == 0) { return; } - Object dest = FixedValueAnchorNode.getObject(object); Word bufferAddress = thread.readWord(g1SATBQueueBufferOffset(INJECTED_VMCONFIG)); Word indexAddress = thread.add(g1SATBQueueIndexOffset(INJECTED_VMCONFIG)); - long dstAddr = GetObjectAddressNode.get(dest); long indexValue = indexAddress.readWord(0).rawValue(); final int scale = arrayIndexScale(JavaKind.Object); - int header = arrayBaseOffset(JavaKind.Object); + long start = getPointerToFirstArrayElement(address, length, elementStride); - for (int i = startIndex; i < length; i++) { - Word address = WordFactory.pointer(dstAddr + header + (i * scale)); - Pointer oop = Word.objectToTrackedPointer(address.readObject(0, BarrierType.NONE)); + for (int i = 0; i < length; i++) { + Word arrElemPtr = WordFactory.pointer(start + i * scale); + Pointer oop = Word.objectToTrackedPointer(arrElemPtr.readObject(0, BarrierType.NONE)); verifyOop(oop.toObject()); if (oop.notEqual(0)) { if (indexValue != 0) { @@ -339,11 +331,10 @@ } @Snippet - public static void g1ArrayRangePostWriteBarrier(Object object, int startIndex, int length, @ConstantParameter Register threadRegister) { + public static void g1ArrayRangePostWriteBarrier(Address address, int length, @ConstantParameter int elementStride, @ConstantParameter Register threadRegister) { if (length == 0) { return; } - Object dest = FixedValueAnchorNode.getObject(object); Word thread = registerAsWord(threadRegister); Word bufferAddress = thread.readWord(g1CardQueueBufferOffset(INJECTED_VMCONFIG)); Word indexAddress = thread.add(g1CardQueueIndexOffset(INJECTED_VMCONFIG)); @@ -351,11 +342,8 @@ int cardShift = cardTableShift(INJECTED_VMCONFIG); final long cardStart = GraalHotSpotVMConfigNode.cardTableAddress(); - final int scale = arrayIndexScale(JavaKind.Object); - int header = arrayBaseOffset(JavaKind.Object); - long dstAddr = GetObjectAddressNode.get(dest); - long start = (dstAddr + header + (long) startIndex * scale) >>> cardShift; - long end = (dstAddr + header + ((long) startIndex + length - 1) * scale) >>> cardShift; + long start = getPointerToFirstArrayElement(address, length, elementStride) >>> cardShift; + long end = getPointerToLastArrayElement(address, length, elementStride) >>> cardShift; long count = end - start + 1; while (count-- > 0) { @@ -384,6 +372,26 @@ } } + private static long getPointerToFirstArrayElement(Address address, int length, int elementStride) { + long result = Word.fromAddress(address).rawValue(); + if (elementStride < 0) { + // the address points to the place after the last array element + result = result + elementStride * length; + } + return result; + } + + private static long getPointerToLastArrayElement(Address address, int length, int elementStride) { + long result = Word.fromAddress(address).rawValue(); + if (elementStride < 0) { + // the address points to the place after the last array element + result = result + elementStride; + } else { + result = result + (length - 1) * elementStride; + } + return result; + } + public static final ForeignCallDescriptor G1WBPRECALL = new ForeignCallDescriptor("write_barrier_pre", void.class, Object.class); @NodeIntrinsic(ForeignCallNode.class) @@ -431,9 +439,9 @@ public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, LoweringTool tool) { Arguments args = new Arguments(serialArrayRangeWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage(), tool.getLoweringStage()); - args.add("object", arrayRangeWriteBarrier.getObject()); - args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); + args.add("address", arrayRangeWriteBarrier.getAddress()); args.add("length", arrayRangeWriteBarrier.getLength()); + args.addConst("elementStride", arrayRangeWriteBarrier.getElementStride()); template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } @@ -519,18 +527,18 @@ public void lower(G1ArrayRangePreWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) { Arguments args = new Arguments(g1ArrayRangePreWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage(), tool.getLoweringStage()); - args.add("object", arrayRangeWriteBarrier.getObject()); - args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); + args.add("address", arrayRangeWriteBarrier.getAddress()); args.add("length", arrayRangeWriteBarrier.getLength()); + args.addConst("elementStride", arrayRangeWriteBarrier.getElementStride()); args.addConst("threadRegister", registers.getThreadRegister()); template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } public void lower(G1ArrayRangePostWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) { Arguments args = new Arguments(g1ArrayRangePostWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage(), tool.getLoweringStage()); - args.add("object", arrayRangeWriteBarrier.getObject()); - args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); + args.add("address", arrayRangeWriteBarrier.getAddress()); args.add("length", arrayRangeWriteBarrier.getLength()); + args.addConst("elementStride", arrayRangeWriteBarrier.getElementStride()); args.addConst("threadRegister", registers.getThreadRegister()); template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java Fri Feb 02 17:28:17 2018 -0800 @@ -40,6 +40,7 @@ import java.lang.reflect.Method; import java.util.EnumMap; +import org.graalvm.collections.UnmodifiableEconomicMap; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; @@ -76,7 +77,6 @@ import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; import org.graalvm.compiler.word.Word; -import org.graalvm.util.UnmodifiableEconomicMap; import org.graalvm.word.LocationIdentity; import org.graalvm.word.WordFactory; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java Fri Feb 02 17:28:17 2018 -0800 @@ -34,6 +34,21 @@ import java.util.ListIterator; import java.util.concurrent.atomic.AtomicInteger; +import jdk.vm.ci.code.CodeCacheProvider; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.site.Call; +import jdk.vm.ci.code.site.ConstantReference; +import jdk.vm.ci.code.site.DataPatch; +import jdk.vm.ci.code.site.Infopoint; +import jdk.vm.ci.hotspot.HotSpotCompiledCode; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; +import jdk.vm.ci.meta.DefaultProfilingInfo; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.TriState; + +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.target.Backend; @@ -54,21 +69,6 @@ import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.printer.GraalDebugHandlersFactory; -import org.graalvm.util.EconomicSet; - -import jdk.vm.ci.code.CodeCacheProvider; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.site.Call; -import jdk.vm.ci.code.site.ConstantReference; -import jdk.vm.ci.code.site.DataPatch; -import jdk.vm.ci.code.site.Infopoint; -import jdk.vm.ci.hotspot.HotSpotCompiledCode; -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.meta.DefaultProfilingInfo; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.TriState; //JaCoCo Exclude diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Fri Feb 02 17:28:17 2018 -0800 @@ -86,6 +86,8 @@ import java.util.List; import java.util.TreeSet; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeLookupSwitch; import org.graalvm.compiler.bytecode.BytecodeStream; @@ -95,8 +97,6 @@ import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.ExceptionHandler; @@ -415,9 +415,6 @@ } public static class ExceptionDispatchBlock extends BciBlock { - - private EconomicMap exceptionDispatch = EconomicMap.create(Equivalence.DEFAULT); - public ExceptionHandler handler; public int deoptBci; } @@ -748,15 +745,6 @@ } } - private EconomicMap initialExceptionDispatch; - - private EconomicMap getInitialExceptionDispatch() { - if (initialExceptionDispatch == null) { - initialExceptionDispatch = EconomicMap.create(Equivalence.DEFAULT); - } - return initialExceptionDispatch; - } - private ExceptionDispatchBlock handleExceptions(BciBlock[] blockMap, int bci) { ExceptionDispatchBlock lastHandler = null; @@ -769,20 +757,17 @@ lastHandler = null; } - EconomicMap exceptionDispatch = lastHandler != null ? lastHandler.exceptionDispatch : getInitialExceptionDispatch(); - ExceptionDispatchBlock curHandler = exceptionDispatch.get(h); - if (curHandler == null) { - curHandler = new ExceptionDispatchBlock(); - blocksNotYetAssignedId++; - curHandler.startBci = -1; - curHandler.endBci = -1; - curHandler.deoptBci = bci; - curHandler.handler = h; - curHandler.addSuccessor(blockMap[h.getHandlerBCI()]); - if (lastHandler != null) { - curHandler.addSuccessor(lastHandler); - } - exceptionDispatch.put(h, curHandler); + // We do not reuse exception dispatch blocks, because nested exception handlers + // might have problems reasoning about the correct frame state. + ExceptionDispatchBlock curHandler = new ExceptionDispatchBlock(); + blocksNotYetAssignedId++; + curHandler.startBci = -1; + curHandler.endBci = -1; + curHandler.deoptBci = bci; + curHandler.handler = h; + curHandler.addSuccessor(blockMap[h.getHandlerBCI()]); + if (lastHandler != null) { + curHandler.addSuccessor(lastHandler); } lastHandler = curHandler; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Fri Feb 02 17:28:17 2018 -0800 @@ -265,6 +265,8 @@ import java.util.Formatter; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeDisassembler; @@ -278,9 +280,12 @@ import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider; import org.graalvm.compiler.core.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition; import org.graalvm.compiler.core.common.calc.FloatConvert; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -343,8 +348,8 @@ import org.graalvm.compiler.nodes.calc.AndNode; import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.calc.ConditionalNode; +import org.graalvm.compiler.nodes.calc.FloatConvertNode; import org.graalvm.compiler.nodes.calc.FloatDivNode; -import org.graalvm.compiler.nodes.calc.FloatConvertNode; import org.graalvm.compiler.nodes.calc.IntegerBelowNode; import org.graalvm.compiler.nodes.calc.IntegerEqualsNode; import org.graalvm.compiler.nodes.calc.IntegerLessThanNode; @@ -408,8 +413,6 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.util.ValueMergeUtil; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.BailoutException; @@ -436,7 +439,6 @@ import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.Signature; import jdk.vm.ci.meta.TriState; -import org.graalvm.compiler.core.common.type.IntegerStamp; /** * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph. @@ -577,10 +579,11 @@ // value on the stack on entry to an exception handler, // namely the exception object. assert frameState.rethrowException(); - ExceptionObjectNode exceptionObject = (ExceptionObjectNode) frameState.stackAt(0); + ValueNode exceptionValue = frameState.stackAt(0); + ExceptionObjectNode exceptionObject = (ExceptionObjectNode) GraphUtil.unproxify(exceptionValue); FrameStateBuilder dispatchState = parser.frameState.copy(); dispatchState.clearStack(); - dispatchState.push(JavaKind.Object, exceptionObject); + dispatchState.push(JavaKind.Object, exceptionValue); dispatchState.setRethrowException(true); FrameState newFrameState = dispatchState.create(parser.bci(), exceptionObject); frameState.replaceAndDelete(newFrameState); @@ -700,6 +703,12 @@ assert code.getCode() != null : "method must contain bytecodes: " + method; + if (TraceBytecodeParserLevel.getValue(options) != 0) { + if (!Assertions.assertionsEnabled()) { + throw new IllegalArgumentException("A non-zero " + TraceBytecodeParserLevel.getName() + " value requires assertions to be enabled"); + } + } + if (graphBuilderConfig.insertFullInfopoints() && !parsingIntrinsic()) { lnt = code.getLineNumberTable(); previousLineNumber = -1; @@ -1893,7 +1902,7 @@ LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver)); LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub)); ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess())); - LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, Condition.EQ, actual, expected, NodeView.DEFAULT)); + LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, CanonicalCondition.EQ, actual, expected, NodeView.DEFAULT)); JavaTypeProfile profile = null; if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) { @@ -2267,8 +2276,10 @@ } protected void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, IntrinsicContext calleeIntrinsicContext) { + FixedWithNextNode calleeBeforeUnwindNode = null; + ValueNode calleeUnwindValue = null; + try (IntrinsicScope s = calleeIntrinsicContext != null && !parsingIntrinsic() ? new IntrinsicScope(this, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), args) : null) { - BytecodeParser parser = graphBuilderInstance.createBytecodeParser(graph, this, targetMethod, INVOCATION_ENTRY_BCI, calleeIntrinsicContext); FrameStateBuilder startFrameState = new FrameStateBuilder(parser, parser.code, graph); if (!targetMethod.isStatic()) { @@ -2315,13 +2326,25 @@ } } - FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode(); + calleeBeforeUnwindNode = parser.getBeforeUnwindNode(); if (calleeBeforeUnwindNode != null) { - ValueNode calleeUnwindValue = parser.getUnwindValue(); + calleeUnwindValue = parser.getUnwindValue(); assert calleeUnwindValue != null; - calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci(), false)); } } + + /* + * Method handleException will call createTarget, which wires this exception edge to the + * corresponding exception dispatch block in the caller. In the case where it wires to the + * caller's unwind block, any FrameState created meanwhile, e.g., FrameState for + * LoopExitNode, would be instantiated with AFTER_EXCEPTION_BCI. Such frame states should + * not be fixed by IntrinsicScope.close, as they denote the states of the caller. Thus, the + * following code should be placed outside the IntrinsicScope, so that correctly created + * FrameStates are not replaced. + */ + if (calleeBeforeUnwindNode != null) { + calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci(), false)); + } } public MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, StampPair returnStamp, JavaTypeProfile profile) { @@ -2773,6 +2796,10 @@ setCurrentFrameState(frameState); currentBlock = block; + if (block != blockMap.getUnwindBlock() && !(block instanceof ExceptionDispatchBlock)) { + frameState.setRethrowException(false); + } + if (firstInstruction instanceof AbstractMergeNode) { setMergeStateAfter(block, firstInstruction); } @@ -2782,7 +2809,6 @@ } else if (block instanceof ExceptionDispatchBlock) { createExceptionDispatch((ExceptionDispatchBlock) block); } else { - frameState.setRethrowException(false); iterateBytecodesForBlock(block); } } @@ -3055,7 +3081,7 @@ } private boolean traceState() { - if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE) { + if (TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE) { frameState.traceState(); } return true; @@ -3075,56 +3101,107 @@ ValueNode a = x; ValueNode b = y; + BciBlock trueSuccessor = trueBlock; + BciBlock falseSuccessor = falseBlock; + + CanonicalizedCondition canonicalizedCondition = cond.canonicalize(); // Check whether the condition needs to mirror the operands. - if (cond.canonicalMirror()) { + if (canonicalizedCondition.mustMirror()) { a = y; b = x; } + if (canonicalizedCondition.mustNegate()) { + trueSuccessor = falseBlock; + falseSuccessor = trueBlock; + } // Create the logic node for the condition. - LogicNode condition = createLogicNode(cond, a, b); - - // Check whether the condition needs to negate the result. - boolean negate = cond.canonicalNegate(); - genIf(condition, negate, trueBlock, falseBlock); - } - - protected void genIf(LogicNode conditionInput, boolean negateCondition, BciBlock trueBlockInput, BciBlock falseBlockInput) { + LogicNode condition = createLogicNode(canonicalizedCondition.getCanonicalCondition(), a, b); + + double probability = -1; + if (condition instanceof IntegerEqualsNode) { + probability = extractInjectedProbability((IntegerEqualsNode) condition); + // the probability coming from here is about the actual condition + } + + if (probability == -1) { + probability = getProfileProbability(canonicalizedCondition.mustNegate()); + } + + probability = clampProbability(probability); + genIf(condition, trueSuccessor, falseSuccessor, probability); + } + + private double getProfileProbability(boolean negate) { + double probability; + if (profilingInfo == null) { + probability = 0.5; + } else { + assert assertAtIfBytecode(); + probability = profilingInfo.getBranchTakenProbability(bci()); + if (probability < 0) { + assert probability == -1 : "invalid probability"; + debug.log("missing probability in %s at bci %d", code, bci()); + probability = 0.5; + } else { + if (negate) { + // the probability coming from profile is about the original condition + probability = 1 - probability; + } + } + } + return probability; + } + + private static double extractInjectedProbability(IntegerEqualsNode condition) { + // Propagate injected branch probability if any. + IntegerEqualsNode equalsNode = condition; + BranchProbabilityNode probabilityNode = null; + ValueNode other = null; + if (equalsNode.getX() instanceof BranchProbabilityNode) { + probabilityNode = (BranchProbabilityNode) equalsNode.getX(); + other = equalsNode.getY(); + } else if (equalsNode.getY() instanceof BranchProbabilityNode) { + probabilityNode = (BranchProbabilityNode) equalsNode.getY(); + other = equalsNode.getX(); + } + + if (probabilityNode != null && probabilityNode.getProbability().isConstant() && other != null && other.isConstant()) { + double probabilityValue = probabilityNode.getProbability().asJavaConstant().asDouble(); + return other.asJavaConstant().asInt() == 0 ? 1.0 - probabilityValue : probabilityValue; + } + return -1; + } + + protected void genIf(LogicNode conditionInput, BciBlock trueBlockInput, BciBlock falseBlockInput, double probabilityInput) { BciBlock trueBlock = trueBlockInput; BciBlock falseBlock = falseBlockInput; LogicNode condition = conditionInput; + double probability = probabilityInput; FrameState stateBefore = null; ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin(); if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null); } - // Remove a logic negation node and fold it into the negate boolean. - boolean negate = negateCondition; + // Remove a logic negation node. if (condition instanceof LogicNegationNode) { LogicNegationNode logicNegationNode = (LogicNegationNode) condition; - negate = !negate; + BciBlock tmpBlock = trueBlock; + trueBlock = falseBlock; + falseBlock = tmpBlock; + probability = 1 - probability; condition = logicNegationNode.getValue(); } if (condition instanceof LogicConstantNode) { - genConstantTargetIf(trueBlock, falseBlock, negate, condition); + genConstantTargetIf(trueBlock, falseBlock, condition); } else { if (condition.graph() == null) { condition = genUnique(condition); } - // Need to get probability based on current bci. - double probability = branchProbability(condition); - - if (negate) { - BciBlock tmpBlock = trueBlock; - trueBlock = falseBlock; - falseBlock = tmpBlock; - probability = 1 - probability; - } - if (isNeverExecutedCode(probability)) { append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true)); if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { @@ -3200,28 +3277,26 @@ } } - private LogicNode createLogicNode(Condition cond, ValueNode a, ValueNode b) { - LogicNode condition; + private LogicNode createLogicNode(CanonicalCondition cond, ValueNode a, ValueNode b) { assert !a.getStackKind().isNumericFloat(); - if (cond == Condition.EQ || cond == Condition.NE) { - if (a.getStackKind() == JavaKind.Object) { - condition = genObjectEquals(a, b); - } else { - condition = genIntegerEquals(a, b); - } - } else { - assert a.getStackKind() != JavaKind.Object && !cond.isUnsigned(); - condition = genIntegerLessThan(a, b); + switch (cond) { + case EQ: + if (a.getStackKind() == JavaKind.Object) { + return genObjectEquals(a, b); + } else { + return genIntegerEquals(a, b); + } + case LT: + assert a.getStackKind() != JavaKind.Object; + return genIntegerLessThan(a, b); + default: + throw GraalError.shouldNotReachHere("Unexpected condition: " + cond); } - return condition; - } - - private void genConstantTargetIf(BciBlock trueBlock, BciBlock falseBlock, boolean negate, LogicNode condition) { + } + + private void genConstantTargetIf(BciBlock trueBlock, BciBlock falseBlock, LogicNode condition) { LogicConstantNode constantLogicNode = (LogicConstantNode) condition; boolean value = constantLogicNode.getValue(); - if (negate) { - value = !value; - } BciBlock nextBlock = falseBlock; if (value) { nextBlock = trueBlock; @@ -3775,7 +3850,13 @@ BciBlock firstSucc = currentBlock.getSuccessor(0); BciBlock secondSucc = currentBlock.getSuccessor(1); if (firstSucc != secondSucc) { - genIf(instanceOfNode, value != Bytecodes.IFNE, firstSucc, secondSucc); + boolean negate = value != Bytecodes.IFNE; + if (negate) { + BciBlock tmp = firstSucc; + firstSucc = secondSucc; + secondSucc = tmp; + } + genIf(instanceOfNode, firstSucc, secondSucc, getProfileProbability(negate)); } else { appendGoto(firstSucc); } @@ -4263,47 +4344,12 @@ return probability == 0 && optimisticOpts.removeNeverExecutedCode(getOptions()); } - private double rawBranchProbability(LogicNode conditionInput) { - if (conditionInput instanceof IntegerEqualsNode) { - // Propagate injected branch probability if any. - IntegerEqualsNode condition = (IntegerEqualsNode) conditionInput; - BranchProbabilityNode injectedProbability = null; - ValueNode other = null; - if (condition.getX() instanceof BranchProbabilityNode) { - injectedProbability = (BranchProbabilityNode) condition.getX(); - other = condition.getY(); - } else if (condition.getY() instanceof BranchProbabilityNode) { - injectedProbability = (BranchProbabilityNode) condition.getY(); - other = condition.getX(); - } - - if (injectedProbability != null && injectedProbability.getProbability().isConstant() && other != null && other.isConstant()) { - double probabilityValue = injectedProbability.getProbability().asJavaConstant().asDouble(); - return other.asJavaConstant().asInt() == 0 ? 1.0 - probabilityValue : probabilityValue; - } - } - - if (profilingInfo == null) { - return 0.5; - } - assert assertAtIfBytecode(); - - return profilingInfo.getBranchTakenProbability(bci()); - } - - protected double branchProbability(LogicNode conditionInput) { - double probability = rawBranchProbability(conditionInput); - if (probability < 0) { - assert probability == -1 : "invalid probability"; - debug.log("missing probability in %s at bci %d", code, bci()); - probability = 0.5; - } - + private double clampProbability(double probability) { if (!optimisticOpts.removeNeverExecutedCode(getOptions())) { if (probability == 0) { - probability = 0.0000001; + return 0.0000001; } else if (probability == 1) { - probability = 0.999999; + return 0.999999; } } return probability; @@ -4568,7 +4614,7 @@ } protected boolean traceInstruction(int bci, int opcode, boolean blockStart) { - if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS) { + if (TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS) { traceInstructionHelper(bci, opcode, blockStart); } return true; @@ -4589,7 +4635,7 @@ if (!currentBlock.getJsrScope().isEmpty()) { sb.append(' ').append(currentBlock.getJsrScope()); } - debug.log("%s", sb); + TTY.println("%s", sb); } @Override diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java Fri Feb 02 17:28:17 2018 -0800 @@ -34,7 +34,9 @@ */ public class BytecodeParserOptions { // @formatter:off - @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode", type = OptionType.Debug) + @Option(help = "The trace level for the bytecode parser. A value of 1 enables instruction tracing " + + "and any greater value emits a frame state trace just prior to an instruction trace. " + + "This option requires assertions to be enabled.", type = OptionType.Debug) public static final OptionKey TraceBytecodeParserLevel = new OptionKey<>(0); @Option(help = "Inlines trivial methods during bytecode parsing.", type = OptionType.Expert) @@ -56,7 +58,7 @@ public static final OptionKey TraceParserPlugins = new OptionKey<>(false); @Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug) - public static final OptionKey InlineDuringParsingMaxDepth = new OptionKey<>(10); + public static final OptionKey InlineDuringParsingMaxDepth = new OptionKey<>(3); @Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug) public static final OptionKey HideSubstitutionStates = new OptionKey<>(false); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,8 +22,11 @@ */ package org.graalvm.compiler.java; +import static org.graalvm.compiler.nodes.cfg.ControlFlowGraph.multiplyProbabilities; + import java.util.List; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.ControlSplitNode; @@ -34,9 +37,6 @@ import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; -import org.graalvm.util.EconomicMap; - -import static org.graalvm.compiler.nodes.cfg.ControlFlowGraph.multiplyProbabilities; public final class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.NodeIteratorClosure { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java Fri Feb 02 17:28:17 2018 -0800 @@ -47,6 +47,7 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; import org.graalvm.compiler.nodeinfo.Verbosity; @@ -999,15 +1000,14 @@ } public void traceState() { - DebugContext debug = graph.getDebug(); - debug.log("| state [nr locals = %d, stack depth = %d, method = %s]", localsSize(), stackSize(), getMethod()); + TTY.println("| state [nr locals = %d, stack depth = %d, method = %s]", localsSize(), stackSize(), getMethod()); for (int i = 0; i < localsSize(); ++i) { ValueNode value = locals[i]; - debug.log("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value); + TTY.println("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value); } for (int i = 0; i < stackSize(); ++i) { ValueNode value = stack[i]; - debug.log("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value); + TTY.println("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value); } } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,9 +26,6 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import java.lang.reflect.Array; -import java.lang.reflect.Field; - import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; @@ -43,7 +40,6 @@ import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.Value; -import sun.misc.Unsafe; /** * Emits code which compares two arrays of the same length. If the CPU supports any vector @@ -72,9 +68,8 @@ assert !kind.isNumericFloat() : "Float arrays comparison (bitwise_equal || both_NaN) isn't supported"; this.kind = kind; - Class arrayClass = Array.newInstance(kind.toJavaClass(), 0).getClass(); - this.arrayBaseOffset = UNSAFE.arrayBaseOffset(arrayClass); - this.arrayIndexScale = UNSAFE.arrayIndexScale(arrayClass); + this.arrayBaseOffset = tool.getProviders().getArrayOffsetProvider().arrayBaseOffset(kind); + this.arrayIndexScale = tool.getProviders().getArrayOffsetProvider().arrayScalingFactor(kind); this.resultValue = result; this.array1Value = array1; @@ -218,20 +213,4 @@ masm.bind(end); masm.mov(64, rscratch1, zr); } - - private static final Unsafe UNSAFE = initUnsafe(); - - private static Unsafe initUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException se) { - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe", e); - } - } - } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,12 +22,9 @@ */ package org.graalvm.compiler.lir.amd64; +import static jdk.vm.ci.code.ValueUtil.asRegister; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static jdk.vm.ci.code.ValueUtil.asRegister; - -import java.lang.reflect.Array; -import java.lang.reflect.Field; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; @@ -50,7 +47,6 @@ import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.Value; -import sun.misc.Unsafe; /** * Emits code which compares two arrays of the same length. If the CPU supports any vector @@ -83,9 +79,8 @@ super(TYPE); this.kind = kind; - Class arrayClass = Array.newInstance(kind.toJavaClass(), 0).getClass(); - this.arrayBaseOffset = UNSAFE.arrayBaseOffset(arrayClass); - this.arrayIndexScale = UNSAFE.arrayIndexScale(arrayClass); + this.arrayBaseOffset = tool.getProviders().getArrayOffsetProvider().arrayBaseOffset(kind); + this.arrayIndexScale = tool.getProviders().getArrayOffsetProvider().arrayScalingFactor(kind); this.resultValue = result; this.array1Value = array1; @@ -531,20 +526,4 @@ // Floats within the range are equal, revert change to the register index masm.subq(index, range); } - - private static final Unsafe UNSAFE = initUnsafe(); - - private static Unsafe initUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException se) { - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe", e); - } - } - } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java Fri Feb 02 17:28:17 2018 -0800 @@ -101,6 +101,10 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { directCall(crb, masm, callTarget, null, true, state); } + + public int emitCall(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + return directCall(crb, masm, callTarget, null, true, state); + } } @Opcode("CALL_INDIRECT") @@ -183,23 +187,27 @@ } } - public static void directCall(CompilationResultBuilder crb, AMD64MacroAssembler masm, InvokeTarget callTarget, Register scratch, boolean align, LIRFrameState info) { + public static int directCall(CompilationResultBuilder crb, AMD64MacroAssembler masm, InvokeTarget callTarget, Register scratch, boolean align, LIRFrameState info) { if (align) { emitAlignmentForDirectCall(crb, masm); } int before = masm.position(); + int callPCOffset; if (scratch != null) { // offset might not fit a 32-bit immediate, generate an // indirect call with a 64-bit immediate masm.movq(scratch, 0L); + callPCOffset = masm.position(); masm.call(scratch); } else { + callPCOffset = masm.position(); masm.call(); } int after = masm.position(); crb.recordDirectCall(before, after, callTarget, info); crb.recordExceptionHandlers(after, info); masm.ensureUniquePC(); + return callPCOffset; } protected static void emitAlignmentForDirectCall(CompilationResultBuilder crb, AMD64MacroAssembler masm) { @@ -228,12 +236,13 @@ masm.ensureUniquePC(); } - public static void indirectCall(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) { + public static int indirectCall(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) { int before = masm.position(); masm.call(dst); int after = masm.position(); crb.recordIndirectCall(before, after, callTarget, info); crb.recordExceptionHandlers(after, info); masm.ensureUniquePC(); + return before; } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,6 +25,7 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag.Equal; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; @@ -755,17 +756,18 @@ } } - public abstract static class Pointer extends AMD64LIRInstruction { + public abstract static class PointerCompressionOp extends AMD64LIRInstruction { protected final LIRKindTool lirKindTool; protected final CompressEncoding encoding; protected final boolean nonNull; @Def({REG, HINT}) private AllocatableValue result; - @Use({REG}) private AllocatableValue input; + @Use({REG, CONST}) private Value input; @Alive({REG, ILLEGAL}) private AllocatableValue baseRegister; - protected Pointer(LIRInstructionClass type, AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, - LIRKindTool lirKindTool) { + protected PointerCompressionOp(LIRInstructionClass type, AllocatableValue result, Value input, + AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) { + super(type); this.result = result; this.input = input; @@ -779,8 +781,12 @@ return GeneratePIC.getValue(crb.getOptions()) || encoding.hasBase(); } - protected final Register getResultRegister() { - return asRegister(result); + public final Value getInput() { + return input; + } + + public final AllocatableValue getResult() { + return result; } protected final Register getBaseRegister() { @@ -796,18 +802,24 @@ } } - public static final class CompressPointer extends Pointer { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CompressPointer.class); + public static class CompressPointerOp extends PointerCompressionOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CompressPointerOp.class); - public CompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) { - super(TYPE, result, input, baseRegister, encoding, nonNull, lirKindTool); + public CompressPointerOp(AllocatableValue result, Value input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) { + this(TYPE, result, input, baseRegister, encoding, nonNull, lirKindTool); + } + + protected CompressPointerOp(LIRInstructionClass type, AllocatableValue result, Value input, + AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) { + + super(type, result, input, baseRegister, encoding, nonNull, lirKindTool); } @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { move(lirKindTool.getObjectKind(), crb, masm); - Register resReg = getResultRegister(); + Register resReg = asRegister(getResult()); if (hasBase(crb)) { Register baseReg = getBaseRegister(); if (!nonNull) { @@ -824,18 +836,24 @@ } } - public static final class UncompressPointer extends Pointer { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(UncompressPointer.class); + public static class UncompressPointerOp extends PointerCompressionOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(UncompressPointerOp.class); - public UncompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) { - super(TYPE, result, input, baseRegister, encoding, nonNull, lirKindTool); + public UncompressPointerOp(AllocatableValue result, Value input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) { + this(TYPE, result, input, baseRegister, encoding, nonNull, lirKindTool); + } + + protected UncompressPointerOp(LIRInstructionClass type, AllocatableValue result, Value input, + AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) { + + super(type, result, input, baseRegister, encoding, nonNull, lirKindTool); } @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { move(lirKindTool.getNarrowOopKind(), crb, masm); - Register resReg = getResultRegister(); + Register resReg = asRegister(getResult()); int shift = getShift(); if (shift != 0) { masm.shlq(resReg, shift); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,11 +22,13 @@ */ package org.graalvm.compiler.lir.amd64; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; import static jdk.vm.ci.code.ValueUtil.asStackSlot; import static jdk.vm.ci.code.ValueUtil.isStackSlot; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; import java.util.Arrays; + +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LIRValueUtil; @@ -34,7 +36,6 @@ import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMap; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Register; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,13 +24,13 @@ import static org.graalvm.compiler.lir.amd64.AMD64SaveRegistersOp.prune; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMap; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterSaveLayout; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java Fri Feb 02 17:28:17 2018 -0800 @@ -36,9 +36,6 @@ import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import java.lang.reflect.Array; -import java.lang.reflect.Field; - import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.sparc.SPARCAddress; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; @@ -52,7 +49,6 @@ import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.sparc.SPARCKind; -import sun.misc.Unsafe; /** * Emits code which compares two arrays of the same length. @@ -82,9 +78,8 @@ assert !kind.isNumericFloat() : "Float arrays comparison (bitwise_equal || both_NaN) isn't supported"; this.kind = kind; - Class arrayClass = Array.newInstance(kind.toJavaClass(), 0).getClass(); - this.arrayBaseOffset = UNSAFE.arrayBaseOffset(arrayClass); - this.arrayIndexScale = UNSAFE.arrayIndexScale(arrayClass); + this.arrayBaseOffset = tool.getProviders().getArrayOffsetProvider().arrayBaseOffset(kind); + this.arrayIndexScale = tool.getProviders().getArrayOffsetProvider().arrayScalingFactor(kind); this.resultValue = result; this.array1Value = array1; @@ -247,20 +242,4 @@ } } } - - private static final Unsafe UNSAFE = initUnsafe(); - - private static Unsafe initUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException se) { - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe", e); - } - } - } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java Fri Feb 02 17:28:17 2018 -0800 @@ -78,6 +78,8 @@ import java.util.EnumSet; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Assembler.LabelHint; import org.graalvm.compiler.asm.Label; @@ -98,8 +100,6 @@ import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,12 +22,14 @@ */ package org.graalvm.compiler.lir.sparc; +import static jdk.vm.ci.code.ValueUtil.asStackSlot; +import static jdk.vm.ci.code.ValueUtil.isStackSlot; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; import static org.graalvm.compiler.lir.sparc.SPARCDelayedControlTransfer.DUMMY; -import static jdk.vm.ci.code.ValueUtil.asStackSlot; -import static jdk.vm.ci.code.ValueUtil.isStackSlot; import java.util.Arrays; + +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.asm.sparc.SPARCAddress; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; @@ -36,7 +38,6 @@ import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMap; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterSaveLayout; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -27,15 +27,14 @@ import java.util.HashSet; +import org.graalvm.collections.Pair; +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.lir.alloc.trace.ShadowedRegisterValue; +import org.graalvm.compiler.lir.alloc.trace.TraceGlobalMoveResolutionPhase; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; -import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.lir.alloc.trace.ShadowedRegisterValue; -import org.graalvm.compiler.lir.alloc.trace.TraceGlobalMoveResolutionPhase; -import org.graalvm.util.Pair; - import jdk.vm.ci.code.Register; import jdk.vm.ci.code.Register.RegisterCategory; import jdk.vm.ci.code.RegisterValue; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java Fri Feb 02 17:28:17 2018 -0800 @@ -33,14 +33,14 @@ import java.util.Arrays; import java.util.EnumSet; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.MapCursor; import org.graalvm.compiler.core.common.FieldIntrospection; import org.graalvm.compiler.core.common.Fields; import org.graalvm.compiler.core.common.FieldsScanner; import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; import org.graalvm.compiler.lir.LIRInstruction.OperandMode; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.MapCursor; import jdk.vm.ci.code.RegisterValue; import jdk.vm.ci.code.StackSlot; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java Fri Feb 02 17:28:17 2018 -0800 @@ -30,7 +30,8 @@ import java.util.Collections; import java.util.EnumSet; -import jdk.vm.ci.code.RegisterConfig; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.debug.CounterKey; @@ -43,11 +44,10 @@ import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterArray; +import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.code.RegisterValue; import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.code.TargetDescription; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java Fri Feb 02 17:28:17 2018 -0800 @@ -31,12 +31,12 @@ import java.util.ArrayList; import java.util.EnumSet; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMap; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterSaveLayout; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java Fri Feb 02 17:28:17 2018 -0800 @@ -35,6 +35,7 @@ import java.util.BitSet; import java.util.EnumSet; +import org.graalvm.collections.Pair; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; @@ -60,7 +61,6 @@ import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.Pair; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterArray; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -35,6 +35,8 @@ import java.util.BitSet; import java.util.EnumSet; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder; @@ -56,8 +58,6 @@ import org.graalvm.compiler.lir.alloc.lsra.LinearScan.BlockData; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterArray; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.lir.alloc.lsra; +import org.graalvm.collections.Pair; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext; -import org.graalvm.util.Pair; import jdk.vm.ci.code.TargetDescription; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,6 +28,8 @@ import java.util.ArrayList; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; @@ -37,8 +39,6 @@ import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRValueUtil; import org.graalvm.compiler.lir.gen.LIRGenerationResult; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java Fri Feb 02 17:28:17 2018 -0800 @@ -32,13 +32,15 @@ import java.util.List; import java.util.function.Consumer; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.asm.AbstractAddress; import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.code.CompilationResult.CodeAnnotation; import org.graalvm.compiler.code.DataSection.Data; import org.graalvm.compiler.code.DataSection.RawData; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.type.DataPointerConstant; @@ -55,8 +57,6 @@ import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.DebugInfo; @@ -324,12 +324,32 @@ } /** - * Notifies this object of a branch instruction at offset {@code pos} in the code. + * Notifies this object of a branch instruction at offset {@code pcOffset} in the code. * * @param isNegated negation status of the branch's condition. */ @SuppressWarnings("unused") - public void recordBranch(int pos, boolean isNegated) { + public void recordBranch(int pcOffset, boolean isNegated) { + } + + /** + * Notifies this object of a call instruction belonging to an INVOKEVIRTUAL or INVOKEINTERFACE + * at offset {@code pcOffset} in the code. + * + * @param nodeSourcePosition source position of the corresponding invoke. + */ + @SuppressWarnings("unused") + public void recordInvokeVirtualOrInterfaceCallOp(int pcOffset, NodeSourcePosition nodeSourcePosition) { + } + + /** + * Notifies this object of a call instruction belonging to an INLINE_INVOKE at offset + * {@code pcOffset} in the code. + * + * @param nodeSourcePosition source position of the corresponding invoke. + */ + @SuppressWarnings("unused") + public void recordInlineInvokeCallOp(int pcOffset, NodeSourcePosition nodeSourcePosition) { } /** diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,7 +22,8 @@ */ package org.graalvm.compiler.lir.gen; -import jdk.vm.ci.code.RegisterConfig; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.CompilationIdentifier.Verbosity; import org.graalvm.compiler.debug.DebugContext; @@ -30,10 +31,9 @@ import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.CallingConvention; +import jdk.vm.ci.code.RegisterConfig; public class LIRGenerationResult { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,20 +22,20 @@ */ package org.graalvm.compiler.lir.gen; -import static org.graalvm.compiler.lir.LIRValueUtil.isVariable; import static jdk.vm.ci.code.ValueUtil.isIllegal; import static jdk.vm.ci.code.ValueUtil.isLegal; import static jdk.vm.ci.meta.Value.ILLEGAL; +import static org.graalvm.compiler.lir.LIRValueUtil.isVariable; import java.util.ArrayList; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.lir.LIRInsertionBuffer; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Value; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/PreAllocationOptimizationStage.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/PreAllocationOptimizationStage.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/PreAllocationOptimizationStage.java Fri Feb 02 17:28:17 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -31,7 +31,7 @@ public PreAllocationOptimizationStage(OptionValues options) { if (ConstantLoadOptimization.Options.LIROptConstantLoadOptimization.getValue(options)) { appendPhase(new ConstantLoadOptimization()); - appendPhase(new SaveCalleeSaveRegisters()); } + appendPhase(new SaveCalleeSaveRegisters()); } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java Fri Feb 02 17:28:17 2018 -0800 @@ -31,6 +31,8 @@ import java.util.Deque; import java.util.EnumSet; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.debug.CounterKey; @@ -43,8 +45,6 @@ import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; import org.graalvm.compiler.lir.LIRInstruction.OperandMode; import org.graalvm.compiler.lir.VirtualStackSlot; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; import jdk.vm.ci.meta.Value; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java Fri Feb 02 17:28:17 2018 -0800 @@ -35,6 +35,7 @@ import java.util.EnumSet; import java.util.PriorityQueue; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; @@ -54,7 +55,6 @@ import org.graalvm.compiler.options.NestedBooleanOptionKey; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.code.TargetDescription; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/util/GenericValueMap.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/util/GenericValueMap.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/util/GenericValueMap.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,8 +22,8 @@ */ package org.graalvm.compiler.lir.util; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import jdk.vm.ci.meta.Value; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java Fri Feb 02 17:28:17 2018 -0800 @@ -31,7 +31,7 @@ import java.util.List; import org.graalvm.compiler.core.common.RetryableBailoutException; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Graph.Mark; @@ -451,7 +451,7 @@ if (!(condition instanceof CompareNode)) { return false; } - if (((CompareNode) condition).condition() == Condition.EQ || ((CompareNode) condition).condition() == Condition.NE) { + if (((CompareNode) condition).condition() == CanonicalCondition.EQ) { condition.getDebug().log(DebugContext.VERBOSE_LEVEL, "isUnrollableLoop %s condition unsupported %s ", loopBegin, ((CompareNode) condition).condition()); return false; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java Fri Feb 02 17:28:17 2018 -0800 @@ -73,12 +73,18 @@ Stamp stamp = iv.valueNode().stamp(NodeView.DEFAULT); ValueNode range = sub(graph, end, iv.initNode()); + ValueNode max; + ValueNode min; ValueNode oneDirection; if (iv.direction() == Direction.Up) { oneDirection = ConstantNode.forIntegerStamp(stamp, 1, graph); + max = end; + min = iv.initNode(); } else { assert iv.direction() == Direction.Down; oneDirection = ConstantNode.forIntegerStamp(stamp, -1, graph); + max = iv.initNode(); + min = end; } if (oneOff) { range = add(graph, range, oneDirection); @@ -95,7 +101,7 @@ return div; } ConstantNode zero = ConstantNode.forIntegerStamp(stamp, 0, graph); - return graph.unique(new ConditionalNode(graph.unique(new IntegerLessThanNode(zero, div)), div, zero)); + return graph.unique(new ConditionalNode(graph.unique(new IntegerLessThanNode(max, min)), zero, div)); } /** diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,7 +22,13 @@ */ package org.graalvm.compiler.loop; -import jdk.vm.ci.code.BytecodeFrame; +import java.util.Collection; +import java.util.LinkedList; +import java.util.Queue; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.core.common.type.IntegerStamp; @@ -67,13 +73,8 @@ import org.graalvm.compiler.nodes.debug.ControlFlowAnchored; import org.graalvm.compiler.nodes.extended.ValueAnchorNode; import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; -import java.util.Collection; -import java.util.LinkedList; -import java.util.Queue; +import jdk.vm.ci.code.BytecodeFrame; public class LoopEx { private final Loop loop; @@ -236,13 +237,13 @@ if (isOutsideLoop(lessThan.getX())) { iv = getInductionVariables().get(lessThan.getY()); if (iv != null) { - condition = lessThan.condition().mirror(); + condition = lessThan.condition().asCondition().mirror(); limit = lessThan.getX(); } } else if (isOutsideLoop(lessThan.getY())) { iv = getInductionVariables().get(lessThan.getX()); if (iv != null) { - condition = lessThan.condition(); + condition = lessThan.condition().asCondition(); limit = lessThan.getY(); } } @@ -393,8 +394,8 @@ } else { boolean isValidConvert = op instanceof PiNode || op instanceof SignExtendNode; if (!isValidConvert && op instanceof ZeroExtendNode) { - IntegerStamp inputStamp = (IntegerStamp) ((ZeroExtendNode) op).getValue().stamp(NodeView.DEFAULT); - isValidConvert = inputStamp.isPositive(); + ZeroExtendNode zeroExtendNode = (ZeroExtendNode) op; + isValidConvert = zeroExtendNode.isInputAlwaysPositive() || ((IntegerStamp) zeroExtendNode.stamp(NodeView.DEFAULT)).isPositive(); } if (isValidConvert) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,7 +22,12 @@ */ package org.graalvm.compiler.loop; -import jdk.vm.ci.meta.TriState; +import java.util.ArrayDeque; +import java.util.Collections; +import java.util.Deque; +import java.util.Iterator; + +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Graph.DuplicationReplacement; @@ -52,12 +57,8 @@ import org.graalvm.compiler.nodes.spi.NodeWithState; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; -import org.graalvm.util.EconomicMap; -import java.util.ArrayDeque; -import java.util.Collections; -import java.util.Deque; -import java.util.Iterator; +import jdk.vm.ci.meta.TriState; public abstract class LoopFragment { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,6 +26,8 @@ import java.util.LinkedList; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Graph.DuplicationReplacement; @@ -62,8 +64,6 @@ import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.memory.MemoryPhiNode; import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; public class LoopFragmentInside extends LoopFragment { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.loop; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Graph; @@ -35,7 +36,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.cfg.Block; -import org.graalvm.util.EconomicSet; public class LoopFragmentWhole extends LoopFragment { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java Fri Feb 02 17:28:17 2018 -0800 @@ -27,6 +27,9 @@ import java.util.LinkedList; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.LoopBeginNode; @@ -34,9 +37,6 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; public class LoopsData { private final EconomicMap loopBeginToEx = EconomicMap.create(Equivalence.IDENTITY); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,7 +24,9 @@ import java.util.Arrays; +import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Warmup; import org.graalvm.compiler.microbenchmarks.graal.util.MethodSpec; @@ -32,7 +34,8 @@ import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; -@Warmup(iterations = 15) +@Warmup(iterations = 20) +@Measurement(iterations = 10) public class SchedulePhaseBenchmark extends GraalBenchmark { @MethodSpec(declaringClass = String.class, name = "equals") @@ -117,5 +120,67 @@ public void intersection_EARLIEST_OPTIMAL(IntersectionState_EARLIEST_OPTIMAL s) { s.schedule.apply(s.graph); } + + @MethodSpec(declaringClass = SchedulePhaseBenchmark.class, name = "intersectionSnippet") + public static class IntersectionState_EARLIEST_WITH_GUARD_ORDER_OPTIMAL extends ScheduleState { + public IntersectionState_EARLIEST_WITH_GUARD_ORDER_OPTIMAL() { + super(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); + } + } + + @Benchmark + public void intersection_EARLIEST_WITH_GUARD_ORDER_OPTIMAL(IntersectionState_EARLIEST_WITH_GUARD_ORDER_OPTIMAL s) { + s.schedule.apply(s.graph); + } + // Checkstyle: resume method name check + + // Checkstyle: stop method name check + @MethodSpec(declaringClass = SchedulePhase.Instance.class, name = "scheduleEarliestIterative") + public static class ScheduleEarliestIterative_LATEST_OPTIMAL extends ScheduleState { + public ScheduleEarliestIterative_LATEST_OPTIMAL() { + super(SchedulingStrategy.LATEST); + } + } + + @Benchmark + public void scheduleEarliestIterative_LATEST_OPTIMAL(ScheduleEarliestIterative_LATEST_OPTIMAL s) { + s.schedule.apply(s.graph); + } + + @MethodSpec(declaringClass = SchedulePhase.Instance.class, name = "scheduleEarliestIterative") + public static class ScheduleEarliestIterative_LATEST_OUT_OF_LOOPS_OPTIMAL extends ScheduleState { + public ScheduleEarliestIterative_LATEST_OUT_OF_LOOPS_OPTIMAL() { + super(SchedulingStrategy.LATEST_OUT_OF_LOOPS); + } + } + + @Benchmark + public void scheduleEarliestIterative_LATEST_OUT_OF_LOOPS_OPTIMAL(ScheduleEarliestIterative_LATEST_OUT_OF_LOOPS_OPTIMAL s) { + s.schedule.apply(s.graph); + } + + @MethodSpec(declaringClass = SchedulePhase.Instance.class, name = "scheduleEarliestIterative") + public static class ScheduleEarliestIterative_EARLIEST_OPTIMAL extends ScheduleState { + public ScheduleEarliestIterative_EARLIEST_OPTIMAL() { + super(SchedulingStrategy.EARLIEST); + } + } + + @Benchmark + public void scheduleEarliestIterative_EARLIEST_OPTIMAL(ScheduleEarliestIterative_EARLIEST_OPTIMAL s) { + s.schedule.apply(s.graph); + } + + @MethodSpec(declaringClass = SchedulePhase.Instance.class, name = "scheduleEarliestIterative") + public static class ScheduleEarliestIterative_EARLIEST_WITH_GUARD_ORDER_OPTIMAL extends ScheduleState { + public ScheduleEarliestIterative_EARLIEST_WITH_GUARD_ORDER_OPTIMAL() { + super(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); + } + } + + @Benchmark + public void scheduleEarliestIterative_EARLIEST_WITH_GUARD_ORDER_OPTIMAL(ScheduleEarliestIterative_EARLIEST_WITH_GUARD_ORDER_OPTIMAL s) { + s.schedule.apply(s.graph); + } // Checkstyle: resume method name check } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,8 +22,12 @@ */ package org.graalvm.compiler.microbenchmarks.graal.util; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; +import org.graalvm.compiler.phases.tiers.HighTierContext; public class ScheduleState extends GraphState { @@ -36,7 +40,7 @@ } public ScheduleState() { - this(SchedulingStrategy.EARLIEST); + this(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); } @Override @@ -44,4 +48,13 @@ schedule = new SchedulePhase(selectedStrategy); super.beforeInvocation(); } + + @Override + protected StructuredGraph preprocessOriginal(StructuredGraph structuredGraph) { + StructuredGraph g = super.preprocessOriginal(structuredGraph); + GraalState graal = new GraalState(); + PhaseSuite highTier = graal.backend.getSuites().getDefaultSuites(graal.options).getHighTier(); + highTier.apply(g, new HighTierContext(graal.providers, graal.backend.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL)); + return g; + } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -156,11 +156,11 @@ PhaseContext context = new PhaseContext(getProviders()); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + new ConvertDeoptimizeToGuardPhase().apply(graph, context); graph.clearAllStateAfter(); graph.setGuardsStage(StructuredGraph.GuardsStage.AFTER_FSA); canonicalizer.apply(graph, context); - new ConvertDeoptimizeToGuardPhase().apply(graph, context); // new DominatorConditionalEliminationPhase(true).apply(graph, context); new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context); canonicalizer.apply(graph, context); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -129,10 +129,13 @@ if (ret == null) { throw new NoSuchElementException(); } - if (!(current instanceof FixedWithNextNode) || (current instanceof AbstractBeginNode && current != AbstractBeginNode.this)) { + if (current instanceof FixedWithNextNode) { + current = ((FixedWithNextNode) current).next(); + if (current instanceof AbstractBeginNode) { + current = null; + } + } else { current = null; - } else { - current = ((FixedWithNextNode) current).next(); } return ret; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ControlSplitNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ControlSplitNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ControlSplitNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -49,7 +49,7 @@ /** * Primary successor of the control split. Data dependencies on the node have to be scheduled in - * the primary successor. + * the primary successor. Returns null if data dependencies are not expected. * * @return the primary successor */ diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -39,7 +39,7 @@ import jdk.vm.ci.meta.Value; @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}") -public final class DeoptimizeNode extends AbstractDeoptimizeNode implements Lowerable, LIRLowerable { +public final class DeoptimizeNode extends AbstractDeoptimizeNode implements Lowerable, LIRLowerable, StaticDeoptimizingNode { public static final int DEFAULT_DEBUG_ID = 0; public static final NodeClass TYPE = NodeClass.create(DeoptimizeNode.class); @@ -67,11 +67,13 @@ this.speculation = speculation; } - public DeoptimizationAction action() { + @Override + public DeoptimizationAction getAction() { return action; } - public DeoptimizationReason reason() { + @Override + public DeoptimizationReason getReason() { return reason; } @@ -115,6 +117,7 @@ return ConstantNode.forConstant(speculation, metaAccess, graph()); } + @Override public JavaConstant getSpeculation() { return speculation; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingGuard.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingGuard.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingGuard.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,25 +24,15 @@ import org.graalvm.compiler.nodes.extended.GuardingNode; -import jdk.vm.ci.meta.DeoptimizationAction; -import jdk.vm.ci.meta.DeoptimizationReason; -import jdk.vm.ci.meta.JavaConstant; - /** * Shared interface to capture core methods of {@link AbstractFixedGuardNode} and {@link GuardNode}. * */ -public interface DeoptimizingGuard extends ValueNodeInterface, GuardingNode { +public interface DeoptimizingGuard extends GuardingNode, StaticDeoptimizingNode { LogicNode getCondition(); void setCondition(LogicNode x, boolean negated); - DeoptimizationReason getReason(); - - DeoptimizationAction getAction(); - - JavaConstant getSpeculation(); - boolean isNegated(); } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -83,15 +83,7 @@ @Override public void lower(LoweringTool tool) { if (graph().getGuardsStage().allowsFloatingGuards()) { - /* - * Don't allow guards with action None and reason RuntimeConstraint to float. In cases - * where 2 guards are testing equivalent conditions they might be lowered at the same - * location. If the guard with the None action is lowered before the other guard then - * the code will be stuck repeatedly deoptimizing without invalidating the code. - * Conditional elimination will eliminate the guard if it's truly redundant in this - * case. - */ - if (getAction() != DeoptimizationAction.None || getReason() != DeoptimizationReason.RuntimeConstraint) { + if (getAction() != DeoptimizationAction.None) { ValueNode guard = tool.createGuard(this, getCondition(), getReason(), getAction(), getSpeculation(), isNegated()).asNode(); this.replaceAtUsages(guard); graph().removeFixed(this); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Fri Feb 02 17:28:17 2018 -0800 @@ -37,6 +37,9 @@ import java.util.SortedMap; import java.util.TreeMap; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.Fields; import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.util.TypeReader; @@ -62,9 +65,6 @@ import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin.LoopExplosionKind; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.meta.DeoptimizationAction; @@ -489,7 +489,8 @@ */ LoopScope outerScope = loopScope.outer; int nextIterationNumber = outerScope.nextIterations.isEmpty() ? outerScope.loopIteration + 1 : outerScope.nextIterations.getLast().loopIteration + 1; - successorAddScope = new LoopScope(methodScope, outerScope.outer, outerScope.loopDepth, nextIterationNumber, outerScope.loopBeginOrderId, outerScope.initialCreatedNodes, + successorAddScope = new LoopScope(methodScope, outerScope.outer, outerScope.loopDepth, nextIterationNumber, outerScope.loopBeginOrderId, + outerScope.initialCreatedNodes == null ? null : Arrays.copyOf(outerScope.initialCreatedNodes, outerScope.initialCreatedNodes.length), Arrays.copyOf(loopScope.initialCreatedNodes, loopScope.initialCreatedNodes.length), outerScope.nextIterations, outerScope.iterationStates); checkLoopExplosionIteration(methodScope, successorAddScope); @@ -736,7 +737,8 @@ assert methodScope.loopExplosion != LoopExplosionKind.NONE; if (methodScope.loopExplosion != LoopExplosionKind.FULL_UNROLL || loopScope.nextIterations.isEmpty()) { int nextIterationNumber = loopScope.nextIterations.isEmpty() ? loopScope.loopIteration + 1 : loopScope.nextIterations.getLast().loopIteration + 1; - LoopScope nextIterationScope = new LoopScope(methodScope, loopScope.outer, loopScope.loopDepth, nextIterationNumber, loopScope.loopBeginOrderId, loopScope.initialCreatedNodes, + LoopScope nextIterationScope = new LoopScope(methodScope, loopScope.outer, loopScope.loopDepth, nextIterationNumber, loopScope.loopBeginOrderId, + Arrays.copyOf(loopScope.initialCreatedNodes, loopScope.initialCreatedNodes.length), Arrays.copyOf(loopScope.initialCreatedNodes, loopScope.initialCreatedNodes.length), loopScope.nextIterations, loopScope.iterationStates); checkLoopExplosionIteration(methodScope, nextIterationScope); loopScope.nextIterations.addLast(nextIterationScope); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java Fri Feb 02 17:28:17 2018 -0800 @@ -27,6 +27,8 @@ import java.util.Iterator; import java.util.Objects; +import org.graalvm.collections.Pair; +import org.graalvm.collections.UnmodifiableMapCursor; import org.graalvm.compiler.core.common.Fields; import org.graalvm.compiler.core.common.util.FrequencyEncoder; import org.graalvm.compiler.core.common.util.TypeConversion; @@ -42,8 +44,6 @@ import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.java.ExceptionObjectNode; -import org.graalvm.util.Pair; -import org.graalvm.util.UnmodifiableMapCursor; import jdk.vm.ci.code.Architecture; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -30,6 +30,8 @@ import java.util.Iterator; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; @@ -59,8 +61,6 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; @@ -557,7 +557,7 @@ } else if (next1 instanceof DeoptimizeNode && next2 instanceof DeoptimizeNode) { DeoptimizeNode deopt1 = (DeoptimizeNode) next1; DeoptimizeNode deopt2 = (DeoptimizeNode) next2; - if (deopt1.reason() == deopt2.reason() && deopt1.action() == deopt2.action()) { + if (deopt1.getReason() == deopt2.getReason() && deopt1.getAction() == deopt2.getAction()) { // Same deoptimization reason and action. return true; } @@ -600,7 +600,7 @@ } } else if (a instanceof CompareNode) { CompareNode compareA = (CompareNode) a; - Condition conditionA = compareA.condition(); + Condition conditionA = compareA.condition().asCondition(); if (compareA.unorderedIsTrue()) { return false; } @@ -614,7 +614,7 @@ return false; } Condition comparableCondition = null; - Condition conditionB = compareB.condition(); + Condition conditionB = compareB.condition().asCondition(); if (compareB.getX() == compareA.getX() && compareB.getY() == compareA.getY()) { comparableCondition = conditionB; } else if (compareB.getX() == compareA.getY() && compareB.getY() == compareA.getX()) { @@ -1384,7 +1384,7 @@ @Override public AbstractBeginNode getPrimarySuccessor() { - return this.trueSuccessor(); + return null; } public AbstractBeginNode getSuccessor(boolean result) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2018, 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 org.graalvm.compiler.nodes; + +import jdk.vm.ci.code.BytecodePosition; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This class contains all inlining decisions performed on a graph during the compilation. + * + * Each inlining decision consists of: + * + *
    + *
  • a value indicating whether the decision was positive or negative
  • + *
  • the call target method
  • + *
  • the reason for the inlining decision
  • + *
  • the name of the phase in which the inlining decision took place
  • + *
  • the special {@link BytecodePositionWithId} value that describes the position in the bytecode + * together with the callsite-specific unique identifier
  • + *
  • the inlining log of the inlined graph, or {@code null} if the decision was negative
  • + *
+ * + * A phase that does inlining should use the instance of this class contained in the + * {@link StructuredGraph} by calling {@link #addDecision} whenever it decides to inline a method. + * If there are invokes in the graph at the end of the respective phase, then that phase must call + * {@link #addDecision} to log negative decisions. + * + * At the end of the compilation, the contents of the inlining log can be converted into a list of + * decisions by calling {@link #formatAsList} or into an inlining tree, by calling + * {@link #formatAsTree}. + */ +public class InliningLog { + /** + * A bytecode position with a unique identifier attached. + * + * The purpose of this class is to disambiguate callsites that are duplicated by a + * transformation (such as loop peeling or path duplication). + */ + public static final class BytecodePositionWithId extends BytecodePosition implements Comparable { + private final int id; + + public BytecodePositionWithId(BytecodePositionWithId caller, ResolvedJavaMethod method, int bci, int id) { + super(caller, method, bci); + this.id = id; + } + + public BytecodePositionWithId addCallerWithId(BytecodePositionWithId caller) { + if (getCaller() == null) { + return new BytecodePositionWithId(caller, getMethod(), getBCI(), id); + } else { + return new BytecodePositionWithId(getCaller().addCallerWithId(caller), getMethod(), getBCI(), id); + } + } + + public static BytecodePositionWithId create(FrameState state) { + return create(state, true); + } + + @SuppressWarnings("deprecation") + private static BytecodePositionWithId create(FrameState state, boolean topLevel) { + if (state == null) { + return null; + } + ResolvedJavaMethod method = state.getMethod(); + int bci = topLevel ? state.bci - 3 : state.bci; + int id = state.getId(); + return new BytecodePositionWithId(create(state.outerFrameState(), false), method, bci, id); + } + + @Override + public BytecodePositionWithId getCaller() { + return (BytecodePositionWithId) super.getCaller(); + } + + public BytecodePositionWithId withoutCaller() { + return new BytecodePositionWithId(null, getMethod(), getBCI(), id); + } + + public long getId() { + return id; + } + + @Override + public boolean equals(Object that) { + return super.equals(that) && this.id == ((BytecodePositionWithId) that).id; + } + + @Override + public int hashCode() { + return super.hashCode() ^ (id << 16); + } + + @Override + public int compareTo(BytecodePositionWithId that) { + int diff = this.getBCI() - that.getBCI(); + if (diff != 0) { + return diff; + } + diff = (int) (this.getId() - that.getId()); + return diff; + } + } + + public static final class Decision { + private final boolean positive; + private final String reason; + private final String phase; + private final ResolvedJavaMethod target; + private final BytecodePositionWithId position; + private final InliningLog childLog; + + private Decision(boolean positive, String reason, String phase, ResolvedJavaMethod target, BytecodePositionWithId position, InliningLog childLog) { + assert position != null; + this.positive = positive; + this.reason = reason; + this.phase = phase; + this.target = target; + this.position = position; + this.childLog = childLog; + } + + public boolean isPositive() { + return positive; + } + + public String getReason() { + return reason; + } + + public String getPhase() { + return phase; + } + + public BytecodePositionWithId getPosition() { + return position; + } + + public InliningLog getChildLog() { + return childLog; + } + + public ResolvedJavaMethod getTarget() { + return target; + } + } + + private static class Callsite { + public final List decisions; + public final Map children; + public final BytecodePositionWithId position; + + Callsite(BytecodePositionWithId position) { + this.children = new HashMap<>(); + this.position = position; + this.decisions = new ArrayList<>(); + } + + public Callsite getOrCreateChild(BytecodePositionWithId fromRootPosition) { + Callsite child = children.get(fromRootPosition.withoutCaller()); + if (child == null) { + child = new Callsite(fromRootPosition); + children.put(fromRootPosition.withoutCaller(), child); + } + return child; + } + + public Callsite createCallsite(BytecodePositionWithId fromRootPosition, String decision) { + Callsite parent = getOrCreateCallsite(fromRootPosition.getCaller()); + Callsite callsite = parent.getOrCreateChild(fromRootPosition); + callsite.decisions.add(decision); + return null; + } + + private Callsite getOrCreateCallsite(BytecodePositionWithId fromRootPosition) { + if (fromRootPosition == null) { + return this; + } else { + Callsite parent = getOrCreateCallsite(fromRootPosition.getCaller()); + Callsite callsite = parent.getOrCreateChild(fromRootPosition); + return callsite; + } + } + } + + private final List decisions; + + public InliningLog() { + this.decisions = new ArrayList<>(); + } + + public List getDecisions() { + return decisions; + } + + public void addDecision(boolean positive, String reason, String phase, ResolvedJavaMethod target, BytecodePositionWithId position, + InliningLog calleeLog) { + Decision decision = new Decision(positive, reason, phase, target, position, calleeLog); + decisions.add(decision); + } + + public String formatAsList() { + StringBuilder builder = new StringBuilder(); + formatAsList("", null, decisions, builder); + return builder.toString(); + } + + private void formatAsList(String phasePrefix, BytecodePositionWithId caller, List subDecisions, StringBuilder builder) { + for (Decision decision : subDecisions) { + String phaseStack = phasePrefix.equals("") ? decision.getPhase() : phasePrefix + "-" + decision.getPhase(); + String target = decision.getTarget().format("%H.%n(%p)"); + String positive = decision.isPositive() ? "inline" : "do not inline"; + BytecodePositionWithId absolutePosition = decision.getPosition().addCallerWithId(caller); + String position = " " + decision.getPosition().toString().replaceAll("\n", "\n "); + String line = String.format("<%s> %s %s: %s\n%s", phaseStack, positive, target, decision.getReason(), position); + builder.append(line).append(System.lineSeparator()); + if (decision.getChildLog() != null) { + formatAsList(phaseStack, absolutePosition, decision.getChildLog().getDecisions(), builder); + } + } + } + + public String formatAsTree() { + Callsite root = new Callsite(null); + createTree("", null, root, decisions); + StringBuilder builder = new StringBuilder(); + formatAsTree(root, "", builder); + return builder.toString(); + } + + private void createTree(String phasePrefix, BytecodePositionWithId caller, Callsite root, List subDecisions) { + for (Decision decision : subDecisions) { + String phaseStack = phasePrefix.equals("") ? decision.getPhase() : phasePrefix + "-" + decision.getPhase(); + String target = decision.getTarget().format("%H.%n(%p)"); + BytecodePositionWithId absolutePosition = decision.getPosition().addCallerWithId(caller); + String line = String.format("<%s> %s: %s", phaseStack, target, decision.getReason()); + root.createCallsite(absolutePosition, line); + if (decision.getChildLog() != null) { + createTree(phaseStack, absolutePosition, root, decision.getChildLog().getDecisions()); + } + } + } + + private void formatAsTree(Callsite site, String indent, StringBuilder builder) { + String position = site.position != null ? site.position.withoutCaller().toString() : ""; + String decision = String.join("; ", site.decisions); + String line = String.format("%s%s; %s", indent, position, decision); + builder.append(line).append(System.lineSeparator()); + String childIndent = indent + " "; + site.children.entrySet().stream().sorted((x, y) -> x.getKey().compareTo(y.getKey())).forEach(e -> { + formatAsTree(e.getValue(), childIndent, builder); + }); + } +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,9 +24,9 @@ import java.util.EnumMap; -import org.graalvm.util.Equivalence; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.word.LocationIdentity; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaKind.FormatWithToString; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StaticDeoptimizingNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StaticDeoptimizingNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.nodes; + +import org.graalvm.compiler.debug.GraalError; + +import jdk.vm.ci.meta.DeoptimizationAction; +import jdk.vm.ci.meta.DeoptimizationReason; +import jdk.vm.ci.meta.JavaConstant; + +public interface StaticDeoptimizingNode extends ValueNodeInterface { + + DeoptimizationReason getReason(); + + DeoptimizationAction getAction(); + + JavaConstant getSpeculation(); + + /** + * Describes how much information is gathered when deoptimization triggers. + * + * This enum is {@link Comparable} and orders its element from highest priority to lowest + * priority. + */ + enum GuardPriority { + Speculation, + Profile, + None; + + public boolean isHigherPriorityThan(GuardPriority other) { + return this.compareTo(other) < 0; + } + + public boolean isLowerPriorityThan(GuardPriority other) { + return this.compareTo(other) > 0; + } + + public static GuardPriority highest() { + return Speculation; + } + } + + default GuardPriority computePriority() { + if (getSpeculation() != null && getSpeculation().isNonNull()) { + return GuardNode.GuardPriority.Speculation; + } + switch (getAction()) { + case InvalidateReprofile: + case InvalidateRecompile: + return GuardNode.GuardPriority.Profile; + case RecompileIfTooManyDeopts: + case InvalidateStopCompiling: + case None: + return GuardNode.GuardPriority.None; + } + throw GraalError.shouldNotReachHere(); + } +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,6 +28,10 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.UnmodifiableEconomicMap; import org.graalvm.compiler.core.common.CancellationBailoutException; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.GraalOptions; @@ -38,6 +42,7 @@ import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; @@ -45,10 +50,6 @@ import org.graalvm.compiler.nodes.spi.VirtualizableAllocation; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; -import org.graalvm.util.UnmodifiableEconomicMap; import jdk.vm.ci.meta.Assumptions; import jdk.vm.ci.meta.Assumptions.Assumption; @@ -169,6 +170,7 @@ private final OptionValues options; private Cancellable cancellable = null; private final DebugContext debug; + private NodeSourcePosition callerContext; /** * Creates a builder for a graph. @@ -255,8 +257,13 @@ return this; } + public Builder callerContext(NodeSourcePosition context) { + this.callerContext = context; + return this; + } + public StructuredGraph build() { - return new StructuredGraph(name, rootMethod, entryBCI, assumptions, speculationLog, useProfilingInfo, compilationId, options, debug, cancellable); + return new StructuredGraph(name, rootMethod, entryBCI, assumptions, speculationLog, useProfilingInfo, compilationId, options, debug, cancellable, callerContext); } } @@ -284,6 +291,13 @@ private ScheduleResult lastSchedule; + private final InliningLog inliningLog; + + /** + * Call stack (context) leading to construction of this graph. + */ + private final NodeSourcePosition callerContext; + /** * Records the methods that were used while constructing this graph, one entry for each time a * specific method is used. @@ -317,7 +331,8 @@ CompilationIdentifier compilationId, OptionValues options, DebugContext debug, - Cancellable cancellable) { + Cancellable cancellable, + NodeSourcePosition context) { super(name, options, debug); this.setStart(add(new StartNode())); this.rootMethod = method; @@ -328,6 +343,8 @@ this.speculationLog = speculationLog; this.useProfilingInfo = useProfilingInfo; this.cancellable = cancellable; + this.inliningLog = new InliningLog(); + this.callerContext = context; } public void setLastSchedule(ScheduleResult result) { @@ -436,6 +453,10 @@ this.start = start; } + public InliningLog getInliningLog() { + return inliningLog; + } + /** * Creates a copy of this graph. * @@ -459,7 +480,7 @@ speculationLog, useProfilingInfo, newCompilationId, - getOptions(), debugForCopy, null); + getOptions(), debugForCopy, null, callerContext); if (allowAssumptions == AllowAssumptions.YES && assumptions != null) { copy.assumptions.record(assumptions); } @@ -931,4 +952,8 @@ protected void afterRegister(Node node) { assert hasValueProxies() || !(node instanceof ValueProxyNode); } + + public NodeSourcePosition getCallerContext() { + return callerContext; + } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,7 +25,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; -import jdk.vm.ci.meta.MetaAccessProvider; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; @@ -42,17 +42,18 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.PrimitiveConstant; -import org.graalvm.compiler.options.OptionValues; @NodeInfo(cycles = CYCLES_1) public abstract class CompareNode extends BinaryOpLogicNode implements Canonicalizable.Binary { public static final NodeClass TYPE = NodeClass.create(CompareNode.class); - protected final Condition condition; + protected final CanonicalCondition condition; protected final boolean unorderedIsTrue; /** @@ -61,7 +62,7 @@ * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ - protected CompareNode(NodeClass c, Condition condition, boolean unorderedIsTrue, ValueNode x, ValueNode y) { + protected CompareNode(NodeClass c, CanonicalCondition condition, boolean unorderedIsTrue, ValueNode x, ValueNode y) { super(c, x, y); this.condition = condition; this.unorderedIsTrue = unorderedIsTrue; @@ -72,7 +73,7 @@ * * @return the condition */ - public final Condition condition() { + public final CanonicalCondition condition() { return condition; } @@ -85,7 +86,7 @@ return this.unorderedIsTrue; } - public static LogicNode tryConstantFold(Condition condition, ValueNode forX, ValueNode forY, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) { + public static LogicNode tryConstantFold(CanonicalCondition condition, ValueNode forX, ValueNode forY, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) { if (forX.isConstant() && forY.isConstant() && (constantReflection != null || forX.asConstant() instanceof PrimitiveConstant)) { return LogicConstantNode.forBoolean(condition.foldCondition(forX.asConstant(), forY.asConstant(), constantReflection, unorderedIsTrue)); } @@ -93,7 +94,7 @@ } @SuppressWarnings("unused") - public static LogicNode tryConstantFoldPrimitive(Condition condition, ValueNode forX, ValueNode forY, boolean unorderedIsTrue, NodeView view) { + public static LogicNode tryConstantFoldPrimitive(CanonicalCondition condition, ValueNode forX, ValueNode forY, boolean unorderedIsTrue, NodeView view) { if (forX.asConstant() instanceof PrimitiveConstant && forY.asConstant() instanceof PrimitiveConstant) { return LogicConstantNode.forBoolean(condition.foldCondition((PrimitiveConstant) forX.asConstant(), (PrimitiveConstant) forY.asConstant(), unorderedIsTrue)); } @@ -107,11 +108,11 @@ * @return true for identity comparisons */ public boolean isIdentityComparison() { - return condition == Condition.EQ; + return condition == CanonicalCondition.EQ; } public abstract static class CompareOp { - public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition, + public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition, boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) { LogicNode constantCondition = tryConstantFold(condition, forX, forY, constantReflection, unorderedIsTrue); if (constantCondition != null) { @@ -151,9 +152,13 @@ } protected LogicNode canonicalizeSymmetricConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) { + CanonicalCondition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) { if (nonConstant instanceof ConditionalNode) { - return optimizeConditional(constant, (ConditionalNode) nonConstant, constantReflection, mirrored ? condition.mirror() : condition, unorderedIsTrue); + Condition realCondition = condition.asCondition(); + if (mirrored) { + realCondition = realCondition.mirror(); + } + return optimizeConditional(constant, (ConditionalNode) nonConstant, constantReflection, realCondition, unorderedIsTrue); } else if (nonConstant instanceof NormalizeCompareNode) { return optimizeNormalizeCompare(constantReflection, metaAccess, options, smallestCompareWidth, constant, (NormalizeCompareNode) nonConstant, mirrored, view); } else if (nonConstant instanceof ConvertNode) { @@ -186,7 +191,7 @@ return null; } - private static ConstantNode canonicalConvertConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Condition condition, + private static ConstantNode canonicalConvertConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, CanonicalCondition condition, ConvertNode convert, Constant constant, NodeView view) { if (convert.preservesOrder(condition, constant, constantReflection)) { Constant reverseConverted = convert.reverse(constant, constantReflection); @@ -235,18 +240,17 @@ protected abstract LogicNode duplicateModified(ValueNode newW, ValueNode newY, boolean unorderedIsTrue, NodeView view); } - public static LogicNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) { + public static LogicNode createCompareNode(StructuredGraph graph, CanonicalCondition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) { LogicNode result = createCompareNode(condition, x, y, constantReflection, view); return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result); } - public static LogicNode createCompareNode(Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) { + public static LogicNode createCompareNode(CanonicalCondition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) { assert x.getStackKind() == y.getStackKind(); - assert condition.isCanonical(); assert !x.getStackKind().isNumericFloat(); LogicNode comparison; - if (condition == Condition.EQ) { + if (condition == CanonicalCondition.EQ) { if (x.stamp(view) instanceof AbstractObjectStamp) { comparison = ObjectEqualsNode.create(x, y, constantReflection, view); } else if (x.stamp(view) instanceof AbstractPointerStamp) { @@ -255,11 +259,11 @@ assert x.getStackKind().isNumericInteger(); comparison = IntegerEqualsNode.create(x, y, view); } - } else if (condition == Condition.LT) { + } else if (condition == CanonicalCondition.LT) { assert x.getStackKind().isNumericInteger(); comparison = IntegerLessThanNode.create(x, y, view); } else { - assert condition == Condition.BT; + assert condition == CanonicalCondition.BT; assert x.getStackKind().isNumericInteger(); comparison = IntegerBelowNode.create(x, y, view); } @@ -268,19 +272,18 @@ } public static LogicNode createCompareNode(StructuredGraph graph, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Condition condition, ValueNode x, ValueNode y, NodeView view) { + CanonicalCondition condition, ValueNode x, ValueNode y, NodeView view) { LogicNode result = createCompareNode(constantReflection, metaAccess, options, smallestCompareWidth, condition, x, y, view); return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result); } public static LogicNode createCompareNode(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Condition condition, ValueNode x, ValueNode y, NodeView view) { + CanonicalCondition condition, ValueNode x, ValueNode y, NodeView view) { assert x.getStackKind() == y.getStackKind(); - assert condition.isCanonical(); assert !x.getStackKind().isNumericFloat(); LogicNode comparison; - if (condition == Condition.EQ) { + if (condition == CanonicalCondition.EQ) { if (x.stamp(view) instanceof AbstractObjectStamp) { assert smallestCompareWidth == null; comparison = ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y, view); @@ -290,11 +293,11 @@ assert x.getStackKind().isNumericInteger(); comparison = IntegerEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view); } - } else if (condition == Condition.LT) { + } else if (condition == CanonicalCondition.LT) { assert x.getStackKind().isNumericInteger(); comparison = IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view); } else { - assert condition == Condition.BT; + assert condition == CanonicalCondition.BT; assert x.getStackKind().isNumericInteger(); comparison = IntegerBelowNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view); } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,7 +26,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; import static org.graalvm.compiler.nodes.calc.CompareNode.createCompareNode; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -268,7 +268,7 @@ generator.emitConditional(this); } - public ConditionalNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) { + public ConditionalNode(StructuredGraph graph, CanonicalCondition condition, ValueNode x, ValueNode y) { this(createCompareNode(graph, condition, x, y, null, NodeView.DEFAULT)); } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConvertNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConvertNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConvertNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.nodes.calc; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValueNodeInterface; @@ -61,7 +61,7 @@ * @param op a comparison operator * @return true iff (c1 op c2) == (convert(c1) op convert(c2)) for all c1, c2 */ - default boolean preservesOrder(Condition op) { + default boolean preservesOrder(CanonicalCondition op) { return isLossless(); } @@ -73,7 +73,7 @@ * @param constantReflection * @return true iff (c1 op value) == (convert(c1) op convert(value)) for value and all c1 */ - default boolean preservesOrder(Condition op, Constant value, ConstantReflectionProvider constantReflection) { + default boolean preservesOrder(CanonicalCondition op, Constant value, ConstantReflectionProvider constantReflection) { return preservesOrder(op); } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,10 +22,9 @@ */ package org.graalvm.compiler.nodes.calc; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.TriState; -import org.graalvm.compiler.core.common.calc.Condition; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; + +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.FloatStamp; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; @@ -42,7 +41,9 @@ import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.TriState; @NodeInfo(shortName = "==", cycles = CYCLES_2) public final class FloatEqualsNode extends CompareNode implements BinaryCommutative { @@ -50,13 +51,13 @@ private static final FloatEqualsOp OP = new FloatEqualsOp(); public FloatEqualsNode(ValueNode x, ValueNode y) { - super(TYPE, Condition.EQ, false, x, y); + super(TYPE, CanonicalCondition.EQ, false, x, y); assert x.stamp(NodeView.DEFAULT) instanceof FloatStamp && y.stamp(NodeView.DEFAULT) instanceof FloatStamp : x.stamp(NodeView.DEFAULT) + " " + y.stamp(NodeView.DEFAULT); assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT)); } public static LogicNode create(ValueNode x, ValueNode y, NodeView view) { - LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.EQ, x, y, false, view); + LogicNode result = CompareNode.tryConstantFoldPrimitive(CanonicalCondition.EQ, x, y, false, view); if (result != null) { return result; } else { @@ -66,7 +67,7 @@ public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, ValueNode x, ValueNode y, NodeView view) { - LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, Condition.EQ, false, x, y, view); + LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, CanonicalCondition.EQ, false, x, y, view); if (value != null) { return value; } @@ -89,7 +90,7 @@ @Override public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { NodeView view = NodeView.from(tool); - ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, unorderedIsTrue, forX, forY, view); + ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), CanonicalCondition.EQ, unorderedIsTrue, forX, forY, view); if (value != null) { return value; } @@ -99,7 +100,7 @@ public static class FloatEqualsOp extends CompareOp { @Override - public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition, + public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition, boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) { LogicNode result = super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY, view); if (result != null) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,10 +22,9 @@ */ package org.graalvm.compiler.nodes.calc; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.TriState; -import org.graalvm.compiler.core.common.calc.Condition; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; + +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.FloatStamp; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; @@ -41,7 +40,9 @@ import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.TriState; @NodeInfo(shortName = "<", cycles = CYCLES_2) public final class FloatLessThanNode extends CompareNode { @@ -49,13 +50,13 @@ private static final FloatLessThanOp OP = new FloatLessThanOp(); public FloatLessThanNode(ValueNode x, ValueNode y, boolean unorderedIsTrue) { - super(TYPE, Condition.LT, unorderedIsTrue, x, y); + super(TYPE, CanonicalCondition.LT, unorderedIsTrue, x, y); assert x.stamp(NodeView.DEFAULT) instanceof FloatStamp && y.stamp(NodeView.DEFAULT) instanceof FloatStamp; assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT)); } public static LogicNode create(ValueNode x, ValueNode y, boolean unorderedIsTrue, NodeView view) { - LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.LT, x, y, unorderedIsTrue, view); + LogicNode result = CompareNode.tryConstantFoldPrimitive(CanonicalCondition.LT, x, y, unorderedIsTrue, view); if (result != null) { return result; } @@ -64,7 +65,7 @@ public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, ValueNode x, ValueNode y, boolean unorderedIsTrue, NodeView view) { - LogicNode result = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, Condition.LT, unorderedIsTrue, x, y, view); + LogicNode result = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, CanonicalCondition.LT, unorderedIsTrue, x, y, view); if (result != null) { return result; } @@ -74,7 +75,7 @@ @Override public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { NodeView view = NodeView.from(tool); - ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.LT, unorderedIsTrue, forX, forY, view); + ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), CanonicalCondition.LT, unorderedIsTrue, forX, forY, view); if (value != null) { return value; } @@ -84,7 +85,7 @@ public static class FloatLessThanOp extends CompareOp { @Override - public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition, + public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition, boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) { LogicNode result = super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY, view); if (result != null) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,10 +22,8 @@ */ package org.graalvm.compiler.nodes.calc; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.MetaAccessProvider; import org.graalvm.compiler.core.common.NumUtil; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; @@ -35,9 +33,11 @@ import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.CodeUtil; -import org.graalvm.compiler.options.OptionValues; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; @NodeInfo(shortName = "|<|") public final class IntegerBelowNode extends IntegerLowerThanNode { @@ -126,8 +126,8 @@ } @Override - protected Condition getCondition() { - return Condition.BT; + protected CanonicalCondition getCondition() { + return CanonicalCondition.BT; } @Override diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,9 +22,7 @@ */ package org.graalvm.compiler.nodes.calc; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.MetaAccessProvider; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.FloatStamp; import org.graalvm.compiler.core.common.type.IntegerStamp; @@ -42,12 +40,14 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.PrimitiveConstant; import jdk.vm.ci.meta.TriState; -import org.graalvm.compiler.options.OptionValues; @NodeInfo(shortName = "==") public final class IntegerEqualsNode extends CompareNode implements BinaryCommutative { @@ -55,13 +55,13 @@ private static final IntegerEqualsOp OP = new IntegerEqualsOp(); public IntegerEqualsNode(ValueNode x, ValueNode y) { - super(TYPE, Condition.EQ, false, x, y); + super(TYPE, CanonicalCondition.EQ, false, x, y); assert !x.getStackKind().isNumericFloat() && x.getStackKind() != JavaKind.Object; assert !y.getStackKind().isNumericFloat() && y.getStackKind() != JavaKind.Object; } public static LogicNode create(ValueNode x, ValueNode y, NodeView view) { - LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.EQ, x, y, false, view); + LogicNode result = CompareNode.tryConstantFoldPrimitive(CanonicalCondition.EQ, x, y, false, view); if (result != null) { return result; } @@ -87,7 +87,7 @@ public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, ValueNode x, ValueNode y, NodeView view) { - LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, Condition.EQ, false, x, y, view); + LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, CanonicalCondition.EQ, false, x, y, view); if (value != null) { return value; } @@ -97,7 +97,7 @@ @Override public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { NodeView view = NodeView.from(tool); - ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, false, forX, forY, view); + ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), CanonicalCondition.EQ, false, forX, forY, view); if (value != null) { return value; } @@ -149,7 +149,7 @@ } @Override - public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition, + public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition, boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { return LogicConstantNode.tautology(); @@ -186,7 +186,7 @@ @Override protected LogicNode canonicalizeSymmetricConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) { + CanonicalCondition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) { if (constant instanceof PrimitiveConstant) { PrimitiveConstant primitiveConstant = (PrimitiveConstant) constant; IntegerStamp nonConstantStamp = ((IntegerStamp) nonConstant.stamp(view)); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,12 +22,10 @@ */ package org.graalvm.compiler.nodes.calc; -import static org.graalvm.compiler.core.common.calc.Condition.LT; +import static org.graalvm.compiler.core.common.calc.CanonicalCondition.LT; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.MetaAccessProvider; import org.graalvm.compiler.core.common.NumUtil; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.FloatStamp; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -42,13 +40,15 @@ import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.PrimitiveConstant; -import org.graalvm.compiler.options.OptionValues; @NodeInfo(shortName = "<") public final class IntegerLessThanNode extends IntegerLowerThanNode { @@ -258,7 +258,7 @@ } @Override - protected Condition getCondition() { + protected CanonicalCondition getCondition() { return LT; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,9 +22,7 @@ */ package org.graalvm.compiler.nodes.calc; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.MetaAccessProvider; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; @@ -36,9 +34,11 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.TriState; -import org.graalvm.compiler.options.OptionValues; /** * Common super-class for "a < b" comparisons both {@linkplain IntegerLowerThanNode signed} and @@ -117,7 +117,7 @@ public abstract static class LowerOp extends CompareOp { @Override - public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition, + public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition, boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) { LogicNode result = super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY, view); if (result != null) { @@ -156,7 +156,7 @@ protected abstract IntegerStamp forInteger(int bits, long min, long max); - protected abstract Condition getCondition(); + protected abstract CanonicalCondition getCondition(); protected abstract IntegerLowerThanNode createNode(ValueNode x, ValueNode y); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -112,9 +112,9 @@ // ==> sxxx -(sign-extend)-> sssssxxx return SignExtendNode.create(other.getValue(), other.getInputBits(), getResultBits(), view); } else if (other instanceof ZeroExtendNode) { - // xxxx -(zero-extend)-> 00000000 00000xxx -(narrow)-> 0000xxxx + // xxxx -(zero-extend)-> 00000000 0000xxxx -(narrow)-> 0000xxxx // ==> xxxx -(zero-extend)-> 0000xxxx - return new ZeroExtendNode(other.getValue(), other.getInputBits(), getResultBits()); + return new ZeroExtendNode(other.getValue(), other.getInputBits(), getResultBits(), ((ZeroExtendNode) other).isInputAlwaysPositive()); } } } else if (forValue instanceof AndNode) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,7 +24,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.IterableNodeType; @@ -67,10 +67,10 @@ } protected static ValueNode tryConstantFold(ValueNode x, ValueNode y, boolean isUnorderedLess, JavaKind kind, ConstantReflectionProvider constantReflection) { - LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, null, false); + LogicNode result = CompareNode.tryConstantFold(CanonicalCondition.EQ, x, y, null, false); if (result instanceof LogicConstantNode) { LogicConstantNode logicConstantNode = (LogicConstantNode) result; - LogicNode resultLT = CompareNode.tryConstantFold(Condition.LT, x, y, constantReflection, isUnorderedLess); + LogicNode resultLT = CompareNode.tryConstantFold(CanonicalCondition.LT, x, y, constantReflection, isUnorderedLess); if (resultLT instanceof LogicConstantNode) { LogicConstantNode logicConstantNodeLT = (LogicConstantNode) resultLT; if (logicConstantNodeLT.getValue()) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.nodes.calc; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.ObjectStamp; @@ -42,6 +42,7 @@ import org.graalvm.compiler.nodes.spi.VirtualizerTool; import org.graalvm.compiler.nodes.virtual.VirtualBoxingNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; @@ -49,7 +50,6 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; -import org.graalvm.compiler.options.OptionValues; @NodeInfo(shortName = "==") public final class ObjectEqualsNode extends PointerEqualsNode implements Virtualizable { @@ -64,7 +64,7 @@ } public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) { - LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false); + LogicNode result = CompareNode.tryConstantFold(CanonicalCondition.EQ, x, y, constantReflection, false); if (result != null) { return result; } else { @@ -77,7 +77,7 @@ } public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, ValueNode x, ValueNode y, NodeView view) { - LogicNode result = OP.canonical(constantReflection, metaAccess, options, null, Condition.EQ, false, x, y, view); + LogicNode result = OP.canonical(constantReflection, metaAccess, options, null, CanonicalCondition.EQ, false, x, y, view); if (result != null) { return result; } @@ -87,7 +87,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { NodeView view = NodeView.from(tool); - ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, false, forX, forY, view); + ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), CanonicalCondition.EQ, false, forX, forY, view); if (value != null) { return value; } @@ -98,7 +98,7 @@ @Override protected LogicNode canonicalizeSymmetricConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, - Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) { + CanonicalCondition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) { ResolvedJavaType type = constantReflection.asJavaType(constant); if (type != null && nonConstant instanceof GetClassNode) { GetClassNode getClassNode = (GetClassNode) nonConstant; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,9 +22,7 @@ */ package org.graalvm.compiler.nodes.calc; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.MetaAccessProvider; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; @@ -41,11 +39,13 @@ import org.graalvm.compiler.nodes.extended.LoadMethodNode; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.TriState; -import org.graalvm.compiler.options.OptionValues; @NodeInfo(shortName = "==") public class PointerEqualsNode extends CompareNode implements BinaryCommutative { @@ -66,7 +66,7 @@ } protected PointerEqualsNode(NodeClass c, ValueNode x, ValueNode y) { - super(c, Condition.EQ, false, x, y); + super(c, CanonicalCondition.EQ, false, x, y); assert x.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp; assert y.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp; } @@ -74,7 +74,7 @@ @Override public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { NodeView view = NodeView.from(tool); - ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, false, forX, forY, view); + ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), CanonicalCondition.EQ, false, forX, forY, view); if (value != null) { return value; } @@ -88,9 +88,9 @@ * could select a certain method and if so, returns {@code true} if the answer is guaranteed * to be false. Otherwise, returns {@code false}. */ - private static boolean isAlwaysFailingVirtualDispatchTest(Condition condition, ValueNode forX, ValueNode forY) { + private static boolean isAlwaysFailingVirtualDispatchTest(CanonicalCondition condition, ValueNode forX, ValueNode forY) { if (forY.isConstant()) { - if (forX instanceof LoadMethodNode && condition == Condition.EQ) { + if (forX instanceof LoadMethodNode && condition == CanonicalCondition.EQ) { LoadMethodNode lm = ((LoadMethodNode) forX); if (lm.getMethod().getEncoding().equals(forY.asConstant())) { if (lm.getHub() instanceof LoadHubNode) { @@ -112,7 +112,7 @@ } @Override - public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition, + public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition, boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) { LogicNode result = findSynonym(forX, forY, view); if (result != null) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -95,7 +95,7 @@ if (other.getResultBits() > other.getInputBits()) { // sxxx -(zero-extend)-> 0000 sxxx -(sign-extend)-> 00000000 0000sxxx // ==> sxxx -(zero-extend)-> 00000000 0000sxxx - return ZeroExtendNode.create(other.getValue(), other.getInputBits(), resultBits, view); + return ZeroExtendNode.create(other.getValue(), other.getInputBits(), resultBits, view, other.isInputAlwaysPositive()); } } @@ -104,7 +104,7 @@ if ((inputStamp.upMask() & (1L << (inputBits - 1))) == 0L) { // 0xxx -(sign-extend)-> 0000 0xxx // ==> 0xxx -(zero-extend)-> 0000 0xxx - return ZeroExtendNode.create(forValue, inputBits, resultBits, view); + return ZeroExtendNode.create(forValue, inputBits, resultBits, view, true); } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,7 +24,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.ArithmeticOpTable; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow; @@ -50,26 +50,33 @@ public static final NodeClass TYPE = NodeClass.create(ZeroExtendNode.class); + private final boolean inputAlwaysPositive; + public ZeroExtendNode(ValueNode input, int resultBits) { - this(input, PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)), resultBits); + this(input, PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)), resultBits, false); assert 0 < PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) && PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) <= resultBits; } - public ZeroExtendNode(ValueNode input, int inputBits, int resultBits) { + public ZeroExtendNode(ValueNode input, int inputBits, int resultBits, boolean inputAlwaysPositive) { super(TYPE, ArithmeticOpTable::getZeroExtend, ArithmeticOpTable::getNarrow, inputBits, resultBits, input); + this.inputAlwaysPositive = inputAlwaysPositive; } public static ValueNode create(ValueNode input, int resultBits, NodeView view) { - return create(input, PrimitiveStamp.getBits(input.stamp(view)), resultBits, view); + return create(input, PrimitiveStamp.getBits(input.stamp(view)), resultBits, view, false); } public static ValueNode create(ValueNode input, int inputBits, int resultBits, NodeView view) { + return create(input, inputBits, resultBits, view, false); + } + + public static ValueNode create(ValueNode input, int inputBits, int resultBits, NodeView view, boolean alwaysPositive) { IntegerConvertOp signExtend = ArithmeticOpTable.forStamp(input.stamp(view)).getZeroExtend(); ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp(view))); if (synonym != null) { return synonym; } - return canonical(null, input, inputBits, resultBits, view); + return canonical(null, input, inputBits, resultBits, view, alwaysPositive); } @Override @@ -77,12 +84,13 @@ return true; } + public boolean isInputAlwaysPositive() { + return inputAlwaysPositive; + } + @Override - public boolean preservesOrder(Condition cond) { + public boolean preservesOrder(CanonicalCondition cond) { switch (cond) { - case GE: - case GT: - case LE: case LT: return false; default: @@ -98,16 +106,16 @@ return ret; } - return canonical(this, forValue, getInputBits(), getResultBits(), view); + return canonical(this, forValue, getInputBits(), getResultBits(), view, inputAlwaysPositive); } - private static ValueNode canonical(ZeroExtendNode zeroExtendNode, ValueNode forValue, int inputBits, int resultBits, NodeView view) { + private static ValueNode canonical(ZeroExtendNode zeroExtendNode, ValueNode forValue, int inputBits, int resultBits, NodeView view, boolean alwaysPositive) { ZeroExtendNode self = zeroExtendNode; if (forValue instanceof ZeroExtendNode) { // xxxx -(zero-extend)-> 0000 xxxx -(zero-extend)-> 00000000 0000xxxx // ==> xxxx -(zero-extend)-> 00000000 0000xxxx ZeroExtendNode other = (ZeroExtendNode) forValue; - return new ZeroExtendNode(other.getValue(), other.getInputBits(), resultBits); + return new ZeroExtendNode(other.getValue(), other.getInputBits(), resultBits, other.isInputAlwaysPositive()); } if (forValue instanceof NarrowNode) { NarrowNode narrow = (NarrowNode) forValue; @@ -135,7 +143,7 @@ } if (self == null) { - self = new ZeroExtendNode(forValue, inputBits, resultBits); + self = new ZeroExtendNode(forValue, inputBits, resultBits, alwaysPositive); } return self; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java Fri Feb 02 17:28:17 2018 -0800 @@ -42,7 +42,6 @@ import org.graalvm.word.LocationIdentity; public final class Block extends AbstractBlockBase { - public static final Block[] EMPTY_ARRAY = new Block[0]; protected final AbstractBeginNode beginNode; @@ -53,7 +52,6 @@ private Loop loop; protected Block postdominator; - protected Block distancedDominatorCache; private LocationSet killLocations; private LocationSet killLocationsBetweenThisAndDominator; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWrite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWrite.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013, 2015, 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 org.graalvm.compiler.nodes.extended; + +import org.graalvm.compiler.graph.NodeInterface; +import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; + +public interface ArrayRangeWrite extends NodeInterface { + AddressNode getAddress(); + + /** + * The length of the modified range. + */ + ValueNode getLength(); + + /** + * Return true if the written array is an object array, false if it is a primitive array. + */ + boolean writesObjectArray(); + + /** + * Returns whether this write is the initialization of the written location. If it is true, the + * old value of the memory location is either uninitialized or zero. If it is false, the memory + * location is guaranteed to contain a valid value or zero. + */ + boolean isInitialization(); + + int getElementStride(); + + @Override + FixedWithNextNode asNode(); +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWriteNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWriteNode.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2013, 2015, 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 org.graalvm.compiler.nodes.extended; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; - -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint; - -/** - * Base class for nodes that modify a range of an array. - */ -@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) -public abstract class ArrayRangeWriteNode extends AbstractMemoryCheckpoint { - - public static final NodeClass TYPE = NodeClass.create(ArrayRangeWriteNode.class); - - protected ArrayRangeWriteNode(NodeClass c, Stamp stamp) { - super(c, 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(); - - /** - * Returns whether this write is the initialization of the written location. If it is true, the - * old value of the memory location is either uninitialized or zero. If it is false, the memory - * location is guaranteed to contain a valid value or zero. - */ - public abstract boolean isInitialization(); -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,7 +25,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.iterators.NodePredicates; @@ -101,7 +101,7 @@ } boolean usageFound = false; for (IntegerEqualsNode node : this.usages().filter(IntegerEqualsNode.class)) { - assert node.condition() == Condition.EQ; + assert node.condition() == CanonicalCondition.EQ; ValueNode other = node.getX(); if (node.getX() == this) { other = node.getY(); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -97,7 +97,7 @@ ValueNode offsetValue = tool.getAlias(offset()); if (offsetValue.isConstant()) { long off = offsetValue.asJavaConstant().asLong(); - int entryIndex = virtual.entryIndexForOffset(off, accessKind()); + int entryIndex = virtual.entryIndexForOffset(tool.getArrayOffsetProvider(), off, accessKind()); if (entryIndex != -1) { ValueNode entry = tool.getEntry(virtual, entryIndex); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -119,7 +119,7 @@ ValueNode indexValue = tool.getAlias(offset()); if (indexValue.isConstant()) { long off = indexValue.asJavaConstant().asLong(); - int entryIndex = virtual.entryIndexForOffset(off, accessKind()); + int entryIndex = virtual.entryIndexForOffset(tool.getArrayOffsetProvider(), off, accessKind()); if (entryIndex != -1 && tool.setVirtualEntry(virtual, entryIndex, value(), accessKind(), off)) { tool.delete(); } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -228,7 +228,7 @@ @Override public AbstractBeginNode getPrimarySuccessor() { - return this.defaultSuccessor(); + return null; } /** diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java Fri Feb 02 17:28:17 2018 -0800 @@ -82,6 +82,10 @@ return methodToInline; } + public boolean allowsInlining() { + return methodToInline != null; + } + /** * Gets the provider of bytecode to be parsed for {@link #getMethodToInline()} if is is an * intrinsic for the original method (i.e., the {@code method} passed to diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java Fri Feb 02 17:28:17 2018 -0800 @@ -35,6 +35,12 @@ import java.util.List; import java.util.Map; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.MapCursor; +import org.graalvm.collections.Pair; +import org.graalvm.collections.UnmodifiableEconomicMap; +import org.graalvm.collections.UnmodifiableMapCursor; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitutionRegistry; import org.graalvm.compiler.bytecode.BytecodeProvider; @@ -44,12 +50,6 @@ import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; -import org.graalvm.util.MapCursor; -import org.graalvm.util.Pair; -import org.graalvm.util.UnmodifiableEconomicMap; -import org.graalvm.util.UnmodifiableMapCursor; import jdk.vm.ci.meta.MetaUtil; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -112,6 +112,26 @@ } /** + * A symbol for an already resolved method. + */ + public static class ResolvedJavaSymbol implements Type { + private final ResolvedJavaType resolved; + + public ResolvedJavaSymbol(ResolvedJavaType type) { + this.resolved = type; + } + + public ResolvedJavaType getResolved() { + return resolved; + } + + @Override + public String toString() { + return resolved.toJavaName(); + } + } + + /** * A symbol that is lazily {@linkplain OptionalLazySymbol#resolve() resolved} to a {@link Type}. */ static class OptionalLazySymbol implements Type { @@ -696,7 +716,7 @@ * * @param declaringClass the class to test */ - protected boolean canBeIntrinsified(ResolvedJavaType declaringClass) { + public boolean canBeIntrinsified(ResolvedJavaType declaringClass) { return true; } @@ -1150,6 +1170,9 @@ } static boolean checkResolvable(boolean isOptional, Type declaringType, Binding binding) { + if (declaringType instanceof ResolvedJavaSymbol) { + return checkResolvable(isOptional, ((ResolvedJavaSymbol) declaringType).getResolved(), binding); + } Class declaringClass = InvocationPlugins.resolveType(declaringType, isOptional); if (declaringClass == null) { return true; @@ -1165,6 +1188,13 @@ } return true; } + + private static boolean checkResolvable(boolean isOptional, ResolvedJavaType declaringType, Binding binding) { + if (resolveJavaMethod(declaringType, binding) == null && !isOptional) { + throw new AssertionError(String.format("Method not found: %s.%s%s", declaringType.toJavaName(), binding.name, binding.argumentsDescriptor)); + } + return true; + } } /** @@ -1235,7 +1265,7 @@ * {@link NoSuchMethodError} is thrown. * * @param declaringClass the class to search for a method matching {@code binding} - * @return the method (if any) in {@code declaringClass} matching binding + * @return the method (if any) in {@code declaringClass} matching {@code binding} */ public static Method resolveMethod(Class declaringClass, Binding binding) { if (binding.name.equals("")) { @@ -1243,32 +1273,70 @@ } Method[] methods = declaringClass.getDeclaredMethods(); List parameterTypeNames = parseParameters(binding.argumentsDescriptor); + Method match = null; for (int i = 0; i < methods.length; ++i) { Method m = methods[i]; - if (binding.isStatic == Modifier.isStatic(m.getModifiers()) && m.getName().equals(binding.name)) { - if (parameterTypeNames.equals(toInternalTypeNames(m.getParameterTypes()))) { - for (int j = i + 1; j < methods.length; ++j) { - Method other = methods[j]; - if (binding.isStatic == Modifier.isStatic(other.getModifiers()) && other.getName().equals(binding.name)) { - if (parameterTypeNames.equals(toInternalTypeNames(other.getParameterTypes()))) { - if (m.getReturnType().isAssignableFrom(other.getReturnType())) { - // `other` has a more specific return type - choose it - // (m is most likely a bridge method) - m = other; - } else { - if (!other.getReturnType().isAssignableFrom(m.getReturnType())) { - throw new NoSuchMethodError(String.format( - "Found 2 methods with same name and parameter types but unrelated return types:%n %s%n %s", m, other)); - } - } - } - } + if (binding.isStatic == Modifier.isStatic(m.getModifiers()) && + m.getName().equals(binding.name) && + parameterTypeNames.equals(toInternalTypeNames(m.getParameterTypes()))) { + if (match == null) { + match = m; + } else if (match.getReturnType().isAssignableFrom(m.getReturnType())) { + // `m` has a more specific return type - choose it + // (`match` is most likely a bridge method) + match = m; + } else { + if (!m.getReturnType().isAssignableFrom(match.getReturnType())) { + throw new NoSuchMethodError(String.format( + "Found 2 methods with same name and parameter types but unrelated return types:%n %s%n %s", match, m)); } + } + } + } + return match; + } + + /** + * Same as {@link #resolveMethod(Class, Binding)} and + * {@link #resolveConstructor(Class, Binding)} except in terms of {@link ResolvedJavaType} and + * {@link ResolvedJavaMethod}. + */ + public static ResolvedJavaMethod resolveJavaMethod(ResolvedJavaType declaringClass, Binding binding) { + ResolvedJavaMethod[] methods = declaringClass.getDeclaredMethods(); + if (binding.name.equals("")) { + for (ResolvedJavaMethod m : methods) { + if (m.getName().equals("") && m.getSignature().toMethodDescriptor().startsWith(binding.argumentsDescriptor)) { return m; } } + return null; } - return null; + + ResolvedJavaMethod match = null; + for (int i = 0; i < methods.length; ++i) { + ResolvedJavaMethod m = methods[i]; + if (binding.isStatic == m.isStatic() && + m.getName().equals(binding.name) && + m.getSignature().toMethodDescriptor().startsWith(binding.argumentsDescriptor)) { + if (match == null) { + match = m; + } else { + final ResolvedJavaType matchReturnType = (ResolvedJavaType) match.getSignature().getReturnType(declaringClass); + final ResolvedJavaType mReturnType = (ResolvedJavaType) m.getSignature().getReturnType(declaringClass); + if (matchReturnType.isAssignableFrom(mReturnType)) { + // `m` has a more specific return type - choose it + // (`match` is most likely a bridge method) + match = m; + } else { + if (!mReturnType.isAssignableFrom(matchReturnType)) { + throw new NoSuchMethodError(String.format( + "Found 2 methods with same name and parameter types but unrelated return types:%n %s%n %s", match, m)); + } + } + } + } + } + return match; } /** diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -39,10 +39,10 @@ import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.Value; -import sun.misc.Unsafe; /** - * Represents an atomic read-and-add operation like {@link Unsafe#getAndAddInt(Object, long, int)}. + * Represents an atomic read-and-add operation like + * {@link sun.misc.Unsafe#getAndAddInt(Object, long, int)}. */ @NodeInfo(allowedUsageTypes = Memory, cycles = CYCLES_8, size = SIZE_2) public final class AtomicReadAndAddNode extends AbstractMemoryCheckpoint implements LIRLowerable, MemoryCheckpoint.Single { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -36,11 +36,10 @@ import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; -import sun.misc.Unsafe; /** - * Represents an atomic read-and-write operation like {@link Unsafe#getAndSetInt(Object, long, int)} - * . + * Represents an atomic read-and-write operation like + * {@link sun.misc.Unsafe#getAndSetInt(Object, long, int)}. */ @NodeInfo(cycles = CYCLES_8, size = SIZE_2) public final class AtomicReadAndWriteNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -125,6 +125,13 @@ } @NodeIntrinsic + private static native Object newArray(Class componentType, int length, @ConstantNodeParameter boolean fillContents); + + public static Object newArray(Class componentType, int length) { + return newArray(componentType, length, true); + } + + @NodeIntrinsic private static native Object newArray(Class componentType, int length, @ConstantNodeParameter boolean fillContents, @ConstantNodeParameter JavaKind knownElementKind); public static Object newArray(Class componentType, int length, JavaKind knownElementKind) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -42,11 +42,10 @@ import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.Value; -import sun.misc.Unsafe; /** * Represents the lowered version of an atomic read-and-write operation like - * {@link Unsafe#getAndSetInt(Object, long, int)} . + * {@link sun.misc.Unsafe#getAndSetInt(Object, long, int)}. */ @NodeInfo(allowedUsageTypes = {Memory}, cycles = CYCLES_8, size = SIZE_2) public final class LoweredAtomicReadAndWriteNode extends FixedAccessNode implements StateSplit, LIRLowerableAccess, MemoryCheckpoint.Single { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,7 +24,7 @@ import java.util.Collections; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -132,7 +132,7 @@ // Should be areFrameStatesAtSideEffects but currently SVM will complain about // RuntimeConstraint if (graph().getGuardsStage().allowsFloatingGuards()) { - LogicNode lengthNegativeCondition = CompareNode.createCompareNode(graph(), Condition.LT, length(), ConstantNode.forInt(0, graph()), tool.getConstantReflection(), view); + LogicNode lengthNegativeCondition = CompareNode.createCompareNode(graph(), CanonicalCondition.LT, length(), ConstantNode.forInt(0, graph()), tool.getConstantReflection(), view); // we do not have a non-deopting path for that at the moment so action=None. FixedGuardNode guard = graph().add(new FixedGuardNode(lengthNegativeCondition, DeoptimizationReason.RuntimeConstraint, DeoptimizationAction.None, true)); graph().replaceFixedWithFixed(this, guard); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -32,6 +32,9 @@ import java.util.Collection; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.MapCursor; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; @@ -41,9 +44,6 @@ import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.MapCursor; import org.graalvm.word.LocationIdentity; @NodeInfo(allowedUsageTypes = {Extension, Memory}, cycles = CYCLES_0, size = SIZE_0) diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.nodes.spi; +import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; @@ -31,7 +32,7 @@ /** * Provides a capability for replacing a higher node with one or more lower level nodes. */ -public interface LoweringProvider { +public interface LoweringProvider extends ArrayOffsetProvider { void lower(Node n, LoweringTool tool); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,6 +24,7 @@ import java.util.List; +import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; @@ -56,6 +57,8 @@ */ ConstantReflectionProvider getConstantReflectionProvider(); + ArrayOffsetProvider getArrayOffsetProvider(); + /** * This method should be used to query the maximum size of virtualized objects before attempting * virtualization. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Fri Feb 02 17:28:17 2018 -0800 @@ -30,6 +30,10 @@ import java.util.List; import java.util.function.BiFunction; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.MapCursor; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.code.SourceStackTraceBailoutException; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; @@ -76,10 +80,6 @@ import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; -import org.graalvm.util.MapCursor; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.BytecodePosition; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,6 +24,7 @@ import java.nio.ByteOrder; +import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.Verbosity; @@ -35,7 +36,6 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaType; -import sun.misc.Unsafe; @NodeInfo(nameTemplate = "VirtualArray({p#objectId}) {p#componentType/s}[{p#length}]") public class VirtualArrayNode extends VirtualObjectNode implements ArrayLengthProvider { @@ -88,53 +88,14 @@ } @Override - public int entryIndexForOffset(long constantOffset, JavaKind expectedEntryKind) { - return entryIndexForOffset(constantOffset, expectedEntryKind, componentType, length); + public int entryIndexForOffset(ArrayOffsetProvider arrayOffsetProvider, long constantOffset, JavaKind expectedEntryKind) { + return entryIndexForOffset(arrayOffsetProvider, constantOffset, expectedEntryKind, componentType, length); } - public static int entryIndexForOffset(long constantOffset, JavaKind expectedEntryKind, ResolvedJavaType componentType, int length) { - int baseOffset; - int indexScale; - switch (componentType.getJavaKind()) { - case Boolean: - baseOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET; - indexScale = Unsafe.ARRAY_BOOLEAN_INDEX_SCALE; - break; - case Byte: - baseOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET; - indexScale = Unsafe.ARRAY_BYTE_INDEX_SCALE; - break; - case Short: - baseOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET; - indexScale = Unsafe.ARRAY_SHORT_INDEX_SCALE; - break; - case Char: - baseOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET; - indexScale = Unsafe.ARRAY_CHAR_INDEX_SCALE; - break; - case Int: - baseOffset = Unsafe.ARRAY_INT_BASE_OFFSET; - indexScale = Unsafe.ARRAY_INT_INDEX_SCALE; - break; - case Long: - baseOffset = Unsafe.ARRAY_LONG_BASE_OFFSET; - indexScale = Unsafe.ARRAY_LONG_INDEX_SCALE; - break; - case Float: - baseOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET; - indexScale = Unsafe.ARRAY_FLOAT_INDEX_SCALE; - break; - case Double: - baseOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET; - indexScale = Unsafe.ARRAY_DOUBLE_INDEX_SCALE; - break; - case Object: - baseOffset = Unsafe.ARRAY_OBJECT_BASE_OFFSET; - indexScale = Unsafe.ARRAY_OBJECT_INDEX_SCALE; - break; - default: - return -1; - } + public static int entryIndexForOffset(ArrayOffsetProvider arrayOffsetProvider, long constantOffset, JavaKind expectedEntryKind, ResolvedJavaType componentType, int length) { + int baseOffset = arrayOffsetProvider.arrayBaseOffset(componentType.getJavaKind()); + int indexScale = arrayOffsetProvider.arrayScalingFactor(componentType.getJavaKind()); + long offset; if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN && componentType.isPrimitive()) { // On big endian, we expect the value to be correctly aligned in memory diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.nodes.virtual; +import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.Verbosity; @@ -100,7 +101,7 @@ } @Override - public int entryIndexForOffset(long constantOffset, JavaKind expectedEntryKind) { + public int entryIndexForOffset(ArrayOffsetProvider arrayOffsetProvider, long constantOffset, JavaKind expectedEntryKind) { return fieldIndex(type.findInstanceFieldWithOffset(constantOffset, expectedEntryKind)); } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualObjectNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualObjectNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualObjectNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,6 +25,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; +import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.graph.IterableNodeType; @@ -95,7 +96,7 @@ * @param expectedEntryKind Specifies which type is expected at this offset (Is important when * doing implicit casts, especially on big endian systems. */ - public abstract int entryIndexForOffset(long constantOffset, JavaKind expectedEntryKind); + public abstract int entryIndexForOffset(ArrayOffsetProvider arrayOffsetProvider, long constantOffset, JavaKind expectedEntryKind); /** * Returns the {@link JavaKind} of the entry at the given index. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,7 +24,7 @@ import java.util.EnumSet; -import org.graalvm.util.EconomicMap; +import org.graalvm.collections.EconomicMap; public class EnumOptionKey> extends OptionKey { final Class enumClass; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,10 +24,10 @@ import java.util.concurrent.atomic.AtomicReference; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; -import org.graalvm.util.UnmodifiableEconomicMap; -import org.graalvm.util.UnmodifiableMapCursor; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.UnmodifiableEconomicMap; +import org.graalvm.collections.UnmodifiableMapCursor; /** * A context for obtaining values for {@link OptionKey}s that allows for key/value pairs to be diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,7 +24,7 @@ import java.util.Formatter; -import org.graalvm.util.EconomicMap; +import org.graalvm.collections.EconomicMap; /** * A key for an option. The value for an option is obtained from an {@link OptionValues} object. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java Fri Feb 02 17:28:17 2018 -0800 @@ -30,10 +30,10 @@ import java.util.SortedMap; import java.util.TreeMap; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; -import org.graalvm.util.UnmodifiableEconomicMap; -import org.graalvm.util.UnmodifiableMapCursor; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.UnmodifiableEconomicMap; +import org.graalvm.collections.UnmodifiableMapCursor; /** * A context for obtaining values for {@link OptionKey}s. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,9 +28,9 @@ import java.util.List; import java.util.ServiceLoader; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.MapCursor; import org.graalvm.util.CollectionsUtil; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.MapCursor; /** * This class contains methods for parsing Graal options and matching them against a set of diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -33,6 +33,15 @@ public class AddressLoweringPhase extends Phase { public abstract static class AddressLowering { + + @SuppressWarnings("unused") + public void preProcess(StructuredGraph graph) { + } + + @SuppressWarnings("unused") + public void postProcess(AddressNode lowered) { + } + public abstract AddressNode lower(ValueNode base, ValueNode offset); } @@ -45,11 +54,13 @@ @Override protected void run(StructuredGraph graph) { + lowering.preProcess(graph); for (Node node : graph.getNodes()) { AddressNode lowered; if (node instanceof OffsetAddressNode) { OffsetAddressNode address = (OffsetAddressNode) node; lowered = lowering.lower(address.getBase(), address.getOffset()); + lowering.postProcess(lowered); } else { continue; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,6 +26,10 @@ import java.util.Deque; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.MapCursor; +import org.graalvm.collections.Pair; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.type.ArithmeticOpTable; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp; @@ -87,10 +91,6 @@ import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.PhaseContext; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; -import org.graalvm.util.MapCursor; -import org.graalvm.util.Pair; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.TriState; @@ -124,7 +124,11 @@ if (moveGuards) { cfg.visitDominatorTree(new MoveGuardsUpwards(), graph.hasValueProxies()); } - SchedulePhase.run(graph, SchedulingStrategy.EARLIEST, cfg); + try (DebugContext.Scope scheduleScope = graph.getDebug().scope(SchedulePhase.class)) { + SchedulePhase.run(graph, SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER, cfg); + } catch (Throwable t) { + throw graph.getDebug().handle(t); + } ScheduleResult r = graph.getLastSchedule(); blockToNodes = r.getBlockToNodesMap(); nodeToBlock = r.getNodeToBlockMap(); @@ -662,7 +666,7 @@ */ InputFilter v = new InputFilter(original); thisGuard.getCondition().applyInputs(v); - if (v.ok && foldGuard(thisGuard, pendingGuard, newStamp, rewireGuardFunction)) { + if (v.ok && foldGuard(thisGuard, pendingGuard, result.toBoolean(), newStamp, rewireGuardFunction)) { return true; } } @@ -670,19 +674,34 @@ return false; } - protected boolean foldGuard(DeoptimizingGuard thisGuard, DeoptimizingGuard otherGuard, Stamp guardedValueStamp, GuardRewirer rewireGuardFunction) { + protected boolean foldGuard(DeoptimizingGuard thisGuard, DeoptimizingGuard otherGuard, boolean outcome, Stamp guardedValueStamp, GuardRewirer rewireGuardFunction) { if (otherGuard.getAction() == thisGuard.getAction() && otherGuard.getSpeculation() == thisGuard.getSpeculation()) { LogicNode condition = (LogicNode) thisGuard.getCondition().copyWithInputs(); + /* + * We have ...; guard(C1); guard(C2);... + * + * Where the first guard is `otherGuard` and the second one `thisGuard`. + * + * Depending on `outcome`, we have C2 => C1 or C2 => !C1. + * + * - If C2 => C1, `mustDeopt` below is false and we transform to ...; guard(C2); ... + * + * - If C2 => !C1, `mustDeopt` is true and we transform to ..; guard(C1); deopt; + */ GuardRewirer rewirer = (guard, result, innerGuardedValueStamp, newInput) -> { - if (rewireGuardFunction.rewire(guard, result, innerGuardedValueStamp, newInput)) { - otherGuard.setCondition(condition, thisGuard.isNegated()); + // `result` is `outcome`, `guard` is `otherGuard` + boolean mustDeopt = result == otherGuard.isNegated(); + if (rewireGuardFunction.rewire(guard, mustDeopt == thisGuard.isNegated(), innerGuardedValueStamp, newInput)) { + if (!mustDeopt) { + otherGuard.setCondition(condition, thisGuard.isNegated()); + } return true; } condition.safeDelete(); return false; }; // Move the later test up - return rewireGuards(otherGuard, !thisGuard.isNegated(), null, guardedValueStamp, rewirer); + return rewireGuards(otherGuard, outcome, null, guardedValueStamp, rewirer); } return false; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,8 +26,8 @@ import java.util.List; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.InputType; @@ -46,6 +46,8 @@ import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.ProxyNode; +import org.graalvm.compiler.nodes.StartNode; +import org.graalvm.compiler.nodes.StaticDeoptimizingNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; @@ -57,8 +59,6 @@ import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.DeoptimizationAction; -import jdk.vm.ci.meta.DeoptimizationReason; -import jdk.vm.ci.meta.JavaConstant; /** * This phase will find branches which always end with a {@link DeoptimizeNode} and replace their @@ -77,18 +77,16 @@ @SuppressWarnings("try") protected void run(final StructuredGraph graph, PhaseContext context) { assert graph.hasValueProxies() : "ConvertDeoptimizeToGuardPhase always creates proxies"; + assert !graph.getGuardsStage().areFrameStatesAtDeopts() : graph.getGuardsStage(); for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.TYPE)) { assert d.isAlive(); - // Can only aggressively move deoptimization point if their action implies that - // the deoptimization will not be triggered again. Example for such action is - // reprofiling or recompiling with less aggressive options. - if (d.action() != DeoptimizationAction.None) { - try (DebugCloseable closable = d.withNodeSourcePosition()) { - visitDeoptBegin(AbstractBeginNode.prevBegin(d), d.action(), d.reason(), d.getSpeculation(), graph, context != null ? context.getLowerer() : null); - } + if (d.getAction() == DeoptimizationAction.None) { + continue; } - + try (DebugCloseable closable = d.withNodeSourcePosition()) { + propagateFixed(d, d, context != null ? context.getLowerer() : null); + } } if (context != null) { @@ -154,71 +152,73 @@ ys = yPhi.valueAt(mergePredecessor).asConstant(); } if (xs != null && ys != null && compare.condition().foldCondition(xs, ys, context.getConstantReflection(), compare.unorderedIsTrue()) == fixedGuard.isNegated()) { - visitDeoptBegin(AbstractBeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), fixedGuard.getSpeculation(), fixedGuard.graph(), context.getLowerer()); + propagateFixed(mergePredecessor, fixedGuard, context.getLowerer()); } } } - private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, JavaConstant speculation, StructuredGraph graph, - LoweringProvider loweringProvider) { - if (deoptBegin.predecessor() instanceof AbstractBeginNode) { - /* - * Walk up chains of LoopExitNodes to the "real" BeginNode that leads to deoptimization. - */ - visitDeoptBegin((AbstractBeginNode) deoptBegin.predecessor(), deoptAction, deoptReason, speculation, graph, loweringProvider); - return; - } + private void propagateFixed(FixedNode from, StaticDeoptimizingNode deopt, LoweringProvider loweringProvider) { + Node current = from; + while (current != null) { + if (GraalOptions.GuardPriorities.getValue(from.getOptions()) && current instanceof FixedGuardNode) { + FixedGuardNode otherGuard = (FixedGuardNode) current; + if (otherGuard.computePriority().isHigherPriorityThan(deopt.computePriority())) { + moveAsDeoptAfter(otherGuard, deopt); + return; + } + } else if (current instanceof AbstractBeginNode) { + if (current instanceof AbstractMergeNode) { + AbstractMergeNode mergeNode = (AbstractMergeNode) current; + FixedNode next = mergeNode.next(); + while (mergeNode.isAlive()) { + AbstractEndNode end = mergeNode.forwardEnds().first(); + propagateFixed(end, deopt, loweringProvider); + } + assert next.isAlive(); + propagateFixed(next, deopt, loweringProvider); + return; + } else if (current.predecessor() instanceof IfNode) { + IfNode ifNode = (IfNode) current.predecessor(); + StructuredGraph graph = ifNode.graph(); + LogicNode conditionNode = ifNode.condition(); + boolean negateGuardCondition = current == ifNode.trueSuccessor(); + FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.getReason(), deopt.getAction(), deopt.getSpeculation(), negateGuardCondition)); + FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor(); + AbstractBeginNode survivingSuccessor; + if (negateGuardCondition) { + survivingSuccessor = ifNode.falseSuccessor(); + } else { + survivingSuccessor = ifNode.trueSuccessor(); + } + graph.removeSplitPropagate(ifNode, survivingSuccessor); - DebugContext debug = deoptBegin.getDebug(); - if (deoptBegin instanceof AbstractMergeNode) { - AbstractMergeNode mergeNode = (AbstractMergeNode) deoptBegin; - debug.log("Visiting %s", mergeNode); - FixedNode next = mergeNode.next(); - while (mergeNode.isAlive()) { - AbstractEndNode end = mergeNode.forwardEnds().first(); - AbstractBeginNode newBeginNode = AbstractBeginNode.prevBegin(end); - visitDeoptBegin(newBeginNode, deoptAction, deoptReason, speculation, graph, loweringProvider); + Node newGuard = guard; + if (survivingSuccessor instanceof LoopExitNode) { + newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor, graph); + } + survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard); + + graph.getDebug().log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", negateGuardCondition, ifNode, survivingSuccessor); + FixedNode next = pred.next(); + pred.setNext(guard); + guard.setNext(next); + SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false, graph.getAssumptions(), graph.getOptions(), loweringProvider); + survivingSuccessor.simplify(simplifierTool); + return; + } else if (current.predecessor() == null || current.predecessor() instanceof ControlSplitNode) { + assert current.predecessor() != null || (current instanceof StartNode && current == ((AbstractBeginNode) current).graph().start()); + moveAsDeoptAfter((AbstractBeginNode) current, deopt); + return; + } } - assert next.isAlive(); - AbstractBeginNode newBeginNode = AbstractBeginNode.prevBegin(next); - visitDeoptBegin(newBeginNode, deoptAction, deoptReason, speculation, graph, loweringProvider); - return; - } else if (deoptBegin.predecessor() instanceof IfNode) { - IfNode ifNode = (IfNode) deoptBegin.predecessor(); - LogicNode conditionNode = ifNode.condition(); - FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deoptReason, deoptAction, speculation, deoptBegin == ifNode.trueSuccessor())); - FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor(); - AbstractBeginNode survivingSuccessor; - if (deoptBegin == ifNode.trueSuccessor()) { - survivingSuccessor = ifNode.falseSuccessor(); - } else { - survivingSuccessor = ifNode.trueSuccessor(); - } - graph.removeSplitPropagate(ifNode, survivingSuccessor); + current = current.predecessor(); + } + } - Node newGuard = guard; - if (survivingSuccessor instanceof LoopExitNode) { - newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor, graph); - } - survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard); - - debug.log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, survivingSuccessor); - FixedNode next = pred.next(); - pred.setNext(guard); - guard.setNext(next); - SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false, graph.getAssumptions(), graph.getOptions(), loweringProvider); - survivingSuccessor.simplify(simplifierTool); - return; - } - - // We could not convert the control split - at least cut off control flow after the split. - FixedWithNextNode deoptPred = deoptBegin; - FixedNode next = deoptPred.next(); - - if (!(next instanceof DeoptimizeNode)) { - DeoptimizeNode newDeoptNode = graph.add(new DeoptimizeNode(deoptAction, deoptReason, speculation)); - deoptPred.setNext(newDeoptNode); - assert deoptPred == newDeoptNode.predecessor(); + private static void moveAsDeoptAfter(FixedWithNextNode node, StaticDeoptimizingNode deopt) { + FixedNode next = node.next(); + if (next != deopt.asNode()) { + node.setNext(node.graph().add(new DeoptimizeNode(deopt.getAction(), deopt.getReason(), deopt.getSpeculation()))); GraphUtil.killCFG(next); } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.phases.common; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.MapCursor; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.type.FloatStamp; @@ -70,8 +72,6 @@ import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.LowTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.MapCursor; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.MetaAccessProvider; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -30,6 +30,10 @@ import java.util.Iterator; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.UnmodifiableMapCursor; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.graph.Graph.NodeEventScope; @@ -67,10 +71,6 @@ import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.LoopInfo; import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.UnmodifiableMapCursor; import org.graalvm.word.LocationIdentity; public class FloatingReadPhase extends Phase { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,6 +24,7 @@ import java.util.List; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.AbstractBeginNode; @@ -40,7 +41,6 @@ import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; -import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BytecodeFrame; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -120,7 +120,7 @@ @Override protected void run(StructuredGraph graph, MidTierContext context) { if (graph.getGuardsStage().allowsFloatingGuards()) { - SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST); + SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); schedulePhase.apply(graph); ScheduleResult schedule = graph.getLastSchedule(); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,6 +22,9 @@ */ package org.graalvm.compiler.phases.common; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.MapCursor; import org.graalvm.compiler.graph.NodeStack; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractDeoptimizeNode; @@ -32,9 +35,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.tiers.PhaseContext; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.MapCursor; /** * This phase will make sure that the branch leading towards this deopt has 0.0 probability. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -50,6 +50,9 @@ import org.graalvm.compiler.nodes.memory.FixedAccessNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.tiers.LowTierContext; @@ -64,16 +67,24 @@ private static final CounterKey counterTrappingNullCheckUnreached = DebugContext.counter("TrappingNullCheckUnreached"); private static final CounterKey counterTrappingNullCheckDynamicDeoptimize = DebugContext.counter("TrappingNullCheckDynamicDeoptimize"); + public static class Options { + + // @formatter:off + @Option(help = "Use traps for null checks instead of explicit null-checks", type = OptionType.Expert) + public static final OptionKey UseTrappingNullChecks = new OptionKey<>(true); + // @formatter:on + } + @Override protected void run(StructuredGraph graph, LowTierContext context) { - if (context.getTarget().implicitNullCheckLimit <= 0) { + if (!Options.UseTrappingNullChecks.getValue(graph.getOptions()) || context.getTarget().implicitNullCheckLimit <= 0) { return; } assert graph.getGuardsStage().areFrameStatesAtDeopts(); long implicitNullCheckLimit = context.getTarget().implicitNullCheckLimit; for (DeoptimizeNode deopt : graph.getNodes(DeoptimizeNode.TYPE)) { - tryUseTrappingNullCheck(deopt, deopt.predecessor(), deopt.reason(), deopt.getSpeculation(), implicitNullCheckLimit); + tryUseTrappingNullCheck(deopt, deopt.predecessor(), deopt.getReason(), deopt.getSpeculation(), implicitNullCheckLimit); } for (DynamicDeoptimizeNode deopt : graph.getNodes(DynamicDeoptimizeNode.TYPE)) { tryUseTrappingNullCheck(context.getMetaAccess(), deopt, implicitNullCheckLimit); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java Fri Feb 02 17:28:17 2018 -0800 @@ -33,6 +33,11 @@ import java.util.Objects; import java.util.function.Consumer; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.UnmodifiableEconomicMap; +import org.graalvm.collections.UnmodifiableMapCursor; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.type.Stamp; @@ -92,11 +97,6 @@ import org.graalvm.compiler.phases.common.inlining.info.InlineInfo; import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener; import org.graalvm.compiler.phases.util.ValueMergeUtil; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; -import org.graalvm.util.UnmodifiableEconomicMap; -import org.graalvm.util.UnmodifiableMapCursor; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.Assumptions; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.phases.common.inlining.info; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; @@ -31,7 +32,6 @@ import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable; import org.graalvm.compiler.phases.common.inlining.info.elem.InlineableGraph; import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.meta.ResolvedJavaMethod; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,12 +22,12 @@ */ package org.graalvm.compiler.phases.common.inlining.info; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.meta.Assumptions.AssumptionResult; import jdk.vm.ci.meta.ResolvedJavaMethod; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,11 +22,11 @@ */ package org.graalvm.compiler.phases.common.inlining.info; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable; import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.meta.ResolvedJavaMethod; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.phases.common.inlining.info; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; @@ -30,7 +31,6 @@ import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.meta.ResolvedJavaMethod; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,6 +25,8 @@ import java.util.ArrayList; import java.util.List; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.AbstractBeginNode; @@ -54,8 +56,6 @@ import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable; import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.DeoptimizationAction; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,7 +22,8 @@ */ package org.graalvm.compiler.phases.common.inlining.info; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.collections.EconomicSet; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.ConstantNode; @@ -37,7 +38,6 @@ import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable; import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; @@ -114,7 +114,7 @@ LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver)); ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(NodeView.DEFAULT), providers.getConstantReflection().asObjectHub(type), providers.getMetaAccess(), graph); - LogicNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub, providers.getConstantReflection(), NodeView.DEFAULT); + LogicNode typeCheck = CompareNode.createCompareNode(graph, CanonicalCondition.EQ, receiverHub, typeHub, providers.getConstantReflection(), NodeView.DEFAULT); FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile)); assert invoke.predecessor() != null; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,6 +26,8 @@ import java.util.LinkedList; import java.util.function.ToDoubleFunction; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.ParameterNode; @@ -33,8 +35,6 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.phases.common.inlining.policy.AbstractInliningPolicy; import org.graalvm.compiler.phases.graph.FixedNodeProbabilityCache; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicSet; import jdk.vm.ci.meta.ResolvedJavaMethod; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,6 +25,8 @@ import java.util.ArrayList; import java.util.function.ToDoubleFunction; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeWorkList; @@ -43,8 +45,6 @@ import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.phases.common.inlining.InliningUtil; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; public class ComputeInliningRelevance { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java Fri Feb 02 17:28:17 2018 -0800 @@ -34,6 +34,8 @@ import java.util.LinkedList; import java.util.List; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; @@ -64,8 +66,6 @@ import org.graalvm.compiler.phases.common.inlining.policy.InliningPolicy; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.meta.Assumptions.AssumptionResult; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,12 +26,12 @@ import java.util.HashSet; import java.util.Set; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.graph.Graph.NodeEvent; import org.graalvm.compiler.graph.Graph.NodeEventListener; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Node.IndirectCanonicalization; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicSet; /** * A simple {@link NodeEventListener} implementation that accumulates event nodes in a diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,8 +22,12 @@ */ package org.graalvm.compiler.phases.graph; +import static org.graalvm.compiler.nodes.cfg.ControlFlowGraph.multiplyProbabilities; + import java.util.function.ToDoubleFunction; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; @@ -36,10 +40,6 @@ import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StartNode; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; - -import static org.graalvm.compiler.nodes.cfg.ControlFlowGraph.multiplyProbabilities; /** * Compute probabilities for fixed nodes on the fly and cache them at {@link AbstractBeginNode}s. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java Fri Feb 02 17:28:17 2018 -0800 @@ -27,6 +27,8 @@ import java.util.Deque; import java.util.Set; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeBitMap; import org.graalvm.compiler.nodes.AbstractBeginNode; @@ -41,8 +43,6 @@ import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; /** * A PostOrderNodeIterator iterates the fixed nodes of the graph in post order starting from a diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,6 +28,8 @@ import java.util.List; import java.util.function.Predicate; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.RetryableBailoutException; import org.graalvm.compiler.core.common.cfg.Loop; @@ -38,8 +40,6 @@ import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.cfg.Block; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; public final class ReentrantBlockIterator { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,6 +28,9 @@ import java.util.Iterator; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.MapCursor; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractEndNode; @@ -38,9 +41,6 @@ import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.LoopExitNode; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.MapCursor; public final class ReentrantNodeIterator { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java Fri Feb 02 17:28:17 2018 -0800 @@ -27,6 +27,8 @@ import java.util.Deque; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeBitMap; import org.graalvm.compiler.nodes.AbstractBeginNode; @@ -42,8 +44,6 @@ import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; /** * A SinglePassNodeIterator iterates the fixed nodes of the graph in post order starting from its diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,6 +24,8 @@ import java.util.List; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.debug.DebugContext; @@ -40,8 +42,6 @@ import org.graalvm.compiler.nodes.memory.MemoryPhiNode; import org.graalvm.compiler.phases.graph.ReentrantBlockIterator; import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; import org.graalvm.word.LocationIdentity; public final class MemoryScheduleVerification extends BlockIteratorClosure> { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,14 +22,23 @@ */ package org.graalvm.compiler.phases.schedule; +import static org.graalvm.collections.Equivalence.IDENTITY; +import static org.graalvm.compiler.core.common.GraalOptions.GuardPriorities; import static org.graalvm.compiler.core.common.GraalOptions.OptScheduleOutOfLoops; import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; +import java.util.EnumMap; import java.util.Formatter; +import java.util.Iterator; import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.function.Function; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.cfg.BlockMap; @@ -48,7 +57,6 @@ import org.graalvm.compiler.nodes.ControlSplitNode; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.FixedNode; -import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.GuardNode; import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.KillingBeginNode; @@ -57,6 +65,8 @@ import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.StartNode; +import org.graalvm.compiler.nodes.StaticDeoptimizingNode; +import org.graalvm.compiler.nodes.StaticDeoptimizingNode.GuardPriority; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; @@ -78,10 +88,19 @@ public final class SchedulePhase extends Phase { public enum SchedulingStrategy { + EARLIEST_WITH_GUARD_ORDER, EARLIEST, LATEST, LATEST_OUT_OF_LOOPS, - FINAL_SCHEDULE + FINAL_SCHEDULE; + + public boolean isEarliest() { + return this == EARLIEST || this == EARLIEST_WITH_GUARD_ORDER; + } + + public boolean isLatest() { + return !isEarliest(); + } } private final SchedulingStrategy selectedStrategy; @@ -164,13 +183,13 @@ this.nodeToBlockMap = currentNodeMap; this.blockToNodesMap = earliestBlockToNodesMap; - scheduleEarliestIterative(earliestBlockToNodesMap, currentNodeMap, visited, graph, immutableGraph); + scheduleEarliestIterative(earliestBlockToNodesMap, currentNodeMap, visited, graph, immutableGraph, selectedStrategy == SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); - if (selectedStrategy != SchedulingStrategy.EARLIEST) { + if (!selectedStrategy.isEarliest()) { // For non-earliest schedules, we need to do a second pass. BlockMap> latestBlockToNodesMap = new BlockMap<>(cfg); for (Block b : cfg.getBlocks()) { - latestBlockToNodesMap.put(b, new ArrayList()); + latestBlockToNodesMap.put(b, new ArrayList<>()); } BlockMap> watchListMap = calcLatestBlocks(selectedStrategy, currentNodeMap, earliestBlockToNodesMap, visited, latestBlockToNodesMap, immutableGraph); @@ -181,8 +200,8 @@ this.blockToNodesMap = latestBlockToNodesMap; - cfg.setNodeToBlock(currentNodeMap); } + cfg.setNodeToBlock(currentNodeMap); graph.setLastSchedule(new ScheduleResult(this.cfg, this.nodeToBlockMap, this.blockToNodesMap)); } @@ -524,7 +543,6 @@ assert latestBlock != null : currentNode; if (strategy == SchedulingStrategy.FINAL_SCHEDULE || strategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS) { - assert latestBlock != null; Block currentBlock = latestBlock; while (currentBlock.getLoopDepth() > earliestBlock.getLoopDepth() && currentBlock != earliestBlock.getDominator()) { Block previousCurrentBlock = currentBlock; @@ -645,7 +663,7 @@ */ public void add(Node node) { assert !(node instanceof FixedNode) : node; - NodeEntry newTail = new NodeEntry(node, null); + NodeEntry newTail = new NodeEntry(node); if (tail == null) { tail = head = newTail; } else { @@ -659,9 +677,18 @@ * Number of nodes in this micro block. */ public int getNodeCount() { + assert getActualNodeCount() == nodeCount : getActualNodeCount() + " != " + nodeCount; return nodeCount; } + private int getActualNodeCount() { + int count = 0; + for (NodeEntry e = head; e != null; e = e.next) { + count++; + } + return count; + } + /** * The id of the micro block, with a block always associated with a lower id than its * successors. @@ -685,6 +712,7 @@ */ public void prependChildrenTo(MicroBlock newBlock) { if (tail != null) { + assert head != null; tail.next = newBlock.head; newBlock.head = head; head = tail = null; @@ -697,6 +725,11 @@ public String toString() { return String.format("MicroBlock[id=%d]", id); } + + @Override + public int hashCode() { + return id; + } } /** @@ -706,9 +739,9 @@ private final Node node; private NodeEntry next; - NodeEntry(Node node, NodeEntry next) { + NodeEntry(Node node) { this.node = node; - this.next = next; + this.next = null; } public NodeEntry getNext() { @@ -720,7 +753,8 @@ } } - private void scheduleEarliestIterative(BlockMap> blockToNodes, NodeMap nodeToBlock, NodeBitMap visited, StructuredGraph graph, boolean immutableGraph) { + private void scheduleEarliestIterative(BlockMap> blockToNodes, NodeMap nodeToBlock, NodeBitMap visited, StructuredGraph graph, boolean immutableGraph, + boolean withGuardOrder) { NodeMap entries = graph.createNodeMap(); NodeStack stack = new NodeStack(); @@ -729,62 +763,44 @@ MicroBlock startBlock = null; int nextId = 1; for (Block b : cfg.reversePostOrder()) { - FixedNode current = b.getBeginNode(); - while (true) { + for (FixedNode current : b.getBeginNode().getBlockNodes()) { MicroBlock microBlock = new MicroBlock(nextId++); - entries.put(current, microBlock); - visited.checkAndMarkInc(current); - + entries.set(current, microBlock); + boolean isNew = visited.checkAndMarkInc(current); + assert isNew; if (startBlock == null) { startBlock = microBlock; } - - // Process inputs of this fixed node. - for (Node input : current.inputs()) { - if (entries.get(input) == null) { - processStack(input, startBlock, entries, visited, stack); - } - } - - if (current == b.getEndNode()) { - // Break loop when reaching end node. - break; - } - - current = ((FixedWithNextNode) current).next(); } } - // Now process guards. - for (GuardNode guardNode : graph.getNodes(GuardNode.TYPE)) { - if (entries.get(guardNode) == null) { - processStack(guardNode, startBlock, entries, visited, stack); + if (graph.getGuardsStage().allowsFloatingGuards() && graph.getNodes(GuardNode.TYPE).isNotEmpty()) { + // Now process guards. + if (GuardPriorities.getValue(graph.getOptions()) && withGuardOrder) { + EnumMap> guardsByPriority = new EnumMap<>(GuardPriority.class); + for (GuardNode guard : graph.getNodes(GuardNode.TYPE)) { + guardsByPriority.computeIfAbsent(guard.computePriority(), p -> new ArrayList<>()).add(guard); + } + // `EnumMap.values` returns values in "natural" key order + for (List guards : guardsByPriority.values()) { + processNodes(visited, entries, stack, startBlock, guards); + } + GuardOrder.resortGuards(graph, entries, stack); + } else { + processNodes(visited, entries, stack, startBlock, graph.getNodes(GuardNode.TYPE)); } + } else { + assert graph.getNodes(GuardNode.TYPE).isEmpty(); } // Now process inputs of fixed nodes. for (Block b : cfg.reversePostOrder()) { - FixedNode current = b.getBeginNode(); - while (true) { - - // Process inputs of this fixed node. - for (Node input : current.inputs()) { - if (entries.get(input) == null) { - processStack(input, startBlock, entries, visited, stack); - } - } - - if (current == b.getEndNode()) { - // Break loop when reaching end node. - break; - } - - current = ((FixedWithNextNode) current).next(); + for (FixedNode current : b.getBeginNode().getBlockNodes()) { + processNodes(visited, entries, stack, startBlock, current.inputs()); } } if (visited.getCounter() < graph.getNodeCount()) { - // Visit back input edges of loop phis. boolean changed; boolean unmarkedPhi; @@ -829,36 +845,29 @@ if (fixedNode instanceof ControlSplitNode) { ControlSplitNode controlSplitNode = (ControlSplitNode) fixedNode; MicroBlock endBlock = entries.get(fixedNode); - MicroBlock primarySuccessor = entries.get(controlSplitNode.getPrimarySuccessor()); - endBlock.prependChildrenTo(primarySuccessor); + AbstractBeginNode primarySuccessor = controlSplitNode.getPrimarySuccessor(); + if (primarySuccessor != null) { + endBlock.prependChildrenTo(entries.get(primarySuccessor)); + } else { + assert endBlock.tail == null; + } } } - // Initialize with begin nodes + // Create lists for each block for (Block b : cfg.reversePostOrder()) { - - FixedNode current = b.getBeginNode(); + // Count nodes in block int totalCount = 0; - while (true) { - + for (FixedNode current : b.getBeginNode().getBlockNodes()) { MicroBlock microBlock = entries.get(current); totalCount += microBlock.getNodeCount() + 1; - - if (current == b.getEndNode()) { - // Break loop when reaching end node. - break; - } - - current = ((FixedWithNextNode) current).next(); } // Initialize with begin node, it is always the first node. ArrayList nodes = new ArrayList<>(totalCount); blockToNodes.put(b, nodes); - current = b.getBeginNode(); - while (true) { - + for (FixedNode current : b.getBeginNode().getBlockNodes()) { MicroBlock microBlock = entries.get(current); nodeToBlock.set(current, b); nodes.add(current); @@ -869,19 +878,20 @@ nodes.add(nextNode); next = next.getNext(); } - - if (current == b.getEndNode()) { - // Break loop when reaching end node. - break; - } - - current = ((FixedWithNextNode) current).next(); } } assert (!Assertions.detailedAssertionsEnabled(cfg.graph.getOptions())) || MemoryScheduleVerification.check(cfg.getStartBlock(), blockToNodes); } + private static void processNodes(NodeBitMap visited, NodeMap entries, NodeStack stack, MicroBlock startBlock, Iterable nodes) { + for (Node node : nodes) { + if (entries.get(node) == null) { + processStack(node, startBlock, entries, visited, stack); + } + } + } + private static void processStackPhi(NodeStack stack, PhiNode phiNode, NodeMap nodeToBlock, NodeBitMap visited) { stack.pop(); if (visited.checkAndMarkInc(phiNode)) { @@ -944,6 +954,166 @@ } } + private static class GuardOrder { + /** + * After an earliest schedule, this will re-sort guards to honor their + * {@linkplain StaticDeoptimizingNode#computePriority() priority}. + * + * Note that this only changes the order of nodes within {@linkplain MicroBlock + * micro-blocks}, nodes will not be moved from one micro-block to another. + */ + private static void resortGuards(StructuredGraph graph, NodeMap entries, NodeStack stack) { + assert stack.isEmpty(); + EconomicSet blocksWithGuards = EconomicSet.create(IDENTITY); + for (GuardNode guard : graph.getNodes(GuardNode.TYPE)) { + MicroBlock block = entries.get(guard); + assert block != null : guard + "should already be scheduled to a micro-block"; + blocksWithGuards.add(block); + } + assert !blocksWithGuards.isEmpty(); + NodeMap priorities = graph.createNodeMap(); + NodeBitMap blockNodes = graph.createNodeBitMap(); + for (MicroBlock block : blocksWithGuards) { + MicroBlock newBlock = resortGuards(block, stack, blockNodes, priorities); + assert stack.isEmpty(); + assert blockNodes.isEmpty(); + if (newBlock != null) { + assert block.getNodeCount() == newBlock.getNodeCount(); + block.head = newBlock.head; + block.tail = newBlock.tail; + } + } + } + + /** + * This resorts guards within one micro-block. + * + * {@code stack}, {@code blockNodes} and {@code priorities} are just temporary + * data-structures which are allocated once by the callers of this method. They should + * be in their "initial"/"empty" state when calling this method and when it returns. + */ + private static MicroBlock resortGuards(MicroBlock block, NodeStack stack, NodeBitMap blockNodes, NodeMap priorities) { + if (!propagatePriority(block, stack, priorities, blockNodes)) { + return null; + } + + Function transitiveGuardPriorityGetter = priorities::get; + Comparator globalGuardPriorityComparator = Comparator.comparing(transitiveGuardPriorityGetter).thenComparing(GuardNode::computePriority).thenComparingInt(Node::hashCode); + + SortedSet availableGuards = new TreeSet<>(globalGuardPriorityComparator); + MicroBlock newBlock = new MicroBlock(block.getId()); + + NodeBitMap sorted = blockNodes; + sorted.invert(); + + for (NodeEntry e = block.head; e != null; e = e.next) { + checkIfAvailable(e.node, stack, sorted, newBlock, availableGuards, false); + } + do { + while (!stack.isEmpty()) { + checkIfAvailable(stack.pop(), stack, sorted, newBlock, availableGuards, true); + } + Iterator iterator = availableGuards.iterator(); + if (iterator.hasNext()) { + addNodeToResort(iterator.next(), stack, sorted, newBlock, true); + iterator.remove(); + } + } while (!stack.isEmpty() || !availableGuards.isEmpty()); + + blockNodes.clearAll(); + return newBlock; + } + + /** + * This checks if {@code n} can be scheduled, if it is the case, it schedules it now by + * calling {@link #addNodeToResort(Node, NodeStack, NodeBitMap, MicroBlock, boolean)}. + */ + private static void checkIfAvailable(Node n, NodeStack stack, NodeBitMap sorted, Instance.MicroBlock newBlock, SortedSet availableGuardNodes, boolean pushUsages) { + if (sorted.isMarked(n)) { + return; + } + for (Node in : n.inputs()) { + if (!sorted.isMarked(in)) { + return; + } + } + if (n instanceof GuardNode) { + availableGuardNodes.add((GuardNode) n); + } else { + addNodeToResort(n, stack, sorted, newBlock, pushUsages); + } + } + + /** + * Add a node to the re-sorted micro-block. This also pushes nodes that need to be + * (re-)examined on the stack. + */ + private static void addNodeToResort(Node n, NodeStack stack, NodeBitMap sorted, MicroBlock newBlock, boolean pushUsages) { + sorted.mark(n); + newBlock.add(n); + if (pushUsages) { + for (Node u : n.usages()) { + if (!sorted.isMarked(u)) { + stack.push(u); + } + } + } + } + + /** + * This fills in a map of transitive priorities ({@code priorities}). It also marks the + * nodes from this micro-block in {@code blockNodes}. + * + * The transitive priority of a guard is the highest of its priority and the priority of + * the guards that depend on it (transitively). + * + * This method returns {@code false} if no re-ordering is necessary in this micro-block. + */ + private static boolean propagatePriority(MicroBlock block, NodeStack stack, NodeMap priorities, NodeBitMap blockNodes) { + assert stack.isEmpty(); + assert blockNodes.isEmpty(); + GuardPriority lowestPriority = GuardPriority.highest(); + for (NodeEntry e = block.head; e != null; e = e.next) { + blockNodes.mark(e.node); + if (e.node instanceof GuardNode) { + GuardNode guard = (GuardNode) e.node; + GuardPriority priority = guard.computePriority(); + if (lowestPriority != null) { + if (priority.isLowerPriorityThan(lowestPriority)) { + lowestPriority = priority; + } else if (priority.isHigherPriorityThan(lowestPriority)) { + lowestPriority = null; + } + } + stack.push(guard); + priorities.set(guard, priority); + } + } + if (lowestPriority != null) { + stack.clear(); + blockNodes.clearAll(); + return false; + } + + do { + Node current = stack.pop(); + assert blockNodes.isMarked(current); + GuardPriority priority = priorities.get(current); + for (Node input : current.inputs()) { + if (!blockNodes.isMarked(input)) { + continue; + } + GuardPriority inputPriority = priorities.get(input); + if (inputPriority == null || inputPriority.isLowerPriorityThan(priority)) { + priorities.set(input, priority); + stack.push(input); + } + } + } while (!stack.isEmpty()); + return true; + } + } + /** * Processes the inputs of given block. Pushes unprocessed inputs onto the stack. Returns * null if there were still unprocessed inputs, otherwise returns the earliest block given @@ -960,7 +1130,7 @@ if (inputBlock == null) { earliestBlock = null; stack.push(input); - } else if (earliestBlock != null && inputBlock.getId() >= earliestBlock.getId()) { + } else if (earliestBlock != null && inputBlock.getId() > earliestBlock.getId()) { earliestBlock = inputBlock; } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,6 +25,8 @@ import java.util.ArrayList; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.GraalGraphError; @@ -55,8 +57,6 @@ import org.graalvm.compiler.phases.graph.StatelessPostOrderNodeIterator; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; public final class GraphOrder { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.phases.util; +import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider; import org.graalvm.compiler.core.common.spi.CodeGenProviders; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; @@ -90,6 +91,11 @@ } @Override + public ArrayOffsetProvider getArrayOffsetProvider() { + return lowerer; + } + + @Override public ConstantReflectionProvider getConstantReflection() { return constantReflection; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java Fri Feb 02 17:28:17 2018 -0800 @@ -143,9 +143,9 @@ "org.graalvm.compiler.phases.BasePhase.dumpAfter", "org.graalvm.compiler.phases.BasePhase.dumpBefore", "org.graalvm.compiler.core.GraalCompiler.emitFrontEnd", - "org.graalvm.compiler.truffle.PartialEvaluator.fastPartialEvaluation", - "org.graalvm.compiler.truffle.PartialEvaluator$PerformanceInformationHandler.reportPerformanceWarnings", - "org.graalvm.compiler.truffle.TruffleCompiler.compileMethodHelper", + "org.graalvm.compiler.truffle.compiler.PartialEvaluator.fastPartialEvaluation", + "org.graalvm.compiler.truffle.compiler.PartialEvaluator$PerformanceInformationHandler.reportPerformanceWarnings", + "org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl.compilePEGraph", "org.graalvm.compiler.core.test.VerifyDebugUsageTest$ValidDumpUsagePhase.run", "org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidConcatDumpUsagePhase.run", "org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidDumpUsagePhase.run")); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,8 +22,10 @@ */ package org.graalvm.compiler.phases.verify; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; @@ -40,10 +42,9 @@ import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.phases.VerifyPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; -import org.graalvm.util.EconomicSet; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; public class VerifyGraphAddUsage extends VerifyPhase { private static final Method ADD_OR_UNIQUE; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java Fri Feb 02 17:28:17 2018 -0800 @@ -33,6 +33,7 @@ import java.util.Map; import java.util.TreeMap; +import org.graalvm.collections.UnmodifiableMapCursor; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeDisassembler; import org.graalvm.compiler.core.common.alloc.Trace; @@ -66,7 +67,6 @@ import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; -import org.graalvm.util.UnmodifiableMapCursor; import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.code.TargetDescription; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java Fri Feb 02 17:28:17 2018 -0800 @@ -23,12 +23,15 @@ package org.graalvm.compiler.replacements.amd64; import org.graalvm.compiler.api.replacements.ClassSubstitution; +import org.graalvm.compiler.api.replacements.Fold; +import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.MethodSubstitution; +import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.word.Word; import org.graalvm.word.Pointer; -import sun.misc.Unsafe; +import jdk.vm.ci.meta.JavaKind; // JaCoCo Exclude @@ -38,6 +41,19 @@ @ClassSubstitution(String.class) public class AMD64StringSubstitutions { + @Fold + static int charArrayBaseOffset(@InjectedParameter ArrayOffsetProvider arrayOffsetProvider) { + return arrayOffsetProvider.arrayBaseOffset(JavaKind.Char); + } + + @Fold + static int charArrayIndexScale(@InjectedParameter ArrayOffsetProvider arrayOffsetProvider) { + return arrayOffsetProvider.arrayScalingFactor(JavaKind.Char); + } + + /** Marker value for the {@link InjectedParameter} injected parameter. */ + static final ArrayOffsetProvider INJECTED = null; + // Only exists in JDK <= 8 @MethodSubstitution(isStatic = true, optional = true) public static int indexOf(char[] source, int sourceOffset, int sourceCount, @@ -62,8 +78,8 @@ } assert sourceCount - fromIndex > 0 && targetCount > 0; - Pointer sourcePointer = Word.objectToTrackedPointer(source).add(Unsafe.ARRAY_CHAR_BASE_OFFSET).add(totalOffset * Unsafe.ARRAY_CHAR_INDEX_SCALE); - Pointer targetPointer = Word.objectToTrackedPointer(target).add(Unsafe.ARRAY_CHAR_BASE_OFFSET).add(targetOffset * Unsafe.ARRAY_CHAR_INDEX_SCALE); + Pointer sourcePointer = Word.objectToTrackedPointer(source).add(charArrayBaseOffset(INJECTED)).add(totalOffset * charArrayIndexScale(INJECTED)); + Pointer targetPointer = Word.objectToTrackedPointer(target).add(charArrayBaseOffset(INJECTED)).add(targetOffset * charArrayIndexScale(INJECTED)); int result = AMD64StringIndexOfNode.optimizedStringIndexPointer(sourcePointer, sourceCount - fromIndex, targetPointer, targetCount); if (result >= 0) { return result + totalOffset; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -79,7 +79,7 @@ @Override protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { - InjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), null); + InjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), getProviders().getLowerer(), null); new PluginFactory_FoldTest().registerPlugins(invocationPlugins, injection); BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider(); Registration r = new Registration(invocationPlugins, TestMethod.class, replacementBytecodeProvider); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NestedExceptionHandlerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NestedExceptionHandlerTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.replacements.test; + +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.phases.HighTier; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Test; + +public class NestedExceptionHandlerTest extends GraalCompilerTest { + + @BytecodeParserNeverInline(invokeWithException = true) + public static void foo() { + } + + @BytecodeParserNeverInline(invokeWithException = true) + public static void bar() { + throw new NegativeArraySizeException(); + } + + public static int nestedExceptionHandler() { + int flag = 0; + try { + try { + try { + foo(); + } catch (NegativeArraySizeException e) { + flag = -1; + } + bar(); + } catch (NullPointerException e) { + flag = -2; + } + } catch (Throwable e) { + GraalDirectives.deoptimize(); + } + return flag; + } + + @Test + public void testNestedExceptionHandler() { + test(new OptionValues(getInitialOptions(), HighTier.Options.Inline, false), "nestedExceptionHandler"); + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,6 +24,7 @@ import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; +import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.java.GraphBuilderPhase; @@ -43,7 +44,6 @@ import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.meta.ResolvedJavaMethod; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,10 +24,13 @@ import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; +import org.graalvm.compiler.api.replacements.Fold; +import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider; import org.graalvm.compiler.debug.DebugHandlersFactory; -import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.OptionValues; @@ -38,7 +41,7 @@ import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; import jdk.vm.ci.code.TargetDescription; -import sun.misc.Unsafe; +import jdk.vm.ci.meta.JavaKind; public class ConstantStringIndexOfSnippets implements Snippets { public static class Templates extends AbstractTemplates { @@ -91,6 +94,14 @@ return cache; } + @Fold + static int charArrayBaseOffset(@InjectedParameter ArrayOffsetProvider arrayOffsetProvider) { + return arrayOffsetProvider.arrayBaseOffset(JavaKind.Char); + } + + /** Marker value for the {@link InjectedParameter} injected parameter. */ + static final ArrayOffsetProvider INJECTED = null; + @Snippet public static int indexOfConstant(char[] source, int sourceOffset, int sourceCount, @ConstantParameter char[] target, int targetOffset, int targetCount, @@ -109,7 +120,7 @@ int targetCountLess1 = targetCount - 1; int sourceEnd = sourceCount - targetCountLess1; - long base = Unsafe.ARRAY_CHAR_BASE_OFFSET; + long base = charArrayBaseOffset(INJECTED); int lastChar = UnsafeAccess.UNSAFE.getChar(target, base + targetCountLess1 * 2); outer_loop: for (long i = sourceOffset + fromIndex; i < sourceEnd;) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Fri Feb 02 17:28:17 2018 -0800 @@ -921,8 +921,7 @@ public abstract int arrayLengthOffset(); - public abstract int arrayBaseOffset(JavaKind elementKind); - + @Override public int arrayScalingFactor(JavaKind elementKind) { return target.arch.getPlatformKind(elementKind).getSizeInBytes(); } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java Fri Feb 02 17:28:17 2018 -0800 @@ -27,7 +27,7 @@ import java.util.List; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; -import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ConditionAnchorNode; @@ -184,7 +184,7 @@ } if (condition == null || (!(condition instanceof CompareNode)) || ((CompareNode) condition).getY() != testValue) { // Re-use previously generated condition if the trueValue for the test is the same - condition = createCompareNode(result.graph(), Condition.EQ, result, testValue, null, NodeView.DEFAULT); + condition = createCompareNode(result.graph(), CanonicalCondition.EQ, result, testValue, null, NodeView.DEFAULT); } return condition; } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java Fri Feb 02 17:28:17 2018 -0800 @@ -23,6 +23,7 @@ package org.graalvm.compiler.replacements; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -40,12 +41,15 @@ private final MetaAccessProvider metaAccess; private final SnippetReflectionProvider snippetReflection; private final ForeignCallsProvider foreignCalls; + private final ArrayOffsetProvider arrayOffsetProvider; private final WordTypes wordTypes; - public NodeIntrinsificationProvider(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, WordTypes wordTypes) { + public NodeIntrinsificationProvider(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, ArrayOffsetProvider arrayOffsetProvider, + WordTypes wordTypes) { this.metaAccess = metaAccess; this.snippetReflection = snippetReflection; this.foreignCalls = foreignCalls; + this.arrayOffsetProvider = arrayOffsetProvider; this.wordTypes = wordTypes; } @@ -73,6 +77,8 @@ return type.cast(foreignCalls); } else if (type.equals(SnippetReflectionProvider.class)) { return type.cast(snippetReflection); + } else if (type.equals(ArrayOffsetProvider.class)) { + return type.cast(arrayOffsetProvider); } else { throw new GraalError("Cannot handle injected argument of type %s.", type.getName()); } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java Fri Feb 02 17:28:17 2018 -0800 @@ -32,6 +32,8 @@ import java.util.List; import java.util.Map; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.PermanentBailoutException; @@ -102,8 +104,6 @@ import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.inlining.InliningUtil; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.BailoutException; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Fri Feb 02 17:28:17 2018 -0800 @@ -36,6 +36,8 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.api.replacements.Snippet; @@ -47,9 +49,9 @@ import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext.Description; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.Node; @@ -81,8 +83,6 @@ import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordOperationPlugin; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.ConstantReflectionProvider; @@ -274,10 +274,13 @@ if (plugin instanceof MethodSubstitutionPlugin) { MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin; ResolvedJavaMethod substitute = msPlugin.getSubstitute(metaAccess); - StructuredGraph graph = graphs.get(substitute); + StructuredGraph graph = UseSnippetGraphCache.getValue(options) ? graphs.get(substitute) : null; if (graph == null) { try (DebugContext debug = openDebugContext("Substitution_", method)) { graph = makeGraph(debug, msPlugin.getBytecodeProvider(), substitute, null, method); + if (!UseSnippetGraphCache.getValue(options)) { + return graph; + } graph.freeze(); graphs.putIfAbsent(substitute, graph); graph = graphs.get(substitute); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Fri Feb 02 17:28:17 2018 -0800 @@ -47,11 +47,27 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.Local; +import jdk.vm.ci.meta.LocalVariableTable; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; +import jdk.vm.ci.meta.ResolvedJavaMethod.Parameter; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.UnmodifiableEconomicMap; import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter; -import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -59,15 +75,15 @@ import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugHandlersFactory; -import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.debug.DebugContext.Description; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TimerKey; -import org.graalvm.compiler.graph.Graph.Mark; +import org.graalvm.compiler.debug.DebugContext.Description; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.Position; +import org.graalvm.compiler.graph.Graph.Mark; import org.graalvm.compiler.loop.LoopEx; import org.graalvm.compiler.loop.LoopsData; import org.graalvm.compiler.loop.phases.LoopTransformations; @@ -86,15 +102,15 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PhiNode; -import org.graalvm.compiler.nodes.PiNode.Placeholder; -import org.graalvm.compiler.nodes.PiNode.PlaceholderStamp; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValueNodeUtil; +import org.graalvm.compiler.nodes.PiNode.Placeholder; +import org.graalvm.compiler.nodes.PiNode.PlaceholderStamp; +import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; import org.graalvm.compiler.nodes.java.StoreIndexedNode; @@ -115,35 +131,19 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; -import org.graalvm.compiler.phases.common.FloatingReadPhase.MemoryMapImpl; import org.graalvm.compiler.phases.common.GuardLoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; +import org.graalvm.compiler.phases.common.FloatingReadPhase.MemoryMapImpl; import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; import org.graalvm.compiler.replacements.nodes.LoadSnippetVarargParameterNode; import org.graalvm.util.CollectionsUtil; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; -import org.graalvm.util.UnmodifiableEconomicMap; import org.graalvm.word.LocationIdentity; import org.graalvm.word.WordBase; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Local; -import jdk.vm.ci.meta.LocalVariableTable; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod.Parameter; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.Signature; - /** * A snippet template is a graph created by parsing a snippet method and then specialized by binding * constants to the snippet's {@link ConstantParameter} parameters. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Fri Feb 02 17:28:17 2018 -0800 @@ -37,10 +37,13 @@ import java.lang.reflect.Field; import java.util.Arrays; +import jdk.vm.ci.code.BytecodePosition; +import jdk.vm.ci.meta.SpeculationLog; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition; import org.graalvm.compiler.core.common.calc.UnsignedMath; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; @@ -456,23 +459,16 @@ @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) { - // the mirroring and negation operations get the condition into canonical form - boolean mirror = condition.canonicalMirror(); - boolean negate = condition.canonicalNegate(); + CanonicalizedCondition canonical = condition.canonicalize(); StructuredGraph graph = b.getGraph(); - ValueNode lhs = mirror ? y : x; - ValueNode rhs = mirror ? x : y; - - ValueNode trueValue = ConstantNode.forBoolean(!negate, graph); - ValueNode falseValue = ConstantNode.forBoolean(negate, graph); + ValueNode lhs = canonical.mustMirror() ? y : x; + ValueNode rhs = canonical.mustMirror() ? x : y; - Condition cond = mirror ? condition.mirror() : condition; - if (negate) { - cond = cond.negate(); - } + ValueNode trueValue = ConstantNode.forBoolean(!canonical.mustNegate(), graph); + ValueNode falseValue = ConstantNode.forBoolean(canonical.mustNegate(), graph); - LogicNode compare = CompareNode.createCompareNode(graph, b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, cond, lhs, rhs, NodeView.DEFAULT); + LogicNode compare = CompareNode.createCompareNode(graph, b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, canonical.getCanonicalCondition(), lhs, rhs, NodeView.DEFAULT); b.addPush(JavaKind.Boolean, new ConditionalNode(compare, trueValue, falseValue)); return true; } @@ -728,6 +724,24 @@ } } + private static final class DirectiveSpeculationReason implements SpeculationLog.SpeculationReason { + private final BytecodePosition pos; + + private DirectiveSpeculationReason(BytecodePosition pos) { + this.pos = pos; + } + + @Override + public int hashCode() { + return pos.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof DirectiveSpeculationReason && ((DirectiveSpeculationReason) obj).pos.equals(this.pos); + } + } + private static void registerGraalDirectivesPlugins(InvocationPlugins plugins) { Registration r = new Registration(plugins, GraalDirectives.class); r.register0("deoptimize", new InvocationPlugin() { @@ -746,6 +760,23 @@ } }); + r.register0("deoptimizeAndInvalidateWithSpeculation", new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + GraalError.guarantee(b.getGraph().getSpeculationLog() != null, "A speculation log is need to use `deoptimizeAndInvalidateWithSpeculation`"); + BytecodePosition pos = new BytecodePosition(null, b.getMethod(), b.bci()); + DirectiveSpeculationReason reason = new DirectiveSpeculationReason(pos); + JavaConstant speculation; + if (b.getGraph().getSpeculationLog().maySpeculate(reason)) { + speculation = b.getGraph().getSpeculationLog().speculate(reason); + } else { + speculation = JavaConstant.defaultForKind(JavaKind.Object); + } + b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter, speculation)); + return true; + } + }); + r.register0("inCompiledCode", new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java Fri Feb 02 17:28:17 2018 -0800 @@ -46,8 +46,8 @@ private final ResolvedJavaType type; private final List codeAttributes; - private static final int MAJOR_VERSION_JAVA_MIN = 51; - private static final int MAJOR_VERSION_JAVA_MAX = 55; + private static final int MAJOR_VERSION_JAVA_MIN = 51; // JDK7 + private static final int MAJOR_VERSION_JAVA_MAX = 55; // JDK11 private static final int MAGIC = 0xCAFEBABE; /** diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java Fri Feb 02 17:28:17 2018 -0800 @@ -29,12 +29,12 @@ import java.io.IOException; import java.io.InputStream; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.serviceprovider.JDK9Method; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java Fri Feb 02 17:28:17 2018 -0800 @@ -54,6 +54,7 @@ public static final byte CONSTANT_NameAndType = 12; public static final byte CONSTANT_MethodHandle = 15; public static final byte CONSTANT_MethodType = 16; + public static final byte CONSTANT_Dynamic = 17; public static final byte CONSTANT_InvokeDynamic = 18; // @formatter:on diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java Fri Feb 02 17:28:17 2018 -0800 @@ -112,6 +112,9 @@ case ClassfileConstant.CONSTANT_MethodType: skipFully(stream, 2); // descriptor_index return new ClassfileConstant.Unsupported(tag, "CONSTANT_MethodType_info"); + case ClassfileConstant.CONSTANT_Dynamic: + skipFully(stream, 4); // bootstrap_method_attr_index, name_and_type_index + return new ClassfileConstant.Unsupported(tag, "CONSTANT_Dynamic_info"); case ClassfileConstant.CONSTANT_InvokeDynamic: skipFully(stream, 4); // bootstrap_method_attr_index, name_and_type_index return new ClassfileConstant.Unsupported(tag, "CONSTANT_InvokeDynamic_info"); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java Fri Feb 02 17:28:17 2018 -0800 @@ -62,7 +62,7 @@ @Override public boolean inferStamp() { - return updateStamp(computeStamp(getObject())); + return updateStamp(stamp.improveWith(computeStamp(getObject()))); } protected Stamp computeStamp(ValueNode object) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java Fri Feb 02 17:28:17 2018 -0800 @@ -37,6 +37,8 @@ import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.MirroredTypeException; import javax.lang.model.type.TypeMirror; @@ -84,8 +86,8 @@ try { annotation.value(); } catch (MirroredTypeException ex) { - TypeMirror serviceInterface = ex.getTypeMirror(); - if (verifyAnnotation(serviceInterface, serviceProvider)) { + TypeMirror service = ex.getTypeMirror(); + if (verifyAnnotation(service, serviceProvider)) { if (serviceProvider.getNestingKind().isNested()) { /* * This is a simplifying constraint that means we don't have to process the @@ -94,7 +96,30 @@ String msg = String.format("Service provider class %s must be a top level class", serviceProvider.getSimpleName()); processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider); } else { - serviceProviders.put(serviceProvider, ex.getTypeMirror().toString()); + /* + * Since the definition of the service class is not necessarily modifiable, + * we need to support a non-top-level service class and ensure its name is + * properly expressed with '$' separating nesting levels instead of '.'. + */ + TypeElement serviceElement = (TypeElement) processingEnv.getTypeUtils().asElement(service); + String serviceName = serviceElement.getSimpleName().toString(); + Element enclosing = serviceElement.getEnclosingElement(); + while (enclosing != null) { + final ElementKind kind = enclosing.getKind(); + if (kind == ElementKind.PACKAGE) { + serviceName = ((PackageElement) enclosing).getQualifiedName().toString() + "." + serviceName; + break; + } else if (kind == ElementKind.CLASS || kind == ElementKind.INTERFACE) { + serviceName = ((TypeElement) enclosing).getSimpleName().toString() + "$" + serviceName; + enclosing = enclosing.getEnclosingElement(); + } else { + String msg = String.format("Cannot generate provider descriptor for service class %s as it is not nested in a package, class or interface", + serviceElement.getQualifiedName()); + processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider); + return; + } + } + serviceProviders.put(serviceProvider, serviceName); } } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,7 +24,6 @@ import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM; import static org.graalvm.compiler.debug.DebugContext.NO_DESCRIPTION; -import static org.graalvm.compiler.debug.DebugContext.NO_GLOBAL_METRIC_VALUES; import java.io.PrintStream; import java.io.PrintWriter; @@ -36,16 +35,17 @@ import java.util.Collections; import java.util.List; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpHandler; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.GlobalMetrics; import org.graalvm.compiler.options.OptionValues; import org.junit.After; import org.junit.Assert; import org.junit.internal.ComparisonCriteria; import org.junit.internal.ExactComparisonCriteria; +import jdk.vm.ci.meta.ResolvedJavaMethod; import sun.misc.Unsafe; /** @@ -398,7 +398,7 @@ /** * Gets a {@link DebugContext} object corresponding to {@code options}, creating a new one if - * none currently exists.Debug contexts created by this method will have their + * none currently exists. Debug contexts created by this method will have their * {@link DebugDumpHandler}s closed in {@link #afterTest()}. * * @param options currently active options @@ -423,11 +423,21 @@ } else { descr = new DebugContext.Description(method, id == null ? method.getName() : id); } - DebugContext debug = DebugContext.create(options, descr, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, getDebugHandlersFactories()); + DebugContext debug = DebugContext.create(options, descr, globalMetrics, DEFAULT_LOG_STREAM, getDebugHandlersFactories()); cached.add(debug); return debug; } + private static final GlobalMetrics globalMetrics = new GlobalMetrics(); + + static { + Runtime.getRuntime().addShutdownHook(new Thread("GlobalMetricsPrinter") { + @Override + public void run() { + globalMetrics.print(new OptionValues(OptionValues.newOptionMap())); + } + }); + } private final ThreadLocal> cachedDebugs = new ThreadLocal<>(); @After @@ -435,6 +445,7 @@ List cached = cachedDebugs.get(); if (cached != null) { for (DebugContext debug : cached) { + debug.close(); debug.closeDumpHandlers(true); } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java Fri Feb 02 17:28:17 2018 -0800 @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.test; -import org.graalvm.util.CollectionsUtil; - import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -37,6 +35,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.graalvm.util.CollectionsUtil; + /** * Utility methods for spawning a VM in a subprocess during unit tests. */ diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,8 +25,8 @@ import java.util.Iterator; import java.util.Map; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.UnmodifiableMapCursor; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.UnmodifiableMapCursor; public abstract class EffectsBlockState> { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,6 +25,9 @@ import java.util.ArrayList; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.core.common.type.Stamp; @@ -59,9 +62,6 @@ import org.graalvm.compiler.phases.graph.ReentrantBlockIterator; import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.LoopInfo; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; import org.graalvm.word.LocationIdentity; public abstract class EffectsClosure> extends EffectsPhase.Closure { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,6 +24,7 @@ import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.core.common.util.CompilationAlarm; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Graph.NodeEventScope; @@ -39,7 +40,6 @@ import org.graalvm.compiler.phases.graph.ReentrantBlockIterator; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.tiers.PhaseContext; -import org.graalvm.util.EconomicSet; public abstract class EffectsPhase extends BasePhase { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,6 +25,8 @@ import java.util.Iterator; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.DebugContext; @@ -35,8 +37,6 @@ import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java Fri Feb 02 17:28:17 2018 -0800 @@ -29,6 +29,11 @@ import java.util.Iterator; import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.MapCursor; +import org.graalvm.collections.Pair; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.graph.Node; @@ -61,11 +66,6 @@ import org.graalvm.compiler.nodes.virtual.VirtualArrayNode; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.virtual.phases.ea.PEReadEliminationBlockState.ReadCacheEntry; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; -import org.graalvm.util.MapCursor; -import org.graalvm.util.Pair; import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.ConstantReflectionProvider; @@ -186,7 +186,7 @@ JavaKind accessKind = load.accessKind(); JavaKind componentKind = type.getComponentType().getJavaKind(); long offset = load.offset().asJavaConstant().asLong(); - int index = VirtualArrayNode.entryIndexForOffset(offset, accessKind, type.getComponentType(), Integer.MAX_VALUE); + int index = VirtualArrayNode.entryIndexForOffset(tool.getArrayOffsetProvider(), offset, accessKind, type.getComponentType(), Integer.MAX_VALUE); ValueNode object = GraphUtil.unproxify(load.object()); LocationIdentity location = NamedLocationIdentity.getArrayLocation(componentKind); ValueNode cachedValue = state.getReadCache(object, location, index, accessKind, this); @@ -212,7 +212,7 @@ if (store.offset().isConstant()) { long offset = store.offset().asJavaConstant().asLong(); boolean overflowAccess = isOverflowAccess(accessKind, componentKind); - int index = overflowAccess ? -1 : VirtualArrayNode.entryIndexForOffset(offset, accessKind, type.getComponentType(), Integer.MAX_VALUE); + int index = overflowAccess ? -1 : VirtualArrayNode.entryIndexForOffset(tool.getArrayOffsetProvider(), offset, accessKind, type.getComponentType(), Integer.MAX_VALUE); return processStore(store, store.object(), location, index, accessKind, overflowAccess, store.value(), state, effects); } else { processIdentity(state, location); diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,6 +28,9 @@ import java.util.List; import java.util.function.IntUnaryOperator; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; @@ -68,9 +71,6 @@ import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.virtual.nodes.VirtualObjectState; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapePhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapePhase.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapePhase.java Fri Feb 02 17:28:17 2018 -0800 @@ -25,6 +25,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.EscapeAnalysisIterations; import static org.graalvm.compiler.core.common.GraalOptions.EscapeAnalyzeOnly; +import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; @@ -37,7 +38,6 @@ import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; -import org.graalvm.util.EconomicSet; public class PartialEscapePhase extends EffectsPhase { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,10 +24,10 @@ import java.util.Iterator; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.util.Equivalence; import org.graalvm.word.LocationIdentity; -import org.graalvm.util.EconomicMap; /** * This class maintains a set of known values, identified by base object, locations and offset. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java Fri Feb 02 17:28:17 2018 -0800 @@ -28,7 +28,10 @@ import java.util.Iterator; import java.util.List; -import jdk.vm.ci.meta.ResolvedJavaType; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.MapCursor; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.Node; @@ -60,13 +63,10 @@ import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.CacheEntry; import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry; import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; -import org.graalvm.util.MapCursor; import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaType; /** * This closure initially handled a set of nodes that is disjunct from diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,6 +26,8 @@ import java.util.List; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; @@ -35,8 +37,6 @@ import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.Equivalence; import jdk.vm.ci.meta.ResolvedJavaMethod; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,6 +26,7 @@ import java.util.List; +import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; @@ -108,6 +109,11 @@ return constantFieldProvider; } + @Override + public ArrayOffsetProvider getArrayOffsetProvider() { + return loweringProvider; + } + public void reset(PartialEscapeBlockState newState, ValueNode newCurrent, FixedNode newPosition, GraphEffectList newEffects) { deleted = false; state = newState; @@ -160,7 +166,7 @@ * Special case: Allow storing a single long or double value into two consecutive * int slots. */ - int nextIndex = virtual.entryIndexForOffset(offset + 4, JavaKind.Int); + int nextIndex = virtual.entryIndexForOffset(getArrayOffsetProvider(), offset + 4, JavaKind.Int); if (nextIndex != -1) { canVirtualize = true; assert nextIndex == index + 1 : "expected to be sequential"; diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java Fri Feb 02 17:28:17 2018 -0800 @@ -31,7 +31,9 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BridgeMethodUtils; +import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; @@ -409,31 +411,30 @@ private ValueNode comparisonOp(GraphBuilderContext graph, Condition condition, ValueNode left, ValueNode right) { assert left.getStackKind() == wordKind && right.getStackKind() == wordKind; - // mirroring gets the condition into canonical form - boolean mirror = condition.canonicalMirror(); + CanonicalizedCondition canonical = condition.canonicalize(); - ValueNode a = mirror ? right : left; - ValueNode b = mirror ? left : right; + ValueNode a = canonical.mustMirror() ? right : left; + ValueNode b = canonical.mustMirror() ? left : right; CompareNode comparison; - if (condition == Condition.EQ || condition == Condition.NE) { + if (canonical.getCanonicalCondition() == CanonicalCondition.EQ) { comparison = new IntegerEqualsNode(a, b); - } else if (condition.isUnsigned()) { + } else if (canonical.getCanonicalCondition() == CanonicalCondition.BT) { comparison = new IntegerBelowNode(a, b); } else { + assert canonical.getCanonicalCondition() == CanonicalCondition.LT; comparison = new IntegerLessThanNode(a, b); } ConstantNode trueValue = graph.add(forInt(1)); ConstantNode falseValue = graph.add(forInt(0)); - if (condition.canonicalNegate()) { + if (canonical.mustNegate()) { ConstantNode temp = trueValue; trueValue = falseValue; falseValue = temp; } - ConditionalNode materialize = graph.add(new ConditionalNode(graph.add(comparison), trueValue, falseValue)); - return materialize; + return graph.add(new ConditionalNode(graph.add(comparison), trueValue, falseValue)); } protected ValueNode readOp(GraphBuilderContext b, JavaKind readKind, AddressNode address, LocationIdentity location, Opcode op) { diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphJavadocSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphJavadocSnippets.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.graphio; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.channels.WritableByteChannel; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +final class GraphJavadocSnippets { + static GraphStructure acmeGraphStructure() { + // @formatter:off + // BEGIN: org.graalvm.graphio.GraphJavadocSnippets#acmeGraphStructure + class AcmeGraphStructure implements + GraphStructure { + + @Override + public AcmeGraph graph(AcmeGraph currentGraph, Object obj) { + return obj instanceof AcmeGraph ? (AcmeGraph) obj : null; + } + + @Override + public Iterable nodes(AcmeGraph graph) { + return graph.allNodes(); + } + + @Override + public int nodesCount(AcmeGraph graph) { + return graph.allNodes().size(); + } + + @Override + public int nodeId(AcmeNode node) { + return node.id; + } + + @Override + public boolean nodeHasPredecessor(AcmeNode node) { + return node.id > 0; + } + + @Override + public void nodeProperties( + AcmeGraph graph, AcmeNode node, Map properties + ) { + properties.put("id", node.id); + } + + @Override + public AcmeNodeType nodeClass(Object obj) { + return obj instanceof AcmeNodeType ? (AcmeNodeType) obj : null; + } + + @Override + public AcmeNode node(Object obj) { + return obj instanceof AcmeNode ? (AcmeNode) obj : null; + } + + @Override + public AcmeNodeType classForNode(AcmeNode node) { + // we have only one type of nodes + return AcmeNodeType.STANDARD; + } + + + @Override + public String nameTemplate(AcmeNodeType nodeClass) { + return "Acme ({p#id})"; + } + + @Override + public Object nodeClassType(AcmeNodeType nodeClass) { + return nodeClass.getClass(); + } + + @Override + public AcmePorts portInputs(AcmeNodeType nodeClass) { + return AcmePorts.INPUT; + } + + @Override + public AcmePorts portOutputs(AcmeNodeType nodeClass) { + return AcmePorts.OUTPUT; + } + + @Override + public int portSize(AcmePorts port) { + return port == AcmePorts.OUTPUT ? 1 : 0; + } + + @Override + public boolean edgeDirect(AcmePorts port, int index) { + return false; + } + + @Override + public String edgeName(AcmePorts port, int index) { + return port.name(); + } + + @Override + public Object edgeType(AcmePorts port, int index) { + return port; + } + + @Override + public Collection edgeNodes( + AcmeGraph graph, AcmeNode node, AcmePorts port, int index + ) { + if (port == AcmePorts.OUTPUT) { + return node.outgoing.targets; + } + return null; + } + } + + // END: org.graalvm.graphio.GraphJavadocSnippets#acmeGraphStructure + + return new AcmeGraphStructure(); + } + + // BEGIN: org.graalvm.graphio.GraphJavadocSnippets#buildOutput + static GraphOutput buildOutput(WritableByteChannel channel) + throws IOException { + return GraphOutput.newBuilder(acmeGraphStructure()). + // use the latest version; currently 5.0 + protocolVersion(5, 0). + build(channel); + } + // END: org.graalvm.graphio.GraphJavadocSnippets#buildOutput + + // BEGIN: org.graalvm.graphio.GraphJavadocSnippets#buildAll + static GraphOutput buildAll(WritableByteChannel channel) + throws IOException { + GraphBlocks graphBlocks = acmeBlocks(); + GraphElements graphElements = acmeElements(); + GraphTypes graphTypes = acmeTypes(); + + return GraphOutput.newBuilder(acmeGraphStructure()). + protocolVersion(5, 0). + blocks(graphBlocks). + elements(graphElements). + types(graphTypes). + build(channel); + } + // END: org.graalvm.graphio.GraphJavadocSnippets#buildAll + + private static GraphTypes acmeTypes() { + GraphTypes graphTypes = null; + // in real world don't return null + return graphTypes; + } + + private static GraphElements acmeElements() { + GraphElements graphElements = null; + // in real world don't return null + return graphElements; + } + + private static GraphBlocks acmeBlocks() { + GraphBlocks graphBlocks = null; + // in real world don't return null + return graphBlocks; + } + + private static class AcmeGraph { + final AcmeNode root; + + AcmeGraph(AcmeNode root) { + this.root = root; + } + + Set allNodes() { + return allNodes(root, new LinkedHashSet<>()); + } + + private static Set allNodes(AcmeNode node, Set collectTo) { + if (collectTo.add(node)) { + for (AcmeNode target : node.outgoing.targets) { + allNodes(target, collectTo); + } + } + return collectTo; + } + } + + private static class AcmeNode { + final int id; + final AcmeEdges outgoing; + + AcmeNode(int id) { + this.id = id; + this.outgoing = new AcmeEdges(); + } + + void linkTo(AcmeNode target) { + outgoing.targets.add(target); + } + } + + private enum AcmeNodeType { + STANDARD + } + + private enum AcmePorts { + INPUT, + OUTPUT; + } + + private static class AcmeEdges { + final Set targets; + + AcmeEdges() { + this.targets = new LinkedHashSet<>(); + } + } + + private static class AcmeBlocks { + } + + private static class AcmeMethod { + } + + private static class AcmeField { + } + + private static class AcmeSignature { + } + + private static class AcmeCodePosition { + } + + // BEGIN: org.graalvm.graphio.GraphJavadocSnippets#dump + static void dump(File toFile) throws IOException { + try ( + FileChannel ch = new FileOutputStream(toFile).getChannel(); + GraphOutput output = buildOutput(ch); + ) { + AcmeNode root = new AcmeNode(0); + AcmeNode n1 = new AcmeNode(1); + AcmeNode n2 = new AcmeNode(2); + AcmeNode n3 = new AcmeNode(3); + + root.linkTo(n1); + root.linkTo(n2); + n1.linkTo(n3); + n2.linkTo(n3); + + AcmeGraph diamondGraph = new AcmeGraph(root); + + output.beginGroup(diamondGraph, "Diamond", "dia", null, 0, null); + output.print(diamondGraph, null, 0, "Diamond graph #%d", 1); + output.endGroup(); + } + } + // END: org.graalvm.graphio.GraphJavadocSnippets#dump + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphSnippets.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphSnippets.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2017, 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 org.graalvm.graphio; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.channels.FileChannel; -import java.nio.channels.WritableByteChannel; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -final class GraphSnippets { - static GraphStructure acmeGraphStructure() { - // @formatter:off - // BEGIN: org.graalvm.graphio.GraphSnippets#acmeGraphStructure - class AcmeGraphStructure implements - GraphStructure { - - @Override - public AcmeGraph graph(AcmeGraph currentGraph, Object obj) { - return obj instanceof AcmeGraph ? (AcmeGraph) obj : null; - } - - @Override - public Iterable nodes(AcmeGraph graph) { - return graph.allNodes(); - } - - @Override - public int nodesCount(AcmeGraph graph) { - return graph.allNodes().size(); - } - - @Override - public int nodeId(AcmeNode node) { - return node.id; - } - - @Override - public boolean nodeHasPredecessor(AcmeNode node) { - return node.id > 0; - } - - @Override - public void nodeProperties( - AcmeGraph graph, AcmeNode node, Map properties - ) { - properties.put("id", node.id); - } - - @Override - public AcmeNodeType nodeClass(Object obj) { - return obj instanceof AcmeNodeType ? (AcmeNodeType) obj : null; - } - - @Override - public AcmeNode node(Object obj) { - return obj instanceof AcmeNode ? (AcmeNode) obj : null; - } - - @Override - public AcmeNodeType classForNode(AcmeNode node) { - // we have only one type of nodes - return AcmeNodeType.STANDARD; - } - - - @Override - public String nameTemplate(AcmeNodeType nodeClass) { - return "Acme ({p#id})"; - } - - @Override - public Object nodeClassType(AcmeNodeType nodeClass) { - return nodeClass.getClass(); - } - - @Override - public AcmePorts portInputs(AcmeNodeType nodeClass) { - return AcmePorts.INPUT; - } - - @Override - public AcmePorts portOutputs(AcmeNodeType nodeClass) { - return AcmePorts.OUTPUT; - } - - @Override - public int portSize(AcmePorts port) { - return port == AcmePorts.OUTPUT ? 1 : 0; - } - - @Override - public boolean edgeDirect(AcmePorts port, int index) { - return false; - } - - @Override - public String edgeName(AcmePorts port, int index) { - return port.name(); - } - - @Override - public Object edgeType(AcmePorts port, int index) { - return port; - } - - @Override - public Collection edgeNodes( - AcmeGraph graph, AcmeNode node, AcmePorts port, int index - ) { - if (port == AcmePorts.OUTPUT) { - return node.outgoing.targets; - } - return null; - } - } - - // END: org.graalvm.graphio.GraphSnippets#acmeGraphStructure - - return new AcmeGraphStructure(); - } - - // BEGIN: org.graalvm.graphio.GraphSnippets#buildOutput - static GraphOutput buildOutput(WritableByteChannel channel) - throws IOException { - return GraphOutput.newBuilder(acmeGraphStructure()). - // use the latest version; currently 5.0 - protocolVersion(5, 0). - build(channel); - } - // END: org.graalvm.graphio.GraphSnippets#buildOutput - - // BEGIN: org.graalvm.graphio.GraphSnippets#buildAll - static GraphOutput buildAll(WritableByteChannel channel) - throws IOException { - GraphBlocks graphBlocks = acmeBlocks(); - GraphElements graphElements = acmeElements(); - GraphTypes graphTypes = acmeTypes(); - - return GraphOutput.newBuilder(acmeGraphStructure()). - protocolVersion(5, 0). - blocks(graphBlocks). - elements(graphElements). - types(graphTypes). - build(channel); - } - // END: org.graalvm.graphio.GraphSnippets#buildAll - - private static GraphTypes acmeTypes() { - GraphTypes graphTypes = null; - // in real world don't return null - return graphTypes; - } - - private static GraphElements acmeElements() { - GraphElements graphElements = null; - // in real world don't return null - return graphElements; - } - - private static GraphBlocks acmeBlocks() { - GraphBlocks graphBlocks = null; - // in real world don't return null - return graphBlocks; - } - - private static class AcmeGraph { - final AcmeNode root; - - AcmeGraph(AcmeNode root) { - this.root = root; - } - - Set allNodes() { - return allNodes(root, new LinkedHashSet<>()); - } - - private static Set allNodes(AcmeNode node, Set collectTo) { - if (collectTo.add(node)) { - for (AcmeNode target : node.outgoing.targets) { - allNodes(target, collectTo); - } - } - return collectTo; - } - } - - private static class AcmeNode { - final int id; - final AcmeEdges outgoing; - - AcmeNode(int id) { - this.id = id; - this.outgoing = new AcmeEdges(); - } - - void linkTo(AcmeNode target) { - outgoing.targets.add(target); - } - } - - private enum AcmeNodeType { - STANDARD - } - - private enum AcmePorts { - INPUT, - OUTPUT; - } - - private static class AcmeEdges { - final Set targets; - - AcmeEdges() { - this.targets = new LinkedHashSet<>(); - } - } - - private static class AcmeBlocks { - } - - private static class AcmeMethod { - } - - private static class AcmeField { - } - - private static class AcmeSignature { - } - - private static class AcmeCodePosition { - } - - // BEGIN: org.graalvm.graphio.GraphSnippets#dump - static void dump(File toFile) throws IOException { - try ( - FileChannel ch = new FileOutputStream(toFile).getChannel(); - GraphOutput output = buildOutput(ch); - ) { - AcmeNode root = new AcmeNode(0); - AcmeNode n1 = new AcmeNode(1); - AcmeNode n2 = new AcmeNode(2); - AcmeNode n3 = new AcmeNode(3); - - root.linkTo(n1); - root.linkTo(n2); - n1.linkTo(n3); - n2.linkTo(n3); - - AcmeGraph diamondGraph = new AcmeGraph(root); - - output.beginGroup(diamondGraph, "Diamond", "dia", null, 0, null); - output.print(diamondGraph, null, 0, "Diamond graph #%d", 1); - output.endGroup(); - } - } - // END: org.graalvm.graphio.GraphSnippets#dump - -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/package-info.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/package-info.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/package-info.java Fri Feb 02 17:28:17 2018 -0800 @@ -24,13 +24,12 @@ /** * Send your graphs to IGV via a socket or a file. This package allows one to easily encode - * any graph-like data structure and send it for visualization to - * OracleLab's Ideal Graph Visualizer tool. Assuming you already have your own data - * structure that contains nodes and edges among them, creating a - * {@link org.graalvm.graphio.GraphOutput} specialized for your data is a matter of implementing a - * single interface: + * any graph-like data structure and send it for visualization to OracleLab's Ideal Graph + * Visualizer tool. Assuming you already have your own data structure that contains + * nodes and edges among them, creating a {@link org.graalvm.graphio.GraphOutput} + * specialized for your data is a matter of implementing a single interface: * - * {@link org.graalvm.graphio.GraphSnippets#acmeGraphStructure} + * {@link org.graalvm.graphio.GraphJavadocSnippets#acmeGraphStructure} * * The {@link org.graalvm.graphio.GraphStructure} interface defines the set of operations that are * needed by the graph protocol to encode a graph into the IGV expected format. The @@ -43,7 +42,7 @@ * {@link org.graalvm.graphio.GraphOutput}. To do so use the associated * {@link org.graalvm.graphio.GraphOutput.Builder builder} just like shown in the following method: * - * {@link org.graalvm.graphio.GraphSnippets#buildOutput} + * {@link org.graalvm.graphio.GraphJavadocSnippets#buildOutput} * * Now you are ready to dump your graph into IGV. Where to obtain the right channel? One * option is to create a {@link java.nio.channels.FileChannel} and dump the data into a file @@ -51,7 +50,7 @@ * 4445 (the default port IGV listens to) and dump the data there. Here is an * example: * - * {@link org.graalvm.graphio.GraphSnippets#dump} + * {@link org.graalvm.graphio.GraphJavadocSnippets#dump} * * Call the {@code dump} method with pointer to file {@code diamond.bgv} and then you can open the * file in IGV. The result will look like this: @@ -75,7 +74,7 @@ * {@link org.graalvm.graphio.GraphOutput.Builder} instance methods, which may, but need not be * called at all. Here is an example: * - * {@link org.graalvm.graphio.GraphSnippets#buildAll} + * {@link org.graalvm.graphio.GraphJavadocSnippets#buildAll} * * All these interfaces follow the * singletonizer API pattern again - e.g. diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionCategory.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionCategory.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2017, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 org.graalvm.options; - -/** - * Categorizes options according to user relevance. - * - * @since 1.0 - */ -public enum OptionCategory { - - /** - * An option common for users to apply. - * - * @since 1.0 - */ - USER, - - /** - * An option only relevant in corner cases and for fine-tuning. - * - * @since 1.0 - */ - EXPERT, - - /** - * An option only relevant when debugging language or instrument implementations. - * - * @since 1.0 - */ - DEBUG - -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2017, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 org.graalvm.options; - -import java.util.Objects; - -/** - * Represents metadata for a single option. - * - * @since 1.0 - */ -public final class OptionDescriptor { - - private final OptionKey key; - private final String name; - private final String help; - private final OptionCategory kind; - private final boolean deprecated; - - OptionDescriptor(OptionKey key, String name, String help, OptionCategory kind, boolean deprecated) { - this.key = key; - this.name = name; - this.help = help; - this.kind = kind; - this.deprecated = deprecated; - } - - /** - * Returns the name of the option that this descriptor represents. - * - * @since 1.0 - */ - public String getName() { - return name; - } - - /** - * Returns the key for this option. - * - * @since 1.0 - */ - public OptionKey getKey() { - return key; - } - - /** - * Returns true if this option was marked deprecated. This indicates that the - * option is going to be removed in a future release or its use is not recommended. - * - * @since 1.0 - */ - public boolean isDeprecated() { - return deprecated; - } - - /** - * Returns the user category of this option. - * - * @since 1.0 - */ - public OptionCategory getCategory() { - return kind; - } - - /** - * Returns a human-readable description on how to use the option. - * - * @since 1.0 - */ - public String getHelp() { - return help; - } - - /** - * {@inheritDoc} - * - * @since 1.0 - */ - @Override - public String toString() { - return "OptionDescriptor [key=" + key + ", help=" + help + ", kind=" + kind + ", deprecated=" + deprecated + "]"; - } - - /** - * {@inheritDoc} - * - * @since 1.0 - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (deprecated ? 1231 : 1237); - result = prime * result + ((help == null) ? 0 : help.hashCode()); - result = prime * result + ((key == null) ? 0 : key.hashCode()); - result = prime * result + ((kind == null) ? 0 : kind.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - /** - * {@inheritDoc} - * - * @since 1.0 - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } else if (obj == null) { - return false; - } else if (getClass() != obj.getClass()) { - return false; - } - OptionDescriptor other = (OptionDescriptor) obj; - return Objects.equals(name, other.name) && - Objects.equals(deprecated, other.deprecated) && - Objects.equals(help, other.help) && - Objects.equals(key, other.key) && - Objects.equals(kind, other.kind); - } - - /** - * Creates a new option descriptor builder by key. The option group and name is inferred by the - * key. - * - * @since 1.0 - */ - public static Builder newBuilder(OptionKey key, String name) { - Objects.requireNonNull(key); - Objects.requireNonNull(name); - return EMPTY.new Builder(key, name); - } - - private static final OptionDescriptor EMPTY = new OptionDescriptor(null, null, null, null, false); - - /** - * Represents an option descriptor builder. - * - * @since 1.0 - */ - public final class Builder { - - private final OptionKey key; - private final String name; - private boolean deprecated; - private OptionCategory category; - private String help; - - Builder(OptionKey key, String name) { - this.key = key; - this.name = name; - } - - /** - * Defines the user category for this option. The default value is - * {@link OptionCategory#DEBUG}. - * - * @since 1.0 - */ - public Builder category(@SuppressWarnings("hiding") OptionCategory category) { - Objects.requireNonNull(category); - this.category = category; - return this; - } - - /** - * Defines if this option is deprecated. The default value for deprecated is - * false. This can be used to evolve options between releases. - * - * @since 1.0 - */ - public Builder deprecated(@SuppressWarnings("hiding") boolean deprecated) { - this.deprecated = deprecated; - return this; - } - - /** - * Specifies a human-readable description on how to use the option. - * - * @since 1.0 - */ - public Builder help(@SuppressWarnings("hiding") String help) { - Objects.requireNonNull(help); - this.help = help; - return this; - } - - /** - * Builds and returns a new option descriptor. - * - * @since 1.0 - */ - public OptionDescriptor build() { - return new OptionDescriptor(key, name, help == null ? "" : help, category == null ? OptionCategory.DEBUG : category, deprecated); - } - - } - -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptors.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptors.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2017, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 org.graalvm.options; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; - -/** - * An interface to a set of {@link OptionDescriptor}s. - * - * @since 1.0 - */ -public interface OptionDescriptors extends Iterable { - - /** - * An empty set of option descriptors. - * - * @since 1.0 - */ - OptionDescriptors EMPTY = new OptionDescriptors() { - - public Iterator iterator() { - return Collections. emptyList().iterator(); - } - - public OptionDescriptor get(String key) { - return null; - } - }; - - /** - * Gets the {@link OptionDescriptor} matching a given option name or {@code null} if this option - * descriptor set does not contain a matching option name. - * - * @since 1.0 - */ - OptionDescriptor get(String optionName); - - /** - * Creates a union options descriptor out of multiple given descriptors. The operation - * descriptors are not checked for duplicate keys. The option descriptors are iterated in - * declaration order. - * - * @since 1.0 - */ - static OptionDescriptors createUnion(OptionDescriptors... descriptors) { - if (descriptors.length == 0) { - return EMPTY; - } else if (descriptors.length == 1) { - return descriptors[0]; - } else { - return new UnionOptionDescriptors(descriptors); - } - } - - /** - * {@inheritDoc} - * - * @since 1.0 - */ - @Override - Iterator iterator(); - - /** - * Creates an {@link OptionDescriptors} instance from a list. The option descriptors - * implementation is backed by a {@link LinkedHashMap} that preserves ordering. - * - * @since 1.0 - */ - static OptionDescriptors create(List descriptors) { - if (descriptors == null || descriptors.isEmpty()) { - return EMPTY; - } - return new OptionDescriptorsMap(descriptors); - } -} - -class OptionDescriptorsMap implements OptionDescriptors { - - final Map descriptors = new LinkedHashMap<>(); - - OptionDescriptorsMap(List descriptorList) { - for (OptionDescriptor descriptor : descriptorList) { - descriptors.put(descriptor.getName(), descriptor); - } - } - - @Override - public OptionDescriptor get(String optionName) { - return descriptors.get(optionName); - } - - @Override - public Iterator iterator() { - return descriptors.values().iterator(); - } - -} - -final class UnionOptionDescriptors implements OptionDescriptors { - - final OptionDescriptors[] descriptorsList; - - UnionOptionDescriptors(OptionDescriptors[] descriptors) { - // defensive copy - this.descriptorsList = Arrays.copyOf(descriptors, descriptors.length); - } - - public Iterator iterator() { - return new Iterator() { - - Iterator descriptors = descriptorsList[0].iterator(); - int descriptorsIndex = 0; - OptionDescriptor next = null; - - public boolean hasNext() { - return fetchNext() != null; - } - - private OptionDescriptor fetchNext() { - if (next != null) { - return next; - } - if (descriptors.hasNext()) { - next = descriptors.next(); - return next; - } else if (descriptorsIndex < descriptorsList.length - 1) { - descriptorsIndex++; - descriptors = descriptorsList[descriptorsIndex].iterator(); - return fetchNext(); - } else { - return null; - } - } - - public OptionDescriptor next() { - OptionDescriptor fetchedNext = fetchNext(); - if (fetchedNext != null) { - // consume next - this.next = null; - return fetchedNext; - } else { - throw new NoSuchElementException(); - } - } - }; - } - - public OptionDescriptor get(String value) { - for (OptionDescriptors descriptors : descriptorsList) { - OptionDescriptor descriptor = descriptors.get(value); - if (descriptor != null) { - return descriptor; - } - } - return null; - } - -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionKey.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionKey.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2017, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 org.graalvm.options; - -import java.util.Objects; - -/** - * Represents the option key for an option specification. - * - * @since 1.0 - */ -public final class OptionKey { - - private final OptionType type; - private final T defaultValue; - - /** - * Constructs a new option key given a default value. Throws {@link IllegalArgumentException} if - * no default {@link OptionType} could be {@link OptionType#defaultType(Object) resolved} for - * the given type. The default value must not be null. - * - * @since 1.0 - */ - public OptionKey(T defaultValue) { - Objects.requireNonNull(defaultValue); - this.defaultValue = defaultValue; - this.type = OptionType.defaultType(defaultValue); - if (type == null) { - throw new IllegalArgumentException("No default type specified for type " + defaultValue.getClass().getName() + ". Specify the option type explicitly to resolve this."); - } - } - - /** - * Constructs a new option key given a default value and option key. - * - * @since 1.0 - */ - public OptionKey(T defaultValue, OptionType type) { - Objects.requireNonNull(type); - this.defaultValue = defaultValue; - this.type = type; - } - - /** - * Returns the option type of this key. - * - * @since 1.0 - */ - public OptionType getType() { - return type; - } - - /** - * Returns the default value for this option. - * - * @since 1.0 - */ - public T getDefaultValue() { - return defaultValue; - } - - /** - * Returns the value of this key given the {@link OptionValues values}. - * - * @since 1.0 - */ - public T getValue(OptionValues values) { - return values.get(this); - } - - /** - * Returns true if a value for this key has been set for the given option values or - * false if no value has been set. - * - * @since 1.0 - */ - public boolean hasBeenSet(OptionValues values) { - return values.hasBeenSet(this); - } - -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionType.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionType.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2017, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 org.graalvm.options; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * Represents a type of an option that allows to convert string values to Java values. - * - * @since 1.0 - */ -public final class OptionType { - - private final String name; - private final Function stringConverter; - private final Consumer validator; - private final T defaultValue; - - /** - * Constructs a new option type with name, defaultValue, and function that allows to convert a - * string to the option type. - * - * @param name the name of the type. - * @param defaultValue the default value to use if no value is given. - * @param stringConverter a function that converts a string value to the option value. Can throw - * {@link IllegalArgumentException} to indicate an invalid string. - * @param validator used for validating the option value. Throws - * {@link IllegalArgumentException} if the value is invalid. - * - * @since 1.0 - */ - public OptionType(String name, T defaultValue, Function stringConverter, Consumer validator) { - Objects.requireNonNull(name); - Objects.requireNonNull(stringConverter); - Objects.requireNonNull(validator); - this.name = name; - this.stringConverter = stringConverter; - this.defaultValue = defaultValue; - this.validator = validator; - } - - /** - * Constructs a new option type with name, defaultValue, and function that allows to convert a - * string to the option type. - * - * @param name the name of the type. - * @param defaultValue the default value to use if no value is given. - * @param stringConverter a function that converts a string value to the option value. Can throw - * {@link IllegalArgumentException} to indicate an invalid string. - * - * @since 1.0 - */ - public OptionType(String name, T defaultValue, Function stringConverter) { - this(name, defaultValue, stringConverter, new Consumer() { - public void accept(T t) { - } - }); - } - - /** - * Returns the default value of this type. Used if no value is available. - * - * @since 1.0 - */ - public T getDefaultValue() { - return defaultValue; - } - - /** - * Returns the name of this type. - * - * @since 1.0 - */ - public String getName() { - return name; - } - - /** - * Converts a string value, validates it, and converts it to an object of this type. - * - * @throws IllegalArgumentException if the value is invalid or cannot be converted. - * @since 1.0 - */ - public T convert(String value) { - T v = stringConverter.apply(value); - validate(v); - return v; - } - - /** - * Validates an option value and throws an {@link IllegalArgumentException} if the value is - * invalid. - * - * @throws IllegalArgumentException if the value is invalid or cannot be converted. - * @since 1.0 - */ - public void validate(T value) { - validator.accept(value); - } - - /** - * @since 1.0 - */ - @Override - public String toString() { - return "OptionType[name=" + name + ", defaultValue=" + defaultValue + "]"; - } - - private static final Map, OptionType> DEFAULTTYPES = new HashMap<>(); - static { - DEFAULTTYPES.put(Boolean.class, new OptionType<>("Boolean", false, new Function() { - public Boolean apply(String t) { - if ("true".equals(t)) { - return Boolean.TRUE; - } else if ("false".equals(t)) { - return Boolean.FALSE; - } else { - throw new IllegalArgumentException(String.format("Invalid boolean option value '%s'. The value of the option must be '%s' or '%s'.", t, "true", "false")); - } - } - })); - DEFAULTTYPES.put(Byte.class, new OptionType<>("Byte", (byte) 0, new Function() { - public Byte apply(String t) { - try { - return Byte.parseByte(t); - } catch (NumberFormatException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } - } - })); - DEFAULTTYPES.put(Integer.class, new OptionType<>("Integer", 0, new Function() { - public Integer apply(String t) { - try { - return Integer.parseInt(t); - } catch (NumberFormatException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } - } - })); - DEFAULTTYPES.put(Long.class, new OptionType<>("Long", 0L, new Function() { - public Long apply(String t) { - try { - return Long.parseLong(t); - } catch (NumberFormatException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } - } - })); - DEFAULTTYPES.put(Float.class, new OptionType<>("Float", 0.0f, new Function() { - public Float apply(String t) { - try { - return Float.parseFloat(t); - } catch (NumberFormatException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } - } - })); - DEFAULTTYPES.put(Double.class, new OptionType<>("Double", 0.0d, new Function() { - public Double apply(String t) { - try { - return Double.parseDouble(t); - } catch (NumberFormatException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } - } - })); - DEFAULTTYPES.put(String.class, new OptionType<>("String", "0", new Function() { - public String apply(String t) { - return t; - } - })); - } - - /** - * Returns the default option type for a given value. Returns null if no default - * option type is available for the Java type of this value. - * - * @since 1.0 - */ - @SuppressWarnings("unchecked") - public static OptionType defaultType(T value) { - return defaultType((Class) value.getClass()); - } - - /** - * Returns the default option type for a class. Returns null if no default option - * type is available for this Java type. - * - * @since 1.0 - */ - @SuppressWarnings("unchecked") - public static OptionType defaultType(Class clazz) { - return (OptionType) DEFAULTTYPES.get(clazz); - } - -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionValues.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionValues.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2017, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 org.graalvm.options; - -/** - * Represents a set of option values based on an {@link OptionDescriptor}. - * - * @since 1.0 - */ -public interface OptionValues { - - /** - * Returns all available options. - * - * @since 1.0 - */ - OptionDescriptors getDescriptors(); - - /** - * Sets the value of {@code optionKey} to {@code value}. - * - * @throws IllegalArgumentException if the given value is not {@link OptionType#validate(Object) - * validated} by the {@link OptionKey#getType() option type} of the key. Note that - * the operation succeeds if the option key is not described by any of the - * associated {@link #getDescriptors() descriptors}. - * - * @since 1.0 - */ - void set(OptionKey optionKey, T value); - - /** - * Returns the value of a given option. If no value is set or the key is not described by any - * {@link #getDescriptors() descriptors} the {@link OptionType#getDefaultValue() default value} - * of the given key is returned. - * - * @since 1.0 - */ - T get(OptionKey optionKey); - - /** - * Determines if a value for {@code optionKey} has been {@link #set} in this set of option - * values. - * - * @since 1.0 - */ - boolean hasBeenSet(OptionKey optionKey); - -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/package-info.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/package-info.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2017, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ -/** - * The Graal-SDK options package contains reusable collection classes for options. - * - * @see org.graalvm.options.OptionDescriptor - * @see org.graalvm.options.OptionValues - * - * @since 1.0 - */ -package org.graalvm.options; \ No newline at end of file diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionSizeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionSizeTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017, 2017, 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 org.graalvm.util.test; + +import static org.junit.Assert.assertEquals; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.compiler.test.GraalTest; +import org.graalvm.util.ObjectSizeEstimate; +import org.junit.Assume; +import org.junit.Test; + +public class CollectionSizeTest { + + /** + * Tests the memory size of an empty map and a map with only one or two entries. + */ + @Test + public void testSize() { + Assume.assumeTrue("Not working in JDK9 due to module visibility.", GraalTest.Java8OrEarlier); + EconomicMap map = EconomicMap.create(Equivalence.IDENTITY); + assertEquals(49, ObjectSizeEstimate.forObject(map).getTotalBytes()); + + Integer value = 1; + map.put(value, value); + assertEquals(153, ObjectSizeEstimate.forObject(map).getTotalBytes()); + + Integer secondValue = 2; + map.put(secondValue, secondValue); + assertEquals(153 + 20, ObjectSizeEstimate.forObject(map).getTotalBytes()); + } + + /** + * Tests whether the map actually compresses the entries array when a large number of entries + * are deleted. + */ + @Test + public void testCompress() { + Assume.assumeTrue("Not working in JDK9 due to module visibility.", GraalTest.Java8OrEarlier); + EconomicMap map = EconomicMap.create(); + + // Measuring size of map with one entry. + Object firstValue = 0; + map.put(firstValue, firstValue); + ObjectSizeEstimate afterFirstValue = ObjectSizeEstimate.forObject(map); + + // Add 999 more entries. + for (int i = 1; i < 1000; ++i) { + Object value = i; + map.put(value, value); + } + ObjectSizeEstimate beforeRemove = ObjectSizeEstimate.forObject(map); + + // Remove 999 first entries. + for (int i = 0; i < 999; ++i) { + map.removeKey(i); + } + ObjectSizeEstimate afterRemove = ObjectSizeEstimate.forObject(map); + + // Check that size is same size as with one entry. + assertEquals(afterFirstValue, afterRemove); + + // Add 999 new entries. + for (int i = 0; i < 999; ++i) { + Object value = i; + map.put(value, value); + } + ObjectSizeEstimate afterAdd = ObjectSizeEstimate.forObject(map); + + // Check that entries array is same size again. + assertEquals(beforeRemove.getPointerCount(), afterAdd.getPointerCount()); + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionTest.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,536 +0,0 @@ -/* - * Copyright (c) 2017, 2017, 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 org.graalvm.util.test; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.Random; -import java.util.function.BiFunction; - -import org.graalvm.util.CollectionsUtil; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.Equivalence; -import org.graalvm.util.MapCursor; -import org.graalvm.util.ObjectSizeEstimate; -import org.graalvm.util.UnmodifiableMapCursor; -import org.junit.Assert; -import org.junit.Test; - -public class CollectionTest { - - /** - * Tests the memory size of an empty map and a map with only one or two entries. - */ - @Test - public void testSize() { - EconomicMap map = EconomicMap.create(Equivalence.IDENTITY); - assertEquals(48, ObjectSizeEstimate.forObject(map).getTotalBytes()); - - Integer value = 1; - map.put(value, value); - assertEquals(152, ObjectSizeEstimate.forObject(map).getTotalBytes()); - - Integer secondValue = 2; - map.put(secondValue, secondValue); - assertEquals(152 + 20, ObjectSizeEstimate.forObject(map).getTotalBytes()); - } - - /** - * Tests whether the map actually compresses the entries array when a large number of entries - * are deleted. - */ - @Test - public void testCompress() { - EconomicMap map = EconomicMap.create(); - - // Measuring size of map with one entry. - Object firstValue = 0; - map.put(firstValue, firstValue); - ObjectSizeEstimate afterFirstValue = ObjectSizeEstimate.forObject(map); - - // Add 999 more entries. - for (int i = 1; i < 1000; ++i) { - Object value = i; - map.put(value, value); - } - ObjectSizeEstimate beforeRemove = ObjectSizeEstimate.forObject(map); - - // Remove 999 first entries. - for (int i = 0; i < 999; ++i) { - map.removeKey(i); - } - ObjectSizeEstimate afterRemove = ObjectSizeEstimate.forObject(map); - - // Check that size is same size as with one entry. - assertEquals(afterFirstValue, afterRemove); - - // Add 999 new entries. - for (int i = 0; i < 999; ++i) { - Object value = i; - map.put(value, value); - } - ObjectSizeEstimate afterAdd = ObjectSizeEstimate.forObject(map); - - // Check that entries array is same size again. - assertEquals(beforeRemove.getPointerCount(), afterAdd.getPointerCount()); - } - - private static int[] createRandomRange(Random random, int count) { - int[] result = new int[count]; - for (int i = 0; i < count; ++i) { - int range = random.nextInt(14); - if (range == 0 || range > 10) { - range = Integer.MAX_VALUE; - } else if (range == 10) { - range = 100; - } - result[i] = range; - } - return result; - } - - private static final class BadHashClass { - private int value; - - BadHashClass(int randomInt) { - this.value = randomInt; - } - - @Override - public int hashCode() { - return 0; - } - - @Override - public boolean equals(Object other) { - if (other instanceof BadHashClass) { - BadHashClass badHashClass = (BadHashClass) other; - return badHashClass.value == value; - } - return false; - } - } - - interface MapAction { - Object perform(EconomicMap map, int randomInt); - } - - static final Object EXISTING_VALUE = new Object(); - - static final MapAction[] INCREASE_ACTIONS = new MapAction[]{ - (map, randomInt) -> map.put(randomInt, "value"), - (map, randomInt) -> map.get(randomInt) - }; - - static final MapAction[] ACTIONS = new MapAction[]{ - (map, randomInt) -> map.removeKey(randomInt), - (map, randomInt) -> map.put(randomInt, "value"), - (map, randomInt) -> map.put(randomInt, null), - (map, randomInt) -> map.put(EXISTING_VALUE, randomInt), - (map, randomInt) -> { - if (randomInt == 0) { - map.clear(); - } - return map.isEmpty(); - }, - (map, randomInt) -> map.containsKey(randomInt), - (map, randomInt) -> map.get(randomInt), - (map, randomInt) -> map.put(new BadHashClass(randomInt), "unique"), - (map, randomInt) -> { - if (randomInt == 0) { - map.replaceAll((key, value) -> Objects.toString(value) + "!"); - } - return map.isEmpty(); - } - - }; - - @Test - public void testVeryLarge() { - EconomicMap map = EconomicMap.create(); - EconomicMap referenceMap = createDebugMap(); - - Random random = new Random(0); - for (int i = 0; i < 200000; ++i) { - for (int j = 0; j < INCREASE_ACTIONS.length; ++j) { - int nextInt = random.nextInt(10000000); - MapAction action = INCREASE_ACTIONS[j]; - Object result = action.perform(map, nextInt); - Object referenceResult = action.perform(referenceMap, nextInt); - Assert.assertEquals(result, referenceResult); - } - } - } - - /** - * Tests a sequence of random operations on the map. - */ - @Test - public void testAddRemove() { - EconomicMap map = EconomicMap.create(); - EconomicMap referenceMap = createDebugMap(); - - for (int seed = 0; seed < 10; ++seed) { - Random random = new Random(seed); - int[] ranges = createRandomRange(random, ACTIONS.length); - int value = random.nextInt(10000); - for (int i = 0; i < value; ++i) { - for (int j = 0; j < ACTIONS.length; ++j) { - if (random.nextInt(ranges[j]) == 0) { - int nextInt = random.nextInt(100); - MapAction action = ACTIONS[j]; - Object result = action.perform(map, nextInt); - Object referenceResult = action.perform(referenceMap, nextInt); - Assert.assertEquals(result, referenceResult); - if (j % 100 == 0) { - checkEquality(map, referenceMap); - } - } - } - - if (random.nextInt(20) == 0) { - removeElement(random.nextInt(100), map, referenceMap); - } - } - } - } - - private static void removeElement(int index, EconomicMap map, EconomicMap referenceMap) { - Assert.assertEquals(referenceMap.size(), map.size()); - MapCursor cursor = map.getEntries(); - MapCursor referenceCursor = referenceMap.getEntries(); - int z = 0; - while (cursor.advance()) { - Assert.assertTrue(referenceCursor.advance()); - Assert.assertEquals(referenceCursor.getKey(), cursor.getKey()); - Assert.assertEquals(referenceCursor.getValue(), cursor.getValue()); - if (index == z) { - cursor.remove(); - referenceCursor.remove(); - } - ++z; - } - - Assert.assertFalse(referenceCursor.advance()); - } - - private static void checkEquality(EconomicMap map, EconomicMap referenceMap) { - Assert.assertEquals(referenceMap.size(), map.size()); - - // Check entries. - UnmodifiableMapCursor cursor = map.getEntries(); - UnmodifiableMapCursor referenceCursor = referenceMap.getEntries(); - while (cursor.advance()) { - Assert.assertTrue(referenceCursor.advance()); - Assert.assertEquals(referenceCursor.getKey(), cursor.getKey()); - Assert.assertEquals(referenceCursor.getValue(), cursor.getValue()); - } - - // Check keys. - Iterator iterator = map.getKeys().iterator(); - Iterator referenceIterator = referenceMap.getKeys().iterator(); - while (iterator.hasNext()) { - Assert.assertTrue(referenceIterator.hasNext()); - Assert.assertEquals(iterator.next(), referenceIterator.next()); - } - - // Check values. - iterator = map.getValues().iterator(); - referenceIterator = referenceMap.getValues().iterator(); - while (iterator.hasNext()) { - Assert.assertTrue(referenceIterator.hasNext()); - Assert.assertEquals(iterator.next(), referenceIterator.next()); - } - Assert.assertFalse(referenceIterator.hasNext()); - } - - public static EconomicMap createDebugMap() { - final LinkedHashMap linkedMap = new LinkedHashMap<>(); - final EconomicMap sparseMap = EconomicMap.create(); - return new EconomicMap() { - - @Override - public V get(K key) { - V result = linkedMap.get(key); - V sparseResult = sparseMap.get(key); - assert Objects.equals(result, sparseResult); - return result; - } - - @Override - public V put(K key, V value) { - V result = linkedMap.put(key, value); - assert Objects.equals(result, sparseMap.put(key, value)); - return result; - } - - @Override - public int size() { - int result = linkedMap.size(); - assert result == sparseMap.size(); - return result; - } - - @Override - public boolean containsKey(K key) { - boolean result = linkedMap.containsKey(key); - assert result == sparseMap.containsKey(key); - return result; - } - - @Override - public void clear() { - linkedMap.clear(); - sparseMap.clear(); - } - - @Override - public V removeKey(K key) { - V result = linkedMap.remove(key); - assert Objects.equals(result, sparseMap.removeKey(key)); - return result; - } - - @Override - public Iterable getValues() { - - Iterator iterator = linkedMap.values().iterator(); - Iterator sparseIterator = sparseMap.getValues().iterator(); - return new Iterable() { - - @Override - public Iterator iterator() { - return new Iterator() { - - @Override - public boolean hasNext() { - boolean result = iterator.hasNext(); - boolean otherResult = sparseIterator.hasNext(); - assert result == otherResult; - return result; - } - - @Override - public V next() { - V sparseNext = sparseIterator.next(); - V next = iterator.next(); - assert Objects.equals(sparseNext, next); - return next; - } - - @Override - public void remove() { - iterator.remove(); - sparseIterator.remove(); - } - }; - } - - }; - } - - @Override - public Iterable getKeys() { - - Iterator iterator = linkedMap.keySet().iterator(); - Iterator sparseIterator = sparseMap.getKeys().iterator(); - return new Iterable() { - - @Override - public Iterator iterator() { - return new Iterator() { - - @Override - public boolean hasNext() { - boolean result = iterator.hasNext(); - boolean otherResult = sparseIterator.hasNext(); - assert result == otherResult; - return result; - } - - @Override - public K next() { - K sparseNext = sparseIterator.next(); - K next = iterator.next(); - assert Objects.equals(sparseNext, next); - return next; - } - - @Override - public void remove() { - iterator.remove(); - sparseIterator.remove(); - } - }; - } - - }; - } - - @Override - public boolean isEmpty() { - boolean result = linkedMap.isEmpty(); - assert result == sparseMap.isEmpty(); - return result; - } - - @Override - public MapCursor getEntries() { - Iterator> iterator = linkedMap.entrySet().iterator(); - MapCursor cursor = sparseMap.getEntries(); - return new MapCursor() { - - private Map.Entry current; - - @Override - public boolean advance() { - boolean result = iterator.hasNext(); - boolean otherResult = cursor.advance(); - assert result == otherResult; - if (result) { - current = iterator.next(); - } - - return result; - } - - @Override - public K getKey() { - K key = current.getKey(); - assert key == cursor.getKey(); - return key; - } - - @Override - public V getValue() { - V value = current.getValue(); - assert Objects.equals(value, cursor.getValue()); - return value; - } - - @Override - public void remove() { - iterator.remove(); - cursor.remove(); - } - }; - } - - @Override - public void replaceAll(BiFunction function) { - linkedMap.replaceAll(function); - sparseMap.replaceAll(function); - } - }; - } - - @Test - public void testIterableConcat() { - List i1 = Arrays.asList("1", "2", "3"); - List i2 = Arrays.asList(); - List i3 = Arrays.asList("4", "5"); - List i4 = Arrays.asList(); - List i5 = Arrays.asList("6"); - List iNull = null; - - List actual = new ArrayList<>(); - List expected = new ArrayList<>(); - expected.addAll(i1); - expected.addAll(i2); - expected.addAll(i3); - expected.addAll(i4); - expected.addAll(i5); - Iterable iterable = CollectionsUtil.concat(Arrays.asList(i1, i2, i3, i4, i5)); - for (String s : iterable) { - actual.add(s); - } - Assert.assertEquals(expected, actual); - - Iterator iter = iterable.iterator(); - while (iter.hasNext()) { - iter.next(); - } - try { - iter.next(); - Assert.fail("Expected NoSuchElementException"); - } catch (NoSuchElementException e) { - // Expected - } - try { - CollectionsUtil.concat(i1, iNull); - Assert.fail("Expected NullPointerException"); - } catch (NullPointerException e) { - // Expected - } - - Iterable emptyIterable = CollectionsUtil.concat(Collections.emptyList()); - Assert.assertFalse(emptyIterable.iterator().hasNext()); - } - - @Test - public void testSetRemoval() { - ArrayList initialList = new ArrayList<>(); - ArrayList removalList = new ArrayList<>(); - ArrayList finalList = new ArrayList<>(); - EconomicSet set = EconomicSet.create(Equivalence.IDENTITY); - set.add(1); - set.add(2); - set.add(3); - set.add(4); - set.add(5); - set.add(6); - set.add(7); - set.add(8); - set.add(9); - Iterator i1 = set.iterator(); - while (i1.hasNext()) { - initialList.add(i1.next()); - } - int size = 0; - Iterator i2 = set.iterator(); - while (i2.hasNext()) { - Integer elem = i2.next(); - if (size++ < 8) { - i2.remove(); - } - removalList.add(elem); - } - Iterator i3 = set.iterator(); - while (i3.hasNext()) { - finalList.add(i3.next()); - } - Assert.assertEquals(initialList, removalList); - Assert.assertEquals(1, finalList.size()); - Assert.assertEquals(new Integer(9), finalList.get(0)); - } -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionUtilTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionUtilTest.java Fri Feb 02 17:28:17 2018 -0800 @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2017, 2017, 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 org.graalvm.util.test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import org.graalvm.util.CollectionsUtil; +import org.junit.Assert; +import org.junit.Test; + +public class CollectionUtilTest { + + private static int sum(Iterable iterable) { + int sum = 0; + for (int i : iterable) { + sum += i; + } + return sum; + } + + private static int indexOf(Iterable iterable, int element) { + int index = 0; + for (int i : iterable) { + if (i == element) { + return index; + } + index++; + } + return -1; + } + + @Test + public void testConcat() { + List a = Arrays.asList(1, 2); + List b = Arrays.asList(3, 4, 5); + Assert.assertEquals(sum(CollectionsUtil.concat(a, b)), 15); + Assert.assertEquals(sum(CollectionsUtil.concat(b, a)), 15); + Assert.assertEquals(indexOf(CollectionsUtil.concat(a, b), 5), 4); + Assert.assertEquals(indexOf(CollectionsUtil.concat(b, a), 5), 2); + } + + @Test + public void testMatch() { + String[] array = {"a", "b", "c", "d", "e"}; + Assert.assertTrue(CollectionsUtil.allMatch(array, s -> !s.isEmpty())); + Assert.assertFalse(CollectionsUtil.allMatch(array, s -> !s.startsWith("c"))); + Assert.assertFalse(CollectionsUtil.anyMatch(array, String::isEmpty)); + Assert.assertTrue(CollectionsUtil.anyMatch(array, s -> s.startsWith("c"))); + } + + @Test + public void testFilterToList() { + String[] array = {"a", "b", "", "d", "e"}; + Assert.assertEquals(CollectionsUtil.filterToList(Arrays.asList(array), String::isEmpty).size(), 1); + } + + @Test + public void testFilterAndMapToArray() { + String[] array = {"a", "b", "", "d", "e"}; + String[] newArray = CollectionsUtil.filterAndMapToArray(array, s -> !s.isEmpty(), String::toUpperCase, String[]::new); + Assert.assertArrayEquals(newArray, new String[]{"A", "B", "D", "E"}); + } + + @Test + public void testMapToArray() { + String[] array = {"a", "b", "c", "d", "e"}; + String[] newArray = CollectionsUtil.mapToArray(array, String::toUpperCase, String[]::new); + Assert.assertArrayEquals(newArray, new String[]{"A", "B", "C", "D", "E"}); + } + + @Test + public void testMapAndJoin() { + String[] array = {"a", "b", "c", "d", "e"}; + Assert.assertEquals(CollectionsUtil.mapAndJoin(array, String::toUpperCase, ", "), "A, B, C, D, E"); + Assert.assertEquals(CollectionsUtil.mapAndJoin(array, String::toUpperCase, ", ", "'"), "'A, 'B, 'C, 'D, 'E"); + Assert.assertEquals(CollectionsUtil.mapAndJoin(array, String::toUpperCase, ", ", "'", "'"), "'A', 'B', 'C', 'D', 'E'"); + + Assert.assertEquals(CollectionsUtil.mapAndJoin(Arrays.asList(array), String::toUpperCase, ", "), "A, B, C, D, E"); + Assert.assertEquals(CollectionsUtil.mapAndJoin(Arrays.asList(array), String::toUpperCase, ", ", "'"), "'A, 'B, 'C, 'D, 'E"); + } + + @Test + public void testIterableConcat() { + List i1 = Arrays.asList("1", "2", "3"); + List i2 = Arrays.asList(); + List i3 = Arrays.asList("4", "5"); + List i4 = Arrays.asList(); + List i5 = Arrays.asList("6"); + List iNull = null; + + List actual = new ArrayList<>(); + List expected = new ArrayList<>(); + expected.addAll(i1); + expected.addAll(i2); + expected.addAll(i3); + expected.addAll(i4); + expected.addAll(i5); + Iterable iterable = CollectionsUtil.concat(Arrays.asList(i1, i2, i3, i4, i5)); + for (String s : iterable) { + actual.add(s); + } + Assert.assertEquals(expected, actual); + + Iterator iter = iterable.iterator(); + while (iter.hasNext()) { + iter.next(); + } + try { + iter.next(); + Assert.fail("Expected NoSuchElementException"); + } catch (NoSuchElementException e) { + // Expected + } + try { + CollectionsUtil.concat(i1, iNull); + Assert.fail("Expected NullPointerException"); + } catch (NullPointerException e) { + // Expected + } + + Iterable emptyIterable = CollectionsUtil.concat(Collections.emptyList()); + Assert.assertFalse(emptyIterable.iterator().hasNext()); + } + +} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/CollectionsUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/CollectionsUtil.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/CollectionsUtil.java Fri Feb 02 17:28:17 2018 -0800 @@ -37,7 +37,10 @@ /** * This class contains utility methods for commonly used functional patterns for collections. */ -public class CollectionsUtil { +public final class CollectionsUtil { + + private CollectionsUtil() { + } /** * Concatenates two iterables into a single iterable. The iterator exposed by the returned @@ -93,10 +96,26 @@ }; } + /** + * Returns whether all elements in {@code inputs} match {@code predicate}. May not evaluate + * {@code predicate} on all elements if not necessary for determining the result. If + * {@code inputs} is empty then {@code true} is returned and {@code predicate} is not evaluated. + * + * @return {@code true} if either all elements in {@code inputs} match {@code predicate} or + * {@code inputs} is empty, otherwise {@code false}. + */ public static boolean allMatch(T[] inputs, Predicate predicate) { return allMatch(Arrays.asList(inputs), predicate); } + /** + * Returns whether all elements in {@code inputs} match {@code predicate}. May not evaluate + * {@code predicate} on all elements if not necessary for determining the result. If + * {@code inputs} is empty then {@code true} is returned and {@code predicate} is not evaluated. + * + * @return {@code true} if either all elements in {@code inputs} match {@code predicate} or + * {@code inputs} is empty, otherwise {@code false}. + */ public static boolean allMatch(Iterable inputs, Predicate predicate) { for (T t : inputs) { if (!predicate.test(t)) { @@ -106,10 +125,28 @@ return true; } + /** + * Returns whether any elements in {@code inputs} match {@code predicate}. May not evaluate + * {@code predicate} on all elements if not necessary for determining the result. If + * {@code inputs} is empty then {@code false} is returned and {@code predicate} is not + * evaluated. + * + * @return {@code true} if any elements in {@code inputs} match {@code predicate}, otherwise + * {@code false}. + */ public static boolean anyMatch(T[] inputs, Predicate predicate) { return anyMatch(Arrays.asList(inputs), predicate); } + /** + * Returns whether any elements in {@code inputs} match {@code predicate}. May not evaluate + * {@code predicate} on all elements if not necessary for determining the result. If + * {@code inputs} is empty then {@code false} is returned and {@code predicate} is not + * evaluated. + * + * @return {@code true} if any elements in {@code inputs} match {@code predicate}, otherwise + * {@code false}. + */ public static boolean anyMatch(Iterable inputs, Predicate predicate) { for (T t : inputs) { if (predicate.test(t)) { @@ -119,10 +156,21 @@ return false; } + /** + * Returns a new list consisting of the elements in {@code inputs} that match {@code predicate}. + * + * @return the new list. + */ public static List filterToList(List inputs, Predicate predicate) { return filterToList(inputs, predicate, ArrayList::new); } + /** + * Appends elements of {@code inputs} that match {@code predicate} to the list generated by + * {@code listGenerator}. + * + * @return the list generated by {@code listGenerator}. + */ public static List filterToList(List inputs, Predicate predicate, Supplier> listGenerator) { List resultList = listGenerator.get(); for (T t : inputs) { @@ -134,8 +182,10 @@ } /** - * Filters the inputs, maps them given the mapping function and adds them in the array provided - * by the generator. + * Filters {@code inputs} with {@code predicate}, applies {@code mapper} and adds them in the + * array provided by {@code arrayGenerator}. + * + * @return the array provided by {@code arrayGenerator}. */ public static R[] filterAndMapToArray(T[] inputs, Predicate predicate, Function mapper, IntFunction arrayGenerator) { List resultList = new ArrayList<>(); @@ -148,13 +198,21 @@ } /** - * Maps the inputs given the mapping function and adds them in the array provided by the - * generator. + * Applies {@code mapper} on the elements in {@code inputs} and adds them in the array provided + * by {@code arrayGenerator}. + * + * @return the array provided by {@code arrayGenerator}. */ public static R[] mapToArray(T[] inputs, Function mapper, IntFunction arrayGenerator) { return mapToArray(Arrays.asList(inputs), mapper, arrayGenerator); } + /** + * Applies {@code mapper} on the elements in {@code inputs} and adds them in the array provided + * by {@code arrayGenerator}. + * + * @return the array provided by {@code arrayGenerator}. + */ public static R[] mapToArray(Collection inputs, Function mapper, IntFunction arrayGenerator) { R[] result = arrayGenerator.apply(inputs.size()); int idx = 0; @@ -164,26 +222,62 @@ return result; } + /** + * Applies {@code mapper} on the elements in {@code inputs}, and joins them together separated + * by {@code delimiter}. + * + * @return a new String that is composed from {@code inputs}. + */ public static String mapAndJoin(T[] inputs, Function mapper, String delimiter) { return mapAndJoin(Arrays.asList(inputs), mapper, delimiter, "", ""); } + /** + * Applies {@code mapper} on the elements in {@code inputs}, and joins them together separated + * by {@code delimiter} and starting with {@code prefix}. + * + * @return a new String that is composed from {@code inputs}. + */ public static String mapAndJoin(T[] inputs, Function mapper, String delimiter, String prefix) { return mapAndJoin(Arrays.asList(inputs), mapper, delimiter, prefix, ""); } + /** + * Applies {@code mapper} on the elements in {@code inputs}, and joins them together separated + * by {@code delimiter} and starting with {@code prefix} and ending with {@code suffix}. + * + * @return a new String that is composed from {@code inputs}. + */ public static String mapAndJoin(T[] inputs, Function mapper, String delimiter, String prefix, String suffix) { return mapAndJoin(Arrays.asList(inputs), mapper, delimiter, prefix, suffix); } + /** + * Applies {@code mapper} on the elements in {@code inputs}, and joins them together separated + * by {@code delimiter}. + * + * @return a new String that is composed from {@code inputs}. + */ public static String mapAndJoin(Iterable inputs, Function mapper, String delimiter) { return mapAndJoin(inputs, mapper, delimiter, "", ""); } + /** + * Applies {@code mapper} on the elements in {@code inputs}, and joins them together separated + * by {@code delimiter} and starting with {@code prefix}. + * + * @return a new String that is composed from {@code inputs}. + */ public static String mapAndJoin(Iterable inputs, Function mapper, String delimiter, String prefix) { return mapAndJoin(inputs, mapper, delimiter, prefix, ""); } + /** + * Applies {@code mapper} on the elements in {@code inputs}, and joins them together separated + * by {@code delimiter} and starting with {@code prefix} and ending with {@code suffix}. + * + * @return a new String that is composed from {@code inputs}. + */ public static String mapAndJoin(Iterable inputs, Function mapper, String delimiter, String prefix, String suffix) { StringBuilder strb = new StringBuilder(); String sep = ""; @@ -193,4 +287,5 @@ } return strb.toString(); } + } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicMap.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicMap.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2017, 2017, 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 org.graalvm.util; - -import java.util.Iterator; -import java.util.Map; -import java.util.function.BiFunction; - -import org.graalvm.util.impl.EconomicMapImpl; - -/** - * Memory efficient map data structure. - */ -public interface EconomicMap extends UnmodifiableEconomicMap { - - V put(K key, V value); - - default void putAll(EconomicMap other) { - MapCursor e = other.getEntries(); - while (e.advance()) { - put(e.getKey(), e.getValue()); - } - } - - void clear(); - - V removeKey(K key); - - @Override - MapCursor getEntries(); - - void replaceAll(BiFunction function); - - default void putAll(UnmodifiableEconomicMap other) { - UnmodifiableMapCursor entry = other.getEntries(); - while (entry.advance()) { - put(entry.getKey(), entry.getValue()); - } - } - - /** - * Creates a new map that guarantees insertion order on the key set with the default - * {@link Equivalence#DEFAULT} comparison strategy for keys. - */ - static EconomicMap create() { - return EconomicMap.create(Equivalence.DEFAULT); - } - - /** - * Creates a new map that guarantees insertion order on the key set with the default - * {@link Equivalence#DEFAULT} comparison strategy for keys and initializes with a specified - * capacity. - */ - static EconomicMap create(int initialCapacity) { - return EconomicMap.create(Equivalence.DEFAULT, initialCapacity); - } - - /** - * Creates a new map that guarantees insertion order on the key set with the given comparison - * strategy for keys. - */ - static EconomicMap create(Equivalence strategy) { - return EconomicMapImpl.create(strategy); - } - - /** - * Creates a new map that guarantees insertion order on the key set with the default - * {@link Equivalence#DEFAULT} comparison strategy for keys and copies all elements from the - * specified existing map. - */ - static EconomicMap create(UnmodifiableEconomicMap m) { - return EconomicMap.create(Equivalence.DEFAULT, m); - } - - /** - * Creates a new map that guarantees insertion order on the key set and copies all elements from - * the specified existing map. - */ - static EconomicMap create(Equivalence strategy, UnmodifiableEconomicMap m) { - return EconomicMapImpl.create(strategy, m); - } - - /** - * Creates a new map that guarantees insertion order on the key set and initializes with a - * specified capacity. - */ - static EconomicMap create(Equivalence strategy, int initialCapacity) { - return EconomicMapImpl.create(strategy, initialCapacity); - } - - /** - * Wraps an existing {@link java.util.Map} as an {@link org.graalvm.util.EconomicMap}. - */ - static EconomicMap wrapMap(Map map) { - return new EconomicMap() { - - @Override - public V get(K key) { - V result = map.get(key); - return result; - } - - @Override - public V put(K key, V value) { - V result = map.put(key, value); - return result; - } - - @Override - public int size() { - int result = map.size(); - return result; - } - - @Override - public boolean containsKey(K key) { - return map.containsKey(key); - } - - @Override - public void clear() { - map.clear(); - } - - @Override - public V removeKey(K key) { - V result = map.remove(key); - return result; - } - - @Override - public Iterable getValues() { - return map.values(); - } - - @Override - public Iterable getKeys() { - return map.keySet(); - } - - @Override - public boolean isEmpty() { - return map.isEmpty(); - } - - @Override - public MapCursor getEntries() { - Iterator> iterator = map.entrySet().iterator(); - return new MapCursor() { - - private Map.Entry current; - - @Override - public boolean advance() { - boolean result = iterator.hasNext(); - if (result) { - current = iterator.next(); - } - - return result; - } - - @Override - public K getKey() { - return current.getKey(); - } - - @Override - public V getValue() { - return current.getValue(); - } - - @Override - public void remove() { - iterator.remove(); - } - }; - } - - @Override - public void replaceAll(BiFunction function) { - map.replaceAll(function); - } - }; - } -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicSet.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicSet.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2017, 2017, 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 org.graalvm.util; - -import java.util.Iterator; - -import org.graalvm.util.impl.EconomicMapImpl; - -/** - * Memory efficient set data structure. - */ -public interface EconomicSet extends UnmodifiableEconomicSet { - - boolean add(E element); - - void remove(E element); - - void clear(); - - default void addAll(EconomicSet values) { - addAll(values.iterator()); - } - - default void addAll(Iterable values) { - addAll(values.iterator()); - } - - default void addAll(Iterator values) { - while (values.hasNext()) { - add(values.next()); - } - } - - default void removeAll(EconomicSet values) { - removeAll(values.iterator()); - } - - default void removeAll(Iterable values) { - removeAll(values.iterator()); - } - - default void removeAll(Iterator values) { - while (values.hasNext()) { - remove(values.next()); - } - } - - default void retainAll(EconomicSet values) { - Iterator iterator = iterator(); - while (iterator.hasNext()) { - E key = iterator.next(); - if (!values.contains(key)) { - iterator.remove(); - } - } - } - - /** - * Creates a new set guaranteeing insertion order when iterating over its elements with the - * default {@link Equivalence#DEFAULT} comparison strategy. - */ - static EconomicSet create() { - return EconomicSet.create(Equivalence.DEFAULT); - } - - /** - * Creates a new set guaranteeing insertion order when iterating over its elements. - */ - static EconomicSet create(Equivalence strategy) { - return EconomicMapImpl.create(strategy); - } - - /** - * Creates a new set guaranteeing insertion order when iterating over its elements with the - * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the - * specified collection. - */ - static EconomicSet create(int initialCapacity) { - return EconomicSet.create(Equivalence.DEFAULT, initialCapacity); - } - - /** - * Creates a new set guaranteeing insertion order when iterating over its elements with the - * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the - * specified collection. - */ - static EconomicSet create(UnmodifiableEconomicSet c) { - return EconomicSet.create(Equivalence.DEFAULT, c); - } - - /** - * Creates a new set guaranteeing insertion order when iterating over its elements and - * initializes with the given capacity. - */ - static EconomicSet create(Equivalence strategy, int initialCapacity) { - return EconomicMapImpl.create(strategy, initialCapacity); - } - - /** - * Creates a new set guaranteeing insertion order when iterating over its elements and inserts - * all elements of the specified collection. - */ - static EconomicSet create(Equivalence strategy, UnmodifiableEconomicSet c) { - return EconomicMapImpl.create(strategy, c); - } -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Equivalence.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Equivalence.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2017, 2017, 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 org.graalvm.util; - -/** - * Strategy for comparing two objects. Default predefined strategies are {@link #DEFAULT}, - * {@link #IDENTITY}, and {@link #IDENTITY_WITH_SYSTEM_HASHCODE}. - */ -public abstract class Equivalence { - - /** - * Default equivalence calling {@link #equals(Object)} to check equality and {@link #hashCode()} - * for obtaining hash values. Do not change the logic of this class as it may be inlined in - * other places. - */ - public static final Equivalence DEFAULT = new Equivalence() { - - @Override - public boolean equals(Object a, Object b) { - return a.equals(b); - } - - @Override - public int hashCode(Object o) { - return o.hashCode(); - } - }; - - /** - * Identity equivalence using {@code ==} to check equality and {@link #hashCode()} for obtaining - * hash values. Do not change the logic of this class as it may be inlined in other places. - */ - public static final Equivalence IDENTITY = new Equivalence() { - - @Override - public boolean equals(Object a, Object b) { - return a == b; - } - - @Override - public int hashCode(Object o) { - return o.hashCode(); - } - }; - - /** - * Identity equivalence using {@code ==} to check equality and - * {@link System#identityHashCode(Object)} for obtaining hash values. Do not change the logic of - * this class as it may be inlined in other places. - */ - public static final Equivalence IDENTITY_WITH_SYSTEM_HASHCODE = new Equivalence() { - - @Override - public boolean equals(Object a, Object b) { - return a == b; - } - - @Override - public int hashCode(Object o) { - return System.identityHashCode(o); - } - }; - - /** - * Subclass for creating custom equivalence definitions. - */ - protected Equivalence() { - } - - public abstract boolean equals(Object a, Object b); - - public abstract int hashCode(Object o); -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/MapCursor.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/MapCursor.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2017, 2017, 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 org.graalvm.util; - -/** - * Cursor to iterate over a mutable map. - */ -public interface MapCursor extends UnmodifiableMapCursor { - /** - * Remove the current entry from the map. May only be called once. After calling - * {@link #remove()}, it is no longer valid to call {@link #getKey()} or {@link #getValue()} on - * the current entry. - */ - void remove(); -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java Fri Feb 02 17:28:17 2018 -0800 @@ -26,6 +26,9 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; + /** * Calculates approximate estimates of the size of an object graph. * @@ -193,8 +196,8 @@ } else { size.recordPointer(); if (maxDepth > 1) { - f.setAccessible(true); try { + f.setAccessible(true); Object inner = f.get(o); if (inner != null) { if (depth < maxDepth && !identityHashMap.containsKey(inner)) { @@ -205,6 +208,14 @@ } } catch (IllegalArgumentException | IllegalAccessException e) { throw new UnsupportedOperationException("Must have access privileges to traverse object graph"); + } catch (RuntimeException e) { + if ("java.lang.reflect.InaccessibleObjectException".equals(e.getClass().getName())) { + // This is a newly introduced exception in JDK9 and thus + // cannot be declared in the catch clause. + throw new UnsupportedOperationException("Target class is not exported to the current module.", e); + } else { + throw e; + } } } } diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Pair.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Pair.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2017, 2017, 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 org.graalvm.util; - -import java.util.Objects; - -/** - * Utility class representing a pair of values. - */ -public final class Pair { - private static final Pair EMPTY = new Pair<>(null, null); - - private final L left; - private final R right; - - @SuppressWarnings("unchecked") - public static Pair empty() { - return (Pair) EMPTY; - } - - public static Pair createLeft(L left) { - if (left == null) { - return empty(); - } else { - return new Pair<>(left, null); - } - } - - public static Pair createRight(R right) { - if (right == null) { - return empty(); - } else { - return new Pair<>(null, right); - } - } - - public static Pair create(L left, R right) { - if (right == null && left == null) { - return empty(); - } else { - return new Pair<>(left, right); - } - } - - private Pair(L left, R right) { - this.left = left; - this.right = right; - } - - public L getLeft() { - return left; - } - - public R getRight() { - return right; - } - - @Override - public int hashCode() { - return Objects.hashCode(left) + 31 * Objects.hashCode(right); - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (obj instanceof Pair) { - Pair pair = (Pair) obj; - return Objects.equals(left, pair.left) && Objects.equals(right, pair.right); - } - - return false; - } - - @Override - public String toString() { - return String.format("(%s, %s)", left, right); - } -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicMap.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicMap.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017, 2017, 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 org.graalvm.util; - -/** - * Unmodifiable memory efficient map data structure. - */ -public interface UnmodifiableEconomicMap { - - V get(K key); - - default V get(K key, V defaultValue) { - V v = get(key); - if (v == null) { - return defaultValue; - } - return v; - } - - boolean containsKey(K key); - - int size(); - - boolean isEmpty(); - - Iterable getValues(); - - Iterable getKeys(); - - UnmodifiableMapCursor getEntries(); -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicSet.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicSet.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2017, 2017, 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 org.graalvm.util; - -/** - * Unmodifiable memory efficient set data structure. - */ -public interface UnmodifiableEconomicSet extends Iterable { - - boolean contains(E element); - - int size(); - - boolean isEmpty(); - - default E[] toArray(E[] target) { - if (target.length != size()) { - throw new UnsupportedOperationException("Length of target array must equal the size of the set."); - } - - int index = 0; - for (E element : this) { - target[index++] = element; - } - - return target; - } -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableMapCursor.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableMapCursor.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2017, 2017, 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 org.graalvm.util; - -/** - * Cursor to iterate over a map without changing its contents. - */ -public interface UnmodifiableMapCursor { - /** - * Advances to the next entry. - * - * @return {@code true} if a next entry exists, {@code false} if there is no next entry. - */ - boolean advance(); - - /** - * The key of the current entry. - */ - K getKey(); - - /** - * The value of the current entry. - */ - V getValue(); -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/impl/EconomicMapImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/impl/EconomicMapImpl.java Fri Feb 02 10:37:48 2018 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,852 +0,0 @@ -/* - * Copyright (c) 2017, 2017, 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 org.graalvm.util.impl; - -import java.util.Iterator; -import java.util.Objects; -import java.util.function.BiFunction; - -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; -import org.graalvm.util.EconomicSet; -import org.graalvm.util.UnmodifiableEconomicMap; -import org.graalvm.util.UnmodifiableEconomicSet; -import org.graalvm.util.MapCursor; - -/** - * Implementation of a map with a memory-efficient structure that always preserves insertion order - * when iterating over keys. Particularly efficient when number of entries is 0 or smaller equal - * {@link #INITIAL_CAPACITY} or smaller 256. - * - * The key/value pairs are kept in an expanding flat object array with keys at even indices and - * values at odd indices. If the map has smaller or equal to {@link #HASH_THRESHOLD} entries, there - * is no additional hash data structure and comparisons are done via linear checking of the - * key/value pairs. For the case where the equality check is particularly cheap (e.g., just an - * object identity comparison), this limit below which the map is without an actual hash table is - * higher and configured at {@link #HASH_THRESHOLD_IDENTITY_COMPARE}. - * - * When the hash table needs to be constructed, the field {@link #hashArray} becomes a new hash - * array where an entry of 0 means no hit and otherwise denotes the entry number in the - * {@link #entries} array. The hash array is interpreted as an actual byte array if the indices fit - * within 8 bit, or as an array of short values if the indices fit within 16 bit, or as an array of - * integer values in other cases. - * - * Hash collisions are handled by chaining a linked list of {@link CollisionLink} objects that take - * the place of the values in the {@link #entries} array. - * - * Removing entries will put {@code null} into the {@link #entries} array. If the occupation of the - * map falls below a specific threshold, the map will be compressed via the - * {@link #maybeCompress(int)} method. - */ -public final class EconomicMapImpl implements EconomicMap, EconomicSet { - - /** - * Initial number of key/value pair entries that is allocated in the first entries array. - */ - private static final int INITIAL_CAPACITY = 4; - - /** - * Maximum number of entries that are moved linearly forward if a key is removed. - */ - private static final int COMPRESS_IMMEDIATE_CAPACITY = 8; - - /** - * Minimum number of key/value pair entries added when the entries array is increased in size. - */ - private static final int MIN_CAPACITY_INCREASE = 8; - - /** - * Number of entries above which a hash table is created. - */ - private static final int HASH_THRESHOLD = 4; - - /** - * Number of entries above which a hash table is created when equality can be checked with - * object identity. - */ - private static final int HASH_THRESHOLD_IDENTITY_COMPARE = 8; - - /** - * Maximum number of entries allowed in the map. - */ - private static final int MAX_ELEMENT_COUNT = Integer.MAX_VALUE >> 1; - - /** - * Number of entries above which more than 1 byte is necessary for the hash index. - */ - private static final int LARGE_HASH_THRESHOLD = ((1 << Byte.SIZE) << 1); - - /** - * Number of entries above which more than 2 bytes are are necessary for the hash index. - */ - private static final int VERY_LARGE_HASH_THRESHOLD = (LARGE_HASH_THRESHOLD << Byte.SIZE); - - /** - * Total number of entries (actual entries plus deleted entries). - */ - private int totalEntries; - - /** - * Number of deleted entries. - */ - private int deletedEntries; - - /** - * Entries array with even indices storing keys and odd indices storing values. - */ - private Object[] entries; - - /** - * Hash array that is interpreted either as byte or short or int array depending on number of - * map entries. - */ - private byte[] hashArray; - - /** - * The strategy used for comparing keys or {@code null} for denoting special strategy - * {@link Equivalence#IDENTITY}. - */ - private final Equivalence strategy; - - /** - * Intercept method for debugging purposes. - */ - private static EconomicMapImpl intercept(EconomicMapImpl map) { - return map; - } - - public static EconomicMapImpl create(Equivalence strategy) { - return intercept(new EconomicMapImpl<>(strategy)); - } - - public static EconomicMapImpl create(Equivalence strategy, int initialCapacity) { - return intercept(new EconomicMapImpl<>(strategy, initialCapacity)); - } - - public static EconomicMapImpl create(Equivalence strategy, UnmodifiableEconomicMap other) { - return intercept(new EconomicMapImpl<>(strategy, other)); - } - - public static EconomicMapImpl create(Equivalence strategy, UnmodifiableEconomicSet other) { - return intercept(new EconomicMapImpl<>(strategy, other)); - } - - private EconomicMapImpl(Equivalence strategy) { - if (strategy == Equivalence.IDENTITY) { - this.strategy = null; - } else { - this.strategy = strategy; - } - } - - private EconomicMapImpl(Equivalence strategy, int initialCapacity) { - this(strategy); - init(initialCapacity); - } - - private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicMap other) { - this(strategy); - if (!initFrom(other)) { - init(other.size()); - putAll(other); - } - } - - private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicSet other) { - this(strategy); - if (!initFrom(other)) { - init(other.size()); - addAll(other); - } - } - - @SuppressWarnings("unchecked") - private boolean initFrom(Object o) { - if (o instanceof EconomicMapImpl) { - EconomicMapImpl otherMap = (EconomicMapImpl) o; - // We are only allowed to directly copy if the strategies of the two maps are the same. - if (strategy == otherMap.strategy) { - totalEntries = otherMap.totalEntries; - deletedEntries = otherMap.deletedEntries; - if (otherMap.entries != null) { - entries = otherMap.entries.clone(); - } - if (otherMap.hashArray != null) { - hashArray = otherMap.hashArray.clone(); - } - return true; - } - } - return false; - } - - private void init(int size) { - if (size > INITIAL_CAPACITY) { - entries = new Object[size << 1]; - } - } - - /** - * Links the collisions. Needs to be immutable class for allowing efficient shallow copy from - * other map on construction. - */ - private static final class CollisionLink { - - CollisionLink(Object value, int next) { - this.value = value; - this.next = next; - } - - final Object value; - - /** - * Index plus one of the next entry in the collision link chain. - */ - final int next; - } - - @SuppressWarnings("unchecked") - @Override - public V get(K key) { - Objects.requireNonNull(key); - - int index = find(key); - if (index != -1) { - return (V) getValue(index); - } - return null; - } - - private int find(K key) { - if (hasHashArray()) { - return findHash(key); - } else { - return findLinear(key); - } - } - - private int findLinear(K key) { - for (int i = 0; i < totalEntries; i++) { - Object entryKey = entries[i << 1]; - if (entryKey != null && compareKeys(key, entryKey)) { - return i; - } - } - return -1; - } - - private boolean compareKeys(Object key, Object entryKey) { - if (key == entryKey) { - return true; - } - if (strategy != null && strategy != Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) { - if (strategy == Equivalence.DEFAULT) { - return key.equals(entryKey); - } else { - return strategy.equals(key, entryKey); - } - } - return false; - } - - private int findHash(K key) { - int index = getHashArray(getHashIndex(key)) - 1; - if (index != -1) { - Object entryKey = getKey(index); - if (compareKeys(key, entryKey)) { - return index; - } else { - Object entryValue = getRawValue(index); - if (entryValue instanceof CollisionLink) { - return findWithCollision(key, (CollisionLink) entryValue); - } - } - } - - return -1; - } - - private int findWithCollision(K key, CollisionLink initialEntryValue) { - int index; - Object entryKey; - CollisionLink entryValue = initialEntryValue; - while (true) { - CollisionLink collisionLink = entryValue; - index = collisionLink.next; - entryKey = getKey(index); - if (compareKeys(key, entryKey)) { - return index; - } else { - Object value = getRawValue(index); - if (value instanceof CollisionLink) { - entryValue = (CollisionLink) getRawValue(index); - } else { - return -1; - } - } - } - } - - private int getHashArray(int index) { - if (entries.length < LARGE_HASH_THRESHOLD) { - return (hashArray[index] & 0xFF); - } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) { - int adjustedIndex = index << 1; - return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8); - } else { - int adjustedIndex = index << 2; - return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8) | ((hashArray[adjustedIndex + 2] & 0xFF) << 16) | ((hashArray[adjustedIndex + 3] & 0xFF) << 24); - } - } - - private void setHashArray(int index, int value) { - if (entries.length < LARGE_HASH_THRESHOLD) { - hashArray[index] = (byte) value; - } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) { - int adjustedIndex = index << 1; - hashArray[adjustedIndex] = (byte) value; - hashArray[adjustedIndex + 1] = (byte) (value >> 8); - } else { - int adjustedIndex = index << 2; - hashArray[adjustedIndex] = (byte) value; - hashArray[adjustedIndex + 1] = (byte) (value >> 8); - hashArray[adjustedIndex + 2] = (byte) (value >> 16); - hashArray[adjustedIndex + 3] = (byte) (value >> 24); - } - } - - private int findAndRemoveHash(Object key) { - int hashIndex = getHashIndex(key); - int index = getHashArray(hashIndex) - 1; - if (index != -1) { - Object entryKey = getKey(index); - if (compareKeys(key, entryKey)) { - Object value = getRawValue(index); - int nextIndex = -1; - if (value instanceof CollisionLink) { - CollisionLink collisionLink = (CollisionLink) value; - nextIndex = collisionLink.next; - } - setHashArray(hashIndex, nextIndex + 1); - return index; - } else { - Object entryValue = getRawValue(index); - if (entryValue instanceof CollisionLink) { - return findAndRemoveWithCollision(key, (CollisionLink) entryValue, index); - } - } - } - - return -1; - } - - private int findAndRemoveWithCollision(Object key, CollisionLink initialEntryValue, int initialIndexValue) { - int index; - Object entryKey; - CollisionLink entryValue = initialEntryValue; - int lastIndex = initialIndexValue; - while (true) { - CollisionLink collisionLink = entryValue; - index = collisionLink.next; - entryKey = getKey(index); - if (compareKeys(key, entryKey)) { - Object value = getRawValue(index); - if (value instanceof CollisionLink) { - CollisionLink thisCollisionLink = (CollisionLink) value; - setRawValue(lastIndex, new CollisionLink(collisionLink.value, thisCollisionLink.next)); - } else { - setRawValue(lastIndex, collisionLink.value); - } - return index; - } else { - Object value = getRawValue(index); - if (value instanceof CollisionLink) { - entryValue = (CollisionLink) getRawValue(index); - lastIndex = index; - } else { - return -1; - } - } - } - } - - private int getHashIndex(Object key) { - int hash; - if (strategy != null && strategy != Equivalence.DEFAULT) { - if (strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) { - hash = System.identityHashCode(key); - } else { - hash = strategy.hashCode(key); - } - } else { - hash = key.hashCode(); - } - hash = hash ^ (hash >>> 16); - return hash & (getHashTableSize() - 1); - } - - @SuppressWarnings("unchecked") - @Override - public V put(K key, V value) { - if (key == null) { - throw new UnsupportedOperationException("null not supported as key!"); - } - int index = find(key); - if (index != -1) { - Object oldValue = getValue(index); - setValue(index, value); - return (V) oldValue; - } - - int nextEntryIndex = totalEntries; - if (entries == null) { - entries = new Object[INITIAL_CAPACITY << 1]; - } else if (entries.length == nextEntryIndex << 1) { - grow(); - - assert entries.length > totalEntries << 1; - // Can change if grow is actually compressing. - nextEntryIndex = totalEntries; - } - - setKey(nextEntryIndex, key); - setValue(nextEntryIndex, value); - totalEntries++; - - if (hasHashArray()) { - // Rehash on collision if hash table is more than three quarters full. - boolean rehashOnCollision = (getHashTableSize() < (size() + (size() >> 1))); - putHashEntry(key, nextEntryIndex, rehashOnCollision); - } else if (totalEntries > getHashThreshold()) { - createHash(); - } - - return null; - } - - /** - * Number of entries above which a hash table should be constructed. - */ - private int getHashThreshold() { - if (strategy == null || strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) { - return HASH_THRESHOLD_IDENTITY_COMPARE; - } else { - return HASH_THRESHOLD; - } - } - - private void grow() { - int entriesLength = entries.length; - int newSize = (entriesLength >> 1) + Math.max(MIN_CAPACITY_INCREASE, entriesLength >> 2); - if (newSize > MAX_ELEMENT_COUNT) { - throw new UnsupportedOperationException("map grown too large!"); - } - Object[] newEntries = new Object[newSize << 1]; - System.arraycopy(entries, 0, newEntries, 0, entriesLength); - entries = newEntries; - if ((entriesLength < LARGE_HASH_THRESHOLD && newEntries.length >= LARGE_HASH_THRESHOLD) || - (entriesLength < VERY_LARGE_HASH_THRESHOLD && newEntries.length > VERY_LARGE_HASH_THRESHOLD)) { - // Rehash in order to change number of bits reserved for hash indices. - createHash(); - } - } - - /** - * Compresses the graph if there is a large number of deleted entries and returns the translated - * new next index. - */ - private int maybeCompress(int nextIndex) { - if (entries.length != INITIAL_CAPACITY << 1 && deletedEntries >= (totalEntries >> 1) + (totalEntries >> 2)) { - return compressLarge(nextIndex); - } - return nextIndex; - } - - /** - * Compresses the graph and returns the translated new next index. - */ - private int compressLarge(int nextIndex) { - int size = INITIAL_CAPACITY; - int remaining = totalEntries - deletedEntries; - - while (size <= remaining) { - size += Math.max(MIN_CAPACITY_INCREASE, size >> 1); - } - - Object[] newEntries = new Object[size << 1]; - int z = 0; - int newNextIndex = remaining; - for (int i = 0; i < totalEntries; ++i) { - Object key = getKey(i); - if (i == nextIndex) { - newNextIndex = z; - } - if (key != null) { - newEntries[z << 1] = key; - newEntries[(z << 1) + 1] = getValue(i); - z++; - } - } - - this.entries = newEntries; - totalEntries = z; - deletedEntries = 0; - if (z <= getHashThreshold()) { - this.hashArray = null; - } else { - createHash(); - } - return newNextIndex; - } - - private int getHashTableSize() { - if (entries.length < LARGE_HASH_THRESHOLD) { - return hashArray.length; - } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) { - return hashArray.length >> 1; - } else { - return hashArray.length >> 2; - } - } - - private void createHash() { - int entryCount = size(); - - // Calculate smallest 2^n that is greater number of entries. - int size = getHashThreshold(); - while (size <= entryCount) { - size <<= 1; - } - - // Give extra size to avoid collisions. - size <<= 1; - - if (this.entries.length >= VERY_LARGE_HASH_THRESHOLD) { - // Every entry has 4 bytes. - size <<= 2; - } else if (this.entries.length >= LARGE_HASH_THRESHOLD) { - // Every entry has 2 bytes. - size <<= 1; - } else { - // Entries are very small => give extra size to further reduce collisions. - size <<= 1; - } - - hashArray = new byte[size]; - for (int i = 0; i < totalEntries; i++) { - Object entryKey = getKey(i); - if (entryKey != null) { - putHashEntry(entryKey, i, false); - } - } - } - - private void putHashEntry(Object key, int entryIndex, boolean rehashOnCollision) { - int hashIndex = getHashIndex(key); - int oldIndex = getHashArray(hashIndex) - 1; - if (oldIndex != -1 && rehashOnCollision) { - this.createHash(); - return; - } - setHashArray(hashIndex, entryIndex + 1); - Object value = getRawValue(entryIndex); - if (oldIndex != -1) { - assert entryIndex != oldIndex : "this cannot happend and would create an endless collision link cycle"; - if (value instanceof CollisionLink) { - CollisionLink collisionLink = (CollisionLink) value; - setRawValue(entryIndex, new CollisionLink(collisionLink.value, oldIndex)); - } else { - setRawValue(entryIndex, new CollisionLink(getRawValue(entryIndex), oldIndex)); - } - } else { - if (value instanceof CollisionLink) { - CollisionLink collisionLink = (CollisionLink) value; - setRawValue(entryIndex, collisionLink.value); - } - } - } - - @Override - public int size() { - return totalEntries - deletedEntries; - } - - @Override - public boolean containsKey(K key) { - return find(key) != -1; - } - - @Override - public void clear() { - entries = null; - hashArray = null; - totalEntries = deletedEntries = 0; - } - - private boolean hasHashArray() { - return hashArray != null; - } - - @SuppressWarnings("unchecked") - @Override - public V removeKey(K key) { - if (key == null) { - throw new UnsupportedOperationException("null not supported as key!"); - } - int index; - if (hasHashArray()) { - index = this.findAndRemoveHash(key); - } else { - index = this.findLinear(key); - } - - if (index != -1) { - Object value = getValue(index); - remove(index); - return (V) value; - } - return null; - } - - /** - * Removes the element at the specific index and returns the index of the next element. This can - * be a different value if graph compression was triggered. - */ - private int remove(int indexToRemove) { - int index = indexToRemove; - int entriesAfterIndex = totalEntries - index - 1; - int result = index + 1; - - // Without hash array, compress immediately. - if (entriesAfterIndex <= COMPRESS_IMMEDIATE_CAPACITY && !hasHashArray()) { - while (index < totalEntries - 1) { - setKey(index, getKey(index + 1)); - setRawValue(index, getRawValue(index + 1)); - index++; - } - result--; - } - - setKey(index, null); - setRawValue(index, null); - if (index == totalEntries - 1) { - // Make sure last element is always non-null. - totalEntries--; - while (index > 0 && getKey(index - 1) == null) { - totalEntries--; - deletedEntries--; - index--; - } - } else { - deletedEntries++; - result = maybeCompress(result); - } - - return result; - } - - private abstract class SparseMapIterator implements Iterator { - - protected int current; - - @Override - public boolean hasNext() { - return current < totalEntries; - } - - @Override - public void remove() { - if (hasHashArray()) { - EconomicMapImpl.this.findAndRemoveHash(getKey(current - 1)); - } - current = EconomicMapImpl.this.remove(current - 1); - } - } - - @Override - public Iterable getValues() { - return new Iterable() { - @Override - public Iterator iterator() { - return new SparseMapIterator() { - @SuppressWarnings("unchecked") - @Override - public V next() { - Object result; - while (true) { - result = getValue(current); - if (result == null && getKey(current) == null) { - // values can be null, double-check if key is also null - current++; - } else { - current++; - break; - } - } - return (V) result; - } - }; - } - }; - } - - @Override - public Iterable getKeys() { - return this; - } - - @Override - public boolean isEmpty() { - return this.size() == 0; - } - - @Override - public MapCursor getEntries() { - return new MapCursor() { - int current = -1; - - @Override - public boolean advance() { - current++; - if (current >= totalEntries) { - return false; - } else { - while (EconomicMapImpl.this.getKey(current) == null) { - // Skip over null entries - current++; - } - return true; - } - } - - @SuppressWarnings("unchecked") - @Override - public K getKey() { - return (K) EconomicMapImpl.this.getKey(current); - } - - @SuppressWarnings("unchecked") - @Override - public V getValue() { - return (V) EconomicMapImpl.this.getValue(current); - } - - @Override - public void remove() { - if (hasHashArray()) { - EconomicMapImpl.this.findAndRemoveHash(EconomicMapImpl.this.getKey(current)); - } - current = EconomicMapImpl.this.remove(current) - 1; - } - }; - } - - @SuppressWarnings("unchecked") - @Override - public void replaceAll(BiFunction function) { - for (int i = 0; i < totalEntries; i++) { - Object entryKey = getKey(i); - if (entryKey != null) { - Object newValue = function.apply((K) entryKey, (V) getValue(i)); - setValue(i, newValue); - } - } - } - - private Object getKey(int index) { - return entries[index << 1]; - } - - private void setKey(int index, Object newValue) { - entries[index << 1] = newValue; - } - - private void setValue(int index, Object newValue) { - Object oldValue = getRawValue(index); - if (oldValue instanceof CollisionLink) { - CollisionLink collisionLink = (CollisionLink) oldValue; - setRawValue(index, new CollisionLink(newValue, collisionLink.next)); - } else { - setRawValue(index, newValue); - } - } - - private void setRawValue(int index, Object newValue) { - entries[(index << 1) + 1] = newValue; - } - - private Object getRawValue(int index) { - return entries[(index << 1) + 1]; - } - - private Object getValue(int index) { - Object object = getRawValue(index); - if (object instanceof CollisionLink) { - return ((CollisionLink) object).value; - } - return object; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("map(size=").append(size()).append(", {"); - MapCursor cursor = getEntries(); - while (cursor.advance()) { - builder.append("(").append(cursor.getKey()).append(",").append(cursor.getValue()).append("),"); - } - builder.append("})"); - return builder.toString(); - } - - @Override - public Iterator iterator() { - return new SparseMapIterator() { - @SuppressWarnings("unchecked") - @Override - public K next() { - Object result; - while ((result = getKey(current++)) == null) { - // skip null entries - } - return (K) result; - } - }; - } - - @Override - public boolean contains(K element) { - return containsKey(element); - } - - @SuppressWarnings("unchecked") - @Override - public boolean add(K element) { - return put(element, (V) element) == null; - } - - @Override - public void remove(K element) { - removeKey(element); - } -} diff -r 5bce1b7e7800 -r 47f19ff9903c src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml Fri Feb 02 10:37:48 2018 -0500 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml Fri Feb 02 17:28:17 2018 -0800 @@ -40,7 +40,7 @@ - +