diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/EconomyPreAllocationOptimizationStage.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/EconomyPreAllocationOptimizationStage.java index 75c290053870..9925898d3de5 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/EconomyPreAllocationOptimizationStage.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/EconomyPreAllocationOptimizationStage.java @@ -24,9 +24,17 @@ */ package org.graalvm.compiler.lir.phases; +import org.graalvm.compiler.lir.alloc.SaveCalleeSaveRegisters; import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; public class EconomyPreAllocationOptimizationStage extends LIRPhaseSuite { public EconomyPreAllocationOptimizationStage() { + /* + * Although HotSpot does not use callee saved registers on any configuration, this phase is + * not optional. SVM for example uses a different calling convention that requires it. If + * used on a configuration without callee saved registers, this phase will simply do + * nothing. + */ + appendPhase(new SaveCalleeSaveRegisters()); } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java index 7b7e42653422..035810f0f538 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java @@ -913,6 +913,20 @@ public void replaceWithExceptionSplit(WithExceptionNode node, WithExceptionNode AbstractBeginNode next = node.next(); AbstractBeginNode exceptionEdge = node.exceptionEdge(); node.replaceAtUsagesAndDelete(replacement); + + if (next instanceof LoopExitNode) { + // see LoopExitNode for special case with exception nodes + BeginNode newNextBegin = add(new BeginNode()); + newNextBegin.setNext(next); + next = newNextBegin; + } + if (exceptionEdge instanceof LoopExitNode) { + // see LoopExitNode for special case with exception nodes + BeginNode newExceptionEdgeBegin = add(new BeginNode()); + newExceptionEdgeBegin.setNext(exceptionEdge); + exceptionEdge = newExceptionEdgeBegin; + } + replacement.setNext(next); replacement.setExceptionEdge(exceptionEdge); } diff --git a/substratevm/CHANGELOG.md b/substratevm/CHANGELOG.md index 8736895c0639..fac8bf82dc4e 100644 --- a/substratevm/CHANGELOG.md +++ b/substratevm/CHANGELOG.md @@ -3,6 +3,7 @@ This changelog summarizes major changes to GraalVM Native Image. ## Version 22.1.0 +* (GR-36568) Add "Quick build" mode, enabled through option `-Ob`, for quicker native image builds. * (GR-35898) Improved handling of static synchronized methods: the lock is no longer stored in the secondary monitor map, but in the mutable DynamicHubCompanion object. * Remove support for JDK8. As a result, `JDK8OrEarlier` and `JDK11OrLater` have been deprecated and will be removed in a future release. * (GR-26814) Red Hat added support for the GC pause-related JFR events (`GCPhasePause`, `GCPhasePauseLevel*`) to the serial GC. diff --git a/substratevm/ci.jsonnet b/substratevm/ci.jsonnet index f6ff5ee7a19e..12cc5e7797de 100644 --- a/substratevm/ci.jsonnet +++ b/substratevm/ci.jsonnet @@ -12,13 +12,22 @@ local svm_cmd_gate = ["mx", "--kill-with-sigquit", "--strict-compliance", "gate", "--strict-mode", "--tags"], + local svm_clone_js_benchmarks = ["git", "clone", "--depth", "1", ["mx", "urlrewrite", "https://github.com/graalvm/js-benchmarks.git"], "../../js-benchmarks"], + local gate_svm_js = svm_common + { run: [ - ["git", "clone", "--depth", "1", ["mx", "urlrewrite", "https://github.com/graalvm/js-benchmarks.git"], "../../js-benchmarks"], + svm_clone_js_benchmarks, svm_cmd_gate + ["build,js"], ], }, + local gate_svm_js_quickbuild = svm_common + { + run: [ + svm_clone_js_benchmarks, + svm_cmd_gate + ["build,js_quickbuild"], + ], + }, + local svm_unittest = { environment+: { "MX_TEST_RESULTS_PATTERN": "es-XXX.json", @@ -40,6 +49,9 @@ common.darwin_amd64 + common.oraclejdk17 + gate_svm_js { name: "gate-svm-darwin-js", }, + common.darwin_amd64 + common.oraclejdk17 + gate_svm_js_quickbuild { + name: "gate-svm-darwin-js-quickbuild", + }, common.linux_amd64 + common.oraclejdk11 + svm_common + maven + svm_unittest + { name: "gate-svm-build-ce-11", timelimit: "30:00", @@ -84,5 +96,12 @@ svm_cmd_gate + ["build,helloworld,test,svmjunit"], ], }, + common.windows_amd64 + common.oraclejdk17 + common.devkits["windows-jdk17"] + svm_common + svm_unittest + { + name: "gate-svm-windows-basics-quickbuild", + timelimit: "1:30:00", + run: [ + svm_cmd_gate + ["build,helloworld_quickbuild,test_quickbuild,svmjunit_quickbuild"], + ], + }, ], -} \ No newline at end of file +} diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 24b79eba486c..9240a530d81a 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -207,9 +207,13 @@ def __getattr__(self, name): GraalTags = Tags([ 'helloworld', 'helloworld_debug', + 'helloworld_quickbuild', 'debuginfotest', + 'debuginfotest_quickbuild', 'test', + 'test_quickbuild', 'js', + 'js_quickbuild', 'build', 'benchmarktest', "nativeimagehelp", @@ -217,7 +221,6 @@ def __getattr__(self, name): 'hellomodule' ]) - def vm_native_image_path(config=None): return vm_executable_path('native-image', config) @@ -308,6 +311,46 @@ def native_image_func(args, **kwargs): _native_unittest_features = '--features=com.oracle.svm.test.ImageInfoTest$TestFeature,com.oracle.svm.test.ServiceLoaderTest$TestFeature,com.oracle.svm.test.SecurityServiceTest$TestFeature' IMAGE_ASSERTION_FLAGS = ['-H:+VerifyGraalGraphs', '-H:+VerifyPhases'] +DEVMODE_FLAGS = ['-Ob'] + + +def image_demo_task(extra_image_args=None, flightrecorder=True): + image_args = ['--output-path', svmbuild_dir()] + if extra_image_args is not None: + image_args += extra_image_args + javac_image(image_args) + javac_command = ['--javac-command', ' '.join(javac_image_command(svmbuild_dir()))] + helloworld(image_args + javac_command) + helloworld(image_args + ['--shared']) # Build and run helloworld as shared library + if not mx.is_windows() and flightrecorder: + helloworld(image_args + ['-J-XX:StartFlightRecording=dumponexit=true']) # Build and run helloworld with FlightRecorder at image build time + cinterfacetutorial(extra_image_args) + clinittest([]) + + +def truffle_unittest_task(quickbuild=False): + truffle_build_args = ['--build-args', '--macro:truffle', + '-H:MaxRuntimeCompileMethods=5000', + '-H:+TruffleCheckBlackListedMethods'] + if quickbuild: + truffle_build_args += DEVMODE_FLAGS + + truffle_args = truffle_build_args + ['--run-args', '--very-verbose', '--enable-timing'] + # ContextPreInitializationNativeImageTest can only run with its own image. + # See class javadoc for details. + native_unittest(['com.oracle.truffle.api.test.polyglot.ContextPreInitializationNativeImageTest'] + truffle_args) + + # Regular Truffle tests that can run with isolated compilation + truffle_tests = ['com.oracle.truffle.api.staticobject.test', + 'com.oracle.truffle.api.test.polyglot.ContextPolicyTest'] + if not quickbuild: + truffle_tests.append('com.oracle.truffle.api.test.TruffleSafepointTest') + + native_unittest(truffle_tests + truffle_args) + + # White Box Truffle compilation tests that need access to compiler graphs. + compiler_args = truffle_args + ['-H:-SupportCompileInIsolates'] + native_unittest(['org.graalvm.compiler.truffle.test.ContextLookupCompilationTest'] + compiler_args) def svm_gate_body(args, tasks): @@ -315,24 +358,17 @@ def svm_gate_body(args, tasks): with Task('image demos', tasks, tags=[GraalTags.helloworld]) as t: if t: with native_image_context(IMAGE_ASSERTION_FLAGS) as native_image: - javac_image(['--output-path', svmbuild_dir()]) - javac_command = ['--javac-command', ' '.join(javac_image_command(svmbuild_dir()))] - helloworld(['--output-path', svmbuild_dir()] + javac_command) - helloworld(['--output-path', svmbuild_dir(), '--shared']) # Build and run helloworld as shared library - if not mx.is_windows(): - helloworld(['--output-path', svmbuild_dir(), '-J-XX:StartFlightRecording=dumponexit=true']) # Build and run helloworld with FlightRecorder at image build time - cinterfacetutorial([]) - clinittest([]) + image_demo_task() with Task('image demos debuginfo', tasks, tags=[GraalTags.helloworld_debug]) as t: if t: with native_image_context(IMAGE_ASSERTION_FLAGS) as native_image: - javac_image(['--output-path', svmbuild_dir(), '-H:GenerateDebugInfo=1']) - javac_command = ['--javac-command', ' '.join(javac_image_command(svmbuild_dir())), '-H:GenerateDebugInfo=1'] - helloworld(['--output-path', svmbuild_dir()] + javac_command) - helloworld(['--output-path', svmbuild_dir(), '--shared', '-H:GenerateDebugInfo=1']) # Build and run helloworld as shared library - cinterfacetutorial(['-H:GenerateDebugInfo=1']) - clinittest([]) + image_demo_task(['-H:GenerateDebugInfo=1'], flightrecorder=False) + + with Task('image demos quickbuild', tasks, tags=[GraalTags.helloworld_quickbuild]) as t: + if t: + with native_image_context(IMAGE_ASSERTION_FLAGS) as native_image: + image_demo_task(DEVMODE_FLAGS, flightrecorder=False) with Task('image debuginfotest', tasks, tags=[GraalTags.debuginfotest]) as t: if t: @@ -344,26 +380,20 @@ def svm_gate_body(args, tasks): with native_image_context(IMAGE_ASSERTION_FLAGS) as native_image: native_unittests_task() - with Task('Run Truffle unittests with SVM image', tasks, tags=["svmjunit"]) as t: + with Task('native unittests quickbuild', tasks, tags=[GraalTags.test_quickbuild]) as t: if t: - truffle_args = ['--build-args', '--macro:truffle', - '-H:MaxRuntimeCompileMethods=5000', - '-H:+TruffleCheckBlackListedMethods', - '--run-args', '--very-verbose', '--enable-timing'] - with native_image_context(IMAGE_ASSERTION_FLAGS) as native_image: - # ContextPreInitializationNativeImageTest can only run with its own image. - # See class javadoc for details. - native_unittest(['com.oracle.truffle.api.test.polyglot.ContextPreInitializationNativeImageTest'] + truffle_args) + native_unittests_task(DEVMODE_FLAGS) - # Regular Truffle tests that can run with isolated compilation - native_unittest(['com.oracle.truffle.api.test.TruffleSafepointTest', - 'com.oracle.truffle.api.staticobject.test', - 'com.oracle.truffle.api.test.polyglot.ContextPolicyTest'] + truffle_args) + with Task('Run Truffle unittests with SVM image', tasks, tags=["svmjunit"]) as t: + if t: + with native_image_context(IMAGE_ASSERTION_FLAGS) as native_image: + truffle_unittest_task() - # White Box Truffle compilation tests that need access to compiler graphs. - compiler_args = truffle_args + ['-H:-SupportCompileInIsolates'] - native_unittest(['org.graalvm.compiler.truffle.test.ContextLookupCompilationTest'] + compiler_args) + with Task('Run Truffle unittests with SVM image with quickbuild', tasks, tags=["svmjunit_quickbuild"]) as t: + if t: + with native_image_context(IMAGE_ASSERTION_FLAGS) as native_image: + truffle_unittest_task(quickbuild=True) with Task('Run Truffle NFI unittests with SVM image', tasks, tags=["svmjunit"]) as t: if t: @@ -376,6 +406,17 @@ def svm_gate_body(args, tasks): '--run-args', testlib, isolation_testlib, '--very-verbose', '--enable-timing'] native_unittest(native_unittest_args) + with Task('Run Truffle NFI unittests with SVM image with quickbuild', tasks, tags=["svmjunit_quickbuild"]) as t: + if t: + with native_image_context(IMAGE_ASSERTION_FLAGS) as native_image: + testlib = mx_subst.path_substitutions.substitute('-Dnative.test.lib=/') + isolation_testlib = mx_subst.path_substitutions.substitute('-Dnative.isolation.test.lib=/') + native_unittest_args = ['com.oracle.truffle.nfi.test', '--build-args', '--language:nfi', + '-H:MaxRuntimeCompileMethods=2000', + '-H:+TruffleCheckBlackListedMethods'] + DEVMODE_FLAGS + [ + '--run-args', testlib, isolation_testlib, '--very-verbose', '--enable-timing'] + native_unittest(native_unittest_args) + with Task('Musl static hello world and JVMCI version check', tasks, tags=[GraalTags.muslcbuild]) as t: if t: with native_image_context(IMAGE_ASSERTION_FLAGS) as native_image: @@ -406,12 +447,21 @@ def help_stdout_check(output): test_run([get_js_launcher(jslib), '-e', 'print("hello:" + Array.from(new Array(10), (x,i) => i*i ).join("|"))'], 'hello:0|1|4|9|16|25|36|49|64|81\n') test_js(jslib, [('octane-richards', 1000, 100, 300)]) + with Task('JavaScript with quickbuild', tasks, tags=[GraalTags.js_quickbuild]) as t: + if t: + config = GraalVMConfig.build(primary_suite_dir=join(suite.vc_dir, 'vm'), # Run from `vm` to clone the right revision of `graal-js` if needed + dynamicimports=['/' + svm_suite().name, '/graal-js']) + with native_image_context(IMAGE_ASSERTION_FLAGS + DEVMODE_FLAGS, config=config) as native_image: + jslib = build_js_lib(native_image) + test_run([get_js_launcher(jslib), '-e', 'print("hello:" + Array.from(new Array(10), (x,i) => i*i ).join("|"))'], 'hello:0|1|4|9|16|25|36|49|64|81\n') + test_js(jslib, [('octane-richards', 1000, 100, 300)]) + with Task('module build demo', tasks, tags=[GraalTags.hellomodule]) as t: if t: hellomodule([]) -def native_unittests_task(): +def native_unittests_task(extra_build_args=None): if mx.is_windows(): # GR-24075 mx_unittest.add_global_ignore_glob('com.oracle.svm.test.ProcessPropertiesTest') @@ -420,6 +470,8 @@ def native_unittests_task(): '-H:AdditionalSecurityProviders=com.oracle.svm.test.SecurityServiceTest$NoOpProvider', '-H:AdditionalSecurityServiceTypes=com.oracle.svm.test.SecurityServiceTest$JCACompliantNoOpService' ] + if extra_build_args is not None: + additional_build_args += extra_build_args if get_jdk().javaCompliance == '17': if mx.is_windows(): diff --git a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64SuitesCreatorProvider.java b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64SuitesCreatorProvider.java index 4ab0c315f936..3a29591ca8d3 100644 --- a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64SuitesCreatorProvider.java +++ b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64SuitesCreatorProvider.java @@ -26,7 +26,6 @@ package com.oracle.svm.core.graal.aarch64; import org.graalvm.compiler.core.aarch64.AArch64SuitesCreator; -import org.graalvm.compiler.core.phases.CommunityCompilerConfiguration; import org.graalvm.compiler.core.phases.EconomyCompilerConfiguration; import org.graalvm.compiler.phases.schedule.SchedulePhase; @@ -36,7 +35,7 @@ public class SubstrateAArch64SuitesCreatorProvider extends SubstrateSuitesCreatorProvider { public SubstrateAArch64SuitesCreatorProvider() { - super(new AArch64SuitesCreator(new CommunityCompilerConfiguration(), Arrays.asList(SchedulePhase.class)), + super(new AArch64SuitesCreator(getHostedCompilerConfiguration(), Arrays.asList(SchedulePhase.class)), new AArch64SuitesCreator(new EconomyCompilerConfiguration(), Arrays.asList(SchedulePhase.class))); } } diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64SuitesCreatorProvider.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64SuitesCreatorProvider.java index 3d9a906d2140..e6a4f369908c 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64SuitesCreatorProvider.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64SuitesCreatorProvider.java @@ -25,14 +25,13 @@ package com.oracle.svm.core.graal.amd64; import org.graalvm.compiler.core.amd64.AMD64SuitesCreator; -import org.graalvm.compiler.core.phases.CommunityCompilerConfiguration; import org.graalvm.compiler.core.phases.EconomyCompilerConfiguration; import com.oracle.svm.core.graal.code.SubstrateSuitesCreatorProvider; public class SubstrateAMD64SuitesCreatorProvider extends SubstrateSuitesCreatorProvider { public SubstrateAMD64SuitesCreatorProvider() { - super(new AMD64SuitesCreator(new CommunityCompilerConfiguration()), + super(new AMD64SuitesCreator(getHostedCompilerConfiguration()), new AMD64SuitesCreator(new EconomyCompilerConfiguration())); } } 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 01d31e70049d..fb5c3ca6f650 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 @@ -255,7 +255,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.Optimize.getValue()); + args.add("-O" + SubstrateOptions.optimizationLevel()); args.add("-filetype=obj"); args.add("-o"); args.add(outputPath); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ParsingReason.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ParsingReason.java index 1c5f5dc1a9e2..baf2fbd50e8c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ParsingReason.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ParsingReason.java @@ -31,4 +31,8 @@ public enum ParsingReason { JITCompilation, EarlyClassInitializerAnalysis, UnsafeSubstitutionAnalysis; + + public boolean isForHosted() { + return this != JITCompilation; + } } 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 ad0edcf0d9a0..ad81a3118a3b 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 @@ -54,6 +54,7 @@ import com.oracle.svm.core.option.APIOption; import com.oracle.svm.core.option.APIOptionGroup; import com.oracle.svm.core.option.HostedOptionKey; +import com.oracle.svm.core.option.HostedOptionValues; import com.oracle.svm.core.option.ImmutableRuntimeOptionKey; import com.oracle.svm.core.option.LocatableMultiOptionValue; import com.oracle.svm.core.option.RuntimeOptionKey; @@ -139,19 +140,51 @@ protected void onValueUpdate(EconomicMap, Object> values, Boolean o private static ValueUpdateHandler optimizeValueUpdateHandler; private static ValueUpdateHandler debugInfoValueUpdateHandler = SubstrateOptions::defaultDebugInfoValueUpdateHandler; - @Option(help = "Control native-image code optimizations: 0 - no optimizations, 1 - basic optimizations, 2 - aggressive optimizations.", type = OptionType.User)// - public static final HostedOptionKey Optimize = new HostedOptionKey<>(2) { + @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, Integer oldValue, Integer newValue) { - SubstrateOptions.IncludeNodeSourcePositions.update(values, newValue < 1); - SubstrateOptions.AOTInline.update(values, newValue > 0); - SubstrateOptions.AOTTrivialInline.update(values, newValue > 0); + 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); if (optimizeValueUpdateHandler != null) { - optimizeValueUpdateHandler.onValueUpdate(values, oldValue, newValue); + optimizeValueUpdateHandler.onValueUpdate(values, oldLevel, newLevel); } } }; + private static Integer parseOptimizationLevel(String value) { + if (value == null) { + return null; + } + // Only allow 'b' or numeric optimization levels, + // throw a user error otherwise. + if (value.equals("b")) { + return 0; + } + try { + return Integer.parseInt(value); + } catch (NumberFormatException nfe) { + throw UserError.abort("Invalid value '%s' provided for option Optimize (expected 'b' or numeric value)", value); + } + } + + @Fold + public static Integer optimizationLevel() { + return parseOptimizationLevel(Optimize.getValue()); + } + + public static boolean useEconomyCompilerConfig(OptionValues options) { + return "b".equals(Optimize.getValue(options)); + } + + @Fold + public static boolean useEconomyCompilerConfig() { + return useEconomyCompilerConfig(HostedOptionValues.singleton()); + } + public interface ValueUpdateHandler { void onValueUpdate(EconomicMap, Object> values, Integer oldValue, Integer newValue); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/EconomyGraalConfiguration.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/EconomyGraalConfiguration.java new file mode 100644 index 000000000000..e8c3a42c9272 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/EconomyGraalConfiguration.java @@ -0,0 +1,37 @@ +/* + * 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 + * 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.core.graal; + +import org.graalvm.compiler.hotspot.EconomyCompilerConfigurationFactory; + +public class EconomyGraalConfiguration extends GraalConfiguration { + + private static final String COMPILER_CONFIGURATION_NAME = EconomyCompilerConfigurationFactory.NAME; + + @Override + public String getCompilerConfigurationName() { + return COMPILER_CONFIGURATION_NAME; + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/GraalConfiguration.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/GraalConfiguration.java index 1b021edfa532..f23cd0bc23a1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/GraalConfiguration.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/GraalConfiguration.java @@ -61,17 +61,46 @@ import jdk.vm.ci.code.Architecture; import jdk.vm.ci.meta.MetaAccessProvider; +class HostedWrapper { + GraalConfiguration config; + + HostedWrapper(GraalConfiguration config) { + this.config = config; + } +} + public class GraalConfiguration { private static final String COMPILER_CONFIGURATION_NAME = CommunityCompilerConfigurationFactory.NAME; - public static GraalConfiguration instance() { + public static GraalConfiguration hostedInstance() { + return ImageSingletons.lookup(HostedWrapper.class).config; + } + + public static void setHostedInstanceIfEmpty(GraalConfiguration config) { + if (!ImageSingletons.contains(HostedWrapper.class)) { + ImageSingletons.add(HostedWrapper.class, new HostedWrapper(config)); + } + } + + public static GraalConfiguration runtimeInstance() { return ImageSingletons.lookup(GraalConfiguration.class); } + public static void setRuntimeInstance(GraalConfiguration config) { + ImageSingletons.add(GraalConfiguration.class, config); + } + public static void setDefaultIfEmpty() { - if (!ImageSingletons.contains(GraalConfiguration.class)) { - ImageSingletons.add(GraalConfiguration.class, new GraalConfiguration()); + // Avoid constructing a new instance if not necessary + if (!ImageSingletons.contains(GraalConfiguration.class) || !ImageSingletons.contains(HostedWrapper.class)) { + GraalConfiguration instance = new GraalConfiguration(); + if (!ImageSingletons.contains(GraalConfiguration.class)) { + ImageSingletons.add(GraalConfiguration.class, instance); + } + if (!ImageSingletons.contains(HostedWrapper.class)) { + ImageSingletons.add(HostedWrapper.class, new HostedWrapper(instance)); + } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateSuitesCreatorProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateSuitesCreatorProvider.java index 3818334c0a63..4a98ec61a8a2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateSuitesCreatorProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateSuitesCreatorProvider.java @@ -28,20 +28,31 @@ import org.graalvm.compiler.core.phases.CommunityCompilerConfiguration; import org.graalvm.compiler.core.phases.EconomyCompilerConfiguration; import org.graalvm.compiler.java.DefaultSuitesCreator; +import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.tiers.SuitesCreator; +import com.oracle.svm.core.SubstrateOptions; + public class SubstrateSuitesCreatorProvider { private final SuitesCreator suitesCreator; private final SuitesCreator firstTierSuitesCreator; + protected static CompilerConfiguration getHostedCompilerConfiguration() { + if (SubstrateOptions.useEconomyCompilerConfig()) { + return new EconomyCompilerConfiguration(); + } else { + return new CommunityCompilerConfiguration(); + } + } + protected SubstrateSuitesCreatorProvider(SuitesCreator suitesCreator, SuitesCreator firstTierSuitesCreator) { this.suitesCreator = suitesCreator; this.firstTierSuitesCreator = firstTierSuitesCreator; } public SubstrateSuitesCreatorProvider() { - this(new DefaultSuitesCreator(new CommunityCompilerConfiguration()), new DefaultSuitesCreator(new EconomyCompilerConfiguration())); + this(new DefaultSuitesCreator(getHostedCompilerConfiguration()), new DefaultSuitesCreator(new EconomyCompilerConfiguration())); } public final SuitesCreator getSuitesCreator() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateLoweringProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateLoweringProvider.java index 38b6c04a5b6d..60108208532e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateLoweringProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateLoweringProvider.java @@ -53,10 +53,14 @@ public interface SubstrateLoweringProvider extends LoweringProvider { Stamp loadStamp(Stamp stamp, JavaKind kind); - static LoweringProvider create(MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, PlatformConfigurationProvider platformConfig, + static LoweringProvider createForHosted(MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, PlatformConfigurationProvider platformConfig, MetaAccessExtensionProvider metaAccessExtensionProvider) { - return GraalConfiguration.instance().createLoweringProvider(metaAccess, foreignCalls, platformConfig, metaAccessExtensionProvider); + return GraalConfiguration.hostedInstance().createLoweringProvider(metaAccess, foreignCalls, platformConfig, metaAccessExtensionProvider); + } + static LoweringProvider createForRuntime(MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, PlatformConfigurationProvider platformConfig, + MetaAccessExtensionProvider metaAccessExtensionProvider) { + return GraalConfiguration.runtimeInstance().createLoweringProvider(metaAccess, foreignCalls, platformConfig, metaAccessExtensionProvider); } @Override diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalFeature.java index c016c6d8c2ef..617c62e6f774 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalFeature.java @@ -425,7 +425,7 @@ public void beforeAnalysis(BeforeAnalysisAccess c) { private static void populateMatchRuleRegistry() { GraalSupport.get().setMatchRuleRegistry(new HashMap<>()); - GraalConfiguration.instance().populateMatchRuleRegistry(GraalSupport.get().getMatchRuleRegistry()); + GraalConfiguration.runtimeInstance().populateMatchRuleRegistry(GraalSupport.get().getMatchRuleRegistry()); } @SuppressWarnings("unused") 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 new file mode 100644 index 000000000000..a9afb1841227 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/EconomyHostedConfiguration.java @@ -0,0 +1,31 @@ +/* + * 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/HostedConfiguration.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java index 70f46dc7175c..ff8432e6832d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java @@ -78,10 +78,15 @@ public static HostedConfiguration instance() { return ImageSingletons.lookup(HostedConfiguration.class); } - public static void setDefaultIfEmpty() { + public static void setInstanceIfEmpty(HostedConfiguration config) { if (!ImageSingletons.contains(HostedConfiguration.class)) { - ImageSingletons.add(HostedConfiguration.class, new HostedConfiguration()); + ImageSingletons.add(HostedConfiguration.class, config); + } + } + public static void setDefaultIfEmpty() { + setInstanceIfEmpty(new HostedConfiguration()); + if (!ImageSingletons.contains(CompressEncoding.class)) { CompressEncoding compressEncoding = new CompressEncoding(SubstrateOptions.SpawnIsolates.getValue() ? 1 : 0, 0); ImageSingletons.add(CompressEncoding.class, compressEncoding); 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 28777432e70a..771abbb52db3 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 @@ -174,6 +174,7 @@ import com.oracle.svm.core.c.struct.OffsetOf; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.cpufeature.RuntimeCPUFeatureCheck; +import com.oracle.svm.core.graal.EconomyGraalConfiguration; import com.oracle.svm.core.graal.GraalConfiguration; import com.oracle.svm.core.graal.code.SubstrateBackend; import com.oracle.svm.core.graal.code.SubstratePlatformConfigurationProvider; @@ -814,6 +815,11 @@ private void setupNativeImage(String imageName, Timer classlistTimer, OptionValu ImageSingletons.add(ImageBuildStatistics.class, new ImageBuildStatistics()); } + if (SubstrateOptions.useEconomyCompilerConfig()) { + HostedConfiguration.setInstanceIfEmpty(new EconomyHostedConfiguration()); + GraalConfiguration.setHostedInstanceIfEmpty(new EconomyGraalConfiguration()); + } + /* Init the BuildPhaseProvider before any features need it. */ BuildPhaseProvider.init(); @@ -1035,7 +1041,7 @@ public static Inflation createBigBang(OptionValues options, TargetDescription ta BarrierSet barrierSet = ImageSingletons.lookup(Heap.class).createBarrierSet(aMetaAccess); SubstratePlatformConfigurationProvider platformConfig = new SubstratePlatformConfigurationProvider(barrierSet); AnalysisMetaAccessExtensionProvider aMetaAccessExtensionProvider = new AnalysisMetaAccessExtensionProvider(); - LoweringProvider aLoweringProvider = SubstrateLoweringProvider.create(aMetaAccess, null, platformConfig, aMetaAccessExtensionProvider); + LoweringProvider aLoweringProvider = SubstrateLoweringProvider.createForHosted(aMetaAccess, null, platformConfig, aMetaAccessExtensionProvider); StampProvider aStampProvider = new SubstrateStampProvider(aMetaAccess); HostedProviders aProviders = new HostedProviders(aMetaAccess, null, aConstantReflection, aConstantFieldProvider, aForeignCalls, aLoweringProvider, null, aStampProvider, aSnippetReflection, aWordTypes, platformConfig, aMetaAccessExtensionProvider, originalProviders.getLoopsDataProvider()); @@ -1293,16 +1299,23 @@ private static boolean checkInvocationPluginMethods(SubstrateReplacements replac public static Suites createSuites(FeatureHandler featureHandler, RuntimeConfiguration runtimeConfig, SnippetReflectionProvider snippetReflection, boolean hosted) { SubstrateBackend backend = runtimeConfig.getBackendForNormalMethod(); - - OptionValues options = hosted ? HostedOptionValues.singleton() : RuntimeOptionValues.singleton(); - Suites suites = GraalConfiguration.instance().createSuites(options, hosted); + Suites suites; + if (hosted) { + suites = GraalConfiguration.hostedInstance().createSuites(HostedOptionValues.singleton(), hosted); + } else { + suites = GraalConfiguration.runtimeInstance().createSuites(RuntimeOptionValues.singleton(), hosted); + } return modifySuites(backend, suites, featureHandler, runtimeConfig, snippetReflection, hosted, false); } public static Suites createFirstTierSuites(FeatureHandler featureHandler, RuntimeConfiguration runtimeConfig, SnippetReflectionProvider snippetReflection, boolean hosted) { SubstrateBackend backend = runtimeConfig.getBackendForNormalMethod(); - OptionValues options = hosted ? HostedOptionValues.singleton() : RuntimeOptionValues.singleton(); - Suites suites = GraalConfiguration.instance().createFirstTierSuites(options, hosted); + Suites suites; + if (hosted) { + suites = GraalConfiguration.hostedInstance().createFirstTierSuites(HostedOptionValues.singleton(), hosted); + } else { + suites = GraalConfiguration.runtimeInstance().createFirstTierSuites(RuntimeOptionValues.singleton(), hosted); + } return modifySuites(backend, suites, featureHandler, runtimeConfig, snippetReflection, hosted, true); } @@ -1315,9 +1328,11 @@ private static Suites modifySuites(SubstrateBackend backend, Suites suites, Feat PhaseSuite midTier = suites.getMidTier(); PhaseSuite lowTier = suites.getLowTier(); + final boolean economy = firstTier || SubstrateOptions.useEconomyCompilerConfig(); + ListIterator> position; if (hosted) { - position = GraalConfiguration.instance().createHostedInliners(highTier); + position = GraalConfiguration.hostedInstance().createHostedInliners(highTier); } else { /* Find the runtime inliner. */ position = highTier.findPhase(InliningPhase.class); @@ -1335,7 +1350,7 @@ private static Suites modifySuites(SubstrateBackend backend, Suites suites, Feat lowTier.addBeforeLast(new OptimizeExceptionPathsPhase()); BasePhase addressLoweringPhase = backend.newAddressLoweringPhase(runtimeCallProviders.getCodeCache()); - if (firstTier) { + if (economy) { lowTier.findPhase(ExpandLogicPhase.class, true).add(addressLoweringPhase); } else { lowTier.findPhase(UseTrappingNullChecksPhase.class).add(addressLoweringPhase); @@ -1359,11 +1374,10 @@ private static Suites modifySuites(SubstrateBackend backend, Suites suites, Feat highTier.removePhase(InliningPhase.class); /* Remove phases that are not suitable for AOT compilation. */ - highTier.findPhase(ConvertDeoptimizeToGuardPhase.class, true).remove(); - midTier.findPhase(DeoptimizationGroupingPhase.class).remove(); - + highTier.removePhase(ConvertDeoptimizeToGuardPhase.class); + midTier.removePhase(DeoptimizationGroupingPhase.class); } else { - if (firstTier) { + if (economy) { ListIterator> it = midTier.findPhase(FrameStateAssignmentPhase.class); it.add(new CollectDeoptimizationSourcePositionsPhase()); @@ -1392,14 +1406,17 @@ private static Suites modifySuites(SubstrateBackend backend, Suites suites, Feat @SuppressWarnings("unused") public static LIRSuites createLIRSuites(FeatureHandler featureHandler, Providers providers, boolean hosted) { - LIRSuites lirSuites = GraalConfiguration.instance().createLIRSuites(hosted ? HostedOptionValues.singleton() : RuntimeOptionValues.singleton()); + LIRSuites lirSuites; if (hosted) { + lirSuites = GraalConfiguration.hostedInstance().createLIRSuites(HostedOptionValues.singleton()); /* * Even though this is a verification phase, we want it enabled all the time and not * just when assertions are enabled. */ lirSuites.getFinalCodeAnalysisStage().appendPhase(new VerifyCFunctionReferenceMapsLIRPhase()); + } else { + lirSuites = GraalConfiguration.runtimeInstance().createLIRSuites(RuntimeOptionValues.singleton()); } /* Add phases that just perform assertion checking. */ @@ -1409,10 +1426,12 @@ public static LIRSuites createLIRSuites(FeatureHandler featureHandler, Providers @SuppressWarnings("unused") public static LIRSuites createFirstTierLIRSuites(FeatureHandler featureHandler, Providers providers, boolean hosted) { - LIRSuites lirSuites = GraalConfiguration.instance().createFirstTierLIRSuites(hosted ? HostedOptionValues.singleton() : RuntimeOptionValues.singleton()); - + LIRSuites lirSuites; if (hosted) { + lirSuites = GraalConfiguration.hostedInstance().createFirstTierLIRSuites(HostedOptionValues.singleton()); lirSuites.getFinalCodeAnalysisStage().appendPhase(new VerifyCFunctionReferenceMapsLIRPhase()); + } else { + lirSuites = GraalConfiguration.runtimeInstance().createFirstTierLIRSuites(RuntimeOptionValues.singleton()); } /* Add phases that just perform assertion checking. */ diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java index 9a9592d1f8aa..f5fd5ed77281 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java @@ -184,6 +184,11 @@ public ProgressReporter(OptionValues options) { showLinks = SubstrateOptions.BuildOutputLinks.getValue(options); } linkStrategy = showLinks ? new LinkyStrategy() : new LinklessStrategy(); + + if (SubstrateOptions.useEconomyCompilerConfig(options)) { + l().redBold().a("You enabled -Ob for this image build. This will configure some optimizations to reduce image build time.").println(); + l().redBold().a("This feature should only be used during development and never for deployment.").reset().println(); + } } public void setNumRuntimeCompiledMethods(int value) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java index 3cdd6435f7e1..4b9fe8b86d8c 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java @@ -329,11 +329,11 @@ private boolean retainLocalVariables() { * reused by javac, local variables can still get illegal values. Since we cannot * "restore" such illegal values during deoptimization, we cannot disable liveness * analysis for deoptimization target methods. - * + * * TODO: ParseOnce does not support deoptimization targets yet, this needs to be added * later. */ - return SubstrateOptions.Optimize.getValue() <= 0; + return SubstrateOptions.optimizationLevel() <= 0; } else { /* @@ -656,7 +656,7 @@ private void checkClassInitializerSideEffect(PointsToAnalysis bb, AnalysisMethod /* * Unsafe memory access nodes are rare, so it does not pay off to check what kind of * field they are accessing. - * + * * Methods that access a thread-local value cannot be initialized at image build time * because such values are not available yet. */ diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java index c71f4c69d9f7..566833e0b735 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java @@ -33,6 +33,7 @@ import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; @@ -74,7 +75,9 @@ import org.graalvm.compiler.lir.asm.DataBuilder; import org.graalvm.compiler.lir.asm.FrameContext; import org.graalvm.compiler.lir.framemap.FrameMap; +import org.graalvm.compiler.lir.phases.LIRPhase; import org.graalvm.compiler.lir.phases.LIRSuites; +import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedNode; @@ -102,6 +105,7 @@ import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectState; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.BoxNodeOptimizationPhase; @@ -1137,7 +1141,7 @@ protected OptionValues getCustomizedOptions(DebugContext debug) { protected GraphBuilderConfiguration createHostedGraphBuilderConfiguration(HostedProviders providers, HostedMethod method) { GraphBuilderConfiguration gbConf = GraphBuilderConfiguration.getDefault(providers.getGraphBuilderPlugins()).withBytecodeExceptionMode(BytecodeExceptionMode.CheckAll); - if (SubstrateOptions.Optimize.getValue() <= 0 && !method.isDeoptTarget()) { + if (SubstrateOptions.optimizationLevel() <= 0 && !method.isDeoptTarget()) { /* * Disabling liveness analysis preserves the values of local variables beyond the * bytecode-liveness. This greatly helps debugging. When local variable numbers are @@ -1386,7 +1390,7 @@ protected void ensureCalleesCompiled(HostedMethod method, CompileReason reason, } protected void removeDeoptTargetOptimizations(Suites suites) { - GraalConfiguration.instance().removeDeoptTargetOptimizations(suites); + GraalConfiguration.hostedInstance().removeDeoptTargetOptimizations(suites); PhaseSuite highTier = suites.getHighTier(); highTier.removePhase(PartialEscapePhase.class); @@ -1395,11 +1399,17 @@ protected void removeDeoptTargetOptimizations(Suites suites) { PhaseSuite midTier = suites.getMidTier(); midTier.removePhase(FloatingReadPhase.class); PhaseSuite lowTier = suites.getLowTier(); - ((FixReadsPhase) lowTier.findPhase(FixReadsPhase.class).previous()).setReplaceInputsWithConstants(false); + ListIterator> it = lowTier.findPhase(FixReadsPhase.class); + if (it != null) { + ((FixReadsPhase) it.previous()).setReplaceInputsWithConstants(false); + } } private static void removeDeoptTargetOptimizations(LIRSuites lirSuites) { - lirSuites.getPostAllocationOptimizationStage().findPhase(RedundantMoveElimination.class).remove(); + ListIterator> it = lirSuites.getPostAllocationOptimizationStage().findPhase(RedundantMoveElimination.class); + if (it != null) { + it.remove(); + } lirSuites.getAllocationStage().findPhaseInstance(RegisterAllocationPhase.class).setNeverSpillConstants(true); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java index f2c0b80883cf..11019b43c17e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java @@ -41,6 +41,7 @@ import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.graal.code.SubstrateBackendFactory; +import com.oracle.svm.core.graal.meta.SubstrateLoweringProvider; import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.c.NativeLibraries; import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport; @@ -75,6 +76,11 @@ protected Providers createProviders(CodeCacheProvider codeCache, ConstantReflect wordTypes, platformConfigurationProvider, metaAccessExtensionProvider, loopsDataProvider); } + @Override + protected LoweringProvider createLoweringProvider(Providers p) { + return SubstrateLoweringProvider.createForHosted(p.getMetaAccess(), p.getForeignCalls(), p.getPlatformConfigurationProvider(), p.getMetaAccessExtensionProvider()); + } + @Override protected ConstantReflectionProvider createConstantReflectionProvider(Providers p) { return new HostedConstantReflectionProvider(hostVM, universe, new HostedMemoryAccessProvider((HostedMetaAccess) p.getMetaAccess())); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java index da5fe3f6a64b..e7187aa085be 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java @@ -136,7 +136,7 @@ public SharedRuntimeConfigurationBuilder build() { Providers newProviders = createProviders(codeCacheProvider, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, snippetReflection, platformConfig, metaAccessExtensionProvider, loopsDataProvider); - backends.put(config, GraalConfiguration.instance().createBackend(newProviders)); + backends.put(config, GraalConfiguration.runtimeInstance().createBackend(newProviders)); } runtimeConfig = new RuntimeConfiguration(p, snippetReflection, backends, wordTypes); @@ -175,7 +175,7 @@ protected ForeignCallsProvider createForeignCallsProvider(RegisterConfig registe } protected LoweringProvider createLoweringProvider(Providers p) { - return SubstrateLoweringProvider.create(p.getMetaAccess(), p.getForeignCalls(), p.getPlatformConfigurationProvider(), p.getMetaAccessExtensionProvider()); + return SubstrateLoweringProvider.createForRuntime(p.getMetaAccess(), p.getForeignCalls(), p.getPlatformConfigurationProvider(), p.getMetaAccessExtensionProvider()); } protected abstract Replacements createReplacements(Providers p, SnippetReflectionProvider snippetReflection); diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateTruffleCompilerImpl.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateTruffleCompilerImpl.java index 7946c82ec8ad..a147fd13694a 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateTruffleCompilerImpl.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateTruffleCompilerImpl.java @@ -62,7 +62,7 @@ public class SubstrateTruffleCompilerImpl extends TruffleCompilerImpl implements @Platforms(Platform.HOSTED_ONLY.class) public SubstrateTruffleCompilerImpl(TruffleCompilerConfiguration config) { super(config); - compilerConfigurationName = GraalConfiguration.instance().getCompilerConfigurationName(); + compilerConfigurationName = GraalConfiguration.runtimeInstance().getCompilerConfigurationName(); } @Platforms(Platform.HOSTED_ONLY.class) diff --git a/vm/ci_common/common.jsonnet b/vm/ci_common/common.jsonnet index 3a672284dfa9..95758533f54b 100644 --- a/vm/ci_common/common.jsonnet +++ b/vm/ci_common/common.jsonnet @@ -378,28 +378,13 @@ local devkits = common_json.devkits; ruby_vm_build_darwin: self.svm_common_darwin + self.sulong_darwin + self.truffleruby_darwin + vm.custom_vm_darwin, full_vm_build_darwin: self.ruby_vm_build_darwin + self.fastr_darwin + self.graalpython_darwin, - libgraal_build_ea_only: ['mx', - '--env', vm.libgraal_env, - # enable ea asserts in the image building code - '--extra-image-builder-argument=-J-ea', - # enable ea asserts in the generated libgraal - '--extra-image-builder-argument=-ea', - 'build' - ], - libgraal_build: ['mx', - '--env', vm.libgraal_env, - # enable all asserts in the image building code - '--extra-image-builder-argument=-J-esa', - '--extra-image-builder-argument=-J-ea', - # enable all asserts in the generated libgraal - '--extra-image-builder-argument=-esa', - '--extra-image-builder-argument=-ea', - 'build' - ], + local libgraal_build(build_args) = + ['mx', '--env', vm.libgraal_env] + ['--extra-image-builder-argument=%s' % arg for arg in build_args] + ['build'], + libgraal_compiler: self.svm_common_linux_amd64 + vm.custom_vm_linux + { run+: [ # enable asserts in the JVM building the image and enable asserts in the resulting native image - $.libgraal_build, + libgraal_build(['-J-esa', '-J-ea', '-esa', '-ea']), ['mx', '--env', vm.libgraal_env, 'gate', '--task', 'LibGraal Compiler'], ], timelimit: '1:00:00', @@ -411,13 +396,29 @@ local devkits = common_json.devkits; }, run+: [ # -ea assertions are enough to keep execution time reasonable - $.libgraal_build_ea_only, + libgraal_build(['-J-ea', '-ea']), ['mx', '--env', vm.libgraal_env, 'gate', '--task', 'LibGraal Truffle'], ], logs+: ['*/graal-compiler.log'], timelimit: '45:00', }, + libgraal_compiler_quickbuild: self.libgraal_compiler + { + run: [ + # enable economy mode building with with the -Ob flag + libgraal_build(['-J-esa', '-J-ea', '-esa', '-ea', '-Ob']), + ['mx', '--env', vm.libgraal_env, 'gate', '--task', 'LibGraal Compiler'], + ], + }, + libgraal_truffle_quickbuild: self.libgraal_truffle + { + run: [ + # enable economy mode building with with the -Ob flag + libgraal_build(['-J-ea', '-ea', '-Ob']), + ['mx', '--env', vm.libgraal_env, 'gate', '--task', 'LibGraal Truffle'], + ], + timelimit: '1:00:00', + }, + # for cases where a maven package is not easily accessible maven_download_unix: { downloads+: { @@ -604,6 +605,9 @@ local devkits = common_json.devkits; self.gate_vm_linux_amd64 + self.libgraal_truffle + vm.vm_java_11 + vm.vm_unittest + { name: 'gate-vm-libgraal-truffle-11-linux-amd64' }, self.gate_vm_linux_amd64 + self.libgraal_truffle + vm.vm_java_17 + vm.vm_unittest + { name: 'gate-vm-libgraal-truffle-17-linux-amd64' }, + self.gate_vm_linux_amd64 + self.libgraal_compiler_quickbuild + vm.vm_java_17 + { name: 'gate-vm-libgraal-compiler-quickbuild-17-linux-amd64' }, + self.gate_vm_linux_amd64 + self.libgraal_truffle_quickbuild + vm.vm_java_17 + { name: 'gate-vm-libgraal-truffle-quickbuild-17-linux-amd64' }, + vm.vm_java_17 + self.svm_common_linux_amd64 + self.sulong_linux + vm.custom_vm_linux + self.gate_vm_linux_amd64 + vm.vm_unittest + { run: [ ['export', 'SVM_SUITE=' + vm.svm_suite], @@ -615,4 +619,4 @@ local devkits = common_json.devkits; ], builds: [{'defined_in': std.thisFile} + b for b in builds], -} \ No newline at end of file +} diff --git a/vm/ci_includes/vm-native.jsonnet b/vm/ci_includes/vm-native.jsonnet index 8b239ad0f116..a189ea41bd63 100644 --- a/vm/ci_includes/vm-native.jsonnet +++ b/vm/ci_includes/vm-native.jsonnet @@ -11,6 +11,14 @@ local vm_common = import '../ci_common/common.jsonnet'; timelimit: '15:00', name: 'gate-vm-native-substratevm-truffle-linux-amd64', }, + vm.vm_java_17 + vm_common.svm_common_linux_amd64 + vm.custom_vm_linux + vm_common.gate_vm_linux_amd64 + { + run+: [ + ['export', 'SVM_SUITE=' + vm.svm_suite], + ['mx', '--dynamicimports', '$SVM_SUITE', '--disable-polyglot', '--disable-libpolyglot', 'gate', '--no-warning-as-error', '--tags', 'build,substratevm-quickbuild'], + ], + timelimit: '15:00', + name: 'gate-vm-native-substratevm-truffle-quickbuild-linux-amd64', + }, vm.vm_java_17 + vm_common.svm_common_linux_amd64 + vm_common.sulong_linux + vm_common.graalpython_linux + vm.custom_vm_linux + vm_common.gate_vm_linux_amd64 + { run+: [ ['export', 'SVM_SUITE=' + vm.svm_suite], @@ -30,4 +38,4 @@ local vm_common = import '../ci_common/common.jsonnet'; ], builds: [{'defined_in': std.thisFile} + b for b in builds], -} \ No newline at end of file +} diff --git a/vm/mx.vm/mx_vm_benchmark.py b/vm/mx.vm/mx_vm_benchmark.py index 460faba9f342..5b32d9c03ab3 100644 --- a/vm/mx.vm/mx_vm_benchmark.py +++ b/vm/mx.vm/mx_vm_benchmark.py @@ -163,6 +163,8 @@ def __init__(self, vm, bm_suite, args): self.base_image_build_args += ['-H:+PrintAnalysisStatistics', '-H:AnalysisStatisticsFile=' + self.analysis_report_path] self.base_image_build_args += ['-H:+PrintCallEdges'] self.base_image_build_args += ['-H:+CollectImageBuildStatistics', '-H:ImageBuildStatisticsFile=' + self.image_build_report_path] + if vm.is_quickbuild: + self.base_image_build_args += ['-Ob'] if vm.is_llvm: self.base_image_build_args += ['-H:CompilerBackend=llvm', '-H:Features=org.graalvm.home.HomeFinderFeature', '-H:DeadlockWatchdogInterval=0'] if vm.gc: @@ -184,6 +186,7 @@ def __init__(self, name, config_name, extra_java_args=None, extra_launcher_args= self.pgo_inline_explored = False self.hotspot_pgo = False self.is_gate = False + self.is_quickbuild = False self.is_llvm = False self.gc = None self.native_architecture = False @@ -205,7 +208,7 @@ def _configure_from_name(self, config_name): return # This defines the allowed config names for NativeImageVM. The ones registered will be available via --jvm-config - rule = r'^(?Pnative-architecture-)?(?Pgate-)?(?Pg1gc-)?(?Pllvm-)?(?Ppgo-|pgo-hotspot-|pgo-ctx-insens-)?(?Paot-inline-|iterative-|inline-explored-)?(?Pce-|ee-)?$' + rule = r'^(?Pnative-architecture-)?(?Pgate-)?(?Pquickbuild-)?(?Pg1gc-)?(?Pllvm-)?(?Ppgo-|pgo-hotspot-|pgo-ctx-insens-)?(?Paot-inline-|iterative-|inline-explored-)?(?Pce-|ee-)?$' mx.logv("== Registering configuration: {}".format(config_name)) match_name = "{}-".format(config_name) # adding trailing dash to simplify the regex @@ -221,6 +224,10 @@ def _configure_from_name(self, config_name): mx.logv("'gate' mode is enabled for {}".format(config_name)) self.is_gate = True + if matching.group("quickbuild") is not None: + mx.logv("'quickbuild' is enabled for {}".format(config_name)) + self.is_quickbuild = True + if matching.group("gc") is not None: gc = matching.group("gc")[:-1] if gc == "g1gc": @@ -1184,7 +1191,7 @@ def register_graalvm_vms(): break # Adding JAVA_HOME VMs to be able to run benchmarks on GraalVM binaries without the need of building it first - for java_home_config in ['default', 'pgo', 'g1gc', 'g1gc-pgo']: + for java_home_config in ['default', 'pgo', 'g1gc', 'g1gc-pgo', 'quickbuild', 'quickbuild-g1gc']: mx_benchmark.add_java_vm(NativeImageVM('native-image-java-home', java_home_config), _suite, 5) diff --git a/vm/mx.vm/mx_vm_gate.py b/vm/mx.vm/mx_vm_gate.py index a946ff06fb4c..afca6f702f7d 100644 --- a/vm/mx.vm/mx_vm_gate.py +++ b/vm/mx.vm/mx_vm_gate.py @@ -48,6 +48,7 @@ class VmGateTasks: compiler = 'compiler' substratevm = 'substratevm' + substratevm_quickbuild = 'substratevm-quickbuild' sulong = 'sulong' graal_js_all = 'graal-js' graal_js_smoke = 'graal-js-smoke' @@ -283,6 +284,7 @@ def gate_body(args, tasks): mx.warn("Skipping libgraal tests: component not enabled") gate_substratevm(tasks) + gate_substratevm(tasks, quickbuild=True) gate_sulong(tasks) gate_python(tasks) gate_svm_sl_tck(tasks) @@ -304,13 +306,21 @@ def native_image_context(common_args=None, hosted_assertions=hosted_assertions): yield native_image return native_image_context, svm.extensions -def gate_substratevm(tasks): - with Task('Run Truffle host interop tests on SVM', tasks, tags=[VmGateTasks.substratevm]) as t: +def gate_substratevm(tasks, quickbuild=False): + tag = VmGateTasks.substratevm + name = 'Run Truffle host interop tests on SVM' + extra_build_args = [] + if quickbuild: + tag = VmGateTasks.substratevm_quickbuild + name += ' with quickbuild' + extra_build_args = ['-Ob'] + + with Task(name, tasks, tags=[tag]) as t: if t: tests = ['ValueHostInteropTest', 'ValueHostConversionTest'] truffle_no_compilation = ['--initialize-at-build-time', '--macro:truffle', '-Dtruffle.TruffleRuntime=com.oracle.truffle.api.impl.DefaultTruffleRuntime'] - args = ['--build-args'] + truffle_no_compilation + ['--'] + tests + args = ['--build-args'] + truffle_no_compilation + extra_build_args + ['--'] + tests native_image_context, svm = graalvm_svm() with native_image_context(svm.IMAGE_ASSERTION_FLAGS) as native_image: svm._native_unittest(native_image, args)