diff --git a/compiler/CHANGELOG.md b/compiler/CHANGELOG.md index 606dfc57b0a6..a22e8f97613c 100644 --- a/compiler/CHANGELOG.md +++ b/compiler/CHANGELOG.md @@ -14,6 +14,7 @@ Optimization phases should use the `OptimizationLog` to log transformations. Rea `Profdiff.md` to learn how to compare performed optimizations in hot compilations of 2 experiments. * The `-Dgraal.PrintCompilation=true` output now includes stub compilations. For example: `StubCompilation-57 exceptionHandler (Object,Word)void | 166us 0B bytecodes 88B codesize 137kB allocated` +* (GR-27475) Add support for the ZGC collector on HotSpot. ## Version 22.3.0 * (GR-19840): An image produced by GraalVM's jlink now includes and uses libgraal by default and its `java -version` output includes GraalVM branding. diff --git a/compiler/ci/ci_common/benchmark-builders.jsonnet b/compiler/ci/ci_common/benchmark-builders.jsonnet index fd7f59ce6829..e2692e76cebd 100644 --- a/compiler/ci/ci_common/benchmark-builders.jsonnet +++ b/compiler/ci/ci_common/benchmark-builders.jsonnet @@ -63,6 +63,19 @@ for suite in bench.groups.main_suites ], + local zgc_builds = [ + c.weekly + hw.x52 + jdk + cc.libgraal + cc.zgc_mode + suite, + for jdk in cc.bench_jdks + for suite in bench.groups.main_suites + ], + + local zgc_avx_builds = [ + c.monthly + hw.x82 + jdk + cc.libgraal + cc.zgc_mode + avx + suite, + for avx in [cc.avx2_mode, cc.avx3_mode] + for jdk in cc.bench_jdks + for suite in bench.groups.main_suites + ], + local no_tiered_builds = [ c.weekly + hw.x52 + jdk + cc.libgraal + cc.no_tiered_comp + suite, for jdk in cc.bench_jdks @@ -76,7 +89,7 @@ ], - local all_builds = main_builds + weekly_amd64_forks_builds + weekly_aarch64_forks_builds + profiling_builds + avx_builds + aarch64_builds + no_tiered_builds + no_profile_info_builds, + local all_builds = main_builds + weekly_amd64_forks_builds + weekly_aarch64_forks_builds + profiling_builds + avx_builds + zgc_builds + zgc_avx_builds + aarch64_builds + no_tiered_builds + no_profile_info_builds, local filtered_builds = [b for b in all_builds if b.is_jdk_supported(b.jdk_version) && b.is_arch_supported(b.arch)], // adds a "defined_in" field to all builds mentioning the location of this current file builds:: [{ defined_in: std.thisFile } + b for b in filtered_builds] diff --git a/compiler/ci/ci_common/compiler-common.libsonnet b/compiler/ci/ci_common/compiler-common.libsonnet index 15af8b5e229e..19923d857f12 100644 --- a/compiler/ci/ci_common/compiler-common.libsonnet +++ b/compiler/ci/ci_common/compiler-common.libsonnet @@ -167,5 +167,12 @@ environment+: { "JVM_CONFIG"+: "-avx3", } + }, + + zgc_mode:: { + platform+:: "-zgc", + environment+: { + "JVM_CONFIG"+: "-zgc", + } } } diff --git a/compiler/ci/ci_common/gate.jsonnet b/compiler/ci/ci_common/gate.jsonnet index 1234ec560550..a69c13c5b4e5 100644 --- a/compiler/ci/ci_common/gate.jsonnet +++ b/compiler/ci/ci_common/gate.jsonnet @@ -5,6 +5,29 @@ local s = self, local t(limit) = {timelimit: limit}, + local jmh_benchmark_test = { + run+: [ + # blackbox jmh test + ["mx", "benchmark", "jmh-dist:GRAAL_COMPILER_MICRO_BENCHMARKS", + "--fail-fast", + "--", + "-Djmh.ignoreLock=true", + "--jvm-config=" + jvm_config, + "--jvm=server", + "--", + ".*TestJMH.*" ], + # whitebox jmh test + ["mx", "benchmark", "jmh-whitebox:*", + "--fail-fast", + "--", + "-Djmh.ignoreLock=true", + "--jvm-config=" + jvm_config, + "--jvm=server", + "--", + ".*TestJMH.*" ] + ] + }, + setup:: { setup+: [ ["cd", "./" + config.compiler.compiler_suite], @@ -56,6 +79,8 @@ }, test:: s.base(no_warning_as_error=true), + test_zgc:: s.base(no_warning_as_error=true, extra_vm_args="-XX:+UseZGC"), + jacoco_gate_args:: ["--jacoco-omit-excluded", "--jacoco-relativize-paths", "--jacoco-omit-src-gen", "--jacocout", "coverage", "--jacoco-format", "lcov"], upload_coverage:: ["mx", "sversions", "--print-repositories", "--json", "|", "coverage-uploader.py", "--associated-repos", "-"], @@ -91,38 +116,31 @@ logs+: ["*/*_compilation.log"] }, + truffle_xcomp_zgc:: s.base("build,unittest", + extra_vm_args="-Dpolyglot.engine.AllowExperimentalOptions=true " + + "-Dpolyglot.engine.CompileImmediately=true " + + "-Dpolyglot.engine.BackgroundCompilation=false " + + "-Dtck.inlineVerifierInstrument=false " + + "-XX:+UseZGC", + extra_unittest_args="--very-verbose truffle") + { + environment+: {"TRACE_COMPILATION": "true"}, + logs+: ["*/*_compilation.log"] + }, + ctw:: s.base("build,ctw", no_warning_as_error=true), + ctw_zgc:: s.base("build,ctw", no_warning_as_error=true, extra_vm_args="-XX:+UseZGC"), ctw_economy:: s.base("build,ctweconomy", extra_vm_args="-Dgraal.CompilerConfiguration=economy"), ctw_phaseplan_fuzzing:: s.base("build,ctwphaseplanfuzzing"), # Runs some benchmarks as tests - benchmarktest:: s.base("build,benchmarktest") + { - run+: [ - # blackbox jmh test - ["mx", "benchmark", "jmh-dist:GRAAL_COMPILER_MICRO_BENCHMARKS", - "--fail-fast", - "--", - "-Djmh.ignoreLock=true", - "--jvm-config=" + jvm_config, - "--jvm=server", - "--", - ".*TestJMH.*" ], - # whitebox jmh test - ["mx", "benchmark", "jmh-whitebox:*", - "--fail-fast", - "--", - "-Djmh.ignoreLock=true", - "--jvm-config=" + jvm_config, - "--jvm=server", - "--", - ".*TestJMH.*" ] - ] - }, + benchmarktest:: s.base("build,benchmarktest") + jmh_benchmark_test, + benchmarktest_zgc:: s.base("build,benchmarktest", extra_vm_args="-XX:+UseZGC") + jmh_benchmark_test, bootstrap:: s.base("build,bootstrap", no_warning_as_error=true), bootstrap_lite:: s.base("build,bootstraplite", no_warning_as_error=true), bootstrap_full:: s.base("build,bootstrapfullverify", no_warning_as_error=true), + bootstrap_full_zgc:: s.base("build,bootstrapfullverify", no_warning_as_error=true, extra_vm_args="-XX:+UseZGC"), bootstrap_economy:: s.base("build,bootstrapeconomy", no_warning_as_error=true, extra_vm_args="-Dgraal.CompilerConfiguration=economy"), style:: c.deps.eclipse + c.deps.jdt + s.base("style,fullbuild,javadoc"), @@ -163,26 +181,34 @@ # fields of the denoted build. local gates = { "gate-compiler-test-labsjdk-20-linux-amd64": t("1:00:00") + c.mach5_target, + "gate-compiler-test-labsjdk-17-linux-amd64": t("1:00:00"), "gate-compiler-test-labsjdk-20-linux-aarch64": t("1:50:00"), "gate-compiler-test-labsjdk-20-darwin-amd64": t("1:00:00") + c.mach5_target, "gate-compiler-test-labsjdk-20-darwin-aarch64": t("1:00:00"), - "gate-compiler-test-labsjdk-20-windows-amd64": t("55:00") + c.mach5_target, + "gate-compiler-test_zgc-labsjdk-20-linux-amd64": t("1:00:00") + c.mach5_target, + "gate-compiler-test_zgc-labsjdk-20-linux-aarch64": t("1:50:00"), + "gate-compiler-test_zgc-labsjdk-20-darwin-amd64": t("1:00:00") + c.mach5_target, + "gate-compiler-test_zgc-labsjdk-20-darwin-aarch64": t("1:00:00"), "gate-compiler-style-labsjdk-20-linux-amd64": t("45:00"), "gate-compiler-ctw-labsjdk-20-linux-amd64": c.mach5_target, "gate-compiler-ctw-labsjdk-20-windows-amd64": t("1:50:00"), + "gate-compiler-ctw_zgc-labsjdk-20-linux-amd64": c.mach5_target, "gate-compiler-ctw_economy-labsjdk-20-linux-amd64": {}, "gate-compiler-ctw_economy-labsjdk-20-windows-amd64": t("1:50:00"), "gate-compiler-benchmarktest-labsjdk-20-linux-amd64": {}, + "gate-compiler-benchmarktest_zgc-labsjdk-20-linux-amd64": {}, "gate-compiler-truffle_xcomp-labsjdk-20-linux-amd64": t("1:30:00"), + "gate-compiler-truffle_xcomp_zgc-labsjdk-20-linux-amd64": t("1:30:00"), "gate-compiler-bootstrap_lite-labsjdk-20-darwin-amd64": t("1:00:00") + c.mach5_target, - "gate-compiler-bootstrap_full-labsjdk-20-linux-amd64": s.many_cores + c.mach5_target + "gate-compiler-bootstrap_full-labsjdk-20-linux-amd64": s.many_cores + c.mach5_target, + "gate-compiler-bootstrap_full_zgc-labsjdk-20-linux-amd64": s.many_cores + c.mach5_target }, # This map defines the builders that run daily. Each key in this map @@ -211,7 +237,6 @@ notify_emails: ["gergo.barany@oracle.com"], }, - "weekly-compiler-test-labsjdk-17-linux-amd64": {}, "weekly-compiler-test-labsjdk-17-linux-aarch64": {}, "weekly-compiler-test-labsjdk-17-windows-amd64": {}, "weekly-compiler-test-labsjdk-17-darwin-amd64": {}, @@ -220,6 +245,7 @@ "weekly-compiler-test_vec16-labsjdk-20-linux-amd64": {}, "weekly-compiler-test_avx0-labsjdk-20-linux-amd64": {}, "weekly-compiler-test_avx1-labsjdk-20-linux-amd64": {}, + "weekly-compiler-test_jtt_phaseplan_fuzzing-labsjdk-20-linux-amd64": { notify_groups: [], notify_emails: ["gergo.barany@oracle.com"], @@ -345,6 +371,28 @@ ] ], + # Test ZGC on support platforms. Windows requires version 1083 or later which will + # probably require adding some capabilities. + local all_zgc_builds = [self.make_build(jdk, os_arch, task).build + for jdk in [ + "17", + "20" + ] + for os_arch in [ + "linux-amd64", + "linux-aarch64", + "darwin-amd64", + "darwin-aarch64" + ] + for task in [ + "test_zgc", + "truffle_xcomp_zgc", + "ctw_zgc", + "benchmarktest_zgc", + "bootstrap_full_zgc" + ] + ], + # Builds run on only on linux-amd64-jdk20 local linux_amd64_jdk20_builds = [self.make_build("20", "linux-amd64", task).build for task in [ @@ -370,6 +418,7 @@ # Complete set of builds defined in this file local all_builds = all_platforms_builds + + all_zgc_builds + linux_amd64_jdk20_builds + linux_amd64_jdk20Debug_builds, diff --git a/compiler/ci/ci_includes/baseline-benchmarks.jsonnet b/compiler/ci/ci_includes/baseline-benchmarks.jsonnet index f307f25508b5..1c67a243b9ae 100644 --- a/compiler/ci/ci_includes/baseline-benchmarks.jsonnet +++ b/compiler/ci/ci_includes/baseline-benchmarks.jsonnet @@ -59,9 +59,17 @@ for suite in bench.groups.main_suites ]), + local zgc_builds = std.flattenArrays([ + [ + c.weekly + hw.x52 + jdk + cc.c2 + cc.zgc_mode + suite, + ] + for jdk in cc.bench_jdks + for suite in bench.groups.main_suites + ]), local all_builds = hotspot_amd64_builds + hotspot_aarch64_builds + hotspot_profiling_builds + - weekly_forks_amd64_builds + weekly_forks_aarch64_builds + daily_economy_builds + weekly_economy_builds + no_tiered_builds, + weekly_forks_amd64_builds + weekly_forks_aarch64_builds + daily_economy_builds + weekly_economy_builds + no_tiered_builds + zgc_builds, local filtered_builds = [b for b in all_builds if b.is_jdk_supported(b.jdk_version) && b.is_arch_supported(b.arch)], + // adds a "defined_in" field to all builds mentioning the location of this current file builds:: [{ defined_in: std.thisFile } + b for b in filtered_builds] } diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index 9180a1e872a1..760caf4ee56e 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -349,10 +349,12 @@ class GraalTags: doc = ['javadoc'] phaseplan_fuzz_jtt_tests = ['phaseplan-fuzz-jtt-tests'] -def _remove_empty_entries(a): +def _remove_empty_entries(a, filter_gcs=False): """Removes empty entries. Return value is always a list.""" if not a: return [] + if filter_gcs: + a = [x for x in a if not x.endswith('GC') or not x.startswith('-XX:+Use')] return [x for x in a if x] def _compiler_error_options(default_compilation_failure_action='ExitVM', vmargs=None, prefix='-Dgraal.'): @@ -392,7 +394,7 @@ def _gate_dacapo(name, iterations, extraVMarguments=None, force_serial_gc=True, vmargs = ['-XX:+UseSerialGC'] if force_serial_gc else [] if set_start_heap_size: vmargs += ['-Xms2g'] - vmargs += ['-XX:-UseCompressedOops', '-Djava.net.preferIPv4Stack=true'] + _compiler_error_options() + _remove_empty_entries(extraVMarguments) + vmargs += ['-XX:-UseCompressedOops', '-Djava.net.preferIPv4Stack=true'] + _compiler_error_options() + _remove_empty_entries(extraVMarguments, filter_gcs=force_serial_gc) args = ['-n', str(iterations), '--preserve'] if threads is not None: args += ['-t', str(threads)] @@ -406,7 +408,7 @@ def jdk_includes_corba(jdk): def _gate_scala_dacapo(name, iterations, extraVMarguments=None): if iterations == -1: return - vmargs = ['-Xms2g', '-XX:+UseSerialGC', '-XX:-UseCompressedOops'] + _compiler_error_options() + _remove_empty_entries(extraVMarguments) + vmargs = ['-Xms2g', '-XX:+UseSerialGC', '-XX:-UseCompressedOops'] + _compiler_error_options() + _remove_empty_entries(extraVMarguments, filter_gcs=True) args = ['-n', str(iterations), '--preserve'] return _run_benchmark('scala-dacapo', name, args, vmargs) diff --git a/compiler/mx.compiler/mx_graal_benchmark.py b/compiler/mx.compiler/mx_graal_benchmark.py index 226c6ba3cf35..519b7fc8ab77 100644 --- a/compiler/mx.compiler/mx_graal_benchmark.py +++ b/compiler/mx.compiler/mx_graal_benchmark.py @@ -127,6 +127,9 @@ def build_jvmci_vm_variants(raw_name, raw_config_name, extra_args, variants, inc ('economy', [], 0, 'economy'), ('economy-no-tiered-comp', ['-XX:-TieredCompilation'], 0, 'economy'), ('g1gc', ['-XX:+UseG1GC'], 12), + ('zgc', ['-XX:+UseZGC'], 12), + ('zgc-avx2', ['-XX:+UseZGC', '-XX:UseAVX=2'], 12), + ('zgc-avx3', ['-XX:+UseZGC', '-XX:UseAVX=3'], 12), ('no-comp-oops', ['-XX:-UseCompressedOops'], 0), ('no-profile-info', ['-Djvmci.UseProfilingInformation=false'], 0), ('no-splitting', ['-Dpolyglot.engine.Splitting=false'], 0), @@ -148,6 +151,7 @@ def build_jvmci_vm_variants(raw_name, raw_config_name, extra_args, variants, inc mx_benchmark.add_java_vm(JvmciJdkVm('server', 'default', ['-server', '-XX:-EnableJVMCI']), _suite, 2) +mx_benchmark.add_java_vm(JvmciJdkVm('server', 'default-zgc', ['-server', '-XX:-EnableJVMCI', '-XX:+UseZGC']), _suite, 2) mx_benchmark.add_java_vm(JvmciJdkVm('server', 'default-no-tiered-comp', ['-server', '-XX:-EnableJVMCI', '-XX:-TieredCompilation']), _suite, 2) mx_benchmark.add_java_vm(JvmciJdkVm('server', 'hosted', ['-server', '-XX:+EnableJVMCI']), _suite, 3) diff --git a/compiler/src/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java b/compiler/src/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java index d2664e62e025..5351b71f0f6e 100644 --- a/compiler/src/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java +++ b/compiler/src/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java @@ -214,6 +214,10 @@ protected void clrex() { public void align(int modulus) { } + @Override + public void halt() { + } + @Override public void jmp(Label l) { } diff --git a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java index b49a6eb4a60d..b296751c237f 100644 --- a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java +++ b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java @@ -552,6 +552,18 @@ public AddressingMode getAddressingMode() { return addressingMode; } + public boolean isBaseRegisterOnly() { + switch (getAddressingMode()) { + case IMMEDIATE_UNSIGNED_SCALED: + case IMMEDIATE_SIGNED_UNSCALED: + return immediate == 0; + case BASE_REGISTER_ONLY: + return true; + default: + return false; + } + } + @Override public String toString() { String addressEncoding; diff --git a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java index 79758a816f8c..b77e4e014adb 100644 --- a/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java +++ b/compiler/src/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java @@ -1984,6 +1984,11 @@ public void align(int modulus) { } } + @Override + public void halt() { + illegal(); + } + /** * Patches jump targets when label gets bound. */ diff --git a/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java b/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java index 948e0b42d4c1..09e0f2309026 100644 --- a/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java +++ b/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java @@ -2812,6 +2812,11 @@ public final int jmp(int jumpTarget, boolean forceDisp32) { return pos; } + @Override + public void halt() { + hlt(); + } + @Override public final void jmp(Label l) { if (l.isBound()) { diff --git a/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java b/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java index c4c74c2a9f47..5f3a6f7efc9f 100644 --- a/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java +++ b/compiler/src/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java @@ -660,6 +660,10 @@ public final int cmpqAndJcc(Register src1, AMD64Address src2, ConditionFlag cc, return applyRMOpAndJcc(CMP.getRMOpcode(QWORD), QWORD, src1, src2, cc, branchTarget, isShortJmp, null); } + public final int cmpqAndJcc(Register src1, AMD64Address src2, ConditionFlag cc, Label branchTarget, boolean isShortJmp, IntConsumer applyBeforeFusedPair) { + return applyRMOpAndJcc(CMP.getRMOpcode(QWORD), QWORD, src1, src2, cc, branchTarget, isShortJmp, applyBeforeFusedPair); + } + public final void cmpAndJcc(OperandSize size, Register src1, Supplier src2, ConditionFlag cc, Label branchTarget) { AMD64Address placeHolder = getPlaceholder(position()); final AMD64RMOp op = CMP.getRMOpcode(size); diff --git a/compiler/src/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java b/compiler/src/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java index cbada2552e44..dac1f0ffefa9 100644 --- a/compiler/src/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java +++ b/compiler/src/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java @@ -37,11 +37,15 @@ import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.gc.ZBarrierSet; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.serviceprovider.GraalServices; import org.graalvm.compiler.test.GraalTest; import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.CodeCacheProvider; @@ -51,14 +55,21 @@ import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.runtime.JVMCI; -import jdk.vm.ci.runtime.JVMCIBackend; public abstract class AssemblerTest extends GraalTest { private final MetaAccessProvider metaAccess; protected final CodeCacheProvider codeCache; private final Backend backend; + private final Providers providers; + + @Before + public void disable() { + // These tests all simply inject a chunk of assembly as the body of a compiled method. Some + // configurations have requirements on the assembly generated in the prolog which are + // violated by doing this. + Assume.assumeFalse("can't work on HotSpot with nmethod entry barriers", providers.getPlatformConfigurationProvider().getBarrierSet() instanceof ZBarrierSet); + } public interface CodeGenTest { byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc); @@ -73,10 +84,10 @@ public static OptionValues getInitialOptions() { } public AssemblerTest() { - JVMCIBackend providers = JVMCI.getRuntime().getHostJVMCIBackend(); + this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); + this.providers = backend.getProviders(); this.metaAccess = providers.getMetaAccess(); this.codeCache = providers.getCodeCache(); - this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); } public MetaAccessProvider getMetaAccess() { diff --git a/compiler/src/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java b/compiler/src/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java index 51218d290317..1f7b4ae52ce8 100644 --- a/compiler/src/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java +++ b/compiler/src/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java @@ -226,6 +226,11 @@ public void bind(Label l) { public abstract void align(int modulus); + /** + * Emit an instruction that will fail in some way if it is reached. + */ + public abstract void halt(); + public abstract void jmp(Label l); protected abstract void patchJumpTarget(int branch, int jumpTarget); @@ -265,20 +270,6 @@ public void reset() { codeBuffer.reset(); } - public InstructionCounter getInstructionCounter() { - throw new UnsupportedOperationException("Instruction counter is not implemented for " + this); - } - - /** - * Instruction counter class which gives the user of the assembler to count different kinds of - * instructions in the generated assembler code. - */ - public interface InstructionCounter { - String[] getSupportedInstructionTypes(); - - int[] countInstructions(String[] instructionTypes, int beginPc, int endPc); - } - public boolean isTargetMP() { return target.isMP; } diff --git a/compiler/src/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java b/compiler/src/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java index a0cc39e15a91..30d94a7b3781 100644 --- a/compiler/src/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java +++ b/compiler/src/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java @@ -734,13 +734,6 @@ public interface MarkId { default Object getId() { return this; } - - /** - * Indicates whether the mark is intended to identify the end of the last instruction or the - * beginning of the next instruction. This information is necessary if the backend needs to - * insert instructions after the normal assembly step. - */ - boolean isMarkAfter(); } /** diff --git a/compiler/src/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java b/compiler/src/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java index 557e029564ea..46231b938b9c 100644 --- a/compiler/src/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java +++ b/compiler/src/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java @@ -111,6 +111,10 @@ public String toString() { return identityHashCodeString(this); } + public boolean isMutable() { + return false; + } + @Override public boolean equals(Object obj) { assert ref != null; @@ -309,7 +313,14 @@ public void close(OptionValues option, int minDataAlignment) { closed = true; // simple heuristic: put items with larger alignment requirement first - dataItems.sort((a, b) -> a.alignment - b.alignment); + dataItems.sort((a, b) -> { + // Workaround JVMCI bug with nmethod entry barriers on aarch64 by forcing mutable data + // items at the beginning of the data section. + if (a.isMutable() != b.isMutable()) { + return Boolean.compare(b.isMutable(), a.isMutable()); + } + return a.alignment - b.alignment; + }); int position = 0; int alignment = 1; diff --git a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64BarrierSetLIRGenerator.java b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64BarrierSetLIRGenerator.java new file mode 100644 index 000000000000..0eb7c0573f8d --- /dev/null +++ b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64BarrierSetLIRGenerator.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.aarch64; + +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.memory.BarrierType; +import org.graalvm.compiler.core.common.memory.MemoryOrderMode; +import org.graalvm.compiler.lir.Variable; +import org.graalvm.compiler.lir.gen.BarrierSetLIRGenerator; + +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; + +/** + * AArch64 specific LIR generation for GC barriers. + */ +public abstract class AArch64BarrierSetLIRGenerator extends BarrierSetLIRGenerator { + + /** + * Emit an atomic read-and-write instruction with any required GC barriers. + */ + public abstract Value emitAtomicReadAndWrite(LIRKind readKind, Value address, Value newValue, BarrierType barrierType); + + /** + * Emit an atomic compare and swap with any required GC barriers. + */ + public abstract void emitCompareAndSwapOp(boolean isLogic, Value address, MemoryOrderMode memoryOrder, AArch64Kind memKind, Variable result, AllocatableValue allocatableExpectedValue, + AllocatableValue allocatableNewValue, BarrierType barrierType); + +} diff --git a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java index 11267a9f8236..ceafee2af4c2 100644 --- a/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java @@ -37,6 +37,7 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.Stride; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.debug.GraalError; @@ -91,6 +92,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64ZapRegistersOp; import org.graalvm.compiler.lir.aarch64.AArch64ZapStackOp; import org.graalvm.compiler.lir.aarch64.AArch64ZeroMemoryOp; +import org.graalvm.compiler.lir.gen.BarrierSetLIRGenerator; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.lir.gen.MoveFactory; @@ -111,8 +113,9 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { - public AArch64LIRGenerator(LIRKindTool lirKindTool, AArch64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, Providers providers, LIRGenerationResult lirGenRes) { - super(lirKindTool, arithmeticLIRGen, moveFactory, providers, lirGenRes); + public AArch64LIRGenerator(LIRKindTool lirKindTool, AArch64ArithmeticLIRGenerator arithmeticLIRGen, BarrierSetLIRGenerator barrierSetLIRGen, MoveFactory moveFactory, Providers providers, + LIRGenerationResult lirGenRes) { + super(lirKindTool, arithmeticLIRGen, barrierSetLIRGen, moveFactory, providers, lirGenRes); } /** @@ -127,6 +130,11 @@ public AllocatableValue moveSp(AllocatableValue val) { return val; } + @Override + public AArch64BarrierSetLIRGenerator getBarrierSet() { + return (AArch64BarrierSetLIRGenerator) super.getBarrierSet(); + } + /** * AArch64 cannot use anything smaller than a word in any instruction other than load and store. */ @@ -179,8 +187,9 @@ protected Value getCompareValueForConstantPointer(Value v) { } @Override - public Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue, MemoryOrderMode memoryOrder) { - emitCompareAndSwap(true, accessKind, address, expectedValue, newValue, memoryOrder); + public Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue, MemoryOrderMode memoryOrder, + BarrierType barrierType) { + emitCompareAndSwap(true, accessKind, address, expectedValue, newValue, memoryOrder, barrierType); assert trueValue.getValueKind().equals(falseValue.getValueKind()); assert isIntConstant(trueValue, 1) && isIntConstant(falseValue, 0); Variable result = newVariable(LIRKind.combine(trueValue, falseValue)); @@ -189,11 +198,11 @@ public Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value } @Override - public Variable emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, MemoryOrderMode memoryOrder) { - return emitCompareAndSwap(false, accessKind, address, expectedValue, newValue, memoryOrder); + public Variable emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, MemoryOrderMode memoryOrder, BarrierType barrierType) { + return emitCompareAndSwap(false, accessKind, address, expectedValue, newValue, memoryOrder, barrierType); } - private Variable emitCompareAndSwap(boolean isLogicVariant, LIRKind accessKind, Value address, Value expectedValue, Value newValue, MemoryOrderMode memoryOrder) { + private Variable emitCompareAndSwap(boolean isLogicVariant, LIRKind accessKind, Value address, Value expectedValue, Value newValue, MemoryOrderMode memoryOrder, BarrierType barrierType) { /* * Atomic instructions only operate on the general (CPU) registers. Hence, float and double * values must temporarily use general registers of the equivalent size. @@ -216,7 +225,7 @@ private Variable emitCompareAndSwap(boolean isLogicVariant, LIRKind accessKind, Variable result = newVariable(toRegisterKind(integerAccessKind)); AllocatableValue allocatableExpectedValue = asAllocatable(reinterpretedExpectedValue); AllocatableValue allocatableNewValue = asAllocatable(reinterpretedNewValue); - append(new CompareAndSwapOp(memKind, memoryOrder, isLogicVariant, result, allocatableExpectedValue, allocatableNewValue, asAllocatable(address))); + emitCompareAndSwapOp(isLogicVariant, address, memoryOrder, memKind, result, allocatableExpectedValue, allocatableNewValue, barrierType); if (isLogicVariant) { // the returned value is unused return null; @@ -226,11 +235,24 @@ private Variable emitCompareAndSwap(boolean isLogicVariant, LIRKind accessKind, } } + protected void emitCompareAndSwapOp(boolean isLogicVariant, Value address, MemoryOrderMode memoryOrder, AArch64Kind memKind, Variable result, AllocatableValue allocatableExpectedValue, + AllocatableValue allocatableNewValue, BarrierType barrierType) { + if (barrierType != BarrierType.NONE && getBarrierSet() != null) { + getBarrierSet().emitCompareAndSwapOp(isLogicVariant, address, memoryOrder, memKind, result, allocatableExpectedValue, allocatableNewValue, barrierType); + } else { + append(new CompareAndSwapOp(memKind, memoryOrder, isLogicVariant, result, allocatableExpectedValue, allocatableNewValue, asAllocatable(address))); + } + } + @Override - public Value emitAtomicReadAndWrite(LIRKind accessKind, Value address, Value newValue) { - Variable result = newVariable(toRegisterKind(accessKind)); - append(new AtomicReadAndWriteOp((AArch64Kind) accessKind.getPlatformKind(), result, asAllocatable(address), asAllocatable(newValue))); - return result; + public Value emitAtomicReadAndWrite(LIRKind accessKind, Value address, Value newValue, BarrierType barrierType) { + if (barrierType != BarrierType.NONE && getBarrierSet() != null) { + return getBarrierSet().emitAtomicReadAndWrite(accessKind, address, newValue, barrierType); + } else { + Variable result = newVariable(toRegisterKind(accessKind)); + append(new AtomicReadAndWriteOp((AArch64Kind) accessKind.getPlatformKind(), result, asAllocatable(address), asAllocatable(newValue))); + return result; + } } @Override diff --git a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java index e2711bc18d6e..9916c3650a9e 100644 --- a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java +++ b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java @@ -26,8 +26,8 @@ package org.graalvm.compiler.core.amd64; import org.graalvm.compiler.asm.amd64.AMD64Address; -import org.graalvm.compiler.core.common.Stride; import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.core.common.Stride; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.debug.DebugContext; @@ -38,7 +38,7 @@ import org.graalvm.compiler.nodes.calc.LeftShiftNode; import org.graalvm.compiler.nodes.calc.NegateNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; -import org.graalvm.compiler.phases.common.AddressLoweringPhase.AddressLowering; +import org.graalvm.compiler.phases.common.AddressLoweringByNodePhase.AddressLowering; import jdk.vm.ci.meta.JavaConstant; diff --git a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64BarrierSetLIRGenerator.java b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64BarrierSetLIRGenerator.java new file mode 100644 index 000000000000..00a59b07ab68 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64BarrierSetLIRGenerator.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.amd64; + +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.memory.BarrierType; +import org.graalvm.compiler.lir.amd64.AMD64AddressValue; +import org.graalvm.compiler.lir.gen.BarrierSetLIRGenerator; + +import jdk.vm.ci.amd64.AMD64Kind; +import jdk.vm.ci.code.RegisterValue; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; + +/** + * AMD64 specific LIR generation for GC barriers. + */ +public abstract class AMD64BarrierSetLIRGenerator extends BarrierSetLIRGenerator { + + /** + * Emit an atomic read-and-write instruction with any required GC barriers. + */ + public abstract Value emitAtomicReadAndWrite(LIRKind readKind, Value address, Value newValue, BarrierType barrierType); + + /** + * Emit an atomic compare and swap with any required GC barriers. + */ + public abstract void emitCompareAndSwapOp(LIRKind accessKind, AMD64Kind memKind, RegisterValue raxValue, AMD64AddressValue address, AllocatableValue newValue, + BarrierType barrierType); +} diff --git a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java index c3de29c58897..396afa08b406 100644 --- a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java @@ -56,6 +56,7 @@ import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.Stride; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; @@ -122,6 +123,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp; import org.graalvm.compiler.lir.amd64.AMD64ZeroMemoryOp; import org.graalvm.compiler.lir.amd64.vector.AMD64VectorCompareOp; +import org.graalvm.compiler.lir.gen.BarrierSetLIRGenerator; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.lir.gen.MoveFactory; @@ -130,7 +132,6 @@ import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64.CPUFeature; import jdk.vm.ci.amd64.AMD64Kind; -import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterValue; import jdk.vm.ci.code.StackSlot; @@ -148,8 +149,14 @@ */ public abstract class AMD64LIRGenerator extends LIRGenerator { - public AMD64LIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, Providers providers, LIRGenerationResult lirGenRes) { - super(lirKindTool, arithmeticLIRGen, moveFactory, providers, lirGenRes); + public AMD64LIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, BarrierSetLIRGenerator barrierSetLIRGen, MoveFactory moveFactory, Providers providers, + LIRGenerationResult lirGenRes) { + super(lirKindTool, arithmeticLIRGen, barrierSetLIRGen, moveFactory, providers, lirGenRes); + } + + @Override + public AMD64BarrierSetLIRGenerator getBarrierSet() { + return (AMD64BarrierSetLIRGenerator) super.getBarrierSet(); } @Override @@ -234,7 +241,7 @@ private AllocatableValue asAllocatable(Value value, ValueKind kind) { } } - private Value emitCompareAndSwap(boolean isLogic, LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + private Value emitCompareAndSwap(boolean isLogic, LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue, BarrierType barrierType) { ValueKind kind = newValue.getValueKind(); assert kind.equals(expectedValue.getValueKind()); @@ -256,7 +263,7 @@ private Value emitCompareAndSwap(boolean isLogic, LIRKind accessKind, Value addr RegisterValue aRes = AMD64.rax.asValue(integerAccessKind); AllocatableValue allocatableNewValue = asAllocatable(reinterpretedNewValue, integerAccessKind); emitMove(aRes, reinterpretedExpectedValue); - append(new CompareAndSwapOp(memKind, aRes, addressValue, aRes, allocatableNewValue)); + emitCompareAndSwapOp(integerAccessKind, memKind, aRes, addressValue, allocatableNewValue, barrierType); if (isLogic) { assert trueValue.getValueKind().equals(falseValue.getValueKind()); @@ -273,27 +280,36 @@ private Value emitCompareAndSwap(boolean isLogic, LIRKind accessKind, Value addr } @Override - public Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue, MemoryOrderMode memoryOrder) { - return LIRValueUtil.asVariable(emitCompareAndSwap(true, accessKind, address, expectedValue, newValue, trueValue, falseValue)); + public Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue, MemoryOrderMode memoryOrder, + BarrierType barrierType) { + return LIRValueUtil.asVariable(emitCompareAndSwap(true, accessKind, address, expectedValue, newValue, trueValue, falseValue, barrierType)); } @Override - public Value emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, MemoryOrderMode memoryOrder) { - return emitCompareAndSwap(false, accessKind, address, expectedValue, newValue, null, null); + public Value emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, MemoryOrderMode memoryOrder, BarrierType barrierType) { + return emitCompareAndSwap(false, accessKind, address, expectedValue, newValue, null, null, barrierType); } - public void emitCompareAndSwapBranch(ValueKind kind, AMD64AddressValue address, Value expectedValue, Value newValue, Condition condition, LabelRef trueLabel, LabelRef falseLabel, - double trueLabelProbability) { + public void emitCompareAndSwapBranch(LIRKind kind, AMD64AddressValue address, Value expectedValue, Value newValue, Condition condition, LabelRef trueLabel, LabelRef falseLabel, + double trueLabelProbability, BarrierType barrierType) { assert kind.getPlatformKind().getSizeInBytes() <= expectedValue.getValueKind().getPlatformKind().getSizeInBytes(); assert kind.getPlatformKind().getSizeInBytes() <= newValue.getValueKind().getPlatformKind().getSizeInBytes(); assert condition == Condition.EQ || condition == Condition.NE; AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind(); RegisterValue raxValue = AMD64.rax.asValue(kind); emitMove(raxValue, expectedValue); - append(new CompareAndSwapOp(memKind, raxValue, address, raxValue, asAllocatable(newValue))); + emitCompareAndSwapOp(kind, memKind, raxValue, address, asAllocatable(newValue), barrierType); append(new BranchOp(condition, trueLabel, falseLabel, trueLabelProbability)); } + protected void emitCompareAndSwapOp(LIRKind accessKind, AMD64Kind memKind, RegisterValue raxValue, AMD64AddressValue address, AllocatableValue newValue, BarrierType barrierType) { + if (barrierType != BarrierType.NONE && getBarrierSet() != null) { + getBarrierSet().emitCompareAndSwapOp(accessKind, memKind, raxValue, address, newValue, barrierType); + } else { + append(new CompareAndSwapOp(memKind, raxValue, address, raxValue, newValue)); + } + } + @Override public Value emitAtomicReadAndAdd(LIRKind accessKind, Value address, Value delta) { Variable result = newVariable(toRegisterKind(accessKind)); @@ -303,7 +319,10 @@ public Value emitAtomicReadAndAdd(LIRKind accessKind, Value address, Value delta } @Override - public Value emitAtomicReadAndWrite(LIRKind accessKind, Value address, Value newValue) { + public Value emitAtomicReadAndWrite(LIRKind accessKind, Value address, Value newValue, BarrierType barrierType) { + if (barrierType != BarrierType.NONE && getBarrierSet() != null) { + return getBarrierSet().emitAtomicReadAndWrite(accessKind, address, newValue, barrierType); + } Variable result = newVariable(toRegisterKind(accessKind)); AMD64AddressValue addressValue = asAddressValue(address); append(new AMD64Move.AtomicReadAndWriteOp((AMD64Kind) accessKind.getPlatformKind(), result, addressValue, asAllocatable(newValue))); @@ -569,8 +588,6 @@ public void emitMembar(int barriers) { } } - public abstract void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args, int numberOfFloatingPointArguments); - @Override protected void emitForeignCallOp(ForeignCallLinkage linkage, Value targetAddress, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { long maxOffset = linkage.getMaxCallTargetOffset(); diff --git a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java index 5f90f4d54fc2..3bf9e6b50a72 100644 --- a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java +++ b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java @@ -409,7 +409,7 @@ public ComplexMatchResult ifCompareValueCas(IfNode root, CompareNode compare, Va Value expectedValue = operand(cas.getExpectedValue()); Value newValue = operand(cas.getNewValue()); AMD64AddressValue address = (AMD64AddressValue) operand(cas.getAddress()); - getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, Condition.EQ, trueLabel, falseLabel, trueLabelProbability); + getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, Condition.EQ, trueLabel, falseLabel, trueLabelProbability, cas.getBarrierType()); return null; }; } @@ -442,7 +442,7 @@ public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, Va Value newValue = operand(cas.getNewValue()); AMD64AddressValue address = (AMD64AddressValue) operand(cas.getAddress()); Condition condition = successIsTrue ? Condition.EQ : Condition.NE; - getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, condition, trueLabel, falseLabel, trueLabelProbability); + getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, condition, trueLabel, falseLabel, trueLabelProbability, cas.getBarrierType()); return null; }; } diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/memory/BarrierType.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/memory/BarrierType.java new file mode 100644 index 000000000000..9f9354e77965 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/memory/BarrierType.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.common.memory; + +/** + * The types of write and read barriers attached to memory operations. + */ +public enum BarrierType { + /** + * Primitive access which does not require a barrier. + */ + NONE, + + /** + * Array object access. + */ + ARRAY, + + /** + * Field object access. + */ + FIELD, + + /** + * Read barrier. + */ + READ, + + /** + * Unknown (aka field or array) object access. + */ + UNKNOWN, + + /** + * Read of {@link java.lang.ref.Reference}.referent. In the HotSpot world this corresponds to an + * access decorated with {@code ON_WEAK_OOP_REF}. Depending on the particular garbage collector + * this might do something different than {@link #READ}. + */ + REFERENCE_GET, + + /** + * Read of {@link java.lang.ref.Reference}{@code .referent} in the context of + * {@link java.lang.ref.WeakReference}{@code .refersTo0}. In the HotSpot world this corresponds + * to an access decorated with {@code AS_NO_KEEPALIVE | ON_WEAK_OOP_REF}. Depending on the + * particular garbage collector this might do something different than {@link #READ}. + */ + + WEAK_REFERS_TO, + + /** + * Read of {@link java.lang.ref.Reference}{@code .referent} in the context of + * {@link java.lang.ref.PhantomReference}{@code .refersTo0}. In the HotSpot world this + * corresponds to an access decorated with {@code AS_NO_KEEPALIVE | ON_PHANTOM_OOP_REF}. + * Depending on the particular garbage collector this might do something different than + * {@link #READ}. + */ + PHANTOM_REFERS_TO +} diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java index 0ade3c91903b..2b63b8915a7e 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java @@ -149,6 +149,13 @@ public boolean isIntegerStamp() { return this instanceof IntegerStamp; } + /** + * Tests whether this stamp represents an Object value. + */ + public boolean isObjectStamp() { + return this instanceof AbstractObjectStamp; + } + /** * If this stamp represents a single value, the methods returns this single value. It returns * null otherwise. diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DirectByteBufferTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DirectByteBufferTest.java index 880b2ed71d89..51f37defaeaa 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DirectByteBufferTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DirectByteBufferTest.java @@ -28,6 +28,7 @@ import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Collection; + import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -82,7 +83,8 @@ public int hashCode() { @Override public String toString() { - return String.format("0x%02x, 0x%04x, 0x%08x, 0x%016x,0x%08x, 0x%016x", byteValue, shortValue, intValue, Float.floatToRawIntBits(floatValue), Double.doubleToRawLongBits(doubleValue)); + return String.format("0x%02x, 0x%04x, 0x%08x, 0x%016x,0x%08x, 0x%016x", byteValue, shortValue, intValue, longValue, Float.floatToRawIntBits(floatValue), + Double.doubleToRawLongBits(doubleValue)); } } diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java index df2a90d8037a..255f90cbf1f9 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java @@ -1213,7 +1213,7 @@ protected CompilationResult compile(ResolvedJavaMethod installedCodeOwner, Struc try (DebugContext.Scope s = debug.scope("Compile", graphToCompile)) { assert options != null; Request request = new Request<>(graphToCompile, installedCodeOwner, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), getOptimisticOptimizations(), - graphToCompile.getProfilingInfo(), createSuites(options), createLIRSuites(options), compilationResult, CompilationResultBuilderFactory.Default, true); + graphToCompile.getProfilingInfo(), createSuites(options), createLIRSuites(options), compilationResult, CompilationResultBuilderFactory.Default, null, true); return GraalCompiler.compile(request); } catch (Throwable e) { throw debug.handle(e); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java index b352577ebb3d..26d20733d3ce 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java @@ -53,7 +53,7 @@ protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph throw debug.handle(e); } - LIRGenerationResult lirGen = LIRCompilerBackend.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions())); + LIRGenerationResult lirGen = LIRCompilerBackend.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions()), null); return lirGen; } diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java index 97f63f4561cc..a7f0e366adc5 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java @@ -38,6 +38,7 @@ import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.phases.OptimisticOptimizations; @@ -77,6 +78,7 @@ public static class Request { public final LIRSuites lirSuites; public final T compilationResult; public final CompilationResultBuilderFactory factory; + public final EntryPointDecorator entryPointDecorator; public final boolean verifySourcePositions; /** @@ -95,7 +97,7 @@ public static class Request { */ public Request(StructuredGraph graph, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, Suites suites, LIRSuites lirSuites, T compilationResult, CompilationResultBuilderFactory factory, - boolean verifySourcePositions) { + EntryPointDecorator entryPointDecorator, boolean verifySourcePositions) { this.graph = graph; this.installedCodeOwner = installedCodeOwner; this.providers = providers; @@ -107,6 +109,7 @@ public Request(StructuredGraph graph, ResolvedJavaMethod installedCodeOwner, Pro this.lirSuites = lirSuites; this.compilationResult = compilationResult; this.factory = factory; + this.entryPointDecorator = entryPointDecorator; this.verifySourcePositions = verifySourcePositions; } @@ -131,10 +134,25 @@ public T execute() { public static T compileGraph(StructuredGraph graph, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, Suites suites, LIRSuites lirSuites, T compilationResult, CompilationResultBuilderFactory factory, boolean verifySourcePositions) { - return compile(new Request<>(graph, installedCodeOwner, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, compilationResult, factory, + return compile(new Request<>(graph, installedCodeOwner, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, compilationResult, factory, null, verifySourcePositions)); } + /** + * Requests compilation of a given graph. + * + * @param graph the graph to be compiled + * @param installedCodeOwner the method the compiled code will be associated with once + * installed. This argument can be null. + * @return the result of the compilation + */ + public static T compileGraph(StructuredGraph graph, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, + PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, Suites suites, LIRSuites lirSuites, T compilationResult, + CompilationResultBuilderFactory factory, EntryPointDecorator entryPointDecorator, boolean verifySourcePositions) { + return compile(new Request<>(graph, installedCodeOwner, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, compilationResult, factory, + entryPointDecorator, verifySourcePositions)); + } + /** * Services a given compilation request. * @@ -149,7 +167,7 @@ public static T compile(Request r) { DebugCloseable a = CompilerTimer.start(debug); DebugCloseable b = CompilerMemory.start(debug)) { emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites); - r.backend.emitBackEnd(r.graph, null, r.installedCodeOwner, r.compilationResult, r.factory, null, r.lirSuites); + r.backend.emitBackEnd(r.graph, null, r.installedCodeOwner, r.compilationResult, r.factory, r.entryPointDecorator, null, r.lirSuites); if (r.verifySourcePositions) { assert r.graph.verifySourcePositions(true); } diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java index 153e7871a99d..3c9ba21b42fc 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java @@ -47,6 +47,7 @@ import org.graalvm.compiler.lir.alloc.OutOfRegistersException; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; @@ -78,12 +79,11 @@ public class LIRCompilerBackend { private static final TimerKey BackEnd = DebugContext.timer("BackEnd").doc("Time spent in EmitLIR and EmitCode."); @SuppressWarnings("try") - public static void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult, - CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) { + public static void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, CompilationResult compilationResult, + CompilationResultBuilderFactory factory, EntryPointDecorator entryPointDecorator, RegisterConfig registerConfig, LIRSuites lirSuites) { DebugContext debug = graph.getDebug(); try (DebugContext.Scope s = debug.scope("BackEnd", graph, graph.getLastSchedule()); DebugCloseable a = BackEnd.start(debug)) { - LIRGenerationResult lirGen = null; - lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites); + LIRGenerationResult lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites, entryPointDecorator); try (DebugContext.Scope s2 = debug.scope("CodeGen", lirGen, lirGen.getLIR())) { int bytecodeSize = graph.method() == null ? 0 : graph.getBytecodeSize(); compilationResult.setHasUnsafeAccess(graph.hasUnsafeAccess()); @@ -96,7 +96,8 @@ public static void emitBackEnd(StructuredGraph gra lirGen, compilationResult, installedCodeOwner, - factory); + factory, + entryPointDecorator); } catch (Throwable e) { throw debug.handle(e); } @@ -108,15 +109,16 @@ public static void emitBackEnd(StructuredGraph gra } @SuppressWarnings("try") - public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) { + public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites, + EntryPointDecorator entryPointDecorator) { String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions()); String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(","); try { - return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); + return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo, entryPointDecorator); } catch (OutOfRegistersException e) { if (allocationRestrictedTo != null) { allocationRestrictedTo = null; - return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); + return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo, entryPointDecorator); } /* If the re-execution fails we convert the exception into a "hard" failure */ throw new GraalError(e); @@ -131,7 +133,7 @@ private static LIRGenerationResult emitLIR0(Backend backend, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites, - String[] allocationRestrictedTo) { + String[] allocationRestrictedTo, EntryPointDecorator entryPointDecorator) { DebugContext debug = graph.getDebug(); try (DebugContext.Scope ds = debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start(debug)) { assert graph.isAfterStage(StageFlag.VALUE_PROXY_REMOVAL); @@ -159,6 +161,10 @@ private static LIRGenerationResult emitLIR0(Backend backend, LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule); new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context); + if (entryPointDecorator != null) { + entryPointDecorator.initialize(backend.getProviders(), lirGenRes); + } + try (DebugContext.Scope s = debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) { // Dump LIR along with HIR (the LIR is looked up from context) debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation"); @@ -206,14 +212,15 @@ public static void emitCode(Backend backend, LIRGenerationResult lirGenRes, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, - CompilationResultBuilderFactory factory) { + CompilationResultBuilderFactory factory, + EntryPointDecorator entryPointDecorator) { DebugContext debug = lirGenRes.getLIR().getDebug(); try (DebugCloseable a = EmitCode.start(debug); CompilerPhaseScope cps = debug.enterCompilerPhase("Emit code");) { LIRGenerationProvider lirBackend = (LIRGenerationProvider) backend; FrameMap frameMap = lirGenRes.getFrameMap(); CompilationResultBuilder crb = lirBackend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory); - lirBackend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner); + lirBackend.emitCode(crb, installedCodeOwner, entryPointDecorator); if (assumptions != null && !assumptions.isEmpty()) { compilationResult.setAssumptions(assumptions.toArray()); } diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRGenerationProvider.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRGenerationProvider.java index 953e951087a6..db2de5f6ec64 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRGenerationProvider.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRGenerationProvider.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; @@ -65,6 +66,7 @@ CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenR * * @param installedCodeOwner the method the compiled code will be associated with once * installed. This argument can be null. + * @param entryPointDecorator optional argument that injects code into the entry point. */ - void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner); + void emitCode(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, EntryPointDecorator entryPointDecorator); } diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java index 9214260797c9..a8d221f33570 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java @@ -167,6 +167,10 @@ public Node getRoot() { return root; } + public MatchStatement getRule() { + return rule; + } + public Result captureNamedValue(String name, Class type, Node value) { if (namedNodes == null) { namedNodes = EconomicMap.create(Equivalence.DEFAULT); diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java index 528e684134be..121a1732e88e 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java @@ -24,6 +24,7 @@ */ package org.graalvm.compiler.core.match; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; @@ -31,6 +32,7 @@ import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.calc.FloatingNode; +import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess; /** * A simple recursive pattern matcher for a DAG of nodes. @@ -47,6 +49,7 @@ enum MatchResultCode { NOT_SAFE, ALREADY_USED, TOO_LATE, + BARRIER, } /** @@ -73,6 +76,7 @@ static class Result { private static final CounterKey MatchResult_NOT_SAFE = DebugContext.counter("MatchResult_NOT_SAFE"); private static final CounterKey MatchResult_ALREADY_USED = DebugContext.counter("MatchResult_ALREADY_USED"); private static final CounterKey MatchResult_TOO_LATE = DebugContext.counter("MatchResult_TOO_LATE"); + private static final CounterKey MatchResult_BARRIER = DebugContext.counter("MatchResult_BARRIER"); static final Result OK = new Result(MatchResultCode.OK, null, null); private static final Result CACHED_WRONG_CLASS = new Result(MatchResultCode.WRONG_CLASS, null, null); @@ -82,6 +86,7 @@ static class Result { private static final Result CACHED_NOT_SAFE = new Result(MatchResultCode.NOT_SAFE, null, null); private static final Result CACHED_ALREADY_USED = new Result(MatchResultCode.ALREADY_USED, null, null); private static final Result CACHED_TOO_LATE = new Result(MatchResultCode.TOO_LATE, null, null); + private static final Result CACHED_BARRIER = new Result(MatchResultCode.BARRIER, null, null); static Result wrongClass(Node node, MatchPattern matcher) { MatchResult_WRONG_CLASS.increment(node.getDebug()); @@ -118,6 +123,11 @@ static Result tooLate(Node node, MatchPattern matcher) { return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.TOO_LATE, node, matcher) : CACHED_TOO_LATE; } + static Result barrier(Node node, MatchPattern matcher) { + MatchResult_BARRIER.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.BARRIER, node, matcher) : CACHED_BARRIER; + } + @Override public String toString() { if (code == MatchResultCode.OK) { @@ -238,6 +248,11 @@ Result matchUsage(Node node, MatchContext context) { } private Result matchUsage(Node node, MatchContext context, boolean atRoot) { + // Barriers can't be folded into other operations + if (node instanceof OnHeapMemoryAccess && ((OnHeapMemoryAccess) node).getBarrierType() != BarrierType.NONE) { + return Result.barrier(node, context.getRule().getPattern()); + } + Result result = matchType(node); if (result != Result.OK) { return result; diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java index a25e386f2fb3..579c60c39dea 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java @@ -24,8 +24,10 @@ */ package org.graalvm.compiler.core.phases; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.phases.PlaceholderPhase; import org.graalvm.compiler.phases.common.AddressLoweringPhase; +import org.graalvm.compiler.phases.common.BarrierSetVerificationPhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ExpandLogicPhase; import org.graalvm.compiler.phases.common.LowTierLoweringPhase; @@ -38,6 +40,11 @@ public EconomyLowTier() { CanonicalizerPhase canonicalizer = CanonicalizerPhase.create(); appendPhase(new LowTierLoweringPhase(canonicalizer)); appendPhase(new ExpandLogicPhase(canonicalizer)); + + if (Assertions.assertionsEnabled()) { + appendPhase(new BarrierSetVerificationPhase()); + } + /* * This placeholder should be replaced by an instance of {@link AddressLoweringPhase} * specific to the target architecture for this compilation. This should be done by the diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java index ca69d28881b6..ab00cd303004 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java @@ -79,7 +79,7 @@ public LowTier(OptionValues options) { * specific to the target architecture for this compilation. This should be done by the * backend or the target specific suites provider. */ - appendPhase(new PlaceholderPhase(AddressLoweringPhase.class)); + appendPhase(new PlaceholderPhase<>(AddressLoweringPhase.class)); appendPhase(FinalCanonicalizerPhase.createFromCanonicalizer(canonicalizerWithoutGVN)); diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java index 70e98c11533e..ab9d053d2d4e 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java @@ -38,6 +38,7 @@ import org.graalvm.compiler.core.gen.LIRCompilerBackend; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.options.OptionValues; @@ -285,8 +286,10 @@ public void emitBackEnd(StructuredGraph graph, ResolvedJavaMethod installedCodeOwner, CompilationResult compilationResult, CompilationResultBuilderFactory factory, - RegisterConfig config, LIRSuites lirSuites) { - LIRCompilerBackend.emitBackEnd(graph, stub, installedCodeOwner, this, compilationResult, factory, config, lirSuites); + EntryPointDecorator entryPointDecorator, + RegisterConfig config, + LIRSuites lirSuites) { + LIRCompilerBackend.emitBackEnd(graph, stub, installedCodeOwner, this, compilationResult, factory, entryPointDecorator, config, lirSuites); } /** diff --git a/compiler/src/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java b/compiler/src/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java index 390eb1305c5c..445f55e52820 100644 --- a/compiler/src/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java +++ b/compiler/src/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java @@ -212,6 +212,9 @@ static String createUnique(OptionValues options, OptionKey baseNameOptio String result = getPath(dumpDir, fileName); try { if (createMissingDirectory) { + if (exists(result)) { + throw new FileAlreadyExistsException(result); + } return createDirectories(result); } else { try { diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java index 91ca0ad81bf4..cbb0dc59ee99 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java @@ -1171,7 +1171,7 @@ void register(Node node) { if (currentNodeSourcePosition != null && trackNodeSourcePosition()) { node.setNodeSourcePosition(currentNodeSourcePosition); } - if (TrackNodeInsertion.getValue(getOptions())) { + if (TrackNodeInsertion.getValue(getOptions()) && node.getInsertionPosition() == null) { node.setInsertionPosition(new NodeInsertionStackTrace()); } diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java index 2607f98e0a07..c779d494835b 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java @@ -1315,6 +1315,9 @@ final Node clone(Graph into, EnumSet edgesToCopy) { if (getNodeSourcePosition() != null && (into == null || into.trackNodeSourcePosition())) { newNode.setNodeSourcePosition(getNodeSourcePosition()); } + if (getInsertionPosition() != null) { + newNode.setInsertionPosition(getInsertionPosition()); + } if (into != null) { into.register(newNode); } diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java index f54e36079756..e0a38e7e62c7 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java @@ -33,6 +33,7 @@ import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.IMMEDIATE_UNSIGNED_SCALED; import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.NMETHOD_ENTRY_BARRIER; import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException; import org.graalvm.compiler.asm.Label; @@ -41,11 +42,13 @@ import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister; import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.code.DataSection; import org.graalvm.compiler.core.aarch64.AArch64NodeMatchRules; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.gen.LIRGenerationProvider; import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotDataBuilder; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; @@ -62,6 +65,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.asm.DataBuilder; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; import org.graalvm.compiler.lir.asm.FrameContext; import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; @@ -160,7 +164,56 @@ private boolean hasInvalidatePlaceholder(CompilationResult compilationResult) { return instruction == masm.getInt(0); } - private class HotSpotFrameContext implements FrameContext { + public static void rawLeave(CompilationResultBuilder crb) { + AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; + FrameMap frameMap = crb.frameMap; + final int totalFrameSize = frameMap.totalFrameSize(); + // based on HotSpot's macroAssembler_aarch64.cpp MacroAssembler::leave_frame + try (ScratchRegister sc = masm.getScratchRegister()) { + int wordSize = 8; + Register scratch = sc.getRegister(); + final int frameSize = frameMap.frameSize(); + assert totalFrameSize > 0; + AArch64Address.AddressingMode addressingMode = AArch64Address.AddressingMode.IMMEDIATE_PAIR_SIGNED_SCALED; + if (AArch64Address.isValidImmediateAddress(64, addressingMode, frameSize)) { + masm.ldp(64, fp, lr, AArch64Address.createImmediateAddress(64, addressingMode, sp, frameSize)); + masm.add(64, sp, sp, totalFrameSize); + } else { + int frameRecordSize = 2 * wordSize; + masm.add(64, sp, sp, totalFrameSize - frameRecordSize, scratch); + masm.ldp(64, fp, lr, AArch64Address.createImmediateAddress(64, AArch64Address.AddressingMode.IMMEDIATE_PAIR_POST_INDEXED, sp, frameRecordSize)); + } + } + } + + public static void rawEnter(CompilationResultBuilder crb, FrameMap frameMap, AArch64MacroAssembler masm, boolean preserveFramePointer) { + // based on HotSpot's macroAssembler_aarch64.cpp MacroAssembler::build_frame + try (ScratchRegister sc = masm.getScratchRegister()) { + final int frameSize = frameMap.frameSize(); + final int totalFrameSize = frameMap.totalFrameSize(); + int wordSize = crb.target.arch.getWordSize(); + assert frameSize + 2 * wordSize == totalFrameSize : "total framesize should be framesize + 2 words"; + Register scratch = sc.getRegister(); + assert totalFrameSize > 0; + AArch64Address.AddressingMode addressingMode = AArch64Address.AddressingMode.IMMEDIATE_PAIR_SIGNED_SCALED; + if (AArch64Address.isValidImmediateAddress(64, addressingMode, frameSize)) { + masm.sub(64, sp, sp, totalFrameSize); + masm.stp(64, fp, lr, AArch64Address.createImmediateAddress(64, addressingMode, sp, frameSize)); + if (preserveFramePointer) { + masm.add(64, fp, sp, frameSize); + } + } else { + int frameRecordSize = 2 * wordSize; + masm.stp(64, fp, lr, AArch64Address.createImmediateAddress(64, AArch64Address.AddressingMode.IMMEDIATE_PAIR_PRE_INDEXED, sp, -frameRecordSize)); + if (preserveFramePointer) { + masm.mov(64, fp, sp); + } + masm.sub(64, sp, sp, totalFrameSize - frameRecordSize, scratch); + } + } + } + + class HotSpotFrameContext implements FrameContext { final boolean isStub; final boolean preserveFramePointer; @@ -172,38 +225,16 @@ private class HotSpotFrameContext implements FrameContext { @Override public void enter(CompilationResultBuilder crb) { FrameMap frameMap = crb.frameMap; - final int frameSize = frameMap.frameSize(); - final int totalFrameSize = frameMap.totalFrameSize(); - int wordSize = crb.target.arch.getWordSize(); - assert frameSize + 2 * wordSize == totalFrameSize : "total framesize should be framesize + 2 words"; AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; if (!isStub) { emitStackOverflowCheck(crb); } crb.blockComment("[method prologue]"); + rawEnter(crb, frameMap, masm, config.preserveFramePointer); - // based on HotSpot's macroAssembler_aarch64.cpp MacroAssembler::build_frame - try (ScratchRegister sc = masm.getScratchRegister()) { - Register scratch = sc.getRegister(); - assert totalFrameSize > 0; - AArch64Address.AddressingMode addressingMode = AArch64Address.AddressingMode.IMMEDIATE_PAIR_SIGNED_SCALED; - if (AArch64Address.isValidImmediateAddress(64, addressingMode, frameSize)) { - masm.sub(64, sp, sp, totalFrameSize); - masm.stp(64, fp, lr, AArch64Address.createImmediateAddress(64, addressingMode, sp, frameSize)); - if (preserveFramePointer) { - masm.add(64, fp, sp, frameSize); - } - } else { - int frameRecordSize = 2 * wordSize; - masm.stp(64, fp, lr, AArch64Address.createImmediateAddress(64, AArch64Address.AddressingMode.IMMEDIATE_PAIR_PRE_INDEXED, sp, -frameRecordSize)); - if (preserveFramePointer) { - masm.mov(64, fp, sp); - } - masm.sub(64, sp, sp, totalFrameSize - frameRecordSize, scratch); - } - } - if (HotSpotMarkId.FRAME_COMPLETE.isAvailable()) { - crb.recordMark(HotSpotMarkId.FRAME_COMPLETE); + crb.recordMark(HotSpotMarkId.FRAME_COMPLETE); + if (!isStub && config.nmethodEntryBarrier != 0) { + emitNmethodEntryBarrier(crb, masm); } if (ZapStackOnMethodEntry.getValue(crb.getOptions())) { try (ScratchRegister sc = masm.getScratchRegister()) { @@ -214,7 +245,7 @@ public void enter(CompilationResultBuilder crb) { try (ScratchRegister sc2 = masm.getScratchRegister()) { Register value = sc2.getRegister(); masm.mov(value, 0xBADDECAFFC0FFEEL); - for (int i = 0; i < frameSize; i += longSize) { + for (int i = 0; i < frameMap.frameSize(); i += longSize) { masm.str(64, value, address); } } @@ -224,30 +255,59 @@ public void enter(CompilationResultBuilder crb) { crb.blockComment("[code body]"); } - @Override - public void leave(CompilationResultBuilder crb) { - AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; - FrameMap frameMap = crb.frameMap; - final int totalFrameSize = frameMap.totalFrameSize(); - - crb.blockComment("[method epilogue]"); - // based on HotSpot's macroAssembler_aarch64.cpp MacroAssembler::leave_frame - try (ScratchRegister sc = masm.getScratchRegister()) { - int wordSize = 8; - Register scratch = sc.getRegister(); - final int frameSize = frameMap.frameSize(); - assert totalFrameSize > 0; - AArch64Address.AddressingMode addressingMode = AArch64Address.AddressingMode.IMMEDIATE_PAIR_SIGNED_SCALED; - if (AArch64Address.isValidImmediateAddress(64, addressingMode, frameSize)) { - masm.ldp(64, fp, lr, AArch64Address.createImmediateAddress(64, addressingMode, sp, frameSize)); - masm.add(64, sp, sp, totalFrameSize); - } else { - int frameRecordSize = 2 * wordSize; - masm.add(64, sp, sp, totalFrameSize - frameRecordSize, scratch); - masm.ldp(64, fp, lr, AArch64Address.createImmediateAddress(64, AArch64Address.AddressingMode.IMMEDIATE_PAIR_POST_INDEXED, sp, frameRecordSize)); + private void emitNmethodEntryBarrier(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + try (ScratchRegister sc = masm.getScratchRegister(); ScratchRegister sc2 = masm.getScratchRegister()) { + Register scratch1 = sc.getRegister(); + Register scratch2 = sc2.getRegister(); + + GraalError.guarantee(HotSpotMarkId.ENTRY_BARRIER_PATCH.isAvailable(), "must be available"); + ForeignCallLinkage callTarget = getForeignCalls().lookupForeignCall(NMETHOD_ENTRY_BARRIER); + Register thread = getProviders().getRegisters().getThreadRegister(); + + // The assembly sequence is from + // src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp. It was + // improved in + // JDK 20 to be more efficient. + final Label continuation = new Label(); + final Label entryPoint = new Label(); + + // The following code sequence must be emitted in exactly this fashion as HotSpot + // will check that the barrier is the expected code sequence. + crb.recordMark(HotSpotMarkId.ENTRY_BARRIER_PATCH); + DataSection.Data data = crb.dataBuilder.createMutableData(4, 4); + masm.ldr(32, scratch1, (AArch64Address) crb.recordDataSectionReference(data)); + + if (config.nmethodEntryBarrierConcurrentPatch) { + masm.dmb(AArch64Assembler.BarrierKind.LOAD_ANY); } + + AArch64Address threadDisarmedAddr = masm.makeAddress(32, thread, config.threadDisarmedOffset, scratch2); + masm.ldr(32, scratch2, threadDisarmedAddr); + masm.cmp(32, scratch1, scratch2); + masm.branchConditionally(AArch64Assembler.ConditionFlag.NE, entryPoint); + crb.getLIR().addSlowPath(null, () -> { + masm.bind(entryPoint); + int beforeCall = masm.position(); + if (AArch64Call.isNearCall(callTarget)) { + // Address is fixed up by the runtime. + masm.bl(); + } else { + masm.movNativeAddress(scratch1, 0L, true); + masm.blr(scratch1); + } + crb.recordDirectCall(beforeCall, masm.position(), callTarget, null); + + // Return to inline code + masm.jmp(continuation); + }); + masm.bind(continuation); } + } + @Override + public void leave(CompilationResultBuilder crb) { + crb.blockComment("[method epilogue]"); + rawLeave(crb); } @Override @@ -274,7 +334,7 @@ public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); CompilationResultBuilder crb = factory.createBuilder(getProviders(), frameMap, masm, dataBuilder, frameContext, lir.getOptions(), lir.getDebug(), compilationResult, - Register.None); + Register.None, lir); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); crb.setMinDataSectionItemAlignment(getMinDataSectionItemAlignment()); @@ -291,29 +351,32 @@ public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult } @Override - public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) { + public void emitCode(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, EntryPointDecorator entryPointDecorator) { Label verifiedStub = new Label(); - crb.buildLabelOffsets(lir); + crb.buildLabelOffsets(); try { - emitCode(crb, lir, installedCodeOwner, verifiedStub); + emitCode(crb, installedCodeOwner, verifiedStub, entryPointDecorator); } catch (BranchTargetOutOfBoundsException e) { // A branch estimation was wrong, now retry with conservative label ranges, this // should always work crb.setConservativeLabelRanges(); crb.resetForEmittingCode(); - lir.resetLabels(); verifiedStub.reset(); - emitCode(crb, lir, installedCodeOwner, verifiedStub); + emitCode(crb, installedCodeOwner, verifiedStub, entryPointDecorator); } } - private void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner, Label verifiedStub) { + private void emitCode(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, Label verifiedStub, EntryPointDecorator entryPointDecorator) { AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; FrameMap frameMap = crb.frameMap; RegisterConfig regConfig = frameMap.getRegisterConfig(); emitCodePrefix(crb, installedCodeOwner, masm, regConfig, verifiedStub); - emitCodeBody(crb, lir, masm); - emitCodeSuffix(crb, masm, frameMap); + + if (entryPointDecorator != null) { + entryPointDecorator.emitEntryPoint(crb); + } + emitCodeBody(crb, masm); + emitCodeSuffix(crb, masm); } private void emitCodePrefix(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, AArch64MacroAssembler masm, RegisterConfig regConfig, Label verifiedStub) { @@ -349,9 +412,9 @@ private void emitCodePrefix(CompilationResultBuilder crb, ResolvedJavaMethod ins crb.recordMark(crb.compilationResult.getEntryBCI() != -1 ? HotSpotMarkId.OSR_ENTRY : HotSpotMarkId.VERIFIED_ENTRY); } - private static void emitCodeBody(CompilationResultBuilder crb, LIR lir, AArch64MacroAssembler masm) { + private static void emitCodeBody(CompilationResultBuilder crb, AArch64MacroAssembler masm) { emitInvalidatePlaceholder(crb, masm); - crb.emit(lir); + crb.emitLIR(); } /** @@ -365,7 +428,7 @@ public static void emitInvalidatePlaceholder(CompilationResultBuilder crb, AArch masm.nop(); } - private void emitCodeSuffix(CompilationResultBuilder crb, AArch64MacroAssembler masm, FrameMap frameMap) { + private void emitCodeSuffix(CompilationResultBuilder crb, AArch64MacroAssembler masm) { HotSpotProviders providers = getProviders(); HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; if (!frameContext.isStub) { @@ -425,10 +488,6 @@ private void emitCodeSuffix(CompilationResultBuilder crb, AArch64MacroAssembler masm.adr(lr, 0); AArch64Call.directJmp(crb, masm, linkage); } - } else { - // No need to emit the stubs for entries back into the method since - // it has no calls that can cause such "return" entries - assert !frameMap.accessesCallerFrame(); } } diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java index 6b0ee96657b3..07f3f20df1c1 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java @@ -49,6 +49,7 @@ import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; +import org.graalvm.compiler.nodes.gc.BarrierSet; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.options.OptionValues; @@ -94,7 +95,8 @@ protected Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRun HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, - OptionValues options) { + OptionValues options, + BarrierSet barrierSet) { Plugins plugins = HotSpotGraphBuilderPlugins.create(graalRuntime, compilerConfiguration, config, @@ -105,7 +107,8 @@ protected Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRun foreignCalls, replacements, options, - target); + target, + barrierSet); AArch64GraphBuilderPlugins.register(plugins, replacements, /* registerForeignCallMath */true, diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java index 6726b6e15eb4..eeb7979bfe50 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java @@ -26,6 +26,7 @@ package org.graalvm.compiler.hotspot.aarch64; +import static jdk.vm.ci.code.ValueUtil.isStackSlot; import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; @@ -52,6 +53,7 @@ import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; +import org.graalvm.compiler.hotspot.HotSpotGraalRuntime; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; @@ -74,6 +76,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64PrefetchOp; import org.graalvm.compiler.lir.aarch64.AArch64RestoreRegistersOp; import org.graalvm.compiler.lir.aarch64.AArch64SaveRegistersOp; +import org.graalvm.compiler.lir.gen.BarrierSetLIRGenerator; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.MoveFactory; @@ -102,13 +105,20 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H final GraalHotSpotVMConfig config; private HotSpotDebugInfoBuilder debugInfoBuilder; + protected static BarrierSetLIRGenerator getBarrierSet(GraalHotSpotVMConfig config, HotSpotProviders providers) { + if (config.gc == HotSpotGraalRuntime.HotSpotGC.Z) { + return new AArch64HotSpotZBarrierSetLIRGenerator(config, providers); + } + return null; + } + protected AArch64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) { - this(new AArch64LIRKindTool(), new AArch64ArithmeticLIRGenerator(null), new AArch64HotSpotMoveFactory(), providers, config, lirGenRes); + this(new AArch64LIRKindTool(), new AArch64ArithmeticLIRGenerator(null), getBarrierSet(config, providers), new AArch64HotSpotMoveFactory(), providers, config, lirGenRes); } - protected AArch64HotSpotLIRGenerator(LIRKindTool lirKindTool, AArch64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, - LIRGenerationResult lirGenRes) { - super(lirKindTool, arithmeticLIRGen, moveFactory, providers, lirGenRes); + protected AArch64HotSpotLIRGenerator(LIRKindTool lirKindTool, AArch64ArithmeticLIRGenerator arithmeticLIRGen, BarrierSetLIRGenerator barrierSetLIRGen, MoveFactory moveFactory, + HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) { + super(lirKindTool, arithmeticLIRGen, barrierSetLIRGen, moveFactory, providers, lirGenRes); this.config = config; } @@ -335,6 +345,15 @@ public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, result = super.emitForeignCall(hotspotLinkage, debugInfo, args); } + // Handle different return value locations + if (stub != null && stub.getLinkage().getEffect() == HotSpotForeignCallLinkage.RegisterEffect.KILLS_NO_REGISTERS && result != null) { + CallingConvention inCC = stub.getLinkage().getIncomingCallingConvention(); + if (!inCC.getReturn().equals(linkage.getOutgoingCallingConvention().getReturn())) { + assert isStackSlot(inCC.getReturn()); + emitMove(inCC.getReturn(), result); + } + } + if (save != null) { HotSpotLIRGenerationResult generationResult = getResult(); LIRFrameState key = currentRuntimeCallInfo; diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java index 180f9bbfd7be..eae9a18d9bca 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java @@ -25,17 +25,22 @@ package org.graalvm.compiler.hotspot.aarch64; import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.hotspot.HotSpotHostBackend.POLLING_PAGE_RETURN_HANDLER; +import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotMarkId; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.aarch64.AArch64Call; import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import jdk.vm.ci.aarch64.AArch64; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.site.InfopointReason; import jdk.vm.ci.meta.AllocatableValue; @@ -67,13 +72,32 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { emitCode(crb, masm, config, false, thread, scratch, state); } - public static void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean onReturn, Register thread, Register scratch, LIRFrameState state) { + public static void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean atReturn, Register thread, Register scratch, LIRFrameState state) { assert config.threadPollingPageOffset >= 0; - masm.ldr(64, scratch, masm.makeAddress(64, thread, config.threadPollingPageOffset)); - crb.recordMark(onReturn ? HotSpotMarkId.POLL_RETURN_FAR : HotSpotMarkId.POLL_FAR); - if (state != null) { - crb.recordInfopoint(masm.position(), state, InfopointReason.SAFEPOINT); + if (config.threadPollingWordOffset != -1 && atReturn && config.pollingPageReturnHandler != 0) { + // HotSpot uses this strategy even if the selected GC doesn't require any concurrent + // stack cleaning. + Label entryPoint = new Label(); + Label poll = new Label(); + masm.bind(poll); + crb.recordMark(HotSpotMarkId.POLL_RETURN_FAR); + masm.ldr(64, scratch, masm.makeAddress(64, thread, config.threadPollingWordOffset, scratch)); + masm.cmp(64, AArch64.sp, scratch); + masm.branchConditionally(AArch64Assembler.ConditionFlag.HI, entryPoint); + crb.getLIR().addSlowPath(null, () -> { + masm.bind(entryPoint); + // store mark pc in scratch + masm.adr(scratch, poll); + masm.str(64, scratch, masm.makeAddress(64, thread, config.savedExceptionPCOffset)); + AArch64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(POLLING_PAGE_RETURN_HANDLER)); + }); + } else { + masm.ldr(64, scratch, masm.makeAddress(64, thread, config.threadPollingPageOffset, scratch)); + crb.recordMark(atReturn ? HotSpotMarkId.POLL_RETURN_FAR : HotSpotMarkId.POLL_FAR); + if (state != null) { + crb.recordInfopoint(masm.position(), state, InfopointReason.SAFEPOINT); + } + masm.deadLoad(32, AArch64Address.createBaseRegisterOnlyAddress(32, scratch), false); } - masm.deadLoad(32, AArch64Address.createBaseRegisterOnlyAddress(32, scratch), false); } } diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZAtomicReadAndWriteOp.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZAtomicReadAndWriteOp.java new file mode 100644 index 000000000000..bfd8ebd7e27a --- /dev/null +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZAtomicReadAndWriteOp.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.aarch64; + +import static jdk.vm.ci.code.ValueUtil.asRegister; + +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Variable; +import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.meta.AllocatableValue; + +/** + * Code generation for atomic read and write with read barrier. + */ +public class AArch64HotSpotZAtomicReadAndWriteOp extends AArch64AtomicMove.AtomicReadAndWriteOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64HotSpotZAtomicReadAndWriteOp.class); + private final GraalHotSpotVMConfig config; + private final ForeignCallLinkage callTarget; + + public AArch64HotSpotZAtomicReadAndWriteOp(AArch64Kind platformKind, Variable result, AllocatableValue newValue, AllocatableValue asAllocatable, GraalHotSpotVMConfig config, + ForeignCallLinkage callTarget) { + super(TYPE, platformKind, result, newValue, asAllocatable); + this.config = config; + this.callTarget = callTarget; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + super.emitCode(crb, masm); + AArch64Address address = AArch64Address.createBaseRegisterOnlyAddress(64, asRegister(addressValue)); + AArch64HotSpotZBarrierSetLIRGenerator.emitBarrier(crb, masm, null, asRegister(resultValue), config, callTarget, address, this, null); + } +} diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZBarrierSetLIRGenerator.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZBarrierSetLIRGenerator.java new file mode 100644 index 000000000000..b9914b5fe0f7 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZBarrierSetLIRGenerator.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.aarch64; + +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.Z_FIELD_BARRIER; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.Z_PHANTOM_REFERS_TO_BARRIER; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.Z_REFERENCE_GET_BARRIER; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.Z_WEAK_REFERS_TO_BARRIER; + +import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.core.aarch64.AArch64BarrierSetLIRGenerator; +import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator; +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.memory.BarrierType; +import org.graalvm.compiler.core.common.memory.MemoryOrderMode; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LIRInstruction; +import org.graalvm.compiler.lir.Variable; +import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; +import org.graalvm.compiler.lir.aarch64.AArch64Call; +import org.graalvm.compiler.lir.aarch64.AArch64FrameMap; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.code.CallingConvention; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; + +/** + * HotSpot specific code generation for ZGC read barriers. + */ +public class AArch64HotSpotZBarrierSetLIRGenerator extends AArch64BarrierSetLIRGenerator { + + public AArch64HotSpotZBarrierSetLIRGenerator(GraalHotSpotVMConfig config, HotSpotProviders providers) { + this.config = config; + this.providers = providers; + } + + public AArch64LIRGenerator getAArch64LIRGen() { + return (AArch64LIRGenerator) lirGen; + } + + private final GraalHotSpotVMConfig config; + private final HotSpotProviders providers; + + public ForeignCallsProvider getForeignCalls() { + return providers.getForeignCalls(); + } + + /** + * Emits the basic Z read barrier pattern with some customization. Normally this code is used + * from a {@link LIRInstruction} where the frame has already been set up. If an + * {@link AArch64FrameMap} is passed then a frame will be setup and torn down around the call. + * The call itself is done with a special stack-only calling convention that saves and restores + * all registers around the call. This simplifies the code generation as no extra registers are + * required. + */ + public static void emitBarrier(CompilationResultBuilder crb, AArch64MacroAssembler masm, Label success, Register resultReg, GraalHotSpotVMConfig config, ForeignCallLinkage callTarget, + AArch64Address address, LIRInstruction op, AArch64FrameMap frameMap) { + assert !resultReg.equals(address.getBase()) && !resultReg.equals(address.getOffset()); + + final Label entryPoint = new Label(); + final Label continuation = new Label(); + + try (AArch64MacroAssembler.ScratchRegister sc1 = masm.getScratchRegister()) { + Register scratch1 = sc1.getRegister(); + + Register thread = AArch64HotSpotRegisterConfig.threadRegister; + AArch64Address badMask = masm.makeAddress(64, thread, config.threadAddressBadMaskOffset, scratch1); + masm.ldr(64, scratch1, badMask); + if (success == null) { + masm.tst(64, scratch1, resultReg); + masm.branchConditionally(AArch64Assembler.ConditionFlag.NE, entryPoint); + } else { + // In this case the pattern is embedded inside another sequence so use a pattern + // which doesn't screw with the condition codes. It also assumes that the label is + // close enough that the reach of cbz is sufficient. + masm.and(64, scratch1, scratch1, resultReg); + masm.cbz(64, scratch1, success); + masm.jmp(entryPoint); + } + crb.getLIR().addSlowPath(op, () -> { + masm.bind(entryPoint); + + if (frameMap != null) { + AArch64HotSpotBackend.rawEnter(crb, frameMap, masm, config.preserveFramePointer); + } + + CallingConvention cc = callTarget.getOutgoingCallingConvention(); + AArch64Address cArg0 = (AArch64Address) crb.asAddress(cc.getArgument(0)); + AArch64Address cArg1 = (AArch64Address) crb.asAddress(cc.getArgument(1)); + + masm.str(64, resultReg, cArg0); + Register addressReg; + if (address.isBaseRegisterOnly()) { + // Can directly use the base register as the address + addressReg = address.getBase(); + } else { + addressReg = resultReg; + masm.loadAddress(resultReg, address); + } + masm.str(64, addressReg, cArg1); + AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget) ? null : scratch1, null); + masm.ldr(64, resultReg, cArg0); + + if (frameMap != null) { + AArch64HotSpotBackend.rawLeave(crb); + } + + // Return to inline code + masm.jmp(continuation); + }); + masm.bind(continuation); + } + } + + @Override + public Variable emitBarrieredLoad(LIRKind kind, Value address, LIRFrameState state, MemoryOrderMode memoryOrder, BarrierType barrierType) { + if (kind.getPlatformKind().getVectorLength() == 1) { + GraalError.guarantee(kind.getPlatformKind() == AArch64Kind.QWORD, "ZGC only uses uncompressed oops: %s", kind); + + ForeignCallLinkage callTarget = getBarrierStub(barrierType); + AArch64AddressValue loadAddress = getAArch64LIRGen().asAddressValue(address, 64); + Variable result = getLIRGen().newVariable(getLIRGen().toRegisterKind(kind)); + getLIRGen().getResult().getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention()); + getLIRGen().append(new AArch64HotSpotZReadBarrierOp(result, loadAddress, memoryOrder, state, config, callTarget)); + return result; + } + throw GraalError.shouldNotReachHere("unhandled"); + } + + public ForeignCallLinkage getBarrierStub(BarrierType barrierType) { + ForeignCallLinkage callTarget; + switch (barrierType) { + case READ: + callTarget = getForeignCalls().lookupForeignCall(Z_FIELD_BARRIER); + break; + case REFERENCE_GET: + callTarget = getForeignCalls().lookupForeignCall(Z_REFERENCE_GET_BARRIER); + break; + case WEAK_REFERS_TO: + callTarget = getForeignCalls().lookupForeignCall(Z_WEAK_REFERS_TO_BARRIER); + break; + case PHANTOM_REFERS_TO: + callTarget = getForeignCalls().lookupForeignCall(Z_PHANTOM_REFERS_TO_BARRIER); + break; + default: + throw GraalError.shouldNotReachHere("Unexpected barrier type: " + barrierType); + } + return callTarget; + } + + @Override + public void emitCompareAndSwapOp(boolean isLogicVariant, Value address, MemoryOrderMode memoryOrder, AArch64Kind memKind, Variable result, AllocatableValue allocatableExpectedValue, + AllocatableValue allocatableNewValue, BarrierType barrierType) { + ForeignCallLinkage callTarget = getBarrierStub(barrierType); + AllocatableValue temp = getLIRGen().newVariable(getLIRGen().toRegisterKind(LIRKind.value(memKind))); + getLIRGen().getResult().getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention()); + getLIRGen().append(new AArch64HotSpotZCompareAndSwapOp(memKind, memoryOrder, isLogicVariant, result, + allocatableExpectedValue, allocatableNewValue, getLIRGen().asAllocatable(address), config, callTarget, temp)); + } + + AllocatableValue asAllocatable(Value value) { + return getLIRGen().asAllocatable(value); + } + + public I append(I op) { + return getLIRGen().append(op); + } + + @Override + public Value emitAtomicReadAndWrite(LIRKind accessKind, Value address, Value newValue, BarrierType barrierType) { + GraalError.guarantee(barrierType == BarrierType.READ, "unexpected type for barrier: %s", barrierType); + Variable result = lirGen.newVariable(lirGen.toRegisterKind(accessKind)); + GraalError.guarantee(accessKind.getPlatformKind() == AArch64Kind.QWORD, "unexpected kind for ZGC"); + ForeignCallLinkage callTarget = getBarrierStub(barrierType); + getLIRGen().getResult().getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention()); + append(new AArch64HotSpotZAtomicReadAndWriteOp((AArch64Kind) accessKind.getPlatformKind(), result, asAllocatable(address), asAllocatable(newValue), config, callTarget)); + return result; + } +} diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZBarrieredOp.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZBarrieredOp.java new file mode 100644 index 000000000000..af06a3595021 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZBarrieredOp.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.aarch64; + +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; + +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; +import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.meta.AllocatableValue; + +/** + * Base class for LIR ops that require a read barrier. This ensures the Def/Alive restrictions for + * safe register allocation are met by any subclass. + */ +public abstract class AArch64HotSpotZBarrieredOp extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64HotSpotZBarrieredOp.class); + + @Def({REG}) protected AllocatableValue result; + @Alive({COMPOSITE}) protected AArch64AddressValue loadAddress; + + protected final GraalHotSpotVMConfig config; + protected final ForeignCallLinkage callTarget; + + protected AArch64HotSpotZBarrieredOp(LIRInstructionClass type, AllocatableValue result, AArch64AddressValue loadAddress, GraalHotSpotVMConfig config, + ForeignCallLinkage callTarget) { + super(type); + this.result = result; + this.loadAddress = loadAddress; + this.config = config; + this.callTarget = callTarget; + } + + protected void emitBarrier(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + AArch64HotSpotZBarrierSetLIRGenerator.emitBarrier(crb, masm, null, asRegister(result), config, callTarget, loadAddress.toAddress(), this, null); + } + +} diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZCompareAndSwapOp.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZCompareAndSwapOp.java new file mode 100644 index 000000000000..08ce8cb18a14 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZCompareAndSwapOp.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.aarch64; + +import static jdk.vm.ci.code.ValueUtil.asRegister; + +import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.core.common.memory.MemoryOrderMode; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; + +@Opcode("CAS_Z") +public final class AArch64HotSpotZCompareAndSwapOp extends AArch64AtomicMove.CompareAndSwapOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64HotSpotZCompareAndSwapOp.class); + + private final GraalHotSpotVMConfig config; + private final ForeignCallLinkage callTarget; + @Temp protected AllocatableValue temp; + + public AArch64HotSpotZCompareAndSwapOp(AArch64Kind accessKind, MemoryOrderMode memoryOrder, boolean setConditionFlags, AllocatableValue result, Value expectedValue, AllocatableValue newValue, + AllocatableValue addressValue, GraalHotSpotVMConfig config, ForeignCallLinkage callTarget, AllocatableValue temp) { + super(TYPE, accessKind, memoryOrder, setConditionFlags, result, expectedValue, newValue, addressValue); + this.config = config; + this.callTarget = callTarget; + this.temp = temp; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + super.emitCode(crb, masm); + AArch64Address location = AArch64Address.createBaseRegisterOnlyAddress(64, asRegister(addressValue)); + Label good = new Label(); + AArch64HotSpotZBarrierSetLIRGenerator.emitBarrier(crb, masm, good, asRegister(resultValue), config, callTarget, location, this, null); + super.emitCode(crb, masm); + masm.bind(good); + } +} diff --git a/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZReadBarrierOp.java b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZReadBarrierOp.java new file mode 100644 index 000000000000..2de3f3900358 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotZReadBarrierOp.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.aarch64; + +import static jdk.vm.ci.code.ValueUtil.asRegister; + +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.core.common.memory.MemoryOrderMode; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Variable; +import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.code.Register; + +public class AArch64HotSpotZReadBarrierOp extends AArch64HotSpotZBarrieredOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64HotSpotZReadBarrierOp.class); + + private final MemoryOrderMode memoryOrder; + @State protected LIRFrameState state; + + public AArch64HotSpotZReadBarrierOp(Variable result, AArch64AddressValue loadAddress, MemoryOrderMode memoryOrder, LIRFrameState state, GraalHotSpotVMConfig config, + ForeignCallLinkage callTarget) { + super(TYPE, result, loadAddress, config, callTarget); + this.memoryOrder = memoryOrder; + this.state = state; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + int loadPosition; + final Register resultReg = asRegister(result); + switch (memoryOrder) { + case PLAIN: + case OPAQUE: // no fences are needed for opaque memory accesses + loadPosition = masm.position(); + masm.ldr(64, resultReg, loadAddress.toAddress(), false); + break; + case ACQUIRE: + case VOLATILE: { + try (AArch64MacroAssembler.ScratchRegister scratch1 = masm.getScratchRegister()) { + AArch64Address address = loadAddress.toAddress(); + final Register addrReg; + if (address.isBaseRegisterOnly()) { + // Can directly use the base register as the address + addrReg = address.getBase(); + } else { + addrReg = scratch1.getRegister(); + masm.loadAddress(addrReg, address); + } + loadPosition = masm.position(); + masm.ldar(64, resultReg, addrReg); + } + break; + } + default: + throw GraalError.shouldNotReachHere("Unexpected memory order"); + } + if (state != null) { + crb.recordImplicitException(loadPosition, state); + } + emitBarrier(crb, masm); + } +} diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java index f6b99738a2dc..cbaa5bed6f48 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java @@ -31,7 +31,9 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static org.graalvm.compiler.core.common.GraalOptions.CanOmitFrame; import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.NMETHOD_ENTRY_BARRIER; +import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; @@ -41,8 +43,10 @@ import org.graalvm.compiler.core.amd64.AMD64NodeMatchRules; import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.gen.LIRGenerationProvider; import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotDataBuilder; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; @@ -59,6 +63,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.asm.DataBuilder; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; import org.graalvm.compiler.lir.asm.FrameContext; import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; @@ -145,9 +150,10 @@ public boolean hasFrame() { public void enter(CompilationResultBuilder crb) { FrameMap frameMap = crb.frameMap; int frameSize = frameMap.frameSize(); - AMD64MacroAssembler asm = (AMD64MacroAssembler) crb.asm; + AMD64HotSpotMacroAssembler asm = (AMD64HotSpotMacroAssembler) crb.asm; if (omitFrame) { if (!isStub) { + GraalError.guarantee(config.nmethodEntryBarrier == 0, "can't omit frames when using nmethod entry barrier"); asm.nop(PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE); } } else { @@ -168,19 +174,54 @@ public void enter(CompilationResultBuilder crb) { } else { asm.decrementq(rsp, frameSize); } - if (HotSpotMarkId.FRAME_COMPLETE.isAvailable()) { + + assert frameMap.getRegisterConfig().getCalleeSaveRegisters() == null; + + if (!isStub && config.nmethodEntryBarrier != 0) { + emitNmethodEntryBarrier(crb, asm); + } else { crb.recordMark(HotSpotMarkId.FRAME_COMPLETE); } + if (ZapStackOnMethodEntry.getValue(crb.getOptions())) { final int intSize = 4; for (int i = 0; i < frameSize / intSize; ++i) { asm.movl(new AMD64Address(rsp, i * intSize), 0xC1C1C1C1); } } - assert frameMap.getRegisterConfig().getCalleeSaveRegisters() == null; } } + private void emitNmethodEntryBarrier(CompilationResultBuilder crb, AMD64HotSpotMacroAssembler asm) { + GraalError.guarantee(HotSpotMarkId.ENTRY_BARRIER_PATCH.isAvailable(), "must be available"); + ForeignCallLinkage callTarget = getForeignCalls().lookupForeignCall(NMETHOD_ENTRY_BARRIER); + + // The assembly sequence is from + // src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp. It was improved in + // JDK 20 to be more efficient. + final Label continuation = new Label(); + final Label entryPoint = new Label(); + + // The following code sequence must be emitted in exactly this fashion as HotSpot + // will check that the barrier is the expected code sequence. + asm.align(4); + crb.recordMark(HotSpotMarkId.FRAME_COMPLETE); + crb.recordMark(HotSpotMarkId.ENTRY_BARRIER_PATCH); + asm.nmethodEntryCompare(config.threadDisarmedOffset); + asm.jcc(ConditionFlag.NotEqual, entryPoint); + crb.getLIR().addSlowPath(null, () -> { + asm.bind(entryPoint); + // This is always a near call + int beforeCall = asm.position(); + asm.call(); + crb.recordDirectCall(beforeCall, asm.position(), callTarget, null); + + // Return to inline code + asm.jmp(continuation); + }); + asm.bind(continuation); + } + @Override public void leave(CompilationResultBuilder crb) { if (!omitFrame) { @@ -217,13 +258,13 @@ public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult OptionValues options = lir.getOptions(); DebugContext debug = lir.getDebug(); boolean omitFrame = CanOmitFrame.getValue(options) && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall() && - !((AMD64FrameMap) frameMap).useStandardFrameProlog(); + !((AMD64FrameMap) frameMap).useStandardFrameProlog() && config.nmethodEntryBarrier == 0; Stub stub = gen.getStub(); AMD64MacroAssembler masm = new AMD64HotSpotMacroAssembler(config, getTarget(), options, config.CPU_HAS_INTEL_JCC_ERRATUM); HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame, config.preserveFramePointer); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); - CompilationResultBuilder crb = factory.createBuilder(getProviders(), frameMap, masm, dataBuilder, frameContext, options, debug, compilationResult, Register.None); + CompilationResultBuilder crb = factory.createBuilder(getProviders(), frameMap, masm, dataBuilder, frameContext, options, debug, compilationResult, Register.None, lir); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); crb.setMinDataSectionItemAlignment(getMinDataSectionItemAlignment()); @@ -240,7 +281,7 @@ public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult } @Override - public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) { + public void emitCode(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, EntryPointDecorator entryPointDecorator) { AMD64MacroAssembler asm = (AMD64MacroAssembler) crb.asm; FrameMap frameMap = crb.frameMap; RegisterConfig regConfig = frameMap.getRegisterConfig(); @@ -248,14 +289,15 @@ public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod i // Emit the prefix emitCodePrefix(installedCodeOwner, crb, asm, regConfig); + if (entryPointDecorator != null) { + entryPointDecorator.emitEntryPoint(crb); + } + // Emit code for the LIR - emitCodeBody(installedCodeOwner, crb, lir); + crb.emitLIR(); // Emit the suffix - emitCodeSuffix(installedCodeOwner, crb, asm, frameMap); - - // Profile assembler instructions - profileInstructions(lir, crb); + emitCodeSuffix(crb, asm, frameMap); } /** @@ -269,7 +311,7 @@ public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationRes crb.recordMark(HotSpotMarkId.UNVERIFIED_ENTRY); CallingConvention cc = regConfig.getCallingConvention(HotSpotCallingConventionType.JavaCallee, null, new JavaType[]{providers.getMetaAccess().lookupJavaType(Object.class)}, this); Register inlineCacheKlass = rax; // see definition of IC_Klass in - // c1_LIRAssembler_x86.cpp + // c1_LIRAssembler_x86.cpp Register receiver = asRegister(cc.getArgument(0)); AMD64Address src = new AMD64Address(receiver, config.hubOffset); int before; @@ -297,19 +339,7 @@ public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationRes crb.recordMark(crb.compilationResult.getEntryBCI() != -1 ? HotSpotMarkId.OSR_ENTRY : HotSpotMarkId.VERIFIED_ENTRY); } - /** - * Emits the code which starts at the verified entry point. - * - * @param installedCodeOwner see {@link LIRGenerationProvider#emitCode} - */ - public void emitCodeBody(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, LIR lir) { - crb.emit(lir); - } - - /** - * @param installedCodeOwner see {@link LIRGenerationProvider#emitCode} - */ - public void emitCodeSuffix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, FrameMap frameMap) { + public void emitCodeSuffix(CompilationResultBuilder crb, AMD64MacroAssembler asm, FrameMap frameMap) { HotSpotProviders providers = getProviders(); HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; if (!frameContext.isStub) { diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java index b03a69fb26d7..c2625108dfc2 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java @@ -44,9 +44,10 @@ import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; +import org.graalvm.compiler.nodes.gc.BarrierSet; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.common.AddressLoweringPhase; +import org.graalvm.compiler.phases.common.AddressLoweringByNodePhase; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.replacements.amd64.AMD64GraphBuilderPlugins; import org.graalvm.compiler.serviceprovider.ServiceProvider; @@ -78,7 +79,7 @@ public Class getArchitecture() { @Override protected Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, TargetDescription target, HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, MetaAccessProvider metaAccess, - HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options) { + HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options, BarrierSet barrierSet) { Plugins plugins = HotSpotGraphBuilderPlugins.create( graalRuntime, compilerConfiguration, @@ -90,7 +91,8 @@ protected Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRun foreignCalls, replacements, options, - target); + target, + barrierSet); AMD64GraphBuilderPlugins.register(plugins, replacements, (AMD64) target.arch, options); return plugins; } @@ -118,7 +120,7 @@ protected HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins, HotSpotRegistersProvider registers, HotSpotReplacementsImpl replacements, OptionValues options) { return new AddressLoweringHotSpotSuitesProvider(new AMD64SuitesCreator(compilerConfiguration, plugins), config, runtime, - new AddressLoweringPhase(new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister()))); + new AddressLoweringByNodePhase(new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister()))); } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java index 8ad535ea458e..07148d79827e 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java @@ -25,18 +25,19 @@ package org.graalvm.compiler.hotspot.amd64; import static jdk.vm.ci.amd64.AMD64.rbp; +import static jdk.vm.ci.code.ValueUtil.isStackSlot; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import org.graalvm.compiler.asm.amd64.AMD64Address; -import org.graalvm.compiler.core.common.Stride; import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize; import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator; import org.graalvm.compiler.core.amd64.AMD64LIRGenerator; import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.Stride; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; @@ -46,10 +47,12 @@ import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; +import org.graalvm.compiler.hotspot.HotSpotGraalRuntime; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; +import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.lir.LIR; @@ -62,7 +65,6 @@ import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.amd64.AMD64AddressValue; -import org.graalvm.compiler.lir.amd64.AMD64CCall; import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.StrategySwitchOp; import org.graalvm.compiler.lir.amd64.AMD64FrameMapBuilder; import org.graalvm.compiler.lir.amd64.AMD64Move; @@ -74,9 +76,11 @@ import org.graalvm.compiler.lir.amd64.AMD64VZeroUpper; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; +import org.graalvm.compiler.lir.gen.BarrierSetLIRGenerator; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.MoveFactory; import org.graalvm.compiler.lir.gen.MoveFactory.BackupSlotProvider; +import org.graalvm.compiler.phases.util.Providers; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64.CPUFeature; @@ -93,7 +97,6 @@ import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.PlatformKind; -import jdk.vm.ci.meta.PrimitiveConstant; import jdk.vm.ci.meta.SpeculationLog; import jdk.vm.ci.meta.Value; @@ -109,13 +112,20 @@ protected AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMCon this(providers, config, lirGenRes, new BackupSlotProvider(lirGenRes.getFrameMapBuilder())); } + protected static BarrierSetLIRGenerator getBarrierSet(GraalHotSpotVMConfig config, Providers providers) { + if (config.gc == HotSpotGraalRuntime.HotSpotGC.Z) { + return new AMD64HotSpotZBarrierSetLIRGenerator(config, providers); + } + return null; + } + private AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, BackupSlotProvider backupSlotProvider) { - this(new AMD64HotSpotLIRKindTool(), new AMD64ArithmeticLIRGenerator(null), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes); + this(new AMD64HotSpotLIRKindTool(), new AMD64ArithmeticLIRGenerator(null), getBarrierSet(config, providers), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes); } - protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, - LIRGenerationResult lirGenRes) { - super(lirKindTool, arithmeticLIRGen, moveFactory, providers, lirGenRes); + protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, BarrierSetLIRGenerator barrierSetLIRGen, MoveFactory moveFactory, + HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) { + super(lirKindTool, arithmeticLIRGen, barrierSetLIRGen, moveFactory, providers, lirGenRes); assert config.basicLockSize == 8; this.config = config; } @@ -340,8 +350,8 @@ protected VirtualStackSlot allocateSaveRegisterLocation(Register register) { * * @return the register save node */ - private AMD64SaveRegistersOp emitSaveAllRegisters() { - Register[] savedRegisters = getSaveableRegisters(); + private AMD64SaveRegistersOp emitSaveAllRegisters(boolean forSafepoint) { + Register[] savedRegisters = getSaveableRegisters(forSafepoint); AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length]; for (int i = 0; i < savedRegisters.length; i++) { savedRegisterLocations[i] = allocateSaveRegisterLocation(savedRegisters[i]); @@ -349,13 +359,16 @@ private AMD64SaveRegistersOp emitSaveAllRegisters() { return emitSaveRegisters(savedRegisters, savedRegisterLocations); } - protected Register[] getSaveableRegisters() { + /** + * @param forSafepoint saveable registers must be describable for register map. + */ + protected Register[] getSaveableRegisters(boolean forSafepoint) { RegisterArray allocatableRegisters = getResult().getRegisterAllocationConfig().getAllocatableRegisters(); ArrayList registers = new ArrayList<>(allocatableRegisters.size()); for (Register reg : allocatableRegisters) { - // mask registers should not be saved - if (!reg.getRegisterCategory().equals(AMD64.MASK)) { + // mask registers should not be saved at safepoints + if (!forSafepoint || !reg.getRegisterCategory().equals(AMD64.MASK)) { registers.add(reg); } } @@ -392,7 +405,7 @@ public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, AMD64SaveRegistersOp save = null; Stub stub = getStub(); if (destroysRegisters && stub != null && stub.shouldSaveRegistersAroundCalls()) { - save = emitSaveAllRegisters(); + save = emitSaveAllRegisters(stub.getLinkage().getDescriptor().getTransition() == HotSpotForeignCallDescriptor.Transition.SAFEPOINT); } Variable result; @@ -411,6 +424,15 @@ public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, result = super.emitForeignCall(hotspotLinkage, debugInfo, args); } + // Handle different return value locations + if (stub != null && stub.getLinkage().getEffect() == HotSpotForeignCallLinkage.RegisterEffect.KILLS_NO_REGISTERS && result != null) { + CallingConvention inCC = stub.getLinkage().getIncomingCallingConvention(); + if (!inCC.getReturn().equals(linkage.getOutgoingCallingConvention().getReturn())) { + assert isStackSlot(inCC.getReturn()); + emitMove(inCC.getReturn(), result); + } + } + if (save != null) { HotSpotLIRGenerationResult generationResult = getResult(); LIRFrameState key = currentRuntimeCallInfo; @@ -425,25 +447,6 @@ public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, return result; } - @Override - public void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args, int numberOfFloatingPointArguments) { - Value[] argLocations = new Value[args.length]; - getResult().getFrameMapBuilder().callsMethod(nativeCallingConvention); - // TODO(mg): in case a native function uses floating point varargs, the ABI requires that - // RAX contains the length of the varargs - PrimitiveConstant intConst = JavaConstant.forInt(numberOfFloatingPointArguments); - AllocatableValue numberOfFloatingPointArgumentsRegister = AMD64.rax.asValue(LIRKind.value(AMD64Kind.DWORD)); - emitMoveConstant(numberOfFloatingPointArgumentsRegister, intConst); - for (int i = 0; i < args.length; i++) { - Value arg = args[i]; - AllocatableValue loc = nativeCallingConvention.getArgument(i); - emitMove(loc, arg); - argLocations[i] = loc; - } - Value ptr = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(address)); - append(new AMD64CCall(nativeCallingConvention.getReturn(), ptr, numberOfFloatingPointArgumentsRegister, argLocations)); - } - @Override public void emitUnwind(Value exception) { ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER); diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java index 22ef5ddebe62..ddd4e11eb866 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java @@ -24,9 +24,16 @@ */ package org.graalvm.compiler.hotspot.amd64; +import static jdk.vm.ci.amd64.AMD64.r15; import static jdk.vm.ci.amd64.AMD64.rax; +import static jdk.vm.ci.amd64.AMD64.rip; +import static jdk.vm.ci.amd64.AMD64.rsp; +import static org.graalvm.compiler.hotspot.HotSpotHostBackend.POLLING_PAGE_RETURN_HANDLER; +import java.util.function.IntConsumer; +import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; +import org.graalvm.compiler.asm.amd64.AMD64Assembler; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -34,6 +41,7 @@ import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.amd64.AMD64Call; import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -73,12 +81,35 @@ public static void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler as assert !atReturn || state == null : "state is unneeded at return"; assert config.threadPollingPageOffset >= 0; - asm.movptr(scratch, new AMD64Address(thread, config.threadPollingPageOffset)); - crb.recordMark(atReturn ? HotSpotMarkId.POLL_RETURN_FAR : HotSpotMarkId.POLL_FAR); - final int pos = asm.position(); - if (state != null) { - crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + if (config.threadPollingWordOffset != -1 && atReturn && config.pollingPageReturnHandler != 0) { + // HotSpot uses this strategy even if the selected GC doesn't require any concurrent + // stack cleaning. + + final int[] pos = new int[1]; + IntConsumer doMark = value -> { + pos[0] = value; + crb.recordMark(HotSpotMarkId.POLL_RETURN_FAR); + }; + + Label entryPoint = new Label(); + asm.cmpqAndJcc(rsp, new AMD64Address(thread, config.threadPollingWordOffset), AMD64Assembler.ConditionFlag.Above, entryPoint, false, doMark); + crb.getLIR().addSlowPath(null, () -> { + asm.bind(entryPoint); + // Load the pc of the poll instruction + asm.leaq(scratch, new AMD64Address(rip, 0)); + final int afterLea = asm.position(); + asm.emitInt(pos[0] - afterLea, afterLea - 4); + asm.movq(new AMD64Address(r15, config.savedExceptionPCOffset), scratch); + AMD64Call.directJmp(crb, asm, crb.foreignCalls.lookupForeignCall(POLLING_PAGE_RETURN_HANDLER), null); + }); + } else { + asm.movptr(scratch, new AMD64Address(thread, config.threadPollingPageOffset)); + crb.recordMark(atReturn ? HotSpotMarkId.POLL_RETURN_FAR : HotSpotMarkId.POLL_FAR); + final int pos = asm.position(); + if (state != null) { + crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + } + asm.testl(rax, new AMD64Address(scratch)); } - asm.testl(rax, new AMD64Address(scratch)); } } diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZAtomicReadAndWriteOp.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZAtomicReadAndWriteOp.java new file mode 100644 index 000000000000..46162f0da454 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZAtomicReadAndWriteOp.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.amd64; + +import static jdk.vm.ci.amd64.AMD64Kind.QWORD; +import static jdk.vm.ci.code.ValueUtil.asRegister; + +import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Variable; +import org.graalvm.compiler.lir.amd64.AMD64AddressValue; +import org.graalvm.compiler.lir.amd64.AMD64Move; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.meta.AllocatableValue; + +/** + * Code generation for atomic read and write with read barrier. + */ +public class AMD64HotSpotZAtomicReadAndWriteOp extends AMD64HotSpotZBarrieredOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotZAtomicReadAndWriteOp.class); + + @Use protected AllocatableValue newValue; + + public AMD64HotSpotZAtomicReadAndWriteOp(Variable result, AMD64AddressValue loadAddress, AllocatableValue newValue, GraalHotSpotVMConfig config, ForeignCallLinkage callTarget) { + super(TYPE, result, loadAddress, config, callTarget); + this.newValue = newValue; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + AMD64Move.move(QWORD, crb, masm, result, newValue); + masm.xchgq(asRegister(result), loadAddress.toAddress()); + emitBarrier(crb, masm); + } +} diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZBarrierSetLIRGenerator.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZBarrierSetLIRGenerator.java new file mode 100644 index 000000000000..ae87bef4386b --- /dev/null +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZBarrierSetLIRGenerator.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.amd64; + +import static jdk.vm.ci.amd64.AMD64.r15; +import static jdk.vm.ci.amd64.AMD64.rbp; +import static jdk.vm.ci.amd64.AMD64.rsp; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.Z_ARRAY_BARRIER; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.Z_FIELD_BARRIER; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.Z_PHANTOM_REFERS_TO_BARRIER; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.Z_REFERENCE_GET_BARRIER; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.Z_WEAK_REFERS_TO_BARRIER; + +import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.asm.amd64.AMD64Address; +import org.graalvm.compiler.asm.amd64.AMD64Assembler; +import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.asm.amd64.AVXKind; +import org.graalvm.compiler.core.amd64.AMD64BarrierSetLIRGenerator; +import org.graalvm.compiler.core.amd64.AMD64LIRGenerator; +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.memory.BarrierType; +import org.graalvm.compiler.core.common.memory.MemoryOrderMode; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LIRInstruction; +import org.graalvm.compiler.lir.Variable; +import org.graalvm.compiler.lir.amd64.AMD64AddressValue; +import org.graalvm.compiler.lir.amd64.AMD64Call; +import org.graalvm.compiler.lir.amd64.AMD64FrameMap; +import org.graalvm.compiler.lir.amd64.vector.AMD64VectorMove; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.compiler.phases.util.Providers; + +import jdk.vm.ci.amd64.AMD64Kind; +import jdk.vm.ci.code.CallingConvention; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterValue; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; + +/** + * HotSpot specific code generation for ZGC read barriers. + */ +public class AMD64HotSpotZBarrierSetLIRGenerator extends AMD64BarrierSetLIRGenerator { + + public AMD64HotSpotZBarrierSetLIRGenerator(GraalHotSpotVMConfig config, Providers providers) { + this.config = config; + this.providers = providers; + } + + public AMD64LIRGenerator getAMD64LIRGen() { + return (AMD64LIRGenerator) lirGen; + } + + private final GraalHotSpotVMConfig config; + private final Providers providers; + + public ForeignCallsProvider getForeignCalls() { + return providers.getForeignCalls(); + } + + /** + * Emits the basic Z read barrier pattern with some customization. Normally this code is used + * from a {@link LIRInstruction} where the frame has already been set up. If an + * {@link AMD64FrameMap} is passed then a frame will be setup and torn down around the call. The + * call itself is done with a special stack-only calling convention that saves and restores all + * registers around the call. This simplifies the code generation as no extra registers are + * required. + */ + public static void emitBarrier(CompilationResultBuilder crb, AMD64MacroAssembler masm, Label success, Register resultReg, GraalHotSpotVMConfig config, ForeignCallLinkage callTarget, + AMD64Address address, LIRInstruction op, AMD64FrameMap frameMap) { + assert !resultReg.equals(address.getBase()) && !resultReg.equals(address.getIndex()); + + final Label entryPoint = new Label(); + final Label continuation = new Label(); + + masm.testq(resultReg, new AMD64Address(r15, config.threadAddressBadMaskOffset)); + if (success != null) { + masm.jcc(AMD64Assembler.ConditionFlag.Zero, success); + masm.jmp(entryPoint); + } else { + masm.jcc(AMD64Assembler.ConditionFlag.NotZero, entryPoint); + } + crb.getLIR().addSlowPath(op, () -> { + masm.bind(entryPoint); + + if (frameMap != null) { + if (frameMap.useStandardFrameProlog()) { + // Stack-walking friendly instructions + masm.push(rbp); + masm.movq(rbp, rsp); + } + masm.decrementq(rsp, frameMap.frameSize()); + } + + CallingConvention cc = callTarget.getOutgoingCallingConvention(); + AMD64Address cArg0 = (AMD64Address) crb.asAddress(cc.getArgument(0)); + AMD64Address cArg1 = (AMD64Address) crb.asAddress(cc.getArgument(1)); + + masm.movq(cArg0, resultReg); + masm.leaq(resultReg, address); + masm.movq(cArg1, resultReg); + AMD64Call.directCall(crb, masm, callTarget, null, false, null); + masm.movq(resultReg, cArg0); + + if (frameMap != null) { + if (frameMap.useStandardFrameProlog()) { + masm.movq(rsp, rbp); + masm.pop(rbp); + } else { + masm.incrementq(rsp, frameMap.frameSize()); + } + } + + // Return to inline code + masm.jmp(continuation); + }); + masm.bind(continuation); + } + + @Override + public Variable emitBarrieredLoad(LIRKind kind, Value address, LIRFrameState state, MemoryOrderMode memoryOrder, BarrierType barrierType) { + if (kind.getPlatformKind().getVectorLength() == 1) { + GraalError.guarantee(kind.getPlatformKind() == AMD64Kind.QWORD, "ZGC only uses uncompressed oops: %s", kind); + + ForeignCallLinkage callTarget = getBarrierStub(barrierType); + AMD64AddressValue loadAddress = getAMD64LIRGen().asAddressValue(address); + Variable result = getLIRGen().newVariable(getLIRGen().toRegisterKind(kind)); + getLIRGen().getResult().getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention()); + getLIRGen().append(new AMD64HotSpotZReadBarrierOp(result, loadAddress, state, config, callTarget)); + return result; + } + if (kind.getPlatformKind().getVectorLength() > 1) { + // Emit a vector barrier + assert barrierType == BarrierType.READ; + ForeignCallLinkage callTarget = getForeignCalls().lookupForeignCall(Z_ARRAY_BARRIER); + AMD64AddressValue loadAddress = getAMD64LIRGen().asAddressValue(address); + Variable result = getLIRGen().newVariable(getLIRGen().toRegisterKind(kind)); + + AMD64Assembler.VexMoveOp op = AMD64VectorMove.getVectorMemMoveOp((AMD64Kind) kind.getPlatformKind()); + Variable temp = getLIRGen().newVariable(getLIRGen().toRegisterKind(kind)); + getLIRGen().getResult().getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention()); + getLIRGen().append(new AMD64HotSpotZVectorReadBarrierOp(AVXKind.getRegisterSize((AMD64Kind) kind.getPlatformKind()), op, result, loadAddress, state, config, callTarget, temp)); + return result; + } + throw GraalError.shouldNotReachHere("unhandled barrier"); + } + + public ForeignCallLinkage getBarrierStub(BarrierType barrierType) { + ForeignCallLinkage callTarget; + switch (barrierType) { + case READ: + callTarget = getForeignCalls().lookupForeignCall(Z_FIELD_BARRIER); + break; + case REFERENCE_GET: + callTarget = getForeignCalls().lookupForeignCall(Z_REFERENCE_GET_BARRIER); + break; + case WEAK_REFERS_TO: + callTarget = getForeignCalls().lookupForeignCall(Z_WEAK_REFERS_TO_BARRIER); + break; + case PHANTOM_REFERS_TO: + callTarget = getForeignCalls().lookupForeignCall(Z_PHANTOM_REFERS_TO_BARRIER); + break; + default: + throw GraalError.shouldNotReachHere("Unexpected barrier type: " + barrierType); + } + return callTarget; + } + + @Override + public void emitCompareAndSwapOp(LIRKind accessKind, AMD64Kind memKind, RegisterValue raxValue, AMD64AddressValue address, AllocatableValue newValue, BarrierType barrierType) { + ForeignCallLinkage callTarget = getBarrierStub(barrierType); + assert memKind == accessKind.getPlatformKind(); + AllocatableValue temp = getLIRGen().newVariable(getLIRGen().toRegisterKind(accessKind)); + getLIRGen().getResult().getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention()); + getLIRGen().append(new AMD64HotSpotZCompareAndSwapOp(memKind, raxValue, address, raxValue, getLIRGen().asAllocatable(newValue), temp, config, callTarget)); + } + + @Override + public Value emitAtomicReadAndWrite(LIRKind accessKind, Value address, Value newValue, BarrierType barrierType) { + AMD64Kind kind = (AMD64Kind) accessKind.getPlatformKind(); + GraalError.guarantee(barrierType == BarrierType.READ, "unexpected type for barrier: %s", barrierType); + Variable result = getLIRGen().newVariable(accessKind); + AMD64AddressValue addressValue = getAMD64LIRGen().asAddressValue(address); + GraalError.guarantee(kind == AMD64Kind.QWORD, "unexpected kind for ZGC"); + ForeignCallLinkage callTarget = getBarrierStub(barrierType); + getLIRGen().getResult().getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention()); + getLIRGen().append(new AMD64HotSpotZAtomicReadAndWriteOp(result, addressValue, getLIRGen().asAllocatable(newValue), config, callTarget)); + return result; + } +} diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZBarrieredOp.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZBarrieredOp.java new file mode 100644 index 000000000000..5c721068fbf6 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZBarrieredOp.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.amd64; + +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; + +import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.amd64.AMD64AddressValue; +import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.AllocatableValue; + +/** + * Base class for LIR ops that require a read barrier. This ensures the Def/Alive restrictions for + * safe register allocation are met by any subclass. + */ +public abstract class AMD64HotSpotZBarrieredOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotZBarrieredOp.class); + + @Def({REG}) protected AllocatableValue result; + @Alive({COMPOSITE}) protected AMD64AddressValue loadAddress; + + protected final GraalHotSpotVMConfig config; + protected final ForeignCallLinkage callTarget; + + protected AMD64HotSpotZBarrieredOp(LIRInstructionClass type, AllocatableValue result, AMD64AddressValue loadAddress, GraalHotSpotVMConfig config, + ForeignCallLinkage callTarget) { + super(type); + this.result = result; + this.loadAddress = loadAddress; + this.config = config; + this.callTarget = callTarget; + } + + /** + * Emit a barrier testing a specific register. + */ + protected void emitBarrier(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Label success) { + AMD64HotSpotZBarrierSetLIRGenerator.emitBarrier(crb, masm, success, register, config, callTarget, loadAddress.toAddress(), this, null); + } + + /** + * Emit a barrier testing the {@code result} register. + */ + protected void emitBarrier(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + emitBarrier(crb, masm, asRegister(result), null); + } +} diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZCompareAndSwapOp.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZCompareAndSwapOp.java new file mode 100644 index 000000000000..8e091c898e45 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZCompareAndSwapOp.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.amd64; + +import static jdk.vm.ci.code.ValueUtil.asRegister; + +import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.asm.amd64.AMD64Assembler; +import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.LIRValueUtil; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.amd64.AMD64AddressValue; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.amd64.AMD64Kind; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.AllocatableValue; + +@Opcode("CAS_Z") +public final class AMD64HotSpotZCompareAndSwapOp extends AMD64HotSpotZBarrieredOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotZCompareAndSwapOp.class); + + private final AMD64Kind accessKind; + + @Use protected AllocatableValue cmpValue; + @Alive protected AllocatableValue newValue; + @Temp protected AllocatableValue temp; + + public AMD64HotSpotZCompareAndSwapOp(AMD64Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue, + AllocatableValue temp, GraalHotSpotVMConfig config, ForeignCallLinkage callTarget) { + super(TYPE, result, address, config, callTarget); + this.accessKind = accessKind; + this.cmpValue = cmpValue; + this.newValue = newValue; + this.temp = temp; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + GraalError.guarantee(accessKind == AMD64Kind.QWORD, "ZGC only supports uncomppressed oops"); + assert asRegister(cmpValue).equals(AMD64.rax) && asRegister(result).equals(AMD64.rax); + assert LIRValueUtil.differentRegisters(cmpValue, newValue, temp, loadAddress); + + Label success = new Label(); + Label barrierOk = new Label(); + Register newReg = asRegister(newValue); + // Make a copy of the value used in the compare + masm.movq(asRegister(temp), asRegister(cmpValue)); + if (crb.target.isMP) { + masm.lock(); + } + masm.cmpxchgq(newReg, loadAddress.toAddress()); + // if the cmpxchgq succeeds then we are done + masm.jccb(AMD64Assembler.ConditionFlag.Zero, success); + /* + * The cmpxchg could have failed because the memory location needs a read barrier. On + * failure rax contains the value from the memory location so perform a read barrier on that + * value. If it's a valid oop then we are done but must recompute the condition codes. + * Otherwise we must retry the cmpxchgq. + */ + emitBarrier(crb, masm, AMD64.rax, barrierOk); + masm.movq(asRegister(cmpValue), asRegister(temp)); + if (crb.target.isMP) { + masm.lock(); + } + masm.cmpxchgq(newReg, loadAddress.toAddress()); + masm.bind(barrierOk); + masm.cmpq(asRegister(temp), asRegister(result)); + masm.bind(success); + } +} diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64CCall.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZReadBarrierOp.java similarity index 50% rename from compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64CCall.java rename to compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZReadBarrierOp.java index d00dd37e319b..40c1a2a766be 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64CCall.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZReadBarrierOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,50 +22,40 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.lir.amd64; +package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOV; +import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Variable; +import org.graalvm.compiler.lir.amd64.AMD64AddressValue; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.ValueUtil; -import jdk.vm.ci.meta.Value; -public final class AMD64CCall extends AMD64LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64CCall.class); +public class AMD64HotSpotZReadBarrierOp extends AMD64HotSpotZBarrieredOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotZReadBarrierOp.class); - @Def({REG, ILLEGAL}) protected Value result; - @Use({REG, STACK}) protected Value[] parameters; - @Use({REG}) protected Value functionPtr; - @Use({REG}) protected Value numberOfFloatingPointArguments; + @State protected LIRFrameState state; - public AMD64CCall(Value result, Value functionPtr, Value numberOfFloatingPointArguments, Value[] parameters) { - super(TYPE); - this.result = result; - this.functionPtr = functionPtr; - this.parameters = parameters; - this.numberOfFloatingPointArguments = numberOfFloatingPointArguments; + public AMD64HotSpotZReadBarrierOp(Variable result, AMD64AddressValue loadAddress, LIRFrameState state, GraalHotSpotVMConfig config, ForeignCallLinkage callTarget) { + super(TYPE, result, loadAddress, config, callTarget); + this.state = state; } @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - directCall(masm); + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } + final Register resultReg = asRegister(result); + MOV.emit(masm, AMD64BaseAssembler.OperandSize.QWORD, resultReg, loadAddress.toAddress()); + emitBarrier(crb, masm); } - - private void directCall(AMD64MacroAssembler masm) { - Register reg = ValueUtil.asRegister(functionPtr); - masm.indirectCall(reg); - masm.ensureUniquePC(); - } - - @Override - public boolean destroysCallerSavedRegisters() { - return true; - } - } diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZVectorReadBarrierOp.java b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZVectorReadBarrierOp.java new file mode 100644 index 000000000000..fb1aa0a65cd5 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotZVectorReadBarrierOp.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.amd64; + +import static jdk.vm.ci.amd64.AMD64.r15; +import static jdk.vm.ci.amd64.AMD64.rax; +import static jdk.vm.ci.code.ValueUtil.asRegister; + +import java.util.EnumSet; + +import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.asm.amd64.AMD64Address; +import org.graalvm.compiler.asm.amd64.AMD64Assembler; +import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRMOp; +import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Variable; +import org.graalvm.compiler.lir.amd64.AMD64AddressValue; +import org.graalvm.compiler.lir.amd64.AMD64Call; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.code.CallingConvention; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.AllocatableValue; + +public class AMD64HotSpotZVectorReadBarrierOp extends AMD64HotSpotZBarrieredOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotZVectorReadBarrierOp.class); + + private final AVXSize size; + private final AMD64Assembler.VexMoveOp op; + + @Temp({OperandFlag.REG}) protected AllocatableValue temp; + @State protected LIRFrameState state; + + public AMD64HotSpotZVectorReadBarrierOp(AVXSize size, AMD64Assembler.VexMoveOp op, Variable result, AMD64AddressValue loadAddress, LIRFrameState state, GraalHotSpotVMConfig config, + ForeignCallLinkage callTarget, Variable temp) { + super(TYPE, result, loadAddress, config, callTarget); + this.size = size; + this.op = op; + this.state = state; + this.temp = temp; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } + Register resultReg = asRegister(result); + op.emit(masm, size, resultReg, loadAddress.toAddress()); + + AMD64Address address = loadAddress.toAddress(); + + final Label entryPoint = new Label(); + final Label continuation = new Label(); + + Register tempReg = asRegister(temp); + EnumSet features = masm.getFeatures(); + GraalError.guarantee(features.contains(AMD64.CPUFeature.AVX), "Unexpected vector LIR without AVX"); + /* + * Depending on the target, we may need to use a broadcast larger than the read's size. This + * is benign as we will only use the part matching the read's size. + */ + AVXSize broadcastSize; + VexRMOp broadcastOp; + if (features.contains(AMD64.CPUFeature.AVX512F)) { + if (features.contains(AMD64.CPUFeature.AVX512VL)) { + broadcastSize = size; + } else { + broadcastSize = AVXSize.ZMM; + } + broadcastOp = VexRMOp.VPBROADCASTQ; + } else if (features.contains(AMD64.CPUFeature.AVX2)) { + broadcastSize = size; + broadcastOp = VexRMOp.VPBROADCASTQ; + } else { + broadcastSize = AVXSize.YMM; + broadcastOp = VexRMOp.VBROADCASTSD; + } + broadcastOp.emit(masm, broadcastSize, tempReg, new AMD64Address(r15, config.threadAddressBadMaskOffset)); + masm.vptest(resultReg, tempReg, size); + masm.jcc(AMD64Assembler.ConditionFlag.NotZero, entryPoint); + crb.getLIR().addSlowPath(this, () -> { + masm.bind(entryPoint); + + int count = size.getBytes() / 8; + CallingConvention cc = callTarget.getOutgoingCallingConvention(); + AMD64Address cArg0 = (AMD64Address) crb.asAddress(cc.getArgument(0)); + AMD64Address cArg1 = (AMD64Address) crb.asAddress(cc.getArgument(1)); + + // Use stack argument space for temporary register + masm.movq(cArg1, rax); + masm.leaq(rax, address); + masm.movq(cArg0, rax); + masm.movq(rax, cArg1); + masm.movslq(cArg1, count); + AMD64Call.directCall(crb, masm, callTarget, null, false, null); + masm.movq(resultReg, cArg0); + op.emit(masm, size, resultReg, loadAddress.toAddress()); + + // Return to inline code + masm.jmp(continuation); + }); + masm.bind(continuation); + } +} diff --git a/compiler/src/org.graalvm.compiler.hotspot.riscv64/src/org/graalvm/compiler/hotspot/riscv64/RISCV64HotSpotBackendFactory.java b/compiler/src/org.graalvm.compiler.hotspot.riscv64/src/org/graalvm/compiler/hotspot/riscv64/RISCV64HotSpotBackendFactory.java index 533d3c1d8048..359099f78327 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.riscv64/src/org/graalvm/compiler/hotspot/riscv64/RISCV64HotSpotBackendFactory.java +++ b/compiler/src/org.graalvm.compiler.hotspot.riscv64/src/org/graalvm/compiler/hotspot/riscv64/RISCV64HotSpotBackendFactory.java @@ -50,6 +50,8 @@ import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.java.DefaultSuitesCreator; import org.graalvm.compiler.lir.framemap.ReferenceMapBuilder; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.gc.BarrierSet; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.options.OptionValues; @@ -87,7 +89,7 @@ public Class getArchitecture() { @Override protected Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, TargetDescription target, HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, MetaAccessProvider metaAccess, - HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options) { + HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options, BarrierSet barrierSet) { Plugins plugins = HotSpotGraphBuilderPlugins.create(graalRuntime, compilerConfiguration, config, @@ -98,7 +100,8 @@ protected Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRun foreignCalls, replacements, options, - target); + target, + barrierSet); return plugins; } @@ -132,11 +135,19 @@ protected HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime return new RISCV64HotSpotForeignCallsProvider(jvmciRuntime, graalRuntime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters); } + public static class EmptyAddressLoweringPhase extends AddressLoweringPhase { + + @Override + protected void run(StructuredGraph graph, CoreProviders context) { + // Do nothing + } + } + @Override protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins, HotSpotRegistersProvider registers, HotSpotReplacementsImpl replacements, OptionValues options) { DefaultSuitesCreator suitesCreator = new DefaultSuitesCreator(compilerConfiguration, plugins); - BasePhase addressLoweringPhase = new AddressLoweringPhase(null); + BasePhase addressLoweringPhase = new EmptyAddressLoweringPhase(); return new AddressLoweringHotSpotSuitesProvider(suitesCreator, config, runtime, addressLoweringPhase); } diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DeferredBarrierAdditionTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DeferredBarrierAdditionTest.java index 2fa0237a4ede..2f232a080d42 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DeferredBarrierAdditionTest.java +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DeferredBarrierAdditionTest.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotGraalRuntime; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.gc.G1PostWriteBarrier; @@ -71,7 +72,7 @@ public static Object testCrossReferences() { @Test public void testGroupAllocation() throws Exception { - testHelper("testCrossReferences", 1, getInitialOptions()); + testHelper("testCrossReferences", config.gc == HotSpotGraalRuntime.HotSpotGC.Z ? 0 : 1, getInitialOptions()); } @SuppressWarnings("try") @@ -95,7 +96,7 @@ protected void testHelper(final String snippetName, final int expectedBarriers, checkAssumptions(graph); int barriers = 0; - if (config.useG1GC) { + if (config.useG1GC()) { barriers = graph.getNodes().filter(G1ReferentFieldReadBarrier.class).count() + graph.getNodes().filter(G1PreWriteBarrier.class).count() + graph.getNodes().filter(G1PostWriteBarrier.class).count(); } else { diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java index 0d113c7e16ae..f6fa0d165adc 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java @@ -121,7 +121,7 @@ public void testDeoptimize() { boolean has8278871 = store.getConstants().containsKey("Deoptimization::Reason_TRAP_HISTORY_LENGTH"); // JDK-8278871 Assume.assumeTrue("release".equals(System.getProperty("jdk.debug")) || has8278871); for (DeoptimizationReason r : DeoptimizationReason.values()) { - for (boolean osr : new boolean[]{false, true}) { + for (boolean osr : new boolean[]{false}) { this.reason = r; this.isOSR = osr; test("deoptimizeSnippet"); diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GCStressTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GCStressTest.java new file mode 100644 index 000000000000..6e448ed945d3 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GCStressTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.concurrent.ConcurrentHashMap; + +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; + +public class GCStressTest { + + @Before + public void before() { + Assume.assumeTrue("stress tests are being ignored", System.getProperty("gcstress") != null); + } + + private static void runTest(int count, Runnable target) throws InterruptedException { + Thread[] threads = new Thread[count]; + for (int i = 0; i < threads.length; i++) { + threads[i] = new Thread(target); + } + for (Thread thread : threads) { + thread.start(); + } + for (Thread thread : threads) { + thread.join(); + } + System.out.println("Done"); + } + + public static void main(String[] args) throws InterruptedException { + runTest(16, new DoList()); + runTest(16, new DoCopyOf()); + + } + + static class DoList implements Runnable { + + static long globalTotal = 0; + + @Override + public void run() { + for (int k = 0; k < 800000; k++) { + LinkedList list = new LinkedList<>(); + for (int i = 0; i < 1000; i++) { + list.add(i); + } + int total = 0; + Collections.reverse(list); + for (Integer v : list) { + total += v; + } + globalTotal += total; + } + } + } + + @Test + public void list() throws InterruptedException { + runTest(16, new DoList()); + } + + static class DoCopyOf implements Runnable { + + static long globalTotal = 0; + + @Override + public void run() { + for (int k = 0; k < 8000; k++) { + Integer[] list = new Integer[0]; + for (int i = 0; i < 1000; i++) { + list = Arrays.copyOf(list, list.length + 1); + list[i] = i; + } + int total = 0; + Arrays.sort(list, new Comparator() { + @Override + public int compare(Integer x, Integer y) { + return (x < y) ? -1 : ((x.equals(y)) ? 1 : 0); + } + }); + + for (Integer v : list) { + total += v; + } + globalTotal += total; + } + } + } + + @Test + public void copyOf() throws InterruptedException { + runTest(16, new DoCopyOf()); + } + + static class DoConcurrent implements Runnable { + ConcurrentHashMap map = new ConcurrentHashMap<>(); + + @Override + public void run() { + for (int k = 0; k < 8000; k++) { + for (int i = 0; i < 1000; i++) { + String s = map.get(i); + if (s == null) { + s = ""; + } + s = s + i; + s = s.substring(s.length() - Math.min(s.length(), 10)); + map.put(i, s); + } + } + } + } + + @Test + public void concurrentMap() throws InterruptedException { + runTest(16, new DoConcurrent()); + } +} diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotObjectSizeTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotObjectSizeTest.java index 030c429b75e5..396c6adc5299 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotObjectSizeTest.java +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotObjectSizeTest.java @@ -47,7 +47,7 @@ public static long objectSize(InstrumentationImpl impl, Object o) { public void testNewInstance() throws InstantiationException, InvalidInstalledCodeException { List> objects = new ArrayList<>(); objects.add(Pair.create(new Object(), 16L)); - objects.add(Pair.create(new String(), 24L)); + objects.add(Pair.create(new String(), runtime().getVMConfig().useCompressedOops ? 24L : 32L)); objects.add(Pair.create(new byte[1], 24L)); objects.add(Pair.create(new boolean[1][1], 24L)); objects.add(Pair.create(new long[64], 528L)); @@ -58,7 +58,8 @@ public void testNewInstance() throws InstantiationException, InvalidInstalledCod InstalledCode code = getCode(getResolvedJavaMethod("objectSize")); for (Pair pair : objects) { - assertTrue(pair.getRight() == (long) code.executeVarargs(instance, pair.getLeft())); + long actual = (long) code.executeVarargs(instance, pair.getLeft()); + assertTrue(pair.getRight() == actual, "%s expected size of %s but got %s", pair.getLeft().getClass(), pair.getRight(), actual); } } diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java index c1dc7d8ca37d..1a64f6bf23c5 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java @@ -29,6 +29,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.PartialEscapeAnalysis; import static org.graalvm.compiler.core.common.GraalOptions.PartialUnroll; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.referentOffset; +import static org.junit.Assume.assumeTrue; import java.lang.ref.Reference; import java.lang.ref.WeakReference; @@ -37,6 +38,7 @@ import java.util.Objects; import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.test.TestPhase; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; @@ -48,7 +50,6 @@ import org.graalvm.compiler.nodes.gc.G1PreWriteBarrier; import org.graalvm.compiler.nodes.gc.G1ReferentFieldReadBarrier; import org.graalvm.compiler.nodes.gc.SerialWriteBarrier; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; @@ -60,7 +61,6 @@ import org.graalvm.compiler.runtime.RuntimeProvider; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import jdk.vm.ci.meta.JavaConstant; @@ -116,7 +116,7 @@ public int hashCode() { */ @Test public void testAllocation() throws Exception { - this.expectedBarriers = (config.useG1GC) ? 4 : 2; + this.expectedBarriers = (config.useG1GC()) ? 4 : 2; testWithoutPEA("testAllocationSnippet"); } @@ -134,7 +134,7 @@ public static Container testAllocationSnippet() { */ @Test public void testLoopAllocation1() throws Exception { - this.expectedBarriers = config.useG1GC ? 8 : 4; + this.expectedBarriers = config.useG1GC() ? 8 : 4; testWithoutPEA("test2Snippet", false); testWithoutPEA("test2Snippet", true); } @@ -159,7 +159,7 @@ public static void test2Snippet(boolean test) { */ @Test public void testLoopAllocation2() throws Exception { - this.expectedBarriers = config.useG1GC ? 8 : 4; + this.expectedBarriers = config.useG1GC() ? 8 : 4; testWithoutPEA("test3Snippet"); } @@ -183,7 +183,7 @@ public static void test3Snippet() { */ @Test public void testReferenceGet() throws Exception { - this.expectedBarriers = config.useG1GC ? 1 : 0; + this.expectedBarriers = config.useG1GC() ? 1 : 0; test("testReferenceGetSnippet"); } @@ -214,7 +214,7 @@ private static MetaAccessProvider getStaticMetaAccess() { */ @Test public void testReferenceReferent1() throws Exception { - this.expectedBarriers = config.useG1GC ? 1 : 0; + this.expectedBarriers = config.useG1GC() ? 1 : 0; test("testReferenceReferentSnippet"); } @@ -224,13 +224,12 @@ public Object testReferenceReferentSnippet() { /** * The type is known to be WeakReference and the offset is non-constant, so the lowering of the - * {@link org.graalvm.compiler.nodes.extended.RawLoadNode} is guarded by a check that the offset - * is the same as {@link #referenceReferentFieldOffset} which does a barrier if requires it. + * {@link org.graalvm.compiler.nodes.extended.RawLoadNode} doesn't require a barrier even if it + * were the referent field. See JDK-8189871 for a discussion. */ @Test - @Ignore("GR-31031") public void testReferenceReferent2() throws Exception { - this.expectedBarriers = config.useG1GC ? 1 : 0; + this.expectedBarriers = 0; test("testReferenceReferent2Snippet", referenceReferentFieldOffset); } @@ -253,15 +252,14 @@ public Object testReferenceReferent3Snippet() { } /** - * The type is a super class of WeakReference and the offset is non-constant, so the lowering of - * the {@link org.graalvm.compiler.nodes.extended.RawLoadNode} is guarded by a check that the - * offset is the same as {@link #referenceReferentFieldOffset} and the base object is a - * subclasses of {@link java.lang.ref.Reference} and does a barrier if requires it. + * The type is a super class of WeakReference and the offset is non-constant, so + * canonicalization of the {@link org.graalvm.compiler.nodes.extended.RawLoadNode} will raise + * this to a {@link org.graalvm.compiler.nodes.java.LoadFieldNode} which will have a barrier + * when the node is lowered. */ @Test - @Ignore("GR-31031") public void testReferenceReferent4() throws Exception { - this.expectedBarriers = config.useG1GC ? 1 : 0; + this.expectedBarriers = config.useG1GC() ? 1 : 0; test("testReferenceReferent4Snippet"); } @@ -310,7 +308,7 @@ private void verifyBarriers(StructuredGraph graph) { Assert.assertTrue("Unknown collector selected", knownSupport.contains(runtime().getGarbageCollector())); Assert.assertNotEquals("test must set expected barrier count", expectedBarriers, -1); int barriers = 0; - if (config.useG1GC) { + if (config.useG1GC()) { barriers = graph.getNodes().filter(G1ReferentFieldReadBarrier.class).count() + graph.getNodes().filter(G1PreWriteBarrier.class).count() + graph.getNodes().filter(G1PostWriteBarrier.class).count(); } else { @@ -320,7 +318,7 @@ private void verifyBarriers(StructuredGraph graph) { Assert.assertEquals(expectedBarriers, barriers); } for (WriteNode write : graph.getNodes().filter(WriteNode.class)) { - if (config.useG1GC) { + if (config.useG1GC()) { if (write.getBarrierType() != BarrierType.NONE) { Assert.assertEquals(1, write.successors().count()); Assert.assertTrue(write.next() instanceof G1PostWriteBarrier); @@ -342,8 +340,8 @@ private void verifyBarriers(StructuredGraph graph) { Assert.assertEquals(referentOffset(getMetaAccess()), constDisp.asLong()); } } - Assert.assertTrue(BarrierType.WEAK_FIELD == read.getBarrierType() || BarrierType.PHANTOM_FIELD == read.getBarrierType()); - if (config.useG1GC) { + Assert.assertTrue(BarrierType.REFERENCE_GET == read.getBarrierType() || BarrierType.PHANTOM_REFERS_TO == read.getBarrierType()); + if (config.useG1GC()) { Assert.assertTrue(read.next() instanceof G1ReferentFieldReadBarrier); } } @@ -356,6 +354,7 @@ protected Result testWithoutPEA(String name, Object... args) { @Before public void before() { + assumeTrue("ZGC has no write barriers", !(config.gc == HotSpotGC.Z)); expectedBarriers = -1; } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java index 485f99c9dc86..cc14e5fb0329 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java @@ -32,6 +32,7 @@ import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.core.common.CompressEncoding; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.options.OptionValues; @@ -80,6 +81,32 @@ public CompressEncoding getKlassEncoding() { return klassEncoding; } + public boolean useG1GC() { + return gc == HotSpotGraalRuntime.HotSpotGC.G1; + } + + public final HotSpotGraalRuntime.HotSpotGC gc = getSelectedGC(); + + private HotSpotGraalRuntime.HotSpotGC getSelectedGC() throws GraalError { + HotSpotGraalRuntime.HotSpotGC selected = null; + for (HotSpotGraalRuntime.HotSpotGC value : HotSpotGraalRuntime.HotSpotGC.values()) { + if (value.isSelected(this)) { + if (!value.supported) { + throw new GraalError(value.name() + " garbage collector is not supported by Graal"); + } + if (selected != null) { + throw new GraalError("Multiple garbage collectors selected: " + selected + " " + value); + } + selected = value; + } + } + if (selected == null) { + // Exactly one GC flag is guaranteed to be selected. + selected = HotSpotGraalRuntime.HotSpotGC.Serial; + } + return selected; + } + public final boolean cAssertions = getConstant("ASSERT", Boolean.class); public final int codeEntryAlignment = getFlag("CodeEntryAlignment", Integer.class); @@ -156,8 +183,6 @@ public boolean useCRC32CIntrinsics() { return useCRC32CIntrinsics && updateBytesCRC32C != 0; } - public final boolean useG1GC = getFlag("UseG1GC", Boolean.class); - public final int allocatePrefetchStyle = getFlag("AllocatePrefetchStyle", Integer.class); public final int allocatePrefetchInstr = getFlag("AllocatePrefetchInstr", Integer.class); public final int allocatePrefetchLines = getFlag("AllocatePrefetchLines", Integer.class); @@ -466,9 +491,30 @@ private static String markWordField(String simpleName) { public final int basicLockSize = getFieldValue("CompilerToVM::Data::sizeof_BasicLock", Integer.class, "int"); public final int basicLockDisplacedHeaderOffset = getFieldOffset("BasicLock::_displaced_header", Integer.class, markWord); + /** + * This indicates whether a JDK is expected to include the export necessary to support ZGC. It + * includes other things that are required for ZGC but that aren't actually directly related to + * ZGC like nmethod entry barriers and support for concurrent scanning of frames. + */ + private final boolean zgcSupport; + { + boolean support = false; + if (JDK == 19) { + // There are still some gates using jdk 19 so we must handle the existence of the + // required entries but we don't permit ZGC to be used there. + support = JVMCI && jvmciGE(JVMCI_23_0_b05); + } else { + support = JVMCI ? jvmciGE(JVMCI_23_0_b07) : JDK >= 20; + } + zgcSupport = support; + } + // JDK-8253180 & JDK-8265932 public final int threadPollingPageOffset = getFieldOffset("JavaThread::_poll_data", Integer.class, "SafepointMechanism::ThreadData") + getFieldOffset("SafepointMechanism::ThreadData::_polling_page", Integer.class, "volatile uintptr_t"); + public final int threadPollingWordOffset = getFieldOffset("JavaThread::_poll_data", Integer.class, "SafepointMechanism::ThreadData") + + getFieldOffset("SafepointMechanism::ThreadData::_polling_word", Integer.class, "volatile uintptr_t"); + public final int savedExceptionPCOffset = getFieldOffset("JavaThread::_saved_exception_pc", Integer.class, "address", -1, zgcSupport); private final int threadLocalAllocBufferEndOffset = getFieldOffset("ThreadLocalAllocBuffer::_end", Integer.class, "HeapWord*"); private final int threadLocalAllocBufferTopOffset = getFieldOffset("ThreadLocalAllocBuffer::_top", Integer.class, "HeapWord*"); @@ -492,6 +538,8 @@ public int threadTlabTopOffset() { public final long deoptBlobUnpack = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_unpack", Long.class, "address"); public final long deoptBlobUnpackWithExceptionInTLS = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_unpack_with_exception_in_tls", Long.class, "address"); + public final long pollingPageReturnHandler = getFieldValue("CompilerToVM::Data::SharedRuntime_polling_page_return_handler", Long.class, "address", 0L, + zgcSupport); public final long deoptBlobUncommonTrap = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap", Long.class, "address"); public final long codeCacheLowBound = getFieldValue("CodeCache::_low_bound", Long.class, "address"); @@ -614,6 +662,60 @@ private boolean checkNullAllocationStubs() { // This flag indicates that support for loom is enabled. public final boolean continuationsEnabled = getFieldValue("CompilerToVM::Data::continuations_enabled", Boolean.class, "bool", JDK > 19, JDK >= 19 && jvmciGE(JVMCI_23_0_b04)); + private long getZGCAddressField(String name) { + long address = getFieldValue(name, Long.class, "address", 0L, zgcSupport); + GraalError.guarantee(!(gc == HotSpotGraalRuntime.HotSpotGC.Z) || address != 0, "Unexpected null value for %s", name); + return address; + } + + // If the nmethod_entry_barrier field is non-null then an entry barrier must be emitted + public final int threadDisarmedOffset = getFieldValue("CompilerToVM::Data::thread_disarmed_offset", Integer.class, "int", 0, zgcSupport); + public final long nmethodEntryBarrier = getFieldValue("CompilerToVM::Data::nmethod_entry_barrier", Long.class, "address", 0L, zgcSupport); + + // ZGC support + public final int threadAddressBadMaskOffset = getFieldValue("CompilerToVM::Data::thread_address_bad_mask_offset", Integer.class, "int", 0, zgcSupport); + public final long zBarrierSetRuntimeLoadBarrierOnOopFieldPreloaded = getZGCAddressField("CompilerToVM::Data::ZBarrierSetRuntime_load_barrier_on_oop_field_preloaded"); + public final long zBarrierSetRuntimeLoadBarrierOnWeakOopFieldPreloaded = getZGCAddressField("CompilerToVM::Data::ZBarrierSetRuntime_load_barrier_on_weak_oop_field_preloaded"); + public final long zBarrierSetRuntimeWeakLoadBarrierOnWeakOopFieldPreloaded = getZGCAddressField("CompilerToVM::Data::ZBarrierSetRuntime_weak_load_barrier_on_weak_oop_field_preloaded"); + public final long zBarrierSetRuntimeWeakLoadBarrierOnPhantomOopFieldPreloaded = getZGCAddressField("CompilerToVM::Data::ZBarrierSetRuntime_weak_load_barrier_on_phantom_oop_field_preloaded"); + public final long zBarrierSetRuntimeLoadBarrierOnOopArray = getZGCAddressField("CompilerToVM::Data::ZBarrierSetRuntime_load_barrier_on_oop_array"); + // There are 3 other entry points which we don't seem to need. + // CompilerToVM::Data::ZBarrierSetRuntime_load_barrier_on_phantom_oop_field_preloaded and + // CompilerToVM::Data::ZBarrierSetRuntime_weak_load_barrier_on_oop_field_preloaded don't seem + // to correspond to any pattern we actually emit. CompilerToVM::Data::ZBarrierSetRuntime_clone + // heals all fields of the passed in object. C2 uses this when cloning because it emit bulk copy + // of the object. We always represent cloning as a field by field copy because this is more PEA + // friendly. + + { + // aarch64 code generation for the entry barrier is complicated and varies by release so + // check for the acceptable patterns here. + Boolean patchConcurrent = null; + if (osArch.equals("aarch64") && nmethodEntryBarrier != 0) { + if (JDK >= 20) { + Integer patchingType = getFieldValue("CompilerToVM::Data::BarrierSetAssembler_nmethod_patching_type", Integer.class, "int"); + if (patchingType != null) { + // There currently only 2 variants in use that differ only by the presence of a + // dmb instruction + int stw = getConstant("NMethodPatchingType::stw_instruction_and_data_patch", Integer.class); + int conc = getConstant("NMethodPatchingType::conc_data_patch", Integer.class); + if (patchingType == stw) { + patchConcurrent = false; + } else if (patchingType == conc) { + patchConcurrent = true; + } else { + throw new IllegalArgumentException("unsupported barrier sequence " + patchingType); + } + } + } else { + // The normal pattern is with a dmb + patchConcurrent = true; + } + } + nmethodEntryBarrierConcurrentPatch = patchConcurrent; + } + public final Boolean nmethodEntryBarrierConcurrentPatch; + // Tracking of the number of monitors held by the current thread. This is used by loom but in // JDK 20 was enabled by default to ensure it was correctly implemented. public final int threadHeldMonitorCountOffset; @@ -622,10 +724,7 @@ private boolean checkNullAllocationStubs() { { int offset = -1; boolean isWord = false; - if (JDK == 19) { - offset = getFieldOffset("JavaThread::_held_monitor_count", Integer.class, "int"); - isWord = false; - } else if (JDK >= 20) { + if (JDK >= 20) { offset = getFieldOffset("JavaThread::_held_monitor_count", Integer.class, "int64_t"); isWord = true; } @@ -634,7 +733,7 @@ private boolean checkNullAllocationStubs() { } // This should be true when loom is enabled on 19 but that still needs to be exposed by JVMCI - public final boolean updateHeldMonitorCount = JDK >= 20; + public final boolean updateHeldMonitorCount = JDK >= 20 || continuationsEnabled; public final long throwAndPostJvmtiExceptionAddress = getAddress("JVMCIRuntime::throw_and_post_jvmti_exception"); public final long throwKlassExternalNameExceptionAddress = getAddress("JVMCIRuntime::throw_klass_external_name_exception"); @@ -691,6 +790,9 @@ private void populateMarkConstants() { String key = "CodeInstaller::" + markId.name(); Long result = constants.get(key); if (result == null) { + if (markId == HotSpotMarkId.ENTRY_BARRIER_PATCH) { + continue; + } GraalHotSpotVMConfigAccess.reportError("Unsupported Mark " + markId); } markId.setValue(result.intValue()); @@ -721,5 +823,4 @@ public boolean supportsMethodHandleDeoptimizationEntry() { return HotSpotMarkId.DEOPT_MH_HANDLER_ENTRY.isAvailable() && VMINTRINSIC_FIRST_MH_SIG_POLY != -1 && VMINTRINSIC_LAST_MH_SIG_POLY != -1 && VMINTRINSIC_INVOKE_GENERIC != -1 && VMINTRINSIC_COMPILED_LAMBDA_FORM != -1; } - } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigAccess.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigAccess.java index ac0a7b08fc8d..8a2b79fbbee0 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigAccess.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigAccess.java @@ -122,6 +122,8 @@ protected static String getProperty(String name) { public final String osArch; protected static final Version JVMCI_23_0_b04 = new Version(23, 0, 4); + protected static final Version JVMCI_23_0_b05 = new Version(23, 0, 5); + protected static final Version JVMCI_23_0_b07 = new Version(23, 0, 7); public static boolean jvmciGE(Version v) { return JVMCI && !JVMCI_VERSION.isLessThan(v); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java index 4e64926fed57..01473794d2a3 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java @@ -43,6 +43,7 @@ import org.graalvm.collections.MapCursor; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; @@ -67,14 +68,12 @@ import org.graalvm.compiler.lir.StandardOp.RestoreRegistersOp; import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.ValueConsumer; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.UnwindNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionKey; -import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.word.Word; @@ -107,9 +106,6 @@ public static class Options { // @formatter:off @Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible") public static final OptionKey GraalArithmeticStubs = new OptionKey<>(true); - @Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." + - " Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug) - public static final OptionKey ASMInstructionProfiling = new OptionKey<>(null); // @formatter:on } @@ -421,6 +417,16 @@ protected void updateStub(Stub stub, HotSpotLIRGenerationResult gen, FrameMap fr } } + // Only allocatable registers must be described as killed. This works around an issue where + // the set of allocatable registers is different than the registers actually used for + // allocation by linear scan on AVX512. + RegisterAllocationConfig registerAllocationConfig = newRegisterAllocationConfig(frameMap.getRegisterConfig(), null); + EconomicSet allocatableRegisters = EconomicSet.create(); + for (Register r : registerAllocationConfig.getAllocatableRegisters()) { + allocatableRegisters.add(r); + } + destroyedRegisters.retainAll(allocatableRegisters); + stub.initDestroyedCallerRegisters(destroyedRegisters); MapCursor cursor = calleeSaveInfo.getEntries(); @@ -443,12 +449,6 @@ public SuitesProvider getSuites() { return getProviders().getSuites(); } - protected void profileInstructions(LIR lir, CompilationResultBuilder crb) { - if (HotSpotBackend.Options.ASMInstructionProfiling.getValue(lir.getOptions()) != null) { - HotSpotInstructionProfiling.countInstructions(lir, crb.asm); - } - } - @Override public CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java index 8c4ddc97cd3d..3828535e4b87 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java @@ -30,6 +30,8 @@ import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider; @@ -40,9 +42,18 @@ import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider; import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider; +import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; +import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.ArrayRangeWrite; +import org.graalvm.compiler.nodes.gc.BarrierSet; +import org.graalvm.compiler.nodes.gc.CardTableBarrierSet; +import org.graalvm.compiler.nodes.gc.G1BarrierSet; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.nodes.java.AbstractNewObjectNode; import org.graalvm.compiler.nodes.loop.LoopsDataProviderImpl; +import org.graalvm.compiler.nodes.memory.FixedAccessNode; import org.graalvm.compiler.nodes.spi.LoopsDataProvider; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; @@ -56,6 +67,8 @@ import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.Value; import jdk.vm.ci.runtime.JVMCIBackend; @@ -73,8 +86,8 @@ protected HotSpotStampProvider createStampProvider() { return new HotSpotStampProvider(); } - protected HotSpotPlatformConfigurationProvider createConfigInfoProvider(GraalHotSpotVMConfig config, MetaAccessProvider metaAccess) { - return new HotSpotPlatformConfigurationProvider(config, metaAccess); + protected HotSpotPlatformConfigurationProvider createConfigInfoProvider(GraalHotSpotVMConfig config, BarrierSet barrierSet) { + return new HotSpotPlatformConfigurationProvider(config, barrierSet); } protected HotSpotMetaAccessExtensionProvider createMetaAccessExtensionProvider() { @@ -143,9 +156,10 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti try (InitTimer rt = timer("create ForeignCalls provider")) { foreignCalls = createForeignCalls(jvmciRuntime, graalRuntime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters); } + BarrierSet barrierSet = createBarrierSet(config, metaAccess); HotSpotPlatformConfigurationProvider platformConfigurationProvider; try (InitTimer rt = timer("create platform configuration provider")) { - platformConfigurationProvider = createConfigInfoProvider(config, metaAccess); + platformConfigurationProvider = createConfigInfoProvider(config, barrierSet); } HotSpotMetaAccessExtensionProvider metaAccessExtensionProvider; try (InitTimer rt = timer("create MetaAccessExtensionProvider")) { @@ -184,7 +198,7 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti GraphBuilderConfiguration.Plugins plugins; try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { plugins = createGraphBuilderPlugins(graalRuntime, compilerConfiguration, config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, - options); + options, barrierSet); replacements.setGraphBuilderPlugins(plugins); } try (InitTimer rt = timer("create Suites provider")) { @@ -205,7 +219,7 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti protected abstract GraphBuilderConfiguration.Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, TargetDescription target, HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, MetaAccessProvider metaAccess, - HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options); + HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options, BarrierSet barrierSet); protected abstract HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, GraphBuilderConfiguration.Plugins plugins, @@ -220,4 +234,80 @@ protected abstract HotSpotLoweringProvider createLowerer(HotSpotGraalRuntimeProv protected abstract HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime, MetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, HotSpotWordTypes wordTypes, Value[] nativeABICallerSaveRegisters); + private BarrierSet createBarrierSet(GraalHotSpotVMConfig config, MetaAccessProvider metaAccess) { + boolean useDeferredInitBarriers = config.useDeferredInitBarriers; + ResolvedJavaType objectArrayType = metaAccess.lookupJavaType(Object[].class); + if (config.gc == HotSpotGraalRuntime.HotSpotGC.Z) { + ResolvedJavaField referentField = HotSpotReplacementsUtil.referentField(metaAccess); + return new HotSpotZBarrierSet(referentField); + } else if (config.useG1GC()) { + ResolvedJavaField referentField = HotSpotReplacementsUtil.referentField(metaAccess); + return new G1BarrierSet(objectArrayType, referentField) { + @Override + protected boolean writeRequiresPostBarrier(FixedAccessNode node, ValueNode writtenValue) { + if (!super.writeRequiresPostBarrier(node, writtenValue)) { + return false; + } + return !useDeferredInitBarriers || !isWriteToNewObject(node); + } + + @Override + protected boolean arrayRangeWriteRequiresPostBarrier(ArrayRangeWrite write) { + if (!super.arrayRangeWriteRequiresPostBarrier(write)) { + return false; + } + return !useDeferredInitBarriers || !isWriteToNewObject(write.asFixedWithNextNode(), write.getAddress().getBase()); + } + }; + } else { + return new CardTableBarrierSet(objectArrayType) { + @Override + protected boolean writeRequiresBarrier(FixedAccessNode node, ValueNode writtenValue) { + if (!super.writeRequiresBarrier(node, writtenValue)) { + return false; + } + return !useDeferredInitBarriers || !isWriteToNewObject(node); + } + + @Override + protected boolean arrayRangeWriteRequiresBarrier(ArrayRangeWrite write) { + if (!super.arrayRangeWriteRequiresBarrier(write)) { + return false; + } + return !useDeferredInitBarriers || !isWriteToNewObject(write.asFixedWithNextNode(), write.getAddress().getBase()); + } + }; + } + } + + /** + * For initializing writes, the last allocation executed by the JVM is guaranteed to be + * automatically card marked so it's safe to skip the card mark in the emitted code. + */ + protected boolean isWriteToNewObject(FixedAccessNode node) { + if (!node.getLocationIdentity().isInit()) { + return false; + } + // This is only allowed for the last allocation in sequence + return isWriteToNewObject(node, node.getAddress().getBase()); + } + + protected boolean isWriteToNewObject(FixedWithNextNode node, ValueNode base) { + if (base instanceof AbstractNewObjectNode) { + Node pred = node.predecessor(); + while (pred != null) { + if (pred == base) { + node.getDebug().log(DebugContext.INFO_LEVEL, "Deferred barrier for %s with base %s", node, base); + return true; + } + if (pred instanceof AbstractNewObjectNode) { + node.getDebug().log(DebugContext.INFO_LEVEL, "Disallowed deferred barrier for %s because %s was last allocation instead of %s", node, pred, base); + return false; + } + pred = pred.predecessor(); + } + } + node.getDebug().log(DebugContext.INFO_LEVEL, "Unable to find allocation for deferred barrier for %s with base %s", node, base); + return false; + } } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java index 435b2ab59f43..f318dad2bd70 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java @@ -107,6 +107,16 @@ public static HotSpotCompiledCode createCompiledCode(CodeCacheProvider codeCache DataSection data = compResult.getDataSection(); byte[] dataSection = new byte[data.getSectionSize()]; + // Ensure the mutable data item for the nmethod entry barrier is the first thing in the data + // section. + boolean first = true; + for (DataSection.Data item : data) { + if (item.isMutable()) { + GraalError.guarantee(first, "mutable item must be first"); + } + first = false; + } + ByteBuffer buffer = ByteBuffer.wrap(dataSection).order(ByteOrder.nativeOrder()); List patches = new ArrayList<>(); data.buildDataSection(buffer, (position, vmConstant) -> { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java index cea7692e852d..54807944bcb9 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java @@ -42,8 +42,23 @@ public interface HotSpotForeignCallLinkage extends ForeignCallLinkage, InvokeTar * {@linkplain ForeignCallLinkage#getTemporaries() temporary} registers. */ enum RegisterEffect { + /** + * Acts like a normal call. + */ DESTROYS_ALL_CALLER_SAVE_REGISTERS, - COMPUTES_REGISTERS_KILLED + + /** + * Compute the set of registers which are killed from the LIR and emits register save and + * restore logic around any internal foreign calls to reduce the number of registers which + * are killed. + */ + COMPUTES_REGISTERS_KILLED, + + /** + * Uses a stack based calling convention and saves and restores all registers around + * internal foreign calls. + */ + KILLS_NO_REGISTERS } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java index 4e5e5ca81387..191a8e6a947c 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java @@ -30,6 +30,7 @@ import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.target.Backend; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -40,19 +41,90 @@ import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.StackSlot; +import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.code.ValueKindFactory; import jdk.vm.ci.hotspot.HotSpotCallingConventionType; import jdk.vm.ci.hotspot.HotSpotForeignCallTarget; import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.Value; +import jdk.vm.ci.meta.ValueKind; /** * The details required to link a HotSpot runtime or stub call. */ public class HotSpotForeignCallLinkageImpl extends HotSpotForeignCallTarget implements HotSpotForeignCallLinkage { + /** + * A calling convention where all arguments are passed through the stack and any return values + * are passed through the stack. This is useful for assembly slow paths where we don't want to + * perturb the register allocation of the fast path. + */ + public enum StackOnlyCallingConvention implements CallingConvention.Type { + + /** + * The stack only convention from the perspective of the caller. + */ + StackOnlyCall(true), + + /** + * The stack only convention from the perspective of the callee. + */ + StackOnlyCallee(false); + + /** + * Determines if this is a request for the outgoing argument locations at a call site. + */ + public final boolean out; + + StackOnlyCallingConvention(boolean out) { + this.out = out; + } + + /** + * Creates a calling convention were all arguments and the return value are passed on the + * stack. This follows the stack layout of normal Java calling convention. + * + * A platform specific definition of this could be provided but currently AMD64 and AArch64 + * do exactly the same thing so for simplicity it is provided here. + */ + public CallingConvention getCallingConvention(TargetDescription target, JavaType returnType, JavaType[] parameterTypes, + ValueKindFactory valueKindFactory) { + AllocatableValue[] locations = new AllocatableValue[parameterTypes.length]; + int currentStackOffset = 0; + for (int i = 0; i < parameterTypes.length; i++) { + final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind(); + switch (kind) { + case Illegal: + case Void: + throw GraalError.shouldNotReachHere(kind.toString()); + } + + ValueKind valueKind = valueKindFactory.getValueKind(kind); + locations[i] = StackSlot.get(valueKind, currentStackOffset, !this.out); + currentStackOffset += Math.max(valueKind.getPlatformKind().getSizeInBytes(), target.wordSize); + } + + JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind(); + AllocatableValue returnLocation = Value.ILLEGAL; + if (returnKind != JavaKind.Void) { + /* + * The return value is also passed through the stack so use the same location that + * would be used if it were an incoming argument. + */ + ValueKind valueKind = valueKindFactory.getValueKind(returnKind); + returnLocation = StackSlot.get(valueKind, 0, !this.out); + int slotSize = Math.max(valueKind.getPlatformKind().getSizeInBytes(), target.wordSize); + currentStackOffset = Math.max(currentStackOffset, slotSize); + } + + return new CallingConvention(currentStackOffset, returnLocation, locations); + } + } + /** * The descriptor of the call. */ @@ -126,6 +198,10 @@ public static CallingConvention createCallingConvention(MetaAccessProvider metaA } JavaType returnType = asJavaType(descriptor.getResultType(), metaAccess, wordTypes); RegisterConfig regConfig = codeCache.getRegisterConfig(); + if (ccType instanceof StackOnlyCallingConvention) { + StackOnlyCallingConvention conventionType = (StackOnlyCallingConvention) ccType; + return conventionType.getCallingConvention(codeCache.getTarget(), returnType, parameterTypes, valueKindFactory); + } return regConfig.getCallingConvention(ccType, returnType, parameterTypes, valueKindFactory); } @@ -261,6 +337,9 @@ public void finalizeAddress(Backend backend) { for (Register reg : killedRegisters) { temporaryLocations[i++] = reg.asValue(); } + if (stub.getLinkage().getEffect() == HotSpotForeignCallLinkage.RegisterEffect.KILLS_NO_REGISTERS) { + GraalError.guarantee(temporaryLocations.length == 0, "no registers are expected to be killed: %s %s", this, temporaryLocations); + } temporaries = temporaryLocations; } address = codeInfo.start; diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java index 855a5d5f9e9b..74892188cda9 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java @@ -27,6 +27,7 @@ import static jdk.vm.ci.common.InitTimer.timer; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; +import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigAccess.JDK; import java.io.PrintStream; import java.util.ArrayList; @@ -46,7 +47,6 @@ import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext.Builder; import org.graalvm.compiler.debug.DebugContext.Description; @@ -105,7 +105,6 @@ public GlobalMetrics getMetricValues() { private final GlobalMetrics metricValues = new GlobalMetrics(); private final List snippetCounterGroups; - private final HotSpotGC garbageCollector; private final EconomicMap, HotSpotBackend> backends = EconomicMap.create(Equivalence.IDENTITY); @@ -138,8 +137,6 @@ public GlobalMetrics getMetricValues() { options = initialOptions; } - garbageCollector = getSelectedGC(); - outputDirectory = new DiagnosticsOutputDirectory(options); compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class); snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null; @@ -208,10 +205,10 @@ public enum HotSpotGC { Serial(true, true, "UseSerialGC", true), Parallel(true, true, "UseParallelGC", true), G1(true, true, "UseG1GC", true), + Z(JDK == 17 || JDK >= 20, true, "UseZGC", true), // Unsupported GCs Epsilon(false, true, "UseEpsilonGC", true), - Z(false, true, "UseZGC", true), Shenandoah(false, true, "UseShenandoahGC", true); HotSpotGC(boolean supported, boolean expectNamePresent, String flag, boolean expectFlagPresent) { @@ -262,27 +259,6 @@ static HotSpotGC forName(int name, GraalHotSpotVMConfig config) { } } - private HotSpotGC getSelectedGC() throws GraalError { - HotSpotGC selected = null; - for (HotSpotGC gc : HotSpotGC.values()) { - if (gc.isSelected(config)) { - if (!gc.supported) { - throw new GraalError(gc.name() + " garbage collector is not supported by Graal"); - } - selected = gc; - if (!Assertions.assertionsEnabled()) { - // When asserting, check that isSelected works for all HotSpotGC values - break; - } - } - } - if (selected == null) { - // Exactly one GC flag is guaranteed to be selected. - selected = HotSpotGC.Serial; - } - return selected; - } - private HotSpotBackend registerBackend(HotSpotBackend backend) { Class arch = backend.getTarget().arch.getClass(); HotSpotBackend oldValue = backends.put(arch, backend); @@ -358,7 +334,7 @@ public T getCapability(Class clazz) { @Override public HotSpotGC getGarbageCollector() { - return garbageCollector; + return config.gc; } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java index 92a75f25142f..6ba0e1a51626 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java @@ -90,6 +90,12 @@ public abstract class HotSpotHostBackend extends HotSpotBackend implements LIRGe public static final HotSpotForeignCallDescriptor THROW_DELAYED_STACKOVERFLOW_ERROR = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS, "throwDelayedStackoverflowError", void.class); + /** + * Descriptor for {@code SharedRuntime::polling_page_return_handler_blob()->entry_point()}. + */ + public static final HotSpotForeignCallDescriptor POLLING_PAGE_RETURN_HANDLER = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS, + "polling_page_return_handler_blob()", void.class); + protected final GraalHotSpotVMConfig config; public HotSpotHostBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java deleted file mode 100644 index f76c51e5ea40..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java +++ /dev/null @@ -1,169 +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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot; - -import java.util.ArrayList; - -import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.asm.Assembler.InstructionCounter; -import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.cfg.BasicBlock; -import org.graalvm.compiler.lir.ConstantValue; -import org.graalvm.compiler.lir.LIR; -import org.graalvm.compiler.lir.LIRInsertionBuffer; -import org.graalvm.compiler.lir.LIRInstruction; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.StandardOp.BlockEndOp; -import org.graalvm.compiler.lir.StandardOp.LabelOp; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.gen.DiagnosticLIRGeneratorTool; -import org.graalvm.compiler.lir.gen.LIRGenerationResult; -import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase; - -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Value; - -public class HotSpotInstructionProfiling extends PostAllocationOptimizationPhase { - public static final String COUNTER_GROUP = "INSTRUCTION_COUNTER"; - private final String[] instructionsToProfile; - - public HotSpotInstructionProfiling(String instructionsToProfile) { - this.instructionsToProfile = instructionsToProfile.split(","); - } - - @Override - protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PostAllocationOptimizationContext context) { - new Analyzer(target, lirGenRes.getCompilationUnitName(), lirGenRes.getLIR(), context.diagnosticLirGenTool).run(); - } - - private class Analyzer { - private final TargetDescription target; - private final LIR lir; - private final DiagnosticLIRGeneratorTool diagnosticLirGenTool; - private final LIRInsertionBuffer buffer; - private final String compilationUnitName; - - Analyzer(TargetDescription target, String compilationUnitName, LIR lir, DiagnosticLIRGeneratorTool diagnosticLirGenTool) { - this.target = target; - this.lir = lir; - this.compilationUnitName = compilationUnitName; - this.diagnosticLirGenTool = diagnosticLirGenTool; - this.buffer = new LIRInsertionBuffer(); - } - - public void run() { - for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { - doBlock(block); - } - } - - public void doBlock(BasicBlock block) { - ArrayList instructions = lir.getLIRforBlock(block); - assert instructions.size() >= 2 : "Malformed block: " + block + ", " + instructions; - assert instructions.get(instructions.size() - 1) instanceof BlockEndOp : "Not a BlockEndOp: " + instructions.get(instructions.size() - 1); - assert !(instructions.get(instructions.size() - 2) instanceof BlockEndOp) : "Is a BlockEndOp: " + instructions.get(instructions.size() - 2); - assert instructions.get(0) instanceof LabelOp : "Not a LabelOp: " + instructions.get(0); - assert !(instructions.get(1) instanceof LabelOp) : "Is a LabelOp: " + instructions.get(1); - String[] names = new String[instructionsToProfile.length]; - String[] groups = new String[instructionsToProfile.length]; - Value[] increments = new Value[instructionsToProfile.length]; - for (int i = 0; i < instructionsToProfile.length; i++) { - names[i] = compilationUnitName; - groups[i] = COUNTER_GROUP + " " + instructionsToProfile[i]; - // Default is zero; this value is patched to the real instruction count after - // assembly in method HotSpotInstructionProfiling.countInstructions - increments[i] = new ConstantValue(LIRKind.fromJavaKind(target.arch, JavaKind.Int), JavaConstant.INT_0); - } - HotSpotCounterOp op = (HotSpotCounterOp) diagnosticLirGenTool.createMultiBenchmarkCounter(names, groups, increments); - LIRInstruction inst = new InstructionCounterOp(op, instructionsToProfile); - assert inst != null; - buffer.init(instructions); - buffer.append(1, inst); - buffer.finish(); - } - } - - /** - * After assembly the {@link HotSpotBackend#profileInstructions(LIR, CompilationResultBuilder)} - * calls this method for patching the instruction counts into the counter increment code. - */ - public static void countInstructions(LIR lir, Assembler asm) { - InstructionCounterOp lastOp = null; - InstructionCounter counter = asm.getInstructionCounter(); - for (int blockId : lir.codeEmittingOrder()) { - if (LIR.isBlockDeleted(blockId)) { - continue; - } - BasicBlock block = lir.getBlockById(blockId); - for (LIRInstruction inst : lir.getLIRforBlock(block)) { - if (inst instanceof InstructionCounterOp) { - InstructionCounterOp currentOp = (InstructionCounterOp) inst; - - if (lastOp != null) { - int beginPc = lastOp.countOffsetEnd; - int endPc = currentOp.countOffsetBegin; - int[] instructionCounts = counter.countInstructions(lastOp.instructionsToProfile, beginPc, endPc); - lastOp.delegate.patchCounterIncrement(asm, instructionCounts); - } - lastOp = ((InstructionCounterOp) inst); - } - } - } - if (lastOp != null) { - assert lastOp.countOffsetBegin < asm.position(); - int beginPc = lastOp.countOffsetBegin; - int endPc = asm.position(); - int[] instructionCounts = counter.countInstructions(lastOp.instructionsToProfile, beginPc, endPc); - lastOp.delegate.patchCounterIncrement(asm, instructionCounts); - } - } - - public static class InstructionCounterOp extends LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(InstructionCounterOp.class); - private final HotSpotCounterOp delegate; - private final String[] instructionsToProfile; - private int countOffsetBegin; - private int countOffsetEnd; - - public InstructionCounterOp(HotSpotCounterOp delegate, String[] instructionsToProfile) { - super(TYPE); - this.delegate = delegate; - this.instructionsToProfile = instructionsToProfile; - } - - @Override - public void emitCode(CompilationResultBuilder crb) { - countOffsetBegin = crb.asm.position(); - this.delegate.emitCode(crb); - countOffsetEnd = crb.asm.position(); - } - - public String[] getInstructionsToProfile() { - return instructionsToProfile; - } - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotMarkId.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotMarkId.java index 657606abb13f..44d294bef513 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotMarkId.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotMarkId.java @@ -26,6 +26,7 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.common.NativeImageReinitialize; @@ -34,37 +35,36 @@ * code. */ public enum HotSpotMarkId implements CompilationResult.MarkId { - VERIFIED_ENTRY(false), - UNVERIFIED_ENTRY(false), - OSR_ENTRY(false), - EXCEPTION_HANDLER_ENTRY(false), - DEOPT_HANDLER_ENTRY(false), - DEOPT_MH_HANDLER_ENTRY(false), - FRAME_COMPLETE(true), - INVOKEINTERFACE(false), - INVOKEVIRTUAL(false), - INVOKESTATIC(false), - INVOKESPECIAL(false), - INLINE_INVOKE(false), - POLL_NEAR(false), - POLL_RETURN_NEAR(false), - POLL_FAR(false), - POLL_RETURN_FAR(false), - CARD_TABLE_ADDRESS(true), - NARROW_KLASS_BASE_ADDRESS(true), - NARROW_OOP_BASE_ADDRESS(true), - CRC_TABLE_ADDRESS(true), - LOG_OF_HEAP_REGION_GRAIN_BYTES(true), - VERIFY_OOPS(true), - VERIFY_OOP_BITS(true), - VERIFY_OOP_MASK(true), - VERIFY_OOP_COUNT_ADDRESS(true); + VERIFIED_ENTRY, + UNVERIFIED_ENTRY, + OSR_ENTRY, + EXCEPTION_HANDLER_ENTRY, + DEOPT_HANDLER_ENTRY, + DEOPT_MH_HANDLER_ENTRY, + FRAME_COMPLETE, + ENTRY_BARRIER_PATCH, + INVOKEINTERFACE, + INVOKEVIRTUAL, + INVOKESTATIC, + INVOKESPECIAL, + INLINE_INVOKE, + POLL_NEAR, + POLL_RETURN_NEAR, + POLL_FAR, + POLL_RETURN_FAR, + CARD_TABLE_ADDRESS, + NARROW_KLASS_BASE_ADDRESS, + NARROW_OOP_BASE_ADDRESS, + CRC_TABLE_ADDRESS, + LOG_OF_HEAP_REGION_GRAIN_BYTES, + VERIFY_OOPS, + VERIFY_OOP_BITS, + VERIFY_OOP_MASK, + VERIFY_OOP_COUNT_ADDRESS(); - private final boolean isMarkAfter; @NativeImageReinitialize private Integer value; - HotSpotMarkId(boolean isMarkAfter) { - this.isMarkAfter = isMarkAfter; + HotSpotMarkId() { this.value = null; } @@ -83,15 +83,10 @@ public String getName() { @Override public Object getId() { - assert isAvailable() : this; + GraalError.guarantee(isAvailable(), "mark is not available %s", this); return value; } - @Override - public boolean isMarkAfter() { - return isMarkAfter; - } - public boolean isAvailable() { return value != null; } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotZBarrierSet.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotZBarrierSet.java new file mode 100644 index 000000000000..f5c47db49eca --- /dev/null +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotZBarrierSet.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot; + +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_OOP_HANDLE_LOCATION; + +import org.graalvm.compiler.core.common.memory.BarrierType; +import org.graalvm.compiler.core.common.type.AbstractObjectStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.gc.ZBarrierSet; +import org.graalvm.word.LocationIdentity; + +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaField; + +/** + * Specialization of {@link ZBarrierSet} that adds support for read barriers on handle locations. + */ +public class HotSpotZBarrierSet extends ZBarrierSet { + public HotSpotZBarrierSet(ResolvedJavaField referentField) { + super(referentField); + } + + @Override + protected BarrierType barrierForLocation(BarrierType currentBarrier, LocationIdentity location, JavaKind storageKind) { + if (location.equals(HOTSPOT_OOP_HANDLE_LOCATION) || location.equals(HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION)) { + return BarrierType.READ; + } + return super.barrierForLocation(currentBarrier, location, storageKind); + } + + @Override + public BarrierType readBarrierType(LocationIdentity location, ValueNode address, Stamp loadStamp) { + if (location.equals(HOTSPOT_OOP_HANDLE_LOCATION) || location.equals(HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION)) { + assert loadStamp instanceof AbstractObjectStamp : loadStamp; + return BarrierType.READ; + } + return super.readBarrierType(location, address, loadStamp); + } +} diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java index 1528de98a0f2..73b196d8fdb8 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java @@ -50,6 +50,7 @@ import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallSignature; @@ -169,7 +170,6 @@ import org.graalvm.compiler.nodes.java.RegisterFinalizerNode; import org.graalvm.compiler.nodes.java.ValidateNewInstanceClassNode; import org.graalvm.compiler.nodes.memory.FloatingReadNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; @@ -658,12 +658,14 @@ private void lowerHubGetClassNode(HubGetClassNode n, LoweringTool tool) { StructuredGraph graph = n.graph(); assert !hub.isConstant(); AddressNode mirrorAddress = createOffsetAddress(graph, hub, vmConfig.classMirrorOffset); + Stamp loadStamp = n.stamp(NodeView.DEFAULT); FloatingReadNode read = graph.unique( new FloatingReadNode(mirrorAddress, CLASS_MIRROR_LOCATION, null, StampFactory.forKind(target.wordJavaKind), null, BarrierType.NONE)); // Read the Object from the OopHandle AddressNode address = createOffsetAddress(graph, read, 0); - read = graph.unique(new FloatingReadNode(address, HOTSPOT_OOP_HANDLE_LOCATION, null, n.stamp(NodeView.DEFAULT), null, BarrierType.NONE)); + read = graph.unique(new FloatingReadNode(address, HOTSPOT_OOP_HANDLE_LOCATION, null, loadStamp, null, + barrierSet.readBarrierType(HOTSPOT_OOP_HANDLE_LOCATION, address, loadStamp))); n.replaceAtUsagesAndDelete(read); } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotExceptionDispatchPlugin.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotExceptionDispatchPlugin.java index 3ec917fd24cd..77f6aa4f7d27 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotExceptionDispatchPlugin.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotExceptionDispatchPlugin.java @@ -31,6 +31,7 @@ import java.util.function.Supplier; import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -46,7 +47,6 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.IntegerEqualsNode; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java index d7424932b8f2..803345a133a0 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java @@ -27,6 +27,7 @@ import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCallee; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_ALL_CALLER_SAVE_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.KILLS_NO_REGISTERS; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Reexecutability.NOT_REEXECUTABLE; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Reexecutability.REEXECUTABLE; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition.LEAF_NO_VZERO; @@ -214,6 +215,22 @@ public void linkForeignCall(OptionValues options, register(targetLinkage); } + public void linkStackOnlyForeignCall(OptionValues options, + HotSpotProviders providers, + HotSpotForeignCallDescriptor descriptor, + long address, + boolean prependThread) { + if (address == 0) { + throw new IllegalArgumentException("Can't link foreign call with zero address"); + } + ForeignCallStub stub = new ForeignCallStub(options, jvmciRuntime, providers, address, descriptor, prependThread, KILLS_NO_REGISTERS); + HotSpotForeignCallLinkage linkage = stub.getLinkage(); + HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); + linkage.setCompiledStub(stub); + register(linkage); + register(targetLinkage); + } + public void invokeJavaMethodStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallDescriptor descriptor, diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index fc7ef32bc170..5cad4012c8e6 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -48,6 +48,7 @@ import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.StampFactory; @@ -97,6 +98,7 @@ import org.graalvm.compiler.nodes.extended.JavaReadNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.ObjectIsArrayNode; +import org.graalvm.compiler.nodes.gc.BarrierSet; import org.graalvm.compiler.nodes.graphbuilderconf.ForeignCallPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginFactory; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; @@ -110,7 +112,6 @@ import org.graalvm.compiler.nodes.java.DynamicNewArrayNode; import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode; import org.graalvm.compiler.nodes.java.NewArrayNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.Replacements; @@ -179,7 +180,8 @@ public static Plugins create(HotSpotGraalRuntimeProvider graalRuntime, HotSpotHostForeignCallsProvider foreignCalls, ReplacementsImpl replacements, OptionValues options, - TargetDescription target) { + TargetDescription target, + BarrierSet barrierSet) { InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(graalRuntime, config, compilerConfiguration, target, options); Plugins plugins = new Plugins(invocationPlugins); @@ -187,7 +189,7 @@ public static Plugins create(HotSpotGraalRuntimeProvider graalRuntime, StandardGraphBuilderPlugins.registerConstantFieldLoadPlugin(plugins); if (!IS_IN_NATIVE_IMAGE) { // In libgraal all word related operations have been fully processed so this is unneeded - HotSpotWordOperationPlugin wordOperationPlugin = new HotSpotWordOperationPlugin(snippetReflection, wordTypes); + HotSpotWordOperationPlugin wordOperationPlugin = new HotSpotWordOperationPlugin(snippetReflection, wordTypes, barrierSet); HotSpotNodePlugin nodePlugin = new HotSpotNodePlugin(wordOperationPlugin); plugins.appendTypePlugin(nodePlugin); @@ -955,7 +957,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec ValueNode offset = b.add(ConstantNode.forLong(HotSpotReplacementsUtil.referentOffset(b.getMetaAccess()))); AddressNode address = b.add(new OffsetAddressNode(receiver.get(), offset)); FieldLocationIdentity locationIdentity = new FieldLocationIdentity(HotSpotReplacementsUtil.referentField(b.getMetaAccess())); - JavaReadNode read = b.add(new JavaReadNode(StampFactory.object(), JavaKind.Object, address, locationIdentity, BarrierType.WEAK_FIELD, MemoryOrderMode.PLAIN, true)); + JavaReadNode read = b.add(new JavaReadNode(StampFactory.object(), JavaKind.Object, address, locationIdentity, BarrierType.WEAK_REFERS_TO, MemoryOrderMode.PLAIN, true)); LogicNode objectEquals = b.add(ObjectEqualsNode.create(b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), read, o, NodeView.DEFAULT)); b.addPush(JavaKind.Boolean, ConditionalNode.create(objectEquals, b.add(forBoolean(true)), b.add(forBoolean(false)), NodeView.DEFAULT)); return true; @@ -973,7 +975,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec ValueNode offset = b.add(ConstantNode.forLong(HotSpotReplacementsUtil.referentOffset(b.getMetaAccess()))); AddressNode address = b.add(new OffsetAddressNode(receiver.get(), offset)); FieldLocationIdentity locationIdentity = new FieldLocationIdentity(HotSpotReplacementsUtil.referentField(b.getMetaAccess())); - JavaReadNode read = b.add(new JavaReadNode(StampFactory.object(), JavaKind.Object, address, locationIdentity, BarrierType.PHANTOM_FIELD, MemoryOrderMode.PLAIN, true)); + JavaReadNode read = b.add(new JavaReadNode(StampFactory.object(), JavaKind.Object, address, locationIdentity, BarrierType.PHANTOM_REFERS_TO, MemoryOrderMode.PLAIN, true)); LogicNode objectEquals = b.add(ObjectEqualsNode.create(b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), read, o, NodeView.DEFAULT)); b.addPush(JavaKind.Boolean, ConditionalNode.create(objectEquals, b.add(forBoolean(true)), b.add(forBoolean(false)), NodeView.DEFAULT)); return true; diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index e696200c1545..ecd4a5094d60 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot.meta; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; +import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_DREM; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_FREM; @@ -66,6 +67,7 @@ import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNPACK; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.ENABLE_STACK_RESERVED_ZONE; +import static org.graalvm.compiler.hotspot.HotSpotHostBackend.POLLING_PAGE_RETURN_HANDLER; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.THROW_DELAYED_STACKOVERFLOW_ERROR; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Reexecutability.NOT_REEXECUTABLE; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Reexecutability.REEXECUTABLE; @@ -171,6 +173,25 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall public static final HotSpotForeignCallDescriptor INVOKE_STATIC_METHOD_ONE_ARG = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, NO_LOCATIONS, "JVMCIRuntime::invoke_static_method_one_arg", long.class, Word.class, Word.class, long.class); + public static final HotSpotForeignCallDescriptor NMETHOD_ENTRY_BARRIER = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, NO_LOCATIONS, "nmethod_entry_barrier", void.class); + + /* + * Functions from ZBarrierSetRuntime. The weak_ prefix refers to AS_NO_KEEPALIVE while the extra + * word before oop_field part refers to java.lang.Reference subclass and corresponds to + * ON_WEAK_OOP_REF/ON_PHANTOM_OOP_REF in HotSpot decorator terminology. + */ + public static final HotSpotForeignCallDescriptor Z_FIELD_BARRIER = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, NO_LOCATIONS, "load_barrier_on_oop_field_preloaded", + long.class, long.class, long.class); + public static final HotSpotForeignCallDescriptor Z_REFERENCE_GET_BARRIER = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, NO_LOCATIONS, + "load_barrier_on_weak_oop_field_preloaded", + long.class, long.class, long.class); + public static final HotSpotForeignCallDescriptor Z_WEAK_REFERS_TO_BARRIER = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, NO_LOCATIONS, + "weak_load_barrier_on_weak_oop_field_preloaded", long.class, long.class, long.class); + public static final HotSpotForeignCallDescriptor Z_PHANTOM_REFERS_TO_BARRIER = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, NO_LOCATIONS, + "weak_load_barrier_on_phantom_oop_field_preloaded", long.class, long.class, long.class); + public static final HotSpotForeignCallDescriptor Z_ARRAY_BARRIER = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, NO_LOCATIONS, "load_barrier_on_oop_array", + void.class, long.class, long.class); + /** * Signature of an unsafe {@link System#arraycopy} stub. * @@ -409,6 +430,9 @@ public void initialize(HotSpotProviders providers, OptionValues options) { if (c.deoptBlobUnpackWithExceptionInTLS != 0) { registerForeignCall(DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS, c.deoptBlobUnpackWithExceptionInTLS, NativeCall); } + if (c.pollingPageReturnHandler != 0) { + registerForeignCall(POLLING_PAGE_RETURN_HANDLER, c.pollingPageReturnHandler, NativeCall); + } registerForeignCall(DEOPT_BLOB_UNCOMMON_TRAP, c.deoptBlobUncommonTrap, NativeCall); registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall); @@ -484,6 +508,29 @@ public void initialize(HotSpotProviders providers, OptionValues options) { linkForeignCall(options, providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD); linkForeignCall(options, providers, NOTIFY, c.notifyAddress, PREPEND_THREAD); linkForeignCall(options, providers, NOTIFY_ALL, c.notifyAllAddress, PREPEND_THREAD); + + if (c.nmethodEntryBarrier != 0) { + registerForeignCall(NMETHOD_ENTRY_BARRIER, c.nmethodEntryBarrier, NativeCall); + } else if (IS_BUILDING_NATIVE_IMAGE) { + // Ensure this is known to libgraal + register(NMETHOD_ENTRY_BARRIER.getSignature()); + } + + if (c.zBarrierSetRuntimeLoadBarrierOnOopFieldPreloaded != 0) { + linkStackOnlyForeignCall(options, providers, Z_FIELD_BARRIER, c.zBarrierSetRuntimeLoadBarrierOnOopFieldPreloaded, DONT_PREPEND_THREAD); + linkStackOnlyForeignCall(options, providers, Z_REFERENCE_GET_BARRIER, c.zBarrierSetRuntimeLoadBarrierOnWeakOopFieldPreloaded, DONT_PREPEND_THREAD); + linkStackOnlyForeignCall(options, providers, Z_WEAK_REFERS_TO_BARRIER, c.zBarrierSetRuntimeWeakLoadBarrierOnWeakOopFieldPreloaded, DONT_PREPEND_THREAD); + linkStackOnlyForeignCall(options, providers, Z_PHANTOM_REFERS_TO_BARRIER, c.zBarrierSetRuntimeWeakLoadBarrierOnPhantomOopFieldPreloaded, DONT_PREPEND_THREAD); + linkStackOnlyForeignCall(options, providers, Z_ARRAY_BARRIER, c.zBarrierSetRuntimeLoadBarrierOnOopArray, DONT_PREPEND_THREAD); + } else if (IS_BUILDING_NATIVE_IMAGE) { + // Ensure these are known to libgraal + register(Z_FIELD_BARRIER.getSignature()); + register(Z_REFERENCE_GET_BARRIER.getSignature()); + register(Z_WEAK_REFERS_TO_BARRIER.getSignature()); + register(Z_PHANTOM_REFERS_TO_BARRIER.getSignature()); + register(Z_ARRAY_BARRIER.getSignature()); + } + linkForeignCall(options, providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD); linkForeignCall(options, providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD); linkForeignCall(options, providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotPlatformConfigurationProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotPlatformConfigurationProvider.java index 38a3471f5905..1edab4cf62e9 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotPlatformConfigurationProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotPlatformConfigurationProvider.java @@ -24,31 +24,17 @@ */ package org.graalvm.compiler.hotspot.meta; -import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.ArrayRangeWrite; import org.graalvm.compiler.nodes.gc.BarrierSet; -import org.graalvm.compiler.nodes.gc.CardTableBarrierSet; -import org.graalvm.compiler.nodes.gc.G1BarrierSet; -import org.graalvm.compiler.nodes.java.AbstractNewObjectNode; -import org.graalvm.compiler.nodes.memory.FixedAccessNode; import org.graalvm.compiler.nodes.spi.PlatformConfigurationProvider; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaType; - public class HotSpotPlatformConfigurationProvider implements PlatformConfigurationProvider { private final BarrierSet barrierSet; private final boolean canVirtualizeLargeByteArrayAccess; - public HotSpotPlatformConfigurationProvider(GraalHotSpotVMConfig config, MetaAccessProvider metaAccess) { - this.barrierSet = createBarrierSet(config, metaAccess); + public HotSpotPlatformConfigurationProvider(GraalHotSpotVMConfig config, BarrierSet barrierSet) { + this.barrierSet = barrierSet; this.canVirtualizeLargeByteArrayAccess = config.deoptimizationSupportLargeAccessByteArrayVirtualization; } @@ -61,78 +47,4 @@ public boolean canVirtualizeLargeByteArrayAccess() { public BarrierSet getBarrierSet() { return barrierSet; } - - private BarrierSet createBarrierSet(GraalHotSpotVMConfig config, MetaAccessProvider metaAccess) { - boolean useDeferredInitBarriers = config.useDeferredInitBarriers; - ResolvedJavaType objectArrayType = metaAccess.lookupJavaType(Object[].class); - if (config.useG1GC) { - ResolvedJavaField referentField = HotSpotReplacementsUtil.referentField(metaAccess); - return new G1BarrierSet(objectArrayType, referentField) { - @Override - protected boolean writeRequiresPostBarrier(FixedAccessNode node, ValueNode writtenValue) { - if (!super.writeRequiresPostBarrier(node, writtenValue)) { - return false; - } - return !useDeferredInitBarriers || !isWriteToNewObject(node); - } - - @Override - protected boolean arrayRangeWriteRequiresPostBarrier(ArrayRangeWrite write) { - if (!super.arrayRangeWriteRequiresPostBarrier(write)) { - return false; - } - return !useDeferredInitBarriers || !isWriteToNewObject(write.asFixedWithNextNode(), write.getAddress().getBase()); - } - }; - } else { - return new CardTableBarrierSet(objectArrayType) { - @Override - protected boolean writeRequiresBarrier(FixedAccessNode node, ValueNode writtenValue) { - if (!super.writeRequiresBarrier(node, writtenValue)) { - return false; - } - return !useDeferredInitBarriers || !isWriteToNewObject(node); - } - - @Override - protected boolean arrayRangeWriteRequiresBarrier(ArrayRangeWrite write) { - if (!super.arrayRangeWriteRequiresBarrier(write)) { - return false; - } - return !useDeferredInitBarriers || !isWriteToNewObject(write.asFixedWithNextNode(), write.getAddress().getBase()); - } - }; - } - } - - /** - * For initializing writes, the last allocation executed by the JVM is guaranteed to be - * automatically card marked so it's safe to skip the card mark in the emitted code. - */ - protected boolean isWriteToNewObject(FixedAccessNode node) { - if (!node.getLocationIdentity().isInit()) { - return false; - } - // This is only allowed for the last allocation in sequence - return isWriteToNewObject(node, node.getAddress().getBase()); - } - - protected boolean isWriteToNewObject(FixedWithNextNode node, ValueNode base) { - if (base instanceof AbstractNewObjectNode) { - Node pred = node.predecessor(); - while (pred != null) { - if (pred == base) { - node.getDebug().log(DebugContext.INFO_LEVEL, "Deferred barrier for %s with base %s", node, base); - return true; - } - if (pred instanceof AbstractNewObjectNode) { - node.getDebug().log(DebugContext.INFO_LEVEL, "Disallowed deferred barrier for %s because %s was last allocation instead of %s", node, pred, base); - return false; - } - pred = pred.predecessor(); - } - } - node.getDebug().log(DebugContext.INFO_LEVEL, "Unable to find allocation for deferred barrier for %s with base %s", node, base); - return false; - } } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java index e6a5785d655c..ffd73db74022 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java @@ -29,9 +29,8 @@ import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotBackend; +import org.graalvm.compiler.hotspot.HotSpotGraalRuntime; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.HotSpotInstructionProfiling; import org.graalvm.compiler.hotspot.lir.HotSpotZapRegistersPhase; import org.graalvm.compiler.hotspot.lir.VerifyMaxRegisterSizePhase; import org.graalvm.compiler.java.GraphBuilderPhase; @@ -48,9 +47,12 @@ import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.AddressLoweringPhase; +import org.graalvm.compiler.phases.common.BarrierSetVerificationPhase; import org.graalvm.compiler.phases.common.UseTrappingNullChecksPhase; +import org.graalvm.compiler.phases.common.WriteBarrierAdditionPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.LowTierContext; +import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.SuitesCreator; @@ -82,6 +84,19 @@ public Suites createSuites(OptionValues options, Architecture arch) { position.previous(); position.add(new UseTrappingNullChecksPhase()); } + + if (config.gc == HotSpotGraalRuntime.HotSpotGC.Z) { + ListIterator> mid = suites.getMidTier().findPhase(WriteBarrierAdditionPhase.class); + // No write barriers required + mid.remove(); + + if (Assertions.assertionsEnabled()) { + // Perform some verification that the barrier type on all reads are properly set + ListIterator> position = suites.getLowTier().findPhase(AddressLoweringPhase.class); + position.previous(); + position.add(new BarrierSetVerificationPhase()); + } + } return suites; } @@ -144,13 +159,10 @@ public LIRSuites createLIRSuites(OptionValues options) { if (Assertions.detailedAssertionsEnabled(options)) { suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotZapRegistersPhase()); } - String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(options); - if (profileInstructions != null) { - suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotInstructionProfiling(profileInstructions)); - } if (Assertions.assertionsEnabled()) { suites.getFinalCodeAnalysisStage().appendPhase(new VerifyMaxRegisterSizePhase(config.maxVectorSize)); } return suites; } + } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java index b8dc59cb21ce..4b87667affaa 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BridgeMethodUtils; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -49,9 +50,9 @@ import org.graalvm.compiler.nodes.calc.IsNullNode; import org.graalvm.compiler.nodes.calc.PointerEqualsNode; import org.graalvm.compiler.nodes.extended.GuardingNode; +import org.graalvm.compiler.nodes.gc.BarrierSet; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.java.LoadIndexedNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.type.StampTool; @@ -68,8 +69,8 @@ * operations}. */ public class HotSpotWordOperationPlugin extends WordOperationPlugin { - HotSpotWordOperationPlugin(SnippetReflectionProvider snippetReflection, WordTypes wordTypes) { - super(snippetReflection, wordTypes); + HotSpotWordOperationPlugin(SnippetReflectionProvider snippetReflection, WordTypes wordTypes, BarrierSet barrierSet) { + super(snippetReflection, wordTypes, barrierSet); } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotLoadReservedReferenceNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotLoadReservedReferenceNode.java index f1706cf16a3b..0b6135e54c39 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotLoadReservedReferenceNode.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotLoadReservedReferenceNode.java @@ -24,6 +24,7 @@ */ package org.graalvm.compiler.hotspot.nodes; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; @@ -37,7 +38,6 @@ import org.graalvm.compiler.nodes.extended.JavaReadNode; import org.graalvm.compiler.nodes.memory.FloatableThreadLocalAccess; import org.graalvm.compiler.nodes.memory.MemoryAccess; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.Lowerable; diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotStoreReservedReferenceNode.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotStoreReservedReferenceNode.java index 88d0a15d78d7..ab103487717c 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotStoreReservedReferenceNode.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotStoreReservedReferenceNode.java @@ -26,6 +26,7 @@ import static org.graalvm.compiler.hotspot.nodes.HotSpotLoadReservedReferenceNode.JVMCI_RESERVED_REFERENCE; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeCycles; @@ -36,7 +37,6 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.JavaWriteNode; import org.graalvm.compiler.nodes.memory.SingleMemoryKill; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.Lowerable; diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotInvocationPluginHelper.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotInvocationPluginHelper.java index af01d3cd3350..6900a86b51e6 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotInvocationPluginHelper.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotInvocationPluginHelper.java @@ -50,8 +50,8 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.IsNullNode; import org.graalvm.compiler.nodes.extended.GuardingNode; +import org.graalvm.compiler.nodes.gc.BarrierSet; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; @@ -70,10 +70,12 @@ public class HotSpotInvocationPluginHelper extends InvocationPluginHelper { private final GraalHotSpotVMConfig config; + private final BarrierSet barrierSet; public HotSpotInvocationPluginHelper(GraphBuilderContext b, ResolvedJavaMethod targetMethod, GraalHotSpotVMConfig config) { super(b, targetMethod); this.config = config; + this.barrierSet = b.getPlatformConfigurationProvider().getBarrierSet(); } private Stamp getClassStamp(boolean nonNull) { @@ -97,7 +99,7 @@ private ValueNode readLocation(ValueNode base, HotSpotVMConfigField field, Stamp private ValueNode readLocation(ValueNode base, int offset, LocationIdentity location, Stamp stamp, GuardingNode guard) { assert StampTool.isPointerNonNull(base) || base.stamp(NodeView.DEFAULT).getStackKind() == getWordKind() : "must be null guarded"; AddressNode address = makeOffsetAddress(base, asWord(offset)); - ReadNode value = b.add(new ReadNode(address, location, stamp, BarrierType.NONE, MemoryOrderMode.PLAIN)); + ReadNode value = b.add(new ReadNode(address, location, stamp, barrierSet.readBarrierType(location, address, stamp), MemoryOrderMode.PLAIN)); ValueNode returnValue = ReadNode.canonicalizeRead(value, value.getAddress(), value.getLocationIdentity(), b, NodeView.DEFAULT); if (value != returnValue) { // We could clean up the dead nodes here @@ -216,7 +218,8 @@ public ValueNode readCurrentThreadObject(CurrentJavaThreadNode thread) { // Read the Object from the OopHandle ValueNode handleOffset = ConstantNode.forIntegerKind(getWordKind(), 0, b.getGraph()); AddressNode handleAddress = b.add(new OffsetAddressNode(value, handleOffset)); - value = b.add(new ReadNode(handleAddress, HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION, threadStamp, BarrierType.NONE, MemoryOrderMode.PLAIN)); + value = b.add(new ReadNode(handleAddress, HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION, threadStamp, + barrierSet.readBarrierType(HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION, handleAddress, threadStamp), MemoryOrderMode.PLAIN)); return value; } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index 0ad0db5e2825..b5dba37966c0 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -178,7 +178,7 @@ public static boolean useTLAB(@InjectedParameter GraalHotSpotVMConfig config) { @Fold public static boolean useG1GC(@InjectedParameter GraalHotSpotVMConfig config) { - return config.useG1GC; + return config.useG1GC(); } /** diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/AbstractForeignCallStub.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/AbstractForeignCallStub.java index 27b01daedf50..07f87c1ac58c 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/AbstractForeignCallStub.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/AbstractForeignCallStub.java @@ -28,8 +28,10 @@ import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCallee; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.COMPUTES_REGISTERS_KILLED; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_ALL_CALLER_SAVE_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.KILLS_NO_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl.StackOnlyCallingConvention.StackOnlyCall; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl.StackOnlyCallingConvention.StackOnlyCallee; import static org.graalvm.compiler.nodes.ConstantNode.forBoolean; import org.graalvm.compiler.core.common.CompilationIdentifier; @@ -103,6 +105,7 @@ public AbstractForeignCallStub(OptionValues options, HotSpotProviders providers, long address, HotSpotForeignCallDescriptor descriptor, + HotSpotForeignCallLinkage.RegisterEffect effect, boolean prependThread) { super(options, providers, HotSpotForeignCallLinkageImpl.create(providers.getMetaAccess(), providers.getCodeCache(), @@ -110,9 +113,9 @@ public AbstractForeignCallStub(OptionValues options, providers.getForeignCalls(), descriptor, 0L, - COMPUTES_REGISTERS_KILLED, - JavaCall, - JavaCallee)); + effect, + effect == KILLS_NO_REGISTERS ? StackOnlyCall : JavaCall, + effect == KILLS_NO_REGISTERS ? StackOnlyCallee : JavaCallee)); this.jvmciRuntime = runtime; this.prependThread = prependThread; MetaAccessProvider metaAccess = providers.getMetaAccess(); @@ -245,7 +248,9 @@ protected final StructuredGraph getGraph(DebugContext debug, CompilationIdentifi graph.getGraphState().forceDisableFrameStateVerification(); ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false)); ValueNode result = createTargetCall(kit, thread); - kit.createIntrinsicInvoke(handlePendingException, thread, forBoolean(shouldClearException, graph), forBoolean(isObjectResult, graph)); + if (linkage.getDescriptor().getTransition() == Transition.SAFEPOINT) { + kit.createIntrinsicInvoke(handlePendingException, thread, forBoolean(shouldClearException, graph), forBoolean(isObjectResult, graph)); + } if (isObjectResult) { InvokeNode object = kit.createIntrinsicInvoke(getAndClearObjectResult, thread); result = kit.createIntrinsicInvoke(verifyObject, object); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java index 5f8fe3f98c39..5457cc3f48b9 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -62,7 +63,12 @@ public class ForeignCallStub extends AbstractForeignCallStub { * to the arguments for the call to {@code address} */ public ForeignCallStub(OptionValues options, HotSpotJVMCIRuntime runtime, HotSpotProviders providers, long address, HotSpotForeignCallDescriptor descriptor, boolean prependThread) { - super(options, runtime, providers, address, descriptor, prependThread); + super(options, runtime, providers, address, descriptor, HotSpotForeignCallLinkage.RegisterEffect.COMPUTES_REGISTERS_KILLED, prependThread); + } + + public ForeignCallStub(OptionValues options, HotSpotJVMCIRuntime runtime, HotSpotProviders providers, long address, HotSpotForeignCallDescriptor descriptor, boolean prependThread, + HotSpotForeignCallLinkage.RegisterEffect effect) { + super(options, runtime, providers, address, descriptor, effect, prependThread); } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/InvokeJavaMethodStub.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/InvokeJavaMethodStub.java index d553fc9529ef..37f35fcf1d80 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/InvokeJavaMethodStub.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/InvokeJavaMethodStub.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; @@ -74,7 +75,7 @@ public InvokeJavaMethodStub(OptionValues options, long address, HotSpotForeignCallDescriptor descriptor, ResolvedJavaMethod staticMethod) { - super(options, runtime, providers, address, descriptor, true); + super(options, runtime, providers, address, descriptor, HotSpotForeignCallLinkage.RegisterEffect.COMPUTES_REGISTERS_KILLED, true); this.javaMethod = staticMethod; // This stub is compiled to kill no registers which interferes with returning float and // double through a long. For simplicity disallow that case until it's required. diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java index cf5ddf108592..bf9721bc2462 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java @@ -128,7 +128,7 @@ public EconomicSet getDestroyedCallerRegisters() { } public boolean shouldSaveRegistersAroundCalls() { - return linkage.getEffect() == HotSpotForeignCallLinkage.RegisterEffect.COMPUTES_REGISTERS_KILLED; + return linkage.getEffect() != HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_ALL_CALLER_SAVE_REGISTERS; } protected final OptionValues options; @@ -241,7 +241,7 @@ private CompilationResult buildCompilationResult(DebugContext debug, final Backe Suites suites = createSuites(); emitFrontEnd(providers, backend, graph, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, DefaultProfilingInfo.get(TriState.UNKNOWN), suites); LIRSuites lirSuites = createLIRSuites(); - backend.emitBackEnd(graph, Stub.this, getInstalledCodeOwner(), compResult, CompilationResultBuilderFactory.Default, getRegisterConfig(), lirSuites); + backend.emitBackEnd(graph, Stub.this, getInstalledCodeOwner(), compResult, CompilationResultBuilderFactory.Default, null, getRegisterConfig(), lirSuites); assert checkStubInvariants(compResult); } catch (Throwable e) { throw debug.handle(e); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java index 8cf807103525..c62be005f0ff 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java @@ -27,7 +27,7 @@ import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.FROM_POINTER; import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.IS_NULL; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.Word.Opcode; import org.graalvm.compiler.word.Word.Operation; diff --git a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index 7019ef993db6..105cd6bf3333 100644 --- a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -2209,7 +2209,7 @@ public void replacePluginWithException(GeneratedInvocationPlugin plugin, Resolve protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) { InvocationPlugins plugins = graphBuilderConfig.getPlugins().getInvocationPlugins(); - InvocationPlugin plugin = plugins.lookupInvocation(targetMethod, true, options); + InvocationPlugin plugin = plugins.lookupInvocation(targetMethod, true, !parsingIntrinsic(), options); if (plugin != null) { if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) { diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AtomicMove.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AtomicMove.java index 5de163344693..4fc5f8e5a7a8 100644 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AtomicMove.java +++ b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AtomicMove.java @@ -86,16 +86,17 @@ public static class CompareAndSwapOp extends AArch64LIRInstruction { private final AArch64Kind accessKind; private final MemoryOrderMode memoryOrder; - private final boolean setConditionFlags; + protected final boolean setConditionFlags; @Def({REG}) protected AllocatableValue resultValue; @Alive({REG}) protected Value expectedValue; @Alive({REG}) protected AllocatableValue newValue; @Alive({REG}) protected AllocatableValue addressValue; - public CompareAndSwapOp(AArch64Kind accessKind, MemoryOrderMode memoryOrder, boolean setConditionFlags, AllocatableValue result, Value expectedValue, AllocatableValue newValue, + protected CompareAndSwapOp(LIRInstructionClass c, + AArch64Kind accessKind, MemoryOrderMode memoryOrder, boolean setConditionFlags, AllocatableValue result, Value expectedValue, AllocatableValue newValue, AllocatableValue addressValue) { - super(TYPE); + super(c); this.accessKind = accessKind; this.memoryOrder = memoryOrder; this.setConditionFlags = setConditionFlags; @@ -105,6 +106,11 @@ public CompareAndSwapOp(AArch64Kind accessKind, MemoryOrderMode memoryOrder, boo this.addressValue = addressValue; } + public CompareAndSwapOp(AArch64Kind accessKind, MemoryOrderMode memoryOrder, boolean setConditionFlags, AllocatableValue result, Value expectedValue, AllocatableValue newValue, + AllocatableValue addressValue) { + this(TYPE, accessKind, memoryOrder, setConditionFlags, result, expectedValue, newValue, addressValue); + } + /** * Both cas and ld(a)xr produce a zero-extended value. Since comparisons must be at minimum * 32-bits, the expected value must also be zero-extended to produce an accurate comparison. @@ -358,7 +364,7 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { * */ @Opcode("ATOMIC_READ_AND_WRITE") - public static final class AtomicReadAndWriteOp extends AArch64LIRInstruction { + public static class AtomicReadAndWriteOp extends AArch64LIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AtomicReadAndWriteOp.class); private final AArch64Kind accessKind; @@ -367,8 +373,8 @@ public static final class AtomicReadAndWriteOp extends AArch64LIRInstruction { @Alive({REG}) protected AllocatableValue addressValue; @Alive({REG}) protected AllocatableValue newValue; - public AtomicReadAndWriteOp(AArch64Kind kind, AllocatableValue result, AllocatableValue address, AllocatableValue newValue) { - super(TYPE); + protected AtomicReadAndWriteOp(LIRInstructionClass c, AArch64Kind kind, AllocatableValue result, AllocatableValue address, AllocatableValue newValue) { + super(c); assert kind.isInteger(); this.accessKind = kind; this.resultValue = result; @@ -376,6 +382,10 @@ public AtomicReadAndWriteOp(AArch64Kind kind, AllocatableValue result, Allocatab this.newValue = newValue; } + public AtomicReadAndWriteOp(AArch64Kind kind, AllocatableValue result, AllocatableValue address, AllocatableValue newValue) { + this(TYPE, kind, result, address, newValue); + } + @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { final int memAccessSize = accessKind.getSizeInBytes() * Byte.SIZE; diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java deleted file mode 100644 index 4875d0775f6f..000000000000 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java +++ /dev/null @@ -1,69 +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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.lir.aarch64; - -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; - -import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.ValueUtil; -import jdk.vm.ci.meta.Value; - -public final class AArch64CCall extends AArch64LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64CCall.class); - - @Def({REG, ILLEGAL}) protected Value result; - @Use({REG, STACK}) protected Value[] parameters; - @Use({REG}) protected Value functionPtr; - - public AArch64CCall(Value result, Value functionPtr, Value[] parameters) { - super(TYPE); - this.result = result; - this.functionPtr = functionPtr; - this.parameters = parameters; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - directCall(masm); - } - - private void directCall(AArch64MacroAssembler masm) { - Register reg = ValueUtil.asRegister(functionPtr); - masm.blr(reg); - masm.ensureUniquePC(); - } - - @Override - public boolean destroysCallerSavedRegisters() { - return true; - } - -} diff --git a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java index d69e6b33387b..fd7dbb39d4ef 100644 --- a/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java +++ b/compiler/src/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java @@ -394,7 +394,7 @@ protected int emitMemAccess(CompilationResultBuilder crb, AArch64MacroAssembler try (ScratchRegister scratch1 = masm.getScratchRegister()) { AArch64Address address = addressValue.toAddress(); final Register addrReg; - if (address.getAddressingMode() == AArch64Address.AddressingMode.BASE_REGISTER_ONLY) { + if (address.isBaseRegisterOnly()) { // Can directly use the base register as the address addrReg = address.getBase(); } else { @@ -500,7 +500,7 @@ protected int emitMemAccess(CompilationResultBuilder crb, AArch64MacroAssembler try (ScratchRegister scratch1 = masm.getScratchRegister()) { AArch64Address address = addressValue.toAddress(); final Register addrReg; - if (address.getAddressingMode() == AArch64Address.AddressingMode.BASE_REGISTER_ONLY) { + if (address.isBaseRegisterOnly()) { // Can directly use the base register as the address addrReg = address.getBase(); } else { diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java index 5ab087f0e8b8..073c47bdad33 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java @@ -43,7 +43,6 @@ import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; -import org.graalvm.compiler.core.common.Stride; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp; import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize; @@ -51,6 +50,7 @@ import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.core.common.Stride; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.common.type.DataPointerConstant; import org.graalvm.compiler.debug.GraalError; @@ -539,7 +539,7 @@ public static void move(CompilationResultBuilder crb, AMD64MacroAssembler masm, move((AMD64Kind) result.getPlatformKind(), crb, masm, result, input); } - private static void move(AMD64Kind moveKind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) { + public static void move(AMD64Kind moveKind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) { if (isRegister(input)) { if (isRegister(result)) { reg2reg(moveKind, masm, result, input); diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorMove.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorMove.java index a24e3f9f9e4a..6e9b54f11e7e 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorMove.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorMove.java @@ -369,7 +369,7 @@ private static VexMoveOp getVectorMoveOp(AMD64Kind kind) { } } - private static VexMoveOp getVectorMemMoveOp(AMD64Kind kind) { + public static VexMoveOp getVectorMemMoveOp(AMD64Kind kind) { switch (AVXKind.getDataSize(kind)) { case DWORD: return VMOVD; diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java index 73993719327d..9f22c3807036 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java @@ -66,6 +66,11 @@ public final class LIR extends LIRGenerator.VariableProvider { */ private final BlockMap> lirInstructions; + /** + * Extra chunks of out of line assembly that must be emitted after all the LIR instructions. + */ + private ArrayList slowPaths; + private boolean hasArgInCallerFrame; private final OptionValues options; @@ -171,6 +176,23 @@ public boolean codeEmittingOrderAvailable() { return codeEmittingOrder != null; } + /** + * The current set of out of line assembly chunks to be emitted. + */ + public ArrayList getSlowPaths() { + return slowPaths; + } + + /** + * Add a chunk of assembly that will be emitted out of line after all LIR has been emitted. + */ + public void addSlowPath(LIRInstruction op, Runnable slowPath) { + if (slowPaths == null) { + slowPaths = new ArrayList<>(); + } + slowPaths.add(new LIRInstruction.LIRInstructionSlowPath(op, slowPath)); + } + /** * Gets an array of all the blocks in this LIR. This should be used by all code that wants to * iterate over the blocks but does not care about a particular order. @@ -314,5 +336,8 @@ public void resetLabels() { } } } + if (slowPaths != null) { + slowPaths.clear(); + } } } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstruction.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstruction.java index c5b357548da6..99ebc791166f 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstruction.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstruction.java @@ -62,6 +62,28 @@ * The base class for an {@code LIRInstruction}. */ public abstract class LIRInstruction { + + /** + * Holder for LIR instructions with out-of-line slow path assembly. + */ + public static class LIRInstructionSlowPath { + private final LIRInstruction op; + private final Runnable slowPath; + + public LIRInstructionSlowPath(LIRInstruction op, Runnable slowPath) { + this.op = op; + this.slowPath = slowPath; + } + + public void emitSlowPathCode() { + slowPath.run(); + } + + public LIRInstruction forOp() { + return op; + } + } + /** * Constants denoting how a LIR instruction uses an operand. */ @@ -170,7 +192,9 @@ public enum OperandFlag { */ UNINITIALIZED, - /** Outgoing block value. */ + /** + * Outgoing block value. + */ OUTGOING, } @@ -351,6 +375,7 @@ public final Value forEachRegisterHint(Value value, OperandMode mode, ValueProce } // Checkstyle: stop + /** * Returns {@code true} if the instruction is a {@link MoveOp}. * diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRValueUtil.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRValueUtil.java index a79414db8234..6b88f7c8906b 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRValueUtil.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRValueUtil.java @@ -138,9 +138,7 @@ public static boolean differentRegisters(Object... values) { Register r1 = registers.get(i); for (int j = 0; j < i; j++) { Register r2 = registers.get(j); - if (r1.equals(r2)) { - return false; - } + assert !r1.equals(r2) : r1 + " appears more than once"; } } return true; @@ -153,6 +151,13 @@ private static List collectRegisters(Object[] values, List r } else if (o instanceof Value) { if (isRegister((Value) o)) { registers.add(asRegister((Value) o)); + } else if (o instanceof CompositeValue) { + CompositeValue compositeValue = (CompositeValue) o; + compositeValue.visitEachComponent(null, null, (instruction, value, mode, flags) -> { + if (isRegister((Value) o)) { + registers.add(asRegister((Value) o)); + } + }); } } else if (o instanceof Object[]) { collectRegisters((Object[]) o, registers); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java index c7272097e69d..05ee7d23115a 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java @@ -137,7 +137,7 @@ public static class PendingImplicitException { /** * The LIR for which code is being generated. */ - protected LIR lir; + protected final LIR lir; /** * The index of the block currently being emitted. @@ -184,28 +184,6 @@ public final boolean mustReplaceWithUncompressedNullRegister(JavaConstant nullCo private final List lirInstructionVerifiers; - public CompilationResultBuilder(CodeGenProviders providers, - FrameMap frameMap, - Assembler asm, - DataBuilder dataBuilder, - FrameContext frameContext, - OptionValues options, - DebugContext debug, - CompilationResult compilationResult, - Register uncompressedNullRegister) { - this(providers, - frameMap, - asm, - dataBuilder, - frameContext, - options, - debug, - compilationResult, - uncompressedNullRegister, - EconomicMap.create(Equivalence.DEFAULT), - NO_VERIFIERS); - } - public CompilationResultBuilder(CodeGenProviders providers, FrameMap frameMap, Assembler asm, @@ -216,7 +194,8 @@ public CompilationResultBuilder(CodeGenProviders providers, CompilationResult compilationResult, Register uncompressedNullRegister, EconomicMap dataCache, - List lirInstructionVerifiers) { + List lirInstructionVerifiers, + LIR lir) { this.target = providers.getCodeCache().getTarget(); this.providers = providers; this.codeCache = providers.getCodeCache(); @@ -224,6 +203,7 @@ public CompilationResultBuilder(CodeGenProviders providers, this.frameMap = frameMap; this.asm = asm; this.dataBuilder = dataBuilder; + this.lir = lir; this.compilationResult = compilationResult; this.uncompressedNullRegister = uncompressedNullRegister; this.frameContext = frameContext; @@ -532,11 +512,9 @@ void close() { /** * Emits code for {@code lir} in its {@linkplain LIR#codeEmittingOrder() code emitting order}. */ - public void emit(@SuppressWarnings("hiding") LIR lir) { - assert this.lir == null; + public void emitLIR() { assert currentBlockIndex == 0; assert lastImplicitExceptionOffset == Integer.MIN_VALUE; - this.lir = lir; this.currentBlockIndex = 0; this.lastImplicitExceptionOffset = Integer.MIN_VALUE; frameContext.enter(this); @@ -570,14 +548,28 @@ public void emit(@SuppressWarnings("hiding") LIR lir) { } currentBlockIndex++; } + + ArrayList slowPaths = lir.getSlowPaths(); + if (slowPaths != null) { + for (LIRInstruction.LIRInstructionSlowPath slowPath : slowPaths) { + try { + emitSlowPath(slowPath); + } catch (GraalError e) { + if (slowPath.forOp() != null) { + throw e.addContext("lir instruction", "slow path for " + slowPath.forOp() + " " + slowPath); + } else { + throw e.addContext("lir instruction", "slow path " + slowPath); + } + } + } + } + logger.close(); - this.lir = null; this.currentBlockIndex = 0; this.lastImplicitExceptionOffset = Integer.MIN_VALUE; } public LIR getLIR() { - assert lir != null; return lir; } @@ -603,6 +595,20 @@ private void emitBlock(BasicBlock block) { } } + private void emitSlowPath(LIRInstruction.LIRInstructionSlowPath op) { + try { + op.emitSlowPathCode(); + // Ensure the slow path doesn't fall through + asm.halt(); + } catch (BailoutException e) { + throw e; + } catch (AssertionError t) { + throw new GraalError(t); + } catch (RuntimeException t) { + throw new GraalError(t); + } + } + private void emitOp(LIRInstruction op) { try { int start = asm.position(); @@ -646,9 +652,9 @@ public void resetForEmittingCode() { if (dataCache != null) { dataCache.clear(); } - lir = null; currentBlockIndex = 0; lastImplicitExceptionOffset = Integer.MIN_VALUE; + lir.resetLabels(); } public OptionValues getOptions() { @@ -659,16 +665,16 @@ public OptionValues getOptions() { * Builds up a map for label and LIR instruction positions where labels are or labels pointing * to. */ - public void buildLabelOffsets(LIR generatedLIR) { + public void buildLabelOffsets() { labelBindLirPositions = EconomicMap.create(Equivalence.IDENTITY); lirPositions = EconomicMap.create(Equivalence.IDENTITY); int instructionPosition = 0; - for (int blockId : generatedLIR.getBlocks()) { + for (int blockId : lir.getBlocks()) { if (LIR.isBlockDeleted(blockId)) { continue; } - BasicBlock block = generatedLIR.getBlockById(blockId); - for (LIRInstruction op : generatedLIR.getLIRforBlock(block)) { + BasicBlock block = lir.getBlockById(blockId); + for (LIRInstruction op : lir.getLIRforBlock(block)) { if (op instanceof LabelHoldingOp) { Label label = ((LabelHoldingOp) op).getLabel(); if (label != null) { diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilderFactory.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilderFactory.java index 5fc110466d36..6967f9b3754f 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilderFactory.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilderFactory.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.core.common.spi.CodeGenProviders; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstructionVerifier; import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.options.Option; @@ -69,7 +70,8 @@ CompilationResultBuilder createBuilder(CodeGenProviders providers, OptionValues options, DebugContext debug, CompilationResult compilationResult, - Register nullRegister); + Register nullRegister, + LIR lir); /** * The default factory creates a standard {@link CompilationResultBuilder}. @@ -102,7 +104,8 @@ public CompilationResultBuilder createBuilder(CodeGenProviders providers, OptionValues options, DebugContext debug, CompilationResult compilationResult, - Register uncompressedNullRegister) { + Register uncompressedNullRegister, + LIR lir) { if (!isVerifierInitialized) { synchronized (lirInstructionVerifiers) { if (!isVerifierInitialized) { @@ -124,7 +127,8 @@ public CompilationResultBuilder createBuilder(CodeGenProviders providers, compilationResult, uncompressedNullRegister, EconomicMap.create(Equivalence.DEFAULT), - lirInstructionVerifiers); + lirInstructionVerifiers, + lir); } }; } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/DataBuilder.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/DataBuilder.java index f500dfb3c299..0dbe1f2d89de 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/DataBuilder.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/DataBuilder.java @@ -46,6 +46,25 @@ public Data createSerializableData(SerializableConstant constant) { return createSerializableData(constant, 1); } + /** + * Create a data object which isn't shared with other entries. This is suitable for creating + * variable slots in the data section. + */ + public Data createMutableData(int alignment, int size) { + assert canForceAlignmentOf(alignment); + return new ZeroData(alignment, size) { + @Override + public boolean equals(Object obj) { + return obj == this; + } + + @Override + public boolean isMutable() { + return true; + } + }; + } + public Data createZeroData(int alignment, int size) { assert canForceAlignmentOf(alignment); switch (size) { diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/EntryPointDecorator.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/EntryPointDecorator.java new file mode 100644 index 000000000000..32ad24c8edcf --- /dev/null +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/EntryPointDecorator.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.asm; + +import org.graalvm.compiler.core.common.spi.CodeGenProviders; +import org.graalvm.compiler.lir.gen.LIRGenerationResult; + +/** + * Helper class to allow emitting custom assembly at the normal entry point before any frame setup + * has occurred. + */ +public interface EntryPointDecorator { + void initialize(CodeGenProviders providers, LIRGenerationResult lirGenRes); + + void emitEntryPoint(CompilationResultBuilder crb); +} diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/BarrierSetLIRGenerator.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/BarrierSetLIRGenerator.java new file mode 100644 index 000000000000..8c73c7a070c8 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/BarrierSetLIRGenerator.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.gen; + +public abstract class BarrierSetLIRGenerator implements BarrierSetLIRGeneratorTool { + protected LIRGenerator lirGen; + + public LIRGenerator getLIRGen() { + return lirGen; + } +} diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/BarrierSetLIRGeneratorTool.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/BarrierSetLIRGeneratorTool.java new file mode 100644 index 000000000000..06be20df6de6 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/BarrierSetLIRGeneratorTool.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.gen; + +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.memory.BarrierType; +import org.graalvm.compiler.core.common.memory.MemoryOrderMode; +import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.Variable; + +import jdk.vm.ci.meta.Value; + +/** + * Base class for handling code generation for GC barriers at the LIR level. Architecture and + * platform specific methods are added as needed in subclasses to interpose on the LIR generation. + */ +public interface BarrierSetLIRGeneratorTool { + + /** + * Emit a read of a memory location along with the required read barrier.. {@code barrierType} + * will always be something besides {@link BarrierType#NONE}. + */ + Variable emitBarrieredLoad(LIRKind kind, Value address, LIRFrameState state, MemoryOrderMode memoryOrder, BarrierType barrierType); +} diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java index 625a92394b5d..d1ec55517c8e 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java @@ -109,14 +109,18 @@ public static class Options { private LIRGenerationResult res; protected final ArithmeticLIRGenerator arithmeticLIRGen; + protected final BarrierSetLIRGeneratorTool barrierSetLIRGen; + private final MoveFactory moveFactory; private final boolean printIrWithLir; private final int traceLIRGeneratorLevel; - public LIRGenerator(LIRKindTool lirKindTool, ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, CodeGenProviders providers, LIRGenerationResult res) { + public LIRGenerator(LIRKindTool lirKindTool, ArithmeticLIRGenerator arithmeticLIRGen, BarrierSetLIRGenerator barrierSetLIRGen, MoveFactory moveFactory, CodeGenProviders providers, + LIRGenerationResult res) { this.lirKindTool = lirKindTool; this.arithmeticLIRGen = arithmeticLIRGen; + this.barrierSetLIRGen = barrierSetLIRGen; this.res = res; this.providers = providers; OptionValues options = res.getLIR().getOptions(); @@ -126,6 +130,11 @@ public LIRGenerator(LIRKindTool lirKindTool, ArithmeticLIRGenerator arithmeticLI assert arithmeticLIRGen.lirGen == null; arithmeticLIRGen.lirGen = this; + if (barrierSetLIRGen != null) { + assert barrierSetLIRGen.lirGen == null; + barrierSetLIRGen.lirGen = this; + } + this.moveFactory = moveFactory; } @@ -134,6 +143,11 @@ public ArithmeticLIRGeneratorTool getArithmetic() { return arithmeticLIRGen; } + @Override + public BarrierSetLIRGeneratorTool getBarrierSet() { + return barrierSetLIRGen; + } + @Override public MoveFactory getMoveFactory() { return moveFactory; @@ -350,7 +364,7 @@ private void doBlockStart() { // set up the list of LIR instructions assert res.getLIR().getLIRforBlock(currentBlock) == null : "LIR list already computed for this block"; - res.getLIR().setLIRforBlock(currentBlock, new ArrayList()); + res.getLIR().setLIRforBlock(currentBlock, new ArrayList<>()); append(new LabelOp(new Label(currentBlock.getId()), currentBlock.isAligned() ? loopHeaderAlignment : 0)); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java index 5e34e3d1fed6..f2d9b0c329d2 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java @@ -32,6 +32,7 @@ import org.graalvm.compiler.core.common.Stride; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.cfg.BasicBlock; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.spi.CodeGenProviders; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; @@ -73,6 +74,8 @@ abstract class BlockScope implements AutoCloseable { ArithmeticLIRGeneratorTool getArithmetic(); + BarrierSetLIRGeneratorTool getBarrierSet(); + CodeGenProviders getProviders(); TargetDescription target(); @@ -119,9 +122,9 @@ abstract class BlockScope implements AutoCloseable { void emitNullCheck(Value address, LIRFrameState state); - Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue, MemoryOrderMode memoryOrder); + Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue, MemoryOrderMode memoryOrder, BarrierType barrierType); - Value emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, MemoryOrderMode memoryOrder); + Value emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, MemoryOrderMode memoryOrder, BarrierType barrierType); /** * Emit an atomic read-and-add instruction. @@ -130,9 +133,7 @@ abstract class BlockScope implements AutoCloseable { * @param address address of the value to be read and written * @param delta the value to be added */ - default Value emitAtomicReadAndAdd(LIRKind accessKind, Value address, Value delta) { - throw GraalError.unimplemented(); // ExcludeFromJacocoGeneratedReport - } + Value emitAtomicReadAndAdd(LIRKind accessKind, Value address, Value delta); /** * Emit an atomic read-and-write instruction. @@ -141,9 +142,7 @@ default Value emitAtomicReadAndAdd(LIRKind accessKind, Value address, Value delt * @param address address of the value to be read and written * @param newValue the new value to be written */ - default Value emitAtomicReadAndWrite(LIRKind accessKind, Value address, Value newValue) { - throw GraalError.unimplemented(); // ExcludeFromJacocoGeneratedReport - } + Value emitAtomicReadAndWrite(LIRKind accessKind, Value address, Value newValue, BarrierType barrierType); void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state); diff --git a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java index e0626cd6739d..2f85b44b516b 100644 --- a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java +++ b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java @@ -325,7 +325,7 @@ protected final void prepareRequest() { ResolvedJavaMethod installedCodeOwner = graph.method(); request = new Request<>(graph, installedCodeOwner, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graph.getProfilingInfo(), createSuites(getOptions()), createLIRSuites(getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default, - true); + null, true); } /** @@ -468,7 +468,7 @@ protected final void emitCode() { request.compilationResult.setHasUnsafeAccess(request.graph.hasUnsafeAccess()); LIRCompilerBackend.emitCode(request.backend, request.graph.getAssumptions(), request.graph.method(), request.graph.getMethods(), speculationLog, bytecodeSize, lirGenRes, request.compilationResult, - request.installedCodeOwner, request.factory); + request.installedCodeOwner, request.factory, request.entryPointDecorator); } protected StructuredGraph graph() { diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaReadNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaReadNode.java index d8f4f8e70b1c..412256782820 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaReadNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaReadNode.java @@ -27,7 +27,9 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; +import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; @@ -73,6 +75,7 @@ protected JavaReadNode(NodeClass c, Stamp stamp, JavaKin this.readKind = readKind; this.compressible = compressible; this.memoryOrder = memoryOrder; + assert barrierType == BarrierType.NONE || stamp instanceof AbstractObjectStamp : "incorrect barrier on non-object type: " + location; } @Override diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java index e29ff62c805e..36e478e8ab44 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java @@ -24,6 +24,7 @@ */ package org.graalvm.compiler.nodes.extended; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/BarrierSet.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/BarrierSet.java index 2d11bc46df92..0f7cc1e26566 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/BarrierSet.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/BarrierSet.java @@ -25,29 +25,36 @@ */ package org.graalvm.compiler.nodes.gc; +import org.graalvm.compiler.core.common.memory.BarrierType; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaField; public interface BarrierSet { + + boolean hasWriteBarrier(); + + boolean hasReadBarrier(); + void addBarriers(FixedAccessNode n); - BarrierType fieldLoadBarrierType(ResolvedJavaField field, JavaKind storageKind); + BarrierType fieldReadBarrierType(ResolvedJavaField field, JavaKind storageKind); - BarrierType fieldStoreBarrierType(ResolvedJavaField field, JavaKind storageKind); + BarrierType fieldWriteBarrierType(ResolvedJavaField field, JavaKind storageKind); - BarrierType readBarrierType(RawLoadNode load); + BarrierType readBarrierType(LocationIdentity location, ValueNode address, Stamp loadStamp); - BarrierType storeBarrierType(RawStoreNode store); + BarrierType writeBarrierType(RawStoreNode store); - BarrierType arrayStoreBarrierType(JavaKind storageKind); + BarrierType arrayWriteBarrierType(JavaKind storageKind); - BarrierType guessStoreBarrierType(ValueNode object, ValueNode value); + BarrierType guessReadWriteBarrier(ValueNode object, ValueNode value); /** * Determine whether writes of the given {@code storageKind} may ever need a pre-write barrier. @@ -57,4 +64,12 @@ public interface BarrierSet { * under certain circumstances. */ boolean mayNeedPreWriteBarrier(JavaKind storageKind); + + /** + * Perform verification of inserted or missing barriers. + * + * @param graph the grraph to verify. + */ + default void verifyBarriers(StructuredGraph graph) { + } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java index e03e24e611b7..3908289d6c73 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java @@ -25,25 +25,26 @@ */ package org.graalvm.compiler.nodes.gc; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ArrayRangeWrite; -import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode; import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaField; @@ -57,32 +58,32 @@ public CardTableBarrierSet(ResolvedJavaType objectArrayType) { } @Override - public BarrierType readBarrierType(RawLoadNode load) { + public BarrierType readBarrierType(LocationIdentity location, ValueNode address, Stamp loadStamp) { return BarrierType.NONE; } @Override - public BarrierType storeBarrierType(RawStoreNode store) { - return store.needsBarrier() ? guessStoreBarrierType(store.object(), store.value()) : BarrierType.NONE; + public BarrierType writeBarrierType(RawStoreNode store) { + return store.needsBarrier() ? guessReadWriteBarrier(store.object(), store.value()) : BarrierType.NONE; } @Override - public BarrierType fieldLoadBarrierType(ResolvedJavaField field, JavaKind storageKind) { + public BarrierType fieldReadBarrierType(ResolvedJavaField field, JavaKind storageKind) { return BarrierType.NONE; } @Override - public BarrierType fieldStoreBarrierType(ResolvedJavaField field, JavaKind storageKind) { + public BarrierType fieldWriteBarrierType(ResolvedJavaField field, JavaKind storageKind) { return storageKind == JavaKind.Object ? BarrierType.FIELD : BarrierType.NONE; } @Override - public BarrierType arrayStoreBarrierType(JavaKind storageKind) { + public BarrierType arrayWriteBarrierType(JavaKind storageKind) { return storageKind == JavaKind.Object ? BarrierType.ARRAY : BarrierType.NONE; } @Override - public BarrierType guessStoreBarrierType(ValueNode object, ValueNode value) { + public BarrierType guessReadWriteBarrier(ValueNode object, ValueNode value) { if (value.getStackKind() == JavaKind.Object && object.getStackKind() == JavaKind.Object) { ResolvedJavaType type = StampTool.typeOrNull(object); if (type != null && type.isArray()) { @@ -96,6 +97,16 @@ public BarrierType guessStoreBarrierType(ValueNode object, ValueNode value) { return BarrierType.NONE; } + @Override + public boolean hasWriteBarrier() { + return true; + } + + @Override + public boolean hasReadBarrier() { + return false; + } + @Override public void addBarriers(FixedAccessNode n) { if (n instanceof ReadNode) { diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1BarrierSet.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1BarrierSet.java index eaabc733fc61..2713238468a6 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1BarrierSet.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1BarrierSet.java @@ -25,22 +25,23 @@ */ package org.graalvm.compiler.nodes.gc; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ArrayRangeWrite; -import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode; import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaField; @@ -56,42 +57,42 @@ public G1BarrierSet(ResolvedJavaType objectArrayType, ResolvedJavaField referent } @Override - public BarrierType readBarrierType(RawLoadNode load) { - // For RawLoadNode resulted from Unsafe access, do not bother inserting barriers. - // See JDK-8189871. + public BarrierType readBarrierType(LocationIdentity location, ValueNode address, Stamp loadStamp) { return BarrierType.NONE; } @Override - public BarrierType storeBarrierType(RawStoreNode store) { - return store.needsBarrier() ? guessStoreBarrierType(store.object(), store.value()) : BarrierType.NONE; + public BarrierType writeBarrierType(RawStoreNode store) { + return store.needsBarrier() ? guessReadWriteBarrier(store.object(), store.value()) : BarrierType.NONE; } @Override - public BarrierType fieldLoadBarrierType(ResolvedJavaField field, JavaKind storageKind) { + public BarrierType fieldReadBarrierType(ResolvedJavaField field, JavaKind storageKind) { if (field.getJavaKind() == JavaKind.Object && field.equals(referentField)) { - // We should not encounter field load of Reference.referent except compiling - // Reference.get(), which won't be executed anyway given the intrinsification. - // We cannot distinguish between PhantomReference and other Reference. Yet returning - // BarrierType.WEAK_FIELD is fine for G1 since the inserted barriers for both WEAK_FIELD - // and PHANTOM_FIELD are identical. - return BarrierType.WEAK_FIELD; + /* + * We should not encounter field load of Reference.referent except compiling + * Reference.get(), which won't be executed anyway given the intrinsification. We cannot + * distinguish between PhantomReference and other References. Yet returning + * BarrierType.REFERENCE_GET is fine for G1 since the inserted barriers for both + * REFERENCE_GET and PHANTOM_REFERS_TO are identical. + */ + return BarrierType.REFERENCE_GET; } return BarrierType.NONE; } @Override - public BarrierType fieldStoreBarrierType(ResolvedJavaField field, JavaKind storageKind) { + public BarrierType fieldWriteBarrierType(ResolvedJavaField field, JavaKind storageKind) { return storageKind == JavaKind.Object ? BarrierType.FIELD : BarrierType.NONE; } @Override - public BarrierType arrayStoreBarrierType(JavaKind storageKind) { + public BarrierType arrayWriteBarrierType(JavaKind storageKind) { return storageKind == JavaKind.Object ? BarrierType.ARRAY : BarrierType.NONE; } @Override - public BarrierType guessStoreBarrierType(ValueNode object, ValueNode value) { + public BarrierType guessReadWriteBarrier(ValueNode object, ValueNode value) { if (value.getStackKind() == JavaKind.Object && object.getStackKind() == JavaKind.Object) { ResolvedJavaType type = StampTool.typeOrNull(object); if (type != null && type.isArray()) { @@ -105,6 +106,16 @@ public BarrierType guessStoreBarrierType(ValueNode object, ValueNode value) { return BarrierType.NONE; } + @Override + public boolean hasWriteBarrier() { + return true; + } + + @Override + public boolean hasReadBarrier() { + return false; + } + @Override public void addBarriers(FixedAccessNode n) { if (n instanceof ReadNode) { @@ -126,7 +137,7 @@ public void addBarriers(FixedAccessNode n) { } private static void addReadNodeBarriers(ReadNode node) { - if (node.getBarrierType() == BarrierType.WEAK_FIELD || node.getBarrierType() == BarrierType.PHANTOM_FIELD) { + if (node.getBarrierType() == BarrierType.REFERENCE_GET || node.getBarrierType() == BarrierType.PHANTOM_REFERS_TO) { StructuredGraph graph = node.graph(); G1ReferentFieldReadBarrier barrier = graph.add(new G1ReferentFieldReadBarrier(node.getAddress(), node)); graph.addAfterFixed(node, barrier); @@ -211,6 +222,6 @@ private static boolean isObjectValue(ValueNode value) { @Override public boolean mayNeedPreWriteBarrier(JavaKind storageKind) { - return arrayStoreBarrierType(storageKind) != BarrierType.NONE; + return arrayWriteBarrierType(storageKind) != BarrierType.NONE; } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/ZBarrierSet.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/ZBarrierSet.java new file mode 100644 index 000000000000..7e536a05641d --- /dev/null +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/ZBarrierSet.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.nodes.gc; + +import static org.graalvm.compiler.nodes.NamedLocationIdentity.OFF_HEAP_LOCATION; + +import org.graalvm.compiler.core.common.memory.BarrierType; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.FieldLocationIdentity; +import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.NodeView; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.extended.RawStoreNode; +import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode; +import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode; +import org.graalvm.compiler.nodes.memory.AddressableMemoryAccess; +import org.graalvm.compiler.nodes.memory.FixedAccessNode; +import org.graalvm.compiler.nodes.memory.FloatingReadNode; +import org.graalvm.compiler.nodes.memory.LIRLowerableAccess; +import org.graalvm.compiler.nodes.memory.ReadNode; +import org.graalvm.compiler.nodes.memory.WriteNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; +import org.graalvm.word.LocationIdentity; + +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaField; + +/** + * Base class for the barrier set for ZGC. This provides the basica requirement that ever reads of + * an object from the heap should have an associated read barrier. Read barriers for non-heap + * locations like handles can be handled by subclasses. + */ +public class ZBarrierSet implements BarrierSet { + + private final ResolvedJavaField referentField; + + public ZBarrierSet(ResolvedJavaField referentField) { + this.referentField = referentField; + } + + @Override + public BarrierType readBarrierType(LocationIdentity location, ValueNode address, Stamp loadStamp) { + if (location.equals(OFF_HEAP_LOCATION)) { + // Off heap locations are never expected to contain objects + assert !loadStamp.isObjectStamp() : location; + return BarrierType.NONE; + } + + if (loadStamp.isObjectStamp()) { + if (address.stamp(NodeView.DEFAULT).isObjectStamp()) { + // A read of an Object from an Object requires a barrier + return BarrierType.READ; + } + + if (address instanceof AddressNode) { + AddressNode addr = (AddressNode) address; + if (addr.getBase().stamp(NodeView.DEFAULT).isObjectStamp()) { + // A read of an Object from an Object requires a barrier + return BarrierType.READ; + } + } + // Objects aren't expected to be read from non-heap locations. + throw GraalError.shouldNotReachHere("Unexpected location type " + loadStamp); + } + + boolean mustBeObject = false; + if (location instanceof FieldLocationIdentity) { + FieldLocationIdentity fieldLocationIdentity = (FieldLocationIdentity) location; + mustBeObject = fieldLocationIdentity.getField().getJavaKind() == JavaKind.Object; + } + assert !mustBeObject : address; + return BarrierType.NONE; + } + + @Override + public BarrierType writeBarrierType(RawStoreNode store) { + return BarrierType.NONE; + } + + @Override + public BarrierType fieldReadBarrierType(ResolvedJavaField field, JavaKind storageKind) { + if (storageKind == JavaKind.Object && field.equals(referentField)) { + return BarrierType.REFERENCE_GET; + } + if (storageKind.isObject()) { + return BarrierType.READ; + } + return BarrierType.NONE; + } + + @Override + public BarrierType fieldWriteBarrierType(ResolvedJavaField field, JavaKind storageKind) { + return BarrierType.NONE; + } + + @Override + public BarrierType arrayWriteBarrierType(JavaKind storageKind) { + return BarrierType.NONE; + } + + @Override + public BarrierType guessReadWriteBarrier(ValueNode object, ValueNode value) { + if (value.stamp(NodeView.DEFAULT).isObjectStamp()) { + return BarrierType.READ; + } + return BarrierType.NONE; + } + + @Override + public boolean hasWriteBarrier() { + return false; + } + + @Override + public boolean hasReadBarrier() { + return true; + } + + @Override + public void addBarriers(FixedAccessNode n) { + } + + @Override + public boolean mayNeedPreWriteBarrier(JavaKind storageKind) { + return false; + } + + @Override + public void verifyBarriers(StructuredGraph graph) { + for (Node node : graph.getNodes()) { + if (node instanceof WriteNode) { + WriteNode write = (WriteNode) node; + GraalError.guarantee(write.getBarrierType() == BarrierType.NONE, "There are no write barriers with ZGC: %s", node); + } else if (node instanceof ReadNode || node instanceof FloatingReadNode || + node instanceof AbstractCompareAndSwapNode || node instanceof LoweredAtomicReadAndWriteNode) { + LIRLowerableAccess read = (LIRLowerableAccess) node; + Stamp stamp = read.getAccessStamp(NodeView.DEFAULT); + if (!stamp.isObjectStamp()) { + GraalError.guarantee(read.getBarrierType() == BarrierType.NONE, "no barriers for primitive reads: %s", read); + continue; + } + + BarrierType expectedBarrier = barrierForLocation(read.getBarrierType(), read.getLocationIdentity(), JavaKind.Object); + if (expectedBarrier != null) { + GraalError.guarantee(expectedBarrier == read.getBarrierType(), "expected %s but found %s in %s", expectedBarrier, read.getBarrierType(), read); + continue; + } + + ValueNode base = read.getAddress().getBase(); + if (!base.stamp(NodeView.DEFAULT).isObjectStamp()) { + GraalError.guarantee(read.getBarrierType() == BarrierType.NONE, "no barrier for non-heap read: %s", read); + } else { + GraalError.guarantee(read.getBarrierType() == BarrierType.READ, "missing barriers for heap read: %s", read); + } + } else if (node instanceof AddressableMemoryAccess) { + AddressableMemoryAccess access = (AddressableMemoryAccess) node; + if (access.getBarrierType() != BarrierType.NONE) { + throw new GraalError("Unexpected memory access with barrier : " + node); + } + } + } + } + + protected BarrierType barrierForLocation(BarrierType currentBarrier, LocationIdentity location, JavaKind storageKind) { + if (location instanceof FieldLocationIdentity) { + FieldLocationIdentity fieldLocationIdentity = (FieldLocationIdentity) location; + BarrierType barrierType = fieldReadBarrierType(fieldLocationIdentity.getField(), storageKind); + if (barrierType != currentBarrier && barrierType == BarrierType.REFERENCE_GET) { + if (currentBarrier == BarrierType.WEAK_REFERS_TO || currentBarrier == BarrierType.PHANTOM_REFERS_TO) { + return currentBarrier; + } + } + return barrierType; + } + if (location.equals(NamedLocationIdentity.getArrayLocation(JavaKind.Object))) { + return BarrierType.READ; + } + return null; + } + +} diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java index fd6f03d2f2b8..ebe4c1fbfae1 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java @@ -36,7 +36,7 @@ import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.nodes.PluginReplacementNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.InlineOnlyInvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInlineOnlyInvocationPlugin; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -46,7 +46,7 @@ * Abstract class for a plugin generated for a method annotated by {@link NodeIntrinsic} or * {@link Fold}. */ -public abstract class GeneratedInvocationPlugin extends InlineOnlyInvocationPlugin { +public abstract class GeneratedInvocationPlugin extends RequiredInlineOnlyInvocationPlugin { private ResolvedJavaMethod executeMethod; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java index 2d45593aad74..b8987d93d4b5 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java @@ -817,9 +817,10 @@ public final void register(Type declaringClass, InvocationPlugin plugin) { * * @param method the method to lookup * @param allowDecorators return {@link InvocationPlugin#isDecorator()} plugins only if true + * @param allowDisable whether to respect the DisableIntrinsics flag * @return the plugin associated with {@code method} or {@code null} if none exists */ - public InvocationPlugin lookupInvocation(ResolvedJavaMethod method, boolean allowDecorators, OptionValues options) { + public InvocationPlugin lookupInvocation(ResolvedJavaMethod method, boolean allowDecorators, boolean allowDisable, OptionValues options) { if (!isDisabledIntrinsicsFilterInitialized) { synchronized (this) { if (!isDisabledIntrinsicsFilterInitialized) { @@ -837,7 +838,7 @@ public InvocationPlugin lookupInvocation(ResolvedJavaMethod method, boolean allo } if (parent != null) { - InvocationPlugin plugin = parent.lookupInvocation(method, allowDecorators, options); + InvocationPlugin plugin = parent.lookupInvocation(method, allowDecorators, allowDisable, options); if (plugin != null) { return plugin; } @@ -845,7 +846,7 @@ public InvocationPlugin lookupInvocation(ResolvedJavaMethod method, boolean allo InvocationPlugin invocationPlugin = get(method); if (invocationPlugin != null) { if (allowDecorators || !invocationPlugin.isDecorator()) { - if (disabledIntrinsicsFilter != null && disabledIntrinsicsFilter.matches(method)) { + if (allowDisable && disabledIntrinsicsFilter != null && disabledIntrinsicsFilter.matches(method)) { if (invocationPlugin.canBeDisabled()) { if (logDisabledIntrinsics) { TTY.println("[Warning] Intrinsic for %s is disabled.", method.format("%H.%n(%p)")); @@ -857,6 +858,9 @@ public InvocationPlugin lookupInvocation(ResolvedJavaMethod method, boolean allo } } } + if (logDisabledIntrinsics && invocationPlugin.canBeDisabled()) { + TTY.println("[Warning] Intrinsic for %s is enabled.", method.format("%H.%n(%p)")); + } return invocationPlugin; } } @@ -872,7 +876,7 @@ public InvocationPlugin lookupInvocation(ResolvedJavaMethod method, boolean allo * @return the plugin associated with {@code method} or {@code null} if none exists */ public InvocationPlugin lookupInvocation(ResolvedJavaMethod method, OptionValues options) { - return lookupInvocation(method, false, options); + return lookupInvocation(method, false, true, options); } /** diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java index 779753a14895..4e71e7c03348 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java @@ -27,6 +27,7 @@ import static org.graalvm.compiler.nodeinfo.InputType.Memory; import static org.graalvm.compiler.nodeinfo.InputType.State; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java index 55c06820b2e6..39ba8300f26e 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java @@ -28,6 +28,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; @@ -65,7 +66,7 @@ public void generate(NodeLIRBuilderTool gen) { Value trueResult = tool.emitConstant(resultKind, JavaConstant.TRUE); Value falseResult = tool.emitConstant(resultKind, JavaConstant.FALSE); Value result = tool.emitLogicCompareAndSwap(tool.getLIRKind(getAccessStamp(NodeView.DEFAULT)), gen.operand(getAddress()), gen.operand(getExpectedValue()), gen.operand(getNewValue()), - trueResult, falseResult, memoryOrder); + trueResult, falseResult, memoryOrder, getBarrierType()); gen.setResult(this, result); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndAddNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndAddNode.java index 35530f4f566f..8c5e8fbc977b 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndAddNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndAddNode.java @@ -30,6 +30,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -57,8 +58,8 @@ public final class LoweredAtomicReadAndAddNode extends FixedAccessNode implement @Input ValueNode delta; @OptionalInput(State) FrameState stateAfter; - public LoweredAtomicReadAndAddNode(AddressNode address, LocationIdentity location, ValueNode delta, BarrierType barrierType) { - super(TYPE, address, location, delta.stamp(NodeView.DEFAULT).unrestricted(), barrierType); + public LoweredAtomicReadAndAddNode(AddressNode address, LocationIdentity location, ValueNode delta) { + super(TYPE, address, location, delta.stamp(NodeView.DEFAULT).unrestricted(), BarrierType.NONE); this.delta = delta; } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java index f3e6ea3d1dba..7b781d16dc47 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java @@ -30,6 +30,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -91,7 +92,7 @@ public void generate(NodeLIRBuilderTool gen) { accessKind = gen.getLIRGeneratorTool().getLIRKind(getAccessStamp(NodeView.DEFAULT)); } - Value result = gen.getLIRGeneratorTool().emitAtomicReadAndWrite(accessKind, gen.operand(getAddress()), emitted); + Value result = gen.getLIRGeneratorTool().emitAtomicReadAndWrite(accessKind, gen.operand(getAddress()), emitted, getBarrierType()); gen.setResult(this, result); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java index 504114b80487..c8aa197f6d6d 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java @@ -27,6 +27,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; @@ -57,7 +58,7 @@ public void generate(NodeLIRBuilderTool gen) { LIRGeneratorTool tool = gen.getLIRGeneratorTool(); assert !this.canDeoptimize(); Value result = tool.emitValueCompareAndSwap(tool.getLIRKind(getAccessStamp(NodeView.DEFAULT)), - gen.operand(getAddress()), gen.operand(getExpectedValue()), gen.operand(getNewValue()), memoryOrder); + gen.operand(getAddress()), gen.operand(getExpectedValue()), gen.operand(getNewValue()), memoryOrder, getBarrierType()); gen.setResult(this, result); } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AbstractWriteNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AbstractWriteNode.java index a8bdddfff670..fddc039169d6 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AbstractWriteNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AbstractWriteNode.java @@ -27,6 +27,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AddressableMemoryAccess.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AddressableMemoryAccess.java index 45e29ce6db29..685c86120cf3 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AddressableMemoryAccess.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AddressableMemoryAccess.java @@ -24,6 +24,7 @@ */ package org.graalvm.compiler.nodes.memory; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.word.LocationIdentity; @@ -44,4 +45,6 @@ public interface AddressableMemoryAccess extends MemoryAccess { AddressNode getAddress(); void setAddress(AddressNode address); + + BarrierType getBarrierType(); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java index 8a24160f1342..ef73284e3c57 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java @@ -26,6 +26,7 @@ import static org.graalvm.compiler.nodeinfo.InputType.Memory; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.NodeClass; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatableAccessNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatableAccessNode.java index c1b929f6786d..7c74abb7cd62 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatableAccessNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatableAccessNode.java @@ -24,6 +24,7 @@ */ package org.graalvm.compiler.nodes.memory; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -66,6 +67,6 @@ public void setForceFixed(boolean flag) { * an attached write barrier with pre-semantics can not also float. */ public boolean canFloat() { - return !forceFixed && getLocationIdentity().isSingle() && getBarrierType() == BarrierType.NONE; + return !forceFixed && getLocationIdentity().isSingle() && (getBarrierType() == BarrierType.NONE || getBarrierType() == BarrierType.READ); } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingAccessNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingAccessNode.java index e4bbe46c4383..a6cddd2788dc 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingAccessNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingAccessNode.java @@ -24,6 +24,7 @@ */ package org.graalvm.compiler.nodes.memory; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.InputType; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java index 7134be658bbd..332cd4657dc8 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java @@ -29,6 +29,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryExtendKind; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.ObjectStamp; @@ -36,14 +37,14 @@ import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNodeUtil; import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; +import org.graalvm.compiler.nodes.spi.Canonicalizable; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.word.LocationIdentity; @@ -72,6 +73,8 @@ public FloatingReadNode(AddressNode address, LocationIdentity location, MemoryKi // The input to floating reads must be always non-null or have at least a guard. assert guard != null || !(address.getBase().stamp(NodeView.DEFAULT) instanceof ObjectStamp) || address.getBase() instanceof ValuePhiNode || ((ObjectStamp) address.getBase().stamp(NodeView.DEFAULT)).nonNull() : address.getBase(); + + assert barrierType == BarrierType.NONE || stamp.isObjectStamp() : "incorrect barrier on non-object type: " + location; } @Override @@ -88,7 +91,11 @@ public void setLastLocationAccess(MemoryKill newlla) { @Override public void generate(NodeLIRBuilderTool gen) { LIRKind readKind = gen.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT)); - gen.setResult(this, gen.getLIRGeneratorTool().getArithmetic().emitLoad(readKind, gen.operand(address), null, MemoryOrderMode.PLAIN, MemoryExtendKind.DEFAULT)); + if (getBarrierType() != BarrierType.NONE && gen.getLIRGeneratorTool().getBarrierSet() != null) { + gen.setResult(this, gen.getLIRGeneratorTool().getBarrierSet().emitBarrieredLoad(readKind, gen.operand(address), null, MemoryOrderMode.PLAIN, getBarrierType())); + } else { + gen.setResult(this, gen.getLIRGeneratorTool().getArithmetic().emitLoad(readKind, gen.operand(address), null, MemoryOrderMode.PLAIN, MemoryExtendKind.DEFAULT)); + } } @Override diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/OnHeapMemoryAccess.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/OnHeapMemoryAccess.java index 99d81fa2dcb8..0a2e11915218 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/OnHeapMemoryAccess.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/OnHeapMemoryAccess.java @@ -24,43 +24,14 @@ */ package org.graalvm.compiler.nodes.memory; +import org.graalvm.compiler.core.common.memory.BarrierType; + /** * * A special form of {@linkplain MemoryAccess} requiring barrier information for garbage collection. */ public interface OnHeapMemoryAccess extends MemoryAccess { - /** - * The types of (write/read) barriers attached to stores. - */ - enum BarrierType { - /** - * Primitive access which do not necessitate barriers. - */ - NONE, - /** - * Array object access. - */ - ARRAY, - /** - * Field object access. - */ - FIELD, - /** - * Unknown (aka field or array) object access. - */ - UNKNOWN, - /** - * Weak field access (e.g. Hotspot's Reference.referent field). - */ - WEAK_FIELD, - /** - * Phantom field access (e.g. Hotspot's Reference.referent field of a PhantomReference - * instance). - */ - PHANTOM_FIELD - } - /** * Gets the write barrier type for that particular access. */ diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java index 827dc00b3f7c..86bfd8b5eb79 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java @@ -29,6 +29,7 @@ import static org.graalvm.compiler.nodes.NamedLocationIdentity.ARRAY_LENGTH_LOCATION; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryExtendKind; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.IntegerStamp; @@ -109,12 +110,19 @@ protected ReadNode(NodeClass c, AddressNode address, Locatio this.accessStamp = accessStamp; this.extendKind = extendKind; this.memoryOrder = memoryOrder; + assert barrierType == BarrierType.NONE || stamp.isObjectStamp() : "incorrect barrier on non-object type: " + location; + assert barrierType == BarrierType.NONE || extendKind == MemoryExtendKind.DEFAULT : "incorrect extension on barriered access: " + location; } @Override public void generate(NodeLIRBuilderTool gen) { LIRKind readKind = gen.getLIRGeneratorTool().getLIRKind(getAccessStamp(NodeView.DEFAULT)); - gen.setResult(this, gen.getLIRGeneratorTool().getArithmetic().emitLoad(readKind, gen.operand(address), gen.state(this), memoryOrder, extendKind)); + if (getBarrierType() != BarrierType.NONE && gen.getLIRGeneratorTool().getBarrierSet() != null) { + assert extendKind == MemoryExtendKind.DEFAULT; + gen.setResult(this, gen.getLIRGeneratorTool().getBarrierSet().emitBarrieredLoad(readKind, gen.operand(address), gen.state(this), memoryOrder, getBarrierType())); + } else { + gen.setResult(this, gen.getLIRGeneratorTool().getArithmetic().emitLoad(readKind, gen.operand(address), gen.state(this), memoryOrder, extendKind)); + } } @Override diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/SideEffectFreeWriteNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/SideEffectFreeWriteNode.java index 8ba3a4ce0c5c..2e1a8044b566 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/SideEffectFreeWriteNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/SideEffectFreeWriteNode.java @@ -24,6 +24,7 @@ */ package org.graalvm.compiler.nodes.memory; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java index fbf44cd65041..8c0a8ab7abea 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java @@ -27,6 +27,7 @@ import static org.graalvm.compiler.core.common.memory.MemoryOrderMode.VOLATILE; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.Node; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java index a0c23f07d8c8..7705b3a3594c 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.RoundNode; +import org.graalvm.compiler.nodes.gc.BarrierSet; import org.graalvm.compiler.nodes.memory.ExtendableMemoryAccess; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.options.OptionValues; @@ -88,6 +89,11 @@ public interface LoweringProvider { */ TargetDescription getTarget(); + /** + * Returns the barrier set use for code generation. + */ + BarrierSet getBarrierSet(); + /** * Indicates whether the target platform complies with the JVM specification semantics for * {@code idiv} and {@code ldiv} when the dividend is {@link Integer#MIN_VALUE} or diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByNodePhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByNodePhase.java new file mode 100644 index 000000000000..da610150a724 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByNodePhase.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.phases.common; + +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; +import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; +import org.graalvm.compiler.nodes.spi.CoreProviders; +import org.graalvm.compiler.nodes.spi.LoopsDataProvider; +import org.graalvm.compiler.nodes.util.GraphUtil; + +/** + * A phase the visits each address node and lowers into a machine dependent form. + */ +public class AddressLoweringByNodePhase extends AddressLoweringPhase { + + public abstract static class AddressLowering { + + @SuppressWarnings("unused") + public void preProcess(StructuredGraph graph, LoopsDataProvider loopsDataProvider) { + } + + @SuppressWarnings("unused") + public void postProcess(AddressNode lowered) { + } + + public abstract AddressNode lower(ValueNode base, ValueNode offset); + } + + private final AddressLoweringByNodePhase.AddressLowering lowering; + + public AddressLoweringByNodePhase(AddressLoweringByNodePhase.AddressLowering lowering) { + this.lowering = lowering; + } + + @Override + protected void run(StructuredGraph graph, CoreProviders providers) { + lowering.preProcess(graph, providers.getLoopsDataProvider()); + for (Node node : graph.getNodes()) { + AddressNode lowered; + if (node instanceof OffsetAddressNode) { + OffsetAddressNode address = (OffsetAddressNode) node; + lowered = lowering.lower(address.getBase(), address.getOffset()); + lowering.postProcess(lowered); + } else { + continue; + } + node.replaceAtUsages(lowered); + GraphUtil.killWithUnusedFloatingInputs(node); + } + } +} diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java index b2ce9a610491..a92a80f103f2 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java @@ -43,14 +43,13 @@ import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.phases.BasePhase; import jdk.vm.ci.meta.JavaKind; /** * Created by adinn on 09/05/17. */ -public class AddressLoweringByUsePhase extends BasePhase { +public class AddressLoweringByUsePhase extends AddressLoweringPhase { public abstract static class AddressLoweringByUse { public abstract AddressNode lower(ValueNode use, Stamp stamp, AddressNode address); diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java index d8847a2da429..1029212622e4 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java @@ -26,38 +26,16 @@ import java.util.Optional; -import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.GraphState; import org.graalvm.compiler.nodes.GraphState.StageFlag; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; -import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.CoreProviders; -import org.graalvm.compiler.nodes.spi.LoopsDataProvider; -import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.BasePhase; -public class AddressLoweringPhase extends BasePhase { - - public abstract static class AddressLowering { - - @SuppressWarnings("unused") - public void preProcess(StructuredGraph graph, LoopsDataProvider loopsDataProvider) { - } - - @SuppressWarnings("unused") - public void postProcess(AddressNode lowered) { - } - - public abstract AddressNode lower(ValueNode base, ValueNode offset); - } - - private final AddressLowering lowering; - - public AddressLoweringPhase(AddressLowering lowering) { - this.lowering = lowering; - } +/** + * The base class of all phases that lower {@link AddressNode} into a machine dependent nodes. + */ +public abstract class AddressLoweringPhase extends BasePhase { @Override public Optional notApplicableTo(GraphState graphState) { @@ -66,23 +44,6 @@ public Optional notApplicableTo(GraphState graphState) { NotApplicable.unlessRunAfter(this, StageFlag.LOW_TIER_LOWERING, graphState)); } - @Override - protected void run(StructuredGraph graph, CoreProviders providers) { - lowering.preProcess(graph, providers.getLoopsDataProvider()); - for (Node node : graph.getNodes()) { - AddressNode lowered; - if (node instanceof OffsetAddressNode) { - OffsetAddressNode address = (OffsetAddressNode) node; - lowered = lowering.lower(address.getBase(), address.getOffset()); - lowering.postProcess(lowered); - } else { - continue; - } - node.replaceAtUsages(lowered); - GraphUtil.killWithUnusedFloatingInputs(node); - } - } - @Override public void updateGraphState(GraphState graphState) { super.updateGraphState(graphState); diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/BarrierSetVerificationPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/BarrierSetVerificationPhase.java new file mode 100644 index 000000000000..5fafffec24f5 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/BarrierSetVerificationPhase.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.phases.common; + +import static org.graalvm.compiler.phases.BasePhase.NotApplicable.ifAny; + +import java.util.Optional; + +import org.graalvm.compiler.nodes.GraphState; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.gc.BarrierSet; +import org.graalvm.compiler.nodes.spi.CoreProviders; +import org.graalvm.compiler.phases.BasePhase; + +public class BarrierSetVerificationPhase extends BasePhase { + + @Override + public Optional notApplicableTo(GraphState graphState) { + return ifAny(BasePhase.NotApplicable.unlessRunAfter(this, GraphState.StageFlag.LOW_TIER_LOWERING, graphState), + BasePhase.NotApplicable.unlessRunBefore(this, GraphState.StageFlag.ADDRESS_LOWERING, graphState)); + } + + @SuppressWarnings("try") + @Override + protected void run(StructuredGraph graph, CoreProviders context) { + BarrierSet barrierSet = context.getPlatformConfigurationProvider().getBarrierSet(); + barrierSet.verifyBarriers(graph); + } + + @Override + public boolean checkContract() { + return false; + } +} diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/WriteBarrierAdditionPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/WriteBarrierAdditionPhase.java index 12f1d480d263..dbe6651166f2 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/WriteBarrierAdditionPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/WriteBarrierAdditionPhase.java @@ -49,9 +49,11 @@ public Optional notApplicableTo(GraphState graphState) { @Override protected void run(StructuredGraph graph, CoreProviders context) { BarrierSet barrierSet = context.getPlatformConfigurationProvider().getBarrierSet(); - for (FixedAccessNode n : graph.getNodes(FixedAccessNode.TYPE)) { - try (DebugCloseable scope = n.graph().withNodeSourcePosition(n)) { - barrierSet.addBarriers(n); + if (barrierSet.hasWriteBarrier()) { + for (FixedAccessNode n : graph.getNodes(FixedAccessNode.TYPE)) { + try (DebugCloseable scope = n.graph().withNodeSourcePosition(n)) { + barrierSet.addBarriers(n); + } } } } diff --git a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java index 80bf22475065..e4ae2b3602fa 100644 --- a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java +++ b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java @@ -29,6 +29,7 @@ import java.io.OutputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -36,8 +37,8 @@ import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeDisassembler; -import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.match.ComplexMatchValue; import org.graalvm.compiler.graph.Node; @@ -59,8 +60,8 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.meta.JavaKind; @@ -221,7 +222,18 @@ private void printNode(Node node, boolean unscheduled) { out.print("d ").print(HOVER_START).print("d").print(HOVER_SEP); out.println("=== Debug Properties ==="); for (Map.Entry entry : props.entrySet()) { - out.print(entry.getKey().toString()).print(": ").print(entry.getValue() == null ? "[null]" : entry.getValue().toString()).println(); + Object value = entry.getValue(); + String s; + if (value == null) { + s = "[null]"; + } else { + if (value instanceof Object[]) { + s = Arrays.toString((Object[]) value); + } else { + s = value.toString(); + } + } + out.print(entry.getKey().toString()).print(": ").print(value == null ? "[null]" : s).println(); } out.println("=== Inputs ==="); printNamedNodes(node, node.inputPositions().iterator(), "", "\n", null); diff --git a/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java index d8e1755a7f58..0c8131563f22 100644 --- a/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java @@ -38,6 +38,7 @@ import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.Stride; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.ConstantNode; @@ -59,7 +60,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; import org.graalvm.compiler.nodes.java.ArrayLengthNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess; import org.graalvm.compiler.nodes.memory.address.IndexAddressNode; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.options.OptionValues; @@ -472,7 +472,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) { b.addPush(JavaKind.Char, new JavaReadNode(JavaKind.Char, new IndexAddressNode(arg1, new LeftShiftNode(arg2, ConstantNode.forInt(1)), JavaKind.Byte), - NamedLocationIdentity.getArrayLocation(JavaKind.Byte), OnHeapMemoryAccess.BarrierType.NONE, MemoryOrderMode.PLAIN, false)); + NamedLocationIdentity.getArrayLocation(JavaKind.Byte), BarrierType.NONE, MemoryOrderMode.PLAIN, false)); return true; } }); diff --git a/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java index 858cfdaaf325..dd02b568e88f 100644 --- a/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java @@ -40,6 +40,7 @@ import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.Stride; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.ConstantNode; @@ -62,7 +63,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; import org.graalvm.compiler.nodes.java.ArrayLengthNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess; import org.graalvm.compiler.nodes.memory.address.IndexAddressNode; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.options.OptionValues; @@ -521,7 +521,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) { b.addPush(JavaKind.Char, new JavaReadNode(JavaKind.Char, new IndexAddressNode(arg1, new LeftShiftNode(arg2, ConstantNode.forInt(1)), JavaKind.Byte), - NamedLocationIdentity.getArrayLocation(JavaKind.Byte), OnHeapMemoryAccess.BarrierType.NONE, MemoryOrderMode.PLAIN, false)); + NamedLocationIdentity.getArrayLocation(JavaKind.Byte), BarrierType.NONE, MemoryOrderMode.PLAIN, false)); return true; } }); diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java index 965ca912f157..75c46d7d8689 100644 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java +++ b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java @@ -29,6 +29,7 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.test.GraalCompilerTest; @@ -48,7 +49,6 @@ 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.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java index dba3abfb3792..ddd987a457a0 100644 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java +++ b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java @@ -26,6 +26,7 @@ import static org.graalvm.compiler.core.GraalCompiler.compileGraph; import static org.graalvm.compiler.core.common.GraalOptions.TrackNodeSourcePosition; +import static org.junit.Assume.assumeTrue; import java.util.List; @@ -58,6 +59,10 @@ public void snippetLowering(String[] array, String value) { @Test public void testSnippetLowering() { + // This test is checking for the source positions from the snippet lowered write barrier so + // it only works for GCs that have write barriers. + assumeTrue("current gc has no write barrier", getProviders().getPlatformConfigurationProvider().getBarrierSet().hasWriteBarrier()); + // @formatter:off // Expect mappings of the form: // at org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.serialWriteBarrier(WriteBarrierSnippets.java:140) [bci: 18] diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/UnsafeReplacementsTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/UnsafeReplacementsTest.java index cec8b52277f7..e7a8d504d8fa 100644 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/UnsafeReplacementsTest.java +++ b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/UnsafeReplacementsTest.java @@ -1110,29 +1110,4 @@ public void testUnsafeGetPutUnaligned() { test("unsafeGetPutIntUnaligned"); test("unsafeGetPutLongUnaligned"); } - - public static Object unsafeGetUncompressedObject(long address) { - return unsafe.getUncompressedObject(address); - } - - @Test - public void testUnsafeGetUncompressionObject() { - testGraph("unsafeGetUncompressedObject"); - // Allocate some memory and fill it with non-zero values. - final int size = 32; - final long address = unsafe.allocateMemory(size); - unsafe.setMemory(address, size, (byte) 0x23); - - // The only thing we can do is check for null-ness. - // So, store a null somewhere. - unsafe.putAddress(address + 16, 0); - - Object nullObj = unsafe.getUncompressedObject(address + 16); - if (nullObj != null) { - throw new InternalError("should be null"); - } - - test("unsafeGetUncompressedObject", address + 16); - unsafe.freeMemory(address); - } } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java index 08212a028d53..3d727ec1fdcc 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java @@ -39,6 +39,7 @@ import java.util.BitSet; import java.util.List; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider; @@ -137,7 +138,6 @@ import org.graalvm.compiler.nodes.java.UnsafeCompareAndExchangeNode; import org.graalvm.compiler.nodes.java.UnsafeCompareAndSwapNode; import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.SideEffectFreeWriteNode; import org.graalvm.compiler.nodes.memory.WriteNode; @@ -235,6 +235,7 @@ public MetaAccessProvider getMetaAccess() { return metaAccess; } + @Override public BarrierSet getBarrierSet() { return barrierSet; } @@ -464,7 +465,7 @@ protected void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) { AddressNode address = createFieldAddress(graph, object, field); assert address != null : "Field that is loaded must not be eliminated: " + field.getDeclaringClass().toJavaName(true) + "." + field.getName(); - BarrierType barrierType = barrierSet.fieldLoadBarrierType(field, getStorageKind(field)); + BarrierType barrierType = barrierSet.fieldReadBarrierType(field, getStorageKind(field)); ReadNode memoryRead = graph.add(new ReadNode(address, overrideFieldLocationIdentity(loadField.getLocationIdentity()), loadStamp, barrierType, loadField.getMemoryOrder())); ValueNode readValue = implicitLoadConvert(graph, getStorageKind(field), memoryRead); loadField.replaceAtUsages(readValue); @@ -480,7 +481,7 @@ protected void lowerStoreFieldNode(StoreFieldNode storeField, LoweringTool tool) AddressNode address = createFieldAddress(graph, object, field); assert address != null; - BarrierType barrierType = barrierSet.fieldStoreBarrierType(field, getStorageKind(field)); + BarrierType barrierType = barrierSet.fieldWriteBarrierType(field, getStorageKind(field)); WriteNode memoryWrite = graph.add(new WriteNode(address, overrideFieldLocationIdentity(storeField.getLocationIdentity()), value, barrierType, storeField.getMemoryOrder())); memoryWrite.setStateAfter(storeField.stateAfter()); graph.replaceFixedWithFixed(storeField, memoryWrite); @@ -548,7 +549,8 @@ public void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool, ValueNode positiveIndex = createPositiveIndex(graph, index, boundsCheck); AddressNode address = createArrayAddress(graph, array, arrayBaseOffset, elementKind, positiveIndex); - ReadNode memoryRead = graph.add(new ReadNode(address, NamedLocationIdentity.getArrayLocation(elementKind), loadStamp, BarrierType.NONE, MemoryOrderMode.PLAIN)); + LocationIdentity arrayLocation = NamedLocationIdentity.getArrayLocation(elementKind); + ReadNode memoryRead = graph.add(new ReadNode(address, arrayLocation, loadStamp, barrierSet.readBarrierType(arrayLocation, address, loadStamp), MemoryOrderMode.PLAIN)); memoryRead.setGuard(boundsCheck); ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead); @@ -600,7 +602,7 @@ public void lowerStoreIndexedNode(StoreIndexedNode storeIndexed, LoweringTool to condition = null; } } - BarrierType barrierType = barrierSet.arrayStoreBarrierType(storageKind); + BarrierType barrierType = barrierSet.arrayWriteBarrierType(storageKind); ValueNode positiveIndex = createPositiveIndex(graph, storeIndexed.index(), boundsCheck); AddressNode address = createArrayAddress(graph, array, arrayBaseOffset, storageKind, positiveIndex); WriteNode memoryWrite = graph.add(new WriteNode(address, NamedLocationIdentity.getArrayLocation(storageKind), implicitStoreConvert(graph, storageKind, value), @@ -703,7 +705,7 @@ protected void lowerCompareAndSwapNode(UnsafeCompareAndSwapNode cas) { ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue()); AddressNode address = graph.unique(new OffsetAddressNode(cas.object(), cas.offset())); - BarrierType barrierType = barrierSet.guessStoreBarrierType(cas.object(), newValue); + BarrierType barrierType = barrierSet.guessReadWriteBarrier(cas.object(), newValue); LogicCompareAndSwapNode atomicNode = graph.add( new LogicCompareAndSwapNode(address, expectedValue, newValue, cas.getKilledLocationIdentity(), barrierType, cas.getMemoryOrder())); atomicNode.setStateAfter(cas.stateAfter()); @@ -718,7 +720,7 @@ protected void lowerCompareAndExchangeNode(UnsafeCompareAndExchangeNode cas) { ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue()); AddressNode address = graph.unique(new OffsetAddressNode(cas.object(), cas.offset())); - BarrierType barrierType = barrierSet.guessStoreBarrierType(cas.object(), newValue); + BarrierType barrierType = barrierSet.guessReadWriteBarrier(cas.object(), newValue); ValueCompareAndSwapNode atomicNode = graph.add( new ValueCompareAndSwapNode(address, expectedValue, newValue, cas.getKilledLocationIdentity(), barrierType, cas.getMemoryOrder())); ValueNode coercedNode = implicitLoadConvert(graph, valueKind, atomicNode, true); @@ -734,7 +736,7 @@ protected void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) { ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue()); AddressNode address = graph.unique(new OffsetAddressNode(n.object(), n.offset())); - BarrierType barrierType = barrierSet.guessStoreBarrierType(n.object(), newValue); + BarrierType barrierType = barrierSet.guessReadWriteBarrier(n.object(), newValue); LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(address, n.getKilledLocationIdentity(), newValue, barrierType)); memoryRead.setStateAfter(n.stateAfter()); @@ -751,8 +753,7 @@ protected void lowerAtomicReadAndAddNode(AtomicReadAndAddNode n) { ValueNode delta = implicitStoreConvert(graph, valueKind, n.delta()); AddressNode address = graph.unique(new OffsetAddressNode(n.object(), n.offset())); - BarrierType barrierType = barrierSet.guessStoreBarrierType(n.object(), delta); - LoweredAtomicReadAndAddNode memoryRead = graph.add(new LoweredAtomicReadAndAddNode(address, n.getKilledLocationIdentity(), delta, barrierType)); + LoweredAtomicReadAndAddNode memoryRead = graph.add(new LoweredAtomicReadAndAddNode(address, n.getKilledLocationIdentity(), delta)); memoryRead.setStateAfter(n.stateAfter()); ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead); @@ -800,7 +801,8 @@ protected ReadNode createUnsafeRead(StructuredGraph graph, RawLoadNode load, Gua JavaKind readKind = load.accessKind(); Stamp loadStamp = loadStamp(load.stamp(NodeView.DEFAULT), readKind, compressible); AddressNode address = createUnsafeAddress(graph, load.object(), load.offset()); - ReadNode memoryRead = graph.add(new ReadNode(address, load.getLocationIdentity(), loadStamp, barrierSet.readBarrierType(load), load.getMemoryOrder())); + LocationIdentity location = load.getLocationIdentity(); + ReadNode memoryRead = graph.add(new ReadNode(address, location, loadStamp, barrierSet.readBarrierType(location, address, loadStamp), load.getMemoryOrder())); if (guard == null) { // An unsafe read must not float otherwise it may float above // a test guaranteeing the read is safe. @@ -818,7 +820,8 @@ protected void lowerUnsafeMemoryLoadNode(UnsafeMemoryLoadNode load) { JavaKind readKind = load.getKind(); Stamp loadStamp = loadStamp(load.stamp(NodeView.DEFAULT), readKind, false); AddressNode address = graph.addOrUniqueWithInputs(OffsetAddressNode.create(load.getAddress())); - ReadNode memoryRead = graph.add(new ReadNode(address, load.getLocationIdentity(), loadStamp, BarrierType.NONE, MemoryOrderMode.PLAIN)); + LocationIdentity location = load.getLocationIdentity(); + ReadNode memoryRead = graph.add(new ReadNode(address, location, loadStamp, barrierSet.readBarrierType(location, address, loadStamp), MemoryOrderMode.PLAIN)); // An unsafe read must not float otherwise it may float above // a test guaranteeing the read is safe. memoryRead.setForceFixed(true); @@ -842,7 +845,7 @@ protected void lowerUnsafeStoreNode(RawStoreNode store) { 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, barrierSet.storeBarrierType(store), store.getMemoryOrder())); + WriteNode write = graph.add(new WriteNode(address, store.getLocationIdentity(), value, barrierSet.writeBarrierType(store), store.getMemoryOrder())); write.setStateAfter(store.stateAfter()); graph.replaceFixedWithFixed(store, write); } @@ -942,12 +945,12 @@ protected void lowerCommitAllocationNode(CommitAllocationNode commit, LoweringTo long offset = fieldOffset(field); if (offset >= 0) { address = createOffsetAddress(graph, newObject, offset); - barrierType = barrierSet.fieldStoreBarrierType(field, getStorageKind(field)); + barrierType = barrierSet.fieldWriteBarrierType(field, getStorageKind(field)); } } else { assert virtual instanceof VirtualArrayNode; address = createOffsetAddress(graph, newObject, metaAccess.getArrayBaseOffset(storageKind) + i * metaAccess.getArrayIndexScale(storageKind)); - barrierType = barrierSet.arrayStoreBarrierType(storageKind); + barrierType = barrierSet.arrayWriteBarrierType(storageKind); } if (address != null) { WriteNode write = new WriteNode(address, LocationIdentity.init(), arrayImplicitStoreConvert(graph, storageKind, value, commit, virtual, valuePos), barrierType, @@ -979,11 +982,11 @@ protected void lowerCommitAllocationNode(CommitAllocationNode commit, LoweringTo VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; ResolvedJavaField field = virtualInstance.field(i); address = createFieldAddress(graph, newObject, field); - barrierType = barrierSet.fieldStoreBarrierType(field, getStorageKind(field)); + barrierType = barrierSet.fieldWriteBarrierType(field, getStorageKind(field)); } else { assert virtual instanceof VirtualArrayNode; address = createArrayAddress(graph, newObject, virtual.entryKind(metaAccessExtensionProvider, i), ConstantNode.forInt(i, graph)); - barrierType = barrierSet.arrayStoreBarrierType(virtual.entryKind(metaAccessExtensionProvider, i)); + barrierType = barrierSet.arrayWriteBarrierType(virtual.entryKind(metaAccessExtensionProvider, i)); } if (address != null) { WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, JavaKind.Object, allocValue), barrierType, MemoryOrderMode.PLAIN); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java index c9610b8403af..ad193527de97 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java @@ -49,6 +49,7 @@ import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition; import org.graalvm.compiler.core.common.calc.UnsignedMath; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; @@ -154,7 +155,6 @@ import org.graalvm.compiler.nodes.java.RegisterFinalizerNode; import org.graalvm.compiler.nodes.java.UnsafeCompareAndExchangeNode; import org.graalvm.compiler.nodes.java.UnsafeCompareAndSwapNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.address.IndexAddressNode; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.Replacements; @@ -617,7 +617,6 @@ private static void registerUnsafePlugins(InvocationPlugins plugins, Replacement registerUnsafeAtomicsPlugins(jdkInternalMiscUnsafe, false, explicitUnsafeNullChecks, "compareAndExchange", supportedJavaKinds, ACQUIRE, RELEASE); supportedJavaKinds = new JavaKind[]{JavaKind.Boolean, JavaKind.Byte, JavaKind.Char, JavaKind.Short, JavaKind.Int, JavaKind.Long, JavaKind.Float, JavaKind.Double, JavaKind.Object}; - registerUnsafeAtomicsPlugins(jdkInternalMiscUnsafe, false, explicitUnsafeNullChecks, "compareAndSet", supportedJavaKinds, VOLATILE); registerUnsafeAtomicsPlugins(jdkInternalMiscUnsafe, false, explicitUnsafeNullChecks, "compareAndExchange", supportedJavaKinds, VOLATILE); @@ -738,7 +737,6 @@ private static void registerUnsafePlugins0(Registration r, boolean sunMiscUnsafe r.register(new UnsafeFencePlugin(MembarNode.FenceKind.FULL, "fullFence")); if (!sunMiscUnsafe) { - r.register(new UnsafeGetPlugin(JavaKind.Object, explicitUnsafeNullChecks, "getUncompressedObject", Receiver.class, long.class)); // These methods are only called if UnsafeConstants.DATA_CACHE_LINE_FLUSH_SIZE != 0 // which implies that the current processor and OS supports writeback to memory. r.register(new CacheWritebackPlugin(false, "writeback0", Receiver.class, long.class)); @@ -1169,7 +1167,7 @@ protected static void registerBoxingPlugins(InvocationPlugins plugins) { private static void registerObjectPlugins(InvocationPlugins plugins) { Registration r = new Registration(plugins, Object.class); - r.register(new InlineOnlyInvocationPlugin("", Receiver.class) { + r.register(new RequiredInlineOnlyInvocationPlugin("", Receiver.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { /* @@ -1265,7 +1263,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec return true; } }); - r.register(new InlineOnlyInvocationPlugin("cast", Receiver.class, Object.class) { + r.register(new InvocationPlugin("cast", Receiver.class, Object.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { b.genCheckcastDynamic(object, receiver.get()); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java index 57993eb24027..1e4d0d2bcd59 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java @@ -32,6 +32,7 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; @@ -48,7 +49,6 @@ import org.graalvm.compiler.nodes.gc.G1PostWriteBarrier; import org.graalvm.compiler.nodes.gc.G1PreWriteBarrier; import org.graalvm.compiler.nodes.gc.G1ReferentFieldReadBarrier; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.AddressNode.Address; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ZeroMemoryNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ZeroMemoryNode.java index 92863d5d1966..f93fa39fb0e8 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ZeroMemoryNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ZeroMemoryNode.java @@ -27,6 +27,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.InputType; diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.aarch64/src/org/graalvm/compiler/truffle/compiler/hotspot/aarch64/AArch64TruffleCallBoundaryInstrumentationFactory.java b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.aarch64/src/org/graalvm/compiler/truffle/compiler/hotspot/aarch64/AArch64TruffleCallBoundaryInstrumentationFactory.java new file mode 100644 index 000000000000..5147cd105857 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.aarch64/src/org/graalvm/compiler/truffle/compiler/hotspot/aarch64/AArch64TruffleCallBoundaryInstrumentationFactory.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.truffle.compiler.hotspot.aarch64; + +import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall; +import static jdk.vm.ci.meta.JavaKind.Object; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.Z_FIELD_BARRIER; + +import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister; +import org.graalvm.compiler.core.common.CompressEncoding; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotGraalRuntime; +import org.graalvm.compiler.hotspot.aarch64.AArch64HotSpotBackend; +import org.graalvm.compiler.hotspot.aarch64.AArch64HotSpotMove; +import org.graalvm.compiler.hotspot.aarch64.AArch64HotSpotZBarrierSetLIRGenerator; +import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; +import org.graalvm.compiler.lir.aarch64.AArch64FrameMap; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; +import org.graalvm.compiler.serviceprovider.ServiceProvider; +import org.graalvm.compiler.truffle.compiler.hotspot.TruffleCallBoundaryInstrumentationFactory; +import org.graalvm.compiler.truffle.compiler.hotspot.TruffleEntryPointDecorator; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.MetaAccessProvider; + +@ServiceProvider(TruffleCallBoundaryInstrumentationFactory.class) +public class AArch64TruffleCallBoundaryInstrumentationFactory extends TruffleCallBoundaryInstrumentationFactory { + + @Override + public EntryPointDecorator create(MetaAccessProvider metaAccess, GraalHotSpotVMConfig config, HotSpotRegistersProvider registers) { + return new TruffleEntryPointDecorator(metaAccess, config, registers) { + @Override + public void emitEntryPoint(CompilationResultBuilder crb) { + AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; + AArch64HotSpotBackend.emitInvalidatePlaceholder(crb, masm); + + try (ScratchRegister scratch = masm.getScratchRegister()) { + Register thisRegister = crb.codeCache.getRegisterConfig().getCallingConventionRegisters(JavaCall, Object).get(0); + Register spillRegister = scratch.getRegister(); + Label doProlog = new Label(); + if (config.useCompressedOops) { + CompressEncoding encoding = config.getOopEncoding(); + masm.ldr(32, spillRegister, AArch64Address.createImmediateAddress(32, AArch64Address.AddressingMode.IMMEDIATE_UNSIGNED_SCALED, thisRegister, installedCodeOffset)); + Register base = encoding.hasBase() ? registers.getHeapBaseRegister() : null; + AArch64HotSpotMove.UncompressPointer.emitUncompressCode(masm, spillRegister, spillRegister, base, encoding.getShift(), true); + } else { + AArch64Address address = AArch64Address.createImmediateAddress(64, AArch64Address.AddressingMode.IMMEDIATE_UNSIGNED_SCALED, thisRegister, installedCodeOffset); + masm.ldr(64, spillRegister, address); + if (config.gc == HotSpotGraalRuntime.HotSpotGC.Z) { + ForeignCallLinkage callTarget = crb.providers.getForeignCalls().lookupForeignCall(Z_FIELD_BARRIER); + AArch64FrameMap frameMap = (AArch64FrameMap) crb.frameMap; + AArch64HotSpotZBarrierSetLIRGenerator.emitBarrier(crb, masm, null, spillRegister, config, callTarget, address, null, frameMap); + } + } + masm.ldr(64, spillRegister, AArch64Address.createImmediateAddress(64, AArch64Address.AddressingMode.IMMEDIATE_UNSIGNED_SCALED, spillRegister, entryPointOffset)); + masm.cbz(64, spillRegister, doProlog); + masm.jmp(spillRegister); + masm.nop(); + masm.bind(doProlog); + } + } + }; + } + + @Override + public String getArchitecture() { + return "aarch64"; + } +} diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.aarch64/src/org/graalvm/compiler/truffle/compiler/hotspot/aarch64/AArch64TruffleCallBoundaryInstumentationFactory.java b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.aarch64/src/org/graalvm/compiler/truffle/compiler/hotspot/aarch64/AArch64TruffleCallBoundaryInstumentationFactory.java deleted file mode 100644 index db7c72e5155f..000000000000 --- a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.aarch64/src/org/graalvm/compiler/truffle/compiler/hotspot/aarch64/AArch64TruffleCallBoundaryInstumentationFactory.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.truffle.compiler.hotspot.aarch64; - -import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall; -import static jdk.vm.ci.meta.JavaKind.Object; - -import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.aarch64.AArch64Address; -import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; -import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister; -import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.core.common.CompressEncoding; -import org.graalvm.compiler.core.common.spi.CodeGenProviders; -import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.aarch64.AArch64HotSpotBackend; -import org.graalvm.compiler.hotspot.aarch64.AArch64HotSpotMove; -import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; -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.options.OptionValues; -import org.graalvm.compiler.serviceprovider.ServiceProvider; -import org.graalvm.compiler.truffle.compiler.hotspot.TruffleCallBoundaryInstrumentation; -import org.graalvm.compiler.truffle.compiler.hotspot.TruffleCallBoundaryInstrumentationFactory; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.meta.MetaAccessProvider; - -@ServiceProvider(TruffleCallBoundaryInstrumentationFactory.class) -public class AArch64TruffleCallBoundaryInstumentationFactory extends TruffleCallBoundaryInstrumentationFactory { - - @Override - public CompilationResultBuilderFactory create(MetaAccessProvider metaAccess, GraalHotSpotVMConfig config, HotSpotRegistersProvider registers) { - return new TruffleCompilationResultBuilderFactory(metaAccess, config, registers) { - @Override - public CompilationResultBuilder createBuilder(CodeGenProviders providers, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, - FrameContext frameContext, - OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister) { - return new TruffleCallBoundaryInstrumentation(providers, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult, config, registers) { - @Override - protected void injectTailCallCode(int installedCodeOffset, int entryPointOffset) { - AArch64MacroAssembler masm = (AArch64MacroAssembler) this.asm; - AArch64HotSpotBackend.emitInvalidatePlaceholder(this, masm); - - try (ScratchRegister scratch = masm.getScratchRegister()) { - Register thisRegister = codeCache.getRegisterConfig().getCallingConventionRegisters(JavaCall, Object).get(0); - Register spillRegister = scratch.getRegister(); - Label doProlog = new Label(); - if (config.useCompressedOops) { - CompressEncoding encoding = config.getOopEncoding(); - masm.ldr(32, spillRegister, AArch64Address.createImmediateAddress(32, AArch64Address.AddressingMode.IMMEDIATE_UNSIGNED_SCALED, thisRegister, installedCodeOffset)); - Register base = encoding.hasBase() ? registers.getHeapBaseRegister() : null; - AArch64HotSpotMove.UncompressPointer.emitUncompressCode(masm, spillRegister, spillRegister, base, encoding.getShift(), true); - } else { - masm.ldr(64, spillRegister, AArch64Address.createImmediateAddress(64, AArch64Address.AddressingMode.IMMEDIATE_UNSIGNED_SCALED, thisRegister, installedCodeOffset)); - } - masm.ldr(64, spillRegister, AArch64Address.createImmediateAddress(64, AArch64Address.AddressingMode.IMMEDIATE_UNSIGNED_SCALED, spillRegister, entryPointOffset)); - masm.cbz(64, spillRegister, doProlog); - masm.jmp(spillRegister); - masm.nop(); - masm.bind(doProlog); - } - } - }; - } - }; - } - - @Override - public String getArchitecture() { - return "aarch64"; - } -} diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.amd64/src/org/graalvm/compiler/truffle/compiler/hotspot/amd64/AMD64TruffleCallBoundaryInstrumentationFactory.java b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.amd64/src/org/graalvm/compiler/truffle/compiler/hotspot/amd64/AMD64TruffleCallBoundaryInstrumentationFactory.java index d71403f24d3c..cef853953ddb 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.amd64/src/org/graalvm/compiler/truffle/compiler/hotspot/amd64/AMD64TruffleCallBoundaryInstrumentationFactory.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot.amd64/src/org/graalvm/compiler/truffle/compiler/hotspot/amd64/AMD64TruffleCallBoundaryInstrumentationFactory.java @@ -25,29 +25,26 @@ package org.graalvm.compiler.truffle.compiler.hotspot.amd64; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall; +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.Z_FIELD_BARRIER; -import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; -import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompressEncoding; -import org.graalvm.compiler.core.common.spi.CodeGenProviders; -import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotGraalRuntime; import org.graalvm.compiler.hotspot.amd64.AMD64HotSpotBackend; +import org.graalvm.compiler.hotspot.amd64.AMD64HotSpotZBarrierSetLIRGenerator; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; +import org.graalvm.compiler.lir.amd64.AMD64FrameMap; import org.graalvm.compiler.lir.amd64.AMD64Move; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; -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.options.OptionValues; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; import org.graalvm.compiler.serviceprovider.ServiceProvider; -import org.graalvm.compiler.truffle.compiler.hotspot.TruffleCallBoundaryInstrumentation; import org.graalvm.compiler.truffle.compiler.hotspot.TruffleCallBoundaryInstrumentationFactory; +import org.graalvm.compiler.truffle.compiler.hotspot.TruffleEntryPointDecorator; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.code.Register; @@ -58,42 +55,40 @@ public class AMD64TruffleCallBoundaryInstrumentationFactory extends TruffleCallBoundaryInstrumentationFactory { @Override - public CompilationResultBuilderFactory create(MetaAccessProvider metaAccess, GraalHotSpotVMConfig config, HotSpotRegistersProvider registers) { - return new TruffleCompilationResultBuilderFactory(metaAccess, config, registers) { - + public EntryPointDecorator create(MetaAccessProvider metaAccess, GraalHotSpotVMConfig config, HotSpotRegistersProvider registers) { + return new TruffleEntryPointDecorator(metaAccess, config, registers) { @Override - public CompilationResultBuilder createBuilder(CodeGenProviders providers, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, - FrameContext frameContext, - OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister) { - return new TruffleCallBoundaryInstrumentation(providers, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult, config, registers) { - @Override - protected void injectTailCallCode(int installedCodeOffset, int entryPointOffset) { - AMD64MacroAssembler masm = (AMD64MacroAssembler) this.asm; - Register thisRegister = codeCache.getRegisterConfig().getCallingConventionRegisters(JavaCall, JavaKind.Object).get(0); - Register spillRegister = AMD64.r10; - Label doProlog = new Label(); - int pos = masm.position(); + public void emitEntryPoint(CompilationResultBuilder crb) { + AMD64MacroAssembler masm = (AMD64MacroAssembler) crb.asm; + Register thisRegister = crb.codeCache.getRegisterConfig().getCallingConventionRegisters(JavaCall, JavaKind.Object).get(0); + Register spillRegister = AMD64.r10; + Label doProlog = new Label(); + int pos = masm.position(); - if (config.useCompressedOops) { - // First instruction must be at least 5 bytes long to be safe for - // patching - masm.movl(spillRegister, new AMD64Address(thisRegister, installedCodeOffset), true); - assert masm.position() - pos >= AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE; - CompressEncoding encoding = config.getOopEncoding(); - Register heapBaseRegister = AMD64Move.UncompressPointerOp.hasBase(encoding) ? registers.getHeapBaseRegister() : Register.None; - AMD64Move.UncompressPointerOp.emitUncompressCode(masm, spillRegister, encoding.getShift(), heapBaseRegister, true); - } else { - // First instruction must be at least 5 bytes long to be safe for - // patching - masm.movq(spillRegister, new AMD64Address(thisRegister, installedCodeOffset), true); - assert masm.position() - pos >= AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE; - } - masm.movq(spillRegister, new AMD64Address(spillRegister, entryPointOffset)); - masm.testqAndJcc(spillRegister, spillRegister, ConditionFlag.Equal, doProlog, true); - masm.jmp(spillRegister); - masm.bind(doProlog); + AMD64Address address = new AMD64Address(thisRegister, installedCodeOffset); + if (config.useCompressedOops) { + // First instruction must be at least 5 bytes long to be safe for + // patching + masm.movl(spillRegister, address, true); + assert masm.position() - pos >= AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE; + CompressEncoding encoding = config.getOopEncoding(); + Register heapBaseRegister = AMD64Move.UncompressPointerOp.hasBase(encoding) ? registers.getHeapBaseRegister() : Register.None; + AMD64Move.UncompressPointerOp.emitUncompressCode(masm, spillRegister, encoding.getShift(), heapBaseRegister, true); + } else { + // First instruction must be at least 5 bytes long to be safe for + // patching + masm.movq(spillRegister, address, true); + assert masm.position() - pos >= AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE; + if (config.gc == HotSpotGraalRuntime.HotSpotGC.Z) { + ForeignCallLinkage callTarget = crb.providers.getForeignCalls().lookupForeignCall(Z_FIELD_BARRIER); + AMD64FrameMap frameMap = (AMD64FrameMap) crb.frameMap; + AMD64HotSpotZBarrierSetLIRGenerator.emitBarrier(crb, masm, null, spillRegister, config, callTarget, address, null, frameMap); } - }; + } + masm.movq(spillRegister, new AMD64Address(spillRegister, entryPointOffset)); + masm.testqAndJcc(spillRegister, spillRegister, ConditionFlag.Equal, doProlog, true); + masm.jmp(spillRegister); + masm.bind(doProlog); } }; } diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/HotSpotTruffleCompilerImpl.java b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/HotSpotTruffleCompilerImpl.java index b1d797069c90..2c74e078bcd8 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/HotSpotTruffleCompilerImpl.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/HotSpotTruffleCompilerImpl.java @@ -56,6 +56,7 @@ import org.graalvm.compiler.hotspot.HotSpotGraalServices; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -215,14 +216,14 @@ public void installTruffleCallBoundaryMethod(ResolvedJavaMethod method) { }); } - private CompilationResultBuilderFactory getTruffleCallBoundaryInstrumentationFactory(String arch) { + private EntryPointDecorator getTruffleCallBoundaryInstrumentationFactory(String arch) { for (TruffleCallBoundaryInstrumentationFactory factory : GraalServices.load(TruffleCallBoundaryInstrumentationFactory.class)) { if (factory.getArchitecture().equals(arch)) { return factory.create(config.lastTier().providers().getMetaAccess(), hotspotGraalRuntime.getVMConfig(), hotspotGraalRuntime.getHostProviders().getRegisters()); } } // No specialization of OptimizedCallTarget on this platform. - return CompilationResultBuilderFactory.Default; + return null; } /** @@ -238,7 +239,7 @@ public void installTruffleReservedOopMethod(ResolvedJavaMethod method) { compileAndInstallStub(method, (debug, javaMethod, compilationId) -> { InvocationPlugins p = new InvocationPlugins(); HotSpotTruffleGraphBuilderPlugins.registerHotspotThreadLocalStubPlugins(p, config.lastTier().providers().getWordTypes(), hotspotGraalRuntime.getVMConfig().jvmciReservedReference0Offset); - return compileTruffleStub(debug, javaMethod, compilationId, CompilationResultBuilderFactory.Default, p); + return compileTruffleStub(debug, javaMethod, compilationId, null, p); }); } @@ -274,8 +275,7 @@ private void compileAndInstallStub(ResolvedJavaMethod method, StubCompilation co * stubs do not perform any inlining and resolve classes eagerly. */ private CompilationResult compileTruffleStub(DebugContext debug, ResolvedJavaMethod javaMethod, CompilationIdentifier compilationId, - CompilationResultBuilderFactory resultFactory, - InvocationPlugins plugins) { + EntryPointDecorator resultFactory, InvocationPlugins plugins) { TruffleTierConfiguration tier = config.lastTier(); Suites newSuites = config.hostSuite().copy(); removeInliningPhases(newSuites); @@ -301,7 +301,7 @@ private CompilationResult compileTruffleStub(DebugContext debug, ResolvedJavaMet PhaseSuite graphBuilderSuite = getGraphBuilderSuite(codeCache, backend.getSuites()); return compileGraph(graph, javaMethod, lastTierProviders, backend, graphBuilderSuite, OptimisticOptimizations.ALL, graph.getProfilingInfo(), newSuites, tier.lirSuites(), - new CompilationResult(compilationId), resultFactory, false); + new CompilationResult(compilationId), CompilationResultBuilderFactory.Default, resultFactory, false); } @Override diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/TruffleCallBoundaryInstrumentation.java b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/TruffleCallBoundaryInstrumentation.java deleted file mode 100644 index bea7224dfe8e..000000000000 --- a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/TruffleCallBoundaryInstrumentation.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.truffle.compiler.hotspot; - -import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.core.common.spi.CodeGenProviders; -import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotMarkId; -import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -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.options.OptionValues; -import org.graalvm.compiler.truffle.common.TruffleCompilerRuntime; - -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.code.Register; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaType; - -/** - * Mechanism for injecting special code into - * {@linkplain HotSpotTruffleCompilerImpl#installTruffleCallBoundaryMethod(jdk.vm.ci.meta.ResolvedJavaMethod) - * call boundary methods}. - */ -public abstract class TruffleCallBoundaryInstrumentation extends CompilationResultBuilder { - protected final GraalHotSpotVMConfig config; - protected final HotSpotRegistersProvider registers; - protected final MetaAccessProvider metaAccess; - - public TruffleCallBoundaryInstrumentation(CodeGenProviders providers, - FrameMap frameMap, - Assembler asm, - DataBuilder dataBuilder, - FrameContext frameContext, - OptionValues options, - DebugContext debug, - CompilationResult compilationResult, - GraalHotSpotVMConfig config, - HotSpotRegistersProvider registers) { - super(providers, - frameMap, - asm, - dataBuilder, - frameContext, - options, - debug, - compilationResult, - Register.None, - null, - CompilationResultBuilder.NO_VERIFIERS); - this.metaAccess = providers.getMetaAccess(); - this.config = config; - this.registers = registers; - } - - @Override - public CompilationResult.CodeMark recordMark(CompilationResult.MarkId id) { - CompilationResult.CodeMark mark = super.recordMark(id); - if (id == HotSpotMarkId.VERIFIED_ENTRY) { - ResolvedJavaType optimizedCallTargetType = TruffleCompilerRuntime.getRuntime().resolveType(metaAccess, "org.graalvm.compiler.truffle.runtime.hotspot.HotSpotOptimizedCallTarget"); - int installedCodeOffset = getFieldOffset("installedCode", optimizedCallTargetType); - int entryPointOffset = getFieldOffset("entryPoint", TruffleCompilerRuntime.getRuntime().resolveType(metaAccess, InstalledCode.class.getName())); - injectTailCallCode(installedCodeOffset, entryPointOffset); - } - return mark; - } - - private static int getFieldOffset(String name, ResolvedJavaType declaringType) { - for (ResolvedJavaField field : declaringType.getInstanceFields(false)) { - if (field.getName().equals(name)) { - return field.getOffset(); - } - } - throw new NoSuchFieldError(declaringType.toJavaName() + "." + name); - } - - /** - * Injects code into the verified entry point of that makes a tail-call to the target callee. - * - * @param entryPointOffset offset of the field {@code HotSpotOptimizedCallTarget.installedCode} - * @param installedCodeOffset offset of the field {@code InstalledCode.entryPoint} - */ - protected abstract void injectTailCallCode(int installedCodeOffset, int entryPointOffset); -} diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/TruffleCallBoundaryInstrumentationFactory.java b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/TruffleCallBoundaryInstrumentationFactory.java index d70ce53d9d92..5f6f50aff876 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/TruffleCallBoundaryInstrumentationFactory.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/TruffleCallBoundaryInstrumentationFactory.java @@ -27,7 +27,7 @@ import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; import jdk.vm.ci.meta.MetaAccessProvider; @@ -49,19 +49,7 @@ */ public abstract class TruffleCallBoundaryInstrumentationFactory { - public abstract static class TruffleCompilationResultBuilderFactory implements CompilationResultBuilderFactory { - protected MetaAccessProvider metaAccess; - protected GraalHotSpotVMConfig config; - protected HotSpotRegistersProvider registers; - - public TruffleCompilationResultBuilderFactory(MetaAccessProvider metaAccess, GraalHotSpotVMConfig config, HotSpotRegistersProvider registers) { - this.metaAccess = metaAccess; - this.config = config; - this.registers = registers; - } - } - - public abstract CompilationResultBuilderFactory create(MetaAccessProvider metaAccess, GraalHotSpotVMConfig config, HotSpotRegistersProvider registers); + public abstract EntryPointDecorator create(MetaAccessProvider metaAccess, GraalHotSpotVMConfig config, HotSpotRegistersProvider registers); /** * Gets the architecture supported by this factory. diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/TruffleEntryPointDecorator.java b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/TruffleEntryPointDecorator.java new file mode 100644 index 000000000000..e68e11eaed11 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.truffle.compiler.hotspot/src/org/graalvm/compiler/truffle/compiler/hotspot/TruffleEntryPointDecorator.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.truffle.compiler.hotspot; + +import static org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.Z_FIELD_BARRIER; + +import org.graalvm.compiler.core.common.spi.CodeGenProviders; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotGraalRuntime; +import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; +import org.graalvm.compiler.lir.gen.LIRGenerationResult; +import org.graalvm.compiler.truffle.common.TruffleCompilerRuntime; + +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaType; + +/** + * Mechanism for injecting special code into + * {@linkplain HotSpotTruffleCompilerImpl#installTruffleCallBoundaryMethod(jdk.vm.ci.meta.ResolvedJavaMethod) + * call boundary methods}. + */ +public abstract class TruffleEntryPointDecorator implements EntryPointDecorator { + + protected MetaAccessProvider metaAccess; + protected GraalHotSpotVMConfig config; + protected HotSpotRegistersProvider registers; + protected final int installedCodeOffset; + protected final int entryPointOffset; + + public TruffleEntryPointDecorator(MetaAccessProvider metaAccess, GraalHotSpotVMConfig config, HotSpotRegistersProvider registers) { + this.metaAccess = metaAccess; + this.config = config; + this.registers = registers; + ResolvedJavaType optimizedCallTargetType = TruffleCompilerRuntime.getRuntime().resolveType(metaAccess, "org.graalvm.compiler.truffle.runtime.hotspot.HotSpotOptimizedCallTarget"); + installedCodeOffset = getFieldOffset("installedCode", optimizedCallTargetType); + entryPointOffset = getFieldOffset("entryPoint", TruffleCompilerRuntime.getRuntime().resolveType(metaAccess, InstalledCode.class.getName())); + } + + private static int getFieldOffset(String name, ResolvedJavaType declaringType) { + for (ResolvedJavaField field : declaringType.getInstanceFields(false)) { + if (field.getName().equals(name)) { + return field.getOffset(); + } + } + throw new NoSuchFieldError(declaringType.toJavaName() + "." + name); + } + + @Override + public void initialize(CodeGenProviders providers, LIRGenerationResult lirGenRes) { + if (config.gc == HotSpotGraalRuntime.HotSpotGC.Z) { + ForeignCallLinkage callTarget = providers.getForeignCalls().lookupForeignCall(Z_FIELD_BARRIER); + lirGenRes.getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention()); + } + } +} diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/TruffleCompilationResultBuilderFactory.java b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/TruffleCompilationResultBuilderFactory.java deleted file mode 100644 index eeccb970bea3..000000000000 --- a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/TruffleCompilationResultBuilderFactory.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2015, 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 org.graalvm.compiler.truffle.compiler; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.core.common.spi.CodeGenProviders; -import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; -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.nodes.StructuredGraph; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.truffle.compiler.nodes.TruffleAssumption; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.meta.Assumptions.Assumption; - -/** - * A mechanism for Truffle to update a {@link CompilationResult} before it is - * {@linkplain CompilationResult#close(OptionValues) closed} by the compiler. - */ -class TruffleCompilationResultBuilderFactory implements CompilationResultBuilderFactory { - - /** - * The graph being compiled. - */ - private final StructuredGraph graph; - - /** - * List into which {@link TruffleAssumption}s are added. - */ - private final List validAssumptions; - - TruffleCompilationResultBuilderFactory(StructuredGraph graph, List validAssumptions) { - this.graph = graph; - this.validAssumptions = validAssumptions; - } - - @Override - public CompilationResultBuilder createBuilder(CodeGenProviders providers, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext, - OptionValues options, DebugContext debug, CompilationResult compilationResult, Register uncompressedNullRegister) { - return new CompilationResultBuilder(providers, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult, uncompressedNullRegister) { - @Override - protected void closeCompilationResult() { - CompilationResult result = this.compilationResult; - result.setMethods(graph.method(), graph.getMethods()); - result.setSpeculationLog(graph.getSpeculationLog()); - result.setBytecodeSize(graph.getBytecodeSize()); - - Set newAssumptions = new HashSet<>(); - for (Assumption assumption : graph.getAssumptions()) { - TruffleCompilationResultBuilderFactory.processAssumption(newAssumptions, assumption, validAssumptions); - } - - if (result.getAssumptions() != null) { - for (Assumption assumption : result.getAssumptions()) { - TruffleCompilationResultBuilderFactory.processAssumption(newAssumptions, assumption, validAssumptions); - } - } - - result.setAssumptions(newAssumptions.toArray(new Assumption[newAssumptions.size()])); - super.closeCompilationResult(); - } - }; - } - - static void processAssumption(Set newAssumptions, Assumption assumption, List manual) { - if (assumption != null) { - if (assumption instanceof TruffleAssumption) { - TruffleAssumption assumptionValidAssumption = (TruffleAssumption) assumption; - manual.add(assumptionValidAssumption); - } else { - newAssumptions.add(assumption); - } - } - } -} diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PartialEvaluationTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PartialEvaluationTest.java index 265b5e4f128b..d0bf0808dafe 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PartialEvaluationTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/PartialEvaluationTest.java @@ -52,12 +52,14 @@ import org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl; import org.graalvm.compiler.truffle.compiler.TruffleTierContext; import org.graalvm.compiler.truffle.compiler.phases.TruffleTier; +import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; import org.graalvm.compiler.truffle.runtime.TruffleInlining; import org.junit.Assert; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ControlFlowException; import com.oracle.truffle.api.nodes.RootNode; @@ -107,6 +109,11 @@ protected OptimizedCallTarget compileHelper(String methodName, RootNode root, Ob newTask(), null); this.lastCompiledGraph = graph; + + // Ensure the invoke stub is installed + GraalTruffleRuntime runtime = (GraalTruffleRuntime) Truffle.getRuntime(); + runtime.bypassedInstalledCode(compilable); + return compilable; } diff --git a/compiler/src/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java b/compiler/src/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java index 6a8ae59d32c1..064ad1e8446e 100644 --- a/compiler/src/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java +++ b/compiler/src/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.calc.UnsignedMath; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; @@ -46,7 +47,6 @@ import org.graalvm.compiler.nodes.calc.UnsignedRemNode; import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; import org.graalvm.compiler.nodes.calc.XorNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.address.AddressNode.Address; import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; import org.graalvm.word.ComparableWord; diff --git a/compiler/src/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java b/compiler/src/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java index 4ce36dc85b45..759fe11a3afa 100644 --- a/compiler/src/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java +++ b/compiler/src/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -57,6 +58,7 @@ import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.JavaReadNode; import org.graalvm.compiler.nodes.extended.JavaWriteNode; +import org.graalvm.compiler.nodes.gc.BarrierSet; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderTool; import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; @@ -68,7 +70,6 @@ import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; import org.graalvm.compiler.nodes.java.StoreIndexedNode; import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.type.StampTool; @@ -92,12 +93,15 @@ public class WordOperationPlugin implements NodePlugin, TypePlugin, InlineInvokePlugin { protected final WordTypes wordTypes; protected final JavaKind wordKind; + private final BarrierSet barrierSet; protected final SnippetReflectionProvider snippetReflection; - public WordOperationPlugin(SnippetReflectionProvider snippetReflection, WordTypes wordTypes) { + public WordOperationPlugin(SnippetReflectionProvider snippetReflection, WordTypes wordTypes, BarrierSet barrierSet) { this.snippetReflection = snippetReflection; this.wordTypes = wordTypes; this.wordKind = wordTypes.getWordKind(); + this.barrierSet = barrierSet; + assert barrierSet != null; } @Override @@ -476,7 +480,7 @@ private ValueNode comparisonOp(GraphBuilderContext graph, Condition condition, V protected ValueNode readOp(GraphBuilderContext b, JavaKind readKind, AddressNode address, LocationIdentity location, Opcode op) { assert op == Opcode.READ_POINTER || op == Opcode.READ_OBJECT || op == Opcode.READ_BARRIERED; - final BarrierType barrier = (op == Opcode.READ_BARRIERED ? BarrierType.UNKNOWN : BarrierType.NONE); + final BarrierType barrier = (op == Opcode.READ_BARRIERED && readKind.isObject() ? barrierSet.readBarrierType(location, address, null) : BarrierType.NONE); final boolean compressible = (op == Opcode.READ_OBJECT || op == Opcode.READ_BARRIERED); return readOp(b, readKind, address, location, barrier, compressible); @@ -494,7 +498,7 @@ public static ValueNode readOp(GraphBuilderContext b, JavaKind readKind, Address protected ValueNode readVolatileOp(GraphBuilderContext b, JavaKind readKind, AddressNode address, LocationIdentity location, Opcode op) { assert op == Opcode.READ_POINTER_VOLATILE || op == Opcode.READ_BARRIERED_VOLATILE; - final BarrierType barrier = op == Opcode.READ_BARRIERED_VOLATILE ? BarrierType.UNKNOWN : BarrierType.NONE; + final BarrierType barrier = op == Opcode.READ_BARRIERED_VOLATILE && readKind.isObject() ? barrierSet.readBarrierType(location, address, null) : BarrierType.NONE; final boolean compressible = op == Opcode.READ_BARRIERED_VOLATILE; /* * A JavaOrderedReadNode is lowered to an OrderedReadNode that will not float. This means it diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/SubstrateCardTableBarrierSet.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/SubstrateCardTableBarrierSet.java index 92d2206869b0..ed669a55204c 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/SubstrateCardTableBarrierSet.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/SubstrateCardTableBarrierSet.java @@ -24,8 +24,8 @@ */ package com.oracle.svm.core.genscavenge.graal; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.nodes.gc.CardTableBarrierSet; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import com.oracle.svm.core.StaticFieldsSupport; @@ -44,10 +44,10 @@ public SubstrateCardTableBarrierSet(ResolvedJavaType objectArrayType) { } @Override - public BarrierType fieldStoreBarrierType(ResolvedJavaField field, JavaKind storageKind) { + public BarrierType fieldWriteBarrierType(ResolvedJavaField field, JavaKind storageKind) { if (field.isStatic() && storageKind == JavaKind.Object) { - return arrayStoreBarrierType(storageKind); + return arrayWriteBarrierType(storageKind); } - return super.fieldStoreBarrierType(field, storageKind); + return super.fieldWriteBarrierType(field, storageKind); } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/SubstrateNoBarrierSet.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/SubstrateNoBarrierSet.java index 39bd82093cca..71e8230ff64c 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/SubstrateNoBarrierSet.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/SubstrateNoBarrierSet.java @@ -24,12 +24,13 @@ */ package com.oracle.svm.core.genscavenge.graal; +import org.graalvm.compiler.core.common.memory.BarrierType; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.gc.BarrierSet; import org.graalvm.compiler.nodes.memory.FixedAccessNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaField; @@ -38,38 +39,48 @@ * A {@link BarrierSet} that does not emit any read or write barriers. */ public class SubstrateNoBarrierSet implements BarrierSet { + @Override + public boolean hasWriteBarrier() { + return false; + } + + @Override + public boolean hasReadBarrier() { + return false; + } + @Override public void addBarriers(FixedAccessNode n) { // Nothing to do. } @Override - public BarrierType fieldLoadBarrierType(ResolvedJavaField field, JavaKind storageKind) { + public BarrierType fieldReadBarrierType(ResolvedJavaField field, JavaKind storageKind) { return BarrierType.NONE; } @Override - public BarrierType fieldStoreBarrierType(ResolvedJavaField field, JavaKind storageKind) { + public BarrierType fieldWriteBarrierType(ResolvedJavaField field, JavaKind storageKind) { return BarrierType.NONE; } @Override - public BarrierType readBarrierType(RawLoadNode load) { + public BarrierType readBarrierType(LocationIdentity location, ValueNode address, Stamp loadStamp) { return BarrierType.NONE; } @Override - public BarrierType storeBarrierType(RawStoreNode store) { + public BarrierType writeBarrierType(RawStoreNode store) { return BarrierType.NONE; } @Override - public BarrierType arrayStoreBarrierType(JavaKind storageKind) { + public BarrierType arrayWriteBarrierType(JavaKind storageKind) { return BarrierType.NONE; } @Override - public BarrierType guessStoreBarrierType(ValueNode object, ValueNode value) { + public BarrierType guessReadWriteBarrier(ValueNode object, ValueNode value) { return BarrierType.NONE; } diff --git a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java index 2308224d1a45..5265faea3326 100755 --- a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java +++ b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java @@ -88,6 +88,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.asm.DataBuilder; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; import org.graalvm.compiler.lir.asm.FrameContext; import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; @@ -488,7 +489,7 @@ public SharedMethod getMethod() { protected class SubstrateAArch64LIRGenerator extends AArch64LIRGenerator implements SubstrateLIRGenerator { public SubstrateAArch64LIRGenerator(LIRKindTool lirKindTool, AArch64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, Providers providers, LIRGenerationResult lirGenRes) { - super(lirKindTool, arithmeticLIRGen, moveFactory, providers, lirGenRes); + super(lirKindTool, arithmeticLIRGen, null, moveFactory, providers, lirGenRes); } @Override @@ -1164,7 +1165,7 @@ public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult DebugContext debug = lir.getDebug(); Register uncompressedNullRegister = useLinearPointerCompression() ? ReservedRegisters.singleton().getHeapBaseRegister() : Register.None; CompilationResultBuilder crb = factory.createBuilder(getProviders(), lirGenResult.getFrameMap(), masm, dataBuilder, frameContext, options, debug, compilationResult, - uncompressedNullRegister); + uncompressedNullRegister, lir); crb.setTotalFrameSize(lirGenResult.getFrameMap().totalFrameSize()); return crb; } @@ -1257,18 +1258,17 @@ protected CompiledCode createCompiledCode(ResolvedJavaMethod method, Compilation } @Override - public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) { + public void emitCode(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, EntryPointDecorator entryPointDecorator) { try { - crb.buildLabelOffsets(lir); - crb.emit(lir); + crb.buildLabelOffsets(); + crb.emitLIR(); } catch (BranchTargetOutOfBoundsException e) { // A branch estimation was wrong, now retry with conservative label ranges, this // should always work resetForEmittingCode(crb); crb.setConservativeLabelRanges(); crb.resetForEmittingCode(); - lir.resetLabels(); - crb.emit(lir); + crb.emitLIR(); } } diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java index 647f9e263952..91f9ceec414b 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java @@ -27,7 +27,6 @@ import static com.oracle.svm.core.graal.code.SubstrateBackend.SubstrateMarkId.PROLOGUE_DECD_RSP; import static com.oracle.svm.core.graal.code.SubstrateBackend.SubstrateMarkId.PROLOGUE_END; import static com.oracle.svm.core.util.VMError.shouldNotReachHere; -import static com.oracle.svm.core.util.VMError.unimplemented; import static jdk.vm.ci.amd64.AMD64.rax; import static jdk.vm.ci.amd64.AMD64.rbp; import static jdk.vm.ci.amd64.AMD64.rsp; @@ -95,6 +94,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.asm.DataBuilder; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; import org.graalvm.compiler.lir.asm.FrameContext; import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; @@ -121,7 +121,7 @@ import org.graalvm.compiler.nodes.spi.NodeValueMap; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; -import org.graalvm.compiler.phases.common.AddressLoweringPhase; +import org.graalvm.compiler.phases.common.AddressLoweringByNodePhase; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.amd64.AMD64IntrinsicStubs; import org.graalvm.nativeimage.AnnotationAccess; @@ -560,7 +560,7 @@ private void vzeroupperBeforeCall(SubstrateAMD64LIRGenerator gen, Value[] argume protected class SubstrateAMD64LIRGenerator extends AMD64LIRGenerator implements SubstrateLIRGenerator { public SubstrateAMD64LIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, Providers providers, LIRGenerationResult lirGenRes) { - super(lirKindTool, arithmeticLIRGen, moveFactory, providers, lirGenRes); + super(lirKindTool, arithmeticLIRGen, null, moveFactory, providers, lirGenRes); } @Override @@ -653,11 +653,6 @@ public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFr throw shouldNotReachHere("Substrate VM does not use deoptimization"); } - @Override - public void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args, int numberOfFloatingPointArguments) { - throw unimplemented(); - } - @Override public void emitVerificationMarker(Object marker) { append(new VerificationMarkerOp(marker)); @@ -1410,7 +1405,7 @@ public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult DebugContext debug = lir.getDebug(); Register uncompressedNullRegister = useLinearPointerCompression() ? ReservedRegisters.singleton().getHeapBaseRegister() : Register.None; CompilationResultBuilder tasm = factory.createBuilder(getProviders(), lirGenResult.getFrameMap(), masm, dataBuilder, frameContext, options, debug, compilationResult, - uncompressedNullRegister); + uncompressedNullRegister, lir); tasm.setTotalFrameSize(lirGenResult.getFrameMap().totalFrameSize()); return tasm; } @@ -1422,7 +1417,7 @@ protected FrameContext createFrameContext(SharedMethod method, CallingConvention @Override public BasePhase newAddressLoweringPhase(CodeCacheProvider codeCache) { CompressEncoding compressEncoding = ImageSingletons.lookup(CompressEncoding.class); - return new AddressLoweringPhase(new SubstrateAMD64AddressLowering(compressEncoding)); + return new AddressLoweringByNodePhase(new SubstrateAMD64AddressLowering(compressEncoding)); } @Override @@ -1431,8 +1426,8 @@ public CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationReq } @Override - public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) { - crb.emit(lir); + public void emitCode(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, EntryPointDecorator entryPointDecorator) { + crb.emitLIR(); } @Override diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java index 4e18ac73522c..09cf1cae3ed9 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java @@ -51,6 +51,7 @@ import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.calc.FloatConvert; import org.graalvm.compiler.core.common.cfg.BasicBlock; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryExtendKind; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.spi.CodeGenProviders; @@ -70,6 +71,7 @@ import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; +import org.graalvm.compiler.lir.gen.BarrierSetLIRGeneratorTool; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.lir.gen.MoveFactory; @@ -195,6 +197,11 @@ public class LLVMGenerator implements LIRGeneratorTool, SubstrateLIRGenerator { addMainFunction(method); } + @Override + public BarrierSetLIRGeneratorTool getBarrierSet() { + return null; + } + @Override public CodeGenProviders getProviders() { return providers; @@ -688,7 +695,7 @@ public void emitMembar(int barriers) { } @Override - public Value emitAtomicReadAndWrite(LIRKind accessKind, Value address, Value newValue) { + public Value emitAtomicReadAndWrite(LIRKind accessKind, Value address, Value newValue, BarrierType barrierType) { LLVMValueRef atomicRMW = builder.buildAtomicXchg(getVal(address), getVal(newValue)); return new LLVMVariable(atomicRMW); } @@ -700,14 +707,15 @@ public Value emitAtomicReadAndAdd(LIRKind accessKind, Value address, Value delta } @Override - public Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue, MemoryOrderMode memoryOrder) { + public Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue, MemoryOrderMode memoryOrder, + BarrierType barrierType) { LLVMValueRef success = buildCmpxchg(getVal(address), getVal(expectedValue), getVal(newValue), memoryOrder, false); LLVMValueRef result = builder.buildSelect(success, getVal(trueValue), getVal(falseValue)); return new LLVMVariable(result); } @Override - public Value emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, MemoryOrderMode memoryOrder) { + public Value emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, MemoryOrderMode memoryOrder, BarrierType barrierType) { LLVMValueRef result = buildCmpxchg(getVal(address), getVal(expectedValue), getVal(newValue), memoryOrder, true); return new LLVMVariable(result); } diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMBackend.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMBackend.java index 681fd956be9a..534e9c0a6cf1 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMBackend.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMBackend.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; +import org.graalvm.compiler.lir.asm.EntryPointDecorator; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.GraphState.StageFlag; import org.graalvm.compiler.nodes.StructuredGraph; @@ -43,7 +44,7 @@ import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; -import org.graalvm.compiler.phases.common.AddressLoweringPhase; +import org.graalvm.compiler.phases.common.AddressLoweringByNodePhase; import org.graalvm.compiler.phases.util.Providers; import com.oracle.svm.core.graal.code.SubstrateBackend; @@ -72,7 +73,7 @@ public SubstrateLLVMBackend(Providers providers) { @Override public BasePhase newAddressLoweringPhase(CodeCacheProvider codeCache) { - return new AddressLoweringPhase(new LLVMAddressLowering()); + return new AddressLoweringByNodePhase(new LLVMAddressLowering()); } @Override @@ -98,7 +99,7 @@ protected CompiledCode createCompiledCode(ResolvedJavaMethod method, Compilation @Override @SuppressWarnings("try") public void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, CompilationResult result, CompilationResultBuilderFactory factory, - RegisterConfig config, LIRSuites lirSuites) { + EntryPointDecorator entryPointDecorator, RegisterConfig config, LIRSuites lirSuites) { DebugContext debug = graph.getDebug(); try (DebugContext.Scope s = debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start(debug)) { emitLLVM(graph, result); diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/lowering/LLVMAddressLowering.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/lowering/LLVMAddressLowering.java index 45fccc0b49dc..f02fdc496e3f 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/lowering/LLVMAddressLowering.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/lowering/LLVMAddressLowering.java @@ -33,12 +33,12 @@ import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.phases.common.AddressLoweringPhase; +import org.graalvm.compiler.phases.common.AddressLoweringByNodePhase; import jdk.vm.ci.meta.Value; import jdk.vm.ci.meta.ValueKind; -public class LLVMAddressLowering extends AddressLoweringPhase.AddressLowering { +public class LLVMAddressLowering extends AddressLoweringByNodePhase.AddressLowering { @Override public AddressNode lower(ValueNode base, ValueNode offset) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateBackend.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateBackend.java index 763033c69920..f002b5e5e98f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateBackend.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateBackend.java @@ -82,11 +82,6 @@ public enum SubstrateMarkId implements CompilationResult.MarkId { public String getName() { return name(); } - - @Override - public boolean isMarkAfter() { - return isMarkAfter; - } } private RuntimeConfiguration runtimeConfiguration; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstratePlatformConfigurationProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstratePlatformConfigurationProvider.java index a7776f89be58..9b178ea0177d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstratePlatformConfigurationProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstratePlatformConfigurationProvider.java @@ -32,6 +32,7 @@ public class SubstratePlatformConfigurationProvider implements PlatformConfigura private final BarrierSet barrierSet; public SubstratePlatformConfigurationProvider(BarrierSet barrierSet) { + assert barrierSet != null; this.barrierSet = barrierSet; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java index 6136cdeefe11..7ab5ed7f986f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateBasicLoweringProvider.java @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.Map; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider; @@ -52,7 +53,6 @@ import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; import org.graalvm.compiler.nodes.memory.FloatingReadNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/CInterfaceReadNode.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/CInterfaceReadNode.java index 0a3116a3c22e..f96fca1a8c2e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/CInterfaceReadNode.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/CInterfaceReadNode.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.graal.nodes; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/CInterfaceWriteNode.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/CInterfaceWriteNode.java index cb0329e5807b..a85d647b4ab0 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/CInterfaceWriteNode.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/CInterfaceWriteNode.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.graal.nodes; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/NonSnippetLowerings.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/NonSnippetLowerings.java index 2ec57ab6b858..af667f70bfbf 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/NonSnippetLowerings.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/NonSnippetLowerings.java @@ -30,6 +30,7 @@ import java.util.Map; import java.util.function.Predicate; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.StampPair; @@ -66,7 +67,6 @@ import org.graalvm.compiler.nodes.extended.OpaqueNode; import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/riscv64/PosixRISCV64VaListSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/riscv64/PosixRISCV64VaListSnippets.java index b255ea041c41..b8a6c0f3c59f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/riscv64/PosixRISCV64VaListSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/riscv64/PosixRISCV64VaListSnippets.java @@ -27,13 +27,13 @@ import java.util.Map; import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LoweringTool; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/thread/LoadVMThreadLocalNode.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/thread/LoadVMThreadLocalNode.java index 6a9b665942fb..bc5e39c28f29 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/thread/LoadVMThreadLocalNode.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/thread/LoadVMThreadLocalNode.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.graal.thread; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; @@ -38,7 +39,6 @@ import org.graalvm.compiler.nodes.memory.FloatableThreadLocalAccess; import org.graalvm.compiler.nodes.memory.MemoryAccess; import org.graalvm.compiler.nodes.memory.MemoryKill; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.OrderedMemoryAccess; import org.graalvm.compiler.nodes.memory.SingleMemoryKill; import org.graalvm.compiler.nodes.memory.address.AddressNode; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/thread/StoreVMThreadLocalNode.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/thread/StoreVMThreadLocalNode.java index ff2ebba69b5d..9de55e00270a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/thread/StoreVMThreadLocalNode.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/thread/StoreVMThreadLocalNode.java @@ -27,6 +27,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; @@ -35,7 +36,6 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.JavaWriteNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.OrderedMemoryAccess; import org.graalvm.compiler.nodes.memory.SingleMemoryKill; import org.graalvm.compiler.nodes.memory.address.AddressNode; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateWordOperationPlugins.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateWordOperationPlugins.java index 064f7af6a006..da303db151ce 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateWordOperationPlugins.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/word/SubstrateWordOperationPlugins.java @@ -25,15 +25,16 @@ package com.oracle.svm.core.graal.word; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.GuardingNode; +import org.graalvm.compiler.nodes.gc.BarrierSet; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.memory.FixedAccessNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.word.WordOperationPlugin; @@ -46,8 +47,8 @@ public class SubstrateWordOperationPlugins extends WordOperationPlugin { - public SubstrateWordOperationPlugins(SnippetReflectionProvider snippetReflection, WordTypes wordTypes) { - super(snippetReflection, wordTypes); + public SubstrateWordOperationPlugins(SnippetReflectionProvider snippetReflection, WordTypes wordTypes, BarrierSet barrierSet) { + super(snippetReflection, wordTypes, barrierSet); } @Override 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 6e0b9f14b050..3b37bcde0ad1 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 @@ -1267,7 +1267,8 @@ public static void registerGraphBuilderPlugins(FeatureHandler featureHandler, Ru TargetDescription target, boolean supportsStubBasedPlugins) { GraphBuilderConfiguration.Plugins plugins = new GraphBuilderConfiguration.Plugins(new SubstitutionInvocationPlugins(annotationSubstitutionProcessor)); - WordOperationPlugin wordOperationPlugin = new SubstrateWordOperationPlugins(providers.getSnippetReflection(), providers.getWordTypes()); + WordOperationPlugin wordOperationPlugin = new SubstrateWordOperationPlugins(providers.getSnippetReflection(), providers.getWordTypes(), + providers.getPlatformConfigurationProvider().getBarrierSet()); SubstrateReplacements replacements = (SubstrateReplacements) providers.getReplacements(); plugins.appendInlineInvokePlugin(replacements); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CGlobalDataFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CGlobalDataFeature.java index ec79b7cc1d40..0bad5ad1abf5 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CGlobalDataFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CGlobalDataFeature.java @@ -37,6 +37,7 @@ import java.util.stream.IntStream; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -63,7 +64,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; import org.graalvm.compiler.nodes.java.LoadFieldNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.phases.util.Providers; @@ -156,7 +156,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec ValueNode isSymbolReference = b.add(LoadFieldNode.create(b.getAssumptions(), info, b.getMetaAccess().lookupJavaField(isSymbolReferenceField))); LogicNode condition = IntegerEqualsNode.create(isSymbolReference, ConstantNode.forBoolean(false, b.getGraph()), NodeView.DEFAULT); ReadNode readValue = b.add(new ReadNode(b.add(OffsetAddressNode.create(address)), NamedLocationIdentity.ANY_LOCATION, - baseAddress.stamp(NodeView.DEFAULT), OnHeapMemoryAccess.BarrierType.NONE, MemoryOrderMode.PLAIN)); + baseAddress.stamp(NodeView.DEFAULT), BarrierType.NONE, MemoryOrderMode.PLAIN)); AbstractBeginNode trueBegin = b.add(new BeginNode()); FixedWithNextNode predecessor = (FixedWithNextNode) trueBegin.predecessor(); 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 5e7a18f881ab..5181bc089fec 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 @@ -62,6 +62,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.java.StableMethodNameFormatter; +import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.asm.DataBuilder; @@ -1162,7 +1163,8 @@ public CompilationResultBuilder createBuilder(CodeGenProviders providers, OptionValues options, DebugContext debug, CompilationResult compilationResult, - Register uncompressedNullRegister) { + Register uncompressedNullRegister, + LIR lir) { return new CompilationResultBuilder(providers, frameMap, asm, @@ -1173,7 +1175,8 @@ public CompilationResultBuilder createBuilder(CodeGenProviders providers, compilationResult, uncompressedNullRegister, EconomicMap.wrapMap(dataCache), - CompilationResultBuilder.NO_VERIFIERS); + CompilationResultBuilder.NO_VERIFIERS, + lir); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIJavaCallVariantWrapperMethod.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIJavaCallVariantWrapperMethod.java index e8c901457390..12603f695aef 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIJavaCallVariantWrapperMethod.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIJavaCallVariantWrapperMethod.java @@ -28,6 +28,7 @@ import java.util.List; import org.graalvm.compiler.core.common.calc.FloatConvert; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -46,7 +47,6 @@ import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.calc.FloatConvertNode; import org.graalvm.compiler.nodes.calc.ReinterpretNode; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.word.WordTypes; import org.graalvm.nativeimage.Platform; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/CInterfaceInvocationPlugin.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/CInterfaceInvocationPlugin.java index 4ca583e40a5e..47ecf853a181 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/CInterfaceInvocationPlugin.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/CInterfaceInvocationPlugin.java @@ -29,6 +29,7 @@ import java.util.Arrays; import org.graalvm.compiler.core.common.calc.FloatConvert; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; @@ -57,7 +58,6 @@ import org.graalvm.compiler.nodes.extended.JavaWriteNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.word.WordTypes; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java index 6ce648eb4e46..e67ac282e45e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java @@ -603,7 +603,8 @@ private boolean processInvokeWithMethodHandle(GraphBuilderContext b, Replacement /* We do all the word type rewriting because parameters to the lambda can be word types. */ SnippetReflectionProvider originalSnippetReflection = GraalAccess.getOriginalSnippetReflection(); - WordOperationPlugin wordOperationPlugin = new WordOperationPlugin(originalSnippetReflection, new SubstrateWordTypes(parsingProviders.getMetaAccess(), FrameAccess.getWordKind())); + WordOperationPlugin wordOperationPlugin = new WordOperationPlugin(originalSnippetReflection, new SubstrateWordTypes(parsingProviders.getMetaAccess(), FrameAccess.getWordKind()), + parsingProviders.getPlatformConfigurationProvider().getBarrierSet()); graphBuilderPlugins.appendInlineInvokePlugin(wordOperationPlugin); graphBuilderPlugins.appendTypePlugin(wordOperationPlugin); graphBuilderPlugins.appendTypePlugin(new TrustedInterfaceTypePlugin()); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadMTFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadMTFeature.java index 689579e371d5..ece738095542 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadMTFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadMTFeature.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; @@ -35,7 +36,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.IsolateThread; @@ -44,6 +44,7 @@ import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.c.NonmovableArray; import com.oracle.svm.core.c.NonmovableArrays; +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.graal.nodes.ReadReservedRegister; import com.oracle.svm.core.graal.thread.AddressOfVMThreadLocalNode; @@ -58,7 +59,6 @@ import com.oracle.svm.core.threadlocal.VMThreadLocalInfo; import com.oracle.svm.core.threadlocal.VMThreadLocalInfos; import com.oracle.svm.core.threadlocal.VMThreadLocalMTSupport; -import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadSTFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadSTFeature.java index f056f1d7accb..e0d13b76591e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadSTFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadSTFeature.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; @@ -35,7 +36,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; -import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.IsolateThread; @@ -180,7 +180,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec private boolean handleGet(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { VMThreadLocalInfo info = threadLocalCollector.findInfo(b, receiver.get()); VMThreadLocalSTHolderNode holder = b.add(new VMThreadLocalSTHolderNode(info)); - b.addPush(targetMethod.getSignature().getReturnKind(), new LoadVMThreadLocalNode(b.getMetaAccess(), info, holder, BarrierType.ARRAY, MemoryOrderMode.PLAIN)); + b.addPush(targetMethod.getSignature().getReturnKind(), new LoadVMThreadLocalNode(b.getMetaAccess(), info, holder, BarrierType.NONE, MemoryOrderMode.PLAIN)); return true; } diff --git a/vm/ci/ci_common/libgraal.jsonnet b/vm/ci/ci_common/libgraal.jsonnet index fe5b938a4226..90819806263f 100644 --- a/vm/ci/ci_common/libgraal.jsonnet +++ b/vm/ci/ci_common/libgraal.jsonnet @@ -19,9 +19,9 @@ local utils = import '../../../ci/ci_common/common-utils.libsonnet'; }, # enable asserts in the JVM building the image and enable asserts in the resulting native image - libgraal_compiler_base(quickbuild_args=[]):: self.libgraal_build(['-J-esa', '-J-ea', '-esa', '-ea'] + quickbuild_args) + { + libgraal_compiler_base(quickbuild_args=[], extra_vm_args=[]):: self.libgraal_build(['-J-esa', '-J-ea', '-esa', '-ea'] + quickbuild_args) + { run+: [ - ['mx', '--env', vm.libgraal_env, 'gate', '--task', 'LibGraal Compiler'], + ['mx', '--env', vm.libgraal_env, 'gate', '--task', 'LibGraal Compiler', '--extra-vm-argument=' + std.join(" ", extra_vm_args)], ], logs+: [ '*/graal-compiler.log', @@ -32,16 +32,18 @@ local utils = import '../../../ci/ci_common/common-utils.libsonnet'; # enable asserts in the JVM building the image and enable asserts in the resulting native image libgraal_compiler:: self.libgraal_compiler_base(), + libgraal_compiler_zgc:: self.libgraal_compiler_base(extra_vm_args=['-XX:+UseZGC']), # enable economy mode building with the -Ob flag - libgraal_compiler_quickbuild:: self.libgraal_compiler_base(['-Ob']), + libgraal_compiler_quickbuild:: self.libgraal_compiler_base(quickbuild_args=['-Ob']), - libgraal_truffle_base(quickbuild_args=[], coverage=false): self.libgraal_build(['-J-ea', '-ea'] + quickbuild_args) + { + libgraal_truffle_base(quickbuild_args=[], extra_vm_args=[], coverage=false): self.libgraal_build(['-J-esa', '-J-ea', '-esa', '-ea'] + quickbuild_args) + { environment+: { # The Truffle TCK tests run as a part of Truffle TCK gate, tools tests run as a part of tools gate TEST_LIBGRAAL_EXCLUDE: 'com.oracle.truffle.tck.tests.* com.oracle.truffle.tools.*' }, run+: [ - ['mx', '--env', vm.libgraal_env, 'gate', '--task', 'LibGraal Truffle'] + if coverage then g.jacoco_gate_args else [], + ['mx', '--env', vm.libgraal_env, 'gate', '--task', 'LibGraal Truffle'] + if coverage then g.jacoco_gate_args else [] + + if extra_vm_args != [] then ['--extra-vm-argument=' + std.join(" ", extra_vm_args)] else [], ], logs+: [ '*/graal-compiler.log', @@ -55,6 +57,7 @@ local utils = import '../../../ci/ci_common/common-utils.libsonnet'; # -ea assertions are enough to keep execution time reasonable libgraal_truffle: self.libgraal_truffle_base(), + libgraal_truffle_zgc: self.libgraal_truffle_base(extra_vm_args=['-XX:+UseZGC']), # enable economy mode building with the -Ob flag libgraal_truffle_quickbuild: self.libgraal_truffle_base(['-Ob']), @@ -65,6 +68,7 @@ local utils = import '../../../ci/ci_common/common-utils.libsonnet'; local gates = { "gate-vm-libgraal_compiler-labsjdk-20-linux-amd64": {}, "gate-vm-libgraal_truffle-labsjdk-20-linux-amd64": {}, + "gate-vm-libgraal_compiler_zgc-labsjdk-20-linux-amd64": {}, "gate-vm-libgraal_compiler_quickbuild-labsjdk-20-linux-amd64": {}, "gate-vm-libgraal_truffle_quickbuild-labsjdk-20-linux-amd64": {}, }, @@ -73,6 +77,9 @@ local utils = import '../../../ci/ci_common/common-utils.libsonnet'; local dailies = { "daily-vm-libgraal_compiler-labsjdk-17-linux-amd64": {}, "daily-vm-libgraal_truffle-labsjdk-17-linux-amd64": {}, + "daily-vm-libgraal_compiler_zgc-labsjdk-17-linux-amd64": {}, + "daily-vm-libgraal_truffle_zgc-labsjdk-17-linux-amd64": {}, + "daily-vm-libgraal_truffle_zgc-labsjdk-20-linux-amd64": {}, "daily-vm-libgraal_compiler_quickbuild-labsjdk-17-linux-amd64": {}, "daily-vm-libgraal_truffle_quickbuild-labsjdk-17-linux-amd64": {}, }, @@ -109,12 +116,13 @@ local utils = import '../../../ci/ci_common/common-utils.libsonnet'; "linux-amd64", "linux-aarch64", "darwin-amd64", - "darwin-aarch64", - "windows-amd64" + "darwin-aarch64" ] for task in [ "libgraal_compiler", "libgraal_truffle", + "libgraal_compiler_zgc", + "libgraal_truffle_zgc", "libgraal_compiler_quickbuild", "libgraal_truffle_quickbuild" ]