diff --git a/sdk/mx.sdk/mx_sdk_vm_impl.py b/sdk/mx.sdk/mx_sdk_vm_impl.py index c1ffd29fd85d..068994eb0d78 100644 --- a/sdk/mx.sdk/mx_sdk_vm_impl.py +++ b/sdk/mx.sdk/mx_sdk_vm_impl.py @@ -1253,7 +1253,7 @@ def contents(self): '-Dorg.graalvm.version={}'.format(_suite.release_version()), ] if _debug_images(): - build_args += ['-ea', '-H:-AOTInline', '-H:+PreserveFramePointer', '-H:-DeleteLocalSymbols'] + build_args += ['-ea', '-O0', '-H:+PreserveFramePointer', '-H:-DeleteLocalSymbols'] if _get_svm_support().is_debug_supported(): build_args += ['-g'] if getattr(image_config, 'link_at_build_time', True): @@ -3303,7 +3303,7 @@ def graalvm_vendor_version(graalvm_dist): mx.add_argument('--disable-polyglot', action='store_true', help='Disable the \'polyglot\' launcher project.') mx.add_argument('--disable-installables', action='store', help='Disable the \'installable\' distributions for gu.' 'This can be a comma-separated list of disabled components short names or `true` to disable all installables.', default=None) -mx.add_argument('--debug-images', action='store_true', help='Build native images in debug mode: \'-H:-AOTInline\' and with \'-ea\'.') +mx.add_argument('--debug-images', action='store_true', help='Build native images in debug mode: \'-O0\' and with \'-ea\'.') mx.add_argument('--native-images', action='store', help='Comma-separated list of launchers and libraries (syntax: lib:polyglot) to build with Native Image.') mx.add_argument('--force-bash-launchers', action='store', help='Force the use of bash launchers instead of native images.' 'This can be a comma-separated list of disabled launchers or `true` to disable all native launchers.', default=None) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 005ac2ba7d29..6da90d5f4638 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -430,6 +430,7 @@ "requiresConcealed" : { "java.base" : [ "jdk.internal.misc", + "jdk.internal.vm.annotation", "jdk.internal.org.objectweb.asm", "sun.reflect.annotation", "sun.security.jca", diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMNativeImageCodeCache.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMNativeImageCodeCache.java index 7ae3ea1ecb50..692c9e9fdb89 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMNativeImageCodeCache.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMNativeImageCodeCache.java @@ -43,7 +43,6 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import com.oracle.graal.pointsto.util.TimerCollection; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.DebugContext; @@ -57,6 +56,7 @@ import com.oracle.graal.pointsto.util.CompletionExecutor; import com.oracle.graal.pointsto.util.CompletionExecutor.DebugContextRunnable; import com.oracle.graal.pointsto.util.Timer.StopTimer; +import com.oracle.graal.pointsto.util.TimerCollection; import com.oracle.objectfile.ObjectFile; import com.oracle.objectfile.ObjectFile.Element; import com.oracle.objectfile.SectionName; @@ -73,6 +73,7 @@ import com.oracle.svm.core.heap.SubstrateReferenceMap; import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicInteger; import com.oracle.svm.core.meta.MethodPointer; +import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.image.NativeImage.NativeTextSectionImpl; import com.oracle.svm.hosted.image.NativeImageCodeCache; import com.oracle.svm.hosted.image.NativeImageHeap; @@ -270,7 +271,7 @@ private void llvmCompile(DebugContext debug, String outputPath, String inputPath args.add("--trap-unreachable"); args.add("-march=" + LLVMTargetSpecific.get().getLLVMArchName()); args.addAll(LLVMTargetSpecific.get().getLLCAdditionalOptions()); - args.add("-O" + SubstrateOptions.optimizationLevel()); + args.add("-O" + optimizationLevel()); args.add("-filetype=obj"); args.add("-o"); args.add(outputPath); @@ -284,6 +285,20 @@ private void llvmCompile(DebugContext debug, String outputPath, String inputPath } } + private static int optimizationLevel() { + switch (SubstrateOptions.optimizationLevel()) { + case O0: + case BUILD_TIME: + return 0; + case O1: + return 1; + case O2: + return 2; + default: + throw VMError.shouldNotReachHere(); + } + } + private void llvmLink(DebugContext debug, String outputPath, List inputPaths) { List args = new ArrayList<>(); args.add("-o"); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index 73f32838ba0b..af74b104a0e2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -151,42 +151,64 @@ protected void onValueUpdate(EconomicMap, Object> values, Boolean o public static final String IMAGE_CLASSPATH_PREFIX = "-imagecp"; public static final String IMAGE_MODULEPATH_PREFIX = "-imagemp"; public static final String WATCHPID_PREFIX = "-watchpid"; - private static ValueUpdateHandler optimizeValueUpdateHandler; - private static ValueUpdateHandler debugInfoValueUpdateHandler = SubstrateOptions::defaultDebugInfoValueUpdateHandler; + private static ValueUpdateHandler optimizeValueUpdateHandler; + private static ValueUpdateHandler debugInfoValueUpdateHandler = SubstrateOptions::defaultDebugInfoValueUpdateHandler; + + /** + * The currently supported optimization levels. See the option description of {@link #Optimize} + * for a description of the levels. + */ + public enum OptimizationLevel { + O0, + O1, + O2, + BUILD_TIME + } @Option(help = "Control native-image code optimizations: b - optimize for shortest build time, 0 - no optimizations, 1 - basic optimizations, 2 - aggressive optimizations.", type = OptionType.User)// public static final HostedOptionKey Optimize = new HostedOptionKey<>("2") { @Override protected void onValueUpdate(EconomicMap, Object> values, String oldValue, String newValue) { - Integer oldLevel = parseOptimizationLevel(oldValue); - Integer newLevel = parseOptimizationLevel(newValue); - SubstrateOptions.IncludeNodeSourcePositions.update(values, newLevel < 1); - SubstrateOptions.AOTInline.update(values, newLevel > 0); - SubstrateOptions.AOTTrivialInline.update(values, newLevel > 0); + OptimizationLevel newLevel = parseOptimizationLevel(newValue); + SubstrateOptions.IncludeNodeSourcePositions.update(values, newLevel == OptimizationLevel.O0); + SubstrateOptions.AOTTrivialInline.update(values, newLevel != OptimizationLevel.O0); if (optimizeValueUpdateHandler != null) { - optimizeValueUpdateHandler.onValueUpdate(values, oldLevel, newLevel); + optimizeValueUpdateHandler.onValueUpdate(values, newLevel); } } }; - private static Integer parseOptimizationLevel(String value) { - if (value == null) { - return null; - } - // Only allow 'b' or numeric optimization levels, - // throw a user error otherwise. + /** + * Only allows 'b' or positive numeric optimization levels, throws a user error otherwise. + */ + private static OptimizationLevel parseOptimizationLevel(String value) { if (value.equals("b")) { - return 0; + return OptimizationLevel.BUILD_TIME; } + + int intLevel; try { - return Integer.parseInt(value); + intLevel = Integer.parseInt(value); } catch (NumberFormatException nfe) { - throw UserError.abort("Invalid value '%s' provided for option Optimize (expected 'b' or numeric value)", value); + intLevel = -1; + } + + if (intLevel == 0) { + return OptimizationLevel.O0; + } else if (intLevel == 1) { + return OptimizationLevel.O1; + } else if (intLevel >= 2) { + /* + * We allow all positive numbers, and treat that as our current highest supported level. + */ + return OptimizationLevel.O2; + } else { + throw UserError.abort("Invalid value '%s' provided for option Optimize (expected 'b' or numeric value >= 0)", value); } } @Fold - public static Integer optimizationLevel() { + public static OptimizationLevel optimizationLevel() { return parseOptimizationLevel(Optimize.getValue()); } @@ -199,15 +221,15 @@ public static boolean useEconomyCompilerConfig() { return useEconomyCompilerConfig(HostedOptionValues.singleton()); } - public interface ValueUpdateHandler { - void onValueUpdate(EconomicMap, Object> values, Integer oldValue, Integer newValue); + public interface ValueUpdateHandler { + void onValueUpdate(EconomicMap, Object> values, T newValue); } - public static void setOptimizeValueUpdateHandler(ValueUpdateHandler updateHandler) { + public static void setOptimizeValueUpdateHandler(ValueUpdateHandler updateHandler) { SubstrateOptions.optimizeValueUpdateHandler = updateHandler; } - public static void setDebugInfoValueUpdateHandler(ValueUpdateHandler updateHandler) { + public static void setDebugInfoValueUpdateHandler(ValueUpdateHandler updateHandler) { SubstrateOptions.debugInfoValueUpdateHandler = updateHandler; } @@ -409,8 +431,8 @@ public static final long getTearDownFailureNanos() { @Option(help = "Enable wildcard expansion in command line arguments on Windows.")// public static final HostedOptionKey EnableWildcardExpansion = new HostedOptionKey<>(true); - @Option(help = "Perform method inlining in the AOT compiled native image")// - public static final HostedOptionKey AOTInline = new HostedOptionKey<>(true); + @Option(help = "Deprecated", deprecated = true)// + static final HostedOptionKey AOTInline = new HostedOptionKey<>(true); @Option(help = "Perform trivial method inlining in the AOT compiled native image")// public static final HostedOptionKey AOTTrivialInline = new HostedOptionKey<>(true); @@ -537,11 +559,11 @@ public static int codeAlignment() { public static final HostedOptionKey GenerateDebugInfo = new HostedOptionKey<>(0) { @Override protected void onValueUpdate(EconomicMap, Object> values, Integer oldValue, Integer newValue) { - debugInfoValueUpdateHandler.onValueUpdate(values, oldValue, newValue); + debugInfoValueUpdateHandler.onValueUpdate(values, newValue); } }; - public static void defaultDebugInfoValueUpdateHandler(EconomicMap, Object> values, @SuppressWarnings("unused") Integer oldValue, Integer newValue) { + public static void defaultDebugInfoValueUpdateHandler(EconomicMap, Object> values, Integer newValue) { /* Force update of TrackNodeSourcePosition */ TrackNodeSourcePosition.update(values, newValue > 0); if (OS.WINDOWS.isCurrent()) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/EconomyHostedConfiguration.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/EconomyHostedConfiguration.java deleted file mode 100644 index a9afb1841227..000000000000 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/EconomyHostedConfiguration.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.hosted; - -public class EconomyHostedConfiguration extends HostedConfiguration { - - public EconomyHostedConfiguration() { - } -} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index fc3a255e464c..50f3efd8b669 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -815,7 +815,6 @@ private void setupNativeImage(String imageName, OptionValues options, Map JDK_FORCE_INLINE_ANNOTATION = lookupForceInlineAnnotation(); - - @SuppressWarnings("unchecked") - private static Class lookupForceInlineAnnotation() { - try { - return (Class) Class.forName("jdk.internal.vm.annotation.ForceInline"); - } catch (ClassNotFoundException ex) { - throw VMError.shouldNotReachHere(ex); - } - } - public static boolean isTrivialMethod(StructuredGraph graph) { - if (graph.method().getAnnotation(JDK_FORCE_INLINE_ANNOTATION) != null) { - /* - * The method is annotated by the JDK as force inline, hopefully for a good reason. - * Treating it as a trivial method means we also inline it everywhere. - */ - return true; - } - int numInvokes = 0; int numOthers = 0; for (Node n : graph.getNodes()) { - if (n instanceof StartNode || n instanceof ParameterNode || n instanceof FullInfopointNode || n instanceof ValueProxy) { + if (n instanceof StartNode || n instanceof ParameterNode || n instanceof FullInfopointNode || n instanceof ValueProxy || n instanceof ValueAnchorNode || n instanceof FrameState) { continue; } if (n instanceof MethodCallTargetNode) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedMethod.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedMethod.java index 50a43b2ed755..6d4f889fd835 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedMethod.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedMethod.java @@ -52,6 +52,7 @@ import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.code.CompilationInfo; +import jdk.internal.vm.annotation.ForceInline; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.ExceptionHandler; @@ -400,7 +401,7 @@ public boolean hasNeverInlineDirective() { @Override public boolean shouldBeInlined() { - return getAnnotation(AlwaysInline.class) != null; + return getAnnotation(AlwaysInline.class) != null || getAnnotation(ForceInline.class) != null; } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/InlineBeforeAnalysisPolicyImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/InlineBeforeAnalysisPolicyImpl.java index 792ccbc82d6d..b4d25274ec90 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/InlineBeforeAnalysisPolicyImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/InlineBeforeAnalysisPolicyImpl.java @@ -40,6 +40,7 @@ import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.UnwindNode; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.ValueAnchorNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.java.AbstractNewObjectNode; import org.graalvm.compiler.nodes.java.NewArrayNode; @@ -179,7 +180,8 @@ protected boolean processNode(CountersScope scope, Node node) { /* Infrastructure nodes that are not even visible to the policy. */ throw VMError.shouldNotReachHere("Node must not be visible to policy: " + node.getClass().getTypeName()); } - if (node instanceof FullInfopointNode || node instanceof ValueProxy || node instanceof FrameState || node instanceof AbstractBeginNode || node instanceof AbstractEndNode) { + if (node instanceof FullInfopointNode || node instanceof ValueProxy || node instanceof ValueAnchorNode || node instanceof FrameState || + node instanceof AbstractBeginNode || node instanceof AbstractEndNode) { /* * Infrastructure nodes that are never counted. We could look at the NodeSize annotation * of a node, but that is a bit unreliable. For example, FrameState and