diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index f436b44a4c1..b087371a7b3 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -493,6 +493,7 @@ jdk.internal.vm.compiler_ADD_JAVAC_FLAGS += -parameters -XDstringConcat=inline \ # 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 @@ jdk.internal.vm.compiler_EXCLUDES += \ 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 --git a/make/CompileToolsHotspot.gmk b/make/CompileToolsHotspot.gmk index 1ccc3e2a31b..54ab9ae0dfb 100644 --- a/make/CompileToolsHotspot.gmk +++ b/make/CompileToolsHotspot.gmk @@ -48,6 +48,7 @@ ifeq ($(INCLUDE_GRAAL), true) 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 @@ ifeq ($(INCLUDE_GRAAL), true) $(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 @@ ifeq ($(INCLUDE_GRAAL), true) 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 --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java index af24057bb73..bd3832e7f45 100644 --- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java @@ -143,7 +143,7 @@ final class DataPatchProcessor { 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 --git a/src/jdk.internal.vm.compiler/.mx.graal/suite.py b/src/jdk.internal.vm.compiler/.mx.graal/suite.py index b1dc74b7d5f..bad46679b02 100644 --- a/src/jdk.internal.vm.compiler/.mx.graal/suite.py +++ b/src/jdk.internal.vm.compiler/.mx.graal/suite.py @@ -82,6 +82,24 @@ suite = { "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 @@ suite = { "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 @@ suite = { "dependencies" : [ "mx:JUNIT", "org.graalvm.util", + "org.graalvm.compiler.core.test", ], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", @@ -970,10 +992,11 @@ suite = { "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 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ + "org.graalvm.collections", "org.graalvm.compiler.debug", "org.graalvm.word", ], @@ -1037,7 +1061,6 @@ suite = { "sourceDirs" : ["src"], "dependencies" : [ "org.graalvm.compiler.debug", - "org.graalvm.util", "mx:JUNIT", ], "checkstyle" : "org.graalvm.compiler.graph", @@ -1225,11 +1248,11 @@ suite = { "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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapImplTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapImplTest.java new file mode 100644 index 00000000000..68a12f572a1 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapImplTest.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapLargeTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapLargeTest.java new file mode 100644 index 00000000000..aa651d75515 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapLargeTest.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapTest.java new file mode 100644 index 00000000000..b6449528a2b --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapTest.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicSetTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicSetTest.java new file mode 100644 index 00000000000..9434a8bc7b6 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicSetTest.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EquivalenceTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EquivalenceTest.java new file mode 100644 index 00000000000..7af76d44b67 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EquivalenceTest.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionCategory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/PairTest.java similarity index 52% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionCategory.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/PairTest.java index fddb093576c..730d1d4a6cb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionCategory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/PairTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,34 +22,31 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.options; +package org.graalvm.collections.test; -/** - * Categorizes options according to user relevance. - * - * @since 1.0 - */ -public enum OptionCategory { +import org.graalvm.collections.Pair; +import org.junit.Assert; +import org.junit.Test; - /** - * An option common for users to apply. - * - * @since 1.0 - */ - USER, +public class PairTest { - /** - * An option only relevant in corner cases and for fine-tuning. - * - * @since 1.0 - */ - EXPERT, + @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)); + } - /** - * An option only relevant when debugging language or instrument implementations. - * - * @since 1.0 - */ - DEBUG + @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicMap.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java similarity index 74% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicMap.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java index 46b0da8a1b8..4eae215ca44 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicMap.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java @@ -4,7 +4,9 @@ * * 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. + * 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 @@ -20,21 +22,34 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.util; +package org.graalvm.collections; import java.util.Iterator; import java.util.Map; import java.util.function.BiFunction; -import org.graalvm.util.impl.EconomicMapImpl; - /** * 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()) { @@ -42,15 +57,11 @@ public interface EconomicMap extends UnmodifiableEconomicMap { } } - void clear(); - - V removeKey(K key); - - @Override - MapCursor getEntries(); - - void replaceAll(BiFunction function); - + /** + * 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()) { @@ -58,9 +69,45 @@ public interface EconomicMap extends UnmodifiableEconomicMap { } } + /** + * 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); @@ -70,6 +117,8 @@ public interface EconomicMap extends UnmodifiableEconomicMap { * 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); @@ -78,15 +127,19 @@ public interface EconomicMap extends UnmodifiableEconomicMap { /** * 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); + 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); @@ -95,21 +148,27 @@ public interface EconomicMap extends UnmodifiableEconomicMap { /** * 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); + 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); + return EconomicMapImpl.create(strategy, initialCapacity, false); } /** - * Wraps an existing {@link java.util.Map} as an {@link org.graalvm.util.EconomicMap}. + * Wraps an existing {@link Map} as an {@link EconomicMap}. + * + * @since 1.0 */ static EconomicMap wrapMap(Map map) { return new EconomicMap() { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/impl/EconomicMapImpl.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMapImpl.java similarity index 94% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/impl/EconomicMapImpl.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMapImpl.java index 272bad77de1..827fc09df31 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/impl/EconomicMapImpl.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMapImpl.java @@ -4,7 +4,9 @@ * * 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. + * 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 @@ -20,19 +22,12 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.util.impl; +package org.graalvm.collections; 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 @@ -58,7 +53,7 @@ import org.graalvm.util.MapCursor; * map falls below a specific threshold, the map will be compressed via the * {@link #maybeCompress(int)} method. */ -public final class EconomicMapImpl implements EconomicMap, EconomicSet { +final class EconomicMapImpl implements EconomicMap, EconomicSet { /** * Initial number of key/value pair entries that is allocated in the first entries array. @@ -135,45 +130,46 @@ public final class EconomicMapImpl implements EconomicMap, EconomicS return map; } - public static EconomicMapImpl create(Equivalence strategy) { - return intercept(new EconomicMapImpl<>(strategy)); + public static EconomicMapImpl create(Equivalence strategy, boolean isSet) { + return intercept(new EconomicMapImpl<>(strategy, isSet)); } - public static EconomicMapImpl create(Equivalence strategy, int initialCapacity) { - return intercept(new EconomicMapImpl<>(strategy, initialCapacity)); + 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) { - return intercept(new EconomicMapImpl<>(strategy, other)); + 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) { - return intercept(new EconomicMapImpl<>(strategy, other)); + public static EconomicMapImpl create(Equivalence strategy, UnmodifiableEconomicSet other, boolean isSet) { + return intercept(new EconomicMapImpl<>(strategy, other, isSet)); } - private EconomicMapImpl(Equivalence strategy) { + 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) { - this(strategy); + private EconomicMapImpl(Equivalence strategy, int initialCapacity, boolean isSet) { + this(strategy, isSet); init(initialCapacity); } - private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicMap other) { - this(strategy); + 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) { - this(strategy); + private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicSet other, boolean isSet) { + this(strategy, isSet); if (!initFrom(other)) { init(other.size()); addAll(other); @@ -807,13 +803,22 @@ public final class EconomicMapImpl implements EconomicMap, EconomicS return object; } + private final boolean isSet; + @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("map(size=").append(size()).append(", {"); + builder.append(isSet ? "set(size=" : "map(size=").append(size()).append(", {"); + String sep = ""; MapCursor cursor = getEntries(); while (cursor.advance()) { - builder.append("(").append(cursor.getKey()).append(",").append(cursor.getValue()).append("),"); + 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(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicSet.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java similarity index 56% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicSet.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java index 67a66fc0002..32b2af28dcc 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicSet.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java @@ -4,7 +4,9 @@ * * 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. + * 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 @@ -20,56 +22,109 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.util; +package org.graalvm.collections; import java.util.Iterator; -import org.graalvm.util.impl.EconomicMapImpl; - /** * 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(); - default void addAll(EconomicSet values) { - addAll(values.iterator()); + /** + * 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()); } - default void addAll(Iterator values) { - while (values.hasNext()) { - add(values.next()); + /** + * 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()); } } - default void removeAll(EconomicSet values) { - removeAll(values.iterator()); + /** + * 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()); } - default void removeAll(Iterator values) { - while (values.hasNext()) { - remove(values.next()); + /** + * 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()); } } - default void retainAll(EconomicSet values) { + /** + * 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 (!values.contains(key)) { + if (!other.contains(key)) { iterator.remove(); } } @@ -78,6 +133,8 @@ public interface EconomicSet extends UnmodifiableEconomicSet { /** * 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); @@ -85,15 +142,19 @@ public interface EconomicSet extends UnmodifiableEconomicSet { /** * Creates a new set guaranteeing insertion order when iterating over its elements. + * + * @since 1.0 */ static EconomicSet create(Equivalence strategy) { - return EconomicMapImpl.create(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); @@ -103,6 +164,8 @@ public interface EconomicSet extends UnmodifiableEconomicSet { * 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); @@ -111,16 +174,20 @@ public interface EconomicSet extends UnmodifiableEconomicSet { /** * 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); + 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); + return EconomicMapImpl.create(strategy, c, true); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Equivalence.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Equivalence.java similarity index 82% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Equivalence.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Equivalence.java index 21d9c9a64ac..ddade583082 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Equivalence.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Equivalence.java @@ -4,7 +4,9 @@ * * 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. + * 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 @@ -20,11 +22,13 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.util; +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 { @@ -32,6 +36,8 @@ 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() { @@ -49,6 +55,8 @@ public abstract class Equivalence { /** * 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() { @@ -67,6 +75,8 @@ public abstract class Equivalence { * 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() { @@ -83,11 +93,24 @@ public abstract class Equivalence { /** * 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/MapCursor.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/MapCursor.java similarity index 83% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/MapCursor.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/MapCursor.java index 872e24f30a3..974a56ac3dc 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/MapCursor.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/MapCursor.java @@ -4,7 +4,9 @@ * * 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. + * 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 @@ -20,16 +22,20 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.util; +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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Pair.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Pair.java similarity index 65% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Pair.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Pair.java index ca6c715c4d3..6cba3764391 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Pair.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Pair.java @@ -4,7 +4,9 @@ * * 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. + * 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 @@ -20,24 +22,39 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.util; +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(); @@ -46,6 +63,13 @@ public final class Pair { } } + /** + * 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(); @@ -54,6 +78,13 @@ public final class Pair { } } + /** + * 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(); @@ -67,19 +98,39 @@ public final class Pair { 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) { @@ -95,6 +146,11 @@ public final class Pair { return false; } + /** + * {@inheritDoc} + * + * @since 1.0 + */ @Override public String toString() { return String.format("(%s, %s)", left, right); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicMap.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicMap.java new file mode 100644 index 00000000000..f246f9626f9 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicMap.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionValues.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicSet.java similarity index 51% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionValues.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicSet.java index 0342356db1a..aa9aa76e42a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionValues.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,49 +22,56 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.options; +package org.graalvm.collections; /** - * Represents a set of option values based on an {@link OptionDescriptor}. + * Unmodifiable memory efficient set data structure. * * @since 1.0 */ -public interface OptionValues { +public interface UnmodifiableEconomicSet extends Iterable { /** - * Returns all available options. + * Returns {@code true} if this set contains a mapping for the {@code element}. * * @since 1.0 */ - OptionDescriptors getDescriptors(); + boolean contains(E element); /** - * 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}. + * Returns the number of elements in this set. * * @since 1.0 */ - void set(OptionKey optionKey, T value); + int size(); /** - * 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. + * Returns {@code true} if this set contains no elements. * * @since 1.0 */ - T get(OptionKey optionKey); + boolean isEmpty(); /** - * Determines if a value for {@code optionKey} has been {@link #set} in this set of option - * values. + * 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 */ - boolean hasBeenSet(OptionKey optionKey); + 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableMapCursor.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableMapCursor.java similarity index 81% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableMapCursor.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableMapCursor.java index dae30884e03..49d3e4bd475 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableMapCursor.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableMapCursor.java @@ -4,7 +4,9 @@ * * 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. + * 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 @@ -20,26 +22,33 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.util; +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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/package-info.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/package-info.java similarity index 86% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/package-info.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/package-info.java index 8108fab34e4..fcf78805175 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/package-info.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/package-info.java @@ -23,11 +23,11 @@ * questions. */ /** - * The Graal-SDK options package contains reusable collection classes for options. + * The Graal-SDK collections package contains memory efficient data structures. * - * @see org.graalvm.options.OptionDescriptor - * @see org.graalvm.options.OptionValues + * @see org.graalvm.collections.EconomicMap + * @see org.graalvm.collections.EconomicSet * * @since 1.0 */ -package org.graalvm.options; \ No newline at end of file +package org.graalvm.collections; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java index 311aabba0b9..9521357d5b3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java @@ -50,6 +50,21 @@ public class ProbabilityDirectiveTest extends GraalCompilerTest { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java index aa23c861a4a..8235d219a9a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java @@ -49,6 +49,13 @@ public final class GraalDirectives { public static void deoptimizeAndInvalidate() { } + /** + * 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. */ diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java index 4992965ff0e..a217f9ba7ca 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java @@ -26,15 +26,52 @@ import java.lang.annotation.ElementType; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java index ea9791a5082..80bcc1cd7bb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java @@ -90,4 +90,12 @@ public interface SnippetReflectionProvider { * 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.runtime/src/org/graalvm/compiler/api/runtime/GraalRuntime.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.runtime/src/org/graalvm/compiler/api/runtime/GraalRuntime.java index d38ac6ca85d..b3d1437b47a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.runtime/src/org/graalvm/compiler/api/runtime/GraalRuntime.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.runtime/src/org/graalvm/compiler/api/runtime/GraalRuntime.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java index 089cb3f4b0e..2bdbabcd46e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java @@ -208,7 +208,6 @@ public class AMD64Assembler extends Assembler { } 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 @@ public class AMD64Assembler extends Assembler { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java index e5928a9304a..8e56035c3f1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java @@ -33,9 +33,9 @@ import java.util.Collections; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java index 557f95991f0..79d45591008 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java @@ -40,7 +40,7 @@ public final class DataSection implements Iterable { public interface Patches { - void registerPatch(VMConstant c); + void registerPatch(int position, VMConstant c); } public abstract static class Data { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java index 595e7174ed2..0bdaef18edb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java @@ -27,7 +27,6 @@ import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; 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 @@ public class AMD64AddressLowering extends AddressLowering { 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 @@ public class AMD64AddressLowering extends AddressLowering { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64CompressAddressLowering.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64CompressAddressLowering.java new file mode 100644 index 00000000000..45b21430560 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64CompressAddressLowering.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java index 198998ae652..a0d9156a369 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java @@ -26,14 +26,14 @@ package org.graalvm.compiler.core.amd64; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java index 7d6a4c7840f..005d16c887b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java @@ -44,6 +44,7 @@ import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize; 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 @@ public class AMD64NodeMatchRules extends NodeMatchRules { } 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 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @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 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java index 8bb79f7b485..c01737e3d08 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java @@ -232,6 +232,9 @@ public final class GraalOptions { @Option(help = "", type = OptionType.Debug) 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); @@ -271,4 +274,7 @@ public final class GraalOptions { @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicSet.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/TraceInliningMode.java similarity index 60% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicSet.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/TraceInliningMode.java index af7b37e68aa..cbd0e24ee35 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicSet.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/TraceInliningMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,29 +20,20 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.util; +package org.graalvm.compiler.core.common; -/** - * Unmodifiable memory efficient set data structure. - */ -public interface UnmodifiableEconomicSet extends Iterable { +public enum TraceInliningMode { + None(false), + Linear(true), + Tree(true); - boolean contains(E element); + private final boolean tracing; - int size(); + TraceInliningMode(boolean tracing) { + this.tracing = tracing; + } - 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; + public boolean isTracing() { + return tracing; } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java index 4b51e378daa..3cf6ba750c5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/CanonicalCondition.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/CanonicalCondition.java new file mode 100644 index 00000000000..039001da5bf --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/CanonicalCondition.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java index 6b1f94926b6..8949a11aed8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java @@ -115,6 +115,55 @@ public enum Condition { 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 @@ public enum Condition { * 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 @@ public enum Condition { * 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicMap.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ArrayOffsetProvider.java similarity index 64% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicMap.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ArrayOffsetProvider.java index 3c11a6d8e33..c3e719da605 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicMap.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ArrayOffsetProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,32 +20,13 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.util; +package org.graalvm.compiler.core.common.spi; -/** - * Unmodifiable memory efficient map data structure. - */ -public interface UnmodifiableEconomicMap { +import jdk.vm.ci.meta.JavaKind; - V get(K key); +public interface ArrayOffsetProvider { - default V get(K key, V defaultValue) { - V v = get(key); - if (v == null) { - return defaultValue; - } - return v; - } + int arrayBaseOffset(JavaKind elementKind); - boolean containsKey(K key); - - int size(); - - boolean isEmpty(); - - Iterable getValues(); - - Iterable getKeys(); - - UnmodifiableMapCursor getEntries(); + int arrayScalingFactor(JavaKind elementKind); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/CodeGenProviders.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/CodeGenProviders.java index 5c6299da877..59f2bb77e28 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/CodeGenProviders.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/CodeGenProviders.java @@ -40,4 +40,5 @@ public interface CodeGenProviders { ConstantReflectionProvider getConstantReflection(); + ArrayOffsetProvider getArrayOffsetProvider(); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java index fb8c0b90029..a8eb1d01369 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java @@ -28,6 +28,9 @@ import java.util.Arrays; 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.Not; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java index 09a840b5ca8..417bb8d3415 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java @@ -25,8 +25,8 @@ package org.graalvm.compiler.core.common.util; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java index 7351a71116d..b833d296c1a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java @@ -58,6 +58,9 @@ import javax.tools.FileObject; 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.debug.GraalError; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java index 53c137fe193..968e479ef85 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java @@ -29,6 +29,7 @@ import static jdk.vm.ci.sparc.SPARCKind.WORD; 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 @@ public class SPARCNodeMatchRules extends NodeMatchRules { @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java index 6978bcfb669..1697fa95727 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java @@ -123,19 +123,19 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java index dfc8aecff31..1d79a13a443 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java @@ -74,7 +74,6 @@ public class ConditionalEliminationTestBase extends GraalCompilerTest { 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 @@ public class ConditionalEliminationTestBase extends GraalCompilerTest { } canonicalizer.apply(referenceGraph, context); canonicalizer.apply(referenceGraph, context); - new ConvertDeoptimizeToGuardPhase().apply(graph, context); } catch (Throwable t) { debug.handle(t); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java index 31ceb066d07..1bd89c5f6d9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java @@ -25,14 +25,12 @@ package org.graalvm.compiler.core.test; 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; 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 @@ public class CountedLoopTest extends GraalCompilerTest { 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 @@ public class CountedLoopTest extends GraalCompilerTest { 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 @@ public class CountedLoopTest extends GraalCompilerTest { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java index 8380c9a4a5e..557d6ac67d9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java @@ -27,10 +27,10 @@ import java.nio.file.DirectoryStream; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java index 4941269fdb3..04972d5c321 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java @@ -561,7 +561,7 @@ public abstract class GraalCompilerTest extends GraalTest { * @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java index 68043b2b6eb..b90e5a0f4a3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java @@ -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.DebugOptions; import org.graalvm.compiler.debug.DebugContext.Scope; +import org.graalvm.compiler.debug.DebugOptions; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java index e8739621661..4206170c1aa 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java @@ -24,20 +24,29 @@ package org.graalvm.compiler.core.test; 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 @@ public class GraphScheduleTest extends GraalCompilerTest { 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 @@ public class GraphScheduleTest extends GraalCompilerTest { Assert.fail("block of A doesn't dominate the block of B"); } } + + @Override + protected SpeculationLog getSpeculationLog() { + return getCodeCache().createSpeculationLog(); + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java new file mode 100644 index 00000000000..269ccf656c9 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java index 2ad055b27a9..c4ecdfbf3a7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java @@ -44,7 +44,7 @@ public class LongNodeChainTest extends GraalCompilerTest { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java index 3f83a26ce07..47532f95132 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java @@ -31,13 +31,13 @@ import java.util.Iterator; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java index e9676b52c7e..e7acff1e245 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java @@ -70,7 +70,7 @@ public class SchedulingTest2 extends GraphScheduleTest { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TrivialInliningExplosionTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TrivialInliningExplosionTest.java new file mode 100644 index 00000000000..efe909d5db2 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TrivialInliningExplosionTest.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java index 0b1468bd7d1..b1dc8ae1fc2 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.core.test.inlining; 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.HighTierContext; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java index 597523dae1c..c005152cbc7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.core; 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.MidTierContext; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java index 63dd347b546..9d5a5a331ef 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java @@ -26,6 +26,8 @@ import java.util.ArrayDeque; 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.EscapeObjectState; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java index a151bc46c28..a781a4251d3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java @@ -33,6 +33,8 @@ import java.util.ArrayList; 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.NodeLIRBuilderTool; 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 abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio 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 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio } 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java index 9e9161b9501..c56e908d8d5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java @@ -28,6 +28,8 @@ import java.util.ArrayList; 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.debug.GraalError; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java index b352ddc61f5..88bf3d41b4c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java @@ -27,6 +27,9 @@ import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; 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.NodeClass; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java index b8af0a4b031..90b32495f18 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java @@ -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.BasePhase; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java index 820a221e2e7..a27f5a2048a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.core.target; 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.nodes.spi.NodeLIRBuilderTool; 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 @@ public abstract class Backend implements TargetProvider, ValueKindFactory extends NodeIdAccessor implements EconomicMap { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java index 754e50e90b6..5fa99028291 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java @@ -74,6 +74,10 @@ public final class NodeStack { return tos == 0; } + public void clear() { + tos = 0; + } + @Override public String toString() { if (tos == 0) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java index 53dc46d92dc..a6bfcb92e49 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java @@ -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.sp; 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.aarch64.AArch64NodeMatchRules; 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.LIRGenerationResult; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java index 1b8d7061a80..f25ff3d71f8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java @@ -49,6 +49,7 @@ import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider; 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 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { 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 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { } 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/ArrayAccessInLoopToAddressTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/ArrayAccessInLoopToAddressTest.java new file mode 100644 index 00000000000..d8366f6e911 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/ArrayAccessInLoopToAddressTest.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java index e2be3f3bb26..d2d94c95da2 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java @@ -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 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { } @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 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { 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 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java index 692c444058e..0bab1a412da 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java @@ -30,6 +30,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.CanOmitFrame; 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.lir.gen.LIRGeneratorTool; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java index ed56a74213b..4b570049fac 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java @@ -49,6 +49,7 @@ import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider; 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 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { 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 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { } 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java index 9082a2bc874..a12c5c472b6 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java @@ -572,7 +572,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp 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 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp 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 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp 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 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java index 3b11a891691..ee32a46b631 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java @@ -67,7 +67,8 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java index c29de938b6d..c0884bdd5d8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java @@ -60,6 +60,7 @@ final class AMD64HotspotDirectVirtualCallOp extends DirectCallOp { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java index f0f1813f0cb..845320340bb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java @@ -70,7 +70,8 @@ final class AMD64IndirectCallOp extends IndirectCallOp { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java similarity index 79% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java index b1171dba201..bd7466081ce 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,15 +26,18 @@ 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 org.graalvm.compiler.core.test.backend.AllocatorTest; - 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); @@ -44,7 +47,7 @@ public class SPARCAllocatorTest extends AllocatorTest { @Test public void test1() { - testAllocation("test1snippet", 2, 0, 0); + testAllocation("test1snippet", config.threadLocalHandshakes ? 1 : 2, 0, 0); } public static long test1snippet(long x) { @@ -53,7 +56,7 @@ public class SPARCAllocatorTest extends AllocatorTest { @Test public void test2() { - testAllocation("test2snippet", 2, 0, 0); + testAllocation("test2snippet", config.threadLocalHandshakes ? 1 : 2, 0, 0); } public static long test2snippet(long x) { @@ -62,7 +65,7 @@ public class SPARCAllocatorTest extends AllocatorTest { @Test public void test3() { - testAllocation("test3snippet", 4, 0, 0); + testAllocation("test3snippet", config.threadLocalHandshakes ? 3 : 4, 0, 0); } public static long test3snippet(long x) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java index 7c1392f2c6d..9c08e127df5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java @@ -46,6 +46,9 @@ import java.util.HashSet; 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.lir.sparc.SPARCTailDelayedLIRInstruction; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java index eadc3cca4e8..4abd8e73857 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java @@ -101,7 +101,7 @@ public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory { 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 @@ public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory { } 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayNewInstanceTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayNewInstanceTest.java new file mode 100644 index 00000000000..22d6ec04405 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayNewInstanceTest.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java index e076a01cf3f..93a141924f8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java @@ -32,6 +32,8 @@ import java.util.Set; 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.nodes.graphbuilderconf.InvocationPlugins.Binding; 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 @@ public class CheckGraalIntrinsics extends GraalTest { "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 @@ public class CheckGraalIntrinsics extends GraalTest { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java index 0c7cbe5fa49..146296fe83d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java @@ -68,6 +68,8 @@ import java.util.jar.JarEntry; 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.OptionKey; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java index 3982a11f925..e151de4832b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java @@ -25,12 +25,12 @@ package org.graalvm.compiler.hotspot.test; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java index 6b47720d1ac..d3c5286301d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java @@ -32,6 +32,7 @@ import java.util.HashMap; 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.debug.TTY; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java index e2927cdf359..7ab30fd6dbd 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java @@ -31,8 +31,8 @@ import static org.junit.Assert.assertTrue; import java.lang.management.ManagementFactory; import java.lang.reflect.Field; - import java.util.Arrays; + import javax.management.Attribute; import javax.management.MBeanAttributeInfo; import javax.management.MBeanInfo; @@ -41,11 +41,11 @@ import javax.management.MBeanServer; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java index ec4aa5a8df8..6ed19c8bbe9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java @@ -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.GraphBuilderConfiguration.Plu 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.options.OptionValues; import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.runtime.RuntimeProvider; -import org.graalvm.util.EconomicMap; import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java index 10298107ad4..a146a30596d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.hotspot.test; 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; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java index 57d5721bf5f..10f744d46a4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java @@ -29,6 +29,7 @@ import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsin 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.EnumOptionKey; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java index bfe32422746..0a3a667ff1c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java @@ -29,6 +29,7 @@ import java.util.Collections; 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.OptionType; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java index 5191305b3e7..68904ddfa12 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java @@ -64,10 +64,10 @@ import org.graalvm.compiler.options.OptionType; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java index ecae5c3b699..3bba3fbfbcf 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java @@ -98,8 +98,8 @@ public class HotSpotCompiledCodeBuilder { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java index 82f3ca48652..c13813ff1f5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java @@ -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.debug.BenchmarkCounters; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java index 78f028049a2..9988f4f3af8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java @@ -56,41 +56,30 @@ public class HotSpotDataBuilder extends DataBuilder { @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java index ca00da23648..5288ae7b762 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java @@ -22,15 +22,15 @@ */ package org.graalvm.compiler.hotspot; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; +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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java index 2d83476c62f..c0c91e29025 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java @@ -44,10 +44,10 @@ import org.graalvm.compiler.options.OptionDescriptors; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java index 2fde550dd64..0d048bcda0d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java @@ -30,6 +30,7 @@ import java.io.IOException; 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.OptionValues; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java index e14b268e885..adb5c431b36 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java @@ -34,6 +34,8 @@ import java.util.EnumMap; 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.phases.tiers.CompilerConfiguration; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java index f3543dd8fed..8d68016b860 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java @@ -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.LIRFrameState; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java index a396035ddcf..3417f71f994 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java @@ -30,6 +30,7 @@ import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition. 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.hotspot.stubs.Stub; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index 2861fd7610f..94088d33e27 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -31,6 +31,7 @@ import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; 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 java.util.zip.CRC32; 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.CRC32Substitutions; import org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions; +import org.graalvm.compiler.hotspot.replacements.CRC32Substitutions; 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.FixedGuardNode; 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.InvocationPlugins.Registratio 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 @@ public class HotSpotGraphBuilderPlugins { * @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 @@ public class HotSpotGraphBuilderPlugins { 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 @@ public class HotSpotGraphBuilderPlugins { }); } + 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index e18d2fde16d..c69c6f2c84f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -101,6 +101,7 @@ import static org.graalvm.word.LocationIdentity.any; 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.nodes.NamedLocationIdentity; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java index 076d4a98700..ba8fcde9f16 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java @@ -27,6 +27,7 @@ import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; 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.nodes.type.StampTool; 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 @@ final class HotSpotInvocationPlugins extends InvocationPlugins { * 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java index 376325e759b..c91a0dc918e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java @@ -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 @@ public class HotSpotSnippetReflectionProvider implements SnippetReflectionProvid } return null; } + + @Override + public Class originalClass(ResolvedJavaType type) { + return ((HotSpotResolvedJavaType) type).mirror(); + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ArrayRangeWriteBarrier.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ArrayRangeWriteBarrier.java index f5c0f8d0447..8c06e32b2c3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ArrayRangeWriteBarrier.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ArrayRangeWriteBarrier.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java index 4759072762f..b6448f377c6 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java @@ -28,13 +28,14 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java index a7b6cc8d47d..da9741ba5e1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java @@ -28,13 +28,14 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java index 29da335efa6..bcbd40e144d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java @@ -28,14 +28,14 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java index f837b9127e6..4c7d5cce096 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java @@ -34,7 +34,7 @@ import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; 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 @@ public class WriteBarrierAdditionPhase extends Phase { 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 @@ public class WriteBarrierAdditionPhase extends Phase { } } - 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java index 639292f3772..12ea16611b5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java @@ -39,7 +39,7 @@ import org.graalvm.compiler.nodes.FixedWithNextNode; 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 @@ public class WriteBarrierVerificationPhase extends Phase { 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 @@ public class WriteBarrierVerificationPhase extends Phase { } 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 @@ public class WriteBarrierVerificationPhase extends Phase { } 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java index 552c91a611f..dd798786991 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java @@ -28,6 +28,11 @@ import java.util.ArrayList; 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.BasePhase; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java index e6972526ff8..ba682ccf2e1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java @@ -29,6 +29,7 @@ import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; 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.graph.ReentrantNodeIterator.NodeIteratorClosu 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java index 62bf05e689e..ca36e1678f3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java @@ -25,10 +25,7 @@ package org.graalvm.compiler.hotspot.replacements; 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 org.graalvm.word.LocationIdentity; 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 @@ public final class ClassGetHubNode extends FloatingNode implements Lowerable, Ca } @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotArraySubstitutions.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotArraySubstitutions.java new file mode 100644 index 00000000000..9ef3aa73160 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotArraySubstitutions.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index 299abdfafa5..fda1e98e301 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -303,7 +303,11 @@ public class HotSpotReplacementsUtil { 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 @@ public class HotSpotReplacementsUtil { 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 @@ public class HotSpotReplacementsUtil { * @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java index 67f8c0cfb18..3cb35efd94c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java @@ -62,6 +62,7 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT 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 @@ public class NewObjectSnippets implements Snippets { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java index 9a3c4011948..36ffe5ab386 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java @@ -24,7 +24,6 @@ package org.graalvm.compiler.hotspot.replacements; 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.G1ArrayRangePreWriteBarrier; 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 @@ public class WriteBarrierSnippets implements Snippets { } @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 @@ public class WriteBarrierSnippets implements Snippets { } @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 @@ public class WriteBarrierSnippets implements Snippets { } @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 @@ public class WriteBarrierSnippets implements Snippets { 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 @@ public class WriteBarrierSnippets implements Snippets { } } + 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 class WriteBarrierSnippets implements Snippets { 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 class WriteBarrierSnippets implements Snippets { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java index 216fb279e0f..94289adc6d4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java @@ -40,6 +40,7 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probabil 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.Snippets; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java index 17f442def05..a5d4f5bd8af 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java @@ -34,6 +34,21 @@ import static org.graalvm.util.CollectionsUtil.allMatch; 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.OptimisticOptimizations; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java index 39539b36238..755b5c942b3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java @@ -86,6 +86,8 @@ import java.util.Iterator; 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.bytecode.Bytecodes; 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 final class BciBlockMapping { } public static class ExceptionDispatchBlock extends BciBlock { - - private EconomicMap exceptionDispatch = EconomicMap.create(Equivalence.DEFAULT); - public ExceptionHandler handler; public int deoptBci; } @@ -748,15 +745,6 @@ public final class BciBlockMapping { } } - 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 @@ public final class BciBlockMapping { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index e39464a0f6a..cf239a1cd62 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -265,6 +265,8 @@ import java.util.Comparator; 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.Bytes; 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.AddNode; 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.FloatDivNode; import org.graalvm.compiler.nodes.calc.FloatConvertNode; +import org.graalvm.compiler.nodes.calc.FloatDivNode; 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.nodes.util.GraphUtil; 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.ResolvedJavaMethod; 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 @@ public class BytecodeParser implements GraphBuilderContext { // 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 @@ public class BytecodeParser implements GraphBuilderContext { 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 @@ public class BytecodeParser implements GraphBuilderContext { 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 @@ public class BytecodeParser implements GraphBuilderContext { } protected void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, IntrinsicContext calleeIntrinsicContext) { - try (IntrinsicScope s = calleeIntrinsicContext != null && !parsingIntrinsic() ? new IntrinsicScope(this, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), args) : null) { + 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 @@ public class BytecodeParser implements GraphBuilderContext { } } - 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 @@ public class BytecodeParser implements GraphBuilderContext { 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 @@ public class BytecodeParser implements GraphBuilderContext { } else if (block instanceof ExceptionDispatchBlock) { createExceptionDispatch((ExceptionDispatchBlock) block); } else { - frameState.setRethrowException(false); iterateBytecodesForBlock(block); } } @@ -3055,7 +3081,7 @@ public class BytecodeParser implements GraphBuilderContext { } 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 @@ public class BytecodeParser implements GraphBuilderContext { 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); + LogicNode condition = createLogicNode(canonicalizedCondition.getCanonicalCondition(), a, b); - // Check whether the condition needs to negate the result. - boolean negate = cond.canonicalNegate(); - genIf(condition, negate, trueBlock, falseBlock); + 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); } - protected void genIf(LogicNode conditionInput, boolean negateCondition, BciBlock trueBlockInput, BciBlock falseBlockInput) { + 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 @@ public class BytecodeParser implements GraphBuilderContext { } } - 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 @@ public class BytecodeParser implements GraphBuilderContext { 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 @@ public class BytecodeParser implements GraphBuilderContext { 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 @@ public class BytecodeParser implements GraphBuilderContext { } 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 @@ public class BytecodeParser implements GraphBuilderContext { if (!currentBlock.getJsrScope().isEmpty()) { sb.append(' ').append(currentBlock.getJsrScope()); } - debug.log("%s", sb); + TTY.println("%s", sb); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java index d8c8f878b71..ad3c28120ee 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java @@ -34,7 +34,9 @@ import org.graalvm.compiler.options.OptionKey; */ 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 class BytecodeParserOptions { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java index 0297239d5fb..c24565a5dfb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java @@ -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.StructuredGraph; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java index 04b2c315ed4..2787bbaec1f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java @@ -47,6 +47,7 @@ import org.graalvm.compiler.core.common.PermanentBailoutException; 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 final class FrameStateBuilder implements SideEffectsState { } 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java index 519ab288a1b..71fa38f6f79 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java @@ -26,9 +26,6 @@ import static jdk.vm.ci.aarch64.AArch64.zr; 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 org.graalvm.compiler.lir.gen.LIRGeneratorTool; 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 @@ public final class AArch64ArrayEqualsOp extends AArch64LIRInstruction { 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 @@ public final class AArch64ArrayEqualsOp extends AArch64LIRInstruction { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java index 8ba05753b81..c93dee914a6 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java @@ -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.Register; 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 @@ public final class AMD64ArrayEqualsOp extends AMD64LIRInstruction { 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 @@ public final class AMD64ArrayEqualsOp extends AMD64LIRInstruction { // 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java index 8b1cfeb3038..45856abd47a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java @@ -101,6 +101,10 @@ public class AMD64Call { 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 class AMD64Call { } } - 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 @@ public class AMD64Call { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java index 7b9add5daaf..18345adca9f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.lir.amd64; 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 class AMD64Move { } } - 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 @@ public class AMD64Move { 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 class AMD64Move { } } - 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 class AMD64Move { } } - 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java index 68e80e0a95a..a8c20095238 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java @@ -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.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.amd64.AMD64Kind; import jdk.vm.ci.code.Register; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java index 134abcbb7ec..7c76f28d054 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java @@ -24,13 +24,13 @@ package org.graalvm.compiler.lir.amd64; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java index 5ed8bc577a5..55d1e4f79b1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java @@ -36,9 +36,6 @@ import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.Less; 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.code.Register; 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 @@ public final class SPARCArrayEqualsOp extends SPARCLIRInstruction { 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 @@ public final class SPARCArrayEqualsOp extends SPARCLIRInstruction { } } } - - 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java index ec96b34ba4e..f5a0e93b26c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java @@ -78,6 +78,8 @@ import java.util.ArrayList; 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; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java index ac79a3dbd59..ba59423a4bf 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java @@ -22,12 +22,14 @@ */ package org.graalvm.compiler.lir.sparc; -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 static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; +import static org.graalvm.compiler.lir.sparc.SPARCDelayedControlTransfer.DUMMY; 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.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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java index df7bb4f1976..f3b907afd87 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java @@ -27,14 +27,13 @@ import static org.junit.Assert.assertTrue; import java.util.HashSet; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - +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.graalvm.util.Pair; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.Register.RegisterCategory; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java index 5e4a5c513cd..53dd628c755 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java @@ -33,14 +33,14 @@ import java.util.ArrayList; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java index 69fbbf4eebf..9444a05384c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java @@ -30,7 +30,8 @@ import java.util.Arrays; 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.StandardOp.ValueMoveOp; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java index 5ec1f8b5278..39d5c1a6555 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java @@ -31,12 +31,12 @@ import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java index 0ed228938f4..92146c1c49d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java @@ -35,6 +35,7 @@ import java.util.Arrays; 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.Option; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java index cb02e6653cb..4ab4f8972c4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java @@ -35,6 +35,8 @@ import java.util.ArrayList; 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.Interval.SpillState; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java index 13380201d72..0d031d189b2 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java index 112b360a51c..e6267a0208a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java @@ -28,6 +28,8 @@ import static jdk.vm.ci.code.ValueUtil.isRegister; 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.LIRInsertionBuffer; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java index fec7aa0466a..7abb15b7996 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java @@ -32,13 +32,15 @@ import java.util.Arrays; 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.Option; 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 @@ public class CompilationResultBuilder { } /** - * 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java index 7d6922adaab..173135c0869 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java @@ -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.LIR; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java index c2b82ba1675..005e8c0af51 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/PreAllocationOptimizationStage.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/PreAllocationOptimizationStage.java index cf60269e026..0a94dd1c47c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/PreAllocationOptimizationStage.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/PreAllocationOptimizationStage.java @@ -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 class PreAllocationOptimizationStage extends LIRPhaseSuite loop; @@ -236,13 +237,13 @@ public class LoopEx { 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 @@ public class LoopEx { } 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java index 9323ec4bb9f..6014cebf3f7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java @@ -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.java.MonitorEnterNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java index 8ae334b11d5..42b656da7b3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java @@ -26,6 +26,8 @@ import java.util.ArrayList; 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.CompareNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java index 99b01dd3848..0a6d267d3a4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java @@ -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.LoopExitNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java index a1344dea709..c2f07108237 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java @@ -27,6 +27,9 @@ import java.util.Collection; 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.StructuredGraph; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java index 82e4900de21..521dfc166ea 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java @@ -24,7 +24,9 @@ package org.graalvm.compiler.microbenchmarks.graal; 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.microbenchmarks.graal.util.ScheduleState; 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 class SchedulePhaseBenchmark extends GraalBenchmark { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java index d94012240a0..e1b2ac94cd0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java @@ -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 class ScheduleState extends GraphState { } public ScheduleState() { - this(SchedulingStrategy.EARLIEST); + this(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); } @Override @@ -44,4 +48,13 @@ public class ScheduleState extends GraphState { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java index cd6e1526011..0af915c98dc 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java @@ -156,11 +156,11 @@ public class IfNodeCanonicalizationTest extends GraalCompilerTest { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java index ecc64e8f7b4..94f081a20de 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java @@ -129,10 +129,13 @@ public abstract class AbstractBeginNode extends FixedWithNextNode implements LIR if (ret == null) { throw new NoSuchElementException(); } - if (!(current instanceof FixedWithNextNode) || (current instanceof AbstractBeginNode && current != AbstractBeginNode.this)) { - current = null; - } else { + if (current instanceof FixedWithNextNode) { current = ((FixedWithNextNode) current).next(); + if (current instanceof AbstractBeginNode) { + current = null; + } + } else { + current = null; } return ret; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ControlSplitNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ControlSplitNode.java index 15543d52409..7fbaa4ad5f8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ControlSplitNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ControlSplitNode.java @@ -49,7 +49,7 @@ public abstract class ControlSplitNode extends FixedNode implements IterableNode /** * 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java index 3a4fc760649..43b9a491b38 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java @@ -39,7 +39,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; 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 @@ public final class DeoptimizeNode extends AbstractDeoptimizeNode implements Lowe 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 @@ public final class DeoptimizeNode extends AbstractDeoptimizeNode implements Lowe return ConstantNode.forConstant(speculation, metaAccess, graph()); } + @Override public JavaConstant getSpeculation() { return speculation; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingGuard.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingGuard.java index 9d3ad076435..b593d246e14 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingGuard.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingGuard.java @@ -24,25 +24,15 @@ package org.graalvm.compiler.nodes; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java index c9ec5a7de28..9d51e2a00a9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java @@ -83,15 +83,7 @@ public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowe @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java index 9b08cbaffaf..be2fa0db07a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java @@ -37,6 +37,9 @@ import java.util.Map; 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.calc.FloatingNode; 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 @@ public class GraphDecoder { */ 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 @@ public class GraphDecoder { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java index db51c69e058..9f227d4847e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java @@ -27,6 +27,8 @@ import java.util.Deque; 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.NodeMap; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java index 3b65fc3ad7c..9a6dc659fbd 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java @@ -30,6 +30,8 @@ import java.util.Arrays; 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.java.LoadFieldNode; 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 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL } 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 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL } } 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 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL 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 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL @Override public AbstractBeginNode getPrimarySuccessor() { - return this.trueSuccessor(); + return null; } public AbstractBeginNode getSuccessor(boolean result) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java new file mode 100644 index 00000000000..80c962f5d8f --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java index 6d534e12cdc..b212a390348 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java @@ -24,9 +24,9 @@ package org.graalvm.compiler.nodes; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StaticDeoptimizingNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StaticDeoptimizingNode.java new file mode 100644 index 00000000000..72f494a3536 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StaticDeoptimizingNode.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java index 8db681571ed..bff9ce3272e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java @@ -28,6 +28,10 @@ import java.util.List; 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.debug.JavaMethodContext; 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.java.MethodCallTargetNode; 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 @@ public final class StructuredGraph extends Graph implements JavaMethodContext { 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 @@ public final class StructuredGraph extends Graph implements JavaMethodContext { 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 @@ public final class StructuredGraph extends Graph implements JavaMethodContext { 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 @@ public final class StructuredGraph extends Graph implements JavaMethodContext { 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 @@ public final class StructuredGraph extends Graph implements JavaMethodContext { 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 @@ public final class StructuredGraph extends Graph implements JavaMethodContext { this.start = start; } + public InliningLog getInliningLog() { + return inliningLog; + } + /** * Creates a copy of this graph. * @@ -459,7 +480,7 @@ public final class StructuredGraph extends Graph implements JavaMethodContext { speculationLog, useProfilingInfo, newCompilationId, - getOptions(), debugForCopy, null); + getOptions(), debugForCopy, null, callerContext); if (allowAssumptions == AllowAssumptions.YES && assumptions != null) { copy.assumptions.record(assumptions); } @@ -931,4 +952,8 @@ public final class StructuredGraph extends Graph implements JavaMethodContext { protected void afterRegister(Node node) { assert hasValueProxies() || !(node instanceof ValueProxyNode); } + + public NodeSourcePosition getCallerContext() { + return callerContext; + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java index 14e102dc243..ea18b63c66c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.nodes.calc; 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.LogicNode; 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 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical * @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 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical * * @return the condition */ - public final Condition condition() { + public final CanonicalCondition condition() { return condition; } @@ -85,7 +86,7 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical 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 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical } @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 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical * @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 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical } 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 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical 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 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical 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 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical 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 abstract class CompareNode extends BinaryOpLogicNode implements Canonical } 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 @@ public abstract class CompareNode extends BinaryOpLogicNode implements Canonical 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java index bff140ebc63..eeb8dbac2fa 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java @@ -26,7 +26,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; 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 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConvertNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConvertNode.java index 53dbc76e1c9..b7d6bb7b727 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConvertNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConvertNode.java @@ -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 @@ public interface ConvertNode extends ValueNodeInterface { * @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 @@ public interface ConvertNode extends ValueNodeInterface { * @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java index 09b7072d31b..32433a9f2e2 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java @@ -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.ValueNode; 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 @@ public final class FloatEqualsNode extends CompareNode implements BinaryCommutat 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 final class FloatEqualsNode extends CompareNode implements BinaryCommutat 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 @@ public final class FloatEqualsNode extends CompareNode implements BinaryCommutat @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 final class FloatEqualsNode extends CompareNode implements BinaryCommutat 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java index 8b1885ff9bd..9121eb83cc9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java @@ -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.ValueNode; 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 @@ public final class FloatLessThanNode extends CompareNode { 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 final class FloatLessThanNode extends CompareNode { 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 @@ public final class FloatLessThanNode extends CompareNode { @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 final class FloatLessThanNode extends CompareNode { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java index 03e963d18d4..1c59aed273c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java @@ -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.nodeinfo.NodeInfo; 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 @@ public final class IntegerBelowNode extends IntegerLowerThanNode { } @Override - protected Condition getCondition() { - return Condition.BT; + protected CanonicalCondition getCondition() { + return CanonicalCondition.BT; } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java index 8408d73e315..058dd408563 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java @@ -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.LogicNode; 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 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut 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 final class IntegerEqualsNode extends CompareNode implements BinaryCommut 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 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut @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 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut } @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 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java index bab63e1f7d9..3d82b901758 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java @@ -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.LogicNegationNode; 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 @@ public final class IntegerLessThanNode extends IntegerLowerThanNode { } @Override - protected Condition getCondition() { + protected CanonicalCondition getCondition() { return LT; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java index 0294ef39a7f..fd4ad73312d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java @@ -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,10 +34,12 @@ import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.util.GraphUtil; - -import jdk.vm.ci.meta.TriState; import org.graalvm.compiler.options.OptionValues; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.TriState; + /** * Common super-class for "a < b" comparisons both {@linkplain IntegerLowerThanNode signed} and * {@linkplain IntegerBelowNode unsigned}. @@ -117,7 +117,7 @@ public abstract class IntegerLowerThanNode extends CompareNode { 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 @@ public abstract class IntegerLowerThanNode extends CompareNode { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java index e417e65cb88..f6bbfa2e7ab 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java @@ -112,9 +112,9 @@ public final class NarrowNode extends IntegerConvertNode { // ==> 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java index 6faad2746c4..1c3a34047bb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.nodes.calc; 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 @@ public final class NormalizeCompareNode extends BinaryNode implements IterableNo } 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java index 9a9f2f402fb..c2a59b94dd0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java @@ -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.Virtualizable; 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.JavaConstant; 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 final class ObjectEqualsNode extends PointerEqualsNode implements Virtual } 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 final class ObjectEqualsNode extends PointerEqualsNode implements Virtual } 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 @@ public final class ObjectEqualsNode extends PointerEqualsNode implements Virtual @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 @@ public final class ObjectEqualsNode extends PointerEqualsNode implements Virtual @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java index d1e399d1c13..b7974b7b6a0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java @@ -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.LoadHubNode; 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 @@ public class PointerEqualsNode extends CompareNode implements BinaryCommutative< } 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 @@ public class PointerEqualsNode extends CompareNode implements BinaryCommutative< @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 @@ public class PointerEqualsNode extends CompareNode implements BinaryCommutative< * 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 @@ public class PointerEqualsNode extends CompareNode implements BinaryCommutative< } @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java index a603eda3934..65401227a6a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java @@ -95,7 +95,7 @@ public final class SignExtendNode extends IntegerConvertNode 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 @@ public final class SignExtendNode extends IntegerConvertNode 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java index 8574c816fca..a8f1a473054 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.nodes.calc; 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 final class ZeroExtendNode extends IntegerConvertNode 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 @@ public final class ZeroExtendNode extends IntegerConvertNode 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 @@ public final class ZeroExtendNode extends IntegerConvertNode 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 @@ public final class ZeroExtendNode extends IntegerConvertNode } if (self == null) { - self = new ZeroExtendNode(forValue, inputBits, resultBits); + self = new ZeroExtendNode(forValue, inputBits, resultBits, alwaysPositive); } return self; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java index 1a4a94724d9..fdfc4719a26 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java @@ -42,7 +42,6 @@ import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; 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 @@ public final class Block extends AbstractBlockBase { private Loop loop; protected Block postdominator; - protected Block distancedDominatorCache; private LocationSet killLocations; private LocationSet killLocationsBetweenThisAndDominator; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWriteNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWrite.java similarity index 59% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWriteNode.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWrite.java index c64a619580c..27ea3335d05 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWriteNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWrite.java @@ -22,51 +22,33 @@ */ 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.graph.NodeInterface; +import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint; +import org.graalvm.compiler.nodes.memory.address.AddressNode; -/** - * 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(); +public interface ArrayRangeWrite extends NodeInterface { + AddressNode getAddress(); /** * The length of the modified range. */ - public abstract ValueNode getLength(); + ValueNode getLength(); /** * Return true if the written array is an object array, false if it is a primitive array. */ - public abstract boolean isObjectArray(); + 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. */ - public abstract boolean isInitialization(); + boolean isInitialization(); + + int getElementStride(); + + @Override + FixedWithNextNode asNode(); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java index e6f436d5729..920a1efa471 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.nodes.extended; 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 @@ public final class BranchProbabilityNode extends FloatingNode implements Simplif } 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java index 6638e3f0d14..39db72a6859 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java @@ -97,7 +97,7 @@ public class RawLoadNode extends UnsafeAccessNode implements Lowerable, Virtuali 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java index 720654f5a82..69503e6c12c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java @@ -119,7 +119,7 @@ public final class RawStoreNode extends UnsafeAccessNode implements StateSplit, 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java index 14ae73e47ef..8edbef05bee 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java @@ -228,7 +228,7 @@ public abstract class SwitchNode extends ControlSplitNode { @Override public AbstractBeginNode getPrimarySuccessor() { - return this.defaultSuccessor(); + return null; } /** diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java index a85d3589ea0..f1599601c18 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java @@ -82,6 +82,10 @@ public interface InlineInvokePlugin extends GraphBuilderPlugin { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java index 770a36eafb0..1b97ce00b20 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java @@ -35,6 +35,12 @@ import java.util.Collections; 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.Node; 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; @@ -111,6 +111,26 @@ public class InvocationPlugins { } } + /** + * 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}. */ @@ -696,7 +716,7 @@ public class InvocationPlugins { * * @param declaringClass the class to test */ - protected boolean canBeIntrinsified(ResolvedJavaType declaringClass) { + public boolean canBeIntrinsified(ResolvedJavaType declaringClass) { return true; } @@ -1150,6 +1170,9 @@ public class InvocationPlugins { } 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 @@ public class InvocationPlugins { } 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 @@ public class InvocationPlugins { * {@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 @@ public class InvocationPlugins { } 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 m; } } } - return null; + 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; + } + + 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java index 450ff24c8eb..702b1c2d638 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java @@ -39,10 +39,10 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java index 10ddb9d8520..72da5220750 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java @@ -36,11 +36,10 @@ import org.graalvm.compiler.nodes.spi.LoweringTool; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java index 7d9e13f0ad1..90814b4062f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java @@ -124,6 +124,13 @@ public class DynamicNewArrayNode extends AbstractNewArrayNode implements Canonic return elementType.getJavaKind() == JavaKind.Void; } + @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); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java index f477655786b..6bb19da8359 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java @@ -42,11 +42,10 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java index 89fd3ddda60..04167c12227 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.nodes.java; 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 @@ public class NewArrayNode extends AbstractNewArrayNode implements VirtualizableA // 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java index d6c30383f3e..ac72a1690cf 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java @@ -32,6 +32,9 @@ import java.util.ArrayList; 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.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.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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java index e2302cd9cbb..23efaf8eb0f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java @@ -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 @@ import jdk.vm.ci.meta.JavaKind; /** * 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java index 785675adde5..c985701cfc2 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.nodes.spi; 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 @@ public interface VirtualizerTool { */ ConstantReflectionProvider getConstantReflectionProvider(); + ArrayOffsetProvider getArrayOffsetProvider(); + /** * This method should be used to query the maximum size of virtualized objects before attempting * virtualization. diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java index fcb46500de5..959e252567b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java @@ -30,6 +30,10 @@ import java.util.Iterator; 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.Option; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java index 65f644b73dc..d71bd537ff3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.nodes.virtual; 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 org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 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 @@ public class VirtualArrayNode extends VirtualObjectNode implements ArrayLengthPr } @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java index bee87d12029..b7685463120 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java @@ -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 @@ public class VirtualInstanceNode extends VirtualObjectNode { } @Override - public int entryIndexForOffset(long constantOffset, JavaKind expectedEntryKind) { + public int entryIndexForOffset(ArrayOffsetProvider arrayOffsetProvider, long constantOffset, JavaKind expectedEntryKind) { return fieldIndex(type.findInstanceFieldWithOffset(constantOffset, expectedEntryKind)); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualObjectNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualObjectNode.java index 2c512a20726..cec945b4c53 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualObjectNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualObjectNode.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.nodes.virtual; 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 @@ public abstract class VirtualObjectNode extends ValueNode implements LIRLowerabl * @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java index f8bcc937840..226dc49cf79 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.options; import java.util.EnumSet; -import org.graalvm.util.EconomicMap; +import org.graalvm.collections.EconomicMap; public class EnumOptionKey> extends OptionKey { final Class enumClass; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java index 6605d5256d2..38bc3622d44 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java @@ -24,10 +24,10 @@ package org.graalvm.compiler.options; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java index 6581853bec9..76baa5a40f8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.options; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java index e7d29533200..5ec5cf4c831 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java @@ -30,10 +30,10 @@ import java.util.Map; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java index 7106312d706..1cb4a607ef4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java @@ -28,9 +28,9 @@ import java.util.Formatter; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java index 333fbccb610..b25fa389cbf 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java @@ -33,6 +33,15 @@ import org.graalvm.compiler.phases.Phase; 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 @@ public class AddressLoweringPhase extends Phase { @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java index 0f1c4206191..b23c25592b7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java @@ -26,6 +26,10 @@ import java.util.ArrayDeque; 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.BasePhase; 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 @@ public class ConditionalEliminationPhase extends BasePhase { 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 @@ public class ConditionalEliminationPhase extends BasePhase { */ 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 @@ public class ConditionalEliminationPhase extends BasePhase { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java index 6e5b235cbbc..641fbd69bd7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java @@ -26,8 +26,8 @@ import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Option 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.IfNode; 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 org.graalvm.compiler.phases.tiers.PhaseContext; 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 @@ public class ConvertDeoptimizeToGuardPhase extends BasePhase { @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 @@ public class ConvertDeoptimizeToGuardPhase extends BasePhase { 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); + + 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; + } + } + current = current.predecessor(); } + } - 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); - } - 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); - - 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java index 0d183bdeb0e..7eaf9078d36 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java @@ -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; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java index e35d0daff1e..02db5abf038 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java @@ -30,6 +30,10 @@ import java.util.EnumSet; 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.common.util.HashSetNodeEventListener; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java index 42e0699d4b1..25e0c90c2de 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.phases.common; 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.nodes.util.GraphUtil; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java index 0da1f41b589..d701789b3aa 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java @@ -120,7 +120,7 @@ public class GuardLoweringPhase extends BasePhase { @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java index 27b50e64c73..6acd6e731a0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java @@ -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.FixedNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java index 4f4c9bb2181..c22095801cd 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java @@ -50,6 +50,9 @@ import org.graalvm.compiler.nodes.extended.NullCheckNode; 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 @@ public class UseTrappingNullChecksPhase extends BasePhase { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java index f0db2b4df29..bf625ed550b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java @@ -33,6 +33,11 @@ import java.util.List; 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.nodes.util.GraphUtil; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java index a0cf7448d05..fe675d91193 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java @@ -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.InliningUtil; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java index c29ea277be7..8d53ec09dba 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java index e2d3f682257..d610ab6a2e7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java index 960c71c3bdb..b778e43b7c4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java @@ -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.CanonicalizerPhase; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java index c117547930f..982c8a4bd13 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java @@ -25,6 +25,8 @@ package org.graalvm.compiler.phases.common.inlining.info; 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.nodes.util.GraphUtil; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java index 1127d5d76fc..cbfe9aeee05 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java @@ -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.nodes.extended.LoadHubNode; 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 @@ public class TypeGuardInlineInfo extends AbstractInlineInfo { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java index ba518af2561..777eaadcd6e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java @@ -26,6 +26,8 @@ import java.util.BitSet; 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.StructuredGraph; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java index 9624d9123ea..640febe9809 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java @@ -25,6 +25,8 @@ package org.graalvm.compiler.phases.common.inlining.walker; 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.MergeNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java index ed6a1208f27..f74fc8449ff 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java @@ -34,6 +34,8 @@ import java.util.Iterator; 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.info.elem.InlineableGraph; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java index eef9f035006..ad7292148b1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java @@ -26,12 +26,12 @@ import java.util.EnumSet; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java index 85b1a9239fe..e4339631881 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java @@ -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.EndNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java index 829826f6f33..0e6198540c1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java @@ -27,6 +27,8 @@ import java.util.ArrayList; 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.InvokeWithExceptionNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java index 24bb2c4b82c..c2c128fc5fa 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java @@ -28,6 +28,8 @@ import java.util.Deque; 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.FixedNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java index 103fa548d29..14e7b1d46e6 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java @@ -28,6 +28,9 @@ import java.util.Deque; 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.FixedWithNextNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java index e6ae39d9cf2..f956235d462 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java @@ -27,6 +27,8 @@ import java.util.ArrayList; 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.LoopBeginNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java index 488fdc15a81..8e96078a0c0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java @@ -24,6 +24,8 @@ package org.graalvm.compiler.phases.schedule; 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.MemoryNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java index 1b896801e58..7e2e51f3237 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java @@ -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.ControlSinkNode; 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.LoopExitNode; 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 @@ import org.graalvm.word.LocationIdentity; 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 @@ public final class SchedulePhase extends Phase { 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 @@ public final class SchedulePhase extends Phase { this.blockToNodesMap = latestBlockToNodesMap; - cfg.setNodeToBlock(currentNodeMap); } + cfg.setNodeToBlock(currentNodeMap); graph.setLastSchedule(new ScheduleResult(this.cfg, this.nodeToBlockMap, this.blockToNodesMap)); } @@ -524,7 +543,6 @@ public final class SchedulePhase extends Phase { 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 final class SchedulePhase extends Phase { */ 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 @@ public final class SchedulePhase extends Phase { * 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 final class SchedulePhase extends Phase { */ 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 final class SchedulePhase extends Phase { public String toString() { return String.format("MicroBlock[id=%d]", id); } + + @Override + public int hashCode() { + return id; + } } /** @@ -706,9 +739,9 @@ public final class SchedulePhase extends Phase { 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 @@ public final class SchedulePhase extends Phase { } } - 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 @@ public final class SchedulePhase extends Phase { 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 @@ public final class SchedulePhase extends Phase { 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 @@ public final class SchedulePhase extends Phase { 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 @@ public final class SchedulePhase extends Phase { } } + 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 @@ public final class SchedulePhase extends Phase { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java index cb3563647e3..7d00f6b0d3b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java @@ -25,6 +25,8 @@ package org.graalvm.compiler.phases.util; 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.ReentrantBlockIterator.BlockIteratorClo 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java index c3101c87ff8..f59dd6d4aa8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java @@ -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; @@ -89,6 +90,11 @@ public class Providers implements CodeGenProviders { return lowerer; } + @Override + public ArrayOffsetProvider getArrayOffsetProvider() { + return lowerer; + } + @Override public ConstantReflectionProvider getConstantReflection() { return constantReflection; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java index e195ad1875b..863f88b1147 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java @@ -143,9 +143,9 @@ public class VerifyDebugUsage extends VerifyPhase { "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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java index 17d7dbaaaf6..aba7840db1d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java @@ -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.java.NewInstanceNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java index 23db00cdfb3..9429831465d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java @@ -33,6 +33,7 @@ import java.util.List; 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.ValuePhiNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java index 8dbb3ff0fa9..0524356c185 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java @@ -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 @@ import sun.misc.Unsafe; @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 @@ public class AMD64StringSubstitutions { } 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java index d8809aeb673..4295309a4b5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java @@ -79,7 +79,7 @@ public class FoldTest extends ReplacementsTest { @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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NestedExceptionHandlerTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NestedExceptionHandlerTest.java new file mode 100644 index 00000000000..e1758a69ece --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NestedExceptionHandlerTest.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java index 0af78121511..57131df9922 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.replacements; 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.CanonicalizerPhase; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java index 98da95e0090..eb2b260db00 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java @@ -24,10 +24,13 @@ package org.graalvm.compiler.replacements; 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.debug.DebugHandlersFactory; 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.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.OptionValues; @@ -38,7 +41,7 @@ import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; 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 @@ public class ConstantStringIndexOfSnippets implements Snippets { 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 @@ public class ConstantStringIndexOfSnippets implements Snippets { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java index 4bfcadde273..60193bff6ac 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java @@ -921,8 +921,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { public abstract int arrayLengthOffset(); - public abstract int arrayBaseOffset(JavaKind elementKind); - + @Override public int arrayScalingFactor(JavaKind elementKind) { return target.arch.getPlatformKind(elementKind).getSizeInBytes(); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java index 0f0440ddaf0..abc6b32cdec 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java @@ -27,7 +27,7 @@ import static org.graalvm.compiler.nodes.calc.CompareNode.createCompareNode; 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 @@ public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates { } 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java index 49d9a2fa579..c56f7d69f9a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java @@ -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 @@ public class NodeIntrinsificationProvider implements InjectionProvider { 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 @@ public class NodeIntrinsificationProvider implements InjectionProvider { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java index aa52ee525d8..2c3be468112 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java @@ -32,6 +32,8 @@ import java.util.HashMap; 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.OptionKey; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java index c569e541320..f034fa3c2bc 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java @@ -36,6 +36,8 @@ import java.util.concurrent.ConcurrentHashMap; 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.bytecode.ResolvedJavaMethodBytecode; 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.tiers.PhaseContext; 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 @@ public class ReplacementsImpl implements Replacements, InlineInvokePlugin { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index 45258eac938..c53b361159d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -47,11 +47,27 @@ import java.util.concurrent.atomic.AtomicInteger; 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.StampPair; 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.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.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.MergeNode; 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.options.OptionValues; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java index 55708c96e59..ddc64e3839d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java @@ -37,10 +37,13 @@ import java.lang.reflect.Array; 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 @@ public class StandardGraphBuilderPlugins { @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 lhs = canonical.mustMirror() ? y : x; + ValueNode rhs = canonical.mustMirror() ? x : y; - ValueNode trueValue = ConstantNode.forBoolean(!negate, graph); - ValueNode falseValue = ConstantNode.forBoolean(negate, graph); + ValueNode trueValue = ConstantNode.forBoolean(!canonical.mustNegate(), graph); + ValueNode falseValue = ConstantNode.forBoolean(canonical.mustNegate(), graph); - Condition cond = mirror ? condition.mirror() : condition; - if (negate) { - cond = cond.negate(); - } - - 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 @@ public class StandardGraphBuilderPlugins { } } + 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 @@ public class StandardGraphBuilderPlugins { } }); + 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java index 48cacb64383..25dc63bf8ec 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java @@ -46,8 +46,8 @@ public class Classfile { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java index f3d788b7d9e..88403c39fa4 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java @@ -29,12 +29,12 @@ import java.io.DataInputStream; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java index cd97128215d..087f78be98e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java @@ -54,6 +54,7 @@ abstract class ClassfileConstant { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java index aac1de4677e..218df10ab96 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java @@ -112,6 +112,9 @@ class ClassfileConstantPool implements ConstantPool { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java index a053795a24f..ab46f0fbbd3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java @@ -62,7 +62,7 @@ public abstract class BasicObjectCloneNode extends MacroStateSplitNode implement @Override public boolean inferStamp() { - return updateStamp(computeStamp(getObject())); + return updateStamp(stamp.improveWith(computeStamp(getObject()))); } protected Stamp computeStamp(ValueNode object) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java index 26f009cd8de..8d17bfd3fff 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java @@ -37,6 +37,8 @@ import javax.annotation.processing.RoundEnvironment; 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 @@ public class ServiceProviderProcessor extends AbstractProcessor { 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 @@ public class ServiceProviderProcessor extends AbstractProcessor { 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java index 256e1ee6123..06f1e7ae9af 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java @@ -24,7 +24,6 @@ package org.graalvm.compiler.test; 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.Collection; 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 @@ public class GraalTest { /** * 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 @@ public class GraalTest { } 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 @@ public class GraalTest { List cached = cachedDebugs.get(); if (cached != null) { for (DebugContext debug : cached) { + debug.close(); debug.closeDumpHandlers(true); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java index d315a9d848f..83c5ebcc45f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java @@ -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.Map; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java index 23b2f324d07..12eebb38eff 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java @@ -25,8 +25,8 @@ package org.graalvm.compiler.virtual.phases.ea; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java index fcdc2185b32..b005b85e617 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java @@ -25,6 +25,9 @@ package org.graalvm.compiler.virtual.phases.ea; 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.options.OptionValues; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java index 5a6d0937579..34860543551 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.virtual.phases.ea; 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.common.util.HashSetNodeEventListener; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java index 5403efad0a3..b934abe3aad 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java @@ -25,6 +25,8 @@ package org.graalvm.compiler.virtual.phases.ea; 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.AllocatedObjectNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java index 59ec8053046..ab0551dbc17 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java @@ -29,6 +29,11 @@ import java.util.EnumMap; 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.util.GraphUtil; 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 @@ public final class PEReadEliminationClosure extends PartialEscapeClosure { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java index 8cf61c7d67c..14dc07883c7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java @@ -24,10 +24,10 @@ package org.graalvm.compiler.virtual.phases.ea; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java index 6e05a283695..7f23c16771e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java @@ -28,7 +28,10 @@ import static org.graalvm.word.LocationIdentity.any; 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.options.OptionValues; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java index 751f9377037..83223b5f1d1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java @@ -26,6 +26,8 @@ import static org.graalvm.compiler.core.common.GraalOptions.TraceEscapeAnalysis; 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.AbstractEndNode; 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java index 314d2d97dd1..bfc3765b188 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java @@ -26,6 +26,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.MaximumEscapeAnalysi 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 @@ class VirtualizerToolImpl implements VirtualizerTool, CanonicalizerTool { 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 @@ class VirtualizerToolImpl implements VirtualizerTool, CanonicalizerTool { * 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java index fafcb50f050..2d5f5a9145d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java @@ -31,7 +31,9 @@ import java.util.Arrays; 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 @@ public class WordOperationPlugin extends WordFactory implements NodePlugin, Type 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphJavadocSnippets.java similarity index 93% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphSnippets.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphJavadocSnippets.java index 3fb3c7f8e07..96998075dd2 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphJavadocSnippets.java @@ -33,10 +33,10 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; -final class GraphSnippets { +final class GraphJavadocSnippets { static GraphStructure acmeGraphStructure() { // @formatter:off - // BEGIN: org.graalvm.graphio.GraphSnippets#acmeGraphStructure + // BEGIN: org.graalvm.graphio.GraphJavadocSnippets#acmeGraphStructure class AcmeGraphStructure implements GraphStructure { @@ -140,12 +140,12 @@ final class GraphSnippets { } } - // END: org.graalvm.graphio.GraphSnippets#acmeGraphStructure + // END: org.graalvm.graphio.GraphJavadocSnippets#acmeGraphStructure return new AcmeGraphStructure(); } - // BEGIN: org.graalvm.graphio.GraphSnippets#buildOutput + // BEGIN: org.graalvm.graphio.GraphJavadocSnippets#buildOutput static GraphOutput buildOutput(WritableByteChannel channel) throws IOException { return GraphOutput.newBuilder(acmeGraphStructure()). @@ -153,9 +153,9 @@ final class GraphSnippets { protocolVersion(5, 0). build(channel); } - // END: org.graalvm.graphio.GraphSnippets#buildOutput + // END: org.graalvm.graphio.GraphJavadocSnippets#buildOutput - // BEGIN: org.graalvm.graphio.GraphSnippets#buildAll + // BEGIN: org.graalvm.graphio.GraphJavadocSnippets#buildAll static GraphOutput buildAll(WritableByteChannel channel) throws IOException { GraphBlocks graphBlocks = acmeBlocks(); @@ -170,7 +170,7 @@ final class GraphSnippets { types(graphTypes). build(channel); } - // END: org.graalvm.graphio.GraphSnippets#buildAll + // END: org.graalvm.graphio.GraphJavadocSnippets#buildAll private static GraphTypes acmeTypes() { GraphTypes graphTypes = null; @@ -257,7 +257,7 @@ final class GraphSnippets { private static class AcmeCodePosition { } - // BEGIN: org.graalvm.graphio.GraphSnippets#dump + // BEGIN: org.graalvm.graphio.GraphJavadocSnippets#dump static void dump(File toFile) throws IOException { try ( FileChannel ch = new FileOutputStream(toFile).getChannel(); @@ -280,6 +280,6 @@ final class GraphSnippets { output.endGroup(); } } - // END: org.graalvm.graphio.GraphSnippets#dump + // END: org.graalvm.graphio.GraphJavadocSnippets#dump } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/package-info.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/package-info.java index 33dd39977e8..c5b4cb428ee 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/package-info.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/package-info.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java deleted file mode 100644 index a59c27bf072..00000000000 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java +++ /dev/null @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptors.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptors.java deleted file mode 100644 index 786299fa1e3..00000000000 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptors.java +++ /dev/null @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionKey.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionKey.java deleted file mode 100644 index 68098ea270d..00000000000 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionKey.java +++ /dev/null @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionType.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionType.java deleted file mode 100644 index d1533db49db..00000000000 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionType.java +++ /dev/null @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionSizeTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionSizeTest.java new file mode 100644 index 00000000000..f5055201351 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionSizeTest.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionTest.java deleted file mode 100644 index 6867ca678b4..00000000000 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionTest.java +++ /dev/null @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionUtilTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionUtilTest.java new file mode 100644 index 00000000000..d16c75dd2da --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionUtilTest.java @@ -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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/CollectionsUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/CollectionsUtil.java index 5bb042e775f..bc150222a35 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/CollectionsUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/CollectionsUtil.java @@ -37,7 +37,10 @@ import java.util.function.Supplier; /** * 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 @@ public class CollectionsUtil { }; } + /** + * 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 @@ public class CollectionsUtil { 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 @@ public class CollectionsUtil { 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 @@ public class CollectionsUtil { } /** - * 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 @@ public class CollectionsUtil { } /** - * 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 @@ public class CollectionsUtil { 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 @@ public class CollectionsUtil { } return strb.toString(); } + } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java index 039474cb4c0..b28fc86fcac 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java @@ -26,6 +26,9 @@ import java.lang.reflect.Field; 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 @@ public final class ObjectSizeEstimate { } 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 @@ public final class ObjectSizeEstimate { } } 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 --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml index 44c996f7eea..e07ad68fbed 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml @@ -40,7 +40,7 @@ - +