diff --git a/common.json b/common.json
index b1ff34e7c501..d6c2a1b88528 100644
--- a/common.json
+++ b/common.json
@@ -8,7 +8,7 @@
"COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet",
"jdks": {
- "galahad-jdk": {"name": "jpg-jdk", "version": "24", "build_id": "jdk-24+23-2783", "platformspecific": true, "extrabundles": ["static-libs"]},
+ "galahad-jdk": {"name": "jpg-jdk", "version": "24", "build_id": "jdk-24+24-2950", "platformspecific": true, "extrabundles": ["static-libs"]},
"oraclejdk17": {"name": "jpg-jdk", "version": "17.0.7", "build_id": "jdk-17.0.7+8", "platformspecific": true, "extrabundles": ["static-libs"]},
"labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.7+4-jvmci-23.1-b02", "platformspecific": true },
@@ -45,13 +45,13 @@
"oraclejdk23": {"name": "jpg-jdk", "version": "23", "build_id": "jdk-23+37", "platformspecific": true, "extrabundles": ["static-libs"]},
- "oraclejdk-latest": {"name": "jpg-jdk", "version": "24", "build_id": "jdk-24+23", "platformspecific": true, "extrabundles": ["static-libs"]},
- "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-24+23-jvmci-b01", "platformspecific": true },
- "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-24+23-jvmci-b01-debug", "platformspecific": true },
- "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-24+23-jvmci-b01-sulong", "platformspecific": true },
- "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-24+23-jvmci-b01", "platformspecific": true },
- "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-24+23-jvmci-b01-debug", "platformspecific": true },
- "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-24+23-jvmci-b01-sulong", "platformspecific": true }
+ "oraclejdk-latest": {"name": "jpg-jdk", "version": "24", "build_id": "jdk-24+24", "platformspecific": true, "extrabundles": ["static-libs"]},
+ "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-24+24-jvmci-b01", "platformspecific": true },
+ "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-24+24-jvmci-b01-debug", "platformspecific": true },
+ "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-24+24-jvmci-b01-sulong", "platformspecific": true },
+ "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-24+24-jvmci-b01", "platformspecific": true },
+ "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-24+24-jvmci-b01-debug", "platformspecific": true },
+ "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-24+24-jvmci-b01-sulong", "platformspecific": true }
},
"eclipse": {
diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py
index 78042442e57d..0a11e64c7c52 100644
--- a/compiler/mx.compiler/mx_compiler.py
+++ b/compiler/mx.compiler/mx_compiler.py
@@ -640,7 +640,7 @@ def compiler_gate_benchmark_runner(tasks, extraVMarguments=None, prefix='', task
}
# Renaissance is missing the msvc redistributable on Windows [GR-50132]
- if not mx.is_windows():
+ if not mx.is_windows() and jdk.javaCompliance <= '21':
for name in renaissance_suite.benchmarkList(bmSuiteArgs):
iterations = renaissance_gate_iterations.get(name, -1)
with Task(prefix + 'Renaissance:' + name, tasks, tags=GraalTags.benchmarktest, report=task_report_component) as t:
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java
index abf5e70448a5..555baf10282e 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java
@@ -66,7 +66,6 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigAccess {
GraalHotSpotVMConfig(HotSpotVMConfigStore store) {
super(store);
- assert narrowKlassShift <= logKlassAlignment : Assertions.errorMessageContext("narrowKlassShift", narrowKlassShift, "logKlassAlignment", logKlassAlignment);
int logMinObjAlignment = logMinObjAlignment();
assert narrowOopShift <= logMinObjAlignment : Assertions.errorMessageContext("narrowOopShift", narrowOopShift, "logMinObjAlignment", logMinObjAlignment);
oopEncoding = new CompressEncoding(narrowOopBase, narrowOopShift);
@@ -201,6 +200,11 @@ public long gcTotalCollectionsAddress() {
// Compressed Oops related values.
public final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
public final boolean useCompressedClassPointers = getFlag("UseCompressedClassPointers", Boolean.class);
+ // JDK-8305895 allows storing the compressed class pointer in the upper 22 bits of the mark
+ // word. This runtime optimization is guarded by the flag UseCompactObjectHeaders. It depends
+ // on compressed class pointers, meaning that if useCompactObjectHeaders is true,
+ // useCompressedClassPointers is certainly true.
+ public final boolean useCompactObjectHeaders = getFlag("UseCompactObjectHeaders", Boolean.class, false, JDK >= 24);
public final long narrowOopBase = getFieldValue("CompilerToVM::Data::Universe_narrow_oop_base", Long.class, "address");
public final int narrowOopShift = getFieldValue("CompilerToVM::Data::Universe_narrow_oop_shift", Integer.class, "int");
@@ -213,7 +217,6 @@ public final int logMinObjAlignment() {
public final int narrowKlassSize = getFieldValue("CompilerToVM::Data::sizeof_narrowKlass", Integer.class, "int");
public final long narrowKlassBase = getFieldValue("CompilerToVM::Data::Universe_narrow_klass_base", Long.class, "address");
public final int narrowKlassShift = getFieldValue("CompilerToVM::Data::Universe_narrow_klass_shift", Integer.class, "int");
- public final int logKlassAlignment = getConstant("LogKlassAlignmentInBytes", Integer.class);
public final int stackShadowPages = getFlag("StackShadowPages", Integer.class);
public final int vmPageSize = getFieldValue("CompilerToVM::Data::vm_page_size", Integer.class, "size_t");
@@ -255,12 +258,17 @@ public final int logMinObjAlignment() {
public final int arrayOopDescSize = getFieldValue("CompilerToVM::Data::sizeof_arrayOopDesc", Integer.class, "int");
+ public final int arrayLengthOffsetInBytes = getFieldValue("CompilerToVM::Data::arrayOopDesc_length_offset_in_bytes", Integer.class, "int", -1, JDK >= 24);
+
/**
* The offset of the array length word in an array object's header.
*
* See {@code arrayOopDesc::length_offset_in_bytes()}.
*/
public final int arrayOopDescLengthOffset() {
+ if (JDK >= 24) {
+ return arrayLengthOffsetInBytes;
+ }
return useCompressedClassPointers ? hubOffset + narrowKlassSize : arrayOopDescSize;
}
@@ -294,6 +302,8 @@ public final int arrayOopDescLengthOffset() {
public final int threadCarrierThreadObjectOffset = getFieldOffset("JavaThread::_threadObj", Integer.class, "OopHandle");
public final int threadScopedValueCacheOffset = getFieldOffset("JavaThread::_scopedValueCache", Integer.class, "OopHandle");
+ public final int javaThreadLockIDOffset = getFieldOffset("JavaThread::_lock_id", Integer.class, "int64_t", -1, JDK > 21);
+
public final int threadIsInVTMSTransitionOffset = getFieldOffset("JavaThread::_is_in_VTMS_transition", Integer.class, "bool");
public final int threadIsInTmpVTMSTransitionOffset = getFieldOffset("JavaThread::_is_in_tmp_VTMS_transition", Integer.class, "bool", -1, JDK == 21);
public final int threadIsDisableSuspendOffset = getFieldOffset("JavaThread::_is_disable_suspend", Integer.class, "bool", -1, JDK >= 22);
@@ -365,37 +375,35 @@ public int threadLastJavaFpOffset() {
public final int frameInterpreterFrameSenderSpOffset = getConstant("frame::interpreter_frame_sender_sp_offset", Integer.class, 0, osArch.equals("amd64"));
public final int frameInterpreterFrameLastSpOffset = getConstant("frame::interpreter_frame_last_sp_offset", Integer.class, 0, osArch.equals("amd64"));
- public final int lockMaskInPlace = getConstant("markWord::lock_mask_in_place", Integer.class);
+ public final long markWordLockMaskInPlace = getConstant("markWord::lock_mask_in_place", Long.class);
+ public final long markWordHashMask = getConstant("markWord::hash_mask", Long.class);
+
+ public final long markWordNoHashInPlace = getConstant("markWord::no_hash_in_place", Long.class);
+ public final long markWordNoLockInPlace = getConstant("markWord::no_lock_in_place", Long.class);
+
+ // Mark word right shift to get identity hash code.
+ public final int markWordHashCodeShift = getConstant("markWord::hash_shift", Integer.class);
+ // Mark word right shift to get compressed klass pointer
+ public final int markWordKlassShift = getConstant("markWord::klass_shift", Integer.class, 0, JDK >= 24);
+
+ // The following three constants are declared as 64 bits uintptr_t, but known to be 32 bits
public final int unlockedValue = getConstant("markWord::unlocked_value", Integer.class);
public final int monitorValue = getConstant("markWord::monitor_value", Integer.class);
+ public final int ageMaskInPlace = getConstant("markWord::age_mask_in_place", Integer.class);
+ public final int unusedMark = getConstant("markWord::marked_value", Integer.class, 3, JDK > 21);
+ // Identity hash code value when uninitialized.
+ public final int uninitializedIdentityHashCodeValue = getConstant("markWord::no_hash", Integer.class);
// This field has no type in vmStructs.cpp
- public final int objectMonitorOwner = getFieldOffset("ObjectMonitor::_owner", Integer.class, null);
+ public final int objectMonitorOwner = getFieldOffset("ObjectMonitor::_owner", Integer.class, JDK > 21 ? "int64_t" : null);
public final int objectMonitorRecursions = getFieldOffset("ObjectMonitor::_recursions", Integer.class, "intptr_t");
public final int objectMonitorCxq = getFieldOffset("ObjectMonitor::_cxq", Integer.class, "ObjectWaiter*");
public final int objectMonitorEntryList = getFieldOffset("ObjectMonitor::_EntryList", Integer.class, "ObjectWaiter*");
- public final int objectMonitorSucc = getFieldOffset("ObjectMonitor::_succ", Integer.class, "JavaThread*");
-
- public final int markWordNoHashInPlace = getConstant("markWord::no_hash_in_place", Integer.class);
- public final int markWordNoLockInPlace = getConstant("markWord::no_lock_in_place", Integer.class);
-
- public long defaultPrototypeMarkWord() {
- return this.markWordNoHashInPlace | this.markWordNoLockInPlace;
- }
-
- /**
- * Mark word right shift to get identity hash code.
- */
- public final int identityHashCodeShift = getConstant("markWord::hash_shift", Integer.class);
+ public final int objectMonitorSucc = getFieldOffset("ObjectMonitor::_succ", Integer.class, JDK > 21 ? "int64_t" : "JavaThread*");
public final int contEntry = getFieldOffset("JavaThread::_cont_entry", Integer.class, "ContinuationEntry*", -1, JDK >= 24);
public final int pinCount = getFieldOffset("ContinuationEntry::_pin_count", Integer.class, "uint32_t", -1, JDK >= 24);
- /**
- * Identity hash code value when uninitialized.
- */
- public final int uninitializedIdentityHashCodeValue = getConstant("markWord::no_hash", Integer.class);
-
public final int methodCompiledEntryOffset = getFieldOffset("Method::_from_compiled_entry", Integer.class, "address");
public final int compilationLevelFullOptimization = getConstant("CompLevel_full_optimization", Integer.class);
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java
index 4dbfb8333b52..2c4526b52507 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java
@@ -55,8 +55,8 @@ public final class JVMCIVersionCheck {
private static final Map> JVMCI_MIN_VERSIONS = Map.of(
"21", Map.of(DEFAULT_VENDOR_ENTRY, createLegacyVersion(23, 1, 33)),
"24", Map.of(
- "Oracle Corporation", createLabsJDKVersion("24+23", 1),
- DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("24+23", 1)));
+ "Oracle Corporation", createLabsJDKVersion("24+24", 1),
+ DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("24+24", 1)));
private static final int NA = 0;
/**
* Minimum Java release supported by Graal.
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java
index dd278bd30654..1c0013ba3923 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2024, 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
@@ -419,15 +419,18 @@ private void emitCodePrefix(CompilationResultBuilder crb, ResolvedJavaMethod ins
CallingConvention cc = regConfig.getCallingConvention(HotSpotCallingConventionType.JavaCallee, null, parameterTypes, this);
Register receiver = asRegister(cc.getArgument(0));
int size = config.useCompressedClassPointers ? 32 : 64;
- AArch64Address klassAddress = masm.makeAddress(size, receiver, config.hubOffset);
if (config.icSpeculatedKlassOffset == Integer.MAX_VALUE) {
crb.recordMark(HotSpotMarkId.UNVERIFIED_ENTRY);
Register klass = rscratch1;
if (config.useCompressedClassPointers) {
- masm.ldr(32, klass, klassAddress);
+ if (config.useCompactObjectHeaders) {
+ ((AArch64HotSpotMacroAssembler) masm).loadCompactClassPointer(klass, receiver);
+ } else {
+ masm.ldr(size, klass, masm.makeAddress(size, receiver, config.hubOffset));
+ }
AArch64HotSpotMove.decodeKlassPointer(masm, klass, klass, config.getKlassEncoding());
} else {
- masm.ldr(64, klass, klassAddress);
+ masm.ldr(size, klass, masm.makeAddress(size, receiver, config.hubOffset));
}
// c1_LIRAssembler_aarch64.cpp: const Register IC_Klass = rscratch2;
Register inlineCacheKlass = AArch64HotSpotRegisterConfig.inlineCacheRegister;
@@ -436,7 +439,6 @@ private void emitCodePrefix(CompilationResultBuilder crb, ResolvedJavaMethod ins
masm.branchConditionally(AArch64Assembler.ConditionFlag.EQ, verifiedStub);
AArch64Call.directJmp(crb, masm, getForeignCalls().lookupForeignCall(IC_MISS_HANDLER));
} else {
-
// JDK-8322630 (removed ICStubs)
Register data = AArch64HotSpotRegisterConfig.inlineCacheRegister;
Register tmp1 = rscratch1;
@@ -445,16 +447,24 @@ private void emitCodePrefix(CompilationResultBuilder crb, ResolvedJavaMethod ins
// Size of IC check sequence checked with a guarantee below.
int inlineCacheCheckSize = AArch64Call.isNearCall(icMissHandler) ? 20 : 32;
+ if (config.useCompactObjectHeaders) {
+ // Extra instruction for shifting
+ inlineCacheCheckSize += 4;
+ }
masm.align(config.codeEntryAlignment, masm.position() + inlineCacheCheckSize);
int startICCheck = masm.position();
crb.recordMark(HotSpotMarkId.UNVERIFIED_ENTRY);
AArch64Address icSpeculatedKlass = masm.makeAddress(size, data, config.icSpeculatedKlassOffset);
- masm.ldr(size, tmp1, klassAddress);
+ if (config.useCompactObjectHeaders) {
+ ((AArch64HotSpotMacroAssembler) masm).loadCompactClassPointer(tmp1, receiver);
+ } else {
+ masm.ldr(size, tmp1, masm.makeAddress(size, receiver, config.hubOffset));
+ }
+
masm.ldr(size, tmp2, icSpeculatedKlass);
masm.cmp(size, tmp1, tmp2);
-
masm.branchConditionally(AArch64Assembler.ConditionFlag.EQ, verifiedStub);
AArch64Call.directJmp(crb, masm, icMissHandler);
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotMacroAssembler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotMacroAssembler.java
index 21456991370b..982013fa6d78 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotMacroAssembler.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotMacroAssembler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
import jdk.graal.compiler.asm.aarch64.AArch64Assembler;
import jdk.graal.compiler.asm.aarch64.AArch64MacroAssembler;
import jdk.graal.compiler.core.common.CompressEncoding;
+import jdk.graal.compiler.debug.GraalError;
import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig;
import jdk.graal.compiler.lir.aarch64.AArch64Move;
import jdk.vm.ci.aarch64.AArch64;
@@ -81,23 +82,24 @@ public void verifyOop(Register value, Register tmp, Register tmp2, boolean compr
cbz(compressed ? 32 : 64, value, ok);
}
- AArch64Address hubAddress;
- int hubSize = config.useCompressedClassPointers ? 32 : 64;
+ Register object = value;
if (compressed) {
CompressEncoding encoding = config.getOopEncoding();
mov(32, tmp, value);
AArch64Move.UncompressPointerOp.emitUncompressCode(this, tmp, tmp, encoding, true, heapBaseRegister, false);
- hubAddress = makeAddress(hubSize, tmp, config.hubOffset);
- } else {
- hubAddress = makeAddress(hubSize, value, config.hubOffset);
+ object = tmp;
}
// Load the class
if (config.useCompressedClassPointers) {
- ldr(32, tmp, hubAddress);
+ if (config.useCompactObjectHeaders) {
+ loadCompactClassPointer(tmp, object);
+ } else {
+ ldr(32, tmp, makeAddress(32, object, config.hubOffset));
+ }
AArch64HotSpotMove.decodeKlassPointer(this, tmp, tmp, config.getKlassEncoding());
} else {
- ldr(64, tmp, hubAddress);
+ ldr(64, tmp, makeAddress(64, object, config.hubOffset));
}
// Klass::_super_check_offset
ldr(32, tmp2, makeAddress(32, tmp, config.superCheckOffsetOffset));
@@ -127,4 +129,9 @@ public void verifyHeapBase() {
}
}
+ public void loadCompactClassPointer(Register result, Register receiver) {
+ GraalError.guarantee(config.useCompactObjectHeaders, "Load class pointer from markWord only when UseCompactObjectHeaders is on");
+ ldr(64, result, makeAddress(64, receiver, config.markOffset));
+ lsr(64, result, result, config.markWordKlassShift);
+ }
}
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotBackend.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotBackend.java
index 594205adfcd5..a25cac73fb79 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotBackend.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotBackend.java
@@ -337,7 +337,6 @@ public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationRes
JavaType[] parameterTypes = {providers.getMetaAccess().lookupJavaType(Object.class)};
CallingConvention cc = regConfig.getCallingConvention(HotSpotCallingConventionType.JavaCallee, null, parameterTypes, this);
Register receiver = asRegister(cc.getArgument(0));
- AMD64Address src = new AMD64Address(receiver, config.hubOffset);
int before;
if (config.icSpeculatedKlassOffset == Integer.MAX_VALUE) {
crb.recordMark(HotSpotMarkId.UNVERIFIED_ENTRY);
@@ -347,18 +346,23 @@ public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationRes
if (config.useCompressedClassPointers) {
Register register = r10;
Register heapBase = providers.getRegisters().getHeapBaseRegister();
- AMD64HotSpotMove.decodeKlassPointer(asm, register, heapBase, src, config);
+ if (config.useCompactObjectHeaders) {
+ ((AMD64HotSpotMacroAssembler) asm).loadCompactClassPointer(register, receiver);
+ } else {
+ asm.movl(register, new AMD64Address(receiver, config.hubOffset));
+ }
+ AMD64HotSpotMove.decodeKlassPointer(asm, register, heapBase, config);
if (config.narrowKlassBase != 0) {
// The heap base register was destroyed above, so restore it
if (config.narrowOopBase == 0L) {
- asm.xorq(heapBase, heapBase);
+ asm.xorl(heapBase, heapBase);
} else {
asm.movq(heapBase, config.narrowOopBase);
}
}
before = asm.cmpqAndJcc(inlineCacheKlass, register, ConditionFlag.NotEqual, null, false);
} else {
- before = asm.cmpqAndJcc(inlineCacheKlass, src, ConditionFlag.NotEqual, null, false);
+ before = asm.cmpqAndJcc(inlineCacheKlass, new AMD64Address(receiver, config.hubOffset), ConditionFlag.NotEqual, null, false);
}
crb.recordDirectCall(before, asm.position(), getForeignCalls().lookupForeignCall(IC_MISS_HANDLER), null);
} else {
@@ -376,6 +380,10 @@ public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationRes
*/
inlineCacheCheckSize += 3 + 3;
}
+ if (config.useCompactObjectHeaders) {
+ // 4 bytes for extra shift instruction, 1 byte less for 0-displacement address
+ inlineCacheCheckSize += 3;
+ }
asm.align(config.codeEntryAlignment, asm.position() + inlineCacheCheckSize);
int startICCheck = asm.position();
@@ -384,10 +392,14 @@ public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationRes
AMD64BaseAssembler.OperandSize size;
if (config.useCompressedClassPointers) {
- asm.movl(temp, src);
+ if (config.useCompactObjectHeaders) {
+ ((AMD64HotSpotMacroAssembler) asm).loadCompactClassPointer(temp, receiver);
+ } else {
+ asm.movl(temp, new AMD64Address(receiver, config.hubOffset));
+ }
size = AMD64BaseAssembler.OperandSize.DWORD;
} else {
- asm.movptr(temp, src);
+ asm.movptr(temp, new AMD64Address(receiver, config.hubOffset));
size = AMD64BaseAssembler.OperandSize.QWORD;
}
before = asm.cmpAndJcc(size, temp, icSpeculatedKlass, ConditionFlag.NotEqual, null, false);
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotMacroAssembler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotMacroAssembler.java
index cb5e2b831943..3af9bae71f40 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotMacroAssembler.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotMacroAssembler.java
@@ -29,7 +29,6 @@
import jdk.graal.compiler.asm.Label;
import jdk.graal.compiler.asm.amd64.AMD64Address;
-import jdk.graal.compiler.asm.amd64.AMD64Assembler;
import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler;
import jdk.graal.compiler.core.common.CompressEncoding;
import jdk.graal.compiler.core.common.NumUtil;
@@ -108,25 +107,28 @@ public void verifyOop(Register value, Register tmp, Register tmp2, boolean compr
if (!nonNull) {
// first null check the value
- testAndJcc(compressed ? DWORD : QWORD, value, value, AMD64Assembler.ConditionFlag.Zero, ok, true);
+ testAndJcc(compressed ? DWORD : QWORD, value, value, ConditionFlag.Zero, ok, true);
}
- AMD64Address hubAddress;
+ Register object = value;
if (compressed) {
CompressEncoding encoding = config.getOopEncoding();
Register heapBaseRegister = AMD64Move.UncompressPointerOp.hasBase(encoding) ? providers.getRegisters().getHeapBaseRegister() : Register.None;
movq(tmp, value);
AMD64Move.UncompressPointerOp.emitUncompressCode(this, tmp, encoding.getShift(), heapBaseRegister, true);
- hubAddress = new AMD64Address(tmp, config.hubOffset);
- } else {
- hubAddress = new AMD64Address(value, config.hubOffset);
+ object = tmp;
}
- // Load the klass
+ // Load the klass into tmp
if (config.useCompressedClassPointers) {
- AMD64HotSpotMove.decodeKlassPointer(this, tmp, tmp2, hubAddress, config);
+ if (config.useCompactObjectHeaders) {
+ loadCompactClassPointer(tmp, object);
+ } else {
+ movl(tmp, new AMD64Address(object, config.hubOffset));
+ }
+ AMD64HotSpotMove.decodeKlassPointer(this, tmp, tmp2, config);
} else {
- movq(tmp, hubAddress);
+ movq(tmp, new AMD64Address(object, config.hubOffset));
}
// Klass::_super_check_offset
movl(tmp2, new AMD64Address(tmp, config.superCheckOffsetOffset));
@@ -136,7 +138,7 @@ public void verifyOop(Register value, Register tmp, Register tmp2, boolean compr
// Load the klass from the primary supers
movq(tmp2, new AMD64Address(tmp, tmp2, Stride.S1));
// the Klass* should be equal
- cmpqAndJcc(tmp2, tmp, AMD64Assembler.ConditionFlag.Equal, ok, true);
+ cmpqAndJcc(tmp2, tmp, ConditionFlag.Equal, ok, true);
illegal();
bind(ok);
}
@@ -176,4 +178,10 @@ protected final int membarOffset() {
public Register getZeroValueRegister() {
return providers.getRegisters().getZeroValueRegister(config);
}
+
+ public void loadCompactClassPointer(Register result, Register receiver) {
+ GraalError.guarantee(config.useCompactObjectHeaders, "Load class pointer from markWord only when UseCompactObjectHeaders is on");
+ movq(result, new AMD64Address(receiver, config.markOffset));
+ shrq(result, config.markWordKlassShift);
+ }
}
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotMove.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotMove.java
index 09a4bd811feb..aa998cbe3a89 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotMove.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotMove.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2024, 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
@@ -169,9 +169,12 @@ public AllocatableValue getResult() {
}
}
- public static void decodeKlassPointer(AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) {
+ /**
+ * Decode compressed class pointer stored in {@code register}. The content in {@code scratch}
+ * might be destroyed.
+ */
+ public static void decodeKlassPointer(AMD64MacroAssembler masm, Register register, Register scratch, GraalHotSpotVMConfig config) {
CompressEncoding encoding = config.getKlassEncoding();
- masm.movl(register, address);
if (encoding.getShift() != 0) {
masm.shlq(register, encoding.getShift());
}
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java
index adb4c4800862..5150e20cf3a7 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java
@@ -30,6 +30,11 @@
import static jdk.graal.compiler.hotspot.HotSpotGraalRuntime.HotSpotGC;
import static jdk.graal.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END;
import static jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider.GENERIC_ARRAYCOPY;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.COMPACT_HUB_LOCATION;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.COMPRESSED_HUB_LOCATION;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_LOCATION;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION;
import static org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode;
import static org.graalvm.word.LocationIdentity.any;
@@ -104,6 +109,7 @@
import jdk.graal.compiler.hotspot.replacements.arraycopy.HotSpotArraycopySnippets;
import jdk.graal.compiler.hotspot.stubs.ForeignCallSnippets;
import jdk.graal.compiler.hotspot.word.KlassPointer;
+import jdk.graal.compiler.hotspot.word.PointerCastNode;
import jdk.graal.compiler.nodes.AbstractBeginNode;
import jdk.graal.compiler.nodes.AbstractDeoptimizeNode;
import jdk.graal.compiler.nodes.CompressionNode.CompressionOp;
@@ -134,11 +140,13 @@
import jdk.graal.compiler.nodes.calc.IntegerDivRemNode;
import jdk.graal.compiler.nodes.calc.IsNullNode;
import jdk.graal.compiler.nodes.calc.LeftShiftNode;
+import jdk.graal.compiler.nodes.calc.NarrowNode;
import jdk.graal.compiler.nodes.calc.RemNode;
import jdk.graal.compiler.nodes.calc.SignedDivNode;
import jdk.graal.compiler.nodes.calc.SignedFloatingIntegerDivNode;
import jdk.graal.compiler.nodes.calc.SignedFloatingIntegerRemNode;
import jdk.graal.compiler.nodes.calc.SignedRemNode;
+import jdk.graal.compiler.nodes.calc.UnsignedRightShiftNode;
import jdk.graal.compiler.nodes.debug.VerifyHeapNode;
import jdk.graal.compiler.nodes.extended.BranchProbabilityNode;
import jdk.graal.compiler.nodes.extended.BytecodeExceptionNode;
@@ -368,7 +376,7 @@ public boolean supportsBulkClearArray(JavaKind elementKind) {
@Override
protected IdentityHashCodeSnippets.Templates createIdentityHashCodeSnippets(OptionValues options, Providers providers) {
- return new IdentityHashCodeSnippets.Templates(new HotSpotHashCodeSnippets(), options, providers, HotSpotReplacementsUtil.MARK_WORD_LOCATION);
+ return new IdentityHashCodeSnippets.Templates(new HotSpotHashCodeSnippets(), options, providers, MARK_WORD_LOCATION);
}
public HotSpotAllocationSnippets.Templates getAllocationSnippets() {
@@ -1115,21 +1123,31 @@ private ReadNode createReadVirtualMethod(StructuredGraph graph, ValueNode hub, i
@Override
protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, LoweringTool tool) {
+ GraalHotSpotVMConfig config = runtime.getVMConfig();
+
if (tool.getLoweringStage() != LoweringTool.StandardLoweringStage.LOW_TIER) {
return graph.unique(new LoadHubNode(tool.getStampProvider(), object));
}
assert !object.isConstant() || object.isNullConstant();
KlassPointerStamp hubStamp = KlassPointerStamp.klassNonNull();
- if (runtime.getVMConfig().useCompressedClassPointers) {
- hubStamp = hubStamp.compressed(runtime.getVMConfig().getKlassEncoding());
+ if (config.useCompressedClassPointers) {
+ hubStamp = hubStamp.compressed(config.getKlassEncoding());
}
- AddressNode address = createOffsetAddress(graph, object, runtime.getVMConfig().hubOffset);
- LocationIdentity hubLocation = runtime.getVMConfig().useCompressedClassPointers ? HotSpotReplacementsUtil.COMPRESSED_HUB_LOCATION : HotSpotReplacementsUtil.HUB_LOCATION;
+ if (config.useCompactObjectHeaders) {
+ AddressNode address = createOffsetAddress(graph, object, config.markOffset);
+ FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(address, COMPACT_HUB_LOCATION, null, StampFactory.forKind(JavaKind.Long), null, BarrierType.NONE));
+ ValueNode rawCompressedHubWordSize = graph.addOrUnique(UnsignedRightShiftNode.create(memoryRead, ConstantNode.forInt(config.markWordKlassShift, graph), NodeView.DEFAULT));
+ ValueNode rawCompressedHub = graph.addOrUnique(NarrowNode.create(rawCompressedHubWordSize, 32, NodeView.DEFAULT));
+ ValueNode compressedKlassPointer = graph.addOrUnique(PointerCastNode.create(hubStamp, rawCompressedHub));
+ return HotSpotCompressionNode.uncompress(graph, compressedKlassPointer, config.getKlassEncoding());
+ }
+ AddressNode address = createOffsetAddress(graph, object, config.hubOffset);
+ LocationIdentity hubLocation = config.useCompressedClassPointers ? COMPRESSED_HUB_LOCATION : HUB_LOCATION;
FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(address, hubLocation, null, hubStamp, null, BarrierType.NONE));
- if (runtime.getVMConfig().useCompressedClassPointers) {
- return HotSpotCompressionNode.uncompress(graph, memoryRead, runtime.getVMConfig().getKlassEncoding());
+ if (config.useCompressedClassPointers) {
+ return HotSpotCompressionNode.uncompress(graph, memoryRead, config.getKlassEncoding());
} else {
return memoryRead;
}
@@ -1137,14 +1155,16 @@ protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, Lower
private WriteNode createWriteHub(StructuredGraph graph, ValueNode object, ValueNode value) {
assert !object.isConstant() || object.asConstant().isDefaultForKind();
+ GraalHotSpotVMConfig config = runtime.getVMConfig();
+ GraalError.guarantee(!config.useCompactObjectHeaders, "Should not reach here with +UseCompactObjectHeaders");
ValueNode writeValue = value;
- if (runtime.getVMConfig().useCompressedClassPointers) {
- writeValue = HotSpotCompressionNode.compress(graph, value, runtime.getVMConfig().getKlassEncoding());
+ if (config.useCompressedClassPointers) {
+ writeValue = HotSpotCompressionNode.compress(graph, value, config.getKlassEncoding());
}
- AddressNode address = createOffsetAddress(graph, object, runtime.getVMConfig().hubOffset);
- return graph.add(new WriteNode(address, HotSpotReplacementsUtil.HUB_WRITE_LOCATION, writeValue, BarrierType.NONE, MemoryOrderMode.PLAIN));
+ AddressNode address = createOffsetAddress(graph, object, config.hubOffset);
+ return graph.add(new WriteNode(address, HUB_WRITE_LOCATION, writeValue, BarrierType.NONE, MemoryOrderMode.PLAIN));
}
@Override
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java
index 6c0aaf48ffe2..872c6034cf3d 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java
@@ -40,8 +40,12 @@
import static jdk.graal.compiler.hotspot.HotSpotBackend.SHAREDRUNTIME_NOTIFY_JVMTI_VTHREAD_UNMOUNT;
import static jdk.graal.compiler.hotspot.HotSpotBackend.UPDATE_BYTES_CRC32;
import static jdk.graal.compiler.hotspot.HotSpotBackend.UPDATE_BYTES_CRC32C;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_CARRIER_THREAD_OOP_HANDLE_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_CONTINUATION_ENTRY_PIN_COUNT;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_JAVA_THREAD_CONT_ENTRY;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_JAVA_THREAD_SCOPED_VALUE_CACHE_HANDLE_LOCATION;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_LOCK_ID_LOCATION;
import static jdk.graal.compiler.java.BytecodeParserOptions.InlineDuringParsing;
import static jdk.graal.compiler.nodes.ConstantNode.forBoolean;
import static jdk.graal.compiler.nodes.ProfileData.BranchProbabilityData.injected;
@@ -61,6 +65,7 @@
import java.math.BigInteger;
import java.util.zip.CRC32;
+import org.graalvm.nativeimage.ImageInfo;
import org.graalvm.word.LocationIdentity;
import jdk.graal.compiler.api.directives.GraalDirectives;
@@ -69,7 +74,9 @@
import jdk.graal.compiler.core.common.memory.BarrierType;
import jdk.graal.compiler.core.common.memory.MemoryOrderMode;
import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor;
+import jdk.graal.compiler.core.common.type.ObjectStamp;
import jdk.graal.compiler.core.common.type.StampFactory;
+import jdk.graal.compiler.core.common.type.TypeReference;
import jdk.graal.compiler.debug.GraalError;
import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig;
import jdk.graal.compiler.hotspot.HotSpotBackend;
@@ -78,6 +85,7 @@
import jdk.graal.compiler.hotspot.nodes.HotSpotLoadReservedReferenceNode;
import jdk.graal.compiler.hotspot.nodes.HotSpotStoreReservedReferenceNode;
import jdk.graal.compiler.hotspot.nodes.KlassFullyInitializedCheckNode;
+import jdk.graal.compiler.hotspot.nodes.VirtualThreadUpdateJFRNode;
import jdk.graal.compiler.hotspot.replacements.CallSiteTargetNode;
import jdk.graal.compiler.hotspot.replacements.DigestBaseSnippets;
import jdk.graal.compiler.hotspot.replacements.FastNotifyNode;
@@ -142,6 +150,8 @@
import jdk.graal.compiler.nodes.java.DynamicNewInstanceWithExceptionNode;
import jdk.graal.compiler.nodes.java.NewArrayNode;
import jdk.graal.compiler.nodes.java.ValidateNewInstanceClassNode;
+import jdk.graal.compiler.nodes.memory.ReadNode;
+import jdk.graal.compiler.nodes.memory.WriteNode;
import jdk.graal.compiler.nodes.memory.address.AddressNode;
import jdk.graal.compiler.nodes.memory.address.OffsetAddressNode;
import jdk.graal.compiler.nodes.spi.Replacements;
@@ -190,7 +200,6 @@
import jdk.vm.ci.meta.SpeculationLog;
import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
import jdk.vm.ci.meta.UnresolvedJavaType;
-import org.graalvm.nativeimage.ImageInfo;
/**
* Defines the {@link Plugins} used when running on HotSpot.
@@ -663,14 +672,28 @@ private static boolean isAnnotatedByChangesCurrentThread(ResolvedJavaMethod meth
return false;
}
+ private static AddressNode getScopedValueCacheAddress(GraphBuilderContext b, HotSpotInvocationPluginHelper helper) {
+ CurrentJavaThreadNode javaThread = b.add(new CurrentJavaThreadNode(helper.getWordKind()));
+ ValueNode scopedValueCacheHandle = helper.readJavaThreadScopedValueCache(javaThread);
+ return b.add(OffsetAddressNode.create(scopedValueCacheHandle));
+ }
+
private static void registerThreadPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) {
+ BarrierSet barrierSet = replacements.getProviders().getPlatformConfigurationProvider().getBarrierSet();
Registration r = new Registration(plugins, Thread.class, replacements);
r.register(new InvocationPlugin("currentThread") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
try (HotSpotInvocationPluginHelper helper = new HotSpotInvocationPluginHelper(b, targetMethod, config)) {
- ValueNode value = helper.readCurrentThreadObject(true);
- b.push(JavaKind.Object, value);
+ CurrentJavaThreadNode thread = b.add(new CurrentJavaThreadNode(helper.getWordKind()));
+ ValueNode vthreadHandle = helper.readJavaThreadVthread(thread);
+ // Read the Object from the OopHandle
+ AddressNode handleAddress = b.add(OffsetAddressNode.create(vthreadHandle));
+ // JavaThread::_vthread is never compressed
+ ObjectStamp threadStamp = StampFactory.objectNonNull(TypeReference.create(b.getAssumptions(), b.getMetaAccess().lookupJavaType(Thread.class)));
+ ValueNode read = new ReadNode(handleAddress, HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION, threadStamp,
+ barrierSet.readBarrierType(HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION, handleAddress, threadStamp), MemoryOrderMode.PLAIN);
+ b.addPush(JavaKind.Object, read);
}
return true;
}
@@ -680,8 +703,15 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
try (HotSpotInvocationPluginHelper helper = new HotSpotInvocationPluginHelper(b, targetMethod, config)) {
- ValueNode value = helper.readCurrentThreadObject(false);
- b.push(JavaKind.Object, value);
+ CurrentJavaThreadNode thread = b.add(new CurrentJavaThreadNode(helper.getWordKind()));
+ ValueNode cthreadHandle = helper.readJavaThreadThreadObj(thread);
+ // Read the Object from the OopHandle
+ AddressNode handleAddress = b.add(OffsetAddressNode.create(cthreadHandle));
+ // JavaThread::_threadObj is never compressed
+ ObjectStamp threadStamp = StampFactory.objectNonNull(TypeReference.create(b.getAssumptions(), b.getMetaAccess().lookupJavaType(Thread.class)));
+ ValueNode read = new ReadNode(handleAddress, HOTSPOT_CARRIER_THREAD_OOP_HANDLE_LOCATION, threadStamp,
+ barrierSet.readBarrierType(HOTSPOT_CARRIER_THREAD_OOP_HANDLE_LOCATION, handleAddress, threadStamp), MemoryOrderMode.PLAIN);
+ b.addPush(JavaKind.Object, read);
}
return true;
}
@@ -693,7 +723,22 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
GraalError.guarantee(ImageInfo.inImageRuntimeCode() || isAnnotatedByChangesCurrentThread(b.getMethod()), "method changes current Thread but is not annotated ChangesCurrentThread");
try (HotSpotInvocationPluginHelper helper = new HotSpotInvocationPluginHelper(b, targetMethod, config)) {
receiver.get(true);
- helper.setCurrentThread(thread);
+ CurrentJavaThreadNode javaThread = b.add(new CurrentJavaThreadNode(helper.getWordKind()));
+ ValueNode threadObjectHandle = helper.readJavaThreadVthread(javaThread);
+ AddressNode handleAddress = b.add(OffsetAddressNode.create(threadObjectHandle));
+ b.add(new WriteNode(handleAddress, HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION, thread,
+ barrierSet.writeBarrierType(HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION), MemoryOrderMode.PLAIN));
+
+ if (JavaVersionUtil.JAVA_SPEC > 21) {
+ GraalError.guarantee(config.javaThreadLockIDOffset != -1, "JavaThread::_lock_id should have been exported");
+ // Change the lock_id of the JavaThread
+ ValueNode tid = helper.loadField(thread, helper.getField(b.getMetaAccess().lookupJavaType(Thread.class), "tid"));
+ OffsetAddressNode address = b.add(new OffsetAddressNode(javaThread, helper.asWord(config.javaThreadLockIDOffset)));
+ b.add(new JavaWriteNode(JavaKind.Long, address, JAVA_THREAD_LOCK_ID_LOCATION, tid, BarrierType.NONE, false));
+ }
+ if (HotSpotReplacementsUtil.supportsVirtualThreadUpdateJFR(config)) {
+ b.add(new VirtualThreadUpdateJFRNode(thread));
+ }
}
return true;
}
@@ -703,7 +748,11 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
try (HotSpotInvocationPluginHelper helper = new HotSpotInvocationPluginHelper(b, targetMethod, config)) {
- b.push(JavaKind.Object, helper.readThreadScopedValueCache());
+ AddressNode handleAddress = getScopedValueCacheAddress(b, helper);
+ ObjectStamp stamp = StampFactory.object(TypeReference.create(b.getAssumptions(), b.getMetaAccess().lookupJavaType(Object[].class)));
+ b.push(JavaKind.Object, b.add(new ReadNode(handleAddress, HOTSPOT_JAVA_THREAD_SCOPED_VALUE_CACHE_HANDLE_LOCATION, stamp,
+ barrierSet.readBarrierType(HOTSPOT_JAVA_THREAD_SCOPED_VALUE_CACHE_HANDLE_LOCATION, handleAddress, stamp),
+ MemoryOrderMode.PLAIN)));
}
return true;
}
@@ -713,7 +762,10 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode cache) {
try (HotSpotInvocationPluginHelper helper = new HotSpotInvocationPluginHelper(b, targetMethod, config)) {
- helper.setThreadScopedValueCache(cache);
+ AddressNode handleAddress = getScopedValueCacheAddress(b, helper);
+ b.add(new WriteNode(handleAddress, HOTSPOT_JAVA_THREAD_SCOPED_VALUE_CACHE_HANDLE_LOCATION, cache,
+ barrierSet.writeBarrierType(HOTSPOT_JAVA_THREAD_SCOPED_VALUE_CACHE_HANDLE_LOCATION),
+ MemoryOrderMode.PLAIN));
}
return true;
}
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotWordOperationPlugin.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotWordOperationPlugin.java
index fb8085184a73..15b068375ee1 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotWordOperationPlugin.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotWordOperationPlugin.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -134,6 +134,11 @@ protected void processHotSpotWordOperation(GraphBuilderContext b, ResolvedJavaMe
b.addPush(returnKind, PointerCastNode.create(StampFactory.forKind(wordKind), args[0]));
break;
+ case FROM_COMPRESSED_POINTER:
+ assert args.length == 1 : args;
+ b.addPush(returnKind, PointerCastNode.create(StampFactory.forKind(JavaKind.Int), args[0]));
+ break;
+
case TO_KLASS_POINTER:
assert args.length == 1 : args;
b.addPush(returnKind, PointerCastNode.create(KlassPointerStamp.klass(), args[0]));
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/DigestBaseSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/DigestBaseSnippets.java
index 3eca041374a4..9374fe29d951 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/DigestBaseSnippets.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/DigestBaseSnippets.java
@@ -98,7 +98,7 @@ static int implCompressMultiBlock0(Object receiver, byte[] buf, int ofs, int lim
Object sha3obj = PiNode.piCast(realReceiver, sha3type, false, true, SnippetAnchorNode.anchor());
int blockSize = RawLoadNode.loadInt(sha3obj, HotSpotReplacementsUtil.getFieldOffset(sha3type, "blockSize"), JavaKind.Int, LocationIdentity.any());
Object state = RawLoadNode.load(sha3obj, HotSpotReplacementsUtil.getFieldOffset(sha3type, "state"), JavaKind.Object, LocationIdentity.any());
- Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int)));
+ Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Long)));
return HotSpotBackend.sha3ImplCompressMBStub(bufAddr, stateAddr, blockSize, ofs, limit);
} else {
return FallbackInvokeWithExceptionNode.fallbackFunctionCallInt();
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotHashCodeSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotHashCodeSnippets.java
index e935c89093fd..67a3c37d1eb6 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotHashCodeSnippets.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotHashCodeSnippets.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,10 +27,11 @@
import static jdk.graal.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
import static jdk.graal.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.IDENTITY_HASHCODE;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.identityHashCode;
-import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.identityHashCodeShift;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadWordFromObject;
-import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.lockMaskInPlace;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.markOffset;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.markWordHashCodeShift;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.markWordHashMark;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.markWordLockMaskInPlace;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.monitorValue;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.uninitializedIdentityHashCodeValue;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.unlockedValue;
@@ -57,26 +58,31 @@ protected int computeIdentityHashCode(final Object x) {
// In HotSpot, the upper bits (i.e., [63:2] in 64-bits VM) of the mark word in object header
// are
- // 1) not used with lightweight locking;
+ // 1) not used or partially used (i.e., [63:42] in 64-bits VM to store compressed class
+ // pointer with -XX:+UseCompactObjectHeaders) with lightweight locking;
// 2) pointer to the displaced mark in a thread's stack with stack locking; or
- // 3) pointer to the monitor object with heavy monitor locking.
+ // 3) pointer to the monitor object with heavy monitor locking when
+ // -XX:+UseObjectMonitorTable is not specified.
//
- // When these upper bits are not used, i.e., when an object is either unlocked or locked
- // with lightweight locking, HotSpot reuses fraction of the upper bits (e.g., [38:8] in
- // 64-bits VM) for caching the identity hash code. Therefore,
+ // When an object is either unlocked, locked with lightweight locking, locked with heavy
+ // monitor locking using -XX:+UseObjectMonitorTable, HotSpot reuses fraction of the upper
+ // bits (e.g., [41:11] in 64-bits VM) for caching the identity hash code.
+ // Therefore,
// 1) when lightweight locking is employed as fast locking scheme (-XX:LockingMode=2), we
- // only need to test if the object is NOT in a monitor-locked state, i.e., lock bits not
- // equals to 0b10;
+ // only need to test if UseObjectMonitorTable is specified or if the object is NOT in a
+ // monitor-locked state, i.e., lock bits not equals to 0b10;
// 2) when stack locking is employed as fast locking scheme (-XX:LockingMode=1) or no fast
// locking scheme is employed (-XX:LockingMode=0), we need to test if the object is
// unlocked, i.e., lock bits equals to 0b01.
//
// See src/hotspot/share/oops/markWord.hpp for more details.
- final Word lockBits = mark.and(lockMaskInPlace(INJECTED_VMCONFIG));
- if (probability(FAST_PATH_PROBABILITY, useObjectMonitorTable(INJECTED_VMCONFIG) ||
+ final Word lockBits = mark.and(WordFactory.unsigned(markWordLockMaskInPlace(INJECTED_VMCONFIG)));
+ if (useObjectMonitorTable(INJECTED_VMCONFIG) || probability(FAST_PATH_PROBABILITY,
useLightweightLocking(INJECTED_VMCONFIG) ? lockBits.notEqual(WordFactory.unsigned(monitorValue(INJECTED_VMCONFIG)))
: lockBits.equal(WordFactory.unsigned(unlockedValue(INJECTED_VMCONFIG))))) {
- int hash = (int) mark.unsignedShiftRight(identityHashCodeShift(INJECTED_VMCONFIG)).rawValue();
+ // `& markWord::hash_mask' is essential with -XX:+UseCompactObjectHeaders, because bit
+ // 42 might be set.
+ int hash = (int) mark.unsignedShiftRight(markWordHashCodeShift(INJECTED_VMCONFIG)).and((int) markWordHashMark(INJECTED_VMCONFIG)).rawValue();
if (probability(FAST_PATH_PROBABILITY, hash != uninitializedIdentityHashCodeValue(INJECTED_VMCONFIG))) {
return hash;
}
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotInvocationPluginHelper.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotInvocationPluginHelper.java
index 557f380fc071..d3c964bc6e88 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotInvocationPluginHelper.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotInvocationPluginHelper.java
@@ -26,9 +26,6 @@
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.ARRAY_KLASS_COMPONENT_MIRROR;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_ARRAY_KLASS_LOCATION;
-import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_CARRIER_THREAD_OOP_HANDLE_LOCATION;
-import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION;
-import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_JAVA_THREAD_SCOPED_VALUE_CACHE_HANDLE_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HOTSPOT_OOP_HANDLE_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_CARRIER_THREAD_OBJECT_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_CURRENT_THREAD_OBJECT_LOCATION;
@@ -41,17 +38,15 @@
import java.util.function.Function;
-import jdk.graal.compiler.core.common.type.AbstractPointerStamp;
import org.graalvm.word.LocationIdentity;
import jdk.graal.compiler.core.common.memory.MemoryOrderMode;
-import jdk.graal.compiler.core.common.type.ObjectStamp;
+import jdk.graal.compiler.core.common.type.AbstractPointerStamp;
import jdk.graal.compiler.core.common.type.Stamp;
import jdk.graal.compiler.core.common.type.StampFactory;
import jdk.graal.compiler.core.common.type.TypeReference;
import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig;
import jdk.graal.compiler.hotspot.nodes.CurrentJavaThreadNode;
-import jdk.graal.compiler.hotspot.nodes.VirtualThreadUpdateJFRNode;
import jdk.graal.compiler.hotspot.nodes.type.KlassPointerStamp;
import jdk.graal.compiler.nodes.NodeView;
import jdk.graal.compiler.nodes.PiNode;
@@ -61,9 +56,7 @@
import jdk.graal.compiler.nodes.gc.BarrierSet;
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import jdk.graal.compiler.nodes.memory.ReadNode;
-import jdk.graal.compiler.nodes.memory.WriteNode;
import jdk.graal.compiler.nodes.memory.address.AddressNode;
-import jdk.graal.compiler.nodes.memory.address.OffsetAddressNode;
import jdk.graal.compiler.nodes.type.StampTool;
import jdk.graal.compiler.replacements.InvocationPluginHelper;
import jdk.vm.ci.meta.JavaKind;
@@ -225,60 +218,24 @@ public ValueNode loadArrayKlass(ValueNode componentType) {
}
/**
- * Reads thread object from current thread. {@code readVirtualThread} indicates whether the
- * caller wants the current virtual thread or its carrier -- the current platform thread.
+ * Read {@code JavaThread::_threadObj}.
*/
- public ValueNode readCurrentThreadObject(boolean readVirtualThread) {
- CurrentJavaThreadNode thread = b.add(new CurrentJavaThreadNode(getWordKind()));
- // JavaThread::_vthread and JavaThread::_threadObj are never compressed
- ObjectStamp threadStamp = StampFactory.objectNonNull(TypeReference.create(b.getAssumptions(), b.getMetaAccess().lookupJavaType(Thread.class)));
- Stamp fieldStamp = StampFactory.forKind(getWordKind());
- ValueNode value = readLocation(thread, readVirtualThread ? HotSpotVMConfigField.JAVA_THREAD_THREAD_OBJECT : HotSpotVMConfigField.JAVA_THREAD_CARRIER_THREAD_OBJECT, fieldStamp);
-
- // Read the Object from the OopHandle
- AddressNode handleAddress = b.add(OffsetAddressNode.create(value));
- LocationIdentity location = readVirtualThread ? HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION : HOTSPOT_CARRIER_THREAD_OOP_HANDLE_LOCATION;
- value = b.add(new ReadNode(handleAddress, location, threadStamp, barrierSet.readBarrierType(location, handleAddress, threadStamp), MemoryOrderMode.PLAIN));
- return value;
- }
-
- /**
- * Sets {@code thread} into {@code JavaThread::_vthread}.
- */
- public void setCurrentThread(ValueNode thread) {
- CurrentJavaThreadNode javaThread = b.add(new CurrentJavaThreadNode(getWordKind()));
- ValueNode threadObjectHandle = readLocation(javaThread, HotSpotVMConfigField.JAVA_THREAD_THREAD_OBJECT, StampFactory.forKind(getWordKind()));
- AddressNode handleAddress = b.add(OffsetAddressNode.create(threadObjectHandle));
- b.add(new WriteNode(handleAddress, HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION, thread, barrierSet.writeBarrierType(HOTSPOT_CURRENT_THREAD_OOP_HANDLE_LOCATION), MemoryOrderMode.PLAIN));
- if (HotSpotReplacementsUtil.supportsVirtualThreadUpdateJFR(config)) {
- b.add(new VirtualThreadUpdateJFRNode(thread));
- }
- }
-
- private AddressNode scopedValueCacheHelper() {
- CurrentJavaThreadNode javaThread = b.add(new CurrentJavaThreadNode(getWordKind()));
- ValueNode scopedValueCacheHandle = readLocation(javaThread, HotSpotVMConfigField.JAVA_THREAD_SCOPED_VALUE_CACHE_OFFSET, StampFactory.forKind(getWordKind()));
- return b.add(OffsetAddressNode.create(scopedValueCacheHandle));
+ public ValueNode readJavaThreadThreadObj(CurrentJavaThreadNode javaThread) {
+ return readLocation(javaThread, HotSpotVMConfigField.JAVA_THREAD_CARRIER_THREAD_OBJECT, StampFactory.forKind(getWordKind()));
}
/**
- * Reads {@code JavaThread::_scopedValueCache}.
+ * Read {@code JavaThread::_vthread}.
*/
- public ValueNode readThreadScopedValueCache() {
- AddressNode handleAddress = scopedValueCacheHelper();
- ObjectStamp stamp = StampFactory.object(TypeReference.create(b.getAssumptions(), b.getMetaAccess().lookupJavaType(Object[].class)));
- return b.add(new ReadNode(handleAddress, HOTSPOT_JAVA_THREAD_SCOPED_VALUE_CACHE_HANDLE_LOCATION, stamp,
- barrierSet.readBarrierType(HOTSPOT_JAVA_THREAD_SCOPED_VALUE_CACHE_HANDLE_LOCATION, handleAddress, stamp), MemoryOrderMode.PLAIN));
+ public ValueNode readJavaThreadVthread(CurrentJavaThreadNode javaThread) {
+ return readLocation(javaThread, HotSpotVMConfigField.JAVA_THREAD_THREAD_OBJECT, StampFactory.forKind(getWordKind()));
}
/**
- * Sets {@code cache} into {@code JavaThread::_scopedValueCache}.
+ * Read {@code JavaThread::_scopedValueCache}.
*/
- public void setThreadScopedValueCache(ValueNode cache) {
- AddressNode handleAddress = scopedValueCacheHelper();
- b.add(new WriteNode(handleAddress, HOTSPOT_JAVA_THREAD_SCOPED_VALUE_CACHE_HANDLE_LOCATION, cache,
- barrierSet.writeBarrierType(HOTSPOT_JAVA_THREAD_SCOPED_VALUE_CACHE_HANDLE_LOCATION),
- MemoryOrderMode.PLAIN));
+ public ValueNode readJavaThreadScopedValueCache(CurrentJavaThreadNode javaThread) {
+ return readLocation(javaThread, HotSpotVMConfigField.JAVA_THREAD_SCOPED_VALUE_CACHE_OFFSET, StampFactory.forKind(getWordKind()));
}
/**
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java
index a33037501696..d0a434c52a16 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java
@@ -27,15 +27,19 @@
import static jdk.graal.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
import static jdk.graal.compiler.hotspot.GraalHotSpotVMConfigAccess.JDK;
import static jdk.graal.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.VERIFY_OOP;
+import static jdk.graal.compiler.nodes.CompressionNode.CompressionOp.Compress;
import java.lang.ref.Reference;
import org.graalvm.word.LocationIdentity;
+import org.graalvm.word.WordFactory;
import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.api.replacements.Fold.InjectedParameter;
+import jdk.graal.compiler.core.common.CompressEncoding;
import jdk.graal.compiler.core.common.SuppressFBWarnings;
import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor;
+import jdk.graal.compiler.core.common.type.IntegerStamp;
import jdk.graal.compiler.core.common.type.ObjectStamp;
import jdk.graal.compiler.core.common.type.Stamp;
import jdk.graal.compiler.core.common.type.TypeReference;
@@ -44,13 +48,20 @@
import jdk.graal.compiler.graph.Node.NodeIntrinsic;
import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig;
import jdk.graal.compiler.hotspot.meta.HotSpotLoweringProvider;
+import jdk.graal.compiler.hotspot.meta.HotSpotProviders;
+import jdk.graal.compiler.hotspot.nodes.HotSpotCompressionNode;
+import jdk.graal.compiler.hotspot.nodes.type.KlassPointerStamp;
import jdk.graal.compiler.hotspot.word.KlassPointer;
+import jdk.graal.compiler.hotspot.word.PointerCastNode;
import jdk.graal.compiler.nodes.CanonicalizableLocation;
import jdk.graal.compiler.nodes.CompressionNode;
+import jdk.graal.compiler.nodes.CompressionNode.CompressionOp;
import jdk.graal.compiler.nodes.ConstantNode;
import jdk.graal.compiler.nodes.NamedLocationIdentity;
import jdk.graal.compiler.nodes.NodeView;
import jdk.graal.compiler.nodes.ValueNode;
+import jdk.graal.compiler.nodes.calc.LeftShiftNode;
+import jdk.graal.compiler.nodes.calc.ZeroExtendNode;
import jdk.graal.compiler.nodes.extended.ForeignCallNode;
import jdk.graal.compiler.nodes.extended.LoadHubNode;
import jdk.graal.compiler.nodes.extended.LoadHubOrNullNode;
@@ -64,6 +75,7 @@
import jdk.graal.compiler.replacements.ReplacementsUtil;
import jdk.graal.compiler.replacements.nodes.ReadRegisterNode;
import jdk.graal.compiler.word.Word;
+import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
@@ -315,6 +327,8 @@ public static Object getPendingException(Word thread) {
public static final LocationIdentity JAVA_THREAD_CARRIER_THREAD_OBJECT_LOCATION = NamedLocationIdentity.mutable("JavaThread::_threadObj");
+ public static final LocationIdentity JAVA_THREAD_LOCK_ID_LOCATION = NamedLocationIdentity.mutable("JavaThread::_lock_id");
+
public static final LocationIdentity JAVA_THREAD_OSTHREAD_LOCATION = NamedLocationIdentity.mutable("JavaThread::_osthread");
public static final LocationIdentity JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION = NamedLocationIdentity.mutable("JavaThread::_held_monitor_count");
@@ -469,14 +483,56 @@ public ValueNode canonicalizeRead(ValueNode read, ValueNode object, ValueNode lo
}
};
+ public static final LocationIdentity COMPACT_HUB_LOCATION = new HotSpotOptimizingLocationIdentity("CompactHub") {
+ @Override
+ public ValueNode canonicalizeRead(ValueNode read, ValueNode object, ValueNode location, NodeView view, CoreProviders tool) {
+ TypeReference constantType = StampTool.typeReferenceOrNull(object);
+ if (constantType != null && constantType.isExact()) {
+ GraalHotSpotVMConfig config = ((HotSpotProviders) tool.getReplacements().getProviders()).getConfig();
+ KlassPointerStamp hubStamp = KlassPointerStamp.klassNonNull().compressed(config.getKlassEncoding());
+ ConstantNode compressedHub = ConstantNode.forConstant(hubStamp, ((HotSpotMetaspaceConstant) tool.getConstantReflection().asObjectHub(constantType.getType())).compress(),
+ tool.getMetaAccess());
+ ValueNode rawCompressedHub = PointerCastNode.create(IntegerStamp.create(32, 0, CodeUtil.mask(64 - config.markWordKlassShift)), compressedHub);
+ ValueNode rawCompressedHubWordSize = ZeroExtendNode.create(rawCompressedHub, 32, 64, NodeView.DEFAULT);
+ return LeftShiftNode.create(rawCompressedHubWordSize, ConstantNode.forInt(config.markWordKlassShift), NodeView.DEFAULT);
+ }
+ return read;
+ }
+ };
+
+ @Fold
+ public static boolean useCompactObjectHeaders(@InjectedParameter GraalHotSpotVMConfig config) {
+ return config.useCompactObjectHeaders;
+ }
+
+ @Fold
+ public static int markWordKlassShift(@InjectedParameter GraalHotSpotVMConfig config) {
+ return config.markWordKlassShift;
+ }
+
+ @NodeIntrinsic(HotSpotCompressionNode.class)
+ private static native KlassPointer compress(@ConstantNodeParameter CompressionOp op, KlassPointer hub, @ConstantNodeParameter CompressEncoding encoding);
+
@Fold
static int hubOffset(@InjectedParameter GraalHotSpotVMConfig config) {
return config.hubOffset;
}
+ @Fold
+ static CompressEncoding klassEncoding(@InjectedParameter GraalHotSpotVMConfig config) {
+ return config.getKlassEncoding();
+ }
+
public static void initializeObjectHeader(Word memory, Word markWord, KlassPointer hub) {
- memory.writeWord(markOffset(INJECTED_VMCONFIG), markWord, MARK_WORD_LOCATION);
- StoreHubNode.write(memory, hub);
+ if (useCompactObjectHeaders(INJECTED_VMCONFIG)) {
+ Word compressedHub = WordFactory.unsigned(compress(Compress, hub, klassEncoding(INJECTED_VMCONFIG)).asInt());
+ Word hubInPlace = compressedHub.shiftLeft(markWordKlassShift(INJECTED_VMCONFIG));
+ Word newMarkWord = markWord.or(hubInPlace);
+ memory.writeWord(markOffset(INJECTED_VMCONFIG), newMarkWord, MARK_WORD_LOCATION);
+ } else {
+ memory.writeWord(markOffset(INJECTED_VMCONFIG), markWord, MARK_WORD_LOCATION);
+ StoreHubNode.write(memory, hub);
+ }
}
@Fold
@@ -504,6 +560,11 @@ public static int monitorValue(@InjectedParameter GraalHotSpotVMConfig config) {
return config.monitorValue;
}
+ @Fold
+ public static int unusedMark(@InjectedParameter GraalHotSpotVMConfig config) {
+ return config.unusedMark;
+ }
+
@Fold
public static int objectMonitorOwnerOffset(@InjectedParameter GraalHotSpotVMConfig config) {
return config.objectMonitorOwner;
@@ -535,8 +596,8 @@ public static int objectMonitorSuccOffset(@InjectedParameter GraalHotSpotVMConfi
* bits afterwards due to elimination of the biased locking.
*/
@Fold
- public static int lockMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.lockMaskInPlace;
+ public static long markWordLockMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config) {
+ return config.markWordLockMaskInPlace;
}
@Fold
@@ -569,6 +630,9 @@ public static int objectAlignment(@InjectedParameter GraalHotSpotVMConfig config
@Fold
public static int instanceHeaderSize(@InjectedParameter GraalHotSpotVMConfig config) {
+ if (config.useCompactObjectHeaders) {
+ return wordSize();
+ }
return config.useCompressedClassPointers ? (2 * wordSize()) - 4 : 2 * wordSize();
}
@@ -679,6 +743,8 @@ public static int secondarySupersOffset(@InjectedParameter GraalHotSpotVMConfig
public static final LocationIdentity OBJECT_MONITOR_SUCC_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_succ");
+ public static final LocationIdentity OBJECT_MONITOR_STACK_LOCKER_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_stack_locker");
+
@Fold
public static int lockMetadataOffset(@InjectedParameter GraalHotSpotVMConfig config) {
return config.basicLockMetadataOffset;
@@ -689,6 +755,11 @@ static int heldMonitorCountOffset(@InjectedParameter GraalHotSpotVMConfig config
return config.threadHeldMonitorCountOffset;
}
+ @Fold
+ static int javaThreadLockIDOffset(@InjectedParameter GraalHotSpotVMConfig config) {
+ return config.javaThreadLockIDOffset;
+ }
+
@Fold
static int javaThreadLockStackTopOffset(@InjectedParameter GraalHotSpotVMConfig config) {
return config.threadLockStackOffset + config.lockStackTopOffset;
@@ -736,7 +807,7 @@ public static int jvmAccIsValueBasedClass(@InjectedParameter GraalHotSpotVMConfi
@Fold
public static long defaultPrototypeMarkWord(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.defaultPrototypeMarkWord();
+ return config.markWordNoHashInPlace | config.markWordNoLockInPlace;
}
@Fold
@@ -745,8 +816,13 @@ static int uninitializedIdentityHashCodeValue(@InjectedParameter GraalHotSpotVMC
}
@Fold
- static int identityHashCodeShift(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.identityHashCodeShift;
+ static int markWordHashCodeShift(@InjectedParameter GraalHotSpotVMConfig config) {
+ return config.markWordHashCodeShift;
+ }
+
+ @Fold
+ static long markWordHashMark(@InjectedParameter GraalHotSpotVMConfig config) {
+ return config.markWordHashMask;
}
/**
@@ -787,17 +863,17 @@ public static long verifyOopCounterAddress(@InjectedParameter GraalHotSpotVMConf
private static native Object verifyOopStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
public static Word loadWordFromObject(Object object, int offset) {
- ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
+ ReplacementsUtil.staticAssert(useCompactObjectHeaders(INJECTED_VMCONFIG) || offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
return loadWordFromObjectIntrinsic(object, offset, LocationIdentity.any(), getWordKind());
}
public static Word loadWordFromObject(Object object, int offset, LocationIdentity identity) {
- ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
+ ReplacementsUtil.staticAssert(useCompactObjectHeaders(INJECTED_VMCONFIG) || offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
return loadWordFromObjectIntrinsic(object, offset, identity, getWordKind());
}
public static KlassPointer loadKlassFromObject(Object object, int offset, LocationIdentity identity) {
- ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadKlassFromObject");
+ ReplacementsUtil.staticAssert(useCompactObjectHeaders(INJECTED_VMCONFIG) || offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadKlassFromObject");
return loadKlassFromObjectIntrinsic(object, offset, identity, getWordKind());
}
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/MonitorSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/MonitorSnippets.java
index 59970602b3aa..2cbc75590343 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/MonitorSnippets.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/MonitorSnippets.java
@@ -34,6 +34,7 @@
import static jdk.graal.compiler.hotspot.nodes.VMErrorNode.vmError;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.BASICLOCK_METADATA_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_LOCK_ID_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_LOCK_STACK_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_LOCK_STACK_TOP_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_OM_CACHE_LOCATION;
@@ -45,9 +46,12 @@
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_ENTRY_LIST_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_OWNER_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_RECURSION_LOCATION;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_STACK_LOCKER_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_SUCC_LOCATION;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.diagnoseSyncOnValueBasedClasses;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.heldMonitorCountOffset;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.isCAssertEnabled;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.javaThreadLockIDOffset;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.javaThreadLockStackEndOffset;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.javaThreadLockStackTopOffset;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.javaThreadOomCacheOffset;
@@ -56,9 +60,9 @@
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.klassAccessFlagsOffset;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.klassMiscFlagsOffset;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadWordFromObject;
-import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.lockMaskInPlace;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.lockMetadataOffset;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.markOffset;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.markWordLockMaskInPlace;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.monitorValue;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorCxqOffset;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorEntryListOffset;
@@ -71,6 +75,7 @@
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.shouldUseKlassMiscFlags;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.unlockedValue;
+import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.unusedMark;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.useLightweightLocking;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.useObjectMonitorTable;
import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.useStackLocking;
@@ -89,6 +94,7 @@
import static jdk.graal.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
import static jdk.graal.compiler.replacements.nodes.CStringConstant.cstring;
import static org.graalvm.word.LocationIdentity.any;
+import static org.graalvm.word.WordFactory.nullPointer;
import static org.graalvm.word.WordFactory.unsigned;
import static org.graalvm.word.WordFactory.zero;
@@ -162,7 +168,11 @@
*
* 64 bits:
* --------
- * unused:25 hash:31 -->| unused_gap:1 age:4 unused_gap:1 lock:2 (normal object)
+ * unused:22 hash:31 -->| unused_gap:4 age:4 self-fwd:1 lock:2 (normal object)
+ *
+ * 64 bits (with compact headers):
+ * --------
+ * nklass:22 hash:31 -->| unused_gap:4 age:4 self-fwd:1 lock:2 (normal object)
*
* - hash contains the identity hash value: largest value is
* 31 bits, see os::random(). Also, 64-bit vm's require
@@ -175,6 +185,7 @@
* [header | 00] locked locked regular object header (fast-locking in use)
* [header | 01] unlocked regular object header
* [ptr | 10] monitor inflated lock (header is swapped out)
+ * [header | 10] monitor inflated lock (UseObjectMonitorTable == true)
* [ptr | 11] marked used to mark an object
* [0 ............ 0| 00] inflating inflation in progress (stack-locking in use)
*
@@ -194,6 +205,16 @@
// @formatter:on
public class MonitorSnippets implements Snippets {
+ /**
+ * This helper method is for bypassing the mandatory branch probabilities for snippets.
+ *
+ * See also {@code jdk.graal.compiler.core.test.VerifySnippetProbabilities}
+ */
+ @Fold
+ public static boolean isJDK21() {
+ return JavaVersionUtil.JAVA_SPEC == 21;
+ }
+
/**
* The monitorenter snippet is slightly different from the HotSpot code:
*
@@ -229,7 +250,9 @@ public static void monitorenter(Object object, KlassPointer hub, @ConstantParame
}
if (tryFastPathLocking(object, stackPointerRegister, trace, counters, mark, lock, thread)) {
- incrementHeldMonitorCount(thread);
+ if (isJDK21() || useStackLocking(INJECTED_VMCONFIG)) {
+ incrementHeldMonitorCount(thread);
+ }
} else {
// slow-path runtime-call
monitorenterStubC(MONITORENTER, object, lock);
@@ -289,22 +312,27 @@ private static boolean tryEnterInflated(Object object, Word lock, Word mark, Wor
cacheIter = cacheIter.add(stepSize);
}
}
+
+ // Cache the monitor for unlock before trashing box. On failure to acquire
+ // the lock, the slow path will reset the entry accordingly (see CacheSetter).
+ writeMonitorCache(lock, monitor);
} else {
// mark is a pointer to the ObjectMonitor + monitorMask
- monitor = mark.subtract(HotSpotReplacementsUtil.monitorValue(INJECTED_VMCONFIG));
+ monitor = mark.subtract(monitorValue(INJECTED_VMCONFIG));
}
- int ownerOffset = HotSpotReplacementsUtil.objectMonitorOwnerOffset(INJECTED_VMCONFIG);
- Word owner = monitor.readWord(ownerOffset, HotSpotReplacementsUtil.OBJECT_MONITOR_OWNER_LOCATION);
+ int ownerOffset = objectMonitorOwnerOffset(INJECTED_VMCONFIG);
+ Word owner = monitor.readWord(ownerOffset, OBJECT_MONITOR_OWNER_LOCATION);
+ Word newOwner = isJDK21() ? thread : thread.readWord(javaThreadLockIDOffset(INJECTED_VMCONFIG), JAVA_THREAD_LOCK_ID_LOCATION);
+
// The following owner null check is essential. In the case where the null check fails, it
// avoids the subsequent bound-to-fail CAS operation, which would have caused the
// invalidation of the L1 cache of the core that runs the lock owner thread, and thus causes
// the lock to be held slightly longer.
- if (probability(FREQUENT_PROBABILITY, owner.equal(0))) {
- // it appears unlocked (owner == 0)
- if (probability(FREQUENT_PROBABILITY, monitor.logicCompareAndSwapWord(ownerOffset, owner, thread, HotSpotReplacementsUtil.OBJECT_MONITOR_OWNER_LOCATION))) {
+ if (probability(FREQUENT_PROBABILITY, owner.equal(nullPointer()))) {
+ // it appears unlocked (owner == null)
+ if (probability(FREQUENT_PROBABILITY, monitor.logicCompareAndSwapWord(ownerOffset, owner, newOwner, OBJECT_MONITOR_OWNER_LOCATION))) {
// success
- writeMonitorCache(lock, monitor);
traceObject(trace, "+lock{heavyweight:cas}", object, true);
counters.lockHeavyCas.inc();
return true;
@@ -312,11 +340,10 @@ private static boolean tryEnterInflated(Object object, Word lock, Word mark, Wor
traceObject(trace, "+lock{heavyweight:failed-cas}", object, true);
counters.lockHeavyFailedCas.inc();
}
- } else if (probability(NOT_LIKELY_PROBABILITY, owner.equal(thread))) {
- int recursionsOffset = HotSpotReplacementsUtil.objectMonitorRecursionsOffset(INJECTED_VMCONFIG);
- Word recursions = monitor.readWord(recursionsOffset, HotSpotReplacementsUtil.OBJECT_MONITOR_RECURSION_LOCATION);
- monitor.writeWord(recursionsOffset, recursions.add(1), HotSpotReplacementsUtil.OBJECT_MONITOR_RECURSION_LOCATION);
- writeMonitorCache(lock, monitor);
+ } else if (probability(NOT_LIKELY_PROBABILITY, owner.equal(newOwner))) {
+ int recursionsOffset = objectMonitorRecursionsOffset(INJECTED_VMCONFIG);
+ Word recursions = monitor.readWord(recursionsOffset, OBJECT_MONITOR_RECURSION_LOCATION);
+ monitor.writeWord(recursionsOffset, recursions.add(1), OBJECT_MONITOR_RECURSION_LOCATION);
traceObject(trace, "+lock{heavyweight:recursive}", object, true);
counters.lockHeavyRecursive.inc();
return true;
@@ -331,7 +358,7 @@ private static boolean tryStackLocking(Object object, Word lock, Word mark, Word
if (probability(SLOW_PATH_PROBABILITY, mark.and(monitorValue(INJECTED_VMCONFIG)).notEqual(0))) {
// Inflated case
// Set the lock slot's displaced mark to unused. Any non-0 value suffices.
- lock.writeWord(lockMetadataOffset(INJECTED_VMCONFIG), WordFactory.unsigned(3), BASICLOCK_METADATA_LOCATION);
+ lock.writeWord(lockMetadataOffset(INJECTED_VMCONFIG), WordFactory.unsigned(unusedMark(INJECTED_VMCONFIG)), BASICLOCK_METADATA_LOCATION);
return tryEnterInflated(object, lock, mark, thread, trace, counters);
}
@@ -463,7 +490,9 @@ public static void monitorexit(Object object, @ConstantParameter int lockDepth,
trace(trace, " lock: 0x%016lx\n", lock);
if (tryFastPathUnlocking(object, trace, counters, thread, lock)) {
- decrementHeldMonitorCount(thread);
+ if (isJDK21() || useStackLocking(INJECTED_VMCONFIG)) {
+ decrementHeldMonitorCount(thread);
+ }
} else {
monitorexitStubC(MONITOREXIT, object, lock);
}
@@ -498,7 +527,7 @@ private static boolean tryStackUnlocking(Object object, Word thread, Word lock,
Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG));
if (probability(SLOW_PATH_PROBABILITY, mark.and(monitorValue(INJECTED_VMCONFIG)).notEqual(0))) {
- return tryExitInflated(object, thread, lock, trace, counters);
+ return tryExitInflated(object, mark, thread, lock, trace, counters);
}
if (probability(VERY_FAST_PATH_PROBABILITY, Word.objectToTrackedPointer(object).logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG),
@@ -538,7 +567,7 @@ private static boolean tryLightweightUnlocking(Object object, Word thread, Word
AssertionSnippets.vmMessageC(VM_MESSAGE_C, true, cstring("Fast Unlock not monitor"), 0L, 0L, 0L);
}
}
- return tryExitInflated(object, thread, lock, trace, counters);
+ return tryExitInflated(object, mark, thread, lock, trace, counters);
}
// Pop lock-stack.
@@ -557,7 +586,7 @@ private static boolean tryLightweightUnlocking(Object object, Word thread, Word
// We elide the monitor check, let the CAS fail instead.
// Try to unlock. Transition lock bits 0b00 => 0b01
- Word markLocked = mark.and(~lockMaskInPlace(INJECTED_VMCONFIG));
+ Word markLocked = mark.and(WordFactory.unsigned(~markWordLockMaskInPlace(INJECTED_VMCONFIG)));
Word markUnlocked = mark.or(unlockedValue(INJECTED_VMCONFIG));
if (probability(FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), markLocked, markUnlocked, MARK_WORD_LOCATION))) {
traceObject(trace, "-lock{lightweight:cas}", object, false);
@@ -575,10 +604,8 @@ private static boolean tryLightweightUnlocking(Object object, Word thread, Word
return false;
}
- private static boolean tryExitInflated(Object object, Word thread, Word lock, boolean trace, Counters counters) {
+ private static boolean tryExitInflated(Object object, Word mark, Word thread, Word lock, boolean trace, Counters counters) {
// Inflated case
- // mark is a pointer to the ObjectMonitor + monitorMask
- Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG));
Word monitor;
if (useObjectMonitorTable(INJECTED_VMCONFIG)) {
monitor = lock.readWord(lockMetadataOffset(INJECTED_VMCONFIG), BASICLOCK_METADATA_LOCATION);
@@ -588,14 +615,16 @@ private static boolean tryExitInflated(Object object, Word thread, Word lock, bo
return false;
}
} else {
+ // mark is a pointer to the ObjectMonitor + monitorMask
monitor = mark.subtract(monitorValue(INJECTED_VMCONFIG));
}
int ownerOffset = objectMonitorOwnerOffset(INJECTED_VMCONFIG);
+
int recursionsOffset = objectMonitorRecursionsOffset(INJECTED_VMCONFIG);
Word recursions = monitor.readWord(recursionsOffset, OBJECT_MONITOR_RECURSION_LOCATION);
if (probability(FAST_PATH_PROBABILITY, recursions.equal(0))) {
- if (JavaVersionUtil.JAVA_SPEC == 21) {
+ if (isJDK21()) {
// recursions == 0
Word entryList = monitor.readWord(objectMonitorEntryListOffset(INJECTED_VMCONFIG), OBJECT_MONITOR_ENTRY_LIST_LOCATION);
Word cxq = monitor.readWord(objectMonitorCxqOffset(INJECTED_VMCONFIG), OBJECT_MONITOR_CXQ_LOCATION);
@@ -604,7 +633,7 @@ private static boolean tryExitInflated(Object object, Word thread, Word lock, bo
// Nobody is waiting, success
// release_store
memoryBarrier(MembarNode.FenceKind.STORE_RELEASE);
- monitor.writeWord(ownerOffset, zero());
+ monitor.writeWord(ownerOffset, nullPointer(), OBJECT_MONITOR_OWNER_LOCATION);
traceObject(trace, "-lock{heavyweight:simple}", object, false);
counters.unlockHeavySimple.inc();
return true;
@@ -614,7 +643,7 @@ private static boolean tryExitInflated(Object object, Word thread, Word lock, bo
if (probability(FREQUENT_PROBABILITY, succ.isNonNull())) {
// There may be a thread spinning on this monitor. Temporarily setting
// the monitor owner to null, and hope that the other thread will grab it.
- monitor.writeWordVolatile(ownerOffset, zero());
+ monitor.writeWordVolatile(ownerOffset, nullPointer());
succ = monitor.readWordVolatile(succOffset, OBJECT_MONITOR_SUCC_LOCATION);
if (probability(NOT_FREQUENT_PROBABILITY, succ.isNonNull())) {
// We manage to release the monitor before the other running thread even
@@ -687,8 +716,8 @@ private static void decrementHeldMonitorCount(Word thread) {
}
private static void updateHeldMonitorCount(Word thread, int increment) {
- Word heldMonitorCount = thread.readWord(HotSpotReplacementsUtil.heldMonitorCountOffset(INJECTED_VMCONFIG), HotSpotReplacementsUtil.JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION);
- thread.writeWord(HotSpotReplacementsUtil.heldMonitorCountOffset(INJECTED_VMCONFIG), heldMonitorCount.add(increment), HotSpotReplacementsUtil.JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION);
+ Word heldMonitorCount = thread.readWord(heldMonitorCountOffset(INJECTED_VMCONFIG), JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION);
+ thread.writeWord(heldMonitorCountOffset(INJECTED_VMCONFIG), heldMonitorCount.add(increment), JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION);
}
@Fold
@@ -816,7 +845,8 @@ public Templates(OptionValues options, SnippetCounter.Group.Factory factory, Hot
JAVA_THREAD_LOCK_STACK_LOCATION,
JAVA_THREAD_LOCK_STACK_TOP_LOCATION,
JAVA_THREAD_OM_CACHE_LOCATION,
- JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION};
+ JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION,
+ JAVA_THREAD_LOCK_ID_LOCATION};
exitLocations = new LocationIdentity[]{
JAVA_THREAD_LOCK_STACK_LOCATION,
JAVA_THREAD_LOCK_STACK_TOP_LOCATION,
@@ -826,10 +856,13 @@ public Templates(OptionValues options, SnippetCounter.Group.Factory factory, Hot
OBJECT_MONITOR_ENTRY_LIST_LOCATION,
OBJECT_MONITOR_RECURSION_LOCATION,
OBJECT_MONITOR_SUCC_LOCATION,
+ OBJECT_MONITOR_STACK_LOCKER_LOCATION,
MARK_WORD_LOCATION,
JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION};
} else {
- enterLocations = new LocationIdentity[]{JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION};
+ enterLocations = new LocationIdentity[]{
+ JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION,
+ JAVA_THREAD_LOCK_ID_LOCATION};
exitLocations = new LocationIdentity[]{
BASICLOCK_METADATA_LOCATION,
OBJECT_MONITOR_OWNER_LOCATION,
@@ -837,6 +870,7 @@ public Templates(OptionValues options, SnippetCounter.Group.Factory factory, Hot
OBJECT_MONITOR_ENTRY_LIST_LOCATION,
OBJECT_MONITOR_RECURSION_LOCATION,
OBJECT_MONITOR_SUCC_LOCATION,
+ OBJECT_MONITOR_STACK_LOCKER_LOCATION,
MARK_WORD_LOCATION,
JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION};
}
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/word/HotSpotOperation.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/word/HotSpotOperation.java
index 3b1c02665350..878f20dd0dd1 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/word/HotSpotOperation.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/word/HotSpotOperation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
enum HotspotOpcode {
FROM_POINTER,
+ FROM_COMPRESSED_POINTER,
TO_KLASS_POINTER,
TO_METHOD_POINTER,
POINTER_EQ,
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/word/MetaspacePointer.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/word/MetaspacePointer.java
index 9a1e4b826022..e4358ccbfa1f 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/word/MetaspacePointer.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/word/MetaspacePointer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
*/
package jdk.graal.compiler.hotspot.word;
+import static jdk.graal.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.FROM_COMPRESSED_POINTER;
import static jdk.graal.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.FROM_POINTER;
import static jdk.graal.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.IS_NULL;
@@ -48,6 +49,9 @@ public abstract class MetaspacePointer {
@HotSpotOperation(opcode = FROM_POINTER)
public abstract Word asWord();
+ @HotSpotOperation(opcode = FROM_COMPRESSED_POINTER)
+ public abstract int asInt();
+
/**
* Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
* bytes.
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/word/PointerCastNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/word/PointerCastNode.java
index 16c3d4b24e43..a1e4f28415aa 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/word/PointerCastNode.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/word/PointerCastNode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,21 +30,21 @@
import jdk.graal.compiler.core.common.type.Stamp;
import jdk.graal.compiler.graph.Node;
import jdk.graal.compiler.graph.NodeClass;
-import jdk.graal.compiler.nodes.spi.Canonicalizable;
-import jdk.graal.compiler.nodes.spi.CanonicalizerTool;
import jdk.graal.compiler.hotspot.word.HotSpotOperation.HotspotOpcode;
import jdk.graal.compiler.nodeinfo.NodeInfo;
import jdk.graal.compiler.nodes.NodeView;
import jdk.graal.compiler.nodes.ValueNode;
import jdk.graal.compiler.nodes.calc.FloatingNode;
+import jdk.graal.compiler.nodes.spi.Canonicalizable;
+import jdk.graal.compiler.nodes.spi.CanonicalizerTool;
import jdk.graal.compiler.nodes.spi.LIRLowerable;
import jdk.graal.compiler.nodes.spi.NodeLIRBuilderTool;
-
import jdk.vm.ci.meta.Value;
/**
- * Cast between Word and metaspace pointers exposed by the {@link HotspotOpcode#FROM_POINTER} and
- * {@link HotspotOpcode#TO_KLASS_POINTER} operations.
+ * Cast between Word and metaspace pointers exposed by the {@link HotspotOpcode#FROM_POINTER},
+ * {@link HotspotOpcode#FROM_COMPRESSED_POINTER} and {@link HotspotOpcode#TO_KLASS_POINTER}
+ * operations.
*/
@NodeInfo(cycles = CYCLES_0, size = SIZE_0)
public final class PointerCastNode extends FloatingNode implements Canonicalizable, LIRLowerable, Node.ValueNumberable {
diff --git a/espresso/mx.espresso/suite.py b/espresso/mx.espresso/suite.py
index ccbf65c49780..2c597c4409e9 100644
--- a/espresso/mx.espresso/suite.py
+++ b/espresso/mx.espresso/suite.py
@@ -222,7 +222,6 @@
"native": "shared_lib",
"deliverable": "nespresso",
"platformDependent": True,
- "use_jdk_headers": True,
"buildDependencies": [
"com.oracle.truffle.espresso.mokapot",
],
@@ -283,7 +282,6 @@
"native": "shared_lib",
"deliverable": "jvm",
"platformDependent": True,
- "use_jdk_headers": True,
"os_arch": {
"darwin": {
"": {
diff --git a/espresso/src/com.oracle.truffle.espresso.mokapot/include/jni.h b/espresso/src/com.oracle.truffle.espresso.mokapot/include/jni.h
index 010bbc0ea020..303ed2d1530c 100644
--- a/espresso/src/com.oracle.truffle.espresso.mokapot/include/jni.h
+++ b/espresso/src/com.oracle.truffle.espresso.mokapot/include/jni.h
@@ -4,7 +4,9 @@
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -37,10 +39,15 @@
#include
#include
-/* jni_md.h contains the machine-dependent typedefs for jbyte, jint
+/* jni_.h contains the machine-dependent typedefs for jbyte, jint
and jlong */
-
-#include "jni_md.h"
+#if defined(_WIN32)
+#include "jni_windows.h"
+#elif defined(__linux__) || defined(__APPLE__)
+#include "jni_unix.h"
+#else
+#error unknown platform
+#endif
#ifdef __cplusplus
extern "C" {
diff --git a/espresso/src/com.oracle.truffle.espresso.mokapot/include/jni_unix.h b/espresso/src/com.oracle.truffle.espresso.mokapot/include/jni_unix.h
new file mode 100644
index 000000000000..6e583da7147e
--- /dev/null
+++ b/espresso/src/com.oracle.truffle.espresso.mokapot/include/jni_unix.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1996, 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.
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#ifndef __has_attribute
+ #define __has_attribute(x) 0
+#endif
+
+#ifndef JNIEXPORT
+ #if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
+ #ifdef ARM
+ #define JNIEXPORT __attribute__((externally_visible,visibility("default")))
+ #else
+ #define JNIEXPORT __attribute__((visibility("default")))
+ #endif
+ #else
+ #define JNIEXPORT
+ #endif
+#endif
+
+#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
+ #ifdef ARM
+ #define JNIIMPORT __attribute__((externally_visible,visibility("default")))
+ #else
+ #define JNIIMPORT __attribute__((visibility("default")))
+ #endif
+#else
+ #define JNIIMPORT
+#endif
+
+#define JNICALL
+
+typedef int jint;
+#ifdef _LP64
+typedef long jlong;
+#else
+typedef long long jlong;
+#endif
+
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
diff --git a/espresso/src/com.oracle.truffle.espresso.mokapot/include/jni_windows.h b/espresso/src/com.oracle.truffle.espresso.mokapot/include/jni_windows.h
new file mode 100644
index 000000000000..b8c144fb047f
--- /dev/null
+++ b/espresso/src/com.oracle.truffle.espresso.mokapot/include/jni_windows.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1996, 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.
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#ifndef JNIEXPORT
+ #define JNIEXPORT __declspec(dllexport)
+#endif
+#define JNIIMPORT __declspec(dllimport)
+#define JNICALL __stdcall
+
+// 'long' is always 32 bit on windows so this matches what jdk expects
+typedef long jint;
+typedef __int64 jlong;
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
diff --git a/espresso/src/com.oracle.truffle.espresso.native/include/jni.h b/espresso/src/com.oracle.truffle.espresso.native/include/jni.h
index 010bbc0ea020..303ed2d1530c 100644
--- a/espresso/src/com.oracle.truffle.espresso.native/include/jni.h
+++ b/espresso/src/com.oracle.truffle.espresso.native/include/jni.h
@@ -4,7 +4,9 @@
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -37,10 +39,15 @@
#include
#include
-/* jni_md.h contains the machine-dependent typedefs for jbyte, jint
+/* jni_.h contains the machine-dependent typedefs for jbyte, jint
and jlong */
-
-#include "jni_md.h"
+#if defined(_WIN32)
+#include "jni_windows.h"
+#elif defined(__linux__) || defined(__APPLE__)
+#include "jni_unix.h"
+#else
+#error unknown platform
+#endif
#ifdef __cplusplus
extern "C" {
diff --git a/espresso/src/com.oracle.truffle.espresso.native/include/jni_unix.h b/espresso/src/com.oracle.truffle.espresso.native/include/jni_unix.h
new file mode 100644
index 000000000000..6e583da7147e
--- /dev/null
+++ b/espresso/src/com.oracle.truffle.espresso.native/include/jni_unix.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1996, 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.
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#ifndef __has_attribute
+ #define __has_attribute(x) 0
+#endif
+
+#ifndef JNIEXPORT
+ #if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
+ #ifdef ARM
+ #define JNIEXPORT __attribute__((externally_visible,visibility("default")))
+ #else
+ #define JNIEXPORT __attribute__((visibility("default")))
+ #endif
+ #else
+ #define JNIEXPORT
+ #endif
+#endif
+
+#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
+ #ifdef ARM
+ #define JNIIMPORT __attribute__((externally_visible,visibility("default")))
+ #else
+ #define JNIIMPORT __attribute__((visibility("default")))
+ #endif
+#else
+ #define JNIIMPORT
+#endif
+
+#define JNICALL
+
+typedef int jint;
+#ifdef _LP64
+typedef long jlong;
+#else
+typedef long long jlong;
+#endif
+
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
diff --git a/espresso/src/com.oracle.truffle.espresso.native/include/jni_windows.h b/espresso/src/com.oracle.truffle.espresso.native/include/jni_windows.h
new file mode 100644
index 000000000000..b8c144fb047f
--- /dev/null
+++ b/espresso/src/com.oracle.truffle.espresso.native/include/jni_windows.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1996, 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.
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#ifndef JNIEXPORT
+ #define JNIEXPORT __declspec(dllexport)
+#endif
+#define JNIIMPORT __declspec(dllimport)
+#define JNICALL __stdcall
+
+// 'long' is always 32 bit on windows so this matches what jdk expects
+typedef long jint;
+typedef __int64 jlong;
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
diff --git a/sdk/mx.sdk/mx_sdk_benchmark.py b/sdk/mx.sdk/mx_sdk_benchmark.py
index b9feb879d9eb..5e09a196746d 100644
--- a/sdk/mx.sdk/mx_sdk_benchmark.py
+++ b/sdk/mx.sdk/mx_sdk_benchmark.py
@@ -1650,9 +1650,6 @@ def postprocessRunArgs(self, benchname, runArgs):
def vmArgs(self, bmSuiteArgs):
vm_args = super(RenaissanceBenchmarkSuite, self).vmArgs(bmSuiteArgs)
-
- # Renaissance issue #439
- vm_args.append("-Djava.security.manager=allow")
return vm_args
def createCommandLineArgs(self, benchmarks, bmSuiteArgs):
diff --git a/sdk/mx.sdk/mx_sdk_vm.py b/sdk/mx.sdk/mx_sdk_vm.py
index bd36e9a1ba12..a45d19face9f 100644
--- a/sdk/mx.sdk/mx_sdk_vm.py
+++ b/sdk/mx.sdk/mx_sdk_vm.py
@@ -1026,9 +1026,6 @@ def jlink_new_jdk(jdk, dst_jdk_dir, module_dists, ignore_dists,
module_names = frozenset((m.name for m in modules))
all_module_names = frozenset(list(jdk_modules.keys())) | module_names
- # Edit lib/security/default.policy in java.base
- patched_java_base = _patch_default_security_policy(build_dir, jmods_dir, dst_jdk_dir)
-
# Now build the new JDK image with jlink
jlink = [jdk.javac.replace('javac', 'jlink')]
jlink_persist = []
@@ -1040,7 +1037,12 @@ def jlink_new_jdk(jdk, dst_jdk_dir, module_dists, ignore_dists,
jlink.append('--add-modules=' + ','.join(_get_image_root_modules(root_module_names, module_names, jdk_modules.keys(), use_upgrade_module_path)))
jlink_persist.append('--add-modules=jdk.internal.vm.ci')
- module_path = patched_java_base + os.pathsep + jmods_dir
+ # Edit lib/security/default.policy in java.base if prior to JDK 24.
+ # GR-59085 deprecated the security manager in JDK 24 so no policy exists.
+ module_path = jmods_dir
+ if jdk.javaCompliance < '24':
+ patched_java_base = _patch_default_security_policy(build_dir, jmods_dir, dst_jdk_dir)
+ module_path = patched_java_base + os.pathsep + jmods_dir
class TempJmods:
"""
diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsThreadCpuTimeSupport.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsThreadCpuTimeSupport.java
index 50544324bce2..2c00384c01e6 100644
--- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsThreadCpuTimeSupport.java
+++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsThreadCpuTimeSupport.java
@@ -55,7 +55,7 @@ public long getThreadCpuTime(IsolateThread isolateThread, boolean includeSystemT
return getThreadCpuTime(hThread, includeSystemTime);
}
- @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-23+26/src/hotspot/os/windows/os_windows.cpp#L4960-L4976")
+ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/hotspot/os/windows/os_windows.cpp#L4787-L4803")
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static long getThreadCpuTime(HANDLE hThread, boolean includeSystemTime) {
FILETIME create = StackValue.get(FILETIME.class);
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/LibCHelper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/LibCHelper.java
index 7b26c78e55b8..6a2803c84c4d 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/LibCHelper.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/LibCHelper.java
@@ -47,12 +47,12 @@ public class LibCHelper {
public static class Locale {
@CFunction(transition = Transition.TO_NATIVE)
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+17/src/java.base/unix/native/libjava/java_props_md.c#L93-L357")
- @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+17/src/java.base/windows/native/libjava/java_props_md.c#L321-L715")
+ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/java.base/windows/native/libjava/java_props_md.c#L321-L713")
public static native CCharPointerPointer parseDisplayLocale();
@CFunction(transition = Transition.TO_NATIVE)
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+17/src/java.base/unix/native/libjava/java_props_md.c#L93-L357")
- @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+17/src/java.base/windows/native/libjava/java_props_md.c#L321-L715")
+ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/java.base/windows/native/libjava/java_props_md.c#L321-L713")
public static native CCharPointerPointer parseFormatLocale();
}
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/attach/AttachListenerThread.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/attach/AttachListenerThread.java
index 718357e81510..b824b39dd37d 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/attach/AttachListenerThread.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/attach/AttachListenerThread.java
@@ -96,7 +96,7 @@ private static void handleJcmd(AttachOperation op) {
}
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+18/src/hotspot/share/services/diagnosticFramework.cpp#L383-L420")
- @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+18/src/hotspot/share/services/diagnosticFramework.cpp#L422-L439")
+ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/hotspot/share/services/diagnosticFramework.cpp#L422-L439")
private static String parseAndExecute(String input) throws Throwable {
String[] args = StringUtil.split(input, " ");
String cmdName = args[0];
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java
index fba1a45c9be1..7ed5d698a66b 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java
@@ -48,9 +48,9 @@
@CContext(ContainerLibraryDirectives.class)
@CLibrary(value = "svm_container", requireStatic = true, dependsOn = "m")
// The following annotations are for files in `src/hotspot`, which are copied from the JDK
-@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/java.base/share/native/include/jni.h")
-@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/java.base/unix/native/include/jni_md.h")
-@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/os/linux/cgroupSubsystem_linux.cpp")
+@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/java.base/share/native/include/jni.h")
+@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/java.base/unix/native/include/jni_md.h")
+@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/hotspot/os/linux/cgroupSubsystem_linux.cpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/os/linux/cgroupSubsystem_linux.hpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/os/linux/cgroupUtil_linux.cpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/os/linux/cgroupUtil_linux.hpp")
@@ -63,16 +63,16 @@
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+21/src/hotspot/os/linux/os_linux.cpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/os/linux/os_linux.hpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/os/linux/os_linux.inline.hpp")
-@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/os/posix/include/jvm_md.h")
-@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+20/src/hotspot/os/posix/os_posix.cpp")
+@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/hotspot/os/posix/include/jvm_md.h")
+@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/hotspot/os/posix/os_posix.cpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+20/src/hotspot/os/posix/os_posix.hpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/os/posix/os_posix.inline.hpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/share/memory/allocation.hpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/share/memory/allocation.inline.hpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/share/memory/allStatic.hpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/share/nmt/memTag.hpp")
-@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+22/src/hotspot/share/runtime/os.cpp")
-@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+20/src/hotspot/share/runtime/os.hpp")
+@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/hotspot/share/runtime/os.cpp")
+@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/hotspot/share/runtime/os.hpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/share/runtime/os.inline.hpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/share/utilities/checkedCast.hpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/share/utilities/compilerWarnings_gcc.hpp")
@@ -85,7 +85,7 @@
// The following annotations are for files in `src/svm`, which are completely customized for SVM
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/share/logging/log.hpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/share/memory/allocation.cpp")
-@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+19/src/hotspot/share/runtime/globals.hpp")
+@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/hotspot/share/runtime/globals.hpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+22/src/hotspot/share/utilities/debug.cpp")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+16/src/hotspot/share/utilities/debug.hpp")
public class ContainerLibrary {
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/AccessControllerUtil.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/AccessControllerUtil.java
index 38b2152b4ffa..188662982abb 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/AccessControllerUtil.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/AccessControllerUtil.java
@@ -29,9 +29,10 @@
import java.util.ArrayDeque;
import java.util.Objects;
-import com.oracle.svm.core.util.VMError;
import com.oracle.svm.util.ReflectionUtil;
+import jdk.graal.compiler.serviceprovider.JavaVersionUtil;
+
/**
* Stack for storing AccessControlContexts. Used in conjunction with
* {@code StackAccessControlContextVisitor}.
@@ -104,10 +105,7 @@ public class AccessControllerUtil {
public static final AccessControlContext DISALLOWED_CONTEXT_MARKER;
static {
- try {
- DISALLOWED_CONTEXT_MARKER = ReflectionUtil.lookupConstructor(AccessControlContext.class, ProtectionDomain[].class, boolean.class).newInstance(new ProtectionDomain[0], true);
- } catch (ReflectiveOperationException ex) {
- throw VMError.shouldNotReachHere(ex);
- }
+ DISALLOWED_CONTEXT_MARKER = JavaVersionUtil.JAVA_SPEC > 21 ? null
+ : ReflectionUtil.newInstance(ReflectionUtil.lookupConstructor(AccessControlContext.class, ProtectionDomain[].class, boolean.class), new ProtectionDomain[0], true);
}
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java
index 0e414850543c..d6e684b47a7e 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java
@@ -428,7 +428,7 @@ private static String getProperty(String key, String def) {
* passed to the image builder.
*/
@Alias @RecomputeFieldValue(kind = Kind.FromAlias, isFinal = true) //
- private static int allowSecurityManager = 1;
+ @TargetElement(onlyWith = JDK21OrEarlier.class) private static int allowSecurityManager = 1;
/**
* We do not support the {@link SecurityManager} so this method must throw a
@@ -440,6 +440,7 @@ private static String getProperty(String key, String def) {
*/
@Substitute
@SuppressWarnings({"removal", "javadoc"})
+ @TargetElement(onlyWith = JDK21OrEarlier.class)
private static void setSecurityManager(SecurityManager sm) {
if (sm != null) {
/* Read the property collected at isolate creation as that is what happens on the JVM */
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java
index d48c3330709e..23dc62dcaca2 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java
@@ -75,7 +75,7 @@
* All security checks are disabled.
*/
-@TargetClass(java.security.AccessController.class)
+@TargetClass(value = java.security.AccessController.class, onlyWith = JDK21OrEarlier.class)
@Platforms(InternalPlatform.NATIVE_ONLY.class)
@SuppressWarnings({"unused"})
final class Target_java_security_AccessController {
@@ -432,11 +432,11 @@ public boolean test(Class> originalClass) {
}
}
-@TargetClass(value = java.security.Policy.class, innerClass = "PolicyInfo")
+@TargetClass(value = java.security.Policy.class, innerClass = "PolicyInfo", onlyWith = JDK21OrEarlier.class)
final class Target_java_security_Policy_PolicyInfo {
}
-@TargetClass(java.security.Policy.class)
+@TargetClass(value = java.security.Policy.class, onlyWith = JDK21OrEarlier.class)
final class Target_java_security_Policy {
@Delete //
@@ -503,7 +503,7 @@ public boolean implies(ProtectionDomain domain, Permission permission) {
* version is more fool-proof in case someone manually registers security providers for reflective
* instantiation.
*/
-@TargetClass(className = "sun.security.provider.PolicySpiFile")
+@TargetClass(className = "sun.security.provider.PolicySpiFile", onlyWith = JDK21OrEarlier.class)
@SuppressWarnings({"unused", "static-method", "deprecation"})
final class Target_sun_security_provider_PolicySpiFile {
@@ -536,7 +536,7 @@ private void engineRefresh() {
}
@Delete("Substrate VM does not use SecurityManager, so loading a security policy file would be misleading")
-@TargetClass(className = "sun.security.provider.PolicyFile")
+@TargetClass(className = "sun.security.provider.PolicyFile", onlyWith = JDK21OrEarlier.class)
final class Target_sun_security_provider_PolicyFile {
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_security_AccessControlContext.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_security_AccessControlContext.java
index cfd7d956e86a..1602bd8bf127 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_security_AccessControlContext.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_security_AccessControlContext.java
@@ -34,7 +34,7 @@
import sun.security.util.Debug;
-@TargetClass(java.security.AccessControlContext.class)
+@TargetClass(value = java.security.AccessControlContext.class, onlyWith = JDK21OrEarlier.class)
final class Target_java_security_AccessControlContext {
@Alias //
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/headers/JNIFunctionPointerTypes.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/headers/JNIFunctionPointerTypes.java
index 95420cac519d..63ffc9533463 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/headers/JNIFunctionPointerTypes.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/headers/JNIFunctionPointerTypes.java
@@ -262,6 +262,11 @@ public interface IsSameObjectFunctionPointer extends CFunctionPointer {
boolean invoke(JNIEnvironment env, JNIObjectHandle obj1, JNIObjectHandle obj2);
}
+ public interface MonitorEnterExitFunctionPointer extends CFunctionPointer {
+ @InvokeCFunctionPointer
+ int invoke(JNIEnvironment env, JNIObjectHandle obj);
+ }
+
private JNIFunctionPointerTypes() {
}
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/headers/JNINativeInterface.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/headers/JNINativeInterface.java
index 3351724ed326..b30e7b449ac1 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/headers/JNINativeInterface.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/headers/JNINativeInterface.java
@@ -63,6 +63,7 @@
import com.oracle.svm.core.jni.headers.JNIFunctionPointerTypes.IsAssignableFromFunctionPointer;
import com.oracle.svm.core.jni.headers.JNIFunctionPointerTypes.IsInstanceOfFunctionPointer;
import com.oracle.svm.core.jni.headers.JNIFunctionPointerTypes.IsSameObjectFunctionPointer;
+import com.oracle.svm.core.jni.headers.JNIFunctionPointerTypes.MonitorEnterExitFunctionPointer;
import com.oracle.svm.core.jni.headers.JNIFunctionPointerTypes.NewByteArrayFunctionPointer;
import com.oracle.svm.core.jni.headers.JNIFunctionPointerTypes.NewGlobalRefFunctionPointer;
import com.oracle.svm.core.jni.headers.JNIFunctionPointerTypes.NewObjectAFunctionPointer;
@@ -1372,16 +1373,16 @@ public interface JNINativeInterface extends PointerBase {
void setUnregisterNatives(CFunctionPointer p);
@CField
- CFunctionPointer getMonitorEnter();
+ MonitorEnterExitFunctionPointer getMonitorEnter();
@CField
- void setMonitorEnter(CFunctionPointer p);
+ void setMonitorEnter(MonitorEnterExitFunctionPointer p);
@CField
- CFunctionPointer getMonitorExit();
+ MonitorEnterExitFunctionPointer getMonitorExit();
@CField
- void setMonitorExit(CFunctionPointer p);
+ void setMonitorExit(MonitorEnterExitFunctionPointer p);
@CField
CFunctionPointer getGetJavaVM();
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java
index 2e034ef9b3ba..8a7c56564940 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java
@@ -36,6 +36,7 @@
import com.oracle.svm.core.jfr.events.JavaMonitorWaitEvent;
import com.oracle.svm.core.thread.JavaThreads;
import com.oracle.svm.core.util.BasedOnJDKClass;
+import com.oracle.svm.core.util.BasedOnJDKFile;
import jdk.internal.misc.Unsafe;
@@ -282,6 +283,7 @@ protected int getSpinAttempts(int parks) {
// see AbstractQueuedLongSynchronizer.acquire(Node, long, false, false, false, 0L)
@SuppressWarnings("all")
+ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+24/src/hotspot/share/runtime/objectMonitor.cpp#L895-L930")
final int acquire(Node node, long arg) {
Thread current = Thread.currentThread();
/* Spinning logic is SVM-specific. */
@@ -289,6 +291,15 @@ final int acquire(Node node, long arg) {
int spins = getSpinAttempts(parks);
boolean first = false;
Node pred = null; // predecessor of node when enqueued
+ long recheckNanos = -1;
+ if (JavaThreads.isCurrentThreadVirtualAndPinned()) {
+ /*
+ * Do not park indefinitely and instead periodically retry acquiring the monitor. This
+ * avoids liveness trouble when all carrier threads have virtual threads pinned to them
+ * and so a queued successor cannot be scheduled when it is unparked.
+ */
+ recheckNanos = 1_000_000;
+ }
for (;;) {
if (!first && (pred = (node == null) ? null : node.prev) != null && !(first = (head == pred))) {
@@ -353,7 +364,16 @@ final int acquire(Node node, long arg) {
parks++;
spins = getSpinAttempts(parks);
try {
- LockSupport.park(this);
+ if (recheckNanos == -1) {
+ LockSupport.park(this);
+ } else {
+ LockSupport.parkNanos(this, recheckNanos);
+ if (tryAcquire(arg)) {
+ cancelAcquire(node);
+ return 1;
+ }
+ recheckNanos = Math.min(recheckNanos << 3, 1_000_000_000);
+ }
} catch (Error | RuntimeException ex) {
cancelAcquire(node); // cancel & rethrow
throw ex;
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java
index 7a458f0a0c65..49508dcec039 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java
@@ -113,12 +113,16 @@ public class MultiThreadedMonitorSupport extends MonitorSupport {
static {
try {
+ HashMap, Boolean> monitorTypes = new HashMap<>();
/*
* The com.oracle.svm.core.WeakIdentityHashMap used to model the
* com.oracle.svm.core.monitor.MultiThreadedMonitorSupport#additionalMonitors map uses
- * java.lang.ref.ReferenceQueue internally.
+ * java.lang.ref.ReferenceQueue internally. The ReferenceQueue uses the inner static
+ * class Lock for all its locking needs.
*/
- HashMap, Boolean> monitorTypes = new HashMap<>();
+ if (JavaVersionUtil.JAVA_SPEC > 21) {
+ monitorTypes.put(Class.forName("java.lang.ref.ReferenceQueue$Lock"), false);
+ }
/* The WeakIdentityHashMap also synchronizes on its internal ReferenceQueue field. */
monitorTypes.put(java.lang.ref.ReferenceQueue.class, false);
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java
index 2b19371ee09e..7edad49d9e46 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java
@@ -382,7 +382,9 @@ static void initializeNewThread(
PlatformThreads.setThreadStatus(fromTarget(tjlt), ThreadStatus.NEW);
- tjlt.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext();
+ if (JavaVersionUtil.JAVA_SPEC == 21) {
+ tjlt.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext();
+ }
initNewThreadLocalsAndLoader(tjlt, inheritThreadLocals, parent);
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreadsFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreadsFeature.java
index c76db9be11cd..ac80b9c4a0d6 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreadsFeature.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreadsFeature.java
@@ -25,12 +25,18 @@
package com.oracle.svm.core.thread;
import com.oracle.svm.core.feature.InternalFeature;
+import com.oracle.svm.util.ReflectionUtil;
+
+import jdk.graal.compiler.serviceprovider.JavaVersionUtil;
public abstract class JavaThreadsFeature implements InternalFeature {
protected static long threadId(Thread thread) {
if (thread == PlatformThreads.singleton().mainThread) {
- return 1;
+ if (JavaVersionUtil.JAVA_SPEC <= 21) {
+ return 1;
+ }
+ return ReflectionUtil.readStaticField(Thread.class, "PRIMORDIAL_TID");
}
return JavaThreads.getThreadId(thread);
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java
index 4ba7f1453517..26385ae097cf 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java
@@ -52,6 +52,7 @@
import jdk.graal.compiler.api.directives.GraalDirectives;
import jdk.graal.compiler.replacements.ReplacementsUtil;
+import jdk.graal.compiler.serviceprovider.JavaVersionUtil;
@TargetClass(Thread.class)
@SuppressWarnings({"unused"})
@@ -115,6 +116,7 @@ public final class Target_java_lang_Thread {
*/
@Alias //
@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) //
+ @TargetElement(onlyWith = JDK21OrEarlier.class) //
public AccessControlContext inheritedAccessControlContext;
@Alias //
@@ -215,6 +217,7 @@ void setCurrentThread(Thread thread) {
@Substitute
@SuppressWarnings({"unused"})
@Platforms(InternalPlatform.NATIVE_ONLY.class)
+ @TargetElement(onlyWith = JDK21OrEarlier.class)
private Target_java_lang_Thread(
ThreadGroup g,
String name,
@@ -234,6 +237,27 @@ private Target_java_lang_Thread(
this.scopedValueBindings = NEW_THREAD_BINDINGS;
}
+ @Substitute
+ @Platforms(InternalPlatform.NATIVE_ONLY.class)
+ @TargetElement(onlyWith = JDKLatest.class)
+ private Target_java_lang_Thread(
+ ThreadGroup g,
+ String name,
+ int characteristics,
+ Runnable target,
+ long stackSize) {
+ /* Non-0 instance field initialization. */
+ this.interruptLock = new Object();
+ /* Injected Target_java_lang_Thread instance field initialization. */
+ this.threadData = new ThreadData();
+
+ String nameLocal = (name != null) ? name : genThreadName();
+ boolean inheritThreadLocals = (characteristics & NO_INHERIT_THREAD_LOCALS) == 0;
+ JavaThreads.initializeNewThread(this, g, target, nameLocal, stackSize, null, inheritThreadLocals);
+
+ this.scopedValueBindings = NEW_THREAD_BINDINGS;
+ }
+
@Substitute
static String genThreadName() {
int threadNum = JavaThreads.JavaThreadNumberSingleton.singleton().threadInitNumber.incrementAndGet();
@@ -252,7 +276,9 @@ private Target_java_lang_Thread(String name, int characteristics, boolean bound)
this.name = (name != null) ? name : "";
this.tid = Target_java_lang_Thread_ThreadIdentifiers.next();
- this.inheritedAccessControlContext = Target_java_lang_Thread_Constants.NO_PERMISSIONS_ACC;
+ if (JavaVersionUtil.JAVA_SPEC == 21) {
+ this.inheritedAccessControlContext = Target_java_lang_Thread_Constants.NO_PERMISSIONS_ACC;
+ }
boolean inheritThreadLocals = (characteristics & NO_INHERIT_THREAD_LOCALS) == 0;
JavaThreads.initNewThreadLocalsAndLoader(this, inheritThreadLocals, Thread.currentThread());
@@ -538,6 +564,7 @@ boolean isTerminated() {
final class Target_java_lang_Thread_Constants {
// Checkstyle: stop
@SuppressWarnings("removal") //
+ @TargetElement(onlyWith = JDK21OrEarlier.class) //
@Alias static AccessControlContext NO_PERMISSIONS_ACC;
@Alias static ThreadGroup VTHREAD_GROUP;
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java
index 9bc620107258..98b4ed23ece4 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java
@@ -61,8 +61,7 @@ public final class Target_java_lang_VirtualThread {
// Checkstyle: stop
@Alias static int NEW;
@Alias static int STARTED;
- @Alias //
- @TargetElement(onlyWith = JDK21OrEarlier.class) static int RUNNABLE;
+ @TargetElement(onlyWith = JDK21OrEarlier.class) @Alias static int RUNNABLE;
@Alias static int RUNNING;
@Alias static int PARKING;
@Alias static int PARKED;
@@ -75,6 +74,13 @@ public final class Target_java_lang_VirtualThread {
@TargetElement(onlyWith = JDKLatest.class) @Alias static int TIMED_PARKED;
@TargetElement(onlyWith = JDKLatest.class) @Alias static int TIMED_PINNED;
@TargetElement(onlyWith = JDKLatest.class) @Alias static int UNPARKED;
+ @TargetElement(onlyWith = JDKLatest.class) @Alias static int BLOCKING;
+ @TargetElement(onlyWith = JDKLatest.class) @Alias static int BLOCKED;
+ @TargetElement(onlyWith = JDKLatest.class) @Alias static int UNBLOCKED;
+ @TargetElement(onlyWith = JDKLatest.class) @Alias static int WAITING;
+ @TargetElement(onlyWith = JDKLatest.class) @Alias static int WAIT;
+ @TargetElement(onlyWith = JDKLatest.class) @Alias static int TIMED_WAITING;
+ @TargetElement(onlyWith = JDKLatest.class) @Alias static int TIMED_WAIT;
@Alias static Target_jdk_internal_vm_ContinuationScope VTHREAD_SCOPE;
/**
@@ -111,6 +117,14 @@ public final class Target_java_lang_VirtualThread {
*/
@Inject @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = NondefaultSchedulerSupplier.class) //
private Executor nondefaultScheduler;
+
+ @TargetElement(onlyWith = JDKLatest.class) @Alias volatile int state;
+
+ // With our monitor implementation, we do not use these fields.
+ @TargetElement(onlyWith = JDKLatest.class) @Delete volatile Target_java_lang_VirtualThread next;
+ @TargetElement(onlyWith = JDKLatest.class) @Alias @InjectAccessors(AlwaysFalseAccessor.class) boolean blockPermit;
+ @TargetElement(onlyWith = JDKLatest.class) @Alias @InjectAccessors(AlwaysFalseAccessor.class) boolean onWaitingList;
+ @TargetElement(onlyWith = JDKLatest.class) @Alias @InjectAccessors(AlwaysFalseAccessor.class) boolean notified;
// Checkstyle: resume
@Alias
@@ -124,6 +138,17 @@ public final class Target_java_lang_VirtualThread {
@TargetElement(onlyWith = JDKLatest.class)
private static native ScheduledExecutorService[] createDelayedTaskSchedulers();
+ @SuppressWarnings("unused")
+ private static final class AlwaysFalseAccessor {
+ static boolean get(Target_java_lang_VirtualThread vt) {
+ return false;
+ }
+
+ static void set(Target_java_lang_VirtualThread vt, boolean value) {
+ assert !value;
+ }
+ }
+
private static final class DefaultSchedulerAccessor {
private static volatile ForkJoinPool defaultScheduler;
@@ -258,6 +283,12 @@ private static void notifyJvmtiDisableSuspend(boolean enter) {
// unimplemented (GR-51158)
}
+ @Substitute
+ @SuppressWarnings("unused")
+ @TargetElement(onlyWith = JDKLatest.class)
+ private static void postPinnedEvent(String op) {
+ }
+
@Alias volatile Thread carrierThread;
@Alias volatile Target_sun_nio_ch_Interruptible nioBlocker;
@@ -298,6 +329,10 @@ boolean getAndClearInterruptJDK21() {
@TargetElement(onlyWith = JDKLatest.class)
native void enableSuspendAndPreempt();
+ @Alias
+ @TargetElement(onlyWith = JDKLatest.class)
+ native Object carrierThreadAccessLock();
+
@Alias
private native void setCarrierThread(Target_java_lang_Thread carrier);
@@ -346,9 +381,33 @@ void unmountJDK21() {
@Alias
native int state();
+ @Substitute
+ @TargetElement(onlyWith = JDKLatest.class)
+ void setState(int s) {
+ assert s != BLOCKING && s != BLOCKED && s != UNBLOCKED && s != WAITING && s != WAIT && s != TIMED_WAIT && s != TIMED_WAITING //
+ : "states should never be reached with our monitor implementation";
+ state = s;
+ }
+
+ @Substitute
+ @TargetElement(onlyWith = JDKLatest.class)
+ @SuppressWarnings({"static-method", "unused"})
+ void waitTimeoutExpired(byte seqNo) {
+ throw VMError.shouldNotReachHere("not used in our monitor implementation");
+ }
+
+ @Delete
+ @TargetElement(onlyWith = JDKLatest.class)
+ static native void unblockVirtualThreads();
+
+ @Delete
+ @TargetElement(onlyWith = JDKLatest.class)
+ private static native Target_java_lang_VirtualThread takeVirtualThreadListToUnblock();
+
/** Needed for handling monitor-specific states. */
@Substitute
@TargetElement(onlyWith = JDKLatest.class)
+ @SuppressWarnings("hiding")
Thread.State threadState() {
int state = state() & ~SUSPENDED;
if (state == NEW) {
@@ -365,7 +424,7 @@ Thread.State threadState() {
if (Thread.currentThread() != asThread(this)) {
disableSuspendAndPreempt();
try {
- synchronized (asTarget(this).interruptLock) {
+ synchronized (carrierThreadAccessLock()) {
Thread carrier = this.carrierThread;
if (carrier != null) {
return asTarget(carrier).threadState();
@@ -378,25 +437,25 @@ Thread.State threadState() {
return Thread.State.RUNNABLE;
} else if (state == PARKING || state == YIELDING) {
return Thread.State.RUNNABLE;
- } else if (state == PARKED || state == PINNED) {
- int parkedThreadStatus = MonitorSupport.singleton().getParkedThreadStatus(asThread(this), false);
+ } else if (state == PARKED || state == PINNED || state == TIMED_PARKED || state == TIMED_PINNED) {
+ boolean timed = (state == TIMED_PARKED || state == TIMED_PINNED);
+ int parkedThreadStatus = MonitorSupport.singleton().getParkedThreadStatus(asThread(this), timed);
switch (parkedThreadStatus) {
case ThreadStatus.BLOCKED_ON_MONITOR_ENTER:
return Thread.State.BLOCKED;
case ThreadStatus.PARKED:
case ThreadStatus.IN_OBJECT_WAIT:
return Thread.State.WAITING;
+ case ThreadStatus.PARKED_TIMED:
+ case ThreadStatus.IN_OBJECT_WAIT_TIMED:
+ return Thread.State.TIMED_WAITING;
default:
throw VMError.shouldNotReachHereUnexpectedInput(parkedThreadStatus); // ExcludeFromJacocoGeneratedReport
}
} else if (state == TERMINATED) {
return Thread.State.TERMINATED;
- } else {
- if (state == TIMED_PARKING) {
- return Thread.State.RUNNABLE;
- } else if (state == TIMED_PARKED || state == TIMED_PINNED) {
- return Thread.State.TIMED_WAITING;
- }
+ } else if (state == TIMED_PARKING) {
+ return Thread.State.RUNNABLE;
}
throw new InternalError();
}
@@ -404,6 +463,7 @@ Thread.State threadState() {
/** Needed because {@link #disableSuspendAndPreempt()} does not exist on JDK 21. */
@Substitute
@TargetElement(name = "threadState", onlyWith = JDK21OrEarlier.class)
+ @SuppressWarnings("hiding")
Thread.State threadStateJDK21() {
int state = state() & ~SUSPENDED;
if (state == NEW) {
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java
index dd5755cac711..1132f74b24c7 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java
@@ -166,8 +166,12 @@ public static class Options {
CertPathBuilder.class, CertPathValidator.class, CertStore.class, CertificateFactory.class,
Cipher.class, Configuration.class, KeyAgreement.class, KeyFactory.class,
KeyGenerator.class, KeyManagerFactory.class, KeyPairGenerator.class,
- KeyStore.class, Mac.class, MessageDigest.class, Policy.class, SSLContext.class,
+ KeyStore.class, Mac.class, MessageDigest.class, SSLContext.class,
SecretKeyFactory.class, SecureRandom.class, Signature.class, TrustManagerFactory.class));
+ if (JavaVersionUtil.JAVA_SPEC <= 21) {
+ // JDK-8338411: Implement JEP 486: Permanently Disable the Security Manager
+ classList.add(Policy.class);
+ }
if (ModuleLayer.boot().findModule("java.security.sasl").isPresent()) {
classList.add(ReflectionUtil.lookupClass(false, "javax.security.sasl.SaslClientFactory"));
@@ -634,6 +638,7 @@ private void registerServices(DuringAnalysisAccess access, Object trigger, Strin
private void doRegisterServices(DuringAnalysisAccess access, Object trigger, String serviceType) {
try (TracingAutoCloseable ignored = trace(access, trigger, serviceType)) {
Set services = availableServices.get(serviceType);
+ VMError.guarantee(services != null);
for (Service service : services) {
registerService(access, service);
}
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/AccessControlContextReplacerFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/AccessControlContextReplacerFeature.java
index e6c26597d24f..53535d322192 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/AccessControlContextReplacerFeature.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/AccessControlContextReplacerFeature.java
@@ -43,6 +43,11 @@
@SuppressWarnings({"unused"})
class AccessControlContextReplacerFeature implements InternalFeature {
+ @Override
+ public boolean isInConfiguration(IsInConfigurationAccess access) {
+ return JavaVersionUtil.JAVA_SPEC == 21;
+ }
+
static Map allowedContexts = new HashMap<>();
static void allowContextIfExists(String className, String fieldName) {
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNINativeCallWrapperMethod.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNINativeCallWrapperMethod.java
index e0244cb2bf27..296bb46b9069 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNINativeCallWrapperMethod.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNINativeCallWrapperMethod.java
@@ -118,6 +118,27 @@ public StructuredGraph buildGraph(DebugContext debug, AnalysisMethod method, Hos
callAddress = kit.invokeNativeCallAddress(kit.createObject(linkage));
}
+ List javaArguments = kit.getInitialArguments();
+
+ /*
+ * Acquire the lock upfront because when in a virtual thread, contention could cause
+ * migration to a different carrier thread with a different JNI environment and local handle
+ * set before the native call.
+ */
+ if (getOriginal().isSynchronized()) {
+ ValueNode monitorObject;
+ if (method.isStatic()) {
+ JavaConstant hubConstant = (JavaConstant) kit.getConstantReflection().asObjectHub(method.getDeclaringClass());
+ monitorObject = ConstantNode.forConstant(hubConstant, kit.getMetaAccess(), kit.getGraph());
+ } else {
+ monitorObject = kit.maybeCreateExplicitNullCheck(javaArguments.get(0));
+ }
+ MonitorIdNode monitorId = kit.getGraph().add(new MonitorIdNode(kit.getFrameState().lockDepth(false)));
+ MonitorEnterNode monitorEnter = kit.append(new MonitorEnterNode(monitorObject, monitorId));
+ kit.getFrameState().pushLock(monitorEnter.object(), monitorEnter.getMonitorId());
+ monitorEnter.setStateAfter(kit.getFrameState().create(kit.bci(), monitorEnter));
+ }
+
ValueNode environment = kit.invokeEnvironment();
/* After the JNI prologue, we must not invoke methods that may throw an exception. */
@@ -125,7 +146,6 @@ public StructuredGraph buildGraph(DebugContext debug, AnalysisMethod method, Hos
AnalysisType javaReturnType = method.getSignature().getReturnType();
List javaArgumentTypes = method.toParameterList();
- List javaArguments = kit.getInitialArguments();
List jniArguments = new ArrayList<>(2 + javaArguments.size());
List jniArgumentTypes = new ArrayList<>(2 + javaArguments.size());
@@ -159,21 +179,6 @@ public StructuredGraph buildGraph(DebugContext debug, AnalysisMethod method, Hos
jniReturnType = objectHandleType;
}
- /* Thrown exceptions may cause a memory leak, see GR-54276. */
- if (getOriginal().isSynchronized()) {
- ValueNode monitorObject;
- if (method.isStatic()) {
- JavaConstant hubConstant = (JavaConstant) kit.getConstantReflection().asObjectHub(method.getDeclaringClass());
- monitorObject = ConstantNode.forConstant(hubConstant, kit.getMetaAccess(), kit.getGraph());
- } else {
- monitorObject = kit.maybeCreateExplicitNullCheck(javaArguments.get(0));
- }
- MonitorIdNode monitorId = kit.getGraph().add(new MonitorIdNode(kit.getFrameState().lockDepth(false)));
- MonitorEnterNode monitorEnter = kit.append(new MonitorEnterNode(monitorObject, monitorId));
- kit.getFrameState().pushLock(monitorEnter.object(), monitorEnter.getMonitorId());
- monitorEnter.setStateAfter(kit.getFrameState().create(kit.bci(), monitorEnter));
- }
-
kit.getFrameState().clearLocals();
var jniSignature = ResolvedSignature.fromList(jniArgumentTypes, jniReturnType);
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java
index 485fc871aeb9..01699fc87374 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/methodhandles/MethodHandleFeature.java
@@ -121,10 +121,16 @@ public void duringSetup(DuringSetupAccess access) {
if (JavaVersionUtil.JAVA_SPEC >= 22) {
try {
Class> referencedKeySetClass = ReflectionUtil.lookupClass("jdk.internal.util.ReferencedKeySet");
- Method create = ReflectionUtil.lookupMethod(referencedKeySetClass, "create", boolean.class, boolean.class, Supplier.class);
// The following call must match the static initializer of MethodType#internTable.
- runtimeMethodTypeInternTable = create.invoke(null,
- /* isSoft */ false, /* useNativeQueue */ true, (Supplier