# HG changeset patch # User dlong # Date 1572566056 25200 # Node ID aec7bf35d6f5db79b292591db664caef224e4136 # Parent 1a8d65e71a66da59e0befe7ae76a8eb9f4c2891a 8233273: Update Graal Reviewed-by: kvn diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicMap.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicMap.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicMap.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicSet.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicSet.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicSet.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Equivalence.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Equivalence.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Equivalence.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/MapCursor.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/MapCursor.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/MapCursor.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Pair.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Pair.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Pair.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicMap.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicMap.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicMap.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicSet.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicSet.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicSet.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableMapCursor.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableMapCursor.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableMapCursor.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/ComparableWord.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/ComparableWord.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/ComparableWord.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/LocationIdentity.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/LocationIdentity.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/LocationIdentity.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/Pointer.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/Pointer.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/Pointer.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/PointerBase.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/PointerBase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/PointerBase.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/SignedWord.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/SignedWord.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/SignedWord.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/UnsignedWord.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/UnsignedWord.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/UnsignedWord.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordBase.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordBase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordBase.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordFactory.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordFactory.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordFactory.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java --- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, 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 @@ -35,9 +35,7 @@ /** * Denotes a method whose body is used by a compiler as the substitute (or intrinsification) of * 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. + * compiler should require substitute methods to be annotated with {@link MethodSubstitution}. * * 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 diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitutionRegistry.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitutionRegistry.java Thu Oct 31 14:23:06 2019 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -package org.graalvm.compiler.api.replacements; - -import java.lang.reflect.Type; - -/** - * A registry for {@link MethodSubstitution}s. - */ -public interface MethodSubstitutionRegistry { - - /** - * Gets the type representing the receiver (i.e., {@code this}) argument in a non-static method. - */ - Class getReceiverType(); - - /** - * Registers a substitution method. - * - * @param substituteDeclaringClass the class declaring the substitute method - * @param name the name of both the original and substitute method - * @param argumentTypes the argument types of the method. Element 0 of this array must be - * {@link #getReceiverType()} iff the method is non-static. Upon returning, element 0 - * will have been rewritten to {@code declaringClass}. - */ - default void registerMethodSubstitution(Class substituteDeclaringClass, String name, Type... argumentTypes) { - registerMethodSubstitution(substituteDeclaringClass, name, name, argumentTypes); - } - - /** - * Registers a substitution method. - * - * @param substituteDeclaringClass the class declaring the substitute method - * @param name the name of both the original method - * @param substituteName the name of the substitute method - * @param argumentTypes the argument types of the method. Element 0 of this array must be - * {@link #getReceiverType()} iff the method is non-static. Upon returning, element 0 - * will have been rewritten to {@code declaringClass}. - */ - void registerMethodSubstitution(Class substituteDeclaringClass, String name, String substituteName, Type... argumentTypes); -} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/ExportingClassLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/ExportingClassLoader.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016, 2019, 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.api.test; + +/** + * A class loader that exports all packages in the module defining the class loader to all classes + * in the unnamed module associated with the loader. + */ +public class ExportingClassLoader extends ClassLoader { + public ExportingClassLoader() { + ModuleSupport.exportAllPackagesTo(getClass(), this); + } + + public ExportingClassLoader(ClassLoader parent) { + super(parent); + ModuleSupport.exportAllPackagesTo(getClass(), this); + } +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/ModuleSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/ModuleSupport.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2019, 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.api.test; + +import java.io.IOException; +import java.lang.module.ModuleDescriptor.Requires; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.graalvm.compiler.debug.DebugOptions; + +import jdk.internal.module.Modules; + +public class ModuleSupport { + + public static void exportPackageTo(Class moduleMember, String packageName, Class requestor) { + Module moduleToExport = moduleMember.getModule(); + Module requestorModule = requestor.getModule(); + if (moduleToExport != requestorModule) { + Modules.addExports(moduleToExport, packageName, requestorModule); + } + } + + public static void exportAllPackagesTo(Class moduleMember, Class requestor) { + Module moduleToExport = moduleMember.getModule(); + Module requestorModule = requestor.getModule(); + if (moduleToExport != requestorModule) { + for (String packageName : moduleToExport.getPackages()) { + Modules.addExports(moduleToExport, packageName, requestorModule); + } + } + } + + public static void exportAllPackagesTo(Class moduleMember, ClassLoader cl) { + Module moduleToExport = moduleMember.getModule(); + Module unnamedModule = cl.getUnnamedModule(); + for (String packageName : moduleToExport.getPackages()) { + Modules.addExports(moduleToExport, packageName, unnamedModule); + } + } + + @SuppressWarnings("unused") + public static void exportAndOpenAllPackagesToUnnamed(String name) { + Module module = ModuleLayer.boot().findModule(name).orElseThrow(); + Set packages = module.getPackages(); + for (String pkg : packages) { + Modules.addExportsToAllUnnamed(module, pkg); + Modules.addOpensToAllUnnamed(module, pkg); + } + } + + public static List getJRTGraalClassNames() throws IOException { + List classNames = new ArrayList<>(); + FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), Collections.emptyMap()); + Module graalModule = DebugOptions.class.getModule(); + Set graalModuleSet = new HashSet<>(); + graalModuleSet.add(graalModule.getName()); + for (Module module : graalModule.getLayer().modules()) { + if (requires(module, graalModule)) { + graalModuleSet.add(module.getName()); + } + } + + Path top = fs.getPath("/modules/"); + Files.find(top, Integer.MAX_VALUE, + (path, attrs) -> attrs.isRegularFile()).forEach(p -> { + int nameCount = p.getNameCount(); + if (nameCount > 2) { + String base = p.getName(nameCount - 1).toString(); + if (base.endsWith(".class") && !base.equals("module-info.class")) { + String module = p.getName(1).toString(); + if (graalModuleSet.contains(module)) { + // Strip module prefix and convert to dotted + // form + String className = p.subpath(2, nameCount).toString().replace('/', '.'); + // Strip ".class" suffix + className = className.replace('/', '.').substring(0, className.length() - ".class".length()); + classNames.add(className); + } + } + } + }); + return classNames; + } + + private static boolean requires(Module module, Module graalModule) { + ModuleLayer graalLayer = graalModule.getLayer(); + for (Requires r : module.getDescriptor().requires()) { + if (r.name().equals(graalModule.getName())) { + return true; + } + Module dep = graalLayer.findModule(r.name()).get(); + if (requires(dep, graalModule)) { + return true; + } + } + return false; + } +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java Thu Oct 31 16:54:16 2019 -0700 @@ -471,6 +471,7 @@ private static final int AddSubExtendedOp = 0x0B200000; private static final int MulOp = 0x1B000000; + private static final int SignedMulLongOp = 0x9B200000; private static final int DataProcessing1SourceOp = 0x5AC00000; private static final int DataProcessing2SourceOp = 0x1AC00000; @@ -2313,7 +2314,7 @@ } /** - * unsigned multiply high. dst = (src1 * src2)[127:64] + * Unsigned multiply high. dst = (src1 * src2)[127:64] * * @param dst general purpose register. May not be null or the stackpointer. * @param src1 general purpose register. May not be null or the stackpointer. @@ -2327,7 +2328,7 @@ } /** - * unsigned multiply add-long. xDst = xSrc3 + (wSrc1 * wSrc2) + * Unsigned multiply add-long. xDst = xSrc3 + (wSrc1 * wSrc2) * * @param dst general purpose register. May not be null or the stackpointer. * @param src1 general purpose register. May not be null or the stackpointer. @@ -2343,7 +2344,7 @@ } /** - * signed multiply add-long. xDst = xSrc3 + (wSrc1 * wSrc2) + * Signed multiply-add long. xDst = xSrc3 + (wSrc1 * wSrc2) * * @param dst general purpose register. May not be null or the stackpointer. * @param src1 general purpose register. May not be null or the stackpointer. @@ -2351,11 +2352,19 @@ * @param src3 general purpose register. May not be null or the stackpointer. */ public void smaddl(Register dst, Register src1, Register src2, Register src3) { - assert !dst.equals(sp); - assert !src1.equals(sp); - assert !src2.equals(sp); - assert !src3.equals(sp); - emitInt(0b10011011001 << 21 | dst.encoding | rs1(src1) | rs2(src2) | rs3(src3)); + smullInstruction(MADD, dst, src1, src2, src3); + } + + /** + * Signed multiply-sub long. xDst = xSrc3 - (wSrc1 * wSrc2) + * + * @param dst general purpose register. May not be null or the stackpointer. + * @param src1 general purpose register. May not be null or the stackpointer. + * @param src2 general purpose register. May not be null or the stackpointer. + * @param src3 general purpose register. May not be null or the stackpointer. + */ + public void smsubl(Register dst, Register src1, Register src2, Register src3) { + smullInstruction(MSUB, dst, src1, src2, src3); } private void mulInstruction(Instruction instr, Register dst, Register src1, Register src2, Register src3, InstructionType type) { @@ -2366,6 +2375,14 @@ emitInt(type.encoding | instr.encoding | MulOp | rd(dst) | rs1(src1) | rs2(src2) | rs3(src3)); } + private void smullInstruction(Instruction instr, Register dst, Register src1, Register src2, Register src3) { + assert !dst.equals(sp); + assert !src1.equals(sp); + assert !src2.equals(sp); + assert !src3.equals(sp); + emitInt(instr.encoding | SignedMulLongOp | rd(dst) | rs1(src1) | rs2(src2) | rs3(src3)); + } + /** * Signed divide. dst = src1 / src2. * diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java Thu Oct 31 16:54:16 2019 -0700 @@ -817,7 +817,7 @@ } /** - * unsigned multiply high. dst = (src1 * src2) >> size + * Unsigned multiply high. dst = (src1 * src2) >> size * * @param size register size. Has to be 32 or 64. * @param dst general purpose register. May not be null or the stackpointer. @@ -838,7 +838,7 @@ } /** - * signed multiply high. dst = (src1 * src2) >> size + * Signed multiply high. dst = (src1 * src2) >> size * * @param size register size. Has to be 32 or 64. * @param dst general purpose register. May not be null or the stackpointer. @@ -859,6 +859,60 @@ } /** + * Signed multiply long. xDst = wSrc1 * wSrc2 + * + * @param size destination register size. Has to be 64. + * @param dst 64-bit general purpose register. May not be null or the stackpointer. + * @param src1 32-bit general purpose register. May not be null or the stackpointer. + * @param src2 32-bit general purpose register. May not be null or the stackpointer. + */ + public void smull(int size, Register dst, Register src1, Register src2) { + this.smaddl(size, dst, src1, src2, zr); + } + + /** + * Signed multiply-negate long. xDst = -(wSrc1 * wSrc2) + * + * @param size destination register size. Has to be 64. + * @param dst 64-bit general purpose register. May not be null or the stackpointer. + * @param src1 32-bit general purpose register. May not be null or the stackpointer. + * @param src2 32-bit general purpose register. May not be null or the stackpointer. + */ + public void smnegl(int size, Register dst, Register src1, Register src2) { + this.smsubl(size, dst, src1, src2, zr); + } + + /** + * Signed multiply-add long. xDst = xSrc3 + (wSrc1 * wSrc2) + * + * @param size destination register size. Has to be 64. + * @param dst 64-bit general purpose register. May not be null or the stackpointer. + * @param src1 32-bit general purpose register. May not be null or the stackpointer. + * @param src2 32-bit general purpose register. May not be null or the stackpointer. + * @param src3 64-bit general purpose register. May not be null or the stackpointer. + */ + public void smaddl(int size, Register dst, Register src1, Register src2, Register src3) { + assert (!dst.equals(sp) && !src1.equals(sp) && !src2.equals(sp) && !src3.equals(sp)); + assert size == 64; + super.smaddl(dst, src1, src2, src3); + } + + /** + * Signed multiply-sub long. xDst = xSrc3 - (wSrc1 * wSrc2) + * + * @param size destination register size. Has to be 64. + * @param dst 64-bit general purpose register. May not be null or the stackpointer. + * @param src1 32-bit general purpose register. May not be null or the stackpointer. + * @param src2 32-bit general purpose register. May not be null or the stackpointer. + * @param src3 64-bit general purpose register. May not be null or the stackpointer. + */ + public void smsubl(int size, Register dst, Register src1, Register src2, Register src3) { + assert (!dst.equals(sp) && !src1.equals(sp) && !src2.equals(sp) && !src3.equals(sp)); + assert size == 64; + super.smsubl(dst, src1, src2, src3); + } + + /** * dst = src1 % src2. Signed. * * @param size register size. Has to be 32 or 64. diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64MultiplyLongTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64MultiplyLongTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, Arm Limited. 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.aarch64.test; + +import org.junit.Test; + +public class AArch64MultiplyLongTest extends AArch64MatchRuleTest { + + public long signedMulLong(int a, int b) { + return a * (long) b; + } + + public long signedMulLongFromShort(short a, short b) { + return (long) a * b; + } + + public long signedMulLongFromChar(char a, char b) { + return a * (long) b; + } + + public long signedMulLongFromByte(byte a, byte b) { + return (long) a * b; + } + + @Test + public void testSignedMulLong() { + test("signedMulLong", 0x12345678, 0x87654321); + checkLIR("signedMulLong", op -> op.name().equals("SMULL"), 1); + test("signedMulLongFromShort", (short) 32767, (short) -32768); + checkLIR("signedMulLongFromShort", op -> op.name().equals("SMULL"), 1); + test("signedMulLongFromChar", (char) 59999, (char) 65535); + checkLIR("signedMulLongFromChar", op -> op.name().equals("SMULL"), 1); + test("signedMulLongFromByte", (byte) 10, (byte) -256); + checkLIR("signedMulLongFromByte", op -> op.name().equals("SMULL"), 1); + } + + public long signedMNegLong1(int a, int b) { + return -(a * (long) b); + } + + public long signedMNegLong2(int a, int b) { + return a * (-(long) b); + } + + @Test + public void testSignedMNegLong() { + test("signedMNegLong1", 0x89abcdef, 0xfedcba98); + checkLIR("signedMNegLong1", op -> op.name().equals("SMNEGL"), 1); + test("signedMNegLong2", 0x89abcdef, 0xfedcba98); + checkLIR("signedMNegLong2", op -> op.name().equals("SMNEGL"), 1); + } + + public long signedMAddLong1(int a, int b, long c) { + return c + a * (long) b; + } + + public long signedMAddLong2(int a, int b, long c) { + return a * (long) b + c; + } + + @Test + public void testSignedMAddLong() { + test("signedMAddLong1", 0x22228888, 0xaaaacccc, 0x123456789abcdL); + checkLIR("signedMAddLong1", op -> op.name().equals("SMADDL"), 1); + test("signedMAddLong2", 0x22228888, 0xaaaacccc, 0x123456789abcdL); + checkLIR("signedMAddLong2", op -> op.name().equals("SMADDL"), 1); + } + + public long signedMSubLong(int a, int b, long c) { + return c - a * (long) b; + } + + @Test + public void testSignedMSubLong() { + test("signedMSubLong", 0x99995555, 0xeeeebbbb, 0x3456789abcdefL); + checkLIR("signedMSubLong", op -> op.name().equals("SMSUBL"), 1); + } +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java Thu Oct 31 16:54:16 2019 -0700 @@ -220,23 +220,34 @@ return result; } - public Value emitMAdd(Value a, Value b, Value c) { - return emitMultiplyAddSub(AArch64ArithmeticOp.ADD, a, b, c); + Value emitIntegerMAdd(Value a, Value b, Value c, boolean isI2L) { + return emitMultiplyAddSub(isI2L ? AArch64ArithmeticOp.SMADDL : AArch64ArithmeticOp.MADD, a, b, c); } - public Value emitMSub(Value a, Value b, Value c) { - return emitMultiplyAddSub(AArch64ArithmeticOp.SUB, a, b, c); + Value emitIntegerMSub(Value a, Value b, Value c, boolean isI2L) { + return emitMultiplyAddSub(isI2L ? AArch64ArithmeticOp.SMSUBL : AArch64ArithmeticOp.MSUB, a, b, c); } private Value emitMultiplyAddSub(AArch64ArithmeticOp op, Value a, Value b, Value c) { - assert a.getPlatformKind() == b.getPlatformKind() && b.getPlatformKind() == c.getPlatformKind(); - if (op == AArch64ArithmeticOp.ADD || op == AArch64ArithmeticOp.SUB) { - assert isNumericInteger(a.getPlatformKind()); - } else if (op == AArch64ArithmeticOp.FADD) { - assert a.getPlatformKind() == AArch64Kind.SINGLE || a.getPlatformKind() == AArch64Kind.DOUBLE; + assert a.getPlatformKind() == b.getPlatformKind(); + Variable result; + if (op == AArch64ArithmeticOp.SMADDL || op == AArch64ArithmeticOp.SMSUBL) { + // For signed multiply int and then add/sub long. + assert a.getPlatformKind() != c.getPlatformKind(); + result = getLIRGen().newVariable(LIRKind.combine(c)); + } else { + assert a.getPlatformKind() == c.getPlatformKind(); + if (op == AArch64ArithmeticOp.FADD) { + // For floating-point Math.fma intrinsic. + assert a.getPlatformKind() == AArch64Kind.SINGLE || a.getPlatformKind() == AArch64Kind.DOUBLE; + } else { + // For int/long multiply add or sub. + assert op == AArch64ArithmeticOp.MADD || op == AArch64ArithmeticOp.MSUB; + assert isNumericInteger(a.getPlatformKind()); + } + result = getLIRGen().newVariable(LIRKind.combine(a, b, c)); } - Variable result = getLIRGen().newVariable(LIRKind.combine(a, b, c)); AllocatableValue x = moveSp(asAllocatable(a)); AllocatableValue y = moveSp(asAllocatable(b)); AllocatableValue z = moveSp(asAllocatable(c)); @@ -451,7 +462,7 @@ @Override public Value emitFusedMultiplyAdd(Value a, Value b, Value c) { - return emitMultiplyAddSub(AArch64ArithmeticOp.FADD, a, b, c); + return emitMultiplyAddSub(AArch64ArithmeticOp.FMADD, a, b, c); } @Override diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java Thu Oct 31 16:54:16 2019 -0700 @@ -57,6 +57,7 @@ import org.graalvm.compiler.nodes.calc.BinaryNode; import org.graalvm.compiler.nodes.calc.IntegerLessThanNode; import org.graalvm.compiler.nodes.calc.LeftShiftNode; +import org.graalvm.compiler.nodes.calc.MulNode; import org.graalvm.compiler.nodes.calc.NotNode; import org.graalvm.compiler.nodes.calc.OrNode; import org.graalvm.compiler.nodes.calc.RightShiftNode; @@ -224,6 +225,33 @@ return emitBinaryShift(op, a, shift, isShiftNot); } + @MatchRule("(Add=binary (Mul (SignExtend a) (SignExtend b)) c)") + @MatchRule("(Sub=binary c (Mul (SignExtend a) (SignExtend b)))") + public ComplexMatchResult signedMultiplyAddSubLong(BinaryNode binary, ValueNode a, ValueNode b, ValueNode c) { + assert a.getStackKind() == JavaKind.Int && b.getStackKind() == JavaKind.Int && c.getStackKind() == JavaKind.Long; + if (binary instanceof AddNode) { + return builder -> getArithmeticLIRGenerator().emitIntegerMAdd(operand(a), operand(b), operand(c), true); + } + return builder -> getArithmeticLIRGenerator().emitIntegerMSub(operand(a), operand(b), operand(c), true); + } + + @MatchRule("(Negate (Mul=mul (SignExtend a) (SignExtend b)))") + @MatchRule("(Mul=mul (Negate (SignExtend a)) (SignExtend b))") + public ComplexMatchResult signedMultiplyNegLong(MulNode mul, ValueNode a, ValueNode b) { + assert a.getStackKind() == JavaKind.Int && b.getStackKind() == JavaKind.Int; + LIRKind resultKind = LIRKind.fromJavaKind(gen.target().arch, mul.getStackKind()); + return builder -> getArithmeticLIRGenerator().emitBinary( + resultKind, AArch64ArithmeticOp.SMNEGL, true, operand(a), operand(b)); + } + + @MatchRule("(Mul=mul (SignExtend a) (SignExtend b))") + public ComplexMatchResult signedMultiplyLong(MulNode mul, ValueNode a, ValueNode b) { + assert a.getStackKind() == JavaKind.Int && b.getStackKind() == JavaKind.Int; + LIRKind resultKind = LIRKind.fromJavaKind(gen.target().arch, mul.getStackKind()); + return builder -> getArithmeticLIRGenerator().emitBinary( + resultKind, AArch64ArithmeticOp.SMULL, true, operand(a), operand(b)); + } + @MatchRule("(Mul (Negate a) b)") @MatchRule("(Negate (Mul a b))") public ComplexMatchResult multiplyNegate(ValueNode a, ValueNode b) { @@ -244,9 +272,9 @@ } if (binary instanceof AddNode) { - return builder -> getArithmeticLIRGenerator().emitMAdd(operand(a), operand(b), operand(c)); + return builder -> getArithmeticLIRGenerator().emitIntegerMAdd(operand(a), operand(b), operand(c), false); } - return builder -> getArithmeticLIRGenerator().emitMSub(operand(a), operand(b), operand(c)); + return builder -> getArithmeticLIRGenerator().emitIntegerMSub(operand(a), operand(b), operand(c), false); } /** diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java Thu Oct 31 16:54:16 2019 -0700 @@ -359,6 +359,7 @@ @MatchRule("(If (IntegerTest Read=access value))") @MatchRule("(If (IntegerTest FloatingRead=access value))") + @MatchRule("(If (IntegerTest VolatileRead=access value))") public ComplexMatchResult integerTestBranchMemory(IfNode root, LIRLowerableAccess access, ValueNode value) { return emitIntegerTestBranchMemory(root, value, access); } @@ -369,14 +370,21 @@ @MatchRule("(If (IntegerEquals=compare value FloatingRead=access))") @MatchRule("(If (IntegerLessThan=compare value FloatingRead=access))") @MatchRule("(If (IntegerBelow=compare value FloatingRead=access))") + @MatchRule("(If (IntegerEquals=compare value VolatileRead=access))") + @MatchRule("(If (IntegerLessThan=compare value VolatileRead=access))") + @MatchRule("(If (IntegerBelow=compare value VolatileRead=access))") @MatchRule("(If (FloatEquals=compare value Read=access))") @MatchRule("(If (FloatEquals=compare value FloatingRead=access))") + @MatchRule("(If (FloatEquals=compare value VolatileRead=access))") @MatchRule("(If (FloatLessThan=compare value Read=access))") @MatchRule("(If (FloatLessThan=compare value FloatingRead=access))") + @MatchRule("(If (FloatLessThan=compare value VolatileRead=access))") @MatchRule("(If (PointerEquals=compare value Read=access))") @MatchRule("(If (PointerEquals=compare value FloatingRead=access))") + @MatchRule("(If (PointerEquals=compare value VolatileRead=access))") @MatchRule("(If (ObjectEquals=compare value Read=access))") @MatchRule("(If (ObjectEquals=compare value FloatingRead=access))") + @MatchRule("(If (ObjectEquals=compare value VolatileRead=access))") public ComplexMatchResult ifCompareMemory(IfNode root, CompareNode compare, ValueNode value, LIRLowerableAccess access) { return emitCompareBranchMemory(root, compare, value, access); } @@ -478,6 +486,7 @@ @MatchRule("(Add value Read=access)") @MatchRule("(Add value FloatingRead=access)") + @MatchRule("(Add value VolatileRead=access)") public ComplexMatchResult addMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { @@ -493,6 +502,7 @@ @MatchRule("(Sub value Read=access)") @MatchRule("(Sub value FloatingRead=access)") + @MatchRule("(Sub value VolatileRead=access)") public ComplexMatchResult subMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { @@ -508,6 +518,7 @@ @MatchRule("(Mul value Read=access)") @MatchRule("(Mul value FloatingRead=access)") + @MatchRule("(Mul value VolatileRead=access)") public ComplexMatchResult mulMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { @@ -523,6 +534,7 @@ @MatchRule("(And value Read=access)") @MatchRule("(And value FloatingRead=access)") + @MatchRule("(And value VolatileRead=access)") public ComplexMatchResult andMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { @@ -534,6 +546,7 @@ @MatchRule("(Or value Read=access)") @MatchRule("(Or value FloatingRead=access)") + @MatchRule("(Or value VolatileRead=access)") public ComplexMatchResult orMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { @@ -545,6 +558,7 @@ @MatchRule("(Xor value Read=access)") @MatchRule("(Xor value FloatingRead=access)") + @MatchRule("(Xor value VolatileRead=access)") public ComplexMatchResult xorMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { @@ -565,12 +579,14 @@ @MatchRule("(SignExtend Read=access)") @MatchRule("(SignExtend FloatingRead=access)") + @MatchRule("(SignExtend VolatileRead=access)") public ComplexMatchResult signExtend(SignExtendNode root, LIRLowerableAccess access) { return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits(), null); } @MatchRule("(ZeroExtend Read=access)") @MatchRule("(ZeroExtend FloatingRead=access)") + @MatchRule("(ZeroExtend VolatileRead=access)") public ComplexMatchResult zeroExtend(ZeroExtendNode root, LIRLowerableAccess access) { AMD64Kind memoryKind = getMemoryKind(access); return builder -> getArithmeticLIRGenerator().emitZeroExtendMemory(memoryKind, root.getResultBits(), (AMD64AddressValue) operand(access.getAddress()), getState(access)); @@ -578,6 +594,7 @@ @MatchRule("(Narrow Read=access)") @MatchRule("(Narrow FloatingRead=access)") + @MatchRule("(Narrow VolatileRead=access)") public ComplexMatchResult narrowRead(NarrowNode root, LIRLowerableAccess access) { return new ComplexMatchResult() { @Override @@ -595,6 +612,7 @@ @MatchRule("(SignExtend (Narrow=narrow Read=access))") @MatchRule("(SignExtend (Narrow=narrow FloatingRead=access))") + @MatchRule("(SignExtend (Narrow=narrow VolatileRead=access))") public ComplexMatchResult signExtendNarrowRead(SignExtendNode root, NarrowNode narrow, LIRLowerableAccess access) { LIRKind kind = getLIRGeneratorTool().getLIRKind(narrow.stamp(NodeView.DEFAULT)); return emitSignExtendMemory(access, narrow.getResultBits(), root.getResultBits(), kind); @@ -602,6 +620,7 @@ @MatchRule("(FloatConvert Read=access)") @MatchRule("(FloatConvert FloatingRead=access)") + @MatchRule("(FloatConvert VolatileRead=access)") public ComplexMatchResult floatConvert(FloatConvertNode root, LIRLowerableAccess access) { switch (root.getFloatConvert()) { case D2F: @@ -631,6 +650,7 @@ @MatchRule("(Reinterpret Read=access)") @MatchRule("(Reinterpret FloatingRead=access)") + @MatchRule("(Reinterpret VolatileRead=access)") public ComplexMatchResult reinterpret(ReinterpretNode root, LIRLowerableAccess access) { return builder -> { LIRKind kind = getLIRGeneratorTool().getLIRKind(root.stamp(NodeView.DEFAULT)); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Thu Oct 31 16:54:16 2019 -0700 @@ -115,7 +115,7 @@ public static final OptionKey PartialUnroll = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionKey MinimumPeelProbability = new OptionKey<>(0.35f); + public static final OptionKey MinimumPeelFrequency = new OptionKey<>(0.35f); @Option(help = "", type = OptionType.Expert) public static final OptionKey LoopMaxUnswitch = new OptionKey<>(3); @@ -242,9 +242,6 @@ public static final OptionKey OptImplicitNullChecks = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionKey OptLoopTransform = new OptionKey<>(true); - - @Option(help = "", type = OptionType.Debug) public static final OptionKey OptFloatingReads = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) @@ -291,4 +288,7 @@ @Option(help = "Alignment in bytes for loop header blocks.", type = OptionType.Expert) public static final OptionKey LoopHeaderAlignment = new OptionKey<>(16); + + @Option(help = "Do not include membars for volatile accesses until the end of optimizations.", type = OptionType.Expert) + public static final OptionKey LateMembars = new OptionKey<>(true); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java Thu Oct 31 16:54:16 2019 -0700 @@ -94,6 +94,38 @@ return dominator; } + /** + * Returns the next dominator of this block that is either in the same loop of this block or in + * an outer loop. + * + * @return the next dominator while skipping over loops + */ + public T getDominatorSkipLoops() { + T d = getDominator(); + + if (d == null) { + // We are at the start block and don't have a dominator. + return null; + } + + if (isLoopHeader()) { + // We are moving out of current loop => just return dominator. + assert d.getLoopDepth() == getLoopDepth() - 1; + assert d.getLoop() != getLoop(); + return d; + } + + while (d.getLoop() != getLoop()) { + // We have a case where our dominator is in a different loop. Move further along + // the domiantor tree until we hit our loop again. + d = d.getDominator(); + } + + assert d.getLoopDepth() <= getLoopDepth(); + + return d; + } + public void setDominator(T dominator) { this.dominator = dominator; this.domDepth = dominator.domDepth + 1; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, 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 @@ -46,7 +46,7 @@ T getStartBlock(); /** - * True if block {@code a} is dominated by block {@code b}. + * True if block {@code a} is dominated by block {@code b} or {@code a} is equal to {@code b}. */ static boolean isDominatedBy(AbstractBlockBase a, AbstractBlockBase b) { int domNumberA = a.getDominatorNumber(); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java Thu Oct 31 16:54:16 2019 -0700 @@ -177,25 +177,6 @@ return true; } - /** - * Determines if one loop is a transitive parent of another loop. - * - * @param childLoop The loop for which parentLoop might be a transitive parent loop. - * @param parentLoop The loop which might be a transitive parent loop of child loop. - * @return {@code true} if parentLoop is a (transitive) parent loop of childLoop, {@code false} - * otherwise - */ - public static > boolean transitiveParentLoop(Loop childLoop, Loop parentLoop) { - Loop curr = childLoop; - while (curr != null) { - if (curr == parentLoop) { - return true; - } - curr = curr.getParent(); - } - return false; - } - @Override public int hashCode() { return index + depth * 31; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java Thu Oct 31 16:54:16 2019 -0700 @@ -167,8 +167,15 @@ @Override public Stamp constant(Constant c, MetaAccessProvider meta) { if (c instanceof PrimitiveConstant) { - long value = ((PrimitiveConstant) c).asLong(); - return StampFactory.forInteger(getBits(), value, value); + PrimitiveConstant primitiveConstant = (PrimitiveConstant) c; + long value = primitiveConstant.asLong(); + if (primitiveConstant.getJavaKind() == JavaKind.Boolean && value == 1) { + // Need to special case booleans as integer stamps are always signed values. + value = -1; + } + Stamp returnedStamp = StampFactory.forInteger(getBits(), value, value); + assert returnedStamp.hasValues(); + return returnedStamp; } return this; } @@ -1605,7 +1612,10 @@ long newUpMask = stamp.upMask() & defaultMask; long newLowerBound = CodeUtil.signExtend((lowerBound | newDownMask) & newUpMask, resultBits); long newUpperBound = CodeUtil.signExtend((upperBound | newDownMask) & newUpMask, resultBits); - return new IntegerStamp(resultBits, newLowerBound, newUpperBound, newDownMask, newUpMask); + + IntegerStamp result = new IntegerStamp(resultBits, newLowerBound, newUpperBound, newDownMask, newUpMask); + assert result.hasValues(); + return result; } }, diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java Thu Oct 31 16:54:16 2019 -0700 @@ -134,12 +134,14 @@ @MatchRule("(SignExtend Read=access)") @MatchRule("(SignExtend FloatingRead=access)") + @MatchRule("(SignExtend VolatileRead=access)") public ComplexMatchResult signExtend(SignExtendNode root, Access access) { return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits()); } @MatchRule("(ZeroExtend Read=access)") @MatchRule("(ZeroExtend FloatingRead=access)") + @MatchRule("(ZeroExtend VolatileRead=access)") public ComplexMatchResult zeroExtend(ZeroExtendNode root, Access access) { return emitZeroExtendMemory(access, root.getInputBits(), root.getResultBits()); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -313,7 +313,7 @@ graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); createInliningPhase().apply(graph, context); - new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); + new PartialEscapePhase(false, createCanonicalizerPhase(), graph.getOptions()).apply(graph, context); } private void compareGraphs(final String snippet, final String referenceSnippet) { @@ -323,7 +323,7 @@ private void compareGraphs(final String snippet, final String referenceSnippet, final boolean loopPeeling, final boolean excludeVirtual) { graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(); canonicalizer.apply(graph, context); createInliningPhase().apply(graph, context); if (loopPeeling) { @@ -339,7 +339,7 @@ StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES); createInliningPhase().apply(referenceGraph, context); new DeadCodeEliminationPhase().apply(referenceGraph); - new CanonicalizerPhase().apply(referenceGraph, context); + this.createCanonicalizerPhase().apply(referenceGraph, context); assertEquals(referenceGraph, graph, excludeVirtual, true); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Thu Oct 31 16:54:16 2019 -0700 @@ -78,7 +78,7 @@ import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.compiler.test.AddExports; -import org.graalvm.compiler.test.ModuleSupport; +import org.graalvm.compiler.api.test.ModuleSupport; import jdk.internal.vm.compiler.word.LocationIdentity; import org.junit.Assert; import org.junit.Assume; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -31,14 +31,13 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConditionalNode; import org.graalvm.compiler.nodes.calc.IntegerTestNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; public class CompareCanonicalizerTest extends GraalCompilerTest { private StructuredGraph getCanonicalizedGraph(String name) { StructuredGraph graph = parseEager(name, AllowAssumptions.YES); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); return graph; } @@ -55,7 +54,7 @@ StructuredGraph graph = parseEager("canonicalCompare" + i, AllowAssumptions.NO); assertEquals(referenceGraph, graph); } - new CanonicalizerPhase().apply(referenceGraph, getProviders()); + createCanonicalizerPhase().apply(referenceGraph, getProviders()); for (int i = 1; i < 4; i++) { StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i); assertEquals(referenceGraph, graph); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java Thu Oct 31 16:54:16 2019 -0700 @@ -26,7 +26,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; public class CompareCanonicalizerTest2 extends GraalCompilerTest { @@ -35,7 +34,7 @@ private StructuredGraph getCanonicalizedGraph(String name) { StructuredGraph graph = getRegularGraph(name); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); return graph; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java Thu Oct 31 16:54:16 2019 -0700 @@ -239,7 +239,7 @@ protected void assertCanonicallyEqual(String snippet, String reference) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); CoreProviders context = getProviders(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(); canonicalizer.apply(graph, context); new GuardLoweringPhase().apply(graph, new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo())); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, 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 @@ -78,7 +78,7 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); new ConditionalEliminationPhase(false).apply(graph, context); - CanonicalizerPhase c = new CanonicalizerPhase(); + CanonicalizerPhase c = createCanonicalizerPhase(); c.apply(graph, context); new ConditionalEliminationPhase(false).apply(graph, context); c.apply(graph, context); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java Thu Oct 31 16:54:16 2019 -0700 @@ -30,7 +30,6 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.junit.Assert; @@ -95,7 +94,7 @@ private void test(String snippet, int guardCount) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); CoreProviders context = getProviders(); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new ConditionalEliminationPhase(true).apply(graph, context); Assert.assertEquals(guardCount, graph.getNodes().filter(GuardNode.class).count()); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest14.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest14.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest14.java Thu Oct 31 16:54:16 2019 -0700 @@ -70,7 +70,7 @@ @Test public void test1() { StructuredGraph graph = parseEager("test1Snippet", AllowAssumptions.YES); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); CoreProviders context = getProviders(); /* Convert the LoadIndexNode to ReadNode with floating guards. */ diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest15.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest15.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest15.java Thu Oct 31 16:54:16 2019 -0700 @@ -47,10 +47,10 @@ private void checkNodeCount(String methodName, Class nodeClass, int count) { StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(); CoreProviders context = getProviders(); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new LoweringPhase(this.createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); // Merge arr.length reads. diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest16.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest16.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest16.java Thu Oct 31 16:54:16 2019 -0700 @@ -31,7 +31,6 @@ import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Before; import org.junit.Test; @@ -69,7 +68,7 @@ break; } } - new CanonicalizerPhase().apply(graph, getDefaultHighTierContext()); + this.createCanonicalizerPhase().apply(graph, getDefaultHighTierContext()); } super.checkHighTierGraph(graph); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java Thu Oct 31 16:54:16 2019 -0700 @@ -109,7 +109,7 @@ @Test public void testRedundantCompares() { StructuredGraph graph = parseEager("testRedundantComparesSnippet", AllowAssumptions.YES); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); CoreProviders context = getProviders(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); @@ -132,7 +132,7 @@ public void testInstanceOfCheckCastLowered() { StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet", AllowAssumptions.YES); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); CoreProviders context = getProviders(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); @@ -146,7 +146,7 @@ private void checkInstanceOfCount(String methodName, int count) { StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(); CoreProviders context = getProviders(); canonicalizer.apply(graph, context); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Thu Oct 31 16:54:16 2019 -0700 @@ -69,8 +69,8 @@ DebugContext debug = graph.getDebug(); debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); CoreProviders context = getProviders(); - CanonicalizerPhase canonicalizer1 = new CanonicalizerPhase(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer1 = createCanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); try (DebugContext.Scope scope = debug.scope("ConditionalEliminationTest", graph)) { prepareGraph(graph, canonicalizer1, context, applyLowering); new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context); @@ -106,10 +106,9 @@ public void testProxies(String snippet, int expectedProxiesCreated) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); CoreProviders context = getProviders(); - CanonicalizerPhase canonicalizer1 = new CanonicalizerPhase(); - canonicalizer1.disableSimplification(); + CanonicalizerPhase canonicalizer1 = CanonicalizerPhase.createWithoutCFGSimplification(); canonicalizer1.apply(graph, context); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -43,6 +43,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.junit.Test; @@ -559,7 +560,7 @@ } public void rewrite(LoopsData loops) { - InductionVariable inductionVariable = loops.getInductionVariable(iv); + InductionVariable inductionVariable = loops.getInductionVariable(GraphUtil.unproxify(iv)); ValueNode node = null; if (inductionVariable == null) { assert loopCanBeRemoved; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DeMorganCanonicalizationTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DeMorganCanonicalizationTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DeMorganCanonicalizationTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -29,7 +29,6 @@ import org.graalvm.compiler.nodes.calc.AndNode; import org.graalvm.compiler.nodes.calc.NotNode; import org.graalvm.compiler.nodes.calc.OrNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Assert; import org.junit.Test; @@ -46,7 +45,7 @@ @Test public void testAnd() { StructuredGraph g = parseEager("and", AllowAssumptions.NO, getInitialOptions()); - new CanonicalizerPhase().apply(g, getDefaultHighTierContext()); + createCanonicalizerPhase().apply(g, getDefaultHighTierContext()); Assert.assertEquals(1, g.getNodes().filter(OrNode.class).count()); Assert.assertEquals(1, g.getNodes().filter(NotNode.class).count()); @@ -59,7 +58,7 @@ @Test public void testOr() { StructuredGraph g = parseEager("or", AllowAssumptions.NO, getInitialOptions()); - new CanonicalizerPhase().apply(g, getDefaultHighTierContext()); + createCanonicalizerPhase().apply(g, getDefaultHighTierContext()); Assert.assertEquals(1, g.getNodes().filter(AndNode.class).count()); Assert.assertEquals(1, g.getNodes().filter(NotNode.class).count()); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -28,7 +28,6 @@ import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.junit.Test; @@ -85,7 +84,7 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); HighTierContext context = getDefaultHighTierContext(); createInliningPhase().apply(graph, context); - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); debug.dump(DebugContext.BASIC_LEVEL, referenceGraph, "ReferenceGraph"); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -29,7 +29,6 @@ import org.graalvm.compiler.nodes.java.LoadIndexedNode; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; -import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.tiers.Suites; import org.junit.Assume; import org.junit.Test; @@ -157,7 +156,7 @@ return "CheckGraphPhase"; } }); - ret.getHighTier().findPhase(RemoveValueProxyPhase.class).add(new Phase() { + ret.getHighTier().addBeforeLast(new Phase() { @Override protected void run(StructuredGraph graph) { /* Re-writing of the switch cases eliminates the array load. */ diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -38,7 +38,6 @@ import org.graalvm.compiler.nodes.java.RegisterFinalizerNode; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.junit.Assert; import org.junit.Test; @@ -80,7 +79,7 @@ new GraphBuilderPhase.Instance(getProviders(), conf, OptimisticOptimizations.ALL, null).apply(graph); HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); createInliningPhase().apply(graph, context); - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); return graph; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -34,7 +34,6 @@ import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.junit.Assert; @@ -68,7 +67,7 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); CoreProviders context = getProviders(); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); ReturnNode returnNode = null; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -126,7 +126,7 @@ import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.test.AddExports; import org.graalvm.compiler.test.GraalTest; -import org.graalvm.compiler.test.ModuleSupport; +import org.graalvm.compiler.api.test.ModuleSupport; import org.junit.After; import org.junit.Assert; import org.junit.BeforeClass; @@ -643,7 +643,7 @@ } protected final BasePhase createInliningPhase() { - return createInliningPhase(new CanonicalizerPhase()); + return createInliningPhase(this.createCanonicalizerPhase()); } protected BasePhase createInliningPhase(CanonicalizerPhase canonicalizer) { @@ -1119,6 +1119,12 @@ return graph; } + protected StructuredGraph getFinalGraph(ResolvedJavaMethod method, OptionValues options) { + StructuredGraph graph = parseForCompile(method, options); + applyFrontEnd(graph); + return graph; + } + @SuppressWarnings("try") protected void applyFrontEnd(StructuredGraph graph) { DebugContext debug = graph.getDebug(); @@ -1515,4 +1521,8 @@ protected boolean isArchitecture(String name) { return name.equals(backend.getTarget().arch.getName()); } + + protected CanonicalizerPhase createCanonicalizerPhase() { + return CanonicalizerPhase.create(); + } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -35,7 +35,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.spi.CoreProviders; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -61,7 +60,7 @@ StructuredGraph originalGraph = parseEager(javaMethod, AllowAssumptions.YES); if (canonicalize) { CoreProviders context = getProviders(); - new CanonicalizerPhase().apply(originalGraph, context); + createCanonicalizerPhase().apply(originalGraph, context); } originalGraphs.add(originalGraph); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -86,7 +86,7 @@ private StructuredGraph prepareGraph(String method) { StructuredGraph graph = parseEager(method, StructuredGraph.AllowAssumptions.YES); HighTierContext highTierContext = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); new ConvertDeoptimizeToGuardPhase().apply(graph, highTierContext); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext); new FloatingReadPhase().apply(graph); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -35,7 +35,6 @@ import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.GuardLoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase; @@ -227,12 +226,12 @@ private void testCombinedIf(String snippet, int count) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); CoreProviders context = getProviders(); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); new GuardLoweringPhase().apply(graph, midContext); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); - new CanonicalizerPhase().apply(graph, context); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); + createCanonicalizerPhase().apply(graph, context); assertDeepEquals(count, graph.getNodes().filter(IfNode.class).count()); } @@ -247,7 +246,7 @@ } } debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); for (FrameState fs : param.usages().filter(FrameState.class).snapshot()) { fs.replaceFirstInput(param, null); param.safeDelete(); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ImplicitNullCheckTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ImplicitNullCheckTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ImplicitNullCheckTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -34,7 +34,6 @@ import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.GuardLoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase; @@ -72,7 +71,7 @@ try (DebugContext.Scope s = debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); CoreProviders context = getProviders(); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); MidTierContext midTierContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); new GuardLoweringPhase().apply(graph, midTierContext); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerEqualsCanonicalizerTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerEqualsCanonicalizerTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerEqualsCanonicalizerTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -27,7 +27,6 @@ import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; public class IntegerEqualsCanonicalizerTest extends GraalCompilerTest { @@ -166,7 +165,7 @@ private StructuredGraph getCanonicalizedGraph(String snippet) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); for (FrameState state : graph.getNodes(FrameState.TYPE).snapshot()) { state.replaceAtUsages(null); state.safeDelete(); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -30,7 +30,7 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.test.ExportingClassLoader; +import org.graalvm.compiler.api.test.ExportingClassLoader; import org.junit.Test; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InvokeExceptionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InvokeExceptionTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InvokeExceptionTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -30,7 +30,6 @@ import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.junit.Test; @@ -69,8 +68,8 @@ hints.put(invoke, 1000d); } HighTierContext context = getDefaultHighTierContext(); - createInliningPhase(hints, new CanonicalizerPhase()).apply(graph, context); - new CanonicalizerPhase().apply(graph, context); + createInliningPhase(hints, createCanonicalizerPhase()).apply(graph, context); + createCanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InvokeHintsTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InvokeHintsTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InvokeHintsTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -30,7 +30,6 @@ import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.junit.Test; @@ -80,8 +79,8 @@ } HighTierContext context = getDefaultHighTierContext(); - createInliningPhase(hints, new CanonicalizerPhase()).apply(graph, context); - new CanonicalizerPhase().apply(graph, context); + createInliningPhase(hints, createCanonicalizerPhase()).apply(graph, context); + createCanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.NO); assertEquals(referenceGraph, graph); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LateMembarInsertionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LateMembarInsertionTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, Red Hat Inc. 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 jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.internal.vm.compiler.collections.EconomicMap; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; +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.compiler.nodes.memory.FixedAccessNode; +import org.graalvm.compiler.nodes.memory.MemoryAccess; +import org.graalvm.compiler.nodes.memory.ReadNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.graalvm.compiler.core.common.GraalOptions.StressTestEarlyReads; + +public class LateMembarInsertionTest extends GraalCompilerTest { + + private final ResolvedJavaType volatileAccessType = getMetaAccess().lookupJavaType(VolatileAccess.class); + private final ResolvedJavaType regularAccessField = getMetaAccess().lookupJavaType(RegularAccess.class); + private final ResolvedJavaType volatileAccess2Type = getMetaAccess().lookupJavaType(VolatileAccess2.class); + + static class VolatileAccess { + static volatile int field; + } + + static class VolatileAccess2 { + static volatile int field; + } + + static class RegularAccess { + static int field; + } + + public static int volatileFieldLoadFieldLoad() { + int v1 = VolatileAccess.field; + int v2 = RegularAccess.field; + return v1 + v2; + } + + @Test + public void test01() { + List accesses = compile("volatileFieldLoadFieldLoad", stressTestEarlyReads()); + + Assert.assertEquals(accesses.size(), 2); + Assert.assertEquals(accesses.get(0).getType(), volatileAccessType); + Assert.assertEquals(accesses.get(1).getType(), regularAccessField); + Assert.assertTrue(accesses.get(0).isRead()); + Assert.assertTrue(accesses.get(1).isRead()); + } + + public static int volatileFieldLoadVolatileFieldLoad() { + int v1 = VolatileAccess.field; + int v2 = VolatileAccess2.field; + return v1 + v2; + } + + @Test + public void test02() { + List accesses = compile("volatileFieldLoadVolatileFieldLoad", stressTestEarlyReads()); + + Assert.assertEquals(accesses.size(), 2); + Assert.assertEquals(accesses.get(0).getType(), volatileAccessType); + Assert.assertEquals(accesses.get(1).getType(), volatileAccess2Type); + Assert.assertTrue(accesses.get(0).isRead()); + Assert.assertTrue(accesses.get(1).isRead()); + } + + public static int volatileFieldLoadVolatileFieldStore(int v2) { + int v1 = VolatileAccess.field; + VolatileAccess2.field = v2; + return v1; + } + + @Test + public void test03() { + List accesses = compile("volatileFieldLoadVolatileFieldStore"); + + Assert.assertEquals(accesses.size(), 2); + Assert.assertEquals(accesses.get(0).getType(), volatileAccessType); + Assert.assertEquals(accesses.get(1).getType(), volatileAccess2Type); + Assert.assertTrue(accesses.get(0).isRead()); + Assert.assertTrue(accesses.get(1).isWrite()); + } + + public static int volatileFieldStoreVolatileFieldLoad(int v2) { + VolatileAccess.field = v2; + return VolatileAccess2.field; + } + + @Test + public void test04() { + List accesses = compile("volatileFieldStoreVolatileFieldLoad", stressTestEarlyReads()); + + Assert.assertEquals(accesses.size(), 2); + Assert.assertEquals(accesses.get(0).getType(), volatileAccessType); + Assert.assertEquals(accesses.get(1).getType(), volatileAccess2Type); + Assert.assertTrue(accesses.get(0).isWrite()); + Assert.assertTrue(accesses.get(1).isRead()); + } + + public static int fieldLoadVolatileFieldStore(int v2) { + int v1 = RegularAccess.field; + VolatileAccess2.field = v2; + return v1; + } + + @Test + public void test05() { + List accesses = compile("fieldLoadVolatileFieldStore"); + + Assert.assertEquals(accesses.size(), 2); + Assert.assertEquals(accesses.get(0).getType(), regularAccessField); + Assert.assertEquals(accesses.get(1).getType(), volatileAccess2Type); + Assert.assertTrue(accesses.get(0).isRead()); + Assert.assertTrue(accesses.get(1).isWrite()); + } + + public static void volatileFieldStoreVolatileFieldStore(int v1, int v2) { + VolatileAccess.field = v1; + VolatileAccess2.field = v2; + } + + @Test + public void test06() { + List accesses = compile("volatileFieldStoreVolatileFieldStore"); + + Assert.assertEquals(accesses.size(), 2); + Assert.assertEquals(accesses.get(0).getType(), volatileAccessType); + Assert.assertEquals(accesses.get(1).getType(), volatileAccess2Type); + Assert.assertTrue(accesses.get(0).isWrite()); + Assert.assertTrue(accesses.get(1).isWrite()); + } + + private static OptionValues stressTestEarlyReads() { + EconomicMap, Object> overrides = OptionValues.newOptionMap(); + overrides.put(StressTestEarlyReads, true); + return new OptionValues(getInitialOptions(), overrides); + } + + static class TypePair { + private boolean isRead; + private ResolvedJavaType type; + + TypePair(boolean isRead, ResolvedJavaType type) { + this.isRead = isRead; + this.type = type; + } + + public boolean isRead() { + return isRead; + } + + public boolean isWrite() { + return !isRead; + } + + public ResolvedJavaType getType() { + return type; + } + } + + private List compile(String test, OptionValues options) { + StructuredGraph graph = getFinalGraph(getResolvedJavaMethod(test), options); + return getAccesses(graph); + } + + private List getAccesses(StructuredGraph graph) { + StructuredGraph.ScheduleResult schedule = graph.getLastSchedule(); + ControlFlowGraph cfg = schedule.getCFG(); + Block[] blocks = cfg.getBlocks(); + + return Arrays.stream(blocks).flatMap(b -> schedule.nodesFor(b).stream()).filter(n -> n instanceof MemoryAccess).map( + n -> new TypePair(n instanceof ReadNode, classForAccess((FixedAccessNode) n))).collect(Collectors.toList()); + } + + private List compile(String test) { + StructuredGraph graph = getFinalGraph(getResolvedJavaMethod(test)); + return getAccesses(graph); + } + + private ResolvedJavaType classForAccess(FixedAccessNode n) { + AddressNode address = n.getAddress(); + ValueNode base = address.getBase(); + Stamp stamp = base.stamp(NodeView.DEFAULT); + MetaAccessProvider metaAccess = getMetaAccess(); + ResolvedJavaType javaType = stamp.javaType(metaAccess); + if (javaType == metaAccess.lookupJavaType(Class.class) && base instanceof ConstantNode) { + ConstantReflectionProvider constantReflection = getConstantReflection(); + javaType = constantReflection.asJavaType(base.asConstant()); + } + return javaType; + } + +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -69,7 +69,7 @@ test("testSynchronizedSnippet", new A(), new A()); StructuredGraph graph = getGraph("testSynchronizedSnippet", false); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); new LockEliminationPhase().apply(graph); assertDeepEquals(1, graph.getNodes().filter(RawMonitorEnterNode.class).count()); assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count()); @@ -87,7 +87,7 @@ test("testSynchronizedMethodSnippet", new A()); StructuredGraph graph = getGraph("testSynchronizedMethodSnippet", false); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); new LockEliminationPhase().apply(graph); assertDeepEquals(1, graph.getNodes().filter(RawMonitorEnterNode.class).count()); assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count()); @@ -104,7 +104,7 @@ @Test public void testUnrolledSync() { StructuredGraph graph = getGraph("testUnrolledSyncSnippet", false); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); canonicalizer.apply(graph, getProviders()); HighTierContext context = getDefaultHighTierContext(); new LoopFullUnrollPhase(canonicalizer, new DefaultLoopPolicies()).apply(graph, context); @@ -117,15 +117,15 @@ ResolvedJavaMethod method = getResolvedJavaMethod(snippet); StructuredGraph graph = parseEager(method, AllowAssumptions.YES); HighTierContext context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); canonicalizer.apply(graph, context); createInliningPhase().apply(graph, context); - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); if (doEscapeAnalysis) { new PartialEscapePhase(true, canonicalizer, graph.getOptions()).apply(graph, context); } - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); return graph; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -37,7 +37,6 @@ import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.extended.OpaqueNode; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -85,7 +84,7 @@ new SchedulePhase(s).apply(graph); } - new CanonicalizerPhase().apply(graph, context); + this.createCanonicalizerPhase().apply(graph, context); JavaConstant asConstant = (JavaConstant) returnNode.result().asConstant(); Assert.assertEquals(N + 1, asConstant.asInt()); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -32,7 +32,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.spi.CoreProviders; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; public class LoopFullUnrollTest extends GraalCompilerTest { @@ -89,7 +88,7 @@ final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, debug); CoreProviders context = getProviders(); - new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context); + new LoopFullUnrollPhase(createCanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context); assertTrue(graph.getNodes().filter(LoopBeginNode.class).count() == loopCount); } catch (Throwable e) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopUnswitchTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopUnswitchTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopUnswitchTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -30,7 +30,6 @@ import org.graalvm.compiler.loop.phases.LoopUnswitchingPhase; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; public class LoopUnswitchTest extends GraalCompilerTest { @@ -133,8 +132,8 @@ graph.clearAllStateAfter(); referenceGraph.clearAllStateAfter(); - new CanonicalizerPhase().apply(graph, getProviders()); - new CanonicalizerPhase().apply(referenceGraph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(referenceGraph, getProviders()); try (DebugContext.Scope s = debug.scope("Test", new DebugDumpScope("Test:" + snippet))) { assertEquals(referenceGraph, graph); } catch (Throwable e) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -37,7 +37,6 @@ import java.nio.file.Path; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.common.inlining.policy.InlineEverythingPolicy; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -125,8 +124,8 @@ Assert.assertNotNull(getMethodImpl); StructuredGraph graph = parseForCompile(getMethodImpl); HighTierContext highContext = getDefaultHighTierContext(); - new CanonicalizerPhase().apply(graph, highContext); - new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase()).apply(graph, highContext); + createCanonicalizerPhase().apply(graph, highContext); + new InliningPhase(new InlineEverythingPolicy(), createCanonicalizerPhase()).apply(graph, highContext); InstalledCode compiledCode = getCode(getMethodImpl, graph); testMappedByteBuffer(mbb -> { try { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryGraphCanonicalizeTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryGraphCanonicalizeTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryGraphCanonicalizeTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -28,7 +28,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; @@ -76,10 +75,9 @@ public void testGraph(String name, int expectedWrites) { StructuredGraph graph = parseEager(name, StructuredGraph.AllowAssumptions.YES); HighTierContext context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase()).apply(graph, context); - new CanonicalizerPhase().apply(graph, context); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new IncrementalCanonicalizerPhase<>(createCanonicalizerPhase(), new FloatingReadPhase()).apply(graph, context); + createCanonicalizerPhase().apply(graph, context); int writes = graph.getNodes().filter(WriteNode.class).count(); assertTrue(writes == expectedWrites, "Expected %d writes, found %d", expectedWrites, writes); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -38,7 +38,6 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.ReturnNode; -import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; @@ -177,7 +176,6 @@ @Test public void testLoop1() { ScheduleResult schedule = getFinalSchedule("testLoop1Snippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(6, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, true); assertReadWithinAllReturnBlocks(schedule, false); } @@ -202,7 +200,6 @@ @Test public void testLoop2() { ScheduleResult schedule = getFinalSchedule("testLoop2Snippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(6, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, false); assertReadWithinAllReturnBlocks(schedule, true); } @@ -224,7 +221,6 @@ @Test public void testLoop3() { ScheduleResult schedule = getFinalSchedule("testLoop3Snippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(6, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, true); assertReadWithinAllReturnBlocks(schedule, false); } @@ -260,7 +256,6 @@ @Test public void testLoop5() { ScheduleResult schedule = getFinalSchedule("testLoop5Snippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(10, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, false); assertReadWithinAllReturnBlocks(schedule, false); } @@ -289,7 +284,6 @@ @Test public void testLoop6() { ScheduleResult schedule = getFinalSchedule("testLoop6Snippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(13, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, false); assertReadWithinAllReturnBlocks(schedule, false); } @@ -322,7 +316,6 @@ @Test public void testLoop7() { ScheduleResult schedule = getFinalSchedule("testLoop7Snippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(18, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, false); assertReadWithinAllReturnBlocks(schedule, false); } @@ -349,7 +342,6 @@ @Test public void testLoop8() { ScheduleResult schedule = getFinalSchedule("testLoop8Snippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(10, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, true); assertReadWithinAllReturnBlocks(schedule, false); } @@ -391,7 +383,6 @@ @Test public void testIfRead1() { ScheduleResult schedule = getFinalSchedule("testIfRead1Snippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(3, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, true); assertReadAndWriteInSameBlock(schedule, false); } @@ -412,7 +403,6 @@ @Test public void testIfRead2() { ScheduleResult schedule = getFinalSchedule("testIfRead2Snippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(3, schedule.getCFG().getBlocks().length); assertDeepEquals(1, schedule.getCFG().graph.getNodes().filter(FloatingReadNode.class).count()); assertReadWithinStartBlock(schedule, false); assertReadWithinAllReturnBlocks(schedule, false); @@ -434,7 +424,6 @@ @Test public void testIfRead3() { ScheduleResult schedule = getFinalSchedule("testIfRead3Snippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(4, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, false); assertReadWithinAllReturnBlocks(schedule, true); } @@ -455,7 +444,6 @@ @Test public void testIfRead4() { ScheduleResult schedule = getFinalSchedule("testIfRead4Snippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(3, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, false); assertReadWithinAllReturnBlocks(schedule, false); assertReadAndWriteInSameBlock(schedule, true); @@ -474,7 +462,6 @@ @Test public void testIfRead5() { ScheduleResult schedule = getFinalSchedule("testIfRead5Snippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(4, schedule.getCFG().getBlocks().length); assertReadWithinStartBlock(schedule, false); assertReadWithinAllReturnBlocks(schedule, true); assertReadAndWriteInSameBlock(schedule, false); @@ -500,7 +487,6 @@ @Test public void testAntiDependency() { ScheduleResult schedule = getFinalSchedule("testAntiDependencySnippet", TestMode.WITHOUT_FRAMESTATES); - assertDeepEquals(4, schedule.getCFG().getBlocks().length); assertReadBeforeAllWritesInStartBlock(schedule); } @@ -527,7 +513,6 @@ StructuredGraph graph = schedule.getCFG().graph; NodeIterable writeNodes = graph.getNodes().filter(WriteNode.class); - assertDeepEquals(1, schedule.getCFG().getBlocks().length); assertDeepEquals(8, writeNodes.count()); assertDeepEquals(1, graph.getNodes().filter(FloatingReadNode.class).count()); @@ -708,7 +693,7 @@ DebugContext debug = graph.getDebug(); try (DebugContext.Scope d = debug.scope("FloatingReadTest", graph)) { HighTierContext context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); canonicalizer.apply(graph, context); if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { createInliningPhase(canonicalizer).apply(graph, context); @@ -729,7 +714,6 @@ SchedulePhase schedule = new SchedulePhase(schedulingStrategy); schedule.apply(graph); - assertDeepEquals(1, graph.getNodes().filter(StartNode.class).count()); return graph.getLastSchedule(); } catch (Throwable e) { throw debug.handle(e); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -30,7 +30,6 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.junit.Test; @@ -70,8 +69,8 @@ private void testReturnCount(String snippet, int returnCount) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - new CanonicalizerPhase().apply(graph, getProviders()); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); graph.getDebug().dump(DebugContext.BASIC_LEVEL, graph, "Graph"); assertDeepEquals(returnCount, graph.getNodes(ReturnNode.TYPE).count()); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MonitorGraphTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MonitorGraphTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MonitorGraphTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -36,7 +36,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.java.MonitorExitNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.junit.Assert; @@ -103,8 +102,8 @@ hints.put(invoke, 1000d); } HighTierContext context = getDefaultHighTierContext(); - createInliningPhase(hints, new CanonicalizerPhase()).apply(graph, context); - new CanonicalizerPhase().apply(graph, context); + createInliningPhase(hints, createCanonicalizerPhase()).apply(graph, context); + createCanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); return graph; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -36,7 +36,7 @@ import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.CanonicalizerPhase.CustomCanonicalizer; +import org.graalvm.compiler.phases.common.CanonicalizerPhase.CustomSimplification; import org.graalvm.compiler.phases.contract.NodeCostUtil; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.junit.Assert; @@ -162,19 +162,21 @@ @Test public void testCanonicalizationExample() { HighTierContext htc = getDefaultHighTierContext(); - ImprovementSavingCanonicalizer c1 = new ImprovementSavingCanonicalizer(); + ImprovementSavingCalculator c1 = new ImprovementSavingCalculator(); StructuredGraph g1 = parseForCompile(getResolvedJavaMethod("test1Snippet")); - new CanonicalizerPhase(c1).apply(g1, htc); - ImprovementSavingCanonicalizer c2 = new ImprovementSavingCanonicalizer(); + CanonicalizerPhase canonicalizer1 = this.createCanonicalizerPhase().copyWithCustomSimplification(c1); + canonicalizer1.apply(g1, htc); + ImprovementSavingCalculator c2 = new ImprovementSavingCalculator(); StructuredGraph g2 = parseForCompile(getResolvedJavaMethod("test2Snippet")); - new CanonicalizerPhase(c2).apply(g2, htc); + CanonicalizerPhase canonicalizer2 = this.createCanonicalizerPhase().copyWithCustomSimplification(c2); + canonicalizer2.apply(g2, htc); Assert.assertEquals(0, c1.savedCycles); Assert.assertEquals(0, c2.savedCycles); } - private static void prepareGraphForLoopFrequencies(StructuredGraph g, HighTierContext htc) { + private void prepareGraphForLoopFrequencies(StructuredGraph g, HighTierContext htc) { // let canonicalizer work away branch probability nodes - new CanonicalizerPhase().apply(g, htc); + createCanonicalizerPhase().apply(g, htc); // recompute the loop frequencies ComputeLoopFrequenciesClosure.compute(g); } @@ -242,8 +244,8 @@ StructuredGraph g1 = parseForCompile(getResolvedJavaMethod("test1Snippet")); StructuredGraph g2 = parseForCompile(getResolvedJavaMethod("test2Snippet")); HighTierContext htc = getDefaultHighTierContext(); - new CanonicalizerPhase().apply(g1, htc); - new CanonicalizerPhase().apply(g2, htc); + createCanonicalizerPhase().apply(g1, htc); + createCanonicalizerPhase().apply(g2, htc); GraphCostPhase gc1 = new GraphCostPhase(); GraphCostPhase gc2 = new GraphCostPhase(); gc1.apply(g1, htc); @@ -257,7 +259,7 @@ public void testExpectUntrusted() { StructuredGraph g1 = parseForCompile(getResolvedJavaMethod("untrused01")); HighTierContext htc = getDefaultHighTierContext(); - new CanonicalizerPhase().apply(g1, htc); + createCanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); } @@ -266,7 +268,7 @@ public void testArrayLoad() { StructuredGraph g1 = parseForCompile(getResolvedJavaMethod("arrayLoadTest")); HighTierContext htc = getDefaultHighTierContext(); - new CanonicalizerPhase().apply(g1, htc); + createCanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); Assert.assertEquals(15, gc1.finalCycles, 25); @@ -276,7 +278,7 @@ public void testArrayStore() { StructuredGraph g1 = parseForCompile(getResolvedJavaMethod("arrayStoreTest")); HighTierContext htc = getDefaultHighTierContext(); - new CanonicalizerPhase().apply(g1, htc); + createCanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); Assert.assertEquals(15, gc1.finalCycles, 25); @@ -286,7 +288,7 @@ public void testFieldLoad() { StructuredGraph g1 = parseForCompile(getResolvedJavaMethod("fieldLoad")); HighTierContext htc = getDefaultHighTierContext(); - new CanonicalizerPhase().apply(g1, htc); + createCanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); Assert.assertEquals(15, gc1.finalCycles, 25); @@ -296,13 +298,13 @@ public void testFieldStore() { StructuredGraph g1 = parseForCompile(getResolvedJavaMethod("fieldStore")); HighTierContext htc = getDefaultHighTierContext(); - new CanonicalizerPhase().apply(g1, htc); + createCanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); Assert.assertEquals(15, gc1.finalCycles, 25); } - static class ImprovementSavingCanonicalizer extends CustomCanonicalizer { + static class ImprovementSavingCalculator implements CustomSimplification { private int savedCycles; @Override diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -104,7 +104,7 @@ private StructuredGraph compileTestSnippet(final String snippet) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); CoreProviders context = getProviders(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); canonicalizer.apply(graph, context); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -29,7 +29,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; public class PushThroughIfTest extends GraalCompilerTest { @@ -65,15 +64,15 @@ fs.replaceAtUsages(null); GraphUtil.killWithUnusedFloatingInputs(fs); } - new CanonicalizerPhase().apply(graph, getProviders()); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); StructuredGraph referenceGraph = parseEager(reference, AllowAssumptions.YES); for (FrameState fs : referenceGraph.getNodes(FrameState.TYPE).snapshot()) { fs.replaceAtUsages(null); GraphUtil.killWithUnusedFloatingInputs(fs); } - new CanonicalizerPhase().apply(referenceGraph, getProviders()); + createCanonicalizerPhase().apply(referenceGraph, getProviders()); assertEquals(referenceGraph, graph); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -90,7 +90,7 @@ // structure changes significantly StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); CoreProviders context = getProviders(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); canonicalizer.apply(graph, context); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReassociateAndCanonicalTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReassociateAndCanonicalTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReassociateAndCanonicalTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -28,7 +28,6 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; public class ReassociateAndCanonicalTest extends GraalCompilerTest { @@ -245,9 +244,9 @@ private void test(String test, String ref) { StructuredGraph testGraph = parseEager(test, AllowAssumptions.NO); - new CanonicalizerPhase().apply(testGraph, getProviders()); + createCanonicalizerPhase().apply(testGraph, getProviders()); StructuredGraph refGraph = parseEager(ref, AllowAssumptions.NO); - new CanonicalizerPhase().apply(refGraph, getProviders()); + createCanonicalizerPhase().apply(refGraph, getProviders()); assertEquals(testGraph, refGraph); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -28,7 +28,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.spi.CoreProviders; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; /** @@ -134,7 +133,7 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); graph.getDebug().dump(DebugContext.BASIC_LEVEL, graph, "Graph"); CoreProviders context = getProviders(); - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); assertEquals(referenceGraph, graph); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java Thu Oct 31 16:54:16 2019 -0700 @@ -44,7 +44,6 @@ import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase; import org.graalvm.compiler.phases.common.GuardLoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase; @@ -99,8 +98,8 @@ } CoreProviders context = getProviders(); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, context); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, context); MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); new GuardLoweringPhase().apply(graph, midContext); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampCanonicalizerTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampCanonicalizerTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampCanonicalizerTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -27,7 +27,6 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.junit.Test; @@ -111,7 +110,7 @@ private void testZeroReturn(String methodName) { StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); new DeadCodeEliminationPhase().apply(graph); assertConstantReturn(graph, 0); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -27,7 +27,6 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; public class StraighteningTest extends GraalCompilerTest { @@ -90,7 +89,7 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); DebugContext debug = graph.getDebug(); debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); assertEquals(referenceGraph, graph); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchCanonicalizerTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchCanonicalizerTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchCanonicalizerTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -26,7 +26,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; public class SwitchCanonicalizerTest extends GraalCompilerTest { @@ -119,7 +118,7 @@ private void shouldFoldSwitch(String methodName) { StructuredGraph graph = parseForCompile(getResolvedJavaMethod(methodName)); - new CanonicalizerPhase().apply(graph, getDefaultHighTierContext()); + createCanonicalizerPhase().apply(graph, getDefaultHighTierContext()); assertTrue(graph.getNodes().filter(IntegerSwitchNode.class).isEmpty()); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchDyingLoopTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchDyingLoopTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchDyingLoopTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -70,7 +70,7 @@ @Test public void test() { - CanonicalizerPhase canonicalizerPhase = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizerPhase = createCanonicalizerPhase(); HighTierContext highTierContext = getDefaultHighTierContext(); StructuredGraph graph = parseEager("snippet", StructuredGraph.AllowAssumptions.YES); // there should be 1 loop and 1 switch diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchFoldingTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchFoldingTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchFoldingTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -27,7 +27,6 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; public class SwitchFoldingTest extends GraalCompilerTest { @@ -484,7 +483,7 @@ StructuredGraph graph = parseEager(snippet, StructuredGraph.AllowAssumptions.YES); DebugContext debug = graph.getDebug(); debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); StructuredGraph referenceGraph = parseEager(ref, StructuredGraph.AllowAssumptions.YES); assertEquals(referenceGraph, graph); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -41,7 +41,6 @@ import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.java.InstanceOfNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.junit.Assert; @@ -188,13 +187,13 @@ * reference graph. */ new ConditionalEliminationPhase(false).apply(graph, getProviders()); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); // a second canonicalizer is needed to process nested MaterializeNodes - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); new ConditionalEliminationPhase(false).apply(referenceGraph, getProviders()); - new CanonicalizerPhase().apply(referenceGraph, getProviders()); - new CanonicalizerPhase().apply(referenceGraph, getProviders()); + this.createCanonicalizerPhase().apply(referenceGraph, getProviders()); + this.createCanonicalizerPhase().apply(referenceGraph, getProviders()); assertEquals(referenceGraph, graph); } @@ -244,8 +243,8 @@ private void testHelper(String snippet, Class clazz) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); - new CanonicalizerPhase().apply(graph, getProviders()); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); DebugContext debug = graph.getDebug(); debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph " + snippet); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext()); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -119,7 +119,7 @@ public void testEarlyReadElimination(StructuredGraph graph, int reads, int writes) { CoreProviders context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); canonicalizer.apply(graph, context); new EarlyReadEliminationPhase(canonicalizer).apply(graph, context); Assert.assertEquals(3, graph.getNodes().filter(UnsafeAccessNode.class).count()); @@ -134,7 +134,7 @@ public void testPartialEscapeReadElimination(StructuredGraph graph, int reads, int writes) { OptionValues options = graph.getOptions(); CoreProviders context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); canonicalizer.apply(graph, context); new PartialEscapePhase(true, true, canonicalizer, null, options).apply(graph, context); Assert.assertEquals(3, graph.getNodes().filter(UnsafeAccessNode.class).count()); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -147,7 +147,7 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); OptionValues options = graph.getOptions(); CoreProviders context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); if (canonicalizeBefore) { canonicalizer.apply(graph, context); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnusedArray.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnusedArray.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnusedArray.java Thu Oct 31 16:54:16 2019 -0700 @@ -30,7 +30,6 @@ import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.java.NewArrayNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Test; public class UnusedArray extends GraalCompilerTest { @@ -66,7 +65,7 @@ public void test(String method) { StructuredGraph graph = parseEager(method, StructuredGraph.AllowAssumptions.YES); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); NodeIterable newArrayNodes = graph.getNodes().filter(NewArrayNode.class); assertThat(newArrayNodes, isEmpty()); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/CompiledMethodTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/CompiledMethodTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/CompiledMethodTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -29,7 +29,6 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.junit.Assert; import org.junit.Test; @@ -62,7 +61,7 @@ public void test1() { final ResolvedJavaMethod javaMethod = getResolvedJavaMethod("testMethod"); final StructuredGraph graph = parseEager(javaMethod, AllowAssumptions.NO); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); new DeadCodeEliminationPhase().apply(graph); for (ConstantNode node : ConstantNode.getConstantNodes(graph)) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java Thu Oct 31 16:54:16 2019 -0700 @@ -37,7 +37,6 @@ import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; @@ -173,7 +172,7 @@ createInliningPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); canonicalizeGraph(); - new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + new PartialEscapePhase(iterativeEscapeAnalysis, false, createCanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); postEACanonicalizeGraph(); returnNodes = graph.getNodes(ReturnNode.TYPE).snapshot(); } catch (Throwable e) { @@ -185,6 +184,6 @@ } protected void canonicalizeGraph() { - new CanonicalizerPhase().apply(graph, context); + this.createCanonicalizerPhase().apply(graph, context); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EarlyReadEliminationTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EarlyReadEliminationTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EarlyReadEliminationTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -27,6 +27,9 @@ import java.util.List; import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -37,7 +40,6 @@ import org.graalvm.compiler.nodes.java.StoreFieldNode; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; @@ -47,6 +49,50 @@ public static Object staticField; + static void cfgSnippet() { + if (staticField != null) { + staticField = 12; + if (staticField != null) { + staticField = 12; + } + if (staticField != null) { + staticField = 12; + } + if (staticField != null) { + staticField = 12; + } + if (staticField != null) { + staticField = 12; + } + } else { + if (staticField != null) { + staticField = 12; + } else { + if (staticField != null) { + staticField = 12; + } + } + } + } + + @Test + public void testDeadBranches() { + StructuredGraph graph = parseEager(getResolvedJavaMethod("cfgSnippet"), AllowAssumptions.NO); + HighTierContext context = getDefaultHighTierContext(); + int index = 0; + boolean[] conditions = new boolean[]{true, false, false, true, true, true, false}; + /* + * Create a graph with "dead" branches in the beginning. + */ + for (Node n : graph.getNodes()) { + if (n instanceof IfNode) { + IfNode ifNode = (IfNode) n; + ifNode.setCondition(LogicConstantNode.forBoolean(conditions[index++], graph)); + } + } + new EarlyReadEliminationPhase(createCanonicalizerPhase()).apply(graph, context); + } + public static class TestObject { public int x; @@ -264,9 +310,9 @@ HighTierContext context = getDefaultHighTierContext(); createInliningPhase().apply(graph, context); if (doLowering) { - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); } - new EarlyReadEliminationPhase(new CanonicalizerPhase()).apply(graph, context); + new EarlyReadEliminationPhase(createCanonicalizerPhase()).apply(graph, context); return graph; } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -38,7 +38,6 @@ import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.test.SubprocessUtil; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; @@ -327,7 +326,7 @@ Assert.assertEquals(1, graph.getNodes().filter(BoxNode.class).count()); List nodes = graph.getNodes().snapshot(); // verify that an additional run doesn't add or remove nodes - new PartialEscapePhase(false, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + new PartialEscapePhase(false, false, createCanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); Assert.assertEquals(nodes.size(), graph.getNodeCount()); for (Node node : nodes) { Assert.assertTrue(node.isAlive()); @@ -362,9 +361,9 @@ Assert.assertEquals(2, graph.getNodes().filter(CommitAllocationNode.class).count()); // create the situation by removing the if graph.replaceFixedWithFloating(graph.getNodes().filter(LoadFieldNode.class).first(), graph.unique(ConstantNode.forInt(0))); - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); // verify that an additional run removes all allocations - new PartialEscapePhase(false, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + new PartialEscapePhase(false, false, createCanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); Assert.assertEquals(0, graph.getNodes().filter(CommitAllocationNode.class).count()); } @@ -440,8 +439,8 @@ @Test public void testFullyUnrolledLoop() { prepareGraph("testFullyUnrolledLoopSnippet", false); - new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context); - new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); + new LoopFullUnrollPhase(createCanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context); + new PartialEscapePhase(false, createCanonicalizerPhase(), graph.getOptions()).apply(graph, context); Assert.assertEquals(1, returnNodes.size()); Assert.assertTrue(returnNodes.get(0).result() instanceof AllocatedObjectNode); CommitAllocationNode commit = ((AllocatedObjectNode) returnNodes.get(0).result()).getCommit(); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -30,7 +30,6 @@ import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; import org.graalvm.compiler.nodes.java.StoreIndexedNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; import org.junit.Test; @@ -181,7 +180,7 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); createInliningPhase().apply(graph, context); - new PartialEscapePhase(false, true, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + new PartialEscapePhase(false, true, createCanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); return graph; } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisIterationTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisIterationTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisIterationTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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,6 @@ import org.graalvm.compiler.nodes.extended.UnboxNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; import org.junit.Assert; import org.junit.Test; @@ -147,7 +146,7 @@ for (String name : new String[]{"noLoopIterationEmpty", "noLoopIteration"}) { prepareGraph(name, false); List allocations = graph.getNodes().filter(CommitAllocationNode.class).snapshot(); - new PartialEscapePhase(true, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + new PartialEscapePhase(true, false, createCanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); Assert.assertEquals(1, allocations.size()); Assert.assertTrue(allocations.get(0).isAlive()); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -44,7 +44,6 @@ import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; /** @@ -287,7 +286,7 @@ merge.setStateAfter(null); } new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); try { Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", graph.getNodes().filter(NewInstanceNode.class).isEmpty()); Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", graph.getNodes().filter(NewArrayNode.class).isEmpty()); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTreesTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTreesTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTreesTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -30,7 +30,6 @@ import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.debug.BlackholeNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.junit.Assert; import org.junit.Test; @@ -118,7 +117,7 @@ graph.removeFixed(node); } new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); InstalledCode code = getCode(method, graph, true); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PoorMansEATest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PoorMansEATest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PoorMansEATest.java Thu Oct 31 16:54:16 2019 -0700 @@ -35,7 +35,6 @@ import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.junit.Test; @@ -68,7 +67,7 @@ HighTierContext highTierContext = getDefaultHighTierContext(); createInliningPhase().apply(graph, highTierContext); CoreProviders context = getProviders(); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); // remove framestates in order to trigger the simplification. cleanup: for (FrameState fs : graph.getNodes(FrameState.TYPE).snapshot()) { @@ -80,7 +79,7 @@ } } } - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); } catch (Throwable e) { throw debug.handle(e); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/TrufflePEATest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/TrufflePEATest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/TrufflePEATest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -32,7 +32,6 @@ import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; import org.junit.Test; @@ -123,7 +122,7 @@ StructuredGraph graph = parseEager(snippet, StructuredGraph.AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); createInliningPhase().apply(graph, context); - new PartialEscapePhase(true, true, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + new PartialEscapePhase(true, true, createCanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); return graph; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -37,7 +37,6 @@ import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.extended.UnsafeAccessNode; import org.graalvm.compiler.nodes.java.LoadFieldNode; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Assert; import org.junit.Test; @@ -123,7 +122,7 @@ for (UnpackEndianHalfNode node : graph.getNodes().filter(UnpackEndianHalfNode.class)) { node.lower(getTarget().arch.getByteOrder()); } - new CanonicalizerPhase().applyIncremental(graph, context, mark); + createCanonicalizerPhase().applyIncremental(graph, context, mark); } private boolean testingUnsafe; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -41,7 +41,6 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.junit.Assert; @@ -291,10 +290,10 @@ : getDefaultGraphBuilderSuite(); HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); createInliningPhase().apply(graph, context); debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); return graph; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -112,8 +112,8 @@ StructuredGraph g1 = prepareGraph(snippet, i); StructuredGraph g2 = (StructuredGraph) g1.copy(g1.getDebug()); ResolvedJavaMethod method = g1.method(); - long elapsedRE = runAndTimePhase(g1, new EarlyReadEliminationPhase(new CanonicalizerPhase())); - long elapsedPEA = runAndTimePhase(g2, new PartialEscapePhase(true, new CanonicalizerPhase(), g1.getOptions())); + long elapsedRE = runAndTimePhase(g1, new EarlyReadEliminationPhase(createCanonicalizerPhase())); + long elapsedPEA = runAndTimePhase(g2, new PartialEscapePhase(true, createCanonicalizerPhase(), g1.getOptions())); if (LOG_PHASE_TIMINGS) { TTY.printf("Needed %dms to run early partial escape analysis on a graph with %d nested loops compiling method %s\n", elapsedPEA, i, method); } @@ -138,7 +138,7 @@ StructuredGraph callerGraph = parseEager(callerMethod, AllowAssumptions.YES); PhaseSuite graphBuilderSuite = getDefaultGraphBuilderSuite(); HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); Invoke next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke(); StructuredGraph calleeGraph = parseBytecodes(next.callTarget().targetMethod(), context, canonicalizer); ResolvedJavaMethod calleeMethod = next.callTarget().targetMethod(); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java Thu Oct 31 16:54:16 2019 -0700 @@ -63,6 +63,7 @@ import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.ReadNode; +import org.graalvm.compiler.nodes.memory.VolatileReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import jdk.vm.ci.meta.Value; @@ -75,6 +76,7 @@ @MatchableNode(nodeClass = LeftShiftNode.class, inputs = {"x", "y"}, ignoresSideEffects = true) @MatchableNode(nodeClass = NarrowNode.class, inputs = {"value"}, ignoresSideEffects = true) @MatchableNode(nodeClass = ReadNode.class, inputs = {"address"}) +@MatchableNode(nodeClass = VolatileReadNode.class, inputs = {"address"}) @MatchableNode(nodeClass = ReinterpretNode.class, inputs = {"value"}, ignoresSideEffects = true) @MatchableNode(nodeClass = SignExtendNode.class, inputs = {"value"}, ignoresSideEffects = true) @MatchableNode(nodeClass = UnsignedRightShiftNode.class, inputs = {"x", "y"}, ignoresSideEffects = true) diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/BaseTier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/BaseTier.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019, 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.phases; + +import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; + +import org.graalvm.compiler.loop.DefaultLoopPolicies; +import org.graalvm.compiler.loop.LoopPolicies; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; + +public class BaseTier extends PhaseSuite { + + public LoopPolicies createLoopPolicies() { + return new DefaultLoopPolicies(); + } + + public CanonicalizerPhase createCanonicalizerPhase(OptionValues options) { + CanonicalizerPhase canonicalizer = null; + if (ImmutableCode.getValue(options)) { + canonicalizer = CanonicalizerPhase.createWithoutReadCanonicalization(); + } else { + canonicalizer = CanonicalizerPhase.create(); + } + return canonicalizer; + } +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -24,23 +24,16 @@ package org.graalvm.compiler.core.phases; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; - import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; -public class EconomyHighTier extends PhaseSuite { +public class EconomyHighTier extends BaseTier { public EconomyHighTier(OptionValues options) { - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue(options)) { - canonicalizer.disableReadCanonicalization(); - } - + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(options); appendPhase(canonicalizer); appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER)); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java Thu Oct 31 16:54:16 2019 -0700 @@ -24,29 +24,20 @@ package org.graalvm.compiler.core.phases; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; - import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ExpandLogicPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.tiers.LowTierContext; -public class EconomyLowTier extends PhaseSuite { +public class EconomyLowTier extends BaseTier { public EconomyLowTier(OptionValues options) { - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue(options)) { - canonicalizer.disableReadCanonicalization(); - } - + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(options); appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER)); - appendPhase(new ExpandLogicPhase()); - appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS)); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java Thu Oct 31 16:54:16 2019 -0700 @@ -24,11 +24,8 @@ package org.graalvm.compiler.core.phases; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; - import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase; import org.graalvm.compiler.phases.common.GuardLoweringPhase; @@ -38,23 +35,15 @@ import org.graalvm.compiler.phases.common.WriteBarrierAdditionPhase; import org.graalvm.compiler.phases.tiers.MidTierContext; -public class EconomyMidTier extends PhaseSuite { +public class EconomyMidTier extends BaseTier { public EconomyMidTier(OptionValues options) { - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue(options)) { - canonicalizer.disableReadCanonicalization(); - } + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(options); appendPhase(new RemoveValueProxyPhase()); - appendPhase(new LoopSafepointInsertionPhase()); - appendPhase(new GuardLoweringPhase()); - appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER)); - appendPhase(new FrameStateAssignmentPhase()); - appendPhase(new WriteBarrierAdditionPhase()); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java Thu Oct 31 16:54:16 2019 -0700 @@ -25,17 +25,16 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ConditionalElimination; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.core.common.GraalOptions.LoopPeeling; import static org.graalvm.compiler.core.common.GraalOptions.LoopUnswitch; import static org.graalvm.compiler.core.common.GraalOptions.OptConvertDeoptsToGuards; -import static org.graalvm.compiler.core.common.GraalOptions.OptLoopTransform; import static org.graalvm.compiler.core.common.GraalOptions.OptReadElimination; import static org.graalvm.compiler.core.common.GraalOptions.PartialEscapeAnalysis; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; import org.graalvm.compiler.loop.DefaultLoopPolicies; import org.graalvm.compiler.loop.LoopPolicies; +import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase; import org.graalvm.compiler.loop.phases.LoopPeelingPhase; import org.graalvm.compiler.loop.phases.LoopUnswitchingPhase; @@ -44,22 +43,19 @@ import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase; import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.NodeCounterPhase; -import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; -public class HighTier extends PhaseSuite { +public class HighTier extends BaseTier { public static class Options { @@ -70,11 +66,7 @@ } public HighTier(OptionValues options) { - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue(options)) { - canonicalizer.disableReadCanonicalization(); - } - + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(options); appendPhase(canonicalizer); if (NodeCounterPhase.Options.NodeCounters.getValue(options)) { @@ -101,13 +93,12 @@ LoopPolicies loopPolicies = createLoopPolicies(); appendPhase(new LoopFullUnrollPhase(canonicalizer, loopPolicies)); - if (OptLoopTransform.getValue(options)) { - if (LoopPeeling.getValue(options)) { - appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new LoopPeelingPhase(loopPolicies))); - } - if (LoopUnswitch.getValue(options)) { - appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new LoopUnswitchingPhase(loopPolicies))); - } + if (LoopPeeling.getValue(options)) { + appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new LoopPeelingPhase(loopPolicies))); + } + + if (LoopUnswitch.getValue(options)) { + appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new LoopUnswitchingPhase(loopPolicies))); } if (PartialEscapeAnalysis.getValue(options)) { @@ -118,8 +109,6 @@ appendPhase(new EarlyReadEliminationPhase(canonicalizer)); } - appendPhase(new RemoveValueProxyPhase()); - if (NodeCounterPhase.Options.NodeCounters.getValue(options)) { appendPhase(new NodeCounterPhase(NodeCounterPhase.Stage.LATE)); } @@ -127,6 +116,7 @@ appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER)); } + @Override public LoopPolicies createLoopPolicies() { return new DefaultLoopPolicies(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java Thu Oct 31 16:54:16 2019 -0700 @@ -24,7 +24,7 @@ package org.graalvm.compiler.core.phases; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; +import static org.graalvm.compiler.core.common.GraalOptions.LateMembars; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; import org.graalvm.compiler.core.common.GraalOptions; @@ -33,11 +33,11 @@ import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.ExpandLogicPhase; import org.graalvm.compiler.phases.common.FixReadsPhase; +import org.graalvm.compiler.phases.common.InsertMembarsPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.ProfileCompiledMethodsPhase; import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase; @@ -46,7 +46,7 @@ import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.LowTierContext; -public class LowTier extends PhaseSuite { +public class LowTier extends BaseTier { static class Options { @@ -58,13 +58,8 @@ } public LowTier(OptionValues options) { - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - CanonicalizerPhase canonicalizerWithoutGVN = new CanonicalizerPhase(); - canonicalizerWithoutGVN.disableGVN(); - if (ImmutableCode.getValue(options)) { - canonicalizer.disableReadCanonicalization(); - canonicalizerWithoutGVN.disableReadCanonicalization(); - } + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(options); + CanonicalizerPhase canonicalizerWithoutGVN = canonicalizer.copyWithoutGVN(); if (Options.ProfileCompiledMethods.getValue(options)) { appendPhase(new ProfileCompiledMethodsPhase()); @@ -85,6 +80,9 @@ appendPhase(new PropagateDeoptimizeProbabilityPhase()); + if (LateMembars.getValue(options)) { + appendPhase(new InsertMembarsPhase()); + } appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS)); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java Thu Oct 31 16:54:16 2019 -0700 @@ -25,10 +25,8 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ConditionalElimination; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.core.common.GraalOptions.OptDeoptimizationGrouping; import static org.graalvm.compiler.core.common.GraalOptions.OptFloatingReads; -import static org.graalvm.compiler.core.common.GraalOptions.OptLoopTransform; import static org.graalvm.compiler.core.common.GraalOptions.PartialUnroll; import static org.graalvm.compiler.core.common.GraalOptions.ReassociateInvariants; import static org.graalvm.compiler.core.common.GraalOptions.VerifyHeapAtReturn; @@ -43,7 +41,6 @@ import org.graalvm.compiler.loop.phases.ReassociateInvariantPhase; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeoptimizationGroupingPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; @@ -56,17 +53,15 @@ import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.OptimizeDivPhase; +import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.common.VerifyHeapAtReturnPhase; import org.graalvm.compiler.phases.common.WriteBarrierAdditionPhase; import org.graalvm.compiler.phases.tiers.MidTierContext; -public class MidTier extends PhaseSuite { +public class MidTier extends BaseTier { public MidTier(OptionValues options) { - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue(options)) { - canonicalizer.disableReadCanonicalization(); - } + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(options); appendPhase(new LockEliminationPhase()); @@ -80,8 +75,6 @@ appendPhase(new LoopSafepointEliminationPhase()); - appendPhase(new LoopSafepointInsertionPhase()); - appendPhase(new GuardLoweringPhase()); if (MitigateSpeculativeExecutionAttacks.getValue(options) == GuardTargets || MitigateSpeculativeExecutionAttacks.getValue(options) == NonDeoptGuardTargets) { @@ -92,18 +85,21 @@ appendPhase(new VerifyHeapAtReturnPhase()); } + appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new RemoveValueProxyPhase())); + + appendPhase(new LoopSafepointInsertionPhase()); + appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER)); appendPhase(new OptimizeDivPhase()); appendPhase(new FrameStateAssignmentPhase()); - LoopPolicies loopPolicies = createLoopPolicies(); - if (OptLoopTransform.getValue(options)) { - if (PartialUnroll.getValue(options)) { - appendPhase(new LoopPartialUnrollPhase(loopPolicies, canonicalizer)); - } + if (PartialUnroll.getValue(options)) { + LoopPolicies loopPolicies = createLoopPolicies(); + appendPhase(new LoopPartialUnrollPhase(loopPolicies, canonicalizer)); } + if (ReassociateInvariants.getValue(options)) { appendPhase(new ReassociateInvariantPhase()); } @@ -117,6 +113,7 @@ appendPhase(new WriteBarrierAdditionPhase()); } + @Override public LoopPolicies createLoopPolicies() { return new DefaultLoopPolicies(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java Thu Oct 31 16:54:16 2019 -0700 @@ -100,6 +100,7 @@ public HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, HotSpotJVMCIRuntime jvmciRuntime, HotSpotBackend host) { assert host == null; + OptionValues options = graalRuntime.getOptions(); JVMCIBackend jvmci = jvmciRuntime.getHostJVMCIBackend(); GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); HotSpotProviders providers; @@ -156,7 +157,7 @@ } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { plugins = createGraphBuilderPlugins(graalRuntime, compilerConfiguration, config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, - graalRuntime.getOptions()); + graalRuntime.getOptions(), target); replacements.setGraphBuilderPlugins(plugins); } try (InitTimer rt = timer("create Suites provider")) { @@ -165,6 +166,7 @@ providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, snippetReflection, wordTypes, plugins, gc); replacements.setProviders(providers); + replacements.maybeInitializeEncoder(options); } try (InitTimer rt = timer("instantiate backend")) { return createBackend(config, graalRuntime, providers); @@ -180,7 +182,8 @@ HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, - OptionValues options) { + OptionValues options, + TargetDescription target) { Plugins plugins = HotSpotGraphBuilderPlugins.create(graalRuntime, compilerConfiguration, config, @@ -190,8 +193,9 @@ snippetReflection, foreignCalls, replacements, - options); - AArch64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), false, + options, + target); + AArch64GraphBuilderPlugins.register(plugins, replacements, false, // /* registerMathPlugins */true, /* emitJDK9StringSubstitutions */true, config.useFMAIntrinsics); return plugins; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Thu Oct 31 16:54:16 2019 -0700 @@ -158,6 +158,7 @@ providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, snippetReflection, wordTypes, plugins, gc); replacements.setProviders(providers); + replacements.maybeInitializeEncoder(options); } try (InitTimer rt = timer("instantiate backend")) { return createBackend(config, graalRuntime, providers); @@ -185,8 +186,9 @@ snippetReflection, foreignCalls, replacements, - options); - AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false, JavaVersionUtil.JAVA_SPEC >= 9, config.useFMAIntrinsics); + options, + target); + AMD64GraphBuilderPlugins.register(plugins, replacements, (AMD64) target.arch, false, JavaVersionUtil.JAVA_SPEC >= 9, config.useFMAIntrinsics); return plugins; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java Thu Oct 31 16:54:16 2019 -0700 @@ -87,6 +87,7 @@ public HotSpotBackend createBackend(HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, HotSpotJVMCIRuntime jvmciRuntime, HotSpotBackend host) { assert host == null; + OptionValues options = runtime.getOptions(); GraalHotSpotVMConfig config = runtime.getVMConfig(); JVMCIBackend jvmci = jvmciRuntime.getHostJVMCIBackend(); HotSpotRegistersProvider registers = createRegisters(); @@ -106,12 +107,13 @@ BytecodeProvider bytecodeProvider = createBytecodeProvider(metaAccess, snippetReflection); HotSpotReplacementsImpl replacements = createReplacements(target, p, snippetReflection, bytecodeProvider); Plugins plugins = createGraphBuilderPlugins(runtime, compilerConfiguration, config, metaAccess, constantReflection, foreignCalls, snippetReflection, replacements, wordTypes, - runtime.getOptions()); + runtime.getOptions(), target); replacements.setGraphBuilderPlugins(plugins); HotSpotSuitesProvider suites = createSuites(config, runtime, compilerConfiguration, plugins, replacements); HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, snippetReflection, wordTypes, plugins, gc); replacements.setProviders(providers); + replacements.maybeInitializeEncoder(options); return createBackend(config, runtime, providers); } @@ -125,7 +127,8 @@ HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, - OptionValues options) { + OptionValues options, + TargetDescription target) { Plugins plugins = HotSpotGraphBuilderPlugins.create( graalRuntime, compilerConfiguration, @@ -136,8 +139,9 @@ snippetReflection, foreignCalls, replacements, - options); - SPARCGraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), false); + options, + target); + SPARCGraphBuilderPlugins.register(plugins, replacements, false); return plugins; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Thu Oct 31 16:54:16 2019 -0700 @@ -24,9 +24,6 @@ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins.aesDecryptName; -import static org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins.aesEncryptName; - import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -368,10 +365,6 @@ add(ignore, "com/sun/crypto/provider/GHASH.processBlocks([BII[J[J)V"); } - if (!(config.useSHA1Intrinsics() || config.useSHA256Intrinsics() || config.useSHA512Intrinsics())) { - add(ignore, - "sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I"); - } if (!config.useFMAIntrinsics) { add(ignore, "java/lang/Math.fma(DDD)D", @@ -516,15 +509,16 @@ "java/util/zip/CRC32C.updateDirectByteBuffer(IJII)I"); } - boolean implNames = HotSpotGraphBuilderPlugins.cbcUsesImplNames(config); - String cbcEncryptName = implNames ? "implEncrypt" : "encrypt"; - String cbcDecryptName = implNames ? "implDecrypt" : "decrypt"; + String cbcEncryptName = HotSpotGraphBuilderPlugins.lookupIntrinsicName(config, "com/sun/crypto/provider/CipherBlockChaining", "implEncrypt", "encrypt"); + String cbcDecryptName = HotSpotGraphBuilderPlugins.lookupIntrinsicName(config, "com/sun/crypto/provider/CipherBlockChaining", "implDecrypt", "decrypt"); + String aesEncryptName = HotSpotGraphBuilderPlugins.lookupIntrinsicName(config, "com/sun/crypto/provider/AESCrypt", "implEncryptBlock", "encryptBlock"); + String aesDecryptName = HotSpotGraphBuilderPlugins.lookupIntrinsicName(config, "com/sun/crypto/provider/AESCrypt", "implDecryptBlock", "decryptBlock"); // AES intrinsics if (!config.useAESIntrinsics) { add(ignore, + "com/sun/crypto/provider/AESCrypt." + aesEncryptName + "([BI[BI)V", "com/sun/crypto/provider/AESCrypt." + aesDecryptName + "([BI[BI)V", - "com/sun/crypto/provider/AESCrypt." + aesEncryptName + "([BI[BI)V", "com/sun/crypto/provider/CipherBlockChaining." + cbcDecryptName + "([BII[BI)I", "com/sun/crypto/provider/CipherBlockChaining." + cbcEncryptName + "([BII[BI)I"); } @@ -549,28 +543,21 @@ if (!config.useSquareToLenIntrinsic()) { add(ignore, "java/math/BigInteger.implSquareToLen([II[II)[I"); } - + // DigestBase intrinsics + if (HotSpotGraphBuilderPlugins.isIntrinsicName(config, "sun/security/provider/DigestBase", "implCompressMultiBlock0") && + !(config.useSHA1Intrinsics() || config.useSHA256Intrinsics() || config.useSHA512Intrinsics())) { + add(ignore, "sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I"); + } // SHA intrinsics + String shaCompressName = HotSpotGraphBuilderPlugins.lookupIntrinsicName(config, "sun/security/provider/SHA", "implCompress0", "implCompress"); if (!config.useSHA1Intrinsics()) { - if (isJDK9OrHigher()) { - add(ignore, "sun/security/provider/SHA.implCompress0([BI)V"); - } else { - add(ignore, "sun/security/provider/SHA.implCompress([BI)V"); - } + add(ignore, "sun/security/provider/SHA." + shaCompressName + "([BI)V"); } if (!config.useSHA256Intrinsics()) { - if (isJDK9OrHigher()) { - add(ignore, "sun/security/provider/SHA2.implCompress0([BI)V"); - } else { - add(ignore, "sun/security/provider/SHA2.implCompress([BI)V"); - } + add(ignore, "sun/security/provider/SHA2." + shaCompressName + "([BI)V"); } if (!config.useSHA512Intrinsics()) { - if (isJDK9OrHigher()) { - add(ignore, "sun/security/provider/SHA5.implCompress0([BI)V"); - } else { - add(ignore, "sun/security/provider/SHA5.implCompress([BI)V"); - } + add(ignore, "sun/security/provider/SHA5." + shaCompressName + "([BI)V"); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Thu Oct 31 16:54:16 2019 -0700 @@ -101,10 +101,10 @@ import org.graalvm.compiler.options.OptionsParser; import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; -import org.graalvm.compiler.test.ModuleSupport; +import org.graalvm.compiler.api.test.ModuleSupport; import jdk.internal.vm.compiler.libgraal.LibGraal; import jdk.internal.vm.compiler.libgraal.LibGraalScope; -import jdk.internal.vm.compiler.libgraal.OptionsEncoder; +import org.graalvm.util.OptionsEncoder; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java Thu Oct 31 16:54:16 2019 -0700 @@ -34,7 +34,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; -import org.graalvm.compiler.test.ModuleSupport; +import org.graalvm.compiler.api.test.ModuleSupport; import org.junit.BeforeClass; import org.junit.Test; import org.objectweb.asm.ClassWriter; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DeferredBarrierAdditionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DeferredBarrierAdditionTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DeferredBarrierAdditionTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -38,7 +38,6 @@ import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.GuardLoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.WriteBarrierAdditionPhase; @@ -83,12 +82,12 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, debug); HighTierContext highContext = getDefaultHighTierContext(); MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); - new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase()).apply(graph, highContext); - new CanonicalizerPhase().apply(graph, highContext); - new PartialEscapePhase(false, new CanonicalizerPhase(), debug.getOptions()).apply(graph, highContext); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext); + new InliningPhase(new InlineEverythingPolicy(), createCanonicalizerPhase()).apply(graph, highContext); + this.createCanonicalizerPhase().apply(graph, highContext); + new PartialEscapePhase(false, createCanonicalizerPhase(), debug.getOptions()).apply(graph, highContext); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext); new GuardLoweringPhase().apply(graph, midContext); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); + new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); new WriteBarrierAdditionPhase().apply(graph, midContext); debug.dump(DebugContext.BASIC_LEVEL, graph, "After Write Barrier Addition"); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -80,7 +80,9 @@ @Test public void testAESCryptIntrinsics() throws Exception { - if (compileAndInstall("com.sun.crypto.provider.AESCrypt", HotSpotGraphBuilderPlugins.aesEncryptName, HotSpotGraphBuilderPlugins.aesDecryptName)) { + String aesEncryptName = HotSpotGraphBuilderPlugins.lookupIntrinsicName(runtime().getVMConfig(), "com/sun/crypto/provider/AESCrypt", "implEncryptBlock", "encryptBlock"); + String aesDecryptName = HotSpotGraphBuilderPlugins.lookupIntrinsicName(runtime().getVMConfig(), "com/sun/crypto/provider/AESCrypt", "implDecryptBlock", "decryptBlock"); + if (compileAndInstall("com.sun.crypto.provider.AESCrypt", aesEncryptName, aesDecryptName)) { ByteArrayOutputStream actual = new ByteArrayOutputStream(); actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding")); actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding")); @@ -90,9 +92,8 @@ @Test public void testCipherBlockChainingIntrinsics() throws Exception { - boolean implNames = HotSpotGraphBuilderPlugins.cbcUsesImplNames(runtime().getVMConfig()); - String cbcEncryptName = implNames ? "implEncrypt" : "encrypt"; - String cbcDecryptName = implNames ? "implDecrypt" : "decrypt"; + String cbcEncryptName = HotSpotGraphBuilderPlugins.lookupIntrinsicName(runtime().getVMConfig(), "com/sun/crypto/provider/CipherBlockChaining", "implEncrypt", "encrypt"); + String cbcDecryptName = HotSpotGraphBuilderPlugins.lookupIntrinsicName(runtime().getVMConfig(), "com/sun/crypto/provider/CipherBlockChaining", "implDecrypt", "decrypt"); if (compileAndInstall("com.sun.crypto.provider.CipherBlockChaining", cbcEncryptName, cbcDecryptName)) { ByteArrayOutputStream actual = new ByteArrayOutputStream(); actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding")); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotInvokeDynamicPluginTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotInvokeDynamicPluginTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotInvokeDynamicPluginTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -93,7 +93,7 @@ StructuredGraph graph = parseEager(name, AllowAssumptions.NO, new OptionValues(getInitialOptions(), GraalOptions.GeneratePIC, true)); MidTierContext midTierContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); Assert.assertEquals(expectedResolves, graph.getNodes().filter(ResolveDynamicConstantNode.class).count()); Assert.assertEquals(0, graph.getNodes().filter(ResolveDynamicStubCall.class).count()); CoreProviders context = getProviders(); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -117,7 +117,7 @@ private void test(String name, int expectedInits, int expectedResolves, int expectedLoads) { StructuredGraph graph = parseEager(name, AllowAssumptions.NO, new OptionValues(getInitialOptions(), GraalOptions.GeneratePIC, true)); HighTierContext highTierContext = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); new EliminateRedundantInitializationPhase().apply(graph, highTierContext); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext); new LoadJavaMirrorWithKlassPhase(config).apply(graph, highTierContext); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestSHASubstitutions.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestSHASubstitutions.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestSHASubstitutions.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, 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 @@ -34,9 +34,7 @@ import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.replacements.SHA2Substitutions; -import org.graalvm.compiler.hotspot.replacements.SHA5Substitutions; -import org.graalvm.compiler.hotspot.replacements.SHASubstitutions; +import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins; import org.graalvm.compiler.runtime.RuntimeProvider; import jdk.vm.ci.code.InstalledCode; @@ -74,7 +72,8 @@ @Test public void testSha1() { if (getConfig().useSHA1Intrinsics()) { - testWithInstalledIntrinsic("sun.security.provider.SHA", SHASubstitutions.implCompressName, "testDigest", "SHA-1", getData()); + String implCompressName = HotSpotGraphBuilderPlugins.lookupIntrinsicName(getConfig(), "sun/security/provider/SHA", "implCompress0", "implCompress"); + testWithInstalledIntrinsic("sun.security.provider.SHA", implCompressName, "testDigest", "SHA-1", getData()); } } @@ -107,14 +106,16 @@ @Test public void testSha256() { if (getConfig().useSHA256Intrinsics()) { - testWithInstalledIntrinsic("sun.security.provider.SHA2", SHA2Substitutions.implCompressName, "testDigest", "SHA-256", getData()); + String implCompressName = HotSpotGraphBuilderPlugins.lookupIntrinsicName(getConfig(), "sun/security/provider/SHA", "implCompress0", "implCompress"); + testWithInstalledIntrinsic("sun.security.provider.SHA2", implCompressName, "testDigest", "SHA-256", getData()); } } @Test public void testSha512() { if (getConfig().useSHA512Intrinsics()) { - testWithInstalledIntrinsic("sun.security.provider.SHA5", SHA5Substitutions.implCompressName, "testDigest", "SHA-512", getData()); + String implCompressName = HotSpotGraphBuilderPlugins.lookupIntrinsicName(getConfig(), "sun/security/provider/SHA", "implCompress0", "implCompress"); + testWithInstalledIntrinsic("sun.security.provider.SHA5", implCompressName, "testDigest", "SHA-512", getData()); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -44,7 +44,6 @@ import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.GuardLoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.WriteBarrierAdditionPhase; @@ -263,11 +262,11 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, debug); HighTierContext highContext = getDefaultHighTierContext(); MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); - new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase()).apply(graph, highContext); - new CanonicalizerPhase().apply(graph, highContext); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext); + new InliningPhase(new InlineEverythingPolicy(), createCanonicalizerPhase()).apply(graph, highContext); + this.createCanonicalizerPhase().apply(graph, highContext); + new LoweringPhase(this.createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext); new GuardLoweringPhase().apply(graph, midContext); - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); + new LoweringPhase(this.createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); new WriteBarrierAdditionPhase().apply(graph, midContext); debug.dump(DebugContext.BASIC_LEVEL, graph, "After Write Barrier Addition"); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java Thu Oct 31 16:54:16 2019 -0700 @@ -72,26 +72,40 @@ replacements.getDefaultReplacementBytecodeProvider(), replacements.target); } + public void maybeInitializeEncoder(OptionValues options) { + if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { + synchronized (HotSpotReplacementsImpl.class) { + if (snippetEncoder == null) { + snippetEncoder = new SymbolicSnippetEncoder(this); + } + } + } + } + @Override public Class getIntrinsifyingPlugin(ResolvedJavaMethod method) { return method.getAnnotation(HotSpotOperation.class) != null ? HotSpotWordOperationPlugin.class : super.getIntrinsifyingPlugin(method); } @Override - public void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) { - if (!IS_IN_NATIVE_IMAGE) { - if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { - synchronized (HotSpotReplacementsImpl.class) { - if (snippetEncoder == null) { - snippetEncoder = new SymbolicSnippetEncoder(this); - } - snippetEncoder.registerMethodSubstitution(plugin, original, context, options); - } - } + public void registerMethodSubstitution(MethodSubstitutionPlugin plugin) { + if (snippetEncoder != null) { + snippetEncoder.registerMethodSubstitution(plugin); } } @Override + public void registerConditionalPlugin(InvocationPlugin plugin) { + if (snippetEncoder != null) { + snippetEncoder.registerConditionalPlugin(plugin); + } + } + + public void checkRegistered(MethodSubstitutionPlugin plugin) { + snippetEncoder.checkRegistered(plugin); + } + + @Override public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug, Cancellable cancellable) { boolean useEncodedGraphs = UseEncodedGraphs.getValue(debug.getOptions()); if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) { @@ -99,8 +113,9 @@ InvocationPlugin plugin = replacements.getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(method); if (plugin instanceof MethodSubstitutionPlugin) { MethodSubstitutionPlugin msp = (MethodSubstitutionPlugin) plugin; - if (useEncodedGraphs) { - replacements.registerMethodSubstitution(msp, method, ROOT_COMPILATION, debug.getOptions()); + if (!IS_IN_NATIVE_IMAGE && useEncodedGraphs) { + replacements.maybeInitializeEncoder(debug.getOptions()); + replacements.registerMethodSubstitution(msp); } StructuredGraph methodSubstitution = replacements.getMethodSubstitution(msp, method, ROOT_COMPILATION, StructuredGraph.AllowAssumptions.YES, cancellable, debug.getOptions()); methodSubstitution.resetDebug(debug); @@ -119,7 +134,8 @@ if (plugin instanceof MethodSubstitutionPlugin && (!plugin.inlineOnly() || invokeBci >= 0)) { MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin; if (!IS_IN_NATIVE_IMAGE && useEncodedGraphs) { - registerMethodSubstitution(msPlugin, targetMethod, INLINE_AFTER_PARSING, options); + maybeInitializeEncoder(options); + registerMethodSubstitution(msPlugin); } // This assumes the normal path creates the graph using // GraphBuilderConfiguration.getSnippetDefault with omits exception edges @@ -155,9 +171,6 @@ assert registeredSnippets.add(method) : "Cannot register snippet twice: " + method.format("%H.%n(%p)"); if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { synchronized (HotSpotReplacementsImpl.class) { - if (snippetEncoder == null) { - snippetEncoder = new SymbolicSnippetEncoder(this); - } snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition, options); } } @@ -169,7 +182,10 @@ snippetRegistrationClosed = true; } - private static SymbolicSnippetEncoder.EncodedSnippets getEncodedSnippets() { + private static SymbolicSnippetEncoder.EncodedSnippets getEncodedSnippets(OptionValues options) { + if (!IS_IN_NATIVE_IMAGE && snippetEncoder != null) { + snippetEncoder.encode(options); + } return encodedSnippets; } @@ -210,20 +226,15 @@ @SuppressWarnings("try") private StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, Object[] args, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { - boolean useEncodedGraphs = UseEncodedGraphs.getValue(options); - if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) { + if (IS_IN_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { synchronized (HotSpotReplacementsImpl.class) { - if (!IS_IN_NATIVE_IMAGE) { - snippetEncoder.encode(options); - } - - if (getEncodedSnippets() == null) { + if (getEncodedSnippets(options) == null) { throw GraalError.shouldNotReachHere("encoded snippets not found"); } // Snippets graphs can contain foreign object reference and // outlive a single compilation. try (CompilationContext scope = HotSpotGraalServices.enterGlobalCompilationContext()) { - StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, this, args, allowAssumptions, options); + StructuredGraph graph = getEncodedSnippets(options).getEncodedSnippet(method, this, args, allowAssumptions, options); if (graph == null) { throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); } @@ -239,16 +250,11 @@ @Override public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, StructuredGraph.AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options) { - boolean useEncodedGraphs = UseEncodedGraphs.getValue(options); - if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) { - if (!IS_IN_NATIVE_IMAGE) { - snippetEncoder.encode(options); - } - - if (getEncodedSnippets() == null) { + if (IS_IN_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { + if (getEncodedSnippets(options) == null) { throw GraalError.shouldNotReachHere("encoded snippets not found"); } - return getEncodedSnippets().getMethodSubstitutionGraph(plugin, original, this, context, allowAssumptions, cancellable, options); + return getEncodedSnippets(options).getMethodSubstitutionGraph(plugin, original, this, context, allowAssumptions, cancellable, options); } return null; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java Thu Oct 31 16:54:16 2019 -0700 @@ -30,6 +30,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; +import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; import java.util.ArrayList; import java.util.Arrays; @@ -156,6 +157,12 @@ */ private Map preparedSnippetGraphs = new HashMap<>(); + private Set knownPlugins = new HashSet<>(); + + private Set conditionalPlugins = new HashSet<>(); + + private int preparedPlugins = 0; + /** * The invocation plugins which were delayed during graph preparation. */ @@ -239,7 +246,7 @@ * for lookup. */ private static String methodKey(ResolvedJavaMethod method) { - return method.format("%f %H.%n(%P)"); + return method.format("%H.%n(%P)"); } SymbolicSnippetEncoder(HotSpotReplacementsImpl replacements) { @@ -255,15 +262,30 @@ this.snippetReplacements.setGraphBuilderPlugins(copy); } + synchronized void registerMethodSubstitution(MethodSubstitutionPlugin plugin) { + knownPlugins.add(plugin); + } + + void registerConditionalPlugin(InvocationPlugin plugin) { + conditionalPlugins.add(plugin); + } + + synchronized void checkRegistered(MethodSubstitutionPlugin plugin) { + if (!knownPlugins.contains(plugin)) { + throw new GraalError("missing plugin should have been registered during construction"); + } + } + /** * Compiles the snippet and stores the graph. */ - synchronized void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) { + private synchronized void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) { ResolvedJavaMethod method = plugin.getSubstitute(snippetReplacements.getProviders().getMetaAccess()); assert method.getAnnotation(MethodSubstitution.class) != null : "MethodSubstitution must be annotated with @" + MethodSubstitution.class.getSimpleName(); - StructuredGraph subst = buildGraph(method, original, null, true, false, context, options); + String originalMethodString = plugin.originalMethodAsString(); + StructuredGraph subst = buildGraph(method, original, originalMethodString, null, true, false, context, options); snippetMethods.add(method); - originalMethods.put(methodKey(method), methodKey(original)); + originalMethods.put(methodKey(method), originalMethodString); preparedSnippetGraphs.put(plugin.toString() + context, subst); } @@ -370,7 +392,7 @@ } } - private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean requireInlining, boolean trackNodeSourcePosition, + private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, Object receiver, boolean requireInlining, boolean trackNodeSourcePosition, IntrinsicContext.CompilationContext context, OptionValues options) { assert method.hasBytecodes() : "Snippet must not be abstract or native"; Object[] args = null; @@ -378,7 +400,13 @@ args = new Object[method.getSignature().getParameterCount(true)]; args[0] = receiver; } - try (DebugContext debug = openDebugContext("Snippet_", method, options)) { + // To get dumping out from this context during image building, it's necessary to pass the + // dumping options directly to the VM, otherwise they aren't available during initialization + // of the backend. Use this: + // + // -J-Dgraal.Dump=SymbolicSnippetEncoder_:2 -J-Dgraal.PrintGraph=File + // -J-Dgraal.DebugStubsAndSnippets=true + try (DebugContext debug = openDebugContext("SymbolicSnippetEncoder_", method, options)) { StructuredGraph graph = snippetReplacements.makeGraph(debug, snippetReplacements.getDefaultReplacementBytecodeProvider(), method, args, original, trackNodeSourcePosition, null, context); // Check if all methods which should be inlined are really inlined. @@ -388,7 +416,7 @@ throw GraalError.shouldNotReachHere("method " + callee.format("%H.%n") + " not inlined in snippet " + method.getName() + " (maybe not final?)"); } } - assert verifySnippetEncodeDecode(method, original, trackNodeSourcePosition, graph); + assert verifySnippetEncodeDecode(debug, method, original, originalMethodString, trackNodeSourcePosition, graph); debug.dump(DebugContext.VERBOSE_LEVEL, graph, "After buildGraph"); return graph; } @@ -426,46 +454,45 @@ } @SuppressWarnings("try") - private boolean verifySnippetEncodeDecode(ResolvedJavaMethod method, ResolvedJavaMethod original, boolean trackNodeSourcePosition, StructuredGraph graph) { + private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, boolean trackNodeSourcePosition, + StructuredGraph graph) { // Verify the encoding and decoding process EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch); - try (DebugContext debug = snippetReplacements.openDebugContext("VerifySnippetEncodeDecode_", method, graph.getOptions())) { - HotSpotProviders originalProvider = (HotSpotProviders) snippetReplacements.getProviders(); + HotSpotProviders originalProvider = (HotSpotProviders) snippetReplacements.getProviders(); - SnippetReflectionProvider snippetReflection = originalProvider.getSnippetReflection(); - SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider constantReflection = new SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider( - originalProvider.getConstantReflection()); - HotSpotProviders newProviders = new HotSpotProviders(originalProvider.getMetaAccess(), originalProvider.getCodeCache(), constantReflection, - originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(), - originalProvider.getRegisters(), snippetReflection, originalProvider.getWordTypes(), originalProvider.getGraphBuilderPlugins(), originalProvider.getGC()); - HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, snippetReflection, - originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget()); - filteringReplacements.setGraphBuilderPlugins(originalProvider.getReplacements().getGraphBuilderPlugins()); - try (DebugContext.Scope scaope = debug.scope("VerifySnippetEncodeDecode", graph)) { - for (int i = 0; i < encodedGraph.getNumObjects(); i++) { - filterSnippetObject(encodedGraph.getObject(i)); - } - StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, null, original, - trackNodeSourcePosition, null); - SymbolicEncodedGraph symbolicGraph = new SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), original != null ? methodKey(original) : null); - StructuredGraph decodedSnippet = decodeSnippetGraph(symbolicGraph, original != null ? original : method, originalReplacements, null, - StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions()); - String snippetString = getCanonicalGraphString(snippet, true, false); - String decodedSnippetString = getCanonicalGraphString(decodedSnippet, true, false); - if (snippetString.equals(decodedSnippetString)) { - debug.log("Snippet decode for %s produces exactly same graph", method); - debug.dump(DebugContext.VERBOSE_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method); - } else { - debug.log("Snippet decode for %s produces different graph", method); - debug.log("%s", compareGraphStrings(snippet, snippetString, decodedSnippet, decodedSnippetString)); - debug.dump(DebugContext.VERBOSE_LEVEL, snippet, "Snippet graph for %s", method); - debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Encoded snippet graph for %s", method); - debug.dump(DebugContext.VERBOSE_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method); - } - } catch (Throwable t) { - throw debug.handle(t); + SnippetReflectionProvider snippetReflection = originalProvider.getSnippetReflection(); + SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider constantReflection = new SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider( + originalProvider.getConstantReflection()); + HotSpotProviders newProviders = new HotSpotProviders(originalProvider.getMetaAccess(), originalProvider.getCodeCache(), constantReflection, + originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(), + originalProvider.getRegisters(), snippetReflection, originalProvider.getWordTypes(), originalProvider.getGraphBuilderPlugins(), originalProvider.getGC()); + HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, snippetReflection, + originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget()); + filteringReplacements.setGraphBuilderPlugins(originalProvider.getReplacements().getGraphBuilderPlugins()); + try (DebugContext.Scope scaope = debug.scope("VerifySnippetEncodeDecode", graph)) { + for (int i = 0; i < encodedGraph.getNumObjects(); i++) { + filterSnippetObject(encodedGraph.getObject(i)); } + StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, null, original, + trackNodeSourcePosition, null); + SymbolicEncodedGraph symbolicGraph = new SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), originalMethodString); + StructuredGraph decodedSnippet = decodeSnippetGraph(symbolicGraph, original != null ? original : method, originalReplacements, null, + StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions()); + String snippetString = getCanonicalGraphString(snippet, true, false); + String decodedSnippetString = getCanonicalGraphString(decodedSnippet, true, false); + if (snippetString.equals(decodedSnippetString)) { + debug.log("Snippet decode for %s produces exactly same graph", method); + debug.dump(DebugContext.VERBOSE_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method); + } else { + debug.log("Snippet decode for %s produces different graph", method); + debug.log("%s", compareGraphStrings(snippet, snippetString, decodedSnippet, decodedSnippetString)); + debug.dump(DebugContext.VERBOSE_LEVEL, snippet, "Snippet graph for %s", method); + debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Encoded snippet graph for %s", method); + debug.dump(DebugContext.VERBOSE_LEVEL, decodedSnippet, "Decoded snippet graph for %s", method); + } + } catch (Throwable t) { + throw debug.handle(t); } return true; } @@ -475,6 +502,17 @@ */ @SuppressWarnings("try") private synchronized EncodedSnippets maybeEncodeSnippets(OptionValues options) { + Set plugins = this.knownPlugins; + if (preparedPlugins != plugins.size()) { + for (MethodSubstitutionPlugin plugin : plugins) { + ResolvedJavaMethod original = plugin.getOriginalMethod(originalReplacements.getProviders().getMetaAccess()); + registerMethodSubstitution(plugin, original, INLINE_AFTER_PARSING, options); + if (!original.isNative()) { + registerMethodSubstitution(plugin, original, ROOT_COMPILATION, options); + } + } + preparedPlugins = plugins.size(); + } Map graphs = this.preparedSnippetGraphs; if (encodedGraphs != graphs.size()) { DebugContext debug = openDebugContext("SnippetEncoder", null, options); @@ -499,7 +537,7 @@ if (original != null) { originalMethods.put(key, methodKey(original)); } - StructuredGraph snippet = buildGraph(method, original, receiver, true, trackNodeSourcePosition, INLINE_AFTER_PARSING, options); + StructuredGraph snippet = buildGraph(method, original, null, receiver, true, trackNodeSourcePosition, INLINE_AFTER_PARSING, options); snippetMethods.add(method); preparedSnippetGraphs.put(key, snippet); } @@ -1001,7 +1039,7 @@ * This horror show of classes exists solely get {@link HotSpotSnippetBytecodeParser} to be used * as the parser for these snippets. */ - static class HotSpotSnippetReplacementsImpl extends HotSpotReplacementsImpl { + class HotSpotSnippetReplacementsImpl extends HotSpotReplacementsImpl { HotSpotSnippetReplacementsImpl(HotSpotReplacementsImpl replacements, Providers providers) { super(replacements, providers); } @@ -1016,7 +1054,7 @@ } } - static class SnippetGraphMaker extends ReplacementsImpl.GraphMaker { + class SnippetGraphMaker extends ReplacementsImpl.GraphMaker { SnippetGraphMaker(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod) { super(replacements, substitute, substitutedMethod); } @@ -1028,7 +1066,7 @@ } } - static class HotSpotSnippetGraphBuilderPhase extends GraphBuilderPhase.Instance { + class HotSpotSnippetGraphBuilderPhase extends GraphBuilderPhase.Instance { HotSpotSnippetGraphBuilderPhase(Providers theProviders, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { super(theProviders, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); } @@ -1039,7 +1077,7 @@ } } - static class HotSpotSnippetBytecodeParser extends BytecodeParser { + class HotSpotSnippetBytecodeParser extends BytecodeParser { HotSpotSnippetBytecodeParser(GraphBuilderPhase.Instance graphBuilderInstance, StructuredGraph graph, BytecodeParser parent, ResolvedJavaMethod method, int entryBCI, IntrinsicContext intrinsicContext) { super(graphBuilderInstance, graph, parent, method, entryBCI, intrinsicContext); @@ -1066,6 +1104,13 @@ // Always defer Fold until decode time but NodeIntrinsics may fold if they are able. return false; } + InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod); + if (conditionalPlugins.contains(plugin)) { + // Because supporting arbitrary plugins in the context of encoded graphs is complex + // we disallow it. This limitation can be worked around through the use of method + // substitutions. + throw new GraalError("conditional plugins are unsupported in snippets and method substitutions: " + targetMethod + " " + plugin); + } return super.tryInvocationPlugin(invokeKind, args, targetMethod, resultType); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Thu Oct 31 16:54:16 2019 -0700 @@ -646,7 +646,7 @@ // write the displaced mark to the correct stack slot AddressNode addressDisplacedMark = createOffsetAddress(graph, beginLockScope, runtime.getVMConfig().basicLockDisplacedHeaderOffset); - WriteNode writeStackSlot = graph.add(new WriteNode(addressDisplacedMark, DISPLACED_MARK_WORD_LOCATION, loadDisplacedHeader, BarrierType.NONE)); + WriteNode writeStackSlot = graph.add(new WriteNode(addressDisplacedMark, DISPLACED_MARK_WORD_LOCATION, loadDisplacedHeader, BarrierType.NONE, false)); graph.addBeforeFixed(migrationEnd, writeStackSlot); // load the lock object from the osr buffer @@ -776,7 +776,7 @@ } AddressNode address = createOffsetAddress(graph, object, runtime.getVMConfig().hubOffset); - return graph.add(new WriteNode(address, HUB_WRITE_LOCATION, writeValue, BarrierType.NONE)); + return graph.add(new WriteNode(address, HUB_WRITE_LOCATION, writeValue, BarrierType.NONE, false)); } @Override diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Thu Oct 31 16:54:16 2019 -0700 @@ -39,7 +39,6 @@ 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; @@ -92,6 +91,7 @@ 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.Replacements; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; @@ -108,6 +108,7 @@ import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.vm.ci.code.CodeUtil; +import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.hotspot.VMIntrinsicMethod; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.DeoptimizationAction; @@ -128,6 +129,7 @@ * @param snippetReflection * @param foreignCalls * @param options + * @param target */ public static Plugins create(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, @@ -138,11 +140,11 @@ SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, ReplacementsImpl replacements, - OptionValues options) { + OptionValues options, TargetDescription target) { InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(graalRuntime, config, compilerConfiguration); Plugins plugins = new Plugins(invocationPlugins); - NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes); + NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes, target); HotSpotWordOperationPlugin wordOperationPlugin = new HotSpotWordOperationPlugin(snippetReflection, wordTypes); HotSpotNodePlugin nodePlugin = new HotSpotNodePlugin(wordOperationPlugin, config, wordTypes); @@ -171,29 +173,28 @@ @Override public void run() { - BytecodeProvider replacementBytecodeProvider = replacements.getDefaultReplacementBytecodeProvider(); - registerObjectPlugins(invocationPlugins, options, config, replacementBytecodeProvider); - registerClassPlugins(plugins, config, replacementBytecodeProvider); + registerObjectPlugins(invocationPlugins, options, config, replacements); + registerClassPlugins(plugins, config, replacements); registerSystemPlugins(invocationPlugins, foreignCalls); - registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config, replacementBytecodeProvider); + registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config, replacements); if (!GeneratePIC.getValue(options)) { registerCallSitePlugins(invocationPlugins); } - registerReflectionPlugins(invocationPlugins, replacementBytecodeProvider); - registerConstantPoolPlugins(invocationPlugins, wordTypes, config, replacementBytecodeProvider); - registerAESPlugins(invocationPlugins, config, replacementBytecodeProvider); - registerCRC32Plugins(invocationPlugins, config, replacementBytecodeProvider); - registerCRC32CPlugins(invocationPlugins, config, replacementBytecodeProvider); - registerBigIntegerPlugins(invocationPlugins, config, replacementBytecodeProvider); - registerSHAPlugins(invocationPlugins, config, replacementBytecodeProvider); + registerReflectionPlugins(invocationPlugins, replacements); + registerConstantPoolPlugins(invocationPlugins, wordTypes, config, replacements); + registerAESPlugins(invocationPlugins, config, replacements); + registerCRC32Plugins(invocationPlugins, config, replacements); + registerCRC32CPlugins(invocationPlugins, config, replacements); + registerBigIntegerPlugins(invocationPlugins, config, replacements); + registerSHAPlugins(invocationPlugins, config, replacements); registerGHASHPlugins(invocationPlugins, config, metaAccess, foreignCalls); - registerCounterModePlugins(invocationPlugins, config, replacementBytecodeProvider); + registerCounterModePlugins(invocationPlugins, config, replacements); registerBase64Plugins(invocationPlugins, config, metaAccess, foreignCalls); - registerUnsafePlugins(invocationPlugins, config, replacementBytecodeProvider); - StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, snippetReflection, invocationPlugins, replacementBytecodeProvider, true, false); - registerArrayPlugins(invocationPlugins, replacementBytecodeProvider); - registerStringPlugins(invocationPlugins, replacementBytecodeProvider); - registerArraysSupportPlugins(invocationPlugins, config, replacementBytecodeProvider); + registerUnsafePlugins(invocationPlugins, config, replacements); + StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, snippetReflection, invocationPlugins, replacements, true, false); + registerArrayPlugins(invocationPlugins, replacements); + registerStringPlugins(invocationPlugins, replacements); + registerArraysSupportPlugins(invocationPlugins, config, replacements); for (NodeIntrinsicPluginFactory factory : GraalServices.load(NodeIntrinsicPluginFactory.class)) { factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider); @@ -203,8 +204,8 @@ return plugins; } - private static void registerObjectPlugins(InvocationPlugins plugins, OptionValues options, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins, Object.class, bytecodeProvider); + private static void registerObjectPlugins(InvocationPlugins plugins, OptionValues options, GraalHotSpotVMConfig config, Replacements replacements) { + Registration r = new Registration(plugins, Object.class, replacements); if (!GeneratePIC.getValue(options)) { // FIXME: clone() requires speculation and requires a fix in here (to check that // b.getAssumptions() != null), and in ReplacementImpl.getSubstitution() where there is @@ -235,8 +236,8 @@ } } - private static void registerClassPlugins(Plugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins.getInvocationPlugins(), Class.class, bytecodeProvider); + private static void registerClassPlugins(Plugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { + Registration r = new Registration(plugins.getInvocationPlugins(), Class.class, replacements); r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "getModifiers", Receiver.class); r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "isInterface", Receiver.class); @@ -273,8 +274,8 @@ plugins.register(plugin, VolatileCallSite.class, "getTarget", Receiver.class); } - private static void registerReflectionPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins, reflectionClass, bytecodeProvider); + private static void registerReflectionPlugins(InvocationPlugins plugins, Replacements replacements) { + Registration r = new Registration(plugins, reflectionClass, replacements); r.register0("getCallerClass", new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { @@ -290,12 +291,12 @@ r.registerMethodSubstitution(ReflectionSubstitutions.class, "getClassAccessFlags", Class.class); } - private static void registerUnsafePlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider replacementBytecodeProvider) { + private static void registerUnsafePlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { Registration r; if (JavaVersionUtil.JAVA_SPEC <= 8) { - r = new Registration(plugins, Unsafe.class, replacementBytecodeProvider); + r = new Registration(plugins, Unsafe.class, replacements); } else { - r = new Registration(plugins, "jdk.internal.misc.Unsafe", replacementBytecodeProvider); + r = new Registration(plugins, "jdk.internal.misc.Unsafe", replacements); } String substituteMethodName = config.doingUnsafeAccessOffset != Integer.MAX_VALUE ? "copyMemoryGuarded" : "copyMemory"; r.registerMethodSubstitution(HotSpotUnsafeSubstitutions.class, HotSpotUnsafeSubstitutions.copyMemoryName, substituteMethodName, Receiver.class, Object.class, long.class, Object.class, @@ -340,8 +341,8 @@ return true; } - private static void registerConstantPoolPlugins(InvocationPlugins plugins, WordTypes wordTypes, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins, constantPoolClass, bytecodeProvider); + private static void registerConstantPoolPlugins(InvocationPlugins plugins, WordTypes wordTypes, GraalHotSpotVMConfig config, Replacements replacements) { + Registration r = new Registration(plugins, constantPoolClass, replacements); r.register2("getSize0", Receiver.class, Object.class, new InvocationPlugin() { @Override @@ -411,22 +412,22 @@ }); } - private static void registerArrayPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins, Array.class, bytecodeProvider); + private static void registerArrayPlugins(InvocationPlugins plugins, Replacements replacements) { + Registration r = new Registration(plugins, Array.class, replacements); r.setAllowOverwrite(true); r.registerMethodSubstitution(HotSpotArraySubstitutions.class, "newInstance", Class.class, int.class); } - private static void registerStringPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { + private static void registerStringPlugins(InvocationPlugins plugins, Replacements replacements) { if (JavaVersionUtil.JAVA_SPEC > 8) { - final Registration utf16r = new Registration(plugins, "java.lang.StringUTF16", bytecodeProvider); + final Registration utf16r = new Registration(plugins, "java.lang.StringUTF16", replacements); utf16r.registerMethodSubstitution(StringUTF16Substitutions.class, "toBytes", char[].class, int.class, int.class); utf16r.registerMethodSubstitution(StringUTF16Substitutions.class, "getChars", byte[].class, int.class, int.class, char[].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); + private static void registerThreadPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, WordTypes wordTypes, GraalHotSpotVMConfig config, Replacements replacements) { + Registration r = new Registration(plugins, Thread.class, replacements); r.register0("currentThread", new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { @@ -443,40 +444,51 @@ r.registerMethodSubstitution(ThreadSubstitutions.class, "isInterrupted", Receiver.class, boolean.class); } - public static final String aesEncryptName; - public static final String aesDecryptName; - public static final String reflectionClass; public static final String constantPoolClass; static { if (JavaVersionUtil.JAVA_SPEC <= 8) { - aesEncryptName = "encryptBlock"; - aesDecryptName = "decryptBlock"; reflectionClass = "sun.reflect.Reflection"; constantPoolClass = "sun.reflect.ConstantPool"; } else { - aesEncryptName = "implEncryptBlock"; - aesDecryptName = "implDecryptBlock"; reflectionClass = "jdk.internal.reflect.Reflection"; constantPoolClass = "jdk.internal.reflect.ConstantPool"; } } - public static boolean cbcUsesImplNames(GraalHotSpotVMConfig config) { + public static String lookupIntrinsicName(GraalHotSpotVMConfig config, String className, String name1, String name2) { + boolean foundName1 = false; + boolean foundName2 = false; + String name = name1; for (VMIntrinsicMethod intrinsic : config.getStore().getIntrinsics()) { - if ("com/sun/crypto/provider/CipherBlockChaining".equals(intrinsic.declaringClass)) { - if ("encrypt".equals(intrinsic.name)) { - return false; - } else if ("implEncrypt".equals(intrinsic.name)) { + if (className.equals(intrinsic.declaringClass)) { + if (name1.equals(intrinsic.name)) { + foundName1 = true; + } else if (name2.equals(intrinsic.name)) { + foundName2 = true; + name = name2; + } + } + } + if (foundName1 != foundName2) { + return name; + } + throw GraalError.shouldNotReachHere(); + } + + public static boolean isIntrinsicName(GraalHotSpotVMConfig config, String className, String name) { + for (VMIntrinsicMethod intrinsic : config.getStore().getIntrinsics()) { + if (className.equals(intrinsic.declaringClass)) { + if (name.equals(intrinsic.name)) { return true; } } } - throw GraalError.shouldNotReachHere(); + return false; } - private static void registerAESPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { + private static void registerAESPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { if (config.useAESIntrinsics) { assert config.aescryptEncryptBlockStub != 0L; assert config.aescryptDecryptBlockStub != 0L; @@ -484,72 +496,66 @@ assert config.cipherBlockChainingDecryptAESCryptStub != 0L; String arch = config.osArch; String decryptSuffix = arch.equals("sparc") ? "WithOriginalKey" : ""; - Registration r = new Registration(plugins, "com.sun.crypto.provider.CipherBlockChaining", bytecodeProvider); - boolean implNames = cbcUsesImplNames(config); - String cbcEncryptName = implNames ? "implEncrypt" : "encrypt"; - String cbcDecryptName = implNames ? "implDecrypt" : "decrypt"; - + String cbcEncryptName = lookupIntrinsicName(config, "com/sun/crypto/provider/CipherBlockChaining", "implEncrypt", "encrypt"); + String cbcDecryptName = lookupIntrinsicName(config, "com/sun/crypto/provider/CipherBlockChaining", "implDecrypt", "decrypt"); + Registration r = new Registration(plugins, "com.sun.crypto.provider.CipherBlockChaining", replacements); r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, cbcEncryptName, Receiver.class, byte[].class, int.class, int.class, byte[].class, int.class); r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, cbcDecryptName, cbcDecryptName + decryptSuffix, Receiver.class, byte[].class, int.class, int.class, byte[].class, int.class); - r = new Registration(plugins, "com.sun.crypto.provider.AESCrypt", bytecodeProvider); + String aesEncryptName = lookupIntrinsicName(config, "com/sun/crypto/provider/AESCrypt", "implEncryptBlock", "encryptBlock"); + String aesDecryptName = lookupIntrinsicName(config, "com/sun/crypto/provider/AESCrypt", "implDecryptBlock", "decryptBlock"); + + r = new Registration(plugins, "com.sun.crypto.provider.AESCrypt", replacements); r.registerMethodSubstitution(AESCryptSubstitutions.class, aesEncryptName, Receiver.class, byte[].class, int.class, byte[].class, int.class); r.registerMethodSubstitution(AESCryptSubstitutions.class, aesDecryptName, aesDecryptName + decryptSuffix, Receiver.class, byte[].class, int.class, byte[].class, int.class); } } - private static void registerBigIntegerPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins, BigInteger.class, bytecodeProvider); - if (config.useMultiplyToLenIntrinsic()) { - assert config.multiplyToLen != 0L; - if (JavaVersionUtil.JAVA_SPEC <= 8) { - r.registerMethodSubstitution(BigIntegerSubstitutions.class, "multiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, int.class, - int[].class); - } else { - r.registerMethodSubstitution(BigIntegerSubstitutions.class, "implMultiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, int.class, - int[].class); - } + private static void registerBigIntegerPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { + Registration r = new Registration(plugins, BigInteger.class, replacements); + assert !config.useMultiplyToLenIntrinsic() || config.multiplyToLen != 0L; + if (JavaVersionUtil.JAVA_SPEC <= 8) { + r.registerConditionalMethodSubstitution(config.useMultiplyToLenIntrinsic(), BigIntegerSubstitutions.class, "multiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, + int.class, int[].class); + } else { + r.registerConditionalMethodSubstitution(config.useMultiplyToLenIntrinsic(), BigIntegerSubstitutions.class, "implMultiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, + int.class, int[].class); } - if (config.useMulAddIntrinsic()) { - r.registerMethodSubstitution(BigIntegerSubstitutions.class, "implMulAdd", int[].class, int[].class, int.class, int.class, int.class); - } - if (config.useMontgomeryMultiplyIntrinsic()) { - r.registerMethodSubstitution(BigIntegerSubstitutions.class, "implMontgomeryMultiply", int[].class, int[].class, int[].class, int.class, long.class, int[].class); - } - if (config.useMontgomerySquareIntrinsic()) { - r.registerMethodSubstitution(BigIntegerSubstitutions.class, "implMontgomerySquare", int[].class, int[].class, int.class, long.class, int[].class); - } - if (config.useSquareToLenIntrinsic()) { - r.registerMethodSubstitution(BigIntegerSubstitutions.class, "implSquareToLen", int[].class, int.class, int[].class, int.class); - } + r.registerConditionalMethodSubstitution(config.useMulAddIntrinsic(), BigIntegerSubstitutions.class, "implMulAdd", int[].class, int[].class, int.class, int.class, int.class); + r.registerConditionalMethodSubstitution(config.useMontgomeryMultiplyIntrinsic(), BigIntegerSubstitutions.class, "implMontgomeryMultiply", int[].class, int[].class, int[].class, int.class, + long.class, int[].class); + r.registerConditionalMethodSubstitution(config.useMontgomerySquareIntrinsic(), BigIntegerSubstitutions.class, "implMontgomerySquare", int[].class, int[].class, int.class, long.class, + int[].class); + r.registerConditionalMethodSubstitution(config.useSquareToLenIntrinsic(), BigIntegerSubstitutions.class, "implSquareToLen", int[].class, int.class, int[].class, int.class); } - private static void registerSHAPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { + private static void registerSHAPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { boolean useSha1 = config.useSHA1Intrinsics(); boolean useSha256 = config.useSHA256Intrinsics(); boolean useSha512 = config.useSHA512Intrinsics(); - if (JavaVersionUtil.JAVA_SPEC > 8 && (useSha1 || useSha256 || useSha512)) { - Registration r = new Registration(plugins, "sun.security.provider.DigestBase", bytecodeProvider); + if (isIntrinsicName(config, "sun/security/provider/DigestBase", "implCompressMultiBlock0") && (useSha1 || useSha256 || useSha512)) { + Registration r = new Registration(plugins, "sun.security.provider.DigestBase", replacements); r.registerMethodSubstitution(DigestBaseSubstitutions.class, "implCompressMultiBlock0", Receiver.class, byte[].class, int.class, int.class); } + String implCompressName = lookupIntrinsicName(config, "sun/security/provider/SHA", "implCompress", "implCompress0"); if (useSha1) { assert config.sha1ImplCompress != 0L; - Registration r = new Registration(plugins, "sun.security.provider.SHA", bytecodeProvider); - r.registerMethodSubstitution(SHASubstitutions.class, SHASubstitutions.implCompressName, "implCompress0", Receiver.class, byte[].class, int.class); + Registration r = new Registration(plugins, "sun.security.provider.SHA", replacements); + r.registerMethodSubstitution(SHASubstitutions.class, implCompressName, "implCompress0", Receiver.class, byte[].class, int.class); } if (useSha256) { assert config.sha256ImplCompress != 0L; - Registration r = new Registration(plugins, "sun.security.provider.SHA2", bytecodeProvider); - r.registerMethodSubstitution(SHA2Substitutions.class, SHA2Substitutions.implCompressName, "implCompress0", Receiver.class, byte[].class, int.class); + Registration r = new Registration(plugins, "sun.security.provider.SHA2", replacements); + r.registerMethodSubstitution(SHA2Substitutions.class, implCompressName, "implCompress0", Receiver.class, byte[].class, int.class); } if (useSha512) { assert config.sha512ImplCompress != 0L; - Registration r = new Registration(plugins, "sun.security.provider.SHA5", bytecodeProvider); - r.registerMethodSubstitution(SHA5Substitutions.class, SHA5Substitutions.implCompressName, "implCompress0", Receiver.class, byte[].class, int.class); + Registration r = new Registration(plugins, "sun.security.provider.SHA5", replacements); + r.registerMethodSubstitution(SHA5Substitutions.class, implCompressName, "implCompress0", Receiver.class, byte[].class, int.class); } } @@ -586,11 +592,12 @@ } } - private static void registerCounterModePlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { - if (config.useAESCTRIntrinsics) { - assert config.counterModeAESCrypt != 0L; - Registration r = new Registration(plugins, "com.sun.crypto.provider.CounterMode", bytecodeProvider); - r.registerMethodSubstitution(CounterModeSubstitutions.class, "implCrypt", Receiver.class, byte[].class, int.class, int.class, byte[].class, int.class); + private static void registerCounterModePlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { + if (JavaVersionUtil.JAVA_SPEC > 8) { + assert !config.useAESCTRIntrinsics || config.counterModeAESCrypt != 0L; + Registration r = new Registration(plugins, "com.sun.crypto.provider.CounterMode", replacements); + r.registerConditionalMethodSubstitution(config.useAESCTRIntrinsics, CounterModeSubstitutions.class, "implCrypt", Receiver.class, byte[].class, int.class, int.class, byte[].class, + int.class); } } @@ -626,32 +633,31 @@ } } - private static void registerCRC32Plugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { - if (config.useCRC32Intrinsics) { - Registration r = new Registration(plugins, CRC32.class, bytecodeProvider); - r.registerMethodSubstitution(CRC32Substitutions.class, "update", int.class, int.class); - if (JavaVersionUtil.JAVA_SPEC <= 8) { - r.registerMethodSubstitution(CRC32Substitutions.class, "updateBytes", int.class, byte[].class, int.class, int.class); - r.registerMethodSubstitution(CRC32Substitutions.class, "updateByteBuffer", int.class, long.class, int.class, int.class); - } else { - r.registerMethodSubstitution(CRC32Substitutions.class, "updateBytes0", int.class, byte[].class, int.class, int.class); - r.registerMethodSubstitution(CRC32Substitutions.class, "updateByteBuffer0", int.class, long.class, int.class, int.class); - } + private static void registerCRC32Plugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { + Registration r = new Registration(plugins, CRC32.class, replacements); + r.registerConditionalMethodSubstitution(config.useCRC32Intrinsics, CRC32Substitutions.class, "update", int.class, int.class); + if (JavaVersionUtil.JAVA_SPEC <= 8) { + r.registerConditionalMethodSubstitution(config.useCRC32Intrinsics, CRC32Substitutions.class, "updateBytes", int.class, byte[].class, int.class, int.class); + r.registerConditionalMethodSubstitution(config.useCRC32Intrinsics, CRC32Substitutions.class, "updateByteBuffer", int.class, long.class, int.class, int.class); + } else { + r.registerConditionalMethodSubstitution(config.useCRC32Intrinsics, CRC32Substitutions.class, "updateBytes0", int.class, byte[].class, int.class, int.class); + r.registerConditionalMethodSubstitution(config.useCRC32Intrinsics, CRC32Substitutions.class, "updateByteBuffer0", int.class, long.class, int.class, int.class); } } - private static void registerCRC32CPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { - if (config.useCRC32CIntrinsics) { - Registration r = new Registration(plugins, "java.util.zip.CRC32C", bytecodeProvider); - r.registerMethodSubstitution(CRC32CSubstitutions.class, "updateBytes", int.class, byte[].class, int.class, int.class); - r.registerMethodSubstitution(CRC32CSubstitutions.class, "updateDirectByteBuffer", int.class, long.class, int.class, int.class); + private static void registerCRC32CPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { + if (JavaVersionUtil.JAVA_SPEC > 8) { + Registration r = new Registration(plugins, "java.util.zip.CRC32C", replacements); + r.registerConditionalMethodSubstitution(config.useCRC32CIntrinsics, CRC32CSubstitutions.class, "updateBytes", int.class, byte[].class, int.class, int.class); + r.registerConditionalMethodSubstitution(config.useCRC32CIntrinsics, CRC32CSubstitutions.class, "updateDirectByteBuffer", int.class, long.class, int.class, int.class); } } - private static void registerArraysSupportPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { - if (config.useVectorizedMismatchIntrinsic) { - Registration r = new Registration(plugins, "jdk.internal.util.ArraysSupport", bytecodeProvider); - r.registerMethodSubstitution(ArraysSupportSubstitutions.class, "vectorizedMismatch", Object.class, long.class, Object.class, long.class, int.class, int.class); + private static void registerArraysSupportPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { + if (JavaVersionUtil.JAVA_SPEC > 8) { + Registration r = new Registration(plugins, "jdk.internal.util.ArraysSupport", replacements); + r.registerConditionalMethodSubstitution(config.useVectorizedMismatchIntrinsic, ArraysSupportSubstitutions.class, "vectorizedMismatch", Object.class, long.class, Object.class, long.class, + int.class, int.class); } } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Thu Oct 31 16:54:16 2019 -0700 @@ -339,8 +339,8 @@ linkForeignCall(options, providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); linkForeignCall(options, providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); linkForeignCall(options, providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, STACK_INSPECTABLE_LEAF, NOT_REEXECUTABLE, any()); - linkForeignCall(options, providers, NOTIFY, c.notifyAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); - linkForeignCall(options, providers, NOTIFY_ALL, c.notifyAllAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); + linkForeignCall(options, providers, NOTIFY, c.notifyAddress, PREPEND_THREAD, LEAF_NO_VZERO, NOT_REEXECUTABLE, any()); + linkForeignCall(options, providers, NOTIFY_ALL, c.notifyAllAddress, PREPEND_THREAD, LEAF_NO_VZERO, NOT_REEXECUTABLE, any()); linkForeignCall(options, providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); linkForeignCall(options, providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); linkForeignCall(options, providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java Thu Oct 31 16:54:16 2019 -0700 @@ -168,7 +168,7 @@ if (profileInstructions != null) { suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotInstructionProfiling(profileInstructions)); } - if (Assertions.detailedAssertionsEnabled(options)) { + if (Assertions.assertionsEnabled()) { suites.getPostAllocationOptimizationStage().appendPhase(new VerifyMaxRegisterSizePhase(config.maxVectorSize)); } return suites; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -73,7 +73,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -56,7 +56,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -72,7 +72,7 @@ } @Override - public LocationIdentity[] getLocationIdentities() { + public LocationIdentity[] getKilledLocationIdentities() { LocationIdentity[] killedLocations = foreignCalls.getKilledLocations(descriptor); killedLocations = Arrays.copyOf(killedLocations, killedLocations.length + 1); killedLocations[killedLocations.length - 1] = HotSpotReplacementsUtil.PENDING_EXCEPTION_LOCATION; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, 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 @@ -64,7 +64,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, 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 @@ -98,7 +98,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -64,7 +64,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -93,7 +93,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/AheadOfTimeVerificationPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/AheadOfTimeVerificationPhase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/AheadOfTimeVerificationPhase.java Thu Oct 31 16:54:16 2019 -0700 @@ -70,10 +70,22 @@ } private static boolean isDirectMethodHandle(ConstantNode node) { + String typeName = StampTool.typeOrNull(node).getName(); if (!isObject(node)) { return false; } - return "Ljava/lang/invoke/DirectMethodHandle;".equals(StampTool.typeOrNull(node).getName()); + + switch (typeName) { + case "Ljava/lang/invoke/DirectMethodHandle;": + case "Ljava/lang/invoke/DirectMethodHandle$StaticAccessor;": + case "Ljava/lang/invoke/DirectMethodHandle$Accessor;": + case "Ljava/lang/invoke/DirectMethodHandle$Constructor;": + case "Ljava/lang/invoke/DirectMethodHandle$Special;": + case "Ljava/lang/invoke/DirectMethodHandle$Interface;": + return true; + default: + return false; + } } private static boolean isBoundMethodHandle(ConstantNode node) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, 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 @@ -61,7 +61,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return HotSpotReplacementsUtil.MARK_WORD_LOCATION; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java Thu Oct 31 16:54:16 2019 -0700 @@ -36,7 +36,6 @@ import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.replacements.ReplacementsUtil; -import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.compiler.word.Word; import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.internal.vm.compiler.word.WordFactory; @@ -46,8 +45,6 @@ @ClassSubstitution(className = "sun.security.provider.SHA2", optional = true) public class SHA2Substitutions { - public static final String implCompressName = JavaVersionUtil.JAVA_SPEC <= 8 ? "implCompress" : "implCompress0"; - @MethodSubstitution(isStatic = false) static void implCompress0(Object receiver, byte[] buf, int ofs) { Object realReceiver = PiNode.piCastNonNull(receiver, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT)); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java Thu Oct 31 16:54:16 2019 -0700 @@ -37,7 +37,6 @@ import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.replacements.ReplacementsUtil; -import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.compiler.word.Word; import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.internal.vm.compiler.word.WordFactory; @@ -47,8 +46,6 @@ @ClassSubstitution(className = "sun.security.provider.SHA5", optional = true) public class SHA5Substitutions { - public static final String implCompressName = JavaVersionUtil.JAVA_SPEC <= 8 ? "implCompress" : "implCompress0"; - @MethodSubstitution(isStatic = false) static void implCompress0(Object receiver, byte[] buf, int ofs) { Object realReceiver = PiNode.piCastNonNull(receiver, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT)); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java Thu Oct 31 16:54:16 2019 -0700 @@ -37,7 +37,6 @@ import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.replacements.ReplacementsUtil; -import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.compiler.word.Word; import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.internal.vm.compiler.word.WordFactory; @@ -47,8 +46,6 @@ @ClassSubstitution(className = "sun.security.provider.SHA", optional = true) public class SHASubstitutions { - public static final String implCompressName = JavaVersionUtil.JAVA_SPEC <= 8 ? "implCompress" : "implCompress0"; - @MethodSubstitution(isStatic = false) static void implCompress0(Object receiver, byte[] buf, int ofs) { Object realReceiver = PiNode.piCastNonNull(receiver, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT)); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java Thu Oct 31 16:54:16 2019 -0700 @@ -56,7 +56,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.replacements.GraphKit; import org.graalvm.compiler.replacements.nodes.ReadRegisterNode; import org.graalvm.compiler.word.Word; @@ -258,7 +257,6 @@ debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Initial stub graph"); kit.inlineInvokes("Foreign call stub.", "Backend"); - new RemoveValueProxyPhase().apply(graph); debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Stub graph before compilation"); return graph; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java Thu Oct 31 16:54:16 2019 -0700 @@ -41,7 +41,6 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.Snippets; @@ -100,9 +99,8 @@ } } - new RemoveValueProxyPhase().apply(graph); graph.setGuardsStage(GuardsStage.FLOATING_GUARDS); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = CanonicalizerPhase.create(); canonicalizer.apply(graph, providers); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, providers); } catch (Throwable e) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Thu Oct 31 16:54:16 2019 -0700 @@ -3221,7 +3221,7 @@ lastInstr = loopBegin; // Create phi functions for all local variables and operand stack slots. - frameState.insertLoopPhis(liveness, block.loopId, loopBegin, forceLoopPhis(), stampFromValueForForcedPhis()); + frameState.insertLoopPhis(liveness, block.loopId, loopBegin, forceLoopPhis() || this.graphBuilderConfig.replaceLocalsWithConstants(), stampFromValueForForcedPhis()); loopBegin.setStateAfter(createFrameState(block.startBci, loopBegin)); /* @@ -3545,8 +3545,9 @@ * will never see that the branch is taken. This can lead to deopt loops or OSR * failure. */ + double calculatedProbability = negated ? BranchProbabilityNode.DEOPT_PROBABILITY : 1.0 - BranchProbabilityNode.DEOPT_PROBABILITY; FixedNode deoptSuccessor = BeginNode.begin(deopt); - ValueNode ifNode = genIfNode(condition, negated ? deoptSuccessor : noDeoptSuccessor, negated ? noDeoptSuccessor : deoptSuccessor, negated ? 1 - probability : probability); + ValueNode ifNode = genIfNode(condition, negated ? deoptSuccessor : noDeoptSuccessor, negated ? noDeoptSuccessor : deoptSuccessor, calculatedProbability); postProcessIfNode(ifNode); append(ifNode); } @@ -3569,8 +3570,28 @@ } this.controlFlowSplit = true; - FixedNode trueSuccessor = createTarget(trueBlock, frameState, false, false); - FixedNode falseSuccessor = createTarget(falseBlock, frameState, false, true); + FixedNode falseSuccessor = createTarget(falseBlock, frameState, false, false); + FixedNode trueSuccessor = createTarget(trueBlock, frameState, false, true); + + if (this.graphBuilderConfig.replaceLocalsWithConstants() && condition instanceof CompareNode) { + CompareNode compareNode = (CompareNode) condition; + if (compareNode.condition() == CanonicalCondition.EQ) { + ValueNode constantNode = null; + ValueNode nonConstantNode = null; + if (compareNode.getX() instanceof ConstantNode) { + constantNode = compareNode.getX(); + nonConstantNode = compareNode.getY(); + } else if (compareNode.getY() instanceof ConstantNode) { + constantNode = compareNode.getY(); + nonConstantNode = compareNode.getX(); + } + + if (constantNode != null && nonConstantNode != null) { + this.getEntryState(trueBlock).replaceValue(nonConstantNode, constantNode); + } + } + } + ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability); postProcessIfNode(ifNode); append(ifNode); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java Thu Oct 31 16:54:16 2019 -0700 @@ -328,8 +328,7 @@ outerFrameState = parent.getFrameStateBuilder().create(parent.bci(), parent.getNonIntrinsicAncestor(), true, null, null); } if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && parent != null) { - FrameState newFrameState = outerFrameState.duplicateModified(outerFrameState.bci, true, false, JavaKind.Void, new JavaKind[]{JavaKind.Object}, new ValueNode[]{stack[0]}); - return newFrameState; + return outerFrameState.duplicateModified(graph, outerFrameState.bci, true, false, JavaKind.Void, new JavaKind[]{JavaKind.Object}, new ValueNode[]{stack[0]}); } if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) { throw shouldNotReachHere(); @@ -527,21 +526,21 @@ ValueNode value = locals[i]; if (value != null && value != TWO_SLOT_MARKER && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { debug.log(" inserting proxy for %s", value); - locals[i] = ProxyNode.forValue(value, loopExit, graph); + locals[i] = ProxyNode.forValue(value, loopExit); } } for (int i = 0; i < stackSize(); i++) { ValueNode value = stack[i]; if (value != null && value != TWO_SLOT_MARKER && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { debug.log(" inserting proxy for %s", value); - stack[i] = ProxyNode.forValue(value, loopExit, graph); + stack[i] = ProxyNode.forValue(value, loopExit); } } for (int i = 0; i < lockedObjects.length; i++) { ValueNode value = lockedObjects[i]; if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { debug.log(" inserting proxy for %s", value); - lockedObjects[i] = ProxyNode.forValue(value, loopExit, graph); + lockedObjects[i] = ProxyNode.forValue(value, loopExit); } } } @@ -1028,4 +1027,17 @@ } sideEffects.add(sideEffect); } + + public void replaceValue(ValueNode oldValue, ValueNode newValue) { + for (int i = 0; i < locals.length; ++i) { + if (locals[i] == oldValue) { + locals[i] = newValue; + } + } + for (int i = 0; i < stack.length; ++i) { + if (stack[i] == oldValue) { + stack[i] = newValue; + } + } + } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -38,7 +38,7 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.jtt.JTTTest; -import org.graalvm.compiler.test.ExportingClassLoader; +import org.graalvm.compiler.api.test.ExportingClassLoader; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, 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 @@ -25,7 +25,7 @@ package org.graalvm.compiler.jtt.except; import org.graalvm.compiler.jtt.JTTTest; -import org.graalvm.compiler.test.ExportingClassLoader; +import org.graalvm.compiler.api.test.ExportingClassLoader; import org.junit.BeforeClass; import org.junit.Test; import org.objectweb.asm.ClassWriter; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java Thu Oct 31 16:54:16 2019 -0700 @@ -44,7 +44,7 @@ protected Suites createSuites(OptionValues options) { Suites suites = super.createSuites(options); ListIterator> position = suites.getHighTier().findPhase(PartialEscapePhase.class); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(); // incremental canonicalizer of PEA is missing some important canonicalization (TODO?) position.add(canonicalizer); position.add(new PartialEscapePhase(true, canonicalizer, options)); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/TrichotomyTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/TrichotomyTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/TrichotomyTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -2527,7 +2527,7 @@ // test folding StructuredGraph graph = self.parseForCompile(self.getResolvedJavaMethod(name)); HighTierContext context = self.getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = self.createCanonicalizerPhase(); canonicalizer.apply(graph, context); Assert.assertTrue("Too many ConditionalNodes after canonicalization", graph.getNodes().filter(ConditionalNode.class).count() <= 1); Assert.assertTrue("Unexpected IfNodes after canonicalization", graph.getNodes().filter(IfNode.class).isEmpty()); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java Thu Oct 31 16:54:16 2019 -0700 @@ -58,6 +58,13 @@ DIV, SMULH, UMULH, + SMULL, + SMNEGL, + MADD, + MSUB, + FMADD, + SMADDL, + SMSUBL, REM, UDIV, UREM, @@ -279,6 +286,12 @@ case MNEG: masm.mneg(size, dst, src1, src2); break; + case SMULL: + masm.smull(size, dst, src1, src2); + break; + case SMNEGL: + masm.smnegl(size, dst, src1, src2); + break; case DIV: masm.sdiv(size, dst, src1, src2); break; @@ -477,11 +490,10 @@ @Use(REG) protected AllocatableValue src3; /** - * Computes result = src3 src1 * src2. + * Computes result = src3 +/- src1 * src2. */ public MultiplyAddSubOp(AArch64ArithmeticOp op, AllocatableValue result, AllocatableValue src1, AllocatableValue src2, AllocatableValue src3) { super(TYPE); - assert op == ADD || op == SUB || op == FADD; this.op = op; this.result = result; this.src1 = src1; @@ -493,15 +505,23 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { int size = result.getPlatformKind().getSizeInBytes() * Byte.SIZE; switch (op) { - case ADD: + case MADD: masm.madd(size, asRegister(result), asRegister(src1), asRegister(src2), asRegister(src3)); break; - case SUB: + case MSUB: masm.msub(size, asRegister(result), asRegister(src1), asRegister(src2), asRegister(src3)); break; - case FADD: + case FMADD: masm.fmadd(size, asRegister(result), asRegister(src1), asRegister(src2), asRegister(src3)); break; + case SMADDL: + assert size == 64; + masm.smaddl(size, asRegister(result), asRegister(src1), asRegister(src2), asRegister(src3)); + break; + case SMSUBL: + assert size == 64; + masm.smsubl(size, asRegister(result), asRegister(src1), asRegister(src2), asRegister(src3)); + break; default: throw GraalError.shouldNotReachHere(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java Thu Oct 31 16:54:16 2019 -0700 @@ -96,7 +96,7 @@ public static final class MoveToRegOp extends AbstractMoveOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MoveToRegOp.class); - @Def({REG, HINT}) protected AllocatableValue result; + @Def({REG, STACK, HINT}) protected AllocatableValue result; @Use({REG, STACK}) protected AllocatableValue input; public MoveToRegOp(AMD64Kind moveKind, AllocatableValue result, AllocatableValue input) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringLatin1InflateOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringLatin1InflateOp.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringLatin1InflateOp.java Thu Oct 31 16:54:16 2019 -0700 @@ -32,6 +32,8 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; +import java.util.EnumSet; + import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler; @@ -43,8 +45,10 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.amd64.AMD64.CPUFeature; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.Value; @Opcode("AMD64_STRING_INFLATE") @@ -73,7 +77,7 @@ rdstTemp = rdst = dst; rlenTemp = rlen = len; - vtmp1 = tool.newVariable(LIRKind.value(AMD64Kind.V512_BYTE)); + vtmp1 = useAVX512ForStringInflateCompress(tool.target()) ? tool.newVariable(LIRKind.value(AMD64Kind.V512_BYTE)) : tool.newVariable(LIRKind.value(AMD64Kind.V128_BYTE)); rtmp2 = tool.newVariable(LIRKind.value(AMD64Kind.DWORD)); } @@ -89,6 +93,13 @@ byteArrayInflate(masm, src, dst, len, tmp1, tmp2); } + public static boolean useAVX512ForStringInflateCompress(TargetDescription target) { + EnumSet features = ((AMD64) target.arch).getFeatures(); + return features.contains(AMD64.CPUFeature.AVX512BW) && + features.contains(AMD64.CPUFeature.AVX512VL) && + features.contains(AMD64.CPUFeature.BMI2); + } + /** * Inflate a Latin1 string using a byte[] array representation into a UTF16 string using a * char[] array representation. @@ -110,10 +121,7 @@ assert dst.number != len.number && dst.number != tmp.number; assert len.number != tmp.number; - if (masm.supports(AMD64.CPUFeature.AVX512BW) && - masm.supports(AMD64.CPUFeature.AVX512VL) && - masm.supports(AMD64.CPUFeature.BMI2)) { - + if (useAVX512ForStringInflateCompress(masm.target)) { // If the length of the string is less than 16, we chose not to use the // AVX512 instructions. masm.testl(len, -16); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringUTF16CompressOp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringUTF16CompressOp.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringUTF16CompressOp.java Thu Oct 31 16:54:16 2019 -0700 @@ -34,6 +34,7 @@ import static jdk.vm.ci.amd64.AMD64.rsp; import static jdk.vm.ci.code.ValueUtil.asRegister; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; +import static org.graalvm.compiler.lir.amd64.AMD64StringLatin1InflateOp.useAVX512ForStringInflateCompress; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; @@ -82,7 +83,7 @@ rdstTemp = rdst = dst; rlenTemp = rlen = len; - LIRKind vkind = LIRKind.value(AMD64Kind.V512_BYTE); + LIRKind vkind = useAVX512ForStringInflateCompress(tool.target()) ? LIRKind.value(AMD64Kind.V512_BYTE) : LIRKind.value(AMD64Kind.V128_BYTE); vtmp1 = tool.newVariable(vkind); vtmp2 = tool.newVariable(vkind); @@ -139,10 +140,7 @@ masm.push(len); // Save length for return. - if (masm.supports(AMD64.CPUFeature.AVX512BW) && - masm.supports(AMD64.CPUFeature.AVX512VL) && - masm.supports(AMD64.CPUFeature.BMI2)) { - + if (useAVX512ForStringInflateCompress(masm.target)) { Label labelRestoreK1ReturnZero = new Label(); Label labelAvxPostAlignment = new Label(); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorMove.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorMove.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorMove.java Thu Oct 31 16:54:16 2019 -0700 @@ -74,7 +74,7 @@ public static final class MoveToRegOp extends AMD64LIRInstruction implements ValueMoveOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MoveToRegOp.class); - @Def({REG, HINT}) protected AllocatableValue result; + @Def({REG, STACK, HINT}) protected AllocatableValue result; @Use({REG, STACK}) protected AllocatableValue input; public MoveToRegOp(AllocatableValue result, AllocatableValue input) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -214,6 +214,23 @@ } } + private static boolean verifyAssignment(LIRInstruction inst, Value newValue, EnumSet flags) { + Class type = newValue.getClass(); + if (!flags.contains(REG)) { + assert !type.isAssignableFrom(REGISTER_VALUE_CLASS) && !type.isAssignableFrom(VARIABLE_CLASS) : "Cannot assign RegisterValue / Variable to field without REG flag: " + inst + " newValue=" + + newValue; + } + if (!flags.contains(STACK)) { + assert !type.isAssignableFrom(STACK_SLOT_CLASS) : "Cannot assign StackSlot to field without STACK flag: " + inst + " newValue=" + + newValue; + } + if (!flags.contains(CONST)) { + assert !type.isAssignableFrom(CONSTANT_VALUE_CLASS) : "Cannot assign Constant to field without CONST flag: " + inst + " newValue=" + + newValue; + } + return true; + } + protected static void forEach(LIRInstruction inst, Values values, OperandMode mode, InstructionValueProcedure proc) { for (int i = 0; i < values.getCount(); i++) { assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(values.getFlags(i)); @@ -228,6 +245,9 @@ newValue = proc.doValue(inst, value, mode, values.getFlags(i)); } if (!value.identityEquals(newValue)) { + if (!(value instanceof CompositeValue)) { + assert verifyAssignment(inst, newValue, values.getFlags(i)); + } values.setValue(inst, i, newValue); } } else { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java Thu Oct 31 16:54:16 2019 -0700 @@ -881,7 +881,12 @@ } } } - return move.getConstant(); + Constant constant = move.getConstant(); + if (!(constant instanceof JavaConstant)) { + // Other kinds of constants might not be supported by the generic move operation. + return null; + } + return constant; } return null; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java Thu Oct 31 16:54:16 2019 -0700 @@ -217,7 +217,7 @@ Node newGuard = guard; if (survivingSuccessor instanceof LoopExitNode) { - newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor, graph); + newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor); } survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPeelingPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPeelingPhase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPeelingPhase.java Thu Oct 31 16:54:16 2019 -0700 @@ -24,6 +24,7 @@ package org.graalvm.compiler.loop.phases; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.loop.LoopEx; import org.graalvm.compiler.loop.LoopPolicies; @@ -33,6 +34,8 @@ public class LoopPeelingPhase extends LoopPhase { + public static final CounterKey PEELED = DebugContext.counter("Peeled"); + public LoopPeelingPhase(LoopPolicies policies) { super(policies); } @@ -45,10 +48,13 @@ LoopsData data = new LoopsData(graph); try (DebugContext.Scope s = debug.scope("peeling", data.getCFG())) { for (LoopEx loop : data.outerFirst()) { - if (getPolicies().shouldPeel(loop, data.getCFG(), context.getMetaAccess())) { - debug.log("Peeling %s", loop); - LoopTransformations.peel(loop); - debug.dump(DebugContext.DETAILED_LEVEL, graph, "Peeling %s", loop); + if (loop.canDuplicateLoop() && loop.loopBegin().getLoopEndCount() > 0) { + if (LoopPolicies.Options.PeelALot.getValue(graph.getOptions()) || getPolicies().shouldPeel(loop, data.getCFG(), context.getMetaAccess())) { + debug.log("Peeling %s", loop); + PEELED.add(debug, 1); + LoopTransformations.peel(loop); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "Peeling %s", loop); + } } } data.deleteUnusedNodes(); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -35,9 +35,13 @@ import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Graph.Mark; +import org.graalvm.compiler.graph.Graph.NodeEventScope; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Position; +import org.graalvm.compiler.graph.spi.Simplifiable; +import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.loop.CountedLoopInfo; +import org.graalvm.compiler.loop.DefaultLoopPolicies; import org.graalvm.compiler.loop.InductionVariable.Direction; import org.graalvm.compiler.loop.LoopEx; import org.graalvm.compiler.loop.LoopFragmentInside; @@ -49,6 +53,7 @@ import org.graalvm.compiler.nodes.BeginNode; import org.graalvm.compiler.nodes.ControlSplitNode; import org.graalvm.compiler.nodes.EndNode; +import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.IfNode; @@ -65,8 +70,10 @@ import org.graalvm.compiler.nodes.extended.OpaqueNode; import org.graalvm.compiler.nodes.extended.SwitchNode; import org.graalvm.compiler.nodes.spi.CoreProviders; +import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.nodes.util.IntegerHelper; import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.util.EconomicSetNodeEventListener; public abstract class LoopTransformations { @@ -75,24 +82,63 @@ } public static void peel(LoopEx loop) { + loop.detectCounted(); loop.inside().duplicate().insertBefore(loop); - loop.loopBegin().setLoopFrequency(Math.max(0.0, loop.loopBegin().loopFrequency() - 1)); + if (loop.isCounted()) { + // For counted loops we assume that we have an effect on the loop frequency. + loop.loopBegin().setLoopFrequency(Math.max(1.0, loop.loopBegin().loopFrequency() - 1)); + } } + @SuppressWarnings("try") public static void fullUnroll(LoopEx loop, CoreProviders context, CanonicalizerPhase canonicalizer) { // assert loop.isCounted(); //TODO (gd) strengthen : counted with known trip count LoopBeginNode loopBegin = loop.loopBegin(); StructuredGraph graph = loopBegin.graph(); int initialNodeCount = graph.getNodeCount(); - while (!loopBegin.isDeleted()) { - Mark mark = graph.getMark(); - peel(loop); - canonicalizer.applyIncremental(graph, context, mark); - loop.invalidateFragments(); - if (graph.getNodeCount() > initialNodeCount + MaximumDesiredSize.getValue(graph.getOptions()) * 2) { - throw new RetryableBailoutException("FullUnroll : Graph seems to grow out of proportion"); + SimplifierTool defaultSimplifier = GraphUtil.getDefaultSimplifier(context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(), + canonicalizer.getCanonicalizeReads(), graph.getAssumptions(), graph.getOptions()); + /* + * IMPORTANT: Canonicalizations inside the body of the remaining loop can introduce new + * control flow that is not automatically picked up by the control flow graph computation of + * the original LoopEx data structure, thus we disable simplification and manually simplify + * conditions in the peeled iteration to simplify the exit path. + */ + CanonicalizerPhase c = canonicalizer.copyWithoutSimplification(); + EconomicSetNodeEventListener l = new EconomicSetNodeEventListener(); + int peelings = 0; + try (NodeEventScope ev = graph.trackNodeEvents(l)) { + while (!loopBegin.isDeleted()) { + Mark newNodes = graph.getMark(); + /* + * Mark is not enough for the canonicalization of the floating nodes in the unrolled + * code since pre-existing constants are not new nodes. Therefore, we canonicalize + * (without simplification) all floating nodes changed during peeling but only + * simplify new (in the peeled iteration) ones. + */ + EconomicSetNodeEventListener peeledListener = new EconomicSetNodeEventListener(); + try (NodeEventScope peeledScope = graph.trackNodeEvents(peeledListener)) { + LoopTransformations.peel(loop); + } + graph.getDebug().dump(DebugContext.VERY_DETAILED_LEVEL, graph, "After peeling loop %s", loop); + c.applyIncremental(graph, context, peeledListener.getNodes()); + loop.invalidateFragments(); + for (Node n : graph.getNewNodes(newNodes)) { + if (n.isAlive() && (n instanceof IfNode || n instanceof SwitchNode || n instanceof FixedGuardNode || n instanceof BeginNode)) { + Simplifiable s = (Simplifiable) n; + s.simplify(defaultSimplifier); + graph.getDebug().dump(DebugContext.VERY_DETAILED_LEVEL, graph, "After simplifying if %s", s); + } + } + if (graph.getNodeCount() > initialNodeCount + MaximumDesiredSize.getValue(graph.getOptions()) * 2 || + peelings > DefaultLoopPolicies.Options.FullUnrollMaxIterations.getValue(graph.getOptions())) { + throw new RetryableBailoutException("FullUnroll : Graph seems to grow out of proportion"); + } + peelings++; } } + // Canonicalize with the original canonicalizer to capture all simplifications + canonicalizer.applyIncremental(graph, context, l.getNodes()); } public static void unswitch(LoopEx loop, List controlSplitNodeSet) { @@ -280,9 +326,9 @@ // Change the preLoop to execute one iteration for now updatePreLoopLimit(preCounted); - preLoopBegin.setLoopFrequency(1); - mainLoopBegin.setLoopFrequency(Math.max(0.0, mainLoopBegin.loopFrequency() - 2)); - postLoopBegin.setLoopFrequency(Math.max(0.0, postLoopBegin.loopFrequency() - 1)); + preLoopBegin.setLoopFrequency(1.0); + mainLoopBegin.setLoopFrequency(Math.max(1.0, mainLoopBegin.loopFrequency() - 2)); + postLoopBegin.setLoopFrequency(Math.max(1.0, postLoopBegin.loopFrequency() - 1)); // The pre and post loops don't require safepoints at all for (SafepointNode safepoint : preLoop.nodes().filter(SafepointNode.class)) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -302,7 +302,7 @@ try (DebugContext.Scope buildScope = graph.getDebug().scope(name, method, graph)) { MidTierContext context = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, null); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = this.createCanonicalizerPhase(); canonicalizer.apply(graph, context); new RemoveValueProxyPhase().apply(graph); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); @@ -338,7 +338,7 @@ StructuredGraph referenceGraph = buildGraph(reference, false); StructuredGraph testGraph = buildGraph(test, true); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); canonicalizer.apply(testGraph, getDefaultMidTierContext()); canonicalizer.apply(referenceGraph, getDefaultMidTierContext()); assertEquals(referenceGraph, testGraph); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -122,18 +122,18 @@ } ValueNode range = sub(max, min); - ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1); + ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph); if (oneOff) { range = add(range, one); } // round-away-from-zero divison: (range + stride -/+ 1) / stride - ValueNode denominator = add(range, sub(absStride, one)); + ValueNode denominator = add(graph, range, sub(absStride, one), NodeView.DEFAULT); ValueNode div = unsignedDivBefore(graph, loop.entryPoint(), denominator, absStride, null); if (assumeLoopEntered) { return graph.addOrUniqueWithInputs(div); } - ConstantNode zero = ConstantNode.forIntegerStamp(stamp, 0); + ConstantNode zero = ConstantNode.forIntegerStamp(stamp, 0, graph); // This check is "wide": it looks like min <= max // That's OK even if the loop is strict (`!isLimitIncluded()`) // because in this case, `div` will be zero when min == max @@ -142,6 +142,40 @@ } /** + * Determine if the loop might be entered. Returns {@code false} if we can tell statically that + * the loop cannot be entered; returns {@code true} if the loop might possibly be entered, + * including in the case where we cannot be sure statically. + * + * @return false if the loop can definitely not be entered, true otherwise + */ + public boolean loopMightBeEntered() { + Stamp stamp = iv.valueNode().stamp(NodeView.DEFAULT); + + ValueNode max; + ValueNode min; + if (iv.direction() == Direction.Up) { + max = end; + min = iv.initNode(); + } else { + assert iv.direction() == Direction.Down; + max = iv.initNode(); + min = end; + } + if (oneOff) { + max = add(max, ConstantNode.forIntegerStamp(stamp, 1)); + } + + LogicNode entryCheck = getCounterIntegerHelper().createCompareNode(min, max, NodeView.DEFAULT); + if (entryCheck.isContradiction()) { + // We can definitely not enter this loop. + return false; + } else { + // We don't know for sure that the loop can't be entered, so assume it can. + return true; + } + } + + /** * @return true if the loop has constant bounds. */ public boolean isConstantMaxTripCount() { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DefaultLoopPolicies.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DefaultLoopPolicies.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DefaultLoopPolicies.java Thu Oct 31 16:54:16 2019 -0700 @@ -26,7 +26,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.LoopMaxUnswitch; import static org.graalvm.compiler.core.common.GraalOptions.MaximumDesiredSize; -import static org.graalvm.compiler.core.common.GraalOptions.MinimumPeelProbability; +import static org.graalvm.compiler.core.common.GraalOptions.MinimumPeelFrequency; import java.util.List; @@ -38,9 +38,6 @@ import org.graalvm.compiler.graph.NodeBitMap; import org.graalvm.compiler.nodes.AbstractBeginNode; 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.InvokeNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.MergeNode; @@ -51,7 +48,6 @@ import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode; -import org.graalvm.compiler.nodes.java.TypeSwitchNode; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; @@ -79,13 +75,32 @@ public boolean shouldPeel(LoopEx loop, ControlFlowGraph cfg, MetaAccessProvider metaAccess) { LoopBeginNode loopBegin = loop.loopBegin(); double entryProbability = cfg.blockFor(loopBegin.forwardEnd()).getRelativeFrequency(); - OptionValues options = cfg.graph.getOptions(); - if (entryProbability > MinimumPeelProbability.getValue(options) && loop.size() + loopBegin.graph().getNodeCount() < MaximumDesiredSize.getValue(options)) { - // check whether we're allowed to peel this loop - return loop.canDuplicateLoop(); - } else { + StructuredGraph graph = cfg.graph; + OptionValues options = graph.getOptions(); + + if (entryProbability < MinimumPeelFrequency.getValue(options)) { return false; } + + if (loop.parent() != null) { + if (loop.size() > loop.parent().size() >> 1) { + // This loops make up more than half of the parent loop in terms of number of nodes. + // There is a risk that this loop unproportionally increases parent loop body size. + return false; + } + } + + if (loop.loop().getChildren().size() > 0) { + // This loop has child loops. Loop peeling could explode graph size. + return false; + } + + if (loop.size() + graph.getNodeCount() > MaximumDesiredSize.getValue(options)) { + // We are out of budget for peeling. + return false; + } + + return true; } @Override @@ -189,7 +204,7 @@ return false; } OptionValues options = loop.entryPoint().getOptions(); - return loopBegin.unswitches() <= LoopMaxUnswitch.getValue(options); + return loopBegin.unswitches() < LoopMaxUnswitch.getValue(options); } private static final class CountingClosure implements VirtualClosure { @@ -238,19 +253,9 @@ int loopTotal = loop.size() - loop.loopBegin().phis().count() - stateNodesCount.count - 1; int actualDiff = (loopTotal - inBranchTotal); ControlSplitNode firstSplit = controlSplits.get(0); - if (firstSplit instanceof TypeSwitchNode) { - int copies = firstSplit.successors().count() - 1; - for (Node succ : firstSplit.successors()) { - FixedNode current = (FixedNode) succ; - while (current instanceof FixedWithNextNode) { - current = ((FixedWithNextNode) current).next(); - } - if (current instanceof DeoptimizeNode) { - copies--; - } - } - actualDiff = actualDiff * copies; - } + + int copies = firstSplit.successors().count() - 1; + actualDiff = actualDiff * copies; debug.log("shouldUnswitch(%s, %s) : delta=%d (%.2f%% inside of branches), max=%d, f=%.2f, phis=%d -> %b", loop, controlSplits, actualDiff, (double) (inBranchTotal) / loopTotal * 100, maxDiff, loopFrequency, phis, actualDiff <= maxDiff); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java Thu Oct 31 16:54:16 2019 -0700 @@ -81,6 +81,7 @@ private LoopsData data; private EconomicMap ivs; private boolean countedLoopChecked; + private int size = -1; LoopEx(Loop loop, LoopsData data) { this.loop = loop; @@ -156,7 +157,10 @@ } public int size() { - return whole().nodes().count(); + if (size == -1) { + size = whole().nodes().count(); + } + return size; } @Override diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java Thu Oct 31 16:54:16 2019 -0700 @@ -349,12 +349,11 @@ TriState isAnchorInLoop = isLoopNode(anchor, loopNodes, nonLoopNodes); if (isAnchorInLoop != TriState.FALSE) { if (!(anchor instanceof LoopExitNode && ((LoopExitNode) anchor).loopBegin() == loopBeginNode)) { - /* - * (gd) this is wrong in general, it's completely avoidable while we - * are doing loop transforms using ValueProxies. If it happens after - * it could still cause problem. - */ - assert !((GuardNode) current).graph().hasValueProxies(); + // It is undecidable whether the node is in the loop or not. This is + // not an issue for getting counted loop information, + // but causes issues when using the information for actual loop + // transformations. This is why a loop transformation must + // not happen while guards are floating. isLoopNode = true; } } else if (AbstractControlFlowGraph.strictlyDominates(cfg.blockFor(anchor), cfg.blockFor(loopBeginNode))) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java Thu Oct 31 16:54:16 2019 -0700 @@ -233,7 +233,7 @@ } } mainLoopBegin.setUnrollFactor(mainLoopBegin.getUnrollFactor() * 2); - mainLoopBegin.setLoopFrequency(mainLoopBegin.loopFrequency() / 2); + mainLoopBegin.setLoopFrequency(Math.max(1.0, mainLoopBegin.loopFrequency() / 2)); graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "LoopPartialUnroll %s", loop); mainLoopBegin.getDebug().dump(DebugContext.VERBOSE_LEVEL, mainLoopBegin.graph(), "After insertWithinAfter %s", mainLoopBegin); @@ -438,7 +438,7 @@ for (int i = 0; i < phi.valueCount(); i++) { ValueNode v = phi.valueAt(i); if (loopBegin.isPhiAtMerge(v)) { - PhiNode newV = peel.getDuplicatedNode((ValuePhiNode) v); + PhiNode newV = peel.getDuplicatedNode((PhiNode) v); if (newV != null) { phi.setValueAt(i, newV); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopPolicies.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopPolicies.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopPolicies.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -28,10 +28,18 @@ import org.graalvm.compiler.nodes.ControlSplitNode; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; import jdk.vm.ci.meta.MetaAccessProvider; public interface LoopPolicies { + + class Options { + @Option(help = "", type = OptionType.Expert) public static final OptionKey PeelALot = new OptionKey<>(false); + } + boolean shouldPeel(LoopEx loop, ControlFlowGraph cfg, MetaAccessProvider metaAccess); boolean shouldFullUnroll(LoopEx loop); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -94,7 +94,9 @@ if (before.predecessor() instanceof FixedBinaryNode) { FixedBinaryNode binaryPredecessor = (FixedBinaryNode) before.predecessor(); if (fixedDiv.dataFlowEquals(binaryPredecessor)) { - fixedDiv.safeDelete(); + if (fixedDiv.isAlive()) { + fixedDiv.safeDelete(); + } return binaryPredecessor; } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/GraalBenchmark.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/GraalBenchmark.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/GraalBenchmark.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -28,6 +28,8 @@ import static org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark.Defaults.MEASUREMENT_ITERATIONS; import static org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark.Defaults.WARMUP_ITERATIONS; +import org.graalvm.compiler.api.test.ModuleSupport; + import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Warmup; @@ -41,6 +43,9 @@ @Measurement(iterations = MEASUREMENT_ITERATIONS) @Fork(FORKS) public class GraalBenchmark { + static { + ModuleSupport.exportAndOpenAllPackagesToUnnamed("jdk.internal.vm.compiler"); + } public static class Defaults { public static final int MEASUREMENT_ITERATIONS = 5; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/TestJMHWhitebox.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/TestJMHWhitebox.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/TestJMHWhitebox.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -36,7 +36,7 @@ /** * This dummy class is used to verify that the JMH microbenchmarking environment is set up properly. */ -public class TestJMHWhitebox { +public class TestJMHWhitebox extends GraalBenchmark { @Benchmark public void testJMH(@SuppressWarnings("unused") GraalState s) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -67,19 +67,19 @@ for (byte d : testValues) { values[3] = d; value = 2; - super.test("testSnippet1", values, true); - super.test("testSnippet1", values, false); + super.test("testSnippet1", values); } } } } } - public int testSnippet1(byte[] values, boolean test) { + public int testSnippet1(byte[] values) { int v = values[0] - values[1]; - if (test) { - v = values[2] - values[3]; + if (v < 0) { + value = 2; } + v = values[3] - values[2]; if (v < 0) { value = 1; } @@ -156,13 +156,12 @@ StructuredGraph graph = parseEager(name, AllowAssumptions.YES); CoreProviders context = getProviders(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); new ConvertDeoptimizeToGuardPhase().apply(graph, context); graph.clearAllStateAfter(); graph.setGuardsStage(StructuredGraph.GuardsStage.AFTER_FSA); canonicalizer.apply(graph, context); - // new DominatorConditionalEliminationPhase(true).apply(graph, context); new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context); canonicalizer.apply(graph, context); canonicalizer.apply(graph, context); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/LoopPhiCanonicalizerTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/LoopPhiCanonicalizerTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/LoopPhiCanonicalizerTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -31,7 +31,6 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.spi.CoreProviders; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -67,7 +66,7 @@ CoreProviders context = getProviders(); Assert.assertEquals(5, graph.getNodes().filter(loopPhis).count()); - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); Assert.assertEquals(2, graph.getNodes().filter(loopPhis).count()); test("loopSnippet"); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ShortCircuitOrNodeTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ShortCircuitOrNodeTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ShortCircuitOrNodeTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -378,7 +378,7 @@ String snippet = "testCascadeSnippet" + i; StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); CoreProviders context = getProviders(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); canonicalizer.apply(graph, context); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase()).apply(graph, context); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java Thu Oct 31 16:54:16 2019 -0700 @@ -306,15 +306,8 @@ /** * Gets a copy of this frame state. */ - public FrameState duplicate(int newBci) { - return graph().add(new FrameState(outerFrameState(), code, newBci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings)); - } - - /** - * Gets a copy of this frame state. - */ public FrameState duplicate() { - return duplicate(bci); + return graph().add(new FrameState(outerFrameState(), code, bci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings)); } /** @@ -350,20 +343,6 @@ } /** - * Creates a copy of this frame state with one stack element of type {@code popKind} popped from - * the stack and the values in {@code pushedValues} pushed on the stack. The - * {@code pushedValues} will be formatted correctly in slot encoding: a long or double will be - * followed by a null slot. - */ - public FrameState duplicateModified(int newBci, boolean newRethrowException, JavaKind popKind, JavaKind[] pushedSlotKinds, ValueNode[] pushedValues) { - return duplicateModified(graph(), newBci, newRethrowException, duringCall, popKind, pushedSlotKinds, pushedValues); - } - - public FrameState duplicateModified(int newBci, boolean newRethrowException, boolean newDuringCall, JavaKind popKind, JavaKind[] pushedSlotKinds, ValueNode[] pushedValues) { - return duplicateModified(graph(), newBci, newRethrowException, newDuringCall, popKind, pushedSlotKinds, pushedValues); - } - - /** * Creates a copy of this frame state with the top of stack replaced with with * {@code pushedValue} which must be of type {@code popKind}. */ diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -1748,7 +1748,7 @@ "Value flowing out of loop, but we are not prepared to insert a ProxyNode"); ProxyPlaceholder proxyPlaceholder = (ProxyPlaceholder) value; - ValueProxyNode proxy = ProxyNode.forValue(proxyPlaceholder.value, loopExit, graph); + ValueProxyNode proxy = ProxyNode.forValue(proxyPlaceholder.value, loopExit); proxyPlaceholder.setValue(proxy); newValues.add(proxy); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardProxyNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardProxyNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardProxyNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -25,19 +25,13 @@ package org.graalvm.compiler.nodes; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.spi.Canonicalizable; -import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.extended.GuardingNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.nodes.spi.Proxy; -@NodeInfo(allowedUsageTypes = {InputType.Guard}, nameTemplate = "Proxy({i#value})") -public final class GuardProxyNode extends ProxyNode implements GuardingNode, Proxy, LIRLowerable, Canonicalizable { +@NodeInfo(allowedUsageTypes = {InputType.Guard}, nameTemplate = "GuardProxy({i#value})") +public final class GuardProxyNode extends ProxyNode implements GuardingNode { public static final NodeClass TYPE = NodeClass.create(GuardProxyNode.class); @OptionalInput(InputType.Guard) GuardingNode value; @@ -47,10 +41,6 @@ this.value = value; } - @Override - public void generate(NodeLIRBuilderTool generator) { - } - public void setValue(GuardingNode newValue) { this.updateUsages(value.asNode(), newValue.asNode()); this.value = newValue; @@ -65,17 +55,4 @@ public PhiNode createPhi(AbstractMergeNode merge) { return graph().addWithoutUnique(new GuardPhiNode(merge)); } - - @Override - public Node getOriginalNode() { - return (value == null ? null : value.asNode()); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - if (value == null) { - return null; - } - return this; - } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -54,7 +54,6 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.iterators.NodeIterable; -import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.Simplifiable; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.InputType; @@ -95,9 +94,6 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable, IterableNodeType, SwitchFoldable { public static final NodeClass TYPE = NodeClass.create(IfNode.class); - private static final int MAX_USAGE_COLOR_SET_SIZE = 64; - private static final int MAX_FRAMESTATE_SEARCH_DEPTH = 4; - private static final CounterKey CORRECTED_PROBABILITIES = DebugContext.counter("CorrectedProbabilities"); @Successor AbstractBeginNode trueSuccessor; @@ -297,10 +293,6 @@ return; } - if (splitIfAtPhi(tool)) { - return; - } - if (conditionalNodeOptimization(tool)) { return; } @@ -1185,400 +1177,6 @@ } /** - * Take an if that is immediately dominated by a merge with a single phi and split off any paths - * where the test would be statically decidable creating a new merge below the appropriate side - * of the IfNode. Any undecidable tests will continue to use the original IfNode. - * - * @param tool - */ - @SuppressWarnings("try") - private boolean splitIfAtPhi(SimplifierTool tool) { - if (!(predecessor() instanceof MergeNode)) { - return false; - } - MergeNode merge = (MergeNode) predecessor(); - if (merge.forwardEndCount() == 1) { - // Don't bother. - return false; - } - if (merge.getUsageCount() != 1 || merge.phis().count() != 1) { - // Don't trigger with multiple phis. Would require more rewiring. - // Most of the time the additional phis are memory phis that are removed after - // fixed read phase. - return false; - } - if (graph().getGuardsStage().areFrameStatesAtSideEffects() && merge.stateAfter() == null) { - return false; - } - - PhiNode generalPhi = merge.phis().first(); - if (!(generalPhi instanceof ValuePhiNode)) { - return false; - } - - if (trueSuccessor().isUsedAsGuardInput() || falseSuccessor().isUsedAsGuardInput()) { - return false; - } - - ValuePhiNode phi = (ValuePhiNode) generalPhi; - - EconomicMap coloredNodes = EconomicMap.create(Equivalence.IDENTITY, 8); - - /* - * Check that the condition uses the phi and that there is only one user of the condition - * expression. - */ - if (!conditionUses(condition(), phi, coloredNodes)) { - return false; - } - - if (!mayRemoveSplit(merge)) { - return false; - } - - LogicNode[] results = new LogicNode[merge.forwardEndCount()]; - boolean success = false; - for (int i = 0; i < results.length; ++i) { - ValueNode value = phi.valueAt(i); - LogicNode curResult = computeCondition(tool, condition, phi, value); - if (curResult != condition) { - for (Node n : curResult.inputs()) { - if (n instanceof ConstantNode || n instanceof ParameterNode || n instanceof FixedNode) { - // Constant inputs or parameters or fixed nodes are OK. - } else if (n == value) { - // References to the value itself are also OK. - } else { - // Input may cause scheduling issues. - curResult = condition; - break; - } - } - success = true; - } - results[i] = curResult; - } - - if (!success) { - return false; - } - - for (Node usage : phi.usages()) { - if (usage == merge.stateAfter()) { - // This usage can be ignored, because it is directly in the state after. - } else { - NodeColor color = colorUsage(coloredNodes, usage, merge, this.trueSuccessor(), this.falseSuccessor()); - if (color == NodeColor.MIXED) { - return false; - } - } - } - - /* - * We could additionally filter for the case that at least some of the Phi inputs or one of - * the condition inputs are constants but there are cases where a non-constant is - * simplifiable, usually where the stamp allows the question to be answered. - */ - - /* Each successor of the if gets a new merge if needed. */ - MergeNode trueMerge = null; - MergeNode falseMerge = null; - int i = 0; - for (EndNode end : merge.forwardEnds().snapshot()) { - ValueNode value = phi.valueAt(end); - LogicNode result = results[i++]; - if (result instanceof LogicConstantNode) { - if (((LogicConstantNode) result).getValue()) { - if (trueMerge == null) { - trueMerge = insertMerge(trueSuccessor(), phi, merge.stateAfter(), tool); - replaceNodesInBranch(coloredNodes, NodeColor.TRUE_BRANCH, phi, trueMerge.phis().first()); - } - trueMerge.phis().first().addInput(value); - trueMerge.addForwardEnd(end); - } else { - if (falseMerge == null) { - falseMerge = insertMerge(falseSuccessor(), phi, merge.stateAfter(), tool); - replaceNodesInBranch(coloredNodes, NodeColor.FALSE_BRANCH, phi, falseMerge.phis().first()); - } - falseMerge.phis().first().addInput(value); - falseMerge.addForwardEnd(end); - } - merge.removeEnd(end); - } else if (result != condition) { - // Build a new IfNode using the new condition - BeginNode trueBegin = graph().add(new BeginNode()); - trueBegin.setNodeSourcePosition(trueSuccessor().getNodeSourcePosition()); - BeginNode falseBegin = graph().add(new BeginNode()); - falseBegin.setNodeSourcePosition(falseSuccessor().getNodeSourcePosition()); - - if (result.graph() == null) { - result = graph().addOrUniqueWithInputs(result); - result.setNodeSourcePosition(condition.getNodeSourcePosition()); - } - IfNode newIfNode = graph().add(new IfNode(result, trueBegin, falseBegin, trueSuccessorProbability)); - newIfNode.setNodeSourcePosition(getNodeSourcePosition()); - - if (trueMerge == null) { - trueMerge = insertMerge(trueSuccessor(), phi, merge.stateAfter(), tool); - replaceNodesInBranch(coloredNodes, NodeColor.TRUE_BRANCH, phi, trueMerge.phis().first()); - } - trueMerge.phis().first().addInput(value); - trueBegin.setNext(graph().add(new EndNode())); - trueMerge.addForwardEnd((EndNode) trueBegin.next()); - - if (falseMerge == null) { - falseMerge = insertMerge(falseSuccessor(), phi, merge.stateAfter(), tool); - replaceNodesInBranch(coloredNodes, NodeColor.FALSE_BRANCH, phi, falseMerge.phis().first()); - } - falseMerge.phis().first().addInput(value); - falseBegin.setNext(graph().add(new EndNode())); - falseMerge.addForwardEnd((EndNode) falseBegin.next()); - - merge.removeEnd(end); - ((FixedWithNextNode) end.predecessor()).setNext(newIfNode); - end.safeDelete(); - } - } - - cleanupMerge(merge); - cleanupMerge(trueMerge); - cleanupMerge(falseMerge); - - return true; - } - - private static void replaceNodesInBranch(EconomicMap coloredNodes, NodeColor branch, ValuePhiNode phi, ValueNode newValue) { - for (Node n : phi.usages().snapshot()) { - if (coloredNodes.get(n) == branch) { - n.replaceAllInputs(phi, newValue); - } else if (coloredNodes.get(n) == NodeColor.PHI_MIXED) { - assert n instanceof PhiNode; - PhiNode phiNode = (PhiNode) n; - AbstractMergeNode merge = phiNode.merge(); - for (int i = 0; i < merge.forwardEndCount(); ++i) { - if (phiNode.valueAt(i) == phi && coloredNodes.get(merge.forwardEndAt(i)) == branch) { - phiNode.setValueAt(i, newValue); - } - } - } - } - } - - private NodeColor colorUsage(EconomicMap coloredNodes, Node node, MergeNode merge, AbstractBeginNode trueSucc, AbstractBeginNode falseSucc) { - NodeColor color = coloredNodes.get(node); - if (color == null) { - - if (coloredNodes.size() >= MAX_USAGE_COLOR_SET_SIZE) { - return NodeColor.MIXED; - } - - coloredNodes.put(node, NodeColor.MIXED); - - if (node == merge) { - color = NodeColor.MIXED; - } else if (node == trueSucc) { - color = NodeColor.TRUE_BRANCH; - } else if (node == falseSucc) { - color = NodeColor.FALSE_BRANCH; - } else { - if (node instanceof AbstractMergeNode) { - AbstractMergeNode mergeNode = (AbstractMergeNode) node; - NodeColor combinedColor = null; - for (int i = 0; i < mergeNode.forwardEndCount(); ++i) { - NodeColor curColor = colorUsage(coloredNodes, mergeNode.forwardEndAt(i), merge, trueSucc, falseSucc); - if (combinedColor == null) { - combinedColor = curColor; - } else if (combinedColor != curColor) { - combinedColor = NodeColor.MIXED; - break; - } - } - color = combinedColor; - } else if (node instanceof StartNode) { - color = NodeColor.MIXED; - } else if (node instanceof FixedNode) { - FixedNode fixedNode = (FixedNode) node; - Node predecessor = fixedNode.predecessor(); - assert predecessor != null : fixedNode; - color = colorUsage(coloredNodes, predecessor, merge, trueSucc, falseSucc); - } else if (node instanceof PhiNode) { - PhiNode phiNode = (PhiNode) node; - AbstractMergeNode phiMerge = phiNode.merge(); - - if (phiMerge instanceof LoopBeginNode) { - color = colorUsage(coloredNodes, phiMerge, merge, trueSucc, falseSucc); - } else { - - for (int i = 0; i < phiMerge.forwardEndCount(); ++i) { - NodeColor curColor = colorUsage(coloredNodes, phiMerge.forwardEndAt(i), merge, trueSucc, falseSucc); - if (curColor != NodeColor.TRUE_BRANCH && curColor != NodeColor.FALSE_BRANCH) { - color = NodeColor.MIXED; - break; - } - } - - if (color == null) { - // Each of the inputs to the phi are either coming unambigously from - // true or false branch. - color = NodeColor.PHI_MIXED; - assert node instanceof PhiNode; - } - } - } else { - NodeColor combinedColor = null; - for (Node n : node.usages()) { - if (n != node) { - NodeColor curColor = colorUsage(coloredNodes, n, merge, trueSucc, falseSucc); - if (combinedColor == null) { - combinedColor = curColor; - } else if (combinedColor != curColor) { - combinedColor = NodeColor.MIXED; - break; - } - } - } - if (combinedColor == NodeColor.PHI_MIXED) { - combinedColor = NodeColor.MIXED; - } - if (combinedColor == null) { - // Floating node without usages => association unclear. - combinedColor = NodeColor.MIXED; - } - color = combinedColor; - } - } - - assert color != null : node; - coloredNodes.put(node, color); - } - return color; - } - - /** - * @param condition - * @param phi - * @param coloredNodes - * @return true if the passed in {@code condition} uses {@code phi} and the condition is only - * used once. Since the phi will go dead the condition using it will also have to be - * dead after the optimization. - */ - private static boolean conditionUses(LogicNode condition, PhiNode phi, EconomicMap coloredNodes) { - if (!condition.hasExactlyOneUsage()) { - return false; - } - if (condition instanceof ShortCircuitOrNode) { - if (condition.graph().getGuardsStage().areDeoptsFixed()) { - /* - * It can be unsafe to simplify a ShortCircuitOr before deopts are fixed because - * conversion to guards assumes that all the required conditions are being tested. - * Simplfying the condition based on context before this happens may lose a - * condition. - */ - ShortCircuitOrNode orNode = (ShortCircuitOrNode) condition; - return (conditionUses(orNode.x, phi, coloredNodes) || conditionUses(orNode.y, phi, coloredNodes)); - } - } else if (condition instanceof Canonicalizable.Unary) { - Canonicalizable.Unary unary = (Canonicalizable.Unary) condition; - if (unary.getValue() == phi) { - coloredNodes.put(condition, NodeColor.CONDITION_USAGE); - return true; - } - } else if (condition instanceof Canonicalizable.Binary) { - Canonicalizable.Binary binary = (Canonicalizable.Binary) condition; - if (binary.getX() == phi || binary.getY() == phi) { - coloredNodes.put(condition, NodeColor.CONDITION_USAGE); - return true; - } - } - return false; - } - - /** - * Canonicalize {@code} condition using {@code value} in place of {@code phi}. - * - * @param tool - * @param condition - * @param phi - * @param value - * @return an improved LogicNode or the original condition - */ - @SuppressWarnings("unchecked") - private static LogicNode computeCondition(SimplifierTool tool, LogicNode condition, PhiNode phi, Node value) { - if (condition instanceof ShortCircuitOrNode) { - if (condition.graph().getGuardsStage().areDeoptsFixed() && !condition.graph().isAfterExpandLogic()) { - ShortCircuitOrNode orNode = (ShortCircuitOrNode) condition; - LogicNode resultX = computeCondition(tool, orNode.x, phi, value); - LogicNode resultY = computeCondition(tool, orNode.y, phi, value); - if (resultX != orNode.x || resultY != orNode.y) { - LogicNode result = orNode.canonical(tool, resultX, resultY); - if (result != orNode) { - return result; - } - /* - * Create a new node to carry the optimized inputs. - */ - ShortCircuitOrNode newOr = new ShortCircuitOrNode(resultX, orNode.xNegated, resultY, - orNode.yNegated, orNode.getShortCircuitProbability()); - return newOr.canonical(tool); - } - return orNode; - } - } else if (condition instanceof Canonicalizable.Binary) { - Canonicalizable.Binary compare = (Canonicalizable.Binary) condition; - if (compare.getX() == phi || compare.getY() == phi) { - return (LogicNode) compare.canonical(tool, compare.getX() == phi ? value : compare.getX(), compare.getY() == phi ? value : compare.getY()); - } - } else if (condition instanceof Canonicalizable.Unary) { - Canonicalizable.Unary compare = (Canonicalizable.Unary) condition; - if (compare.getValue() == phi) { - return (LogicNode) compare.canonical(tool, value); - } - } - if (condition instanceof Canonicalizable) { - return (LogicNode) ((Canonicalizable) condition).canonical(tool); - } - return condition; - } - - private void cleanupMerge(MergeNode merge) { - if (merge != null && merge.isAlive()) { - if (merge.forwardEndCount() == 0) { - GraphUtil.killCFG(merge); - } else if (merge.forwardEndCount() == 1) { - graph().reduceTrivialMerge(merge); - } - } - } - - @SuppressWarnings("try") - private MergeNode insertMerge(AbstractBeginNode begin, ValuePhiNode oldPhi, FrameState stateAfter, SimplifierTool tool) { - MergeNode merge = graph().add(new MergeNode()); - - AbstractBeginNode newBegin; - try (DebugCloseable position = begin.withNodeSourcePosition()) { - newBegin = graph().add(new BeginNode()); - begin.replaceAtPredecessor(newBegin); - newBegin.setNext(begin); - } - - FixedNode next = newBegin.next(); - next.replaceAtPredecessor(merge); - newBegin.setNext(graph().add(new EndNode())); - merge.addForwardEnd((EndNode) newBegin.next()); - - ValuePhiNode phi = begin.graph().addOrUnique(new ValuePhiNode(oldPhi.stamp(NodeView.DEFAULT), merge)); - phi.addInput(oldPhi); - - if (stateAfter != null) { - FrameState newState = stateAfter.duplicate(); - newState.replaceAllInputs(oldPhi, phi); - merge.setStateAfter(newState); - } - merge.setNext(next); - tool.addToWorkList(begin); - return merge; - } - - /** * Tries to connect code that initializes a variable directly with the successors of an if * construct that switches on the variable. For example, the pseudo code below: * @@ -1709,7 +1307,7 @@ return false; } - if (!mayRemoveSplit(merge)) { + if (merge.stateAfter() != null && !GraphUtil.mayRemoveSplit(this)) { return false; } @@ -1771,15 +1369,6 @@ return true; } - private boolean mayRemoveSplit(AbstractMergeNode merge) { - - if (merge.stateAfter() != null && (!checkFrameState(trueSuccessor, MAX_FRAMESTATE_SEARCH_DEPTH) || !checkFrameState(trueSuccessor, MAX_FRAMESTATE_SEARCH_DEPTH))) { - return false; - } - - return true; - } - private static void propagateZeroProbability(FixedNode startNode) { Node prev = null; for (FixedNode node : GraphUtil.predecessorIterable(startNode)) { @@ -1817,53 +1406,6 @@ } /** - * Snippet lowerings may produce patterns without a frame state on the merge. We need to take - * extra care when optimizing these patterns. - */ - private static boolean checkFrameState(FixedNode start, int maxDepth) { - if (maxDepth == 0) { - return false; - } - FixedNode node = start; - while (true) { - if (node instanceof AbstractMergeNode) { - AbstractMergeNode mergeNode = (AbstractMergeNode) node; - if (mergeNode.stateAfter() == null) { - return false; - } else { - return true; - } - } else if (node instanceof StateSplit) { - StateSplit stateSplitNode = (StateSplit) node; - if (stateSplitNode.stateAfter() != null) { - return true; - } - } - - if (node instanceof ControlSplitNode) { - ControlSplitNode controlSplitNode = (ControlSplitNode) node; - for (Node succ : controlSplitNode.cfgSuccessors()) { - if (checkFrameState((FixedNode) succ, maxDepth - 1)) { - return true; - } - } - return false; - } else if (node instanceof FixedWithNextNode) { - FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node; - node = fixedWithNextNode.next(); - } else if (node instanceof AbstractEndNode) { - AbstractEndNode endNode = (AbstractEndNode) node; - node = endNode.merge(); - } else if (node instanceof ControlSinkNode) { - return true; - } else { - assert false : "unexpected node"; - return false; - } - } - } - - /** * Connects a set of ends to a given successor, inserting a merge node if there is more than one * end. If {@code ends} is not empty, then {@code successor} is added to {@code tool}'s * {@linkplain SimplifierTool#addToWorkList(org.graalvm.compiler.graph.Node) work list}. diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -109,7 +109,7 @@ this.bci = invoke.bci; this.polymorphic = invoke.polymorphic; this.useForInlining = invoke.useForInlining; - this.identity = invoke.getLocationIdentity(); + this.identity = invoke.getKilledLocationIdentity(); } @Override @@ -181,7 +181,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return identity; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -159,7 +159,7 @@ @Override public void setNext(FixedNode x) { if (x != null) { - this.setNext(KillingBeginNode.begin(x, getLocationIdentity())); + this.setNext(KillingBeginNode.begin(x, this.getKilledLocationIdentity())); } else { this.setNext(null); } @@ -192,7 +192,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } @@ -290,7 +290,7 @@ * code. */ public InvokeNode replaceWithInvoke() { - InvokeNode newInvoke = graph().add(new InvokeNode(callTarget, bci, stamp, getLocationIdentity())); + InvokeNode newInvoke = graph().add(new InvokeNode(callTarget, bci, stamp, this.getKilledLocationIdentity())); newInvoke.setStateAfter(stateAfter); newInvoke.setStateDuring(stateDuring); AbstractBeginNode oldException = this.exceptionEdge; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/KillingBeginNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/KillingBeginNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/KillingBeginNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, 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 @@ -58,7 +58,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return locationIdentity; } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -141,7 +141,7 @@ } public void setLoopFrequency(double loopFrequency) { - assert loopFrequency >= 0; + assert loopFrequency >= 1.0; this.loopFrequency = loopFrequency; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/MemoryProxyNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/MemoryProxyNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019, 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.core.common.type.StampFactory; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.InputType; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.memory.MemoryNode; +import org.graalvm.compiler.nodes.memory.MemoryPhiNode; +import jdk.internal.vm.compiler.word.LocationIdentity; + +@NodeInfo(allowedUsageTypes = {InputType.Memory}, nameTemplate = "MemoryProxy({i#value})") +public final class MemoryProxyNode extends ProxyNode implements MemoryNode { + + public static final NodeClass TYPE = NodeClass.create(MemoryProxyNode.class); + @OptionalInput(InputType.Memory) MemoryNode value; + protected final LocationIdentity locationIdentity; + + public MemoryProxyNode(MemoryNode value, LoopExitNode proxyPoint, LocationIdentity locationIdentity) { + super(TYPE, StampFactory.forVoid(), proxyPoint); + this.value = value; + this.locationIdentity = locationIdentity; + } + + public void setValue(MemoryNode newValue) { + this.updateUsages(value.asNode(), newValue.asNode()); + this.value = newValue; + } + + @Override + public ValueNode value() { + return (value == null ? null : value.asNode()); + } + + @Override + public PhiNode createPhi(AbstractMergeNode merge) { + return graph().addWithoutUnique(new MemoryPhiNode(merge, locationIdentity)); + } +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ProxyNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ProxyNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ProxyNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -29,18 +29,24 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Node.ValueNumberable; +import org.graalvm.compiler.graph.spi.Canonicalizable; +import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.GuardingNode; +import org.graalvm.compiler.nodes.memory.MemoryNode; +import org.graalvm.compiler.nodes.spi.Proxy; +import jdk.internal.vm.compiler.word.LocationIdentity; /** * A proxy is inserted at loop exits for any value that is created inside the loop (i.e. was not * live on entry to the loop) and is (potentially) used after the loop. */ @NodeInfo(cycles = CYCLES_0, size = SIZE_0) -public abstract class ProxyNode extends FloatingNode implements ValueNumberable { +public abstract class ProxyNode extends FloatingNode implements Proxy, ValueNumberable, Canonicalizable { public static final NodeClass TYPE = NodeClass.create(ProxyNode.class); @Input(Association) LoopExitNode loopExit; @@ -63,17 +69,34 @@ } @Override + public ValueNode getOriginalNode() { + return value(); + } + + @Override public boolean verify() { assert !(value() instanceof ProxyNode) || ((ProxyNode) value()).loopExit != loopExit; return super.verify(); } - public static ValueProxyNode forValue(ValueNode value, LoopExitNode exit, StructuredGraph graph) { - return graph.unique(new ValueProxyNode(value, exit)); + public static ValueProxyNode forValue(ValueNode value, LoopExitNode exit) { + return exit.graph().unique(new ValueProxyNode(value, exit)); + } + + public static GuardProxyNode forGuard(GuardingNode value, LoopExitNode exit) { + return exit.graph().unique(new GuardProxyNode(value, exit)); } - public static GuardProxyNode forGuard(GuardingNode value, LoopExitNode exit, StructuredGraph graph) { - return graph.unique(new GuardProxyNode(value, exit)); + public static MemoryProxyNode forMemory(MemoryNode value, LoopExitNode exit, LocationIdentity locationIdentity) { + return exit.graph().unique(new MemoryProxyNode(value, exit, locationIdentity)); + } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (value() == null) { + return null; + } + return this; } public abstract PhiNode createPhi(AbstractMergeNode merge); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StartNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StartNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StartNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -49,7 +49,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Thu Oct 31 16:54:16 2019 -0700 @@ -125,6 +125,10 @@ public boolean areDeoptsFixed() { return this.ordinal() >= FIXED_DEOPTS.ordinal(); } + + public boolean requiresValueProxies() { + return this != AFTER_FSA; + } } /** diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueProxyNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueProxyNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueProxyNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -35,7 +35,7 @@ import org.graalvm.compiler.nodes.spi.VirtualizerTool; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; -@NodeInfo(nameTemplate = "Proxy({i#value})") +@NodeInfo(nameTemplate = "ValueProxy({i#value})") public final class ValueProxyNode extends ProxyNode implements Canonicalizable, Virtualizable, ValueProxy { public static final NodeClass TYPE = NodeClass.create(ValueProxyNode.class); @@ -65,8 +65,13 @@ @Override public Node canonical(CanonicalizerTool tool) { + Node result = super.canonical(tool); + if (result != this) { + return result; + } + ValueNode curValue = value; - if (curValue.isConstant()) { + if (curValue.getNodeClass().isLeafNode()) { return curValue; } if (loopPhiProxy && !loopExit.loopBegin().isPhiAtMerge(curValue)) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AndNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AndNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AndNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -28,7 +28,6 @@ import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.And; import org.graalvm.compiler.core.common.type.IntegerStamp; -import org.graalvm.compiler.core.common.type.PrimitiveStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative; @@ -41,7 +40,6 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.util.GraphUtil; -import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.PrimitiveConstant; @@ -61,7 +59,7 @@ if (tryConstantFold != null) { return tryConstantFold; } - return canonical(null, op, stamp, x, y, view); + return canonical(null, op, x, y, view); } @Override @@ -77,16 +75,29 @@ } NodeView view = NodeView.from(tool); - return canonical(this, getOp(forX, forY), stamp(view), forX, forY, view); + return canonical(this, getOp(forX, forY), forX, forY, view); } - private static ValueNode canonical(AndNode self, BinaryOp op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) { + private static ValueNode canonical(AndNode self, BinaryOp op, ValueNode forX, ValueNode forY, NodeView view) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { return forX; } if (forX.isConstant() && !forY.isConstant()) { return new AndNode(forY, forX); } + + Stamp rawXStamp = forX.stamp(view); + Stamp rawYStamp = forY.stamp(view); + if (rawXStamp instanceof IntegerStamp && rawYStamp instanceof IntegerStamp) { + IntegerStamp xStamp = (IntegerStamp) rawXStamp; + IntegerStamp yStamp = (IntegerStamp) rawYStamp; + if (((~xStamp.downMask()) & yStamp.upMask()) == 0) { + return forY; + } else if (((~yStamp.downMask()) & xStamp.upMask()) == 0) { + return forX; + } + } + if (forY.isConstant()) { Constant c = forY.asConstant(); if (op.isNeutral(c)) { @@ -95,21 +106,12 @@ if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) { long rawY = ((PrimitiveConstant) c).asLong(); - long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp)); - if ((rawY & mask) == 0) { - return ConstantNode.forIntegerStamp(stamp, 0); - } if (forX instanceof SignExtendNode) { SignExtendNode ext = (SignExtendNode) forX; if (rawY == ((1L << ext.getInputBits()) - 1)) { return new ZeroExtendNode(ext.getValue(), ext.getResultBits()); } } - IntegerStamp xStamp = (IntegerStamp) forX.stamp(view); - if (((xStamp.upMask() | xStamp.downMask()) & ~rawY) == 0) { - // No bits are set which are outside the mask, so the mask will have no effect. - return forX; - } } return reassociate(self != null ? self : (AndNode) new AndNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY, view); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -59,6 +59,10 @@ super(c, opForStampComputation.foldStamp(x.stamp(NodeView.DEFAULT), y.stamp(NodeView.DEFAULT)), x, y); } + protected BinaryArithmeticNode(NodeClass> c, Stamp stamp, ValueNode x, ValueNode y) { + super(c, stamp, x, y); + } + public static ArithmeticOpTable getArithmeticOpTable(ValueNode forValue) { return ArithmeticOpTable.forStamp(forValue.stamp(NodeView.DEFAULT)); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -33,8 +33,11 @@ import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.IntegerStamp; +import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.Position; import org.graalvm.compiler.graph.spi.Canonicalizable; +import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.BinaryOpLogicNode; import org.graalvm.compiler.nodes.ConstantNode; @@ -44,6 +47,7 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.memory.VolatileReadNode; import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.Constant; @@ -189,6 +193,19 @@ } else if (nonConstant instanceof ConvertNode) { ConvertNode convert = (ConvertNode) nonConstant; boolean multiUsage = (convert.asNode().hasMoreThanOneUsage() && convert.getValue().hasExactlyOneUsage()); + if (!multiUsage && convert.asNode().hasMoreThanOneUsage() && convert.getValue() instanceof VolatileReadNode) { + // Only account for data usages + VolatileReadNode read = (VolatileReadNode) convert.getValue(); + int nonMemoryEdges = 0; + for (Node u : read.usages()) { + for (Position pos : u.inputPositions()) { + if (pos.get(u) == read && pos.getInputType() != InputType.Memory) { + nonMemoryEdges++; + } + } + } + multiUsage = nonMemoryEdges == 1; + } if (convert instanceof IntegerConvertNode && multiUsage) { // Do not perform for integer convers if it could introduce // new live values. diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/OrNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/OrNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/OrNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -27,7 +27,7 @@ import org.graalvm.compiler.core.common.type.ArithmeticOpTable; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Or; -import org.graalvm.compiler.core.common.type.PrimitiveStamp; +import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative; @@ -40,9 +40,7 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.util.GraphUtil; -import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.PrimitiveConstant; @NodeInfo(shortName = "|") public final class OrNode extends BinaryArithmeticNode implements BinaryCommutative, NarrowableArithmeticNode { @@ -53,6 +51,18 @@ super(TYPE, getArithmeticOpTable(x).getOr(), x, y); } + private OrNode(ValueNode x, ValueNode y, Stamp forcedStamp) { + super(TYPE, forcedStamp, x, y); + } + + /** + * Create a new XorNode with a forced stamp, without eager folding. This should only be used in + * snippet code, where native-image may assign wrong stamps during graph generation. + */ + public static ValueNode createForSnippet(ValueNode x, ValueNode y, Stamp forcedStamp) { + return new OrNode(x, y, forcedStamp); + } + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { BinaryOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getOr(); Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); @@ -60,7 +70,7 @@ if (tryConstantFold != null) { return tryConstantFold; } - return canonical(null, op, stamp, x, y, view); + return canonical(null, op, x, y, view); } @Override @@ -76,34 +86,42 @@ return ret; } - return canonical(this, getOp(forX, forY), stamp(view), forX, forY, view); + return canonical(this, getOp(forX, forY), forX, forY, view); } - private static ValueNode canonical(OrNode self, BinaryOp op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) { + private static ValueNode canonical(OrNode self, BinaryOp op, ValueNode forX, ValueNode forY, NodeView view) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { return forX; } if (forX.isConstant() && !forY.isConstant()) { return new OrNode(forY, forX); } + + Stamp rawXStamp = forX.stamp(view); + Stamp rawYStamp = forY.stamp(view); + if (rawXStamp instanceof IntegerStamp && rawYStamp instanceof IntegerStamp) { + IntegerStamp xStamp = (IntegerStamp) rawXStamp; + IntegerStamp yStamp = (IntegerStamp) rawYStamp; + if (((~xStamp.downMask()) & yStamp.upMask()) == 0) { + return forX; + } else if (((~yStamp.downMask()) & xStamp.upMask()) == 0) { + return forY; + } + } + if (forY.isConstant()) { Constant c = forY.asConstant(); if (op.isNeutral(c)) { return forX; } - if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) { - long rawY = ((PrimitiveConstant) c).asLong(); - long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp)); - if ((rawY & mask) == mask) { - return ConstantNode.forIntegerStamp(stamp, mask); - } - } return reassociate(self != null ? self : (OrNode) new OrNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY, view); } + if (forX instanceof NotNode && forY instanceof NotNode) { return new NotNode(AndNode.create(((NotNode) forX).getValue(), ((NotNode) forY).getValue(), view)); } + return self != null ? self : new OrNode(forX, forY).maybeCommuteInputs(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/XorNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/XorNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/XorNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -54,6 +54,18 @@ assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT)); } + private XorNode(ValueNode x, ValueNode y, Stamp forcedStamp) { + super(TYPE, forcedStamp, x, y); + } + + /** + * Create a new XorNode with a forced stamp, without eager folding. This should only be used in + * snippet code, where native-image may assign wrong stamps during graph generation. + */ + public static ValueNode createForSnippet(ValueNode x, ValueNode y, Stamp forcedStamp) { + return new XorNode(x, y, forcedStamp); + } + public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { BinaryOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getXor(); Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java Thu Oct 31 16:54:16 2019 -0700 @@ -260,10 +260,10 @@ LocationSet result = new LocationSet(); for (FixedNode node : this.getNodes()) { if (node instanceof MemoryCheckpoint.Single) { - LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity(); + LocationIdentity identity = ((MemoryCheckpoint.Single) node).getKilledLocationIdentity(); result.add(identity); } else if (node instanceof MemoryCheckpoint.Multi) { - for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) { + for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getKilledLocationIdentities()) { result.add(identity); } } @@ -365,4 +365,26 @@ protected void setPostDominator(Block postdominator) { this.postdominator = postdominator; } + + /** + * Checks whether {@code this} block is in the same loop or an outer loop of the block given as + * parameter. + */ + public boolean isInSameOrOuterLoopOf(Block block) { + + if (this.loop == null) { + // We are in no loop, so this holds true for every other block. + return true; + } + + Loop l = block.loop; + while (l != null) { + if (l == this.loop) { + return true; + } + l = l.getParent(); + } + + return false; + } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java Thu Oct 31 16:54:16 2019 -0700 @@ -38,6 +38,7 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; +import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractEndNode; import org.graalvm.compiler.nodes.ControlSinkNode; @@ -416,6 +417,15 @@ return nodeToBlock.get(node); } + public Block commonDominatorFor(NodeIterable nodes) { + Block commonDom = null; + for (Node n : nodes) { + Block b = blockFor(n); + commonDom = (Block) AbstractControlFlowGraph.commonDominator(commonDom, b); + } + return commonDom; + } + @Override public List> getLoops() { return loops; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/StringToBytesNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/StringToBytesNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/StringToBytesNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -66,7 +66,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return NamedLocationIdentity.getArrayLocation(JavaKind.Byte); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -100,7 +100,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -159,7 +159,7 @@ } @Override - public LocationIdentity[] getLocationIdentities() { + public LocationIdentity[] getKilledLocationIdentities() { return foreignCalls.getKilledLocations(descriptor); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -79,4 +79,9 @@ public Stamp getAccessStamp() { return StampFactory.forKind(writeKind); } + + @Override + public LocationIdentity getKilledLocationIdentity() { + return getLocationIdentity(); + } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/MembarNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/MembarNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/MembarNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -58,7 +58,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return location; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -161,7 +161,7 @@ @Override protected ValueNode cloneAsFieldAccess(Assumptions assumptions, ResolvedJavaField field, boolean volatileAccess) { - return LoadFieldNode.create(assumptions, object(), field, volatileAccess); + return LoadFieldNode.create(assumptions, field.isStatic() ? null : object(), field, volatileAccess); } @Override diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -134,7 +134,7 @@ @Override protected ValueNode cloneAsFieldAccess(Assumptions assumptions, ResolvedJavaField field, boolean volatileAccess) { - return new StoreFieldNode(object(), field, value(), stateAfter(), volatileAccess); + return new StoreFieldNode(field.isStatic() ? null : object(), field, value(), stateAfter(), volatileAccess); } @Override @@ -145,4 +145,9 @@ public FrameState getState() { return stateAfter; } + + @Override + public LocationIdentity getKilledLocationIdentity() { + return getLocationIdentity(); + } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -290,4 +290,7 @@ } } + public int[] getKeySuccessors() { + return keySuccessors.clone(); + } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeAccessNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeAccessNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeAccessNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -27,6 +27,8 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import java.nio.ByteOrder; + import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -40,6 +42,8 @@ import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaType; @@ -95,10 +99,14 @@ // Try to canonicalize to a field access. ResolvedJavaType receiverType = StampTool.typeOrNull(object()); if (receiverType != null) { - ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(constantOffset, accessKind()); - // No need for checking that the receiver is non-null. The field access includes - // the null check and if a field is found, the offset is so small that this is - // never a valid access of an arbitrary address. + ResolvedJavaField field = getStaticFieldUnsafeAccess(tool.getConstantReflection()); + if (field == null) { + field = receiverType.findInstanceFieldWithOffset(constantOffset, accessKind()); + } + + // No need for checking that the receiver is non-null. The field access + // includes the null check and if a field is found, the offset is so small that + // this is never a valid access of an arbitrary address. if (field != null && field.getJavaKind() == this.accessKind()) { assert !graph().isAfterFloatingReadPhase() : "cannot add more precise memory location after floating read phase"; // Unsafe accesses never have volatile semantics. @@ -128,4 +136,58 @@ protected abstract ValueNode cloneAsFieldAccess(Assumptions assumptions, ResolvedJavaField field, boolean volatileAccess); protected abstract ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity); + + /** + * In this method we check if the unsafe access is to a static field. This is the case when + * {@code object} is a constant of type {@link Class} (static field's declaring class) and + * {@code offset} is a constant (HotSpot-specific field offset from the declaring class). + * + * @return the static field, if any, that this node is reading + */ + private ResolvedJavaField getStaticFieldUnsafeAccess(ConstantReflectionProvider constantReflection) { + if (!object().isJavaConstant() || !offset().isJavaConstant() || + object().isNullConstant() || offset().isNullConstant()) { + return null; + } + JavaConstant objectConstant = object().asJavaConstant(); + JavaConstant offsetConstant = offset().asJavaConstant(); + assert objectConstant != null && offsetConstant != null : "Verified by the check at the beginning."; + ResolvedJavaType staticReceiverType = constantReflection.asJavaType(objectConstant); + if (staticReceiverType == null) { + // object is not of type Class so it is not a static field + return null; + } + return findStaticFieldWithOffset(staticReceiverType, offsetConstant.asLong(), accessKind); + } + + private static ResolvedJavaField findStaticFieldWithOffset(ResolvedJavaType type, long offset, JavaKind expectedEntryKind) { + try { + ResolvedJavaField[] declaredFields = type.getStaticFields(); + return findFieldWithOffset(offset, expectedEntryKind, declaredFields); + } catch (UnsupportedOperationException e) { + return null; + } + } + + /** + * NOTE GR-18873: this is a copy-paste implementation derived from + * {@code jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl#findStaticFieldWithOffset}. + */ + private static ResolvedJavaField findFieldWithOffset(long offset, JavaKind expectedEntryKind, ResolvedJavaField[] declaredFields) { + for (ResolvedJavaField field : declaredFields) { + long resolvedFieldOffset = field.getOffset(); + if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN && + expectedEntryKind.isPrimitive() && + !expectedEntryKind.equals(JavaKind.Void) && + field.getJavaKind().isPrimitive()) { + resolvedFieldOffset += field.getJavaKind().getByteCount() - + Math.min(field.getJavaKind().getByteCount(), 4 + expectedEntryKind.getByteCount()); + } + if (resolvedFieldOffset == offset) { + return field; + } + } + return null; + } + } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeMemoryStoreNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeMemoryStoreNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeMemoryStoreNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, 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 @@ -77,7 +77,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return locationIdentity; } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderConfiguration.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderConfiguration.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderConfiguration.java Thu Oct 31 16:54:16 2019 -0700 @@ -203,6 +203,7 @@ private final boolean trackNodeSourcePosition; private final boolean retainLocalVariables; private final Plugins plugins; + private final boolean replaceLocalsWithConstants; public enum BytecodeExceptionMode { /** @@ -231,6 +232,7 @@ boolean insertFullInfopoints, boolean trackNodeSourcePosition, boolean retainLocalVariables, + boolean replaceLocalsWithConstants, List skippedExceptionTypes, Plugins plugins) { this.eagerResolving = eagerResolving; @@ -240,6 +242,7 @@ this.insertFullInfopoints = insertFullInfopoints; this.trackNodeSourcePosition = trackNodeSourcePosition; this.retainLocalVariables = retainLocalVariables; + this.replaceLocalsWithConstants = replaceLocalsWithConstants; this.skippedExceptionTypes = skippedExceptionTypes; this.plugins = plugins; } @@ -259,6 +262,7 @@ insertFullInfopoints, trackNodeSourcePosition, retainLocalVariables, + replaceLocalsWithConstants, skippedExceptionTypes, newPlugins); return result; @@ -279,6 +283,7 @@ insertFullInfopoints, trackNodeSourcePosition, retainLocalVariables, + replaceLocalsWithConstants, skippedExceptionTypes, plugins); } @@ -292,6 +297,7 @@ insertFullInfopoints, trackNodeSourcePosition, retainLocalVariables, + replaceLocalsWithConstants, skippedExceptionTypes, plugins); } @@ -305,6 +311,7 @@ insertFullInfopoints, trackNodeSourcePosition, retainLocalVariables, + replaceLocalsWithConstants, Collections.unmodifiableList(Arrays.asList(newSkippedExceptionTypes)), plugins); } @@ -317,6 +324,7 @@ insertFullInfopoints, trackNodeSourcePosition, retainLocalVariables, + replaceLocalsWithConstants, skippedExceptionTypes, plugins); } @@ -330,6 +338,7 @@ insertFullInfopoints, trackNodeSourcePosition, retainLocalVariables, + replaceLocalsWithConstants, skippedExceptionTypes, plugins); } @@ -343,6 +352,7 @@ newInsertFullInfopoints, trackNodeSourcePosition, retainLocalVariables, + replaceLocalsWithConstants, skippedExceptionTypes, plugins); } @@ -356,6 +366,7 @@ insertFullInfopoints, newTrackNodeSourcePosition, retainLocalVariables, + replaceLocalsWithConstants, skippedExceptionTypes, plugins); } @@ -369,6 +380,21 @@ insertFullInfopoints, trackNodeSourcePosition, newRetainLocalVariables, + replaceLocalsWithConstants, + skippedExceptionTypes, + plugins); + } + + public GraphBuilderConfiguration withReplaceLocalsWithConstants(boolean newReplaceLocalsWithConstants) { + return new GraphBuilderConfiguration( + eagerResolving, + unresolvedIsError, + bytecodeExceptionMode, + omitAssertions, + insertFullInfopoints, + trackNodeSourcePosition, + retainLocalVariables, + newReplaceLocalsWithConstants, skippedExceptionTypes, plugins); } @@ -401,6 +427,10 @@ return insertFullInfopoints; } + public boolean replaceLocalsWithConstants() { + return this.replaceLocalsWithConstants; + } + public static GraphBuilderConfiguration getDefault(Plugins plugins) { return new GraphBuilderConfiguration( /* eagerResolving: */ false, @@ -410,6 +440,7 @@ /* insertFullInfopoints: */ false, /* trackNodeSourcePosition: */ false, /* retainLocalVariables */ false, + /* replaceLocalsWithConstants */ false, Collections.emptyList(), plugins); } @@ -423,6 +454,7 @@ /* insertFullInfopoints: */ false, /* trackNodeSourcePosition: */ false, /* retainLocalVariables */ false, + /* replaceLocalsWithConstants */ false, Collections.emptyList(), plugins); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java Thu Oct 31 16:54:16 2019 -0700 @@ -46,7 +46,6 @@ import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap; import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor; import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.api.replacements.MethodSubstitutionRegistry; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.debug.Assertions; @@ -55,6 +54,7 @@ import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; +import org.graalvm.compiler.nodes.spi.Replacements; import jdk.vm.ci.meta.MetaUtil; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -175,21 +175,25 @@ } /** - * Utility for {@linkplain InvocationPlugins#register(InvocationPlugin, Class, String, Class...) - * registration} of invocation plugins. + * Utility for {@linkplain InvocationPlugins#register registration} of invocation plugins. */ - public static class Registration implements MethodSubstitutionRegistry { + public static class Registration { private final InvocationPlugins plugins; + private final Type declaringType; - private final BytecodeProvider methodSubstitutionBytecodeProvider; + private final Replacements replacements; + private final BytecodeProvider bytecodeProvider; private boolean allowOverwrite; - @Override public Class getReceiverType() { return Receiver.class; } + public Type getDeclaringType() { + return declaringType; + } + /** * Creates an object for registering {@link InvocationPlugin}s for methods declared by a * given class. @@ -201,7 +205,8 @@ public Registration(InvocationPlugins plugins, Type declaringType) { this.plugins = plugins; this.declaringType = declaringType; - this.methodSubstitutionBytecodeProvider = null; + this.replacements = null; + this.bytecodeProvider = null; } /** @@ -211,13 +216,29 @@ * @param plugins where to register the plugins * @param declaringType the class declaring the methods for which plugins will be registered * via this object - * @param methodSubstitutionBytecodeProvider provider used to get the bytecodes to parse for - * method substitutions + * @param replacements the current Replacements provider */ - public Registration(InvocationPlugins plugins, Type declaringType, BytecodeProvider methodSubstitutionBytecodeProvider) { + public Registration(InvocationPlugins plugins, Type declaringType, Replacements replacements) { this.plugins = plugins; this.declaringType = declaringType; - this.methodSubstitutionBytecodeProvider = methodSubstitutionBytecodeProvider; + this.replacements = replacements; + this.bytecodeProvider = replacements != null ? replacements.getDefaultReplacementBytecodeProvider() : null; + } + + /** + * Creates an object for registering {@link InvocationPlugin}s for methods declared by a + * given class. + * + * @param plugins where to register the plugins + * @param declaringType the class declaring the methods for which plugins will be registered + * via this object + * @param replacements the current Replacements provider + */ + public Registration(InvocationPlugins plugins, Type declaringType, Replacements replacements, BytecodeProvider bytecodeProvider) { + this.plugins = plugins; + this.declaringType = declaringType; + this.replacements = replacements; + this.bytecodeProvider = bytecodeProvider; } /** @@ -231,7 +252,8 @@ public Registration(InvocationPlugins plugins, String declaringClassName) { this.plugins = plugins; this.declaringType = new OptionalLazySymbol(declaringClassName); - this.methodSubstitutionBytecodeProvider = null; + this.replacements = null; + this.bytecodeProvider = null; } /** @@ -241,13 +263,13 @@ * @param plugins where to register the plugins * @param declaringClassName the name of the class class declaring the methods for which * plugins will be registered via this object - * @param methodSubstitutionBytecodeProvider provider used to get the bytecodes to parse for - * method substitutions + * @param replacements the current Replacements provider */ - public Registration(InvocationPlugins plugins, String declaringClassName, BytecodeProvider methodSubstitutionBytecodeProvider) { + public Registration(InvocationPlugins plugins, String declaringClassName, Replacements replacements) { this.plugins = plugins; this.declaringType = new OptionalLazySymbol(declaringClassName); - this.methodSubstitutionBytecodeProvider = methodSubstitutionBytecodeProvider; + this.replacements = replacements; + this.bytecodeProvider = replacements != null ? replacements.getDefaultReplacementBytecodeProvider() : null; } /** @@ -339,6 +361,118 @@ } /** + * Registers a plugin for a method with no arguments that is conditionally enabled. This + * ensures that {@code Replacements} is aware of this plugin. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerConditional0(boolean isEnabled, String name, InvocationPlugin plugin) { + replacements.registerConditionalPlugin(plugin); + if (isEnabled) { + plugins.register(plugin, false, allowOverwrite, declaringType, name); + } + } + + /** + * Registers a plugin for a method with 1 argument that is conditionally enabled. This + * ensures that {@code Replacements} is aware of this plugin. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerConditional1(boolean isEnabled, String name, Type arg, InvocationPlugin plugin) { + replacements.registerConditionalPlugin(plugin); + if (isEnabled) { + plugins.register(plugin, false, allowOverwrite, declaringType, name, arg); + } + } + + /** + * Registers a plugin for a method with 2 arguments that is conditionally enabled. This + * ensures that {@code Replacements} is aware of this plugin. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerConditional2(boolean isEnabled, String name, Type arg1, Type arg2, InvocationPlugin plugin) { + replacements.registerConditionalPlugin(plugin); + if (isEnabled) { + plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2); + } + } + + /** + * Registers a plugin for a method with 3 arguments that is conditionally enabled. This + * ensures that {@code Replacements} is aware of this plugin. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerConditional3(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, InvocationPlugin plugin) { + replacements.registerConditionalPlugin(plugin); + if (isEnabled) { + plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3); + } + } + + /** + * Registers a plugin for a method with 4 arguments that is conditionally enabled. This + * ensures that {@code Replacements} is aware of this plugin. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerConditional4(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, Type arg4, InvocationPlugin plugin) { + replacements.registerConditionalPlugin(plugin); + if (isEnabled) { + plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4); + } + } + + /** + * Registers a plugin for a method with 5 arguments that is conditionally enabled. This + * ensures that {@code Replacements} is aware of this plugin. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerConditional5(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, InvocationPlugin plugin) { + replacements.registerConditionalPlugin(plugin); + if (isEnabled) { + plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5); + } + } + + /** + * Registers a plugin for a method with 6 arguments that is conditionally enabled. This + * ensures that {@code Replacements} is aware of this plugin. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerConditional6(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, Type arg6, InvocationPlugin plugin) { + replacements.registerConditionalPlugin(plugin); + if (isEnabled) { + plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5, arg6); + } + } + + /** + * Registers a plugin for a method with 7 arguments that is conditionally enabled. This + * ensures that {@code Replacements} is aware of this plugin. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerConditional7(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, Type arg6, Type arg7, InvocationPlugin plugin) { + replacements.registerConditionalPlugin(plugin); + if (isEnabled) { + plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + } + + /** * Registers a plugin for an optional method with no arguments. * * @param name the name of the method @@ -398,7 +532,6 @@ * is non-static. Upon returning, element 0 will have been rewritten to * {@code declaringClass} */ - @Override public void registerMethodSubstitution(Class substituteDeclaringClass, String name, Type... argumentTypes) { registerMethodSubstitution(substituteDeclaringClass, name, name, argumentTypes); } @@ -407,25 +540,63 @@ * Registers a plugin that implements a method based on the bytecode of a substitute method. * * @param substituteDeclaringClass the class declaring the substitute method - * @param name the name of both the original method + * @param name the name of the original method * @param substituteName the name of the substitute method * @param argumentTypes the argument types of the method. Element 0 of this array must be * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method * is non-static. Upon returning, element 0 will have been rewritten to * {@code declaringClass} */ - @Override public void registerMethodSubstitution(Class substituteDeclaringClass, String name, String substituteName, Type... argumentTypes) { - MethodSubstitutionPlugin plugin = createMethodSubstitution(substituteDeclaringClass, substituteName, argumentTypes); - plugins.register(plugin, false, allowOverwrite, declaringType, name, argumentTypes); + doMethodSubstitutionRegistration(false, true, substituteDeclaringClass, name, substituteName, argumentTypes); + } + + /** + * Registers a plugin that implements a method based on the bytecode of a substitute method + * that is conditinally enabled. This ensures that {@code Replacements} is aware of this + * plugin. + * + * @param isEnabled whether the plugin is enabled in the current compiler + * @param substituteDeclaringClass the class declaring the substitute method + * @param name the name of both the original and substitute method + * @param argumentTypes the argument types of the method. Element 0 of this array must be + * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method + * is non-static. Upon returning, element 0 will have been rewritten to + * {@code declaringClass} + */ + public void registerConditionalMethodSubstitution(boolean isEnabled, Class substituteDeclaringClass, String name, Type... argumentTypes) { + registerConditionalMethodSubstitution(isEnabled, substituteDeclaringClass, name, name, argumentTypes); } - public MethodSubstitutionPlugin createMethodSubstitution(Class substituteDeclaringClass, String substituteName, Type... argumentTypes) { - assert methodSubstitutionBytecodeProvider != null : "Registration used for method substitutions requires a non-null methodSubstitutionBytecodeProvider"; - MethodSubstitutionPlugin plugin = new MethodSubstitutionPlugin(methodSubstitutionBytecodeProvider, substituteDeclaringClass, substituteName, argumentTypes); - return plugin; + /** + * Registers a plugin that implements a method based on the bytecode of a substitute method + * that is conditinally enabled. This ensures that {@code Replacements} is aware of this + * plugin. + * + * @param isEnabled whether the plugin is enabled in the current compiler + * @param substituteDeclaringClass the class declaring the substitute method + * @param name the name of the original method + * @param substituteName the name of the substitute method + * @param argumentTypes the argument types of the method. Element 0 of this array must be + * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method + * is non-static. Upon returning, element 0 will have been rewritten to + * {@code declaringClass} + */ + public void registerConditionalMethodSubstitution(boolean isEnabled, Class substituteDeclaringClass, String name, String substituteName, Type... argumentTypes) { + doMethodSubstitutionRegistration(true, isEnabled, substituteDeclaringClass, name, substituteName, argumentTypes); } + private void doMethodSubstitutionRegistration(boolean isConditional, boolean isEnabled, Class substituteDeclaringClass, String name, String substituteName, Type[] argumentTypes) { + MethodSubstitutionPlugin plugin = new MethodSubstitutionPlugin(this, bytecodeProvider, name, substituteDeclaringClass, substituteName, argumentTypes); + replacements.registerMethodSubstitution(plugin); + if (isConditional) { + // Notify Replacements about the plugin even if it's not current enabled + replacements.registerConditionalPlugin(plugin); + } + if (isEnabled) { + plugins.register(plugin, false, allowOverwrite, declaringType, name, argumentTypes); + } + } } /** @@ -519,13 +690,7 @@ this.plugin = data; this.isStatic = isStatic; this.name = name; - StringBuilder buf = new StringBuilder(); - buf.append('('); - for (int i = isStatic ? 0 : 1; i < argumentTypes.length; i++) { - buf.append(MetaUtil.toInternalName(argumentTypes[i].getTypeName())); - } - buf.append(')'); - this.argumentsDescriptor = buf.toString(); + this.argumentsDescriptor = toArgumentDescriptor(isStatic, argumentTypes); assert !name.equals("") || !isStatic : this; } @@ -546,6 +711,16 @@ } } + static String toArgumentDescriptor(boolean isStatic, Type[] argumentTypes) { + StringBuilder buf = new StringBuilder(); + buf.append('('); + for (int i = isStatic ? 0 : 1; i < argumentTypes.length; i++) { + buf.append(MetaUtil.toInternalName(argumentTypes[i].getTypeName())); + } + buf.append(')'); + return buf.toString(); + } + /** * Plugin registrations for already resolved methods. If non-null, then {@link #registrations} * is null and no further registrations can be made. diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java Thu Oct 31 16:54:16 2019 -0700 @@ -42,6 +42,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; /** * An {@link InvocationPlugin} for a method where the implementation of the method is provided by a @@ -56,6 +57,8 @@ */ public final class MethodSubstitutionPlugin implements InvocationPlugin { + private InvocationPlugins.Registration registration; + private ResolvedJavaMethod cachedSubstitute; /** @@ -64,9 +67,14 @@ private final Class declaringClass; /** - * The name of the original and substitute method. + * The name of the substitute method. */ - private final String name; + private final String substituteName; + + /** + * The name of the original method. + */ + private final String originalName; /** * The parameter types of the substitute method. @@ -81,16 +89,21 @@ * Creates a method substitution plugin. * * @param bytecodeProvider used to get the bytecodes to parse for the substitute method + * @param originalName the name of the original method * @param declaringClass the class in which the substitute method is declared - * @param name the name of the substitute method + * @param substituteName the name of the substitute method * @param parameters the parameter types of the substitute method. If the original method is not * static, then {@code parameters[0]} must be the {@link Class} value denoting * {@link InvocationPlugin.Receiver} */ - public MethodSubstitutionPlugin(BytecodeProvider bytecodeProvider, Class declaringClass, String name, Type... parameters) { + public MethodSubstitutionPlugin(InvocationPlugins.Registration registration, BytecodeProvider bytecodeProvider, String originalName, Class declaringClass, String substituteName, + Type... parameters) { + assert bytecodeProvider != null : "Requires a non-null methodSubstitutionBytecodeProvider"; + this.registration = registration; this.bytecodeProvider = bytecodeProvider; + this.originalName = originalName; this.declaringClass = declaringClass; - this.name = name; + this.substituteName = substituteName; this.parameters = parameters; this.originalIsStatic = parameters.length == 0 || parameters[0] != InvocationPlugin.Receiver.class; } @@ -144,7 +157,7 @@ * Determines if a given method is the substitute method of this plugin. */ private boolean isSubstitute(Method m) { - if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(name)) { + if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(substituteName)) { if (parameters.length == m.getParameterCount()) { Class[] mparams = m.getParameterTypes(); int start = 0; @@ -189,9 +202,6 @@ @Override public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) { if (IS_IN_NATIVE_IMAGE || (UseEncodedGraphs.getValue(b.getOptions()) && !b.parsingIntrinsic())) { - if (!IS_IN_NATIVE_IMAGE && UseEncodedGraphs.getValue(b.getOptions())) { - b.getReplacements().registerMethodSubstitution(this, targetMethod, INLINE_AFTER_PARSING, b.getOptions()); - } StructuredGraph subst = b.getReplacements().getMethodSubstitution(this, targetMethod, INLINE_AFTER_PARSING, @@ -220,7 +230,27 @@ @Override public String toString() { - return String.format("%s[%s.%s(%s)]", getClass().getSimpleName(), declaringClass.getName(), name, + return String.format("%s[%s.%s(%s)]", getClass().getSimpleName(), declaringClass.getName(), substituteName, Arrays.asList(parameters).stream().map(c -> c.getTypeName()).collect(Collectors.joining(", "))); } + + public String originalMethodAsString() { + return String.format("%s.%s(%s)", declaringClass.getName(), substituteName, Arrays.asList(parameters).stream().map(c -> c.getTypeName()).collect(Collectors.joining(", "))); + } + + public ResolvedJavaMethod getOriginalMethod(MetaAccessProvider metaAccess) { + Class clazz = resolveType(registration.getDeclaringType(), false); + if (clazz == null) { + throw new GraalError("Can't find original class for " + this + " with class " + registration.getDeclaringType()); + } + ResolvedJavaType type = metaAccess.lookupJavaType(clazz); + String argumentsDescriptor = InvocationPlugins.toArgumentDescriptor(originalIsStatic, this.parameters); + for (ResolvedJavaMethod declared : type.getDeclaredMethods()) { + if (declared.getName().equals(originalName) && declared.isStatic() == originalIsStatic && + declared.getSignature().toMethodDescriptor().startsWith(argumentsDescriptor)) { + return declared; + } + } + throw new GraalError("Can't find original method for " + this + " with class " + registration.getDeclaringType()); + } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, 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 @@ -93,4 +93,9 @@ public Stamp getAccessStamp() { return expectedValue.stamp(NodeView.DEFAULT).meet(newValue.stamp(NodeView.DEFAULT)).unrestricted(); } + + @Override + public LocationIdentity getKilledLocationIdentity() { + return getLocationIdentity(); + } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractUnsafeCompareAndSwapNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractUnsafeCompareAndSwapNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractUnsafeCompareAndSwapNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -97,7 +97,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return locationIdentity; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, 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 @@ -74,7 +74,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return locationIdentity; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, 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 @@ -80,7 +80,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return locationIdentity; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ExceptionObjectNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ExceptionObjectNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ExceptionObjectNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2019, 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 @@ -60,7 +60,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } @@ -80,7 +80,7 @@ * Now the lowering to BeginNode+LoadExceptionNode can be performed, since no more * deopts can float in between the begin node and the load exception node. */ - LocationIdentity locationsKilledByInvoke = ((InvokeWithExceptionNode) predecessor()).getLocationIdentity(); + LocationIdentity locationsKilledByInvoke = ((InvokeWithExceptionNode) predecessor()).getKilledLocationIdentity(); AbstractBeginNode entry = graph().add(KillingBeginNode.create(locationsKilledByInvoke)); LoadExceptionObjectNode loadException = graph().add(new LoadExceptionObjectNode(stamp(NodeView.DEFAULT))); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, 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 @@ -103,4 +103,9 @@ public Stamp getAccessStamp() { return stamp(NodeView.DEFAULT); } + + @Override + public LocationIdentity getKilledLocationIdentity() { + return getLocationIdentity(); + } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorEnterNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorEnterNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorEnterNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2019, 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 @@ -57,7 +57,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -70,7 +70,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RawMonitorEnterNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RawMonitorEnterNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RawMonitorEnterNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2019, 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 @@ -64,7 +64,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -25,6 +25,7 @@ package org.graalvm.compiler.nodes.memory; import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -39,7 +40,7 @@ * does not include a null check on the object. */ @NodeInfo -public abstract class FixedAccessNode extends DeoptimizingFixedWithNextNode implements Access { +public abstract class FixedAccessNode extends DeoptimizingFixedWithNextNode implements Access, IterableNodeType { public static final NodeClass TYPE = NodeClass.create(FixedAccessNode.class); @OptionalInput(InputType.Guard) protected GuardingNode guard; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryCheckpoint.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryCheckpoint.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryCheckpoint.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -44,8 +44,7 @@ * * @return the identity of the location killed by this node. */ - LocationIdentity getLocationIdentity(); - + LocationIdentity getKilledLocationIdentity(); } interface Multi extends MemoryCheckpoint { @@ -57,7 +56,7 @@ * * @return the identities of all locations killed by this node. */ - LocationIdentity[] getLocationIdentities(); + LocationIdentity[] getKilledLocationIdentities(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/VolatileReadNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/VolatileReadNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, Red Hat Inc. 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.memory; + +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.memory.address.AddressNode; +import jdk.internal.vm.compiler.word.LocationIdentity; + +import static org.graalvm.compiler.nodeinfo.InputType.Memory; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; + +@NodeInfo(nameTemplate = "Read#{p#location/s}", allowedUsageTypes = Memory, cycles = CYCLES_2, size = SIZE_1) +public class VolatileReadNode extends ReadNode implements MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(VolatileReadNode.class); + + public VolatileReadNode(AddressNode address, LocationIdentity location, Stamp stamp, BarrierType barrierType) { + super(TYPE, address, location, stamp, null, barrierType, false, null); + assert GraalOptions.LateMembars.getValue(address.getOptions()); + } + + @SuppressWarnings("try") + @Override + public FloatingAccessNode asFloatingNode() { + throw new RuntimeException(); + } + + @Override + public boolean canFloat() { + return false; + } + + @Override + public LocationIdentity getKilledLocationIdentity() { + return LocationIdentity.any(); + } + + @Override + public boolean canNullCheck() { + return false; + } + +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -44,13 +44,16 @@ public class WriteNode extends AbstractWriteNode implements LIRLowerableAccess, Canonicalizable { public static final NodeClass TYPE = NodeClass.create(WriteNode.class); + private final boolean volatileAccess; - public WriteNode(AddressNode address, LocationIdentity location, ValueNode value, BarrierType barrierType) { + public WriteNode(AddressNode address, LocationIdentity location, ValueNode value, BarrierType barrierType, boolean volatileAccess) { super(TYPE, address, location, value, barrierType); + this.volatileAccess = volatileAccess; } protected WriteNode(NodeClass c, AddressNode address, LocationIdentity location, ValueNode value, BarrierType barrierType) { super(c, address, location, value, barrierType); + this.volatileAccess = false; } @Override @@ -61,7 +64,7 @@ @Override public boolean canNullCheck() { - return true; + return !isVolatile(); } @Override @@ -73,11 +76,23 @@ public Node canonical(CanonicalizerTool tool) { if (tool.canonicalizeReads() && hasExactlyOneUsage() && next() instanceof WriteNode) { WriteNode write = (WriteNode) next(); - if (write.lastLocationAccess == this && write.getAddress() == getAddress() && getAccessStamp().isCompatible(write.getAccessStamp())) { + if (write.lastLocationAccess == this && write.getAddress() == getAddress() && getAccessStamp().isCompatible(write.getAccessStamp()) && !isVolatile()) { write.setLastLocationAccess(getLastLocationAccess()); return write; } } return this; } + + @Override + public LocationIdentity getKilledLocationIdentity() { + if (isVolatile()) { + return LocationIdentity.any(); + } + return getLocationIdentity(); + } + + public boolean isVolatile() { + return volatileAccess; + } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java Thu Oct 31 16:54:16 2019 -0700 @@ -34,6 +34,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.options.OptionValues; @@ -82,8 +83,13 @@ } @Override - public void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) { - delegate.registerMethodSubstitution(plugin, original, context, options); + public void registerMethodSubstitution(MethodSubstitutionPlugin plugin) { + delegate.registerMethodSubstitution(plugin); + } + + @Override + public void registerConditionalPlugin(InvocationPlugin plugin) { + delegate.registerConditionalPlugin(plugin); } @Override diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java Thu Oct 31 16:54:16 2019 -0700 @@ -97,7 +97,14 @@ /** * Registers a plugin as a substitution. */ - void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options); + void registerMethodSubstitution(MethodSubstitutionPlugin plugin); + + /** + * Marks a plugin as conditionally applied. In the contenxt of libgraal conditional plugins + * can't be used in during graph encoding for snippets and method substitutions and this is used + * to detect violations of this restriction. + */ + void registerConditionalPlugin(InvocationPlugin plugin); /** * Gets a graph that is a substitution for a given method. diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Thu Oct 31 16:54:16 2019 -0700 @@ -54,11 +54,13 @@ import org.graalvm.compiler.nodes.AbstractEndNode; import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.ControlSinkNode; import org.graalvm.compiler.nodes.ControlSplitNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.GuardNode; +import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.LoopExitNode; @@ -105,6 +107,8 @@ public static final OptionKey VerifyKillCFGUnusedNodes = new OptionKey<>(false); } + public static final int MAX_FRAMESTATE_SEARCH_DEPTH = 4; + private static void killCFGInner(FixedNode node) { EconomicSet markedNodes = EconomicSet.create(); EconomicMap> unmarkedMerges = EconomicMap.create(); @@ -1110,4 +1114,55 @@ tool.createVirtualObject(newVirtualArray, newEntryState, Collections. emptyList(), false); tool.replaceWithVirtual(newVirtualArray); } + + /** + * Snippet lowerings may produce patterns without a frame state on the merge. We need to take + * extra care when optimizing these patterns. + */ + public static boolean checkFrameState(FixedNode start, int maxDepth) { + if (maxDepth == 0) { + return false; + } + FixedNode node = start; + while (true) { + if (node instanceof AbstractMergeNode) { + AbstractMergeNode mergeNode = (AbstractMergeNode) node; + if (mergeNode.stateAfter() == null) { + return false; + } else { + return true; + } + } else if (node instanceof StateSplit) { + StateSplit stateSplitNode = (StateSplit) node; + if (stateSplitNode.stateAfter() != null) { + return true; + } + } + + if (node instanceof ControlSplitNode) { + ControlSplitNode controlSplitNode = (ControlSplitNode) node; + for (Node succ : controlSplitNode.cfgSuccessors()) { + if (checkFrameState((FixedNode) succ, maxDepth - 1)) { + return true; + } + } + return false; + } else if (node instanceof FixedWithNextNode) { + FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node; + node = fixedWithNextNode.next(); + } else if (node instanceof AbstractEndNode) { + AbstractEndNode endNode = (AbstractEndNode) node; + node = endNode.merge(); + } else if (node instanceof ControlSinkNode) { + return true; + } else { + assert false : "unexpected node"; + return false; + } + } + } + + public static boolean mayRemoveSplit(IfNode ifNode) { + return GraphUtil.checkFrameState(ifNode.trueSuccessor(), MAX_FRAMESTATE_SEARCH_DEPTH) && GraphUtil.checkFrameState(ifNode.falseSuccessor(), MAX_FRAMESTATE_SEARCH_DEPTH); + } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/AllocatedObjectNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/AllocatedObjectNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/AllocatedObjectNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2019, 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 @@ -36,7 +36,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; -import org.graalvm.compiler.nodes.spi.Virtualizable; +import org.graalvm.compiler.nodes.spi.VirtualizableAllocation; import org.graalvm.compiler.nodes.spi.VirtualizerTool; import org.graalvm.compiler.nodes.util.GraphUtil; @@ -45,7 +45,7 @@ * {@link VirtualObjectNode}. */ @NodeInfo(cycles = CYCLES_0, size = SIZE_0) -public final class AllocatedObjectNode extends FloatingNode implements Virtualizable, ArrayLengthProvider { +public final class AllocatedObjectNode extends FloatingNode implements VirtualizableAllocation, ArrayLengthProvider { public static final NodeClass TYPE = NodeClass.create(AllocatedObjectNode.class); @Input VirtualObjectNode virtualObject; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/CommitAllocationNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/CommitAllocationNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/CommitAllocationNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2019, 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 @@ -121,7 +121,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return locks.isEmpty() ? LocationIdentity.init() : LocationIdentity.any(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Thu Oct 31 16:54:16 2019 -0700 @@ -24,6 +24,12 @@ package org.graalvm.compiler.phases.common; +import static org.graalvm.compiler.phases.common.CanonicalizerPhase.CanonicalizerFeature.CFG_SIMPLIFICATION; +import static org.graalvm.compiler.phases.common.CanonicalizerPhase.CanonicalizerFeature.GVN; +import static org.graalvm.compiler.phases.common.CanonicalizerPhase.CanonicalizerFeature.READ_CANONICALIZATION; + +import java.util.EnumSet; + import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.CounterKey; @@ -66,6 +72,12 @@ public class CanonicalizerPhase extends BasePhase { + public enum CanonicalizerFeature { + READ_CANONICALIZATION, + CFG_SIMPLIFICATION, + GVN + } + private static final int MAX_ITERATION_PER_NODE = 10; private static final CounterKey COUNTER_CANONICALIZED_NODES = DebugContext.counter("CanonicalizedNodes"); private static final CounterKey COUNTER_PROCESSED_NODES = DebugContext.counter("ProcessedNodes"); @@ -75,40 +87,79 @@ private static final CounterKey COUNTER_SIMPLIFICATION_CONSIDERED_NODES = DebugContext.counter("SimplificationConsideredNodes"); private static final CounterKey COUNTER_GLOBAL_VALUE_NUMBERING_HITS = DebugContext.counter("GlobalValueNumberingHits"); - private boolean globalValueNumber = true; - private boolean canonicalizeReads = true; - private boolean simplify = true; - private final CustomCanonicalizer customCanonicalizer; + private final EnumSet features; + private final CustomCanonicalization customCanonicalization; + private final CustomSimplification customSimplification; - public abstract static class CustomCanonicalizer { + public interface CustomCanonicalization { + /** + * @param node the node to be canonicalized + * @return the same node if no action should be taken, {@code null} if the node should be + * deleted, or a new node that should replace the given node + */ + Node canonicalize(Node node); + } - public Node canonicalize(Node node) { - return node; - } + public interface CustomSimplification { + /** + * @param node the node to be simplified + * @param tool utility available during the simplification process + */ + void simplify(Node node, SimplifierTool tool); + } - @SuppressWarnings("unused") - public void simplify(Node node, SimplifierTool tool) { - } + protected CanonicalizerPhase(EnumSet features) { + this(null, null, features); + } + + protected CanonicalizerPhase() { + this(null, null, EnumSet.allOf(CanonicalizerFeature.class)); + } + + protected CanonicalizerPhase(CustomCanonicalization customCanonicalization, CustomSimplification customSimplification) { + this(customCanonicalization, customSimplification, EnumSet.allOf(CanonicalizerFeature.class)); } - public CanonicalizerPhase() { - this(null); + protected CanonicalizerPhase(CustomCanonicalization customCanonicalization, CustomSimplification customSimplification, EnumSet features) { + this.customCanonicalization = customCanonicalization; + this.customSimplification = customSimplification; + this.features = features; } - public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer) { - this.customCanonicalizer = customCanonicalizer; + public CanonicalizerPhase copyWithCustomCanonicalization(CustomCanonicalization newCanonicalization) { + return new CanonicalizerPhase(newCanonicalization, customSimplification, features); + } + + public CanonicalizerPhase copyWithCustomSimplification(CustomSimplification newSimplification) { + return new CanonicalizerPhase(customCanonicalization, newSimplification, features); + } + + public CanonicalizerPhase copyWithoutGVN() { + EnumSet newFeatures = EnumSet.copyOf(features); + newFeatures.remove(GVN); + return new CanonicalizerPhase(customCanonicalization, customSimplification, newFeatures); } - public void disableGVN() { - globalValueNumber = false; + public CanonicalizerPhase copyWithoutSimplification() { + EnumSet newFeatures = EnumSet.copyOf(features); + newFeatures.remove(CFG_SIMPLIFICATION); + return new CanonicalizerPhase(customCanonicalization, customSimplification, newFeatures); + } + + public static CanonicalizerPhase create() { + return new CanonicalizerPhase(null, null, EnumSet.allOf(CanonicalizerFeature.class)); } - public void disableReadCanonicalization() { - canonicalizeReads = false; + public static CanonicalizerPhase createWithoutReadCanonicalization() { + return new CanonicalizerPhase(EnumSet.complementOf(EnumSet.of(READ_CANONICALIZATION))); } - public void disableSimplification() { - simplify = false; + public static CanonicalizerPhase createWithoutGVN() { + return new CanonicalizerPhase(EnumSet.complementOf(EnumSet.of(GVN))); + } + + public static CanonicalizerPhase createWithoutCFGSimplification() { + return new CanonicalizerPhase(EnumSet.complementOf(EnumSet.of(CFG_SIMPLIFICATION))); } @Override @@ -274,7 +325,7 @@ if (tryCanonicalize(node, nodeClass)) { return true; } - if (globalValueNumber && tryGlobalValueNumbering(node, nodeClass)) { + if (features.contains(GVN) && tryGlobalValueNumbering(node, nodeClass)) { return true; } if (node instanceof ValueNode) { @@ -329,24 +380,18 @@ @SuppressWarnings("try") public boolean tryCanonicalize(final Node node, NodeClass nodeClass) { try (DebugCloseable position = node.withNodeSourcePosition(); DebugContext.Scope scope = debug.withContext(node)) { - if (customCanonicalizer != null) { - Node canonical = customCanonicalizer.canonicalize(node); - if (performReplacement(node, canonical)) { - return true; - } else { - customCanonicalizer.simplify(node, tool); - if (node.isDeleted()) { - return true; - } - } - } if (nodeClass.isCanonicalizable()) { COUNTER_CANONICALIZATION_CONSIDERED_NODES.increment(debug); - Node canonical; + Node canonical = node; try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) { - canonical = ((Canonicalizable) node).canonical(tool); - if (canonical == node && nodeClass.isCommutative()) { - canonical = ((BinaryCommutative) node).maybeCommuteInputs(); + if (customCanonicalization != null) { + canonical = customCanonicalization.canonicalize(node); + } + if (canonical == node) { + canonical = ((Canonicalizable) node).canonical(tool); + if (canonical == node && nodeClass.isCommutative()) { + canonical = ((BinaryCommutative) node).maybeCommuteInputs(); + } } } catch (Throwable e) { throw new GraalGraphError(e).addContext(node); @@ -356,12 +401,17 @@ } } - if (nodeClass.isSimplifiable() && simplify) { + if (features.contains(CFG_SIMPLIFICATION) && nodeClass.isSimplifiable()) { debug.log(DebugContext.VERBOSE_LEVEL, "Canonicalizer: simplifying %s", node); COUNTER_SIMPLIFICATION_CONSIDERED_NODES.increment(debug); - node.simplify(tool); - if (node.isDeleted()) { - debug.log("Canonicalizer: simplified %s", node); + if (customSimplification != null) { + customSimplification.simplify(node, tool); + } + if (node.isAlive()) { + node.simplify(tool); + if (node.isDeleted()) { + debug.log("Canonicalizer: simplified %s", node); + } } return node.isDeleted(); } @@ -518,7 +568,7 @@ @Override public boolean canonicalizeReads() { - return canonicalizeReads; + return features.contains(READ_CANONICALIZATION); } @Override @@ -549,7 +599,7 @@ } public boolean getCanonicalizeReads() { - return canonicalizeReads; + return features.contains(READ_CANONICALIZATION); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Thu Oct 31 16:54:16 2019 -0700 @@ -186,6 +186,8 @@ // Check if we can move guards upwards. AbstractBeginNode trueSuccessor = node.trueSuccessor(); + AbstractBeginNode falseSuccessor = node.falseSuccessor(); + EconomicMap trueGuards = EconomicMap.create(Equivalence.IDENTITY); for (GuardNode guard : trueSuccessor.guards()) { LogicNode condition = guard.getCondition(); @@ -195,7 +197,7 @@ } if (!trueGuards.isEmpty()) { - for (GuardNode guard : node.falseSuccessor().guards().snapshot()) { + for (GuardNode guard : falseSuccessor.guards().snapshot()) { GuardNode otherGuard = trueGuards.get(guard.getCondition()); if (otherGuard != null && guard.isNegated() == otherGuard.isNegated()) { Speculation speculation = otherGuard.getSpeculation(); @@ -210,9 +212,17 @@ guard.getNoDeoptSuccessorPosition()); GuardNode newGuard = node.graph().unique(newlyCreatedGuard); if (otherGuard.isAlive()) { - otherGuard.replaceAndDelete(newGuard); + if (trueSuccessor instanceof LoopExitNode && beginNode.graph().hasValueProxies()) { + otherGuard.replaceAndDelete(ProxyNode.forGuard(newGuard, (LoopExitNode) trueSuccessor)); + } else { + otherGuard.replaceAndDelete(newGuard); + } } - guard.replaceAndDelete(newGuard); + if (falseSuccessor instanceof LoopExitNode && beginNode.graph().hasValueProxies()) { + guard.replaceAndDelete(ProxyNode.forGuard(newGuard, (LoopExitNode) falseSuccessor)); + } else { + guard.replaceAndDelete(newGuard); + } } } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java Thu Oct 31 16:54:16 2019 -0700 @@ -48,6 +48,7 @@ import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.PhiNode; +import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -166,9 +167,9 @@ protected void processNode(FixedNode node, EconomicSet currentState) { if (node instanceof MemoryCheckpoint.Single) { - processIdentity(currentState, ((MemoryCheckpoint.Single) node).getLocationIdentity()); + processIdentity(currentState, ((MemoryCheckpoint.Single) node).getKilledLocationIdentity()); } else if (node instanceof MemoryCheckpoint.Multi) { - for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) { + for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getKilledLocationIdentities()) { processIdentity(currentState, identity); } } @@ -274,7 +275,7 @@ } mergedStatesCount++; } - newState.lastMemorySnapshot.put(key, merged); + newState.getMap().put(key, merged); } return newState; @@ -301,6 +302,16 @@ @Override protected MemoryMapImpl processNode(FixedNode node, MemoryMapImpl state) { + + if (node instanceof LoopExitNode) { + final LoopExitNode loopExitNode = (LoopExitNode) node; + final EconomicSet modifiedInLoop = modifiedInLoops.get(loopExitNode.loopBegin()); + final boolean anyModified = modifiedInLoop.contains(LocationIdentity.any()); + state.getMap().replaceAll((locationIdentity, memoryNode) -> (anyModified || modifiedInLoop.contains(locationIdentity)) + ? ProxyNode.forMemory(memoryNode, loopExitNode, locationIdentity) + : memoryNode); + } + if (node instanceof MemoryAnchorNode) { processAnchor((MemoryAnchorNode) node, state); return state; @@ -312,7 +323,8 @@ if (createFloatingReads && node instanceof FloatableAccessNode) { processFloatable((FloatableAccessNode) node, state); - } else if (node instanceof MemoryCheckpoint.Single) { + } + if (node instanceof MemoryCheckpoint.Single) { processCheckpoint((MemoryCheckpoint.Single) node, state); } else if (node instanceof MemoryCheckpoint.Multi) { processCheckpoint((MemoryCheckpoint.Multi) node, state); @@ -320,7 +332,7 @@ assert MemoryCheckpoint.TypeAssertion.correctType(node) : node; if (createMemoryMapNodes && node instanceof ReturnNode) { - ((ReturnNode) node).setMemoryMap(node.graph().unique(new MemoryMapNode(state.lastMemorySnapshot))); + ((ReturnNode) node).setMemoryMap(node.graph().unique(new MemoryMapNode(state.getMap()))); } return state; } @@ -355,21 +367,21 @@ } private static void processCheckpoint(MemoryCheckpoint.Single checkpoint, MemoryMapImpl state) { - processIdentity(checkpoint.getLocationIdentity(), checkpoint, state); + processIdentity(checkpoint.getKilledLocationIdentity(), checkpoint, state); } private static void processCheckpoint(MemoryCheckpoint.Multi checkpoint, MemoryMapImpl state) { - for (LocationIdentity identity : checkpoint.getLocationIdentities()) { + for (LocationIdentity identity : checkpoint.getKilledLocationIdentities()) { processIdentity(identity, checkpoint, state); } } private static void processIdentity(LocationIdentity identity, MemoryCheckpoint checkpoint, MemoryMapImpl state) { if (identity.isAny()) { - state.lastMemorySnapshot.clear(); + state.getMap().clear(); } if (identity.isMutable()) { - state.lastMemorySnapshot.put(identity, checkpoint); + state.getMap().put(identity, checkpoint); } } @@ -405,7 +417,7 @@ * side it needs to choose by putting in the location identity on both successors. */ InvokeWithExceptionNode invoke = (InvokeWithExceptionNode) node.predecessor(); - result.lastMemorySnapshot.put(invoke.getLocationIdentity(), (MemoryCheckpoint) node); + result.getMap().put(invoke.getKilledLocationIdentity(), (MemoryCheckpoint) node); } return result; } @@ -417,13 +429,13 @@ if (modifiedLocations.contains(LocationIdentity.any())) { // create phis for all locations if ANY is modified in the loop modifiedLocations = EconomicSet.create(Equivalence.DEFAULT, modifiedLocations); - modifiedLocations.addAll(initialState.lastMemorySnapshot.getKeys()); + modifiedLocations.addAll(initialState.getMap().getKeys()); } for (LocationIdentity location : modifiedLocations) { createMemoryPhi(loop, initialState, phis, location); } - initialState.lastMemorySnapshot.putAll(phis); + initialState.getMap().putAll(phis); LoopInfo loopInfo = ReentrantNodeIterator.processLoop(this, loop, initialState); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, 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 @@ -24,7 +24,6 @@ package org.graalvm.compiler.phases.common; -import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; @@ -34,8 +33,6 @@ import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.GuardNode; import org.graalvm.compiler.nodes.IfNode; -import org.graalvm.compiler.nodes.LoopBeginNode; -import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; @@ -62,11 +59,9 @@ private static class LowerGuards extends ScheduledNodeIterator { - private final Block block; private boolean useGuardIdAsDebugId; - LowerGuards(Block block, boolean useGuardIdAsDebugId) { - this.block = block; + LowerGuards(boolean useGuardIdAsDebugId) { this.useGuardIdAsDebugId = useGuardIdAsDebugId; } @@ -95,7 +90,6 @@ AbstractBeginNode deoptBranch = BeginNode.begin(deopt); AbstractBeginNode trueSuccessor; AbstractBeginNode falseSuccessor; - insertLoopExits(deopt); if (guard.isNegated()) { trueSuccessor = deoptBranch; falseSuccessor = fastPath; @@ -108,16 +102,6 @@ insert(ifNode, fastPath); } } - - private void insertLoopExits(DeoptimizeNode deopt) { - Loop loop = block.getLoop(); - StructuredGraph graph = deopt.graph(); - while (loop != null) { - LoopExitNode exit = graph.add(new LoopExitNode((LoopBeginNode) loop.getHeader().getBeginNode())); - graph.addBeforeFixed(deopt, exit); - loop = loop.getParent(); - } - } } @Override @@ -143,6 +127,6 @@ private static void processBlock(Block block, ScheduleResult schedule) { DebugContext debug = block.getBeginNode().getDebug(); - new LowerGuards(block, debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod()).processNodes(block, schedule); + new LowerGuards(debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod()).processNodes(block, schedule); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/InsertMembarsPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/InsertMembarsPhase.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, Red Hat Inc. 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.phases.common; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.extended.MembarNode; +import org.graalvm.compiler.nodes.memory.FixedAccessNode; +import org.graalvm.compiler.nodes.memory.ReadNode; +import org.graalvm.compiler.nodes.memory.VolatileReadNode; +import org.graalvm.compiler.nodes.memory.WriteNode; +import org.graalvm.compiler.phases.Phase; + +import static jdk.vm.ci.code.MemoryBarriers.JMM_POST_VOLATILE_READ; +import static jdk.vm.ci.code.MemoryBarriers.JMM_POST_VOLATILE_WRITE; +import static jdk.vm.ci.code.MemoryBarriers.JMM_PRE_VOLATILE_READ; +import static jdk.vm.ci.code.MemoryBarriers.JMM_PRE_VOLATILE_WRITE; + +public class InsertMembarsPhase extends Phase { + @Override + protected void run(StructuredGraph graph) { + for (FixedAccessNode access : graph.getNodes(FixedAccessNode.TYPE)) { + if (access instanceof VolatileReadNode) { + ReadNode read = (ReadNode) access; + MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); + graph.addBeforeFixed(read, preMembar); + MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); + graph.addAfterFixed(read, postMembar); + } else if (access instanceof WriteNode && ((WriteNode) access).isVolatile()) { + WriteNode write = (WriteNode) access; + MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + graph.addBeforeFixed(write, preMembar); + MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); + graph.addAfterFixed(write, postMembar); + } + } + } + + @Override + public float codeSizeIncrease() { + return 3f; + } +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java Thu Oct 31 16:54:16 2019 -0700 @@ -46,6 +46,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeBitMap; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodeinfo.InputType; @@ -131,12 +132,14 @@ private final NodeBitMap activeGuards; private AnchoringNode guardAnchor; private FixedWithNextNode lastFixedNode; + private NodeMap nodeMap; - LoweringToolImpl(CoreProviders context, AnchoringNode guardAnchor, NodeBitMap activeGuards, FixedWithNextNode lastFixedNode) { + LoweringToolImpl(CoreProviders context, AnchoringNode guardAnchor, NodeBitMap activeGuards, FixedWithNextNode lastFixedNode, NodeMap nodeMap) { this.context = context; this.guardAnchor = guardAnchor; this.activeGuards = activeGuards; this.lastFixedNode = lastFixedNode; + this.nodeMap = nodeMap; } @Override @@ -199,7 +202,8 @@ StructuredGraph graph = before.graph(); if (OptEliminateGuards.getValue(graph.getOptions())) { for (Node usage : condition.usages()) { - if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage) && ((GuardNode) usage).isNegated() == negated) { + if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage) && ((GuardNode) usage).isNegated() == negated && + (!before.graph().hasValueProxies() || nodeMap.get(((GuardNode) usage).getAnchor().asNode()).isInSameOrOuterLoopOf(nodeMap.get(before)))) { return (GuardNode) usage; } } @@ -310,9 +314,9 @@ */ boolean isAny = false; if (n instanceof MemoryCheckpoint.Single) { - isAny = ((MemoryCheckpoint.Single) n).getLocationIdentity().isAny(); + isAny = ((MemoryCheckpoint.Single) n).getKilledLocationIdentity().isAny(); } else { - for (LocationIdentity ident : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) { + for (LocationIdentity ident : ((MemoryCheckpoint.Multi) n).getKilledLocationIdentities()) { if (ident.isAny()) { isAny = true; } @@ -447,7 +451,7 @@ @SuppressWarnings("try") private AnchoringNode process(final Block b, final NodeBitMap activeGuards, final AnchoringNode startAnchor) { - final LoweringToolImpl loweringTool = new LoweringToolImpl(context, startAnchor, activeGuards, b.getBeginNode()); + final LoweringToolImpl loweringTool = new LoweringToolImpl(context, startAnchor, activeGuards, b.getBeginNode(), this.schedule.getNodeToBlockMap()); // Lower the instructions of this block. List nodes = schedule.nodesFor(b); @@ -613,69 +617,6 @@ } } - public static void processBlockBounded(final Frame rootFrame) { - ProcessBlockState state = ST_PROCESS; - Frame f = rootFrame; - while (f != null) { - ProcessBlockState nextState; - if (state == ST_PROCESS || state == ST_PROCESS_ALWAYS_REACHED) { - f.preprocess(); - nextState = state == ST_PROCESS_ALWAYS_REACHED ? ST_ENTER : ST_ENTER_ALWAYS_REACHED; - } else if (state == ST_ENTER_ALWAYS_REACHED) { - if (f.alwaysReachedBlock != null && f.alwaysReachedBlock.getDominator() == f.block) { - Frame continueRecur = f.enterAlwaysReached(f.alwaysReachedBlock); - if (continueRecur == null) { - // stop recursion here - f.postprocess(); - f = f.parent; - state = ST_ENTER; - continue; - } - f = continueRecur; - nextState = ST_PROCESS; - } else { - nextState = ST_ENTER; - } - } else if (state == ST_ENTER) { - if (f.dominated != null) { - Block n = f.dominated; - f.dominated = n.getDominatedSibling(); - if (n == f.alwaysReachedBlock) { - if (f.dominated != null) { - n = f.dominated; - f.dominated = n.getDominatedSibling(); - } else { - n = null; - } - } - if (n == null) { - nextState = ST_LEAVE; - } else { - Frame continueRecur = f.enter(n); - if (continueRecur == null) { - // stop recursion here - f.postprocess(); - f = f.parent; - state = ST_ENTER; - continue; - } - f = continueRecur; - nextState = ST_PROCESS; - } - } else { - nextState = ST_LEAVE; - } - } else if (state == ST_LEAVE) { - f.postprocess(); - f = f.parent; - nextState = ST_ENTER; - } else { - throw GraalError.shouldNotReachHere(); - } - state = nextState; - } - } - public abstract static class Frame> { protected final Block block; final T parent; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java Thu Oct 31 16:54:16 2019 -0700 @@ -56,6 +56,7 @@ import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.NodeWorkList; +import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractEndNode; @@ -87,6 +88,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.IsNullNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; +import org.graalvm.compiler.nodes.extended.GuardedNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.java.ExceptionObjectNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; @@ -526,7 +528,17 @@ assert unwindNode.predecessor() != null; assert invokeWithException.exceptionEdge().successors().count() == 1; ExceptionObjectNode obj = (ExceptionObjectNode) invokeWithException.exceptionEdge(); - obj.replaceAtUsages(unwindNode.exception()); + /* + * The exception object node is a begin node, i.e., it can be used as an anchor for + * other nodes, thus we need to re-route them to a valid anchor, i.e. the begin node + * of the unwind block. + */ + assert obj.usages().filter(x -> x instanceof GuardedNode && ((GuardedNode) x).getGuard() == obj).count() == 0 : "Must not have guards attached to an exception object node"; + AbstractBeginNode replacementAnchor = AbstractBeginNode.prevBegin(unwindNode); + assert replacementAnchor != null; + obj.replaceAtUsages(InputType.Anchor, replacementAnchor); + obj.replaceAtUsages(InputType.Value, unwindNode.exception()); + Node n = obj.next(); obj.setNext(null); unwindNode.replaceAndDelete(n); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, 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 @@ -208,8 +208,10 @@ FixedNode exceptionSux = exceptionEdge.next(); graph.addBeforeFixed(exceptionSux, exceptionMerge); exceptionObjectPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(JavaKind.Object), exceptionMerge)); - exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, JavaKind.Object, new JavaKind[]{JavaKind.Object}, - new ValueNode[]{exceptionObjectPhi})); + + assert exceptionEdge.stateAfter().bci == invoke.bci(); + assert exceptionEdge.stateAfter().rethrowException(); + exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(JavaKind.Object, JavaKind.Object, exceptionObjectPhi)); } // create one separate block for each invoked method @@ -396,7 +398,7 @@ JavaKind kind = invoke.asNode().getStackKind(); if (kind != JavaKind.Void) { FrameState stateAfter = invoke.stateAfter(); - stateAfter = stateAfter.duplicate(stateAfter.bci); + stateAfter = stateAfter.duplicate(); stateAfter.replaceFirstInput(invoke.asNode(), result.asNode()); result.setStateAfter(stateAfter); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java Thu Oct 31 14:23:06 2019 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -/* - * 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 - * 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.phases.schedule; - -import java.util.List; - -import jdk.internal.vm.compiler.collections.EconomicSet; -import jdk.internal.vm.compiler.collections.Equivalence; -import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.core.common.cfg.Loop; -import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.nodes.AbstractBeginNode; -import org.graalvm.compiler.nodes.AbstractMergeNode; -import org.graalvm.compiler.nodes.LoopBeginNode; -import org.graalvm.compiler.nodes.PhiNode; -import org.graalvm.compiler.nodes.cfg.Block; -import org.graalvm.compiler.nodes.cfg.HIRLoop; -import org.graalvm.compiler.nodes.memory.FloatingReadNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -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 jdk.internal.vm.compiler.word.LocationIdentity; - -public final class MemoryScheduleVerification extends BlockIteratorClosure> { - - private final BlockMap> blockToNodesMap; - - public static boolean check(Block startBlock, BlockMap> blockToNodesMap) { - ReentrantBlockIterator.apply(new MemoryScheduleVerification(blockToNodesMap), startBlock); - return true; - } - - private MemoryScheduleVerification(BlockMap> blockToNodesMap) { - this.blockToNodesMap = blockToNodesMap; - } - - @Override - protected EconomicSet getInitialState() { - return EconomicSet.create(Equivalence.IDENTITY); - } - - @Override - protected EconomicSet processBlock(Block block, EconomicSet currentState) { - AbstractBeginNode beginNode = block.getBeginNode(); - if (beginNode instanceof AbstractMergeNode) { - AbstractMergeNode abstractMergeNode = (AbstractMergeNode) beginNode; - for (PhiNode phi : abstractMergeNode.phis()) { - if (phi instanceof MemoryPhiNode) { - MemoryPhiNode memoryPhiNode = (MemoryPhiNode) phi; - addFloatingReadUsages(currentState, memoryPhiNode); - } - } - } - for (Node n : blockToNodesMap.get(block)) { - if (n instanceof MemoryCheckpoint) { - if (n instanceof MemoryCheckpoint.Single) { - MemoryCheckpoint.Single single = (MemoryCheckpoint.Single) n; - processLocation(n, single.getLocationIdentity(), currentState); - } else if (n instanceof MemoryCheckpoint.Multi) { - MemoryCheckpoint.Multi multi = (MemoryCheckpoint.Multi) n; - for (LocationIdentity location : multi.getLocationIdentities()) { - processLocation(n, location, currentState); - } - } - - addFloatingReadUsages(currentState, n); - } else if (n instanceof MemoryNode) { - addFloatingReadUsages(currentState, n); - } else if (n instanceof FloatingReadNode) { - FloatingReadNode floatingReadNode = (FloatingReadNode) n; - if (floatingReadNode.getLastLocationAccess() != null && floatingReadNode.getLocationIdentity().isMutable()) { - if (currentState.contains(floatingReadNode)) { - // Floating read was found in the state. - currentState.remove(floatingReadNode); - } else { - throw new RuntimeException("Floating read node " + n + " was not found in the state, i.e., it was killed by a memory check point before its place in the schedule. Block=" + - block + ", block begin: " + block.getBeginNode() + " block loop: " + block.getLoop() + ", " + blockToNodesMap.get(block).get(0)); - } - } - - } - } - return currentState; - } - - private static void addFloatingReadUsages(EconomicSet currentState, Node n) { - for (FloatingReadNode read : n.usages().filter(FloatingReadNode.class)) { - if (read.getLastLocationAccess() == n && read.getLocationIdentity().isMutable()) { - currentState.add(read); - } - } - } - - private void processLocation(Node n, LocationIdentity location, EconomicSet currentState) { - assert n != null; - if (location.isImmutable()) { - return; - } - - for (FloatingReadNode r : cloneState(currentState)) { - if (r.getLocationIdentity().overlaps(location)) { - // This read is killed by this location. - r.getDebug().log(DebugContext.VERBOSE_LEVEL, "%s removing %s from state", n, r); - currentState.remove(r); - } - } - } - - @Override - protected EconomicSet merge(Block merge, List> states) { - EconomicSet result = states.get(0); - for (int i = 1; i < states.size(); ++i) { - result.retainAll(states.get(i)); - } - return result; - } - - @Override - protected EconomicSet cloneState(EconomicSet oldState) { - EconomicSet result = EconomicSet.create(Equivalence.IDENTITY); - if (oldState != null) { - result.addAll(oldState); - } - return result; - } - - @Override - protected List> processLoop(Loop loop, EconomicSet initialState) { - HIRLoop l = (HIRLoop) loop; - for (MemoryPhiNode memoryPhi : ((LoopBeginNode) l.getHeader().getBeginNode()).memoryPhis()) { - for (FloatingReadNode r : cloneState(initialState)) { - if (r.getLocationIdentity().overlaps(memoryPhi.getLocationIdentity())) { - initialState.remove(r); - } - } - } - return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates; - } -} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java Thu Oct 31 16:54:16 2019 -0700 @@ -206,7 +206,8 @@ sortNodesLatestWithinBlock(cfg, earliestBlockToNodesMap, latestBlockToNodesMap, currentNodeMap, watchListMap, visited); assert verifySchedule(cfg, latestBlockToNodesMap, currentNodeMap); - assert (!Assertions.detailedAssertionsEnabled(graph.getOptions())) || MemoryScheduleVerification.check(cfg.getStartBlock(), latestBlockToNodesMap); + assert (!Assertions.detailedAssertionsEnabled(graph.getOptions())) || + ScheduleVerification.check(cfg.getStartBlock(), latestBlockToNodesMap, currentNodeMap); this.blockToNodesMap = latestBlockToNodesMap; @@ -358,7 +359,7 @@ } if (lastBlock.getBeginNode() instanceof KillingBeginNode) { - LocationIdentity locationIdentity = ((KillingBeginNode) lastBlock.getBeginNode()).getLocationIdentity(); + LocationIdentity locationIdentity = ((KillingBeginNode) lastBlock.getBeginNode()).getKilledLocationIdentity(); if ((locationIdentity.isAny() || locationIdentity.equals(location)) && lastBlock != earliestBlock) { // The begin of this block kills the location, so we *have* to schedule the node // in the dominating block. @@ -374,13 +375,13 @@ for (Node n : subList) { // Check if this node kills a node in the watch list. if (n instanceof MemoryCheckpoint.Single) { - LocationIdentity identity = ((MemoryCheckpoint.Single) n).getLocationIdentity(); + LocationIdentity identity = ((MemoryCheckpoint.Single) n).getKilledLocationIdentity(); killed.add(identity); if (killed.isAny()) { return; } } else if (n instanceof MemoryCheckpoint.Multi) { - for (LocationIdentity identity : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) { + for (LocationIdentity identity : ((MemoryCheckpoint.Multi) n).getKilledLocationIdentities()) { killed.add(identity); if (killed.isAny()) { return; @@ -471,10 +472,10 @@ if (watchList != null && !watchList.isEmpty()) { // Check if this node kills a node in the watch list. if (n instanceof MemoryCheckpoint.Single) { - LocationIdentity identity = ((MemoryCheckpoint.Single) n).getLocationIdentity(); + LocationIdentity identity = ((MemoryCheckpoint.Single) n).getKilledLocationIdentity(); checkWatchList(watchList, identity, b, result, nodeMap, unprocessed); } else if (n instanceof MemoryCheckpoint.Multi) { - for (LocationIdentity identity : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) { + for (LocationIdentity identity : ((MemoryCheckpoint.Multi) n).getKilledLocationIdentities()) { checkWatchList(watchList, identity, b, result, nodeMap, unprocessed); } } @@ -896,7 +897,7 @@ } } - assert (!Assertions.detailedAssertionsEnabled(cfg.graph.getOptions())) || MemoryScheduleVerification.check(cfg.getStartBlock(), blockToNodes); + assert (!Assertions.detailedAssertionsEnabled(cfg.graph.getOptions())) || ScheduleVerification.check(cfg.getStartBlock(), blockToNodes, nodeToBlock); } private static void processNodes(NodeBitMap visited, NodeMap entries, NodeStack stack, MicroBlock startBlock, Iterable nodes) { @@ -1183,10 +1184,10 @@ Formatter buf = new Formatter(); buf.format("%s", n); if (n instanceof MemoryCheckpoint.Single) { - buf.format(" // kills %s", ((MemoryCheckpoint.Single) n).getLocationIdentity()); + buf.format(" // kills %s", ((MemoryCheckpoint.Single) n).getKilledLocationIdentity()); } else if (n instanceof MemoryCheckpoint.Multi) { buf.format(" // kills "); - for (LocationIdentity locid : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) { + for (LocationIdentity locid : ((MemoryCheckpoint.Multi) n).getKilledLocationIdentities()) { buf.format("%s, ", locid); } } else if (n instanceof FloatingReadNode) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/ScheduleVerification.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/ScheduleVerification.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2015, 2019, 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.phases.schedule; + +import java.util.List; + +import jdk.internal.vm.compiler.collections.EconomicSet; +import jdk.internal.vm.compiler.collections.Equivalence; +import org.graalvm.compiler.core.common.cfg.BlockMap; +import org.graalvm.compiler.core.common.cfg.Loop; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeMap; +import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.AbstractMergeNode; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.LoopExitNode; +import org.graalvm.compiler.nodes.MemoryProxyNode; +import org.graalvm.compiler.nodes.PhiNode; +import org.graalvm.compiler.nodes.ProxyNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.VirtualState; +import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRLoop; +import org.graalvm.compiler.nodes.memory.FloatingReadNode; +import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; +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 jdk.internal.vm.compiler.word.LocationIdentity; + +/** + * Verifies that the schedule of the graph is correct. Checks that floating reads are not killed + * between definition and usage. Also checks that there are no usages spanning loop exits without a + * proper proxy node. + */ +public final class ScheduleVerification extends BlockIteratorClosure> { + + private final BlockMap> blockToNodesMap; + private final NodeMap nodeMap; + private final StructuredGraph graph; + + public static boolean check(Block startBlock, BlockMap> blockToNodesMap, NodeMap nodeMap) { + ReentrantBlockIterator.apply(new ScheduleVerification(blockToNodesMap, nodeMap, startBlock.getBeginNode().graph()), startBlock); + return true; + } + + private ScheduleVerification(BlockMap> blockToNodesMap, NodeMap nodeMap, StructuredGraph graph) { + this.blockToNodesMap = blockToNodesMap; + this.nodeMap = nodeMap; + this.graph = graph; + } + + @Override + protected EconomicSet getInitialState() { + return EconomicSet.create(Equivalence.IDENTITY); + } + + @Override + protected EconomicSet processBlock(Block block, EconomicSet currentState) { + AbstractBeginNode beginNode = block.getBeginNode(); + if (beginNode instanceof AbstractMergeNode) { + AbstractMergeNode abstractMergeNode = (AbstractMergeNode) beginNode; + for (PhiNode phi : abstractMergeNode.phis()) { + if (phi instanceof MemoryPhiNode) { + MemoryPhiNode memoryPhiNode = (MemoryPhiNode) phi; + addFloatingReadUsages(currentState, memoryPhiNode); + } + } + } + if (beginNode instanceof LoopExitNode) { + LoopExitNode loopExitNode = (LoopExitNode) beginNode; + for (ProxyNode proxy : loopExitNode.proxies()) { + if (proxy instanceof MemoryProxyNode) { + MemoryProxyNode memoryProxyNode = (MemoryProxyNode) proxy; + addFloatingReadUsages(currentState, memoryProxyNode); + } + } + } + for (Node n : blockToNodesMap.get(block)) { + if (n instanceof MemoryCheckpoint) { + if (n instanceof MemoryCheckpoint.Single) { + MemoryCheckpoint.Single single = (MemoryCheckpoint.Single) n; + processLocation(n, single.getKilledLocationIdentity(), currentState); + } else if (n instanceof MemoryCheckpoint.Multi) { + MemoryCheckpoint.Multi multi = (MemoryCheckpoint.Multi) n; + for (LocationIdentity location : multi.getKilledLocationIdentities()) { + processLocation(n, location, currentState); + } + } + + addFloatingReadUsages(currentState, n); + } else if (n instanceof MemoryNode) { + addFloatingReadUsages(currentState, n); + } else if (n instanceof FloatingReadNode) { + FloatingReadNode floatingReadNode = (FloatingReadNode) n; + if (floatingReadNode.getLastLocationAccess() != null && floatingReadNode.getLocationIdentity().isMutable()) { + if (currentState.contains(floatingReadNode)) { + // Floating read was found in the state. + currentState.remove(floatingReadNode); + } else { + throw new RuntimeException("Floating read node " + n + " was not found in the state, i.e., it was killed by a memory check point before its place in the schedule. Block=" + + block + ", block begin: " + block.getBeginNode() + " block loop: " + block.getLoop() + ", " + blockToNodesMap.get(block).get(0)); + } + } + } + assert nodeMap.get(n) == block; + if (graph.hasValueProxies() && block.getLoop() != null && !(n instanceof VirtualState)) { + for (Node usage : n.usages()) { + Node usageNode = usage; + + if (usageNode instanceof PhiNode) { + PhiNode phiNode = (PhiNode) usage; + usageNode = phiNode.merge(); + } + + if (usageNode instanceof LoopExitNode) { + LoopExitNode loopExitNode = (LoopExitNode) usageNode; + if (loopExitNode.loopBegin() == n || loopExitNode.stateAfter() == n) { + continue; + } + } + Block usageBlock = nodeMap.get(usageNode); + + Loop usageLoop = null; + if (usageNode instanceof ProxyNode) { + ProxyNode proxyNode = (ProxyNode) usageNode; + usageLoop = nodeMap.get(proxyNode.proxyPoint().loopBegin()).getLoop(); + } else { + if (usageBlock.getBeginNode() instanceof LoopExitNode) { + // For nodes in the loop exit node block, we don't know for sure + // whether they are "in the loop" or not. It depends on whether + // one of their transient usages is a loop proxy node. + // For now, let's just assume those nodes are OK, i.e., "in the loop". + LoopExitNode loopExitNode = (LoopExitNode) usageBlock.getBeginNode(); + usageLoop = nodeMap.get(loopExitNode.loopBegin()).getLoop(); + } else { + usageLoop = usageBlock.getLoop(); + } + } + + assert usageLoop != null : n + ", " + nodeMap.get(n) + " / " + usageNode + ", " + nodeMap.get(usageNode); + while (usageLoop != block.getLoop() && usageLoop != null) { + usageLoop = usageLoop.getParent(); + } + assert usageLoop != null : n + ", " + usageNode + ", " + usageBlock + ", " + usageBlock.getLoop() + ", " + block + ", " + block.getLoop(); + } + } + } + return currentState; + } + + private static void addFloatingReadUsages(EconomicSet currentState, Node n) { + for (FloatingReadNode read : n.usages().filter(FloatingReadNode.class)) { + if (read.getLastLocationAccess() == n && read.getLocationIdentity().isMutable()) { + currentState.add(read); + } + } + } + + private void processLocation(Node n, LocationIdentity location, EconomicSet currentState) { + assert n != null; + if (location.isImmutable()) { + return; + } + + for (FloatingReadNode r : cloneState(currentState)) { + if (r.getLocationIdentity().overlaps(location)) { + // This read is killed by this location. + r.getDebug().log(DebugContext.VERBOSE_LEVEL, "%s removing %s from state", n, r); + currentState.remove(r); + } + } + } + + @Override + protected EconomicSet merge(Block merge, List> states) { + EconomicSet result = states.get(0); + for (int i = 1; i < states.size(); ++i) { + result.retainAll(states.get(i)); + } + return result; + } + + @Override + protected EconomicSet cloneState(EconomicSet oldState) { + EconomicSet result = EconomicSet.create(Equivalence.IDENTITY); + if (oldState != null) { + result.addAll(oldState); + } + return result; + } + + @Override + protected List> processLoop(Loop loop, EconomicSet initialState) { + HIRLoop l = (HIRLoop) loop; + for (MemoryPhiNode memoryPhi : ((LoopBeginNode) l.getHeader().getBeginNode()).memoryPhis()) { + for (FloatingReadNode r : cloneState(initialState)) { + if (r.getLocationIdentity().overlaps(memoryPhi.getLocationIdentity())) { + initialState.remove(r); + } + } + } + return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates; + } +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java Thu Oct 31 16:54:16 2019 -0700 @@ -32,7 +32,6 @@ import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN; import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN; -import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool.RoundingMode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; @@ -45,6 +44,7 @@ import org.graalvm.compiler.nodes.java.AtomicReadAndWriteNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; +import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.replacements.TargetGraphBuilderPlugins; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.FusedMultiplyAddNode; @@ -60,39 +60,39 @@ public class AArch64GraphBuilderPlugins implements TargetGraphBuilderPlugins { @Override - public void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, Architecture arch, boolean explicitUnsafeNullChecks, boolean registerMathPlugins, + public void register(Plugins plugins, Replacements replacements, Architecture arch, boolean explicitUnsafeNullChecks, boolean registerMathPlugins, boolean emitJDK9StringSubstitutions, boolean useFMAIntrinsics) { - register(plugins, replacementsBytecodeProvider, explicitUnsafeNullChecks, registerMathPlugins, emitJDK9StringSubstitutions, useFMAIntrinsics); + register(plugins, replacements, explicitUnsafeNullChecks, registerMathPlugins, emitJDK9StringSubstitutions, useFMAIntrinsics); } - public static void register(Plugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks, + public static void register(Plugins plugins, Replacements replacements, boolean explicitUnsafeNullChecks, boolean registerMathPlugins, boolean emitJDK9StringSubstitutions, boolean useFMAIntrinsics) { InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); invocationPlugins.defer(new Runnable() { @Override public void run() { - registerIntegerLongPlugins(invocationPlugins, JavaKind.Int, bytecodeProvider); - registerIntegerLongPlugins(invocationPlugins, JavaKind.Long, bytecodeProvider); + registerIntegerLongPlugins(invocationPlugins, JavaKind.Int, replacements); + registerIntegerLongPlugins(invocationPlugins, JavaKind.Long, replacements); if (registerMathPlugins) { registerMathPlugins(invocationPlugins, useFMAIntrinsics); } if (emitJDK9StringSubstitutions) { - registerStringLatin1Plugins(invocationPlugins, bytecodeProvider); - registerStringUTF16Plugins(invocationPlugins, bytecodeProvider); + registerStringLatin1Plugins(invocationPlugins, replacements); + registerStringUTF16Plugins(invocationPlugins, replacements); } - registerUnsafePlugins(invocationPlugins, bytecodeProvider); + registerUnsafePlugins(invocationPlugins, replacements); // This is temporarily disabled until we implement correct emitting of the CAS // instructions of the proper width. - registerPlatformSpecificUnsafePlugins(invocationPlugins, bytecodeProvider, explicitUnsafeNullChecks, + registerPlatformSpecificUnsafePlugins(invocationPlugins, replacements, explicitUnsafeNullChecks, new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}); } }); } - private static void registerIntegerLongPlugins(InvocationPlugins plugins, JavaKind kind, BytecodeProvider bytecodeProvider) { + private static void registerIntegerLongPlugins(InvocationPlugins plugins, JavaKind kind, Replacements replacements) { Class declaringClass = kind.toBoxedJavaClass(); Class type = kind.toJavaClass(); - Registration r = new Registration(plugins, declaringClass, bytecodeProvider); + Registration r = new Registration(plugins, declaringClass, replacements); r.register1("numberOfLeadingZeros", type, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { @@ -196,29 +196,29 @@ }); } - private static void registerStringLatin1Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) { + private static void registerStringLatin1Plugins(InvocationPlugins plugins, Replacements replacements) { if (JavaVersionUtil.JAVA_SPEC >= 9) { - Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider); + Registration r = new Registration(plugins, "java.lang.StringLatin1", replacements); r.setAllowOverwrite(true); r.registerMethodSubstitution(AArch64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class); r.registerMethodSubstitution(AArch64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class); } } - private static void registerStringUTF16Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) { + private static void registerStringUTF16Plugins(InvocationPlugins plugins, Replacements replacements) { if (JavaVersionUtil.JAVA_SPEC >= 9) { - Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider); + Registration r = new Registration(plugins, "java.lang.StringUTF16", replacements); r.setAllowOverwrite(true); r.registerMethodSubstitution(AArch64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class); r.registerMethodSubstitution(AArch64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class); } } - private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) { + private static void registerUnsafePlugins(InvocationPlugins plugins, Replacements replacements) { registerUnsafePlugins(new Registration(plugins, Unsafe.class), new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}, "Object"); if (JavaVersionUtil.JAVA_SPEC > 8) { - registerUnsafePlugins(new Registration(plugins, "jdk.internal.misc.Unsafe", replacementsBytecodeProvider), + registerUnsafePlugins(new Registration(plugins, "jdk.internal.misc.Unsafe", replacements), new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}, JavaVersionUtil.JAVA_SPEC <= 11 ? "Object" : "Reference"); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountLeadingZerosNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountLeadingZerosNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountLeadingZerosNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -90,4 +90,10 @@ public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) { builder.setResult(this, ((AMD64ArithmeticLIRGeneratorTool) gen).emitCountLeadingZeros(builder.operand(getValue()))); } + + @NodeIntrinsic + public static native int countLeadingZeros(int i); + + @NodeIntrinsic + public static native int countLeadingZeros(long i); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountTrailingZerosNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountTrailingZerosNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64CountTrailingZerosNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -90,4 +90,10 @@ public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) { builder.setResult(this, ((AMD64ArithmeticLIRGeneratorTool) gen).emitCountTrailingZeros(builder.operand(getValue()))); } + + @NodeIntrinsic + public static native int countTrailingZeros(int i); + + @NodeIntrinsic + public static native int countTrailingZeros(long i); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java Thu Oct 31 16:54:16 2019 -0700 @@ -35,7 +35,6 @@ import java.util.Arrays; -import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool.RoundingMode; import org.graalvm.compiler.nodes.PauseNode; import org.graalvm.compiler.nodes.ValueNode; @@ -48,9 +47,8 @@ import org.graalvm.compiler.nodes.java.AtomicReadAndAddNode; import org.graalvm.compiler.nodes.java.AtomicReadAndWriteNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; +import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.replacements.ArraysSubstitutions; -import org.graalvm.compiler.replacements.IntegerSubstitutions; -import org.graalvm.compiler.replacements.LongSubstitutions; import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins.UnsafeAccessPlugin; import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins.UnsafeGetPlugin; import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins.UnsafePutPlugin; @@ -72,30 +70,31 @@ public class AMD64GraphBuilderPlugins implements TargetGraphBuilderPlugins { @Override - public void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, Architecture architecture, boolean explicitUnsafeNullChecks, + public void register(Plugins plugins, Replacements replacements, Architecture architecture, boolean explicitUnsafeNullChecks, boolean registerMathPlugins, boolean emitJDK9StringSubstitutions, boolean useFMAIntrinsics) { - register(plugins, replacementsBytecodeProvider, (AMD64) architecture, explicitUnsafeNullChecks, emitJDK9StringSubstitutions, useFMAIntrinsics); + register(plugins, replacements, (AMD64) architecture, explicitUnsafeNullChecks, emitJDK9StringSubstitutions, useFMAIntrinsics); } - public static void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, AMD64 arch, boolean explicitUnsafeNullChecks, boolean emitJDK9StringSubstitutions, + public static void register(Plugins plugins, Replacements replacements, AMD64 arch, boolean explicitUnsafeNullChecks, + boolean emitJDK9StringSubstitutions, boolean useFMAIntrinsics) { InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); invocationPlugins.defer(new Runnable() { @Override public void run() { registerThreadPlugins(invocationPlugins, arch); - registerIntegerLongPlugins(invocationPlugins, IntegerSubstitutions.class, JavaKind.Int, arch, replacementsBytecodeProvider); - registerIntegerLongPlugins(invocationPlugins, LongSubstitutions.class, JavaKind.Long, arch, replacementsBytecodeProvider); - registerPlatformSpecificUnsafePlugins(invocationPlugins, replacementsBytecodeProvider, explicitUnsafeNullChecks, + registerIntegerLongPlugins(invocationPlugins, AMD64IntegerSubstitutions.class, JavaKind.Int, arch, replacements); + registerIntegerLongPlugins(invocationPlugins, AMD64LongSubstitutions.class, JavaKind.Long, arch, replacements); + registerPlatformSpecificUnsafePlugins(invocationPlugins, replacements, explicitUnsafeNullChecks, new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object, JavaKind.Boolean, JavaKind.Byte, JavaKind.Short, JavaKind.Char, JavaKind.Float, JavaKind.Double}); - registerUnsafePlugins(invocationPlugins, replacementsBytecodeProvider, explicitUnsafeNullChecks); - registerStringPlugins(invocationPlugins, replacementsBytecodeProvider); + registerUnsafePlugins(invocationPlugins, replacements, explicitUnsafeNullChecks); + registerStringPlugins(invocationPlugins, replacements); if (emitJDK9StringSubstitutions) { - registerStringLatin1Plugins(invocationPlugins, replacementsBytecodeProvider); - registerStringUTF16Plugins(invocationPlugins, replacementsBytecodeProvider); + registerStringLatin1Plugins(invocationPlugins, replacements); + registerStringUTF16Plugins(invocationPlugins, replacements); } - registerMathPlugins(invocationPlugins, useFMAIntrinsics, arch, replacementsBytecodeProvider); - registerArraysEqualsPlugins(invocationPlugins, replacementsBytecodeProvider); + registerMathPlugins(invocationPlugins, useFMAIntrinsics, arch, replacements); + registerArraysEqualsPlugins(invocationPlugins, replacements); } }); } @@ -103,72 +102,37 @@ private static void registerThreadPlugins(InvocationPlugins plugins, AMD64 arch) { if (JavaVersionUtil.JAVA_SPEC > 8) { // Pause instruction introduced with SSE2 - if (arch.getFeatures().contains(AMD64.CPUFeature.SSE2)) { - Registration r = new Registration(plugins, Thread.class); - r.register0("onSpinWait", new InvocationPlugin() { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.append(new PauseNode()); - return true; - } - }); - } - } - } - - private static void registerIntegerLongPlugins(InvocationPlugins plugins, Class substituteDeclaringClass, JavaKind kind, AMD64 arch, BytecodeProvider bytecodeProvider) { - Class declaringClass = kind.toBoxedJavaClass(); - Class type = kind.toJavaClass(); - Registration r = new Registration(plugins, declaringClass, bytecodeProvider); - r.registerMethodSubstitution(substituteDeclaringClass, "numberOfLeadingZeros", type); - if (arch.getFeatures().contains(AMD64.CPUFeature.LZCNT) && arch.getFlags().contains(AMD64.Flag.UseCountLeadingZerosInstruction)) { - r.setAllowOverwrite(true); - r.register1("numberOfLeadingZeros", type, new InvocationPlugin() { + assert (arch.getFeatures().contains(AMD64.CPUFeature.SSE2)); + Registration r = new Registration(plugins, Thread.class); + r.register0("onSpinWait", new InvocationPlugin() { @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - ValueNode folded = AMD64CountLeadingZerosNode.tryFold(value); - if (folded != null) { - b.addPush(JavaKind.Int, folded); - } else { - b.addPush(JavaKind.Int, new AMD64CountLeadingZerosNode(value)); - } + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + b.append(new PauseNode()); return true; } }); } - - r.registerMethodSubstitution(substituteDeclaringClass, "numberOfTrailingZeros", type); - if (arch.getFeatures().contains(AMD64.CPUFeature.BMI1) && arch.getFlags().contains(AMD64.Flag.UseCountTrailingZerosInstruction)) { - r.setAllowOverwrite(true); - r.register1("numberOfTrailingZeros", type, new InvocationPlugin() { - - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - ValueNode folded = AMD64CountTrailingZerosNode.tryFold(value); - if (folded != null) { - b.addPush(JavaKind.Int, folded); - } else { - b.addPush(JavaKind.Int, new AMD64CountTrailingZerosNode(value)); - } - return true; - } - }); - } - - if (arch.getFeatures().contains(AMD64.CPUFeature.POPCNT)) { - r.register1("bitCount", type, new InvocationPlugin() { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.push(JavaKind.Int, b.append(new BitCountNode(value).canonical(null))); - return true; - } - }); - } - } - private static void registerMathPlugins(InvocationPlugins plugins, boolean useFMAIntrinsics, AMD64 arch, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins, Math.class, bytecodeProvider); + private static void registerIntegerLongPlugins(InvocationPlugins plugins, Class substituteDeclaringClass, JavaKind kind, AMD64 arch, Replacements replacements) { + Class declaringClass = kind.toBoxedJavaClass(); + Class type = kind.toJavaClass(); + Registration r = new Registration(plugins, declaringClass, replacements); + r.registerMethodSubstitution(substituteDeclaringClass, "numberOfLeadingZeros", type); + r.registerMethodSubstitution(substituteDeclaringClass, "numberOfTrailingZeros", type); + + r.registerConditional1(arch.getFeatures().contains(AMD64.CPUFeature.POPCNT), + "bitCount", type, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { + b.push(JavaKind.Int, b.append(new BitCountNode(value).canonical(null))); + return true; + } + }); + } + + private static void registerMathPlugins(InvocationPlugins plugins, boolean useFMAIntrinsics, AMD64 arch, Replacements replacements) { + Registration r = new Registration(plugins, Math.class, replacements); registerUnaryMath(r, "log", LOG); registerUnaryMath(r, "log10", LOG10); registerUnaryMath(r, "exp", EXP); @@ -177,19 +141,18 @@ registerUnaryMath(r, "cos", COS); registerUnaryMath(r, "tan", TAN); - if (arch.getFeatures().contains(CPUFeature.SSE4_1)) { - registerRound(r, "rint", RoundingMode.NEAREST); - registerRound(r, "ceil", RoundingMode.UP); - registerRound(r, "floor", RoundingMode.DOWN); - } + boolean roundEnabled = arch.getFeatures().contains(CPUFeature.SSE4_1); + registerRound(roundEnabled, r, "rint", RoundingMode.NEAREST); + registerRound(roundEnabled, r, "ceil", RoundingMode.UP); + registerRound(roundEnabled, r, "floor", RoundingMode.DOWN); - if (useFMAIntrinsics && JavaVersionUtil.JAVA_SPEC > 8 && arch.getFeatures().contains(CPUFeature.FMA)) { - registerFMA(r); + if (JavaVersionUtil.JAVA_SPEC > 8) { + registerFMA(r, useFMAIntrinsics && arch.getFeatures().contains(CPUFeature.FMA)); } } - private static void registerFMA(Registration r) { - r.register3("fma", + private static void registerFMA(Registration r, boolean isEnabled) { + r.registerConditional3(isEnabled, "fma", Double.TYPE, Double.TYPE, Double.TYPE, @@ -205,7 +168,7 @@ return true; } }); - r.register3("fma", + r.registerConditional3(isEnabled, "fma", Float.TYPE, Float.TYPE, Float.TYPE, @@ -243,8 +206,8 @@ }); } - private static void registerRound(Registration r, String name, RoundingMode mode) { - r.register1(name, Double.TYPE, new InvocationPlugin() { + private static void registerRound(boolean isEnabled, Registration r, String name, RoundingMode mode) { + r.registerConditional1(isEnabled, name, Double.TYPE, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { b.push(JavaKind.Double, b.append(new AMD64RoundNode(arg, mode))); @@ -253,10 +216,10 @@ }); } - private static void registerStringPlugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) { + private static void registerStringPlugins(InvocationPlugins plugins, Replacements replacements) { if (JavaVersionUtil.JAVA_SPEC <= 8) { Registration r; - r = new Registration(plugins, String.class, replacementsBytecodeProvider); + r = new Registration(plugins, String.class, replacements); r.setAllowOverwrite(true); r.registerMethodSubstitution(AMD64StringSubstitutions.class, "indexOf", char[].class, int.class, int.class, char[].class, int.class, int.class, int.class); @@ -265,8 +228,8 @@ } } - private static void registerStringLatin1Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) { - Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider); + private static void registerStringLatin1Plugins(InvocationPlugins plugins, Replacements replacements) { + Registration r = new Registration(plugins, "java.lang.StringLatin1", replacements); r.setAllowOverwrite(true); r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class); r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class); @@ -276,8 +239,8 @@ r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class); } - private static void registerStringUTF16Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) { - Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider); + private static void registerStringUTF16Plugins(InvocationPlugins plugins, Replacements replacements) { + Registration r = new Registration(plugins, "java.lang.StringUTF16", replacements); r.setAllowOverwrite(true); r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class); r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class); @@ -288,10 +251,10 @@ r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class); } - private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider, boolean explicitUnsafeNullChecks) { + private static void registerUnsafePlugins(InvocationPlugins plugins, Replacements replacements, boolean explicitUnsafeNullChecks) { registerUnsafePlugins(new Registration(plugins, Unsafe.class), explicitUnsafeNullChecks, new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}, true); if (JavaVersionUtil.JAVA_SPEC > 8) { - registerUnsafePlugins(new Registration(plugins, "jdk.internal.misc.Unsafe", replacementsBytecodeProvider), explicitUnsafeNullChecks, + registerUnsafePlugins(new Registration(plugins, "jdk.internal.misc.Unsafe", replacements), explicitUnsafeNullChecks, new JavaKind[]{JavaKind.Boolean, JavaKind.Byte, JavaKind.Char, JavaKind.Short, JavaKind.Int, JavaKind.Long, JavaKind.Object}, JavaVersionUtil.JAVA_SPEC <= 11); } @@ -330,8 +293,8 @@ } } - private static void registerArraysEqualsPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins, Arrays.class, bytecodeProvider); + private static void registerArraysEqualsPlugins(InvocationPlugins plugins, Replacements replacements) { + Registration r = new Registration(plugins, Arrays.class, replacements); r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", float[].class, float[].class); r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", double[].class, double[].class); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64IntegerSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64IntegerSubstitutions.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019, 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.amd64; + +import static org.graalvm.compiler.replacements.NodeIntrinsificationProvider.INJECTED_TARGET; + +import org.graalvm.compiler.api.replacements.ClassSubstitution; +import org.graalvm.compiler.api.replacements.Fold; +import org.graalvm.compiler.api.replacements.MethodSubstitution; +import org.graalvm.compiler.core.common.SuppressFBWarnings; +import org.graalvm.compiler.replacements.nodes.BitScanForwardNode; +import org.graalvm.compiler.replacements.nodes.BitScanReverseNode; + +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.code.TargetDescription; + +@ClassSubstitution(Integer.class) +public class AMD64IntegerSubstitutions { + + @Fold + static boolean lzcnt(@Fold.InjectedParameter TargetDescription target) { + AMD64 arch = (AMD64) target.arch; + return arch.getFeatures().contains(AMD64.CPUFeature.LZCNT) && arch.getFlags().contains(AMD64.Flag.UseCountLeadingZerosInstruction); + } + + @Fold + static boolean tzcnt(@Fold.InjectedParameter TargetDescription target) { + AMD64 arch = (AMD64) target.arch; + return arch.getFeatures().contains(AMD64.CPUFeature.BMI1) && arch.getFlags().contains(AMD64.Flag.UseCountTrailingZerosInstruction); + } + + @MethodSubstitution + @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected") + public static int numberOfLeadingZeros(int i) { + if (lzcnt(INJECTED_TARGET)) { + return AMD64CountLeadingZerosNode.countLeadingZeros(i); + } + if (i == 0) { + return 32; + } + return 31 - BitScanReverseNode.unsafeScan(i); + } + + @MethodSubstitution + @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected") + public static int numberOfTrailingZeros(int i) { + if (tzcnt(INJECTED_TARGET)) { + return AMD64CountTrailingZerosNode.countTrailingZeros(i); + } + if (i == 0) { + return 32; + } + return BitScanForwardNode.unsafeScan(i); + } +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64LongSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64LongSubstitutions.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2019, 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.amd64; + +// JaCoCo Exclude + +import static org.graalvm.compiler.replacements.NodeIntrinsificationProvider.INJECTED_TARGET; + +import org.graalvm.compiler.api.replacements.ClassSubstitution; +import org.graalvm.compiler.api.replacements.Fold; +import org.graalvm.compiler.api.replacements.MethodSubstitution; +import org.graalvm.compiler.core.common.SuppressFBWarnings; +import org.graalvm.compiler.replacements.nodes.BitScanForwardNode; +import org.graalvm.compiler.replacements.nodes.BitScanReverseNode; + +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.code.TargetDescription; + +@ClassSubstitution(Long.class) +public class AMD64LongSubstitutions { + + @Fold + static boolean lzcnt(@Fold.InjectedParameter TargetDescription target) { + AMD64 arch = (AMD64) target.arch; + return arch.getFeatures().contains(AMD64.CPUFeature.LZCNT) && arch.getFlags().contains(AMD64.Flag.UseCountLeadingZerosInstruction); + } + + @Fold + static boolean tzcnt(@Fold.InjectedParameter TargetDescription target) { + AMD64 arch = (AMD64) target.arch; + return arch.getFeatures().contains(AMD64.CPUFeature.BMI1) && arch.getFlags().contains(AMD64.Flag.UseCountTrailingZerosInstruction); + } + + @MethodSubstitution + @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected") + public static int numberOfLeadingZeros(long i) { + if (lzcnt(INJECTED_TARGET)) { + return AMD64CountLeadingZerosNode.countLeadingZeros(i); + } + if (i == 0) { + return 64; + } + return 63 - BitScanReverseNode.unsafeScan(i); + } + + @MethodSubstitution + @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected") + public static int numberOfTrailingZeros(long i) { + if (tzcnt(INJECTED_TARGET)) { + return AMD64CountTrailingZerosNode.countTrailingZeros(i); + } + + if (i == 0) { + return 64; + } + return BitScanForwardNode.unsafeScan(i); + } +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringLatin1InflateNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringLatin1InflateNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringLatin1InflateNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -82,7 +82,7 @@ } @Override - public LocationIdentity[] getLocationIdentities() { + public LocationIdentity[] getKilledLocationIdentities() { // Model write access via 'dst' using: return new LocationIdentity[]{NamedLocationIdentity.getArrayLocation(writeKind)}; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16CompressNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16CompressNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16CompressNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -82,7 +82,7 @@ } @Override - public LocationIdentity[] getLocationIdentities() { + public LocationIdentity[] getKilledLocationIdentities() { // Model write access via 'dst' using: return new LocationIdentity[]{NamedLocationIdentity.getArrayLocation(JavaKind.Byte)}; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.jdk9.test/src/org/graalvm/compiler/replacements/jdk9/test/VarHandleTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.jdk9.test/src/org/graalvm/compiler/replacements/jdk9/test/VarHandleTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.jdk9.test/src/org/graalvm/compiler/replacements/jdk9/test/VarHandleTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -162,12 +162,12 @@ startNodes++; } else if (n instanceof MemoryCheckpoint.Single) { MemoryCheckpoint.Single single = (MemoryCheckpoint.Single) n; - if (single.getLocationIdentity().isAny()) { + if (single.getKilledLocationIdentity().isAny()) { anyKillCount++; } } else if (n instanceof MemoryCheckpoint.Multi) { MemoryCheckpoint.Multi multi = (MemoryCheckpoint.Multi) n; - for (LocationIdentity loc : multi.getLocationIdentities()) { + for (LocationIdentity loc : multi.getKilledLocationIdentities()) { if (loc.isAny()) { anyKillCount++; break; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.sparc/src/org/graalvm/compiler/replacements/sparc/SPARCGraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.sparc/src/org/graalvm/compiler/replacements/sparc/SPARCGraphBuilderPlugins.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.sparc/src/org/graalvm/compiler/replacements/sparc/SPARCGraphBuilderPlugins.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -32,13 +32,13 @@ import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN; import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN; -import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; +import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.replacements.IntegerSubstitutions; import org.graalvm.compiler.replacements.LongSubstitutions; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; @@ -51,26 +51,26 @@ public class SPARCGraphBuilderPlugins { - public static void register(Plugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks) { + public static void register(Plugins plugins, Replacements replacements, boolean explicitUnsafeNullChecks) { InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); invocationPlugins.defer(new Runnable() { @Override public void run() { - registerIntegerLongPlugins(invocationPlugins, IntegerSubstitutions.class, JavaKind.Int, bytecodeProvider); - registerIntegerLongPlugins(invocationPlugins, LongSubstitutions.class, JavaKind.Long, bytecodeProvider); + registerIntegerLongPlugins(invocationPlugins, IntegerSubstitutions.class, JavaKind.Int, replacements); + registerIntegerLongPlugins(invocationPlugins, LongSubstitutions.class, JavaKind.Long, replacements); registerMathPlugins(invocationPlugins); // This is temporarily disabled until we implement correct emitting of the CAS // instructions of the proper width. - registerPlatformSpecificUnsafePlugins(invocationPlugins, bytecodeProvider, explicitUnsafeNullChecks, + registerPlatformSpecificUnsafePlugins(invocationPlugins, replacements, explicitUnsafeNullChecks, new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}); } }); } - private static void registerIntegerLongPlugins(InvocationPlugins plugins, Class substituteDeclaringClass, JavaKind kind, BytecodeProvider bytecodeProvider) { + private static void registerIntegerLongPlugins(InvocationPlugins plugins, Class substituteDeclaringClass, JavaKind kind, Replacements replacements) { Class declaringClass = kind.toBoxedJavaClass(); Class type = kind.toJavaClass(); - Registration r = new Registration(plugins, declaringClass, bytecodeProvider); + Registration r = new Registration(plugins, declaringClass, replacements); r.registerMethodSubstitution(substituteDeclaringClass, "numberOfLeadingZeros", type); r.registerMethodSubstitution(substituteDeclaringClass, "numberOfTrailingZeros", type); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ArraysSubstitutionsTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ArraysSubstitutionsTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ArraysSubstitutionsTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -31,7 +31,6 @@ import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; @@ -132,7 +131,7 @@ StructuredGraph graph = parseEager("testCanonicalLengthSnippet", AllowAssumptions.NO); HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); createInliningPhase().apply(graph, context); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0); } @@ -148,7 +147,7 @@ StructuredGraph graph = parseEager("testCanonicalEqualSnippet", AllowAssumptions.NO); HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); createInliningPhase().apply(graph, context); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1); } @@ -162,9 +161,9 @@ StructuredGraph graph = parseEager("testVirtualEqualSnippet", AllowAssumptions.NO); HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); createInliningPhase().apply(graph, context); - new CanonicalizerPhase().apply(graph, getProviders()); - new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); + new PartialEscapePhase(false, this.createCanonicalizerPhase(), graph.getOptions()).apply(graph, context); + createCanonicalizerPhase().apply(graph, getProviders()); Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1); } @@ -180,9 +179,9 @@ StructuredGraph graph = parseEager("testVirtualNotEqualSnippet", AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); createInliningPhase().apply(graph, context); - new CanonicalizerPhase().apply(graph, getProviders()); - new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); - new CanonicalizerPhase().apply(graph, getProviders()); + createCanonicalizerPhase().apply(graph, getProviders()); + new PartialEscapePhase(false, this.createCanonicalizerPhase(), graph.getOptions()).apply(graph, context); + createCanonicalizerPhase().apply(graph, getProviders()); Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BitOpNodesTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BitOpNodesTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BitOpNodesTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -303,7 +303,7 @@ private ValueNode parseAndInline(String name, Class expectedClass) { StructuredGraph graph = parseEager(name, AllowAssumptions.YES); HighTierContext context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); canonicalizer.apply(graph, context); createInliningPhase(canonicalizer).apply(graph, context); canonicalizer.apply(graph, context); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DeoptimizeOnExceptionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DeoptimizeOnExceptionTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DeoptimizeOnExceptionTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -35,7 +35,7 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.AbstractInliningPhase; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; -import org.graalvm.compiler.test.ExportingClassLoader; +import org.graalvm.compiler.api.test.ExportingClassLoader; import org.junit.Assert; import org.junit.Assume; import org.junit.Test; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/EdgesTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/EdgesTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/EdgesTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, 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 @@ -45,7 +45,6 @@ import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.common.inlining.policy.InlineMethodSubstitutionsPolicy; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -133,8 +132,8 @@ ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method); StructuredGraph g = parseProfiled(javaMethod, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); - new InliningPhase(new InlineMethodSubstitutionsPolicy(), new CanonicalizerPhase()).apply(g, context); - new CanonicalizerPhase().apply(g, context); + new InliningPhase(new InlineMethodSubstitutionsPolicy(), createCanonicalizerPhase()).apply(g, context); + this.createCanonicalizerPhase().apply(g, context); Assert.assertTrue(g.getNodes().filter(InstanceOfNode.class).isEmpty()); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -81,10 +81,10 @@ @Override protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { - InjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), null); + InjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), null, getTarget()); new PluginFactory_FoldTest().registerPlugins(invocationPlugins, injection); BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider(); - Registration r = new Registration(invocationPlugins, TestMethod.class, replacementBytecodeProvider); + Registration r = new Registration(invocationPlugins, TestMethod.class, getReplacements(), replacementBytecodeProvider); r.registerMethodSubstitution(TestMethodSubstitution.class, "test"); super.registerInvocationPlugins(invocationPlugins); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactFoldTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactFoldTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactFoldTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -94,7 +94,7 @@ Node originalNode = graph.getNodes().filter(x -> x instanceof IntegerExactArithmeticNode).first(); assertNotNull("original node must be in the graph", originalNode); - new CanonicalizerPhase().apply(graph, getDefaultHighTierContext()); + createCanonicalizerPhase().apply(graph, getDefaultHighTierContext()); ValueNode node = findNode(graph); boolean overflowExpected = node instanceof IntegerExactArithmeticNode; @@ -109,19 +109,19 @@ Node originalNode = graph.getNodes().filter(x -> x instanceof IntegerExactArithmeticNode).first(); assertNotNull("original node must be in the graph", originalNode); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); HighTierContext highTierContext = getDefaultHighTierContext(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext); MidTierContext midTierContext = getDefaultMidTierContext(); new GuardLoweringPhase().apply(graph, midTierContext); - new CanonicalizerPhase().apply(graph, midTierContext); + createCanonicalizerPhase().apply(graph, midTierContext); IntegerExactArithmeticSplitNode loweredNode = graph.getNodes().filter(IntegerExactArithmeticSplitNode.class).first(); assertNotNull("the lowered node must be in the graph", loweredNode); loweredNode.getX().setStamp(StampFactory.forInteger(bits, lowerBoundA, upperBoundA)); loweredNode.getY().setStamp(StampFactory.forInteger(bits, lowerBoundB, upperBoundB)); - new CanonicalizerPhase().apply(graph, midTierContext); + createCanonicalizerPhase().apply(graph, midTierContext); ValueNode node = findNode(graph); boolean overflowExpected = node instanceof IntegerExactArithmeticSplitNode; @@ -144,7 +144,7 @@ String snippet = "snippetInt" + bits; StructuredGraph graph = parseEager(getResolvedJavaMethod(operation.getClass(), snippet), AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); return graph; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -25,6 +25,7 @@ package org.graalvm.compiler.replacements.test; import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.core.test.GraalCompilerTest; @@ -35,7 +36,6 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -78,14 +78,14 @@ debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); createInliningPhase().apply(graph, context); debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); - new CanonicalizerPhase().apply(graph, context); + createCanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); // Try to ensure any macro nodes are lowered to expose any resulting invokes if (graph.getNodes().filter(MacroNode.class).isNotEmpty()) { - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new LoweringPhase(this.createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); } if (graph.getNodes().filter(MacroNode.class).isNotEmpty()) { - new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, context); + new LoweringPhase(this.createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, context); } assertNotInGraph(graph, MacroNode.class); if (name != null) { @@ -153,13 +153,20 @@ } } - protected static StructuredGraph assertInGraph(StructuredGraph graph, Class clazz) { + protected static StructuredGraph assertInGraph(StructuredGraph graph, Class... clazzes) { for (Node node : graph.getNodes()) { - if (clazz.isInstance(node)) { - return graph; + for (Class clazz : clazzes) { + if (clazz.isInstance(node)) { + return graph; + } } } - fail("Graph does not contain a node of class " + clazz.getName()); + if (clazzes.length == 1) { + fail("Graph does not contain a node of class " + clazzes[0].getName()); + } else { + fail("Graph does not contain a node of one these classes class " + Arrays.toString(clazzes)); + + } return graph; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ObjectAccessTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ObjectAccessTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ObjectAccessTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, 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 @@ -130,7 +130,7 @@ Assert.assertEquals(graph.getParameter(0), address.getBase()); Assert.assertEquals(BytecodeFrame.AFTER_BCI, write.stateAfter().bci); - Assert.assertEquals(locationIdentity, write.getLocationIdentity()); + Assert.assertEquals(locationIdentity, write.getKilledLocationIdentity()); if (indexConvert) { SignExtendNode convert = (SignExtendNode) address.getOffset(); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -46,7 +46,6 @@ import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.replacements.CachingPEGraphDecoder; import jdk.internal.vm.compiler.word.LocationIdentity; import org.junit.Test; @@ -146,7 +145,7 @@ targetGraph.verify(); CoreProviders context = getProviders(); - new CanonicalizerPhase().apply(targetGraph, context); + createCanonicalizerPhase().apply(targetGraph, context); targetGraph.verify(); } catch (Throwable ex) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, 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 @@ -37,7 +37,6 @@ import org.graalvm.compiler.nodes.extended.JavaWriteNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordCastNode; @@ -150,7 +149,7 @@ Assert.assertEquals(graph.getParameter(0), cast.getInput()); Assert.assertEquals(target.wordJavaKind, cast.stamp(NodeView.DEFAULT).getStackKind()); - Assert.assertEquals(locationIdentity, write.getLocationIdentity()); + Assert.assertEquals(locationIdentity, write.getKilledLocationIdentity()); if (indexConvert) { SignExtendNode convert = (SignExtendNode) address.getOffset(); @@ -409,7 +408,7 @@ HighTierContext context = new HighTierContext(getProviders(), null, OptimisticOptimizations.ALL); StructuredGraph graph = parseEager(snippetName, AllowAssumptions.YES); - new CanonicalizerPhase().apply(graph, context); + this.createCanonicalizerPhase().apply(graph, context); Assert.assertEquals(expectedWordCasts, graph.getNodes().filter(WordCastNode.class).count()); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -318,7 +318,7 @@ @Override protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider(); - Registration r = new Registration(invocationPlugins, TestObject.class, replacementBytecodeProvider); + Registration r = new Registration(invocationPlugins, TestObject.class, getReplacements(), replacementBytecodeProvider); NodeIntrinsicPluginFactory.InjectionProvider injections = new DummyInjectionProvider(); new PluginFactory_ReplacementsParseTest().registerPlugins(invocationPlugins, injections); r.registerMethodSubstitution(TestObjectSubstitutions.class, "nextAfter", double.class, double.class); @@ -634,7 +634,7 @@ node.remove(); } HighTierContext context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); canonicalizer.apply(graph, context); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -31,6 +31,8 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.calc.AbsNode; import org.graalvm.compiler.nodes.calc.ReinterpretNode; +import org.graalvm.compiler.replacements.amd64.AMD64CountLeadingZerosNode; +import org.graalvm.compiler.replacements.amd64.AMD64CountTrailingZerosNode; import org.graalvm.compiler.replacements.nodes.BitCountNode; import org.graalvm.compiler.replacements.nodes.BitScanForwardNode; import org.graalvm.compiler.replacements.nodes.BitScanReverseNode; @@ -132,7 +134,7 @@ return Math.sqrt(value) + Math.log(value) + Math.log10(value) + Math.sin(value) + Math.cos(value) + Math.tan(value); } - public void testSubstitution(String testMethodName, Class intrinsicClass, Class holder, String methodName, boolean optional, Object... args) { + public void testSubstitution(String testMethodName, Class holder, String methodName, boolean optional, Object[] args, Class... intrinsicClasses) { ResolvedJavaMethod realJavaMethod = getResolvedJavaMethod(holder, methodName); ResolvedJavaMethod testJavaMethod = getResolvedJavaMethod(testMethodName); StructuredGraph graph = testGraph(testMethodName); @@ -140,7 +142,7 @@ // Check to see if the resulting graph contains the expected node StructuredGraph replacement = getReplacements().getSubstitution(realJavaMethod, -1, false, null, graph.getOptions()); if (replacement == null && !optional) { - assertInGraph(graph, intrinsicClass); + assertInGraph(graph, intrinsicClasses); } for (Object l : args) { @@ -159,7 +161,7 @@ public void testCharSubstitutions() { Object[] args = new Character[]{Character.MIN_VALUE, (char) -1, (char) 0, (char) 1, Character.MAX_VALUE}; - testSubstitution("charReverseBytes", ReverseBytesNode.class, Character.class, "reverseBytes", false, args); + testSubstitution("charReverseBytes", Character.class, "reverseBytes", false, args, ReverseBytesNode.class); } public static char charReverseBytes(char value) { @@ -183,7 +185,7 @@ public void testShortSubstitutions() { Object[] args = new Short[]{Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE}; - testSubstitution("shortReverseBytes", ReverseBytesNode.class, Short.class, "reverseBytes", false, args); + testSubstitution("shortReverseBytes", Short.class, "reverseBytes", false, args, ReverseBytesNode.class); } public static short shortReverseBytes(short value) { @@ -207,10 +209,10 @@ public void testIntegerSubstitutions() { Object[] args = new Object[]{Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE}; - testSubstitution("integerReverseBytes", ReverseBytesNode.class, Integer.class, "reverseBytes", false, args); - testSubstitution("integerNumberOfLeadingZeros", BitScanReverseNode.class, Integer.class, "numberOfLeadingZeros", true, args); - testSubstitution("integerNumberOfTrailingZeros", BitScanForwardNode.class, Integer.class, "numberOfTrailingZeros", false, args); - testSubstitution("integerBitCount", BitCountNode.class, Integer.class, "bitCount", true, args); + testSubstitution("integerReverseBytes", Integer.class, "reverseBytes", false, args, ReverseBytesNode.class); + testSubstitution("integerNumberOfLeadingZeros", Integer.class, "numberOfLeadingZeros", true, args, BitScanReverseNode.class, AMD64CountLeadingZerosNode.class); + testSubstitution("integerNumberOfTrailingZeros", Integer.class, "numberOfTrailingZeros", false, args, BitScanForwardNode.class, AMD64CountTrailingZerosNode.class); + testSubstitution("integerBitCount", Integer.class, "bitCount", true, args, BitCountNode.class); } public static int integerReverseBytes(int value) { @@ -233,10 +235,10 @@ public void testLongSubstitutions() { Object[] args = new Object[]{Long.MIN_VALUE, -1L, 0L, 1L, Long.MAX_VALUE}; - testSubstitution("longReverseBytes", ReverseBytesNode.class, Long.class, "reverseBytes", false, args); - testSubstitution("longNumberOfLeadingZeros", BitScanReverseNode.class, Long.class, "numberOfLeadingZeros", true, args); - testSubstitution("longNumberOfTrailingZeros", BitScanForwardNode.class, Long.class, "numberOfTrailingZeros", false, args); - testSubstitution("longBitCount", BitCountNode.class, Long.class, "bitCount", true, args); + testSubstitution("longReverseBytes", Long.class, "reverseBytes", false, args, ReverseBytesNode.class); + testSubstitution("longNumberOfLeadingZeros", Long.class, "numberOfLeadingZeros", true, args, BitScanReverseNode.class, AMD64CountLeadingZerosNode.class); + testSubstitution("longNumberOfTrailingZeros", Long.class, "numberOfTrailingZeros", false, args, BitScanForwardNode.class, AMD64CountTrailingZerosNode.class); + testSubstitution("longBitCount", Long.class, "bitCount", true, args, BitCountNode.class); } public static long longReverseBytes(long value) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -84,7 +84,7 @@ protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { new PluginFactory_SubstitutionNodeSourcePositionTest().registerPlugins(invocationPlugins, null); ClassfileBytecodeProvider bytecodeProvider = getSystemClassLoaderBytecodeProvider(); - InvocationPlugins.Registration r = new InvocationPlugins.Registration(invocationPlugins, TestMethod.class, bytecodeProvider); + InvocationPlugins.Registration r = new InvocationPlugins.Registration(invocationPlugins, TestMethod.class, getReplacements(), bytecodeProvider); r.registerMethodSubstitution(TestMethodSubstitution.class, "test", int.class); super.registerInvocationPlugins(invocationPlugins); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionsTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionsTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionsTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -120,7 +120,7 @@ protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { new PluginFactory_SubstitutionsTest().registerPlugins(invocationPlugins, null); ClassfileBytecodeProvider bytecodeProvider = getSystemClassLoaderBytecodeProvider(); - Registration r = new Registration(invocationPlugins, TestMethod.class, bytecodeProvider); + Registration r = new Registration(invocationPlugins, TestMethod.class, getReplacements(), bytecodeProvider); r.registerMethodSubstitution(TestMethodSubstitution.class, "test"); super.registerInvocationPlugins(invocationPlugins); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -104,7 +104,7 @@ import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider; import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; -import org.graalvm.compiler.test.ModuleSupport; +import org.graalvm.compiler.api.test.ModuleSupport; import org.graalvm.compiler.test.SubprocessUtil; import org.junit.Assert; import org.junit.Assume; diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java Thu Oct 31 16:54:16 2019 -0700 @@ -87,7 +87,7 @@ @Override protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider(); - Registration r = new Registration(invocationPlugins, Original.class, replacementBytecodeProvider); + Registration r = new Registration(invocationPlugins, Original.class, getReplacements(), replacementBytecodeProvider); r.registerMethodSubstitution(Intrinsic.class, "getValue"); super.registerInvocationPlugins(invocationPlugins); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java Thu Oct 31 16:54:16 2019 -0700 @@ -132,7 +132,7 @@ : null; GraphBuilderPhase.Instance graphBuilderPhaseInstance = createGraphBuilderPhaseInstance(initialIntrinsicContext); graphBuilderPhaseInstance.apply(graphToEncode); - new CanonicalizerPhase().apply(graphToEncode, providers); + CanonicalizerPhase.create().apply(graphToEncode, providers); if (postParsingPhase != null) { postParsingPhase.apply(graphToEncode, providers); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Thu Oct 31 16:54:16 2019 -0700 @@ -47,6 +47,7 @@ import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; @@ -129,6 +130,7 @@ import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; +import org.graalvm.compiler.nodes.memory.VolatileReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.IndexAddressNode; @@ -397,12 +399,17 @@ AddressNode address = createFieldAddress(graph, object, field); assert address != null : "Field that is loaded must not be eliminated: " + field.getDeclaringClass().toJavaName(true) + "." + field.getName(); - ReadNode memoryRead = graph.add(new ReadNode(address, fieldLocationIdentity(field), loadStamp, fieldLoadBarrierType(field))); + ReadNode memoryRead = null; + if (loadField.isVolatile() && GraalOptions.LateMembars.getValue(graph.getOptions())) { + memoryRead = graph.add(new VolatileReadNode(address, fieldLocationIdentity(field), loadStamp, fieldLoadBarrierType(field))); + } else { + memoryRead = graph.add(new ReadNode(address, fieldLocationIdentity(field), loadStamp, fieldLoadBarrierType(field))); + } ValueNode readValue = implicitLoadConvert(graph, getStorageKind(field), memoryRead); loadField.replaceAtUsages(readValue); graph.replaceFixed(loadField, memoryRead); - if (loadField.isVolatile()) { + if (loadField.isVolatile() && !GraalOptions.LateMembars.getValue(graph.getOptions())) { MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); graph.addBeforeFixed(memoryRead, preMembar); MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); @@ -419,11 +426,11 @@ AddressNode address = createFieldAddress(graph, object, field); assert address != null; - WriteNode memoryWrite = graph.add(new WriteNode(address, fieldLocationIdentity(field), value, fieldStoreBarrierType(storeField.field()))); + WriteNode memoryWrite = graph.add(new WriteNode(address, fieldLocationIdentity(field), value, fieldStoreBarrierType(storeField.field()), storeField.isVolatile())); memoryWrite.setStateAfter(storeField.stateAfter()); graph.replaceFixedWithFixed(storeField, memoryWrite); - if (storeField.isVolatile()) { + if (storeField.isVolatile() && !GraalOptions.LateMembars.getValue(graph.getOptions())) { MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); graph.addBeforeFixed(memoryWrite, preMembar); MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); @@ -528,7 +535,7 @@ AddressNode address = createArrayIndexAddress(graph, array, elementKind, storeIndexed.index(), boundsCheck); WriteNode memoryWrite = graph.add(new WriteNode(address, NamedLocationIdentity.getArrayLocation(elementKind), implicitStoreConvert(graph, elementKind, value), - arrayStoreBarrierType(storeIndexed.elementKind()))); + arrayStoreBarrierType(storeIndexed.elementKind()), false)); memoryWrite.setGuard(boundsCheck); if (condition != null) { tool.createGuard(storeIndexed, condition, DeoptimizationReason.ArrayStoreException, DeoptimizationAction.InvalidateReprofile); @@ -623,7 +630,7 @@ AddressNode address = graph.unique(new OffsetAddressNode(cas.object(), cas.offset())); BarrierType barrierType = guessStoreBarrierType(cas.object(), expectedValue); - LogicCompareAndSwapNode atomicNode = graph.add(new LogicCompareAndSwapNode(address, cas.getLocationIdentity(), expectedValue, newValue, barrierType)); + LogicCompareAndSwapNode atomicNode = graph.add(new LogicCompareAndSwapNode(address, cas.getKilledLocationIdentity(), expectedValue, newValue, barrierType)); atomicNode.setStateAfter(cas.stateAfter()); graph.replaceFixedWithFixed(cas, atomicNode); } @@ -637,7 +644,7 @@ AddressNode address = graph.unique(new OffsetAddressNode(cas.object(), cas.offset())); BarrierType barrierType = guessStoreBarrierType(cas.object(), expectedValue); - ValueCompareAndSwapNode atomicNode = graph.add(new ValueCompareAndSwapNode(address, expectedValue, newValue, cas.getLocationIdentity(), barrierType)); + ValueCompareAndSwapNode atomicNode = graph.add(new ValueCompareAndSwapNode(address, expectedValue, newValue, cas.getKilledLocationIdentity(), barrierType)); ValueNode coercedNode = implicitLoadConvert(graph, valueKind, atomicNode, true); atomicNode.setStateAfter(cas.stateAfter()); cas.replaceAtUsages(coercedNode); @@ -653,7 +660,7 @@ AddressNode address = graph.unique(new OffsetAddressNode(n.object(), n.offset())); BarrierType barrierType = guessStoreBarrierType(n.object(), n.newValue()); LIRKind lirAccessKind = LIRKind.fromJavaKind(target.arch, valueKind); - LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(address, n.getLocationIdentity(), newValue, lirAccessKind, barrierType)); + LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(address, n.getKilledLocationIdentity(), newValue, lirAccessKind, barrierType)); memoryRead.setStateAfter(n.stateAfter()); ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead); @@ -744,7 +751,7 @@ JavaKind valueKind = store.accessKind(); ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible); AddressNode address = createUnsafeAddress(graph, store.object(), store.offset()); - WriteNode write = graph.add(new WriteNode(address, store.getLocationIdentity(), value, unsafeStoreBarrierType(store))); + WriteNode write = graph.add(new WriteNode(address, store.getKilledLocationIdentity(), value, unsafeStoreBarrierType(store), false)); write.setStateAfter(store.stateAfter()); graph.replaceFixedWithFixed(store, write); } @@ -755,7 +762,7 @@ JavaKind valueKind = store.getKind(); ValueNode value = implicitStoreConvert(graph, valueKind, store.getValue(), false); AddressNode address = graph.addOrUniqueWithInputs(OffsetAddressNode.create(store.getAddress())); - WriteNode write = graph.add(new WriteNode(address, store.getLocationIdentity(), value, BarrierType.NONE)); + WriteNode write = graph.add(new WriteNode(address, store.getKilledLocationIdentity(), value, BarrierType.NONE, false)); write.setStateAfter(store.stateAfter()); graph.replaceFixedWithFixed(store, write); } @@ -782,7 +789,7 @@ protected void lowerJavaWriteNode(JavaWriteNode write) { StructuredGraph graph = write.graph(); ValueNode value = implicitStoreConvert(graph, write.getWriteKind(), write.value(), write.isCompressible()); - WriteNode memoryWrite = graph.add(new WriteNode(write.getAddress(), write.getLocationIdentity(), value, write.getBarrierType())); + WriteNode memoryWrite = graph.add(new WriteNode(write.getAddress(), write.getKilledLocationIdentity(), value, write.getBarrierType(), false)); memoryWrite.setStateAfter(write.stateAfter()); graph.replaceFixedWithFixed(write, memoryWrite); memoryWrite.setGuard(write.getGuard()); @@ -842,7 +849,7 @@ barrierType = arrayInitializationBarrier(entryKind); } if (address != null) { - WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, entryKind, value), barrierType); + WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, entryKind, value), barrierType, false); graph.addAfterFixed(newObject, graph.add(write)); } } @@ -875,7 +882,7 @@ barrierType = arrayStoreBarrierType(virtual.entryKind(i)); } if (address != null) { - WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, JavaKind.Object, allocValue), barrierType); + WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, JavaKind.Object, allocValue), barrierType, false); graph.addBeforeFixed(commit, graph.add(write)); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -34,22 +34,27 @@ import org.graalvm.compiler.replacements.arraycopy.ArrayCopyForeignCalls; import org.graalvm.compiler.word.WordTypes; +import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; public class NodeIntrinsificationProvider implements InjectionProvider { + public static final TargetDescription INJECTED_TARGET = null; + private final MetaAccessProvider metaAccess; private final SnippetReflectionProvider snippetReflection; private final ForeignCallsProvider foreignCalls; private final WordTypes wordTypes; + private final TargetDescription target; - public NodeIntrinsificationProvider(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, WordTypes wordTypes) { + public NodeIntrinsificationProvider(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, WordTypes wordTypes, TargetDescription target) { this.metaAccess = metaAccess; this.snippetReflection = snippetReflection; this.foreignCalls = foreignCalls; this.wordTypes = wordTypes; + this.target = target; } @Override @@ -78,6 +83,8 @@ return type.cast(snippetReflection); } else if (type.equals(WordTypes.class)) { return type.cast(wordTypes); + } else if (type.equals(TargetDescription.class)) { + return type.cast(target); } else { throw new GraalError("Cannot handle injected argument of type %s.", type.getName()); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Thu Oct 31 16:54:16 2019 -0700 @@ -269,11 +269,15 @@ } @Override - public void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) { + public void registerMethodSubstitution(MethodSubstitutionPlugin plugin) { // No initialization needed as method substitutions are parsed by the BytecodeParser. } @Override + public void registerConditionalPlugin(InvocationPlugin plugin) { + } + + @Override public boolean hasSubstitution(ResolvedJavaMethod method, int invokeBci) { InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method); return plugin != null && (!plugin.inlineOnly() || invokeBci >= 0); @@ -560,7 +564,7 @@ createGraphBuilder(replacements.providers, config, OptimisticOptimizations.NONE, initialIntrinsicContext).apply(graph); - new CanonicalizerPhase().apply(graph, replacements.providers); + CanonicalizerPhase.create().apply(graph, replacements.providers); } catch (Throwable e) { throw debug.handle(e); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Thu Oct 31 16:54:16 2019 -0700 @@ -891,7 +891,7 @@ } snippetCopy.setGuardsStage(guardsStage); try (DebugContext.Scope s = debug.scope("LoweringSnippetTemplate", snippetCopy)) { - new LoweringPhase(new CanonicalizerPhase(), args.cacheKey.loweringStage).apply(snippetCopy, providers); + new LoweringPhase(CanonicalizerPhase.create(), args.cacheKey.loweringStage).apply(snippetCopy, providers); } catch (Throwable e) { throw debug.handle(e); } @@ -930,7 +930,10 @@ assert checkAllVarargPlaceholdersAreDeleted(parameterCount, placeholders); new FloatingReadPhase(true, true).apply(snippetCopy); - new RemoveValueProxyPhase().apply(snippetCopy); + + if (!guardsStage.requiresValueProxies()) { + new RemoveValueProxyPhase().apply(snippetCopy); + } MemoryAnchorNode anchor = snippetCopy.add(new MemoryAnchorNode()); snippetCopy.start().replaceAtUsages(InputType.Memory, anchor); @@ -1059,8 +1062,14 @@ if (loopBegin != null) { LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin); Mark mark = snippetCopy.getMark(); - LoopTransformations.fullUnroll(loop, providers, new CanonicalizerPhase()); - new CanonicalizerPhase().applyIncremental(snippetCopy, providers, mark, false); + CanonicalizerPhase canonicalizer = null; + if (GraalOptions.ImmutableCode.getValue(snippetCopy.getOptions())) { + canonicalizer = CanonicalizerPhase.createWithoutReadCanonicalization(); + } else { + canonicalizer = CanonicalizerPhase.create(); + } + LoopTransformations.fullUnroll(loop, providers, canonicalizer); + CanonicalizerPhase.create().applyIncremental(snippetCopy, providers, mark, false); loop.deleteUnusedNodes(); } GraphUtil.removeFixedWithUnusedInputs(explodeLoop); @@ -1278,7 +1287,7 @@ if (replacee instanceof MemoryCheckpoint.Single) { // check if some node in snippet graph also kills the same location - LocationIdentity locationIdentity = ((MemoryCheckpoint.Single) replacee).getLocationIdentity(); + LocationIdentity locationIdentity = ((MemoryCheckpoint.Single) replacee).getKilledLocationIdentity(); if (locationIdentity.isAny()) { assert !(memoryMap.getLastLocationAccess(any()) instanceof MemoryAnchorNode) : replacee + " kills ANY_LOCATION, but snippet does not"; // if the replacee kills ANY_LOCATION, the snippet can kill arbitrary locations diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Thu Oct 31 16:54:16 2019 -0700 @@ -40,7 +40,6 @@ 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; @@ -115,6 +114,7 @@ import org.graalvm.compiler.nodes.java.UnsafeCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.HeapAccess; import org.graalvm.compiler.nodes.memory.address.IndexAddressNode; +import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.nodes.virtual.EnsureVirtualizedNode; @@ -154,30 +154,30 @@ */ public class StandardGraphBuilderPlugins { - public static void registerInvocationPlugins(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, InvocationPlugins plugins, BytecodeProvider bytecodeProvider, + public static void registerInvocationPlugins(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, InvocationPlugins plugins, Replacements replacements, boolean allowDeoptimization, boolean explicitUnsafeNullChecks) { registerObjectPlugins(plugins); registerClassPlugins(plugins); registerMathPlugins(plugins, allowDeoptimization); registerStrictMathPlugins(plugins); registerUnsignedMathPlugins(plugins); - registerStringPlugins(plugins, bytecodeProvider, snippetReflection); + registerStringPlugins(plugins, replacements, snippetReflection); registerCharacterPlugins(plugins); registerShortPlugins(plugins); registerIntegerLongPlugins(plugins, JavaKind.Int); registerIntegerLongPlugins(plugins, JavaKind.Long); registerFloatPlugins(plugins); registerDoublePlugins(plugins); - registerArraysPlugins(plugins, bytecodeProvider); - registerArrayPlugins(plugins, bytecodeProvider); - registerUnsafePlugins(plugins, bytecodeProvider, explicitUnsafeNullChecks); + registerArraysPlugins(plugins, replacements); + registerArrayPlugins(plugins, replacements); + registerUnsafePlugins(plugins, replacements, explicitUnsafeNullChecks); registerEdgesPlugins(metaAccess, plugins); registerGraalDirectivesPlugins(plugins); registerBoxingPlugins(plugins); - registerJMHBlackholePlugins(plugins, bytecodeProvider); - registerJFRThrowablePlugins(plugins, bytecodeProvider); - registerMethodHandleImplPlugins(plugins, snippetReflection, bytecodeProvider); - registerJcovCollectPlugins(plugins, bytecodeProvider); + registerJMHBlackholePlugins(plugins, replacements); + registerJFRThrowablePlugins(plugins, replacements); + registerMethodHandleImplPlugins(plugins, snippetReflection, replacements); + registerJcovCollectPlugins(plugins, replacements); } private static final Field STRING_VALUE_FIELD; @@ -196,8 +196,8 @@ STRING_CODER_FIELD = coder; } - private static void registerStringPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider, SnippetReflectionProvider snippetReflection) { - final Registration r = new Registration(plugins, String.class, bytecodeProvider); + private static void registerStringPlugins(InvocationPlugins plugins, Replacements replacements, SnippetReflectionProvider snippetReflection) { + final Registration r = new Registration(plugins, String.class, replacements); r.register1("hashCode", Receiver.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { @@ -243,7 +243,7 @@ }); } else { r.registerMethodSubstitution(JDK9StringSubstitutions.class, "equals", Receiver.class, Object.class); - Registration utf16sub = new Registration(plugins, StringUTF16Substitutions.class, bytecodeProvider); + Registration utf16sub = new Registration(plugins, StringUTF16Substitutions.class, replacements); utf16sub.register2("getCharDirect", byte[].class, int.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) { @@ -261,10 +261,10 @@ } }); - final Registration latin1r = new Registration(plugins, "java.lang.StringLatin1", bytecodeProvider); + final Registration latin1r = new Registration(plugins, "java.lang.StringLatin1", replacements); latin1r.register5("indexOf", byte[].class, int.class, byte[].class, int.class, int.class, new StringLatin1IndexOfConstantPlugin()); - final Registration utf16r = new Registration(plugins, "java.lang.StringUTF16", bytecodeProvider); + final Registration utf16r = new Registration(plugins, "java.lang.StringUTF16", replacements); utf16r.register5("indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class, new StringUTF16IndexOfConstantPlugin()); utf16r.setAllowOverwrite(true); utf16r.registerMethodSubstitution(StringUTF16Substitutions.class, "getChar", byte[].class, int.class); @@ -292,8 +292,8 @@ } } - private static void registerArraysPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins, Arrays.class, bytecodeProvider); + private static void registerArraysPlugins(InvocationPlugins plugins, Replacements replacements) { + Registration r = new Registration(plugins, Arrays.class, replacements); r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", boolean[].class, boolean[].class); r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", byte[].class, byte[].class); r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", short[].class, short[].class); @@ -302,8 +302,8 @@ r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", long[].class, long[].class); } - private static void registerArrayPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins, Array.class, bytecodeProvider); + private static void registerArrayPlugins(InvocationPlugins plugins, Replacements replacements) { + Registration r = new Registration(plugins, Array.class, replacements); r.register2("newInstance", Class.class, int.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unused, ValueNode componentType, ValueNode length) { @@ -381,10 +381,10 @@ private static UnsafeCompareAndExchangePluginsRegistrar unsafeCompareAndExchangePluginsRegistrar = new UnsafeCompareAndExchangePluginsRegistrar(); - public static void registerPlatformSpecificUnsafePlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks, JavaKind[] supportedCasKinds) { + public static void registerPlatformSpecificUnsafePlugins(InvocationPlugins plugins, Replacements replacements, boolean explicitUnsafeNullChecks, JavaKind[] supportedCasKinds) { registerPlatformSpecificUnsafePlugins(supportedCasKinds, new Registration(plugins, Unsafe.class), true, explicitUnsafeNullChecks); if (JavaVersionUtil.JAVA_SPEC > 8) { - registerPlatformSpecificUnsafePlugins(supportedCasKinds, new Registration(plugins, "jdk.internal.misc.Unsafe", bytecodeProvider), false, explicitUnsafeNullChecks); + registerPlatformSpecificUnsafePlugins(supportedCasKinds, new Registration(plugins, "jdk.internal.misc.Unsafe", replacements), false, explicitUnsafeNullChecks); } } @@ -398,10 +398,10 @@ } } - private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks) { + private static void registerUnsafePlugins(InvocationPlugins plugins, Replacements replacements, boolean explicitUnsafeNullChecks) { registerUnsafePlugins(new Registration(plugins, Unsafe.class), true, explicitUnsafeNullChecks); if (JavaVersionUtil.JAVA_SPEC > 8) { - registerUnsafePlugins(new Registration(plugins, "jdk.internal.misc.Unsafe", bytecodeProvider), false, explicitUnsafeNullChecks); + registerUnsafePlugins(new Registration(plugins, "jdk.internal.misc.Unsafe", replacements), false, explicitUnsafeNullChecks); } } @@ -1300,7 +1300,7 @@ }); } - private static void registerJMHBlackholePlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { + private static void registerJMHBlackholePlugins(InvocationPlugins plugins, Replacements replacements) { InvocationPlugin blackholePlugin = new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver blackhole, ValueNode value) { @@ -1316,7 +1316,7 @@ }; String[] names = {"org.openjdk.jmh.infra.Blackhole", "org.openjdk.jmh.logic.BlackHole"}; for (String name : names) { - Registration r = new Registration(plugins, name, bytecodeProvider); + Registration r = new Registration(plugins, name, replacements); for (JavaKind kind : JavaKind.values()) { if ((kind.isPrimitive() && kind != JavaKind.Void) || kind == JavaKind.Object) { Class javaClass = kind == JavaKind.Object ? Object.class : kind.toJavaClass(); @@ -1327,8 +1327,8 @@ } } - private static void registerJFRThrowablePlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins, "oracle.jrockit.jfr.jdkevents.ThrowableTracer", bytecodeProvider); + private static void registerJFRThrowablePlugins(InvocationPlugins plugins, Replacements replacements) { + Registration r = new Registration(plugins, "oracle.jrockit.jfr.jdkevents.ThrowableTracer", replacements); r.register2("traceThrowable", Throwable.class, String.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode throwable, ValueNode message) { @@ -1343,8 +1343,8 @@ }); } - private static void registerMethodHandleImplPlugins(InvocationPlugins plugins, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins, "java.lang.invoke.MethodHandleImpl", bytecodeProvider); + private static void registerMethodHandleImplPlugins(InvocationPlugins plugins, SnippetReflectionProvider snippetReflection, Replacements replacements) { + Registration r = new Registration(plugins, "java.lang.invoke.MethodHandleImpl", replacements); // In later JDKs this no longer exists and the usage is replace by Class.cast which is // already an intrinsic r.registerOptional2("castReference", Class.class, Object.class, new InvocationPlugin() { @@ -1408,8 +1408,8 @@ * Registers a plugin to ignore {@code com.sun.tdk.jcov.runtime.Collect.hit} within an * intrinsic. */ - private static void registerJcovCollectPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { - Registration r = new Registration(plugins, "com.sun.tdk.jcov.runtime.Collect", bytecodeProvider); + private static void registerJcovCollectPlugins(InvocationPlugins plugins, Replacements replacements) { + Registration r = new Registration(plugins, "com.sun.tdk.jcov.runtime.Collect", replacements); r.register1("hit", int.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/TargetGraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/TargetGraphBuilderPlugins.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/TargetGraphBuilderPlugins.java Thu Oct 31 16:54:16 2019 -0700 @@ -24,12 +24,12 @@ package org.graalvm.compiler.replacements; -import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.nodes.spi.Replacements; import jdk.vm.ci.code.Architecture; public interface TargetGraphBuilderPlugins { - void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, Architecture arch, boolean explicitUnsafeNullChecks, boolean registerMathPlugins, boolean emitJDK9StringSubstitutions, + void register(Plugins plugins, Replacements replacements, Architecture arch, boolean explicitUnsafeNullChecks, boolean registerMathPlugins, boolean emitJDK9StringSubstitutions, boolean useFMAIntrinsics); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -188,6 +188,11 @@ return locationIdentity; } + @Override + public LocationIdentity getKilledLocationIdentity() { + return getLocationIdentity(); + } + @NodeIntrinsic(hasSideEffect = true) private static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter JavaKind elementKind, @ConstantNodeParameter boolean aligned, @ConstantNodeParameter boolean disjoint, @ConstantNodeParameter boolean uninitialized, @ConstantNodeParameter int heapWordSize); diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, 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 @@ -57,7 +57,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { if (!forceAnyLocation && elementKind == null) { elementKind = ArrayCopySnippets.Templates.selectComponentKind(this); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/CheckcastArrayCopyCallNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/CheckcastArrayCopyCallNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/CheckcastArrayCopyCallNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, 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 @@ -146,7 +146,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { /* * Because of restrictions that the memory graph of snippets matches the original node, * pretend that we kill any. diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/GenericArrayCopyCallNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/GenericArrayCopyCallNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/GenericArrayCopyCallNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, 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 @@ -102,7 +102,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -128,6 +128,11 @@ } @Override + public LocationIdentity getKilledLocationIdentity() { + return getLocationIdentity(); + } + + @Override public MemoryNode getLastLocationAccess() { return lastLocationAccess; } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -173,7 +173,7 @@ } DebugContext debug = replacementGraph.getDebug(); try (DebugContext.Scope s = debug.scope("LoweringSnippetTemplate", replacementGraph)) { - new LoweringPhase(new CanonicalizerPhase(), tool.getLoweringStage()).apply(replacementGraph, c); + new LoweringPhase(CanonicalizerPhase.create(), tool.getLoweringStage()).apply(replacementGraph, c); } catch (Throwable e) { throw debug.handle(e); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, 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 @@ -75,7 +75,7 @@ } @Override - public LocationIdentity getLocationIdentity() { + public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } @@ -87,7 +87,7 @@ } assert invoke.stateAfter().bci == BytecodeFrame.AFTER_BCI; // Here we need to fix the bci of the invoke - InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), bci(), invoke.getLocationIdentity())); + InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), bci(), invoke.getKilledLocationIdentity())); newInvoke.setStateAfter(invoke.stateAfter()); snippetGraph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/ExportingClassLoader.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/ExportingClassLoader.java Thu Oct 31 14:23:06 2019 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2016, 2019, 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.test; - -/** - * A class loader that exports all packages in the module defining the class loader to all classes - * in the unnamed module associated with the loader. - */ -public class ExportingClassLoader extends ClassLoader { - public ExportingClassLoader() { - ModuleSupport.exportAllPackagesTo(getClass(), this); - } - - public ExportingClassLoader(ClassLoader parent) { - super(parent); - ModuleSupport.exportAllPackagesTo(getClass(), this); - } -} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/ModuleSupport.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/ModuleSupport.java Thu Oct 31 14:23:06 2019 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2019, 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.test; - -import java.io.IOException; -import java.lang.module.ModuleDescriptor.Requires; -import java.net.URI; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.graalvm.compiler.debug.DebugOptions; - -import jdk.internal.module.Modules; - -public class ModuleSupport { - - public static void exportPackageTo(Class moduleMember, String packageName, Class requestor) { - Module moduleToExport = moduleMember.getModule(); - Module requestorModule = requestor.getModule(); - if (moduleToExport != requestorModule) { - Modules.addExports(moduleToExport, packageName, requestorModule); - } - } - - public static void exportAllPackagesTo(Class moduleMember, Class requestor) { - Module moduleToExport = moduleMember.getModule(); - Module requestorModule = requestor.getModule(); - if (moduleToExport != requestorModule) { - for (String packageName : moduleToExport.getPackages()) { - Modules.addExports(moduleToExport, packageName, requestorModule); - } - } - } - - public static void exportAllPackagesTo(Class moduleMember, ClassLoader cl) { - Module moduleToExport = moduleMember.getModule(); - Module unnamedModule = cl.getUnnamedModule(); - for (String packageName : moduleToExport.getPackages()) { - Modules.addExports(moduleToExport, packageName, unnamedModule); - } - } - - @SuppressWarnings("unused") - public static void exportAndOpenAllPackagesToUnnamed(String name) { - Module module = ModuleLayer.boot().findModule(name).orElseThrow(); - Set packages = module.getPackages(); - for (String pkg : packages) { - Modules.addExportsToAllUnnamed(module, pkg); - Modules.addOpensToAllUnnamed(module, pkg); - } - } - - public static List getJRTGraalClassNames() throws IOException { - List classNames = new ArrayList<>(); - FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), Collections.emptyMap()); - Module graalModule = DebugOptions.class.getModule(); - Set graalModuleSet = new HashSet<>(); - graalModuleSet.add(graalModule.getName()); - for (Module module : graalModule.getLayer().modules()) { - if (requires(module, graalModule)) { - graalModuleSet.add(module.getName()); - } - } - - Path top = fs.getPath("/modules/"); - Files.find(top, Integer.MAX_VALUE, - (path, attrs) -> attrs.isRegularFile()).forEach(p -> { - int nameCount = p.getNameCount(); - if (nameCount > 2) { - String base = p.getName(nameCount - 1).toString(); - if (base.endsWith(".class") && !base.equals("module-info.class")) { - String module = p.getName(1).toString(); - if (graalModuleSet.contains(module)) { - // Strip module prefix and convert to dotted - // form - String className = p.subpath(2, nameCount).toString().replace('/', '.'); - // Strip ".class" suffix - className = className.replace('/', '.').substring(0, className.length() - ".class".length()); - classNames.add(className); - } - } - } - }); - return classNames; - } - - private static boolean requires(Module module, Module graalModule) { - ModuleLayer graalLayer = graalModule.getLayer(); - for (Requires r : module.getDescriptor().requires()) { - if (r.name().equals(graalModule.getName())) { - return true; - } - Module dep = graalLayer.findModule(r.name()).get(); - if (requires(dep, graalModule)) { - return true; - } - } - return false; - } -} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java Thu Oct 31 16:54:16 2019 -0700 @@ -121,11 +121,11 @@ return processUnsafeStore((RawStoreNode) node, state, effects); } else if (node instanceof MemoryCheckpoint.Single) { COUNTER_MEMORYCHECKPOINT.increment(node.getDebug()); - LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity(); + LocationIdentity identity = ((MemoryCheckpoint.Single) node).getKilledLocationIdentity(); processIdentity(state, identity); } else if (node instanceof MemoryCheckpoint.Multi) { COUNTER_MEMORYCHECKPOINT.increment(node.getDebug()); - for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) { + for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getKilledLocationIdentities()) { processIdentity(state, identity); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -152,6 +152,7 @@ } public ReadEliminationBlockState(ReadEliminationBlockState other) { + super(other); readCache = EconomicMap.create(Equivalence.DEFAULT, other.readCache); } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java Thu Oct 31 14:23:06 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java Thu Oct 31 16:54:16 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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 @@ -135,9 +135,9 @@ } } else if (node instanceof WriteNode) { WriteNode write = (WriteNode) node; - if (write.getLocationIdentity().isSingle()) { + if (write.getKilledLocationIdentity().isSingle()) { ValueNode object = GraphUtil.unproxify(write.getAddress()); - LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity()); + LoadCacheEntry identifier = new LoadCacheEntry(object, write.getKilledLocationIdentity()); ValueNode cachedValue = state.getCacheEntry(identifier); ValueNode value = getScalarAlias(write.value()); @@ -145,10 +145,10 @@ effects.deleteNode(write); deleted = true; } - processIdentity(state, write.getLocationIdentity()); + processIdentity(state, write.getKilledLocationIdentity()); state.addCacheEntry(identifier, value); } else { - processIdentity(state, write.getLocationIdentity()); + processIdentity(state, write.getKilledLocationIdentity()); } } else if (node instanceof UnsafeAccessNode) { ResolvedJavaType type = StampTool.typeOrNull(((UnsafeAccessNode) node).object()); @@ -170,9 +170,9 @@ } else { assert node instanceof RawStoreNode; RawStoreNode write = (RawStoreNode) node; - if (write.getLocationIdentity().isSingle()) { + if (write.getKilledLocationIdentity().isSingle()) { ValueNode object = GraphUtil.unproxify(write.object()); - UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, write.offset(), write.getLocationIdentity()); + UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, write.offset(), write.getKilledLocationIdentity()); ValueNode cachedValue = state.getCacheEntry(identifier); ValueNode value = getScalarAlias(write.value()); @@ -180,18 +180,18 @@ effects.deleteNode(write); deleted = true; } - processIdentity(state, write.getLocationIdentity()); + processIdentity(state, write.getKilledLocationIdentity()); state.addCacheEntry(identifier, value); } else { - processIdentity(state, write.getLocationIdentity()); + processIdentity(state, write.getKilledLocationIdentity()); } } } } else if (node instanceof MemoryCheckpoint.Single) { - LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity(); + LocationIdentity identity = ((MemoryCheckpoint.Single) node).getKilledLocationIdentity(); processIdentity(state, identity); } else if (node instanceof MemoryCheckpoint.Multi) { - for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) { + for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getKilledLocationIdentities()) { processIdentity(state, identity); } } diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/OptionsEncoder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/OptionsEncoder.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Facilities for encoding/decoding a set of options to/from a byte array. + */ +public final class OptionsEncoder { + + private OptionsEncoder() { + } + + /** + * Determines if {@code value} is supported by {@link #encode(Map)}. + */ + public static boolean isValueSupported(Object value) { + return TypedDataOutputStream.isValueSupported(value); + } + + /** + * Encodes {@code options} into a byte array. + * + * @throws IllegalArgumentException if any value in {@code options} is not + * {@linkplain #isValueSupported(Object) supported} + */ + public static byte[] encode(final Map options) { + try (ByteArrayOutputStream baout = new ByteArrayOutputStream()) { + try (TypedDataOutputStream out = new TypedDataOutputStream(baout)) { + out.writeInt(options.size()); + for (Map.Entry e : options.entrySet()) { + out.writeUTF(e.getKey()); + try { + out.writeTypedValue(e.getValue()); + } catch (IllegalArgumentException iae) { + throw new IllegalArgumentException(String.format("Key: %s, Value: %s, Value type: %s", + e.getKey(), e.getValue(), e.getValue().getClass()), iae); + } + } + } + return baout.toByteArray(); + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); + } + } + + /** + * Decodes {@code input} into a name/value map. + * + * @throws IllegalArgumentException if {@code input} cannot be decoded + */ + public static Map decode(byte[] input) { + Map res = new LinkedHashMap<>(); + try (TypedDataInputStream in = new TypedDataInputStream(new ByteArrayInputStream(input))) { + final int size = in.readInt(); + for (int i = 0; i < size; i++) { + final String key = in.readUTF(); + final Object value = in.readTypedValue(); + res.put(key, value); + } + if (in.available() != 0) { + throw new IllegalArgumentException(in.available() + " undecoded bytes"); + } + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); + } + return res; + } +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/TypedDataInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/TypedDataInputStream.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.util; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * A stream that can read (trivial) values using their in-band data type information, intended for + * use with {@link TypedDataOutputStream}. + */ +public class TypedDataInputStream extends DataInputStream { + public TypedDataInputStream(InputStream in) { + super(in); + } + + /** + * Reads a single value, using the data type encoded in the stream. + * + * @return The read value, such as a boxed primitive or a {@link String}. + * @exception IOException in case of an I/O error. + */ + public Object readTypedValue() throws IOException { + Object value; + final byte type = readByte(); + switch (type) { + case 'Z': + value = readBoolean(); + break; + case 'B': + value = readByte(); + break; + case 'S': + value = readShort(); + break; + case 'C': + value = readChar(); + break; + case 'I': + value = readInt(); + break; + case 'J': + value = readLong(); + break; + case 'F': + value = readFloat(); + break; + case 'D': + value = readDouble(); + break; + case 'U': + value = readUTF(); + break; + default: + throw new IOException("Unsupported type: " + Integer.toHexString(type)); + } + return value; + } +} diff -r 1a8d65e71a66 -r aec7bf35d6f5 src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/TypedDataOutputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/TypedDataOutputStream.java Thu Oct 31 16:54:16 2019 -0700 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.util; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * A stream that can write (trivial) values together with their data type, for use with + * {@link TypedDataInputStream}. + */ +public class TypedDataOutputStream extends DataOutputStream { + /** Determines if {@code value} is supported by {@link #writeTypedValue(Object)}. */ + public static boolean isValueSupported(Object value) { + if (value == null) { + return false; + } + Class valueClass = value.getClass(); + return valueClass == Boolean.class || + valueClass == Byte.class || + valueClass == Short.class || + valueClass == Character.class || + valueClass == Integer.class || + valueClass == Long.class || + valueClass == Float.class || + valueClass == Double.class || + valueClass == String.class || + value.getClass().isEnum(); + } + + public TypedDataOutputStream(OutputStream out) { + super(out); + } + + /** + * Writes the value that is represented by the given non-null object, together with information + * on the value's data type. + * + * @param value A value of a {@linkplain #isValueSupported supported type}. + * @exception IllegalArgumentException when the provided type is not supported. + * @exception IOException in case of an I/O error. + */ + public void writeTypedValue(Object value) throws IOException { + Class valueClz = value.getClass(); + if (valueClz == Boolean.class) { + this.writeByte('Z'); + this.writeBoolean((Boolean) value); + } else if (valueClz == Byte.class) { + this.writeByte('B'); + this.writeByte((Byte) value); + } else if (valueClz == Short.class) { + this.writeByte('S'); + this.writeShort((Short) value); + } else if (valueClz == Character.class) { + this.writeByte('C'); + this.writeChar((Character) value); + } else if (valueClz == Integer.class) { + this.writeByte('I'); + this.writeInt((Integer) value); + } else if (valueClz == Long.class) { + this.writeByte('J'); + this.writeLong((Long) value); + } else if (valueClz == Float.class) { + this.writeByte('F'); + this.writeFloat((Float) value); + } else if (valueClz == Double.class) { + this.writeByte('D'); + this.writeDouble((Double) value); + } else if (valueClz == String.class) { + this.writeByte('U'); + this.writeUTF((String) value); + } else if (valueClz.isEnum()) { + this.writeByte('U'); + this.writeUTF(((Enum) value).name()); + } else { + throw new IllegalArgumentException(String.format("Unsupported type: Value: %s, Value type: %s", value, valueClz)); + } + } +}