Skip to content

Commit ed03217

Browse files
committed
8305895: Implement JEP 450: Compact Object Headers (Experimental)
1 parent 6cf7f9c commit ed03217

File tree

187 files changed

+3855
-1288
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

187 files changed

+3855
-1288
lines changed

make/Images.gmk

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,16 @@ CDS_DUMP_FLAGS = -Xmx128M -Xms128M
132132
# Helper function for creating the CDS archives for the JDK and JRE
133133
#
134134
# Param1 - VM variant (e.g., server, client, zero, ...)
135-
# Param2 - _nocoops, or empty
135+
# Param2 - _nocoops, _coh, _nocoops_coh, or empty
136136
define CreateCDSArchive
137-
$1_$2_DUMP_EXTRA_ARG := $(if $(filter _nocoops, $2),-XX:-UseCompressedOops,)
138-
$1_$2_DUMP_TYPE := $(if $(filter _nocoops, $2),-NOCOOPS,)
137+
$1_$2_COOPS_OPTION := $(if $(findstring _nocoops, $2),-XX:-UseCompressedOops)
138+
# enable and also explicitly disable coh as needed.
139+
ifeq ($(call isTargetCpuBits, 64), true)
140+
$1_$2_COH_OPTION := -XX:+UnlockExperimentalVMOptions \
141+
$(if $(findstring _coh, $2),-XX:+UseCompactObjectHeaders,-XX:-UseCompactObjectHeaders)
142+
endif
143+
$1_$2_DUMP_EXTRA_ARG := $$($1_$2_COOPS_OPTION) $$($1_$2_COH_OPTION)
144+
$1_$2_DUMP_TYPE := $(if $(findstring _nocoops, $2),-NOCOOPS,)$(if $(findstring _coh, $2),-COH,)
139145

140146
# Only G1 supports dumping the shared heap, so explicitly use G1 if the JVM supports it.
141147
$1_$2_CDS_DUMP_FLAGS := $(CDS_DUMP_FLAGS) $(if $(filter g1gc, $(JVM_FEATURES_$1)),-XX:+UseG1GC)
@@ -190,6 +196,14 @@ ifeq ($(BUILD_CDS_ARCHIVE), true)
190196
$(foreach v, $(JVM_VARIANTS), \
191197
$(eval $(call CreateCDSArchive,$v,_nocoops)) \
192198
)
199+
ifeq ($(BUILD_CDS_ARCHIVE_COH), true)
200+
$(foreach v, $(JVM_VARIANTS), \
201+
$(eval $(call CreateCDSArchive,$v,_coh)) \
202+
)
203+
$(foreach v, $(JVM_VARIANTS), \
204+
$(eval $(call CreateCDSArchive,$v,_nocoops_coh)) \
205+
)
206+
endif
193207
endif
194208
endif
195209

make/autoconf/configure.ac

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
33
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
#
55
# This code is free software; you can redistribute it and/or modify it
@@ -260,6 +260,7 @@ JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST
260260
JDKOPT_EXCLUDE_TRANSLATIONS
261261
JDKOPT_ENABLE_DISABLE_MANPAGES
262262
JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE
263+
JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_COH
263264
JDKOPT_ENABLE_DISABLE_COMPATIBLE_CDS_ALIGNMENT
264265
JDKOPT_SETUP_MACOSX_SIGNING
265266

make/autoconf/jdk-options.m4

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,33 @@ AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE],
673673
AC_SUBST(BUILD_CDS_ARCHIVE)
674674
])
675675

676+
################################################################################
677+
#
678+
# Enable or disable the default CDS archive generation for Compact Object Headers
679+
#
680+
AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_COH],
681+
[
682+
UTIL_ARG_ENABLE(NAME: cds-archive-coh, DEFAULT: auto, RESULT: BUILD_CDS_ARCHIVE_COH,
683+
DESC: [enable generation of default CDS archives for compact object headers (requires --enable-cds-archive)],
684+
DEFAULT_DESC: [auto],
685+
CHECKING_MSG: [if default CDS archives for compact object headers should be generated],
686+
CHECK_AVAILABLE: [
687+
AC_MSG_CHECKING([if CDS archive with compact object headers is available])
688+
if test "x$BUILD_CDS_ARCHIVE" = "xfalse"; then
689+
AC_MSG_RESULT([no (CDS default archive generation is disabled)])
690+
AVAILABLE=false
691+
elif test "x$OPENJDK_TARGET_CPU" != "xx86_64" &&
692+
test "x$OPENJDK_TARGET_CPU" != "xaarch64"; then
693+
AC_MSG_RESULT([no (compact object headers not supported for this platform)])
694+
AVAILABLE=false
695+
else
696+
AC_MSG_RESULT([yes])
697+
AVAILABLE=true
698+
fi
699+
])
700+
AC_SUBST(BUILD_CDS_ARCHIVE_COH)
701+
])
702+
676703
################################################################################
677704
#
678705
# Enable the alternative CDS core region alignment

make/autoconf/spec.gmk.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ EXCLUDE_TRANSLATIONS := @EXCLUDE_TRANSLATIONS@
370370
BUILD_MANPAGES := @BUILD_MANPAGES@
371371

372372
BUILD_CDS_ARCHIVE := @BUILD_CDS_ARCHIVE@
373+
BUILD_CDS_ARCHIVE_COH := @BUILD_CDS_ARCHIVE_COH@
373374

374375
ENABLE_COMPATIBLE_CDS_ALIGNMENT := @ENABLE_COMPATIBLE_CDS_ALIGNMENT@
375376

src/hotspot/cpu/aarch64/aarch64.ad

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6438,7 +6438,7 @@ instruct loadKlass(iRegPNoSp dst, memory mem)
64386438
instruct loadNKlass(iRegNNoSp dst, memory mem)
64396439
%{
64406440
match(Set dst (LoadNKlass mem));
6441-
predicate(!needs_acquiring_load(n));
6441+
predicate(!needs_acquiring_load(n) && !UseCompactObjectHeaders);
64426442

64436443
ins_cost(4 * INSN_COST);
64446444
format %{ "ldrw $dst, $mem\t# compressed class ptr" %}
@@ -6448,6 +6448,20 @@ instruct loadNKlass(iRegNNoSp dst, memory mem)
64486448
ins_pipe(iload_reg_mem);
64496449
%}
64506450

6451+
instruct loadNKlassCompactHeaders(iRegNNoSp dst, memory mem, rFlagsReg cr)
6452+
%{
6453+
match(Set dst (LoadNKlass mem));
6454+
effect(KILL cr);
6455+
predicate(!needs_acquiring_load(n) && UseCompactObjectHeaders);
6456+
6457+
ins_cost(4 * INSN_COST);
6458+
format %{ "ldrw $dst, $mem\t# compressed class ptr" %}
6459+
ins_encode %{
6460+
__ load_nklass_compact($dst$$Register, $mem$$base$$Register, $mem$$index$$Register, $mem$$scale, $mem$$disp);
6461+
%}
6462+
ins_pipe(pipe_slow);
6463+
%}
6464+
64516465
// Load Float
64526466
instruct loadF(vRegF dst, memory mem)
64536467
%{

src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2246,8 +2246,6 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
22462246

22472247
Address src_length_addr = Address(src, arrayOopDesc::length_offset_in_bytes());
22482248
Address dst_length_addr = Address(dst, arrayOopDesc::length_offset_in_bytes());
2249-
Address src_klass_addr = Address(src, oopDesc::klass_offset_in_bytes());
2250-
Address dst_klass_addr = Address(dst, oopDesc::klass_offset_in_bytes());
22512249

22522250
// test for null
22532251
if (flags & LIR_OpArrayCopy::src_null_check) {
@@ -2308,15 +2306,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
23082306
// We don't know the array types are compatible
23092307
if (basic_type != T_OBJECT) {
23102308
// Simple test for basic type arrays
2311-
if (UseCompressedClassPointers) {
2312-
__ ldrw(tmp, src_klass_addr);
2313-
__ ldrw(rscratch1, dst_klass_addr);
2314-
__ cmpw(tmp, rscratch1);
2315-
} else {
2316-
__ ldr(tmp, src_klass_addr);
2317-
__ ldr(rscratch1, dst_klass_addr);
2318-
__ cmp(tmp, rscratch1);
2319-
}
2309+
__ cmp_klass(src, dst, tmp, rscratch1);
23202310
__ br(Assembler::NE, *stub->entry());
23212311
} else {
23222312
// For object arrays, if src is a sub class of dst then we can
@@ -2438,36 +2428,14 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
24382428
// but not necessarily exactly of type default_type.
24392429
Label known_ok, halt;
24402430
__ mov_metadata(tmp, default_type->constant_encoding());
2441-
if (UseCompressedClassPointers) {
2442-
__ encode_klass_not_null(tmp);
2443-
}
24442431

24452432
if (basic_type != T_OBJECT) {
2446-
2447-
if (UseCompressedClassPointers) {
2448-
__ ldrw(rscratch1, dst_klass_addr);
2449-
__ cmpw(tmp, rscratch1);
2450-
} else {
2451-
__ ldr(rscratch1, dst_klass_addr);
2452-
__ cmp(tmp, rscratch1);
2453-
}
2433+
__ cmp_klass(dst, tmp, rscratch1);
24542434
__ br(Assembler::NE, halt);
2455-
if (UseCompressedClassPointers) {
2456-
__ ldrw(rscratch1, src_klass_addr);
2457-
__ cmpw(tmp, rscratch1);
2458-
} else {
2459-
__ ldr(rscratch1, src_klass_addr);
2460-
__ cmp(tmp, rscratch1);
2461-
}
2435+
__ cmp_klass(src, tmp, rscratch1);
24622436
__ br(Assembler::EQ, known_ok);
24632437
} else {
2464-
if (UseCompressedClassPointers) {
2465-
__ ldrw(rscratch1, dst_klass_addr);
2466-
__ cmpw(tmp, rscratch1);
2467-
} else {
2468-
__ ldr(rscratch1, dst_klass_addr);
2469-
__ cmp(tmp, rscratch1);
2470-
}
2438+
__ cmp_klass(dst, tmp, rscratch1);
24712439
__ br(Assembler::EQ, known_ok);
24722440
__ cmp(src, dst);
24732441
__ br(Assembler::EQ, known_ok);
@@ -2551,7 +2519,12 @@ void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) {
25512519
}
25522520

25532521
if (UseCompressedClassPointers) {
2554-
__ ldrw(result, Address (obj, oopDesc::klass_offset_in_bytes()));
2522+
if (UseCompactObjectHeaders) {
2523+
__ ldr(result, Address(obj, oopDesc::mark_offset_in_bytes()));
2524+
__ lsr(result, result, markWord::klass_shift);
2525+
} else {
2526+
__ ldrw(result, Address (obj, oopDesc::klass_offset_in_bytes()));
2527+
}
25552528
__ decode_klass_not_null(result);
25562529
} else {
25572530
__ ldr(result, Address (obj, oopDesc::klass_offset_in_bytes()));

src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -175,15 +175,19 @@ void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, i
175175

176176
void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1, Register t2) {
177177
assert_different_registers(obj, klass, len);
178-
// This assumes that all prototype bits fit in an int32_t
179-
mov(t1, (int32_t)(intptr_t)markWord::prototype().value());
180-
str(t1, Address(obj, oopDesc::mark_offset_in_bytes()));
181178

182-
if (UseCompressedClassPointers) { // Take care not to kill klass
183-
encode_klass_not_null(t1, klass);
184-
strw(t1, Address(obj, oopDesc::klass_offset_in_bytes()));
179+
if (UseCompactObjectHeaders) {
180+
ldr(t1, Address(klass, Klass::prototype_header_offset()));
181+
str(t1, Address(obj, oopDesc::mark_offset_in_bytes()));
185182
} else {
186-
str(klass, Address(obj, oopDesc::klass_offset_in_bytes()));
183+
mov(t1, checked_cast<int32_t>(markWord::prototype().value()));
184+
str(t1, Address(obj, oopDesc::mark_offset_in_bytes()));
185+
if (UseCompressedClassPointers) { // Take care not to kill klass
186+
encode_klass_not_null(t1, klass);
187+
strw(t1, Address(obj, oopDesc::klass_offset_in_bytes()));
188+
} else {
189+
str(klass, Address(obj, oopDesc::klass_offset_in_bytes()));
190+
}
187191
}
188192

189193
if (len->is_valid()) {
@@ -194,7 +198,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
194198
// Clear gap/first 4 bytes following the length field.
195199
strw(zr, Address(obj, base_offset));
196200
}
197-
} else if (UseCompressedClassPointers) {
201+
} else if (UseCompressedClassPointers && !UseCompactObjectHeaders) {
198202
store_klass_gap(obj, zr);
199203
}
200204
}

src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2557,3 +2557,22 @@ bool C2_MacroAssembler::in_scratch_emit_size() {
25572557
}
25582558
return MacroAssembler::in_scratch_emit_size();
25592559
}
2560+
2561+
void C2_MacroAssembler::load_nklass_compact(Register dst, Register obj, Register index, int scale, int disp) {
2562+
// Note: Don't clobber obj anywhere in that method!
2563+
2564+
// The incoming address is pointing into obj-start + klass_offset_in_bytes. We need to extract
2565+
// obj-start, so that we can load from the object's mark-word instead. Usually the address
2566+
// comes as obj-start in obj and klass_offset_in_bytes in disp. However, sometimes C2
2567+
// emits code that pre-computes obj-start + klass_offset_in_bytes into a register, and
2568+
// then passes that register as obj and 0 in disp. The following code extracts the base
2569+
// and offset to load the mark-word.
2570+
int offset = oopDesc::mark_offset_in_bytes() + disp - oopDesc::klass_offset_in_bytes();
2571+
if (index == noreg) {
2572+
ldr(dst, Address(obj, offset));
2573+
} else {
2574+
lea(dst, Address(obj, index, Address::lsl(scale)));
2575+
ldr(dst, Address(dst, offset));
2576+
}
2577+
lsr(dst, dst, markWord::klass_shift);
2578+
}

src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,6 @@
179179
void vector_signum_sve(FloatRegister dst, FloatRegister src, FloatRegister zero,
180180
FloatRegister one, FloatRegister vtmp, PRegister pgtmp, SIMD_RegVariant T);
181181

182+
void load_nklass_compact(Register dst, Register obj, Register index, int scale, int disp);
183+
182184
#endif // CPU_AARCH64_C2_MACROASSEMBLER_AARCH64_HPP

src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,31 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size
118118
return result;
119119
}
120120

121-
void CompressedKlassPointers::initialize(address addr, size_t len) {
121+
bool CompressedKlassPointers::pd_initialize(address addr, size_t len) {
122+
123+
if (tiny_classpointer_mode()) {
124+
// In tiny-classpointer mode, we do what all other platforms do.
125+
return false;
126+
}
127+
128+
// Aarch64 uses an own initialization logic that avoids zero-base shifted mode
129+
// (_base=0 _shift>0), instead preferring non-zero-based mode with shift=0
122130
constexpr uintptr_t unscaled_max = nth_bit(32);
123131
assert(len <= unscaled_max, "Klass range larger than 32 bits?");
124132

125-
// Shift is always 0 on aarch64.
126133
_shift = 0;
127134

128-
// On aarch64, we don't bother with zero-based encoding (base=0 shift>0).
129135
address const end = addr + len;
130136
_base = (end <= (address)unscaled_max) ? nullptr : addr;
131137

132138
_range = end - _base;
139+
140+
#ifdef ASSERT
141+
_klass_range_start = addr;
142+
_klass_range_end = addr + len;
143+
calc_lowest_highest_narrow_klass_id();
144+
sanity_check_after_initialization();
145+
#endif
146+
147+
return true;
133148
}

0 commit comments

Comments
 (0)