Skip to content

Commit

Permalink
8305895: Implement JEP 450: Compact Object Headers (Experimental)
Browse files Browse the repository at this point in the history
  • Loading branch information
rkennke committed Aug 22, 2024
1 parent 6cf7f9c commit 96ec3c2
Show file tree
Hide file tree
Showing 189 changed files with 3,860 additions and 1,291 deletions.
20 changes: 17 additions & 3 deletions make/Images.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,16 @@ CDS_DUMP_FLAGS = -Xmx128M -Xms128M
# Helper function for creating the CDS archives for the JDK and JRE
#
# Param1 - VM variant (e.g., server, client, zero, ...)
# Param2 - _nocoops, or empty
# Param2 - _nocoops, _coh, _nocoops_coh, or empty
define CreateCDSArchive
$1_$2_DUMP_EXTRA_ARG := $(if $(filter _nocoops, $2),-XX:-UseCompressedOops,)
$1_$2_DUMP_TYPE := $(if $(filter _nocoops, $2),-NOCOOPS,)
$1_$2_COOPS_OPTION := $(if $(findstring _nocoops, $2),-XX:-UseCompressedOops)
# enable and also explicitly disable coh as needed.
ifeq ($(call isTargetCpuBits, 64), true)
$1_$2_COH_OPTION := -XX:+UnlockExperimentalVMOptions \
$(if $(findstring _coh, $2),-XX:+UseCompactObjectHeaders,-XX:-UseCompactObjectHeaders)
endif
$1_$2_DUMP_EXTRA_ARG := $$($1_$2_COOPS_OPTION) $$($1_$2_COH_OPTION)
$1_$2_DUMP_TYPE := $(if $(findstring _nocoops, $2),-NOCOOPS,)$(if $(findstring _coh, $2),-COH,)

# Only G1 supports dumping the shared heap, so explicitly use G1 if the JVM supports it.
$1_$2_CDS_DUMP_FLAGS := $(CDS_DUMP_FLAGS) $(if $(filter g1gc, $(JVM_FEATURES_$1)),-XX:+UseG1GC)
Expand Down Expand Up @@ -190,6 +196,14 @@ ifeq ($(BUILD_CDS_ARCHIVE), true)
$(foreach v, $(JVM_VARIANTS), \
$(eval $(call CreateCDSArchive,$v,_nocoops)) \
)
ifeq ($(BUILD_CDS_ARCHIVE_COH), true)
$(foreach v, $(JVM_VARIANTS), \
$(eval $(call CreateCDSArchive,$v,_coh)) \
)
$(foreach v, $(JVM_VARIANTS), \
$(eval $(call CreateCDSArchive,$v,_nocoops_coh)) \
)
endif
endif
endif

Expand Down
3 changes: 2 additions & 1 deletion make/autoconf/configure.ac
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 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
Expand Down Expand Up @@ -260,6 +260,7 @@ JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST
JDKOPT_EXCLUDE_TRANSLATIONS
JDKOPT_ENABLE_DISABLE_MANPAGES
JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE
JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_COH
JDKOPT_ENABLE_DISABLE_COMPATIBLE_CDS_ALIGNMENT
JDKOPT_SETUP_MACOSX_SIGNING

Expand Down
27 changes: 27 additions & 0 deletions make/autoconf/jdk-options.m4
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,33 @@ AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE],
AC_SUBST(BUILD_CDS_ARCHIVE)
])

################################################################################
#
# Enable or disable the default CDS archive generation for Compact Object Headers
#
AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_COH],
[
UTIL_ARG_ENABLE(NAME: cds-archive-coh, DEFAULT: auto, RESULT: BUILD_CDS_ARCHIVE_COH,
DESC: [enable generation of default CDS archives for compact object headers (requires --enable-cds-archive)],
DEFAULT_DESC: [auto],
CHECKING_MSG: [if default CDS archives for compact object headers should be generated],
CHECK_AVAILABLE: [
AC_MSG_CHECKING([if CDS archive with compact object headers is available])
if test "x$BUILD_CDS_ARCHIVE" = "xfalse"; then
AC_MSG_RESULT([no (CDS default archive generation is disabled)])
AVAILABLE=false
elif test "x$OPENJDK_TARGET_CPU" != "xx86_64" &&
test "x$OPENJDK_TARGET_CPU" != "xaarch64"; then
AC_MSG_RESULT([no (compact object headers not supported for this platform)])
AVAILABLE=false
else
AC_MSG_RESULT([yes])
AVAILABLE=true
fi
])
AC_SUBST(BUILD_CDS_ARCHIVE_COH)
])

################################################################################
#
# Enable the alternative CDS core region alignment
Expand Down
1 change: 1 addition & 0 deletions make/autoconf/spec.gmk.template
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ EXCLUDE_TRANSLATIONS := @EXCLUDE_TRANSLATIONS@
BUILD_MANPAGES := @BUILD_MANPAGES@

BUILD_CDS_ARCHIVE := @BUILD_CDS_ARCHIVE@
BUILD_CDS_ARCHIVE_COH := @BUILD_CDS_ARCHIVE_COH@

ENABLE_COMPATIBLE_CDS_ALIGNMENT := @ENABLE_COMPATIBLE_CDS_ALIGNMENT@

Expand Down
16 changes: 15 additions & 1 deletion src/hotspot/cpu/aarch64/aarch64.ad
Original file line number Diff line number Diff line change
Expand Up @@ -6438,7 +6438,7 @@ instruct loadKlass(iRegPNoSp dst, memory mem)
instruct loadNKlass(iRegNNoSp dst, memory mem)
%{
match(Set dst (LoadNKlass mem));
predicate(!needs_acquiring_load(n));
predicate(!needs_acquiring_load(n) && !UseCompactObjectHeaders);

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

instruct loadNKlassCompactHeaders(iRegNNoSp dst, memory mem, rFlagsReg cr)
%{
match(Set dst (LoadNKlass mem));
effect(KILL cr);
predicate(!needs_acquiring_load(n) && UseCompactObjectHeaders);

ins_cost(4 * INSN_COST);
format %{ "ldrw $dst, $mem\t# compressed class ptr" %}
ins_encode %{
__ load_nklass_compact($dst$$Register, $mem$$base$$Register, $mem$$index$$Register, $mem$$scale, $mem$$disp);
%}
ins_pipe(pipe_slow);
%}

// Load Float
instruct loadF(vRegF dst, memory mem)
%{
Expand Down
47 changes: 10 additions & 37 deletions src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2246,8 +2246,6 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {

Address src_length_addr = Address(src, arrayOopDesc::length_offset_in_bytes());
Address dst_length_addr = Address(dst, arrayOopDesc::length_offset_in_bytes());
Address src_klass_addr = Address(src, oopDesc::klass_offset_in_bytes());
Address dst_klass_addr = Address(dst, oopDesc::klass_offset_in_bytes());

// test for null
if (flags & LIR_OpArrayCopy::src_null_check) {
Expand Down Expand Up @@ -2308,15 +2306,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
// We don't know the array types are compatible
if (basic_type != T_OBJECT) {
// Simple test for basic type arrays
if (UseCompressedClassPointers) {
__ ldrw(tmp, src_klass_addr);
__ ldrw(rscratch1, dst_klass_addr);
__ cmpw(tmp, rscratch1);
} else {
__ ldr(tmp, src_klass_addr);
__ ldr(rscratch1, dst_klass_addr);
__ cmp(tmp, rscratch1);
}
__ cmp_klass(src, dst, tmp, rscratch1);
__ br(Assembler::NE, *stub->entry());
} else {
// For object arrays, if src is a sub class of dst then we can
Expand Down Expand Up @@ -2438,36 +2428,14 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
// but not necessarily exactly of type default_type.
Label known_ok, halt;
__ mov_metadata(tmp, default_type->constant_encoding());
if (UseCompressedClassPointers) {
__ encode_klass_not_null(tmp);
}

if (basic_type != T_OBJECT) {

if (UseCompressedClassPointers) {
__ ldrw(rscratch1, dst_klass_addr);
__ cmpw(tmp, rscratch1);
} else {
__ ldr(rscratch1, dst_klass_addr);
__ cmp(tmp, rscratch1);
}
__ cmp_klass(dst, tmp, rscratch1);
__ br(Assembler::NE, halt);
if (UseCompressedClassPointers) {
__ ldrw(rscratch1, src_klass_addr);
__ cmpw(tmp, rscratch1);
} else {
__ ldr(rscratch1, src_klass_addr);
__ cmp(tmp, rscratch1);
}
__ cmp_klass(src, tmp, rscratch1);
__ br(Assembler::EQ, known_ok);
} else {
if (UseCompressedClassPointers) {
__ ldrw(rscratch1, dst_klass_addr);
__ cmpw(tmp, rscratch1);
} else {
__ ldr(rscratch1, dst_klass_addr);
__ cmp(tmp, rscratch1);
}
__ cmp_klass(dst, tmp, rscratch1);
__ br(Assembler::EQ, known_ok);
__ cmp(src, dst);
__ br(Assembler::EQ, known_ok);
Expand Down Expand Up @@ -2551,7 +2519,12 @@ void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) {
}

if (UseCompressedClassPointers) {
__ ldrw(result, Address (obj, oopDesc::klass_offset_in_bytes()));
if (UseCompactObjectHeaders) {
__ ldr(result, Address(obj, oopDesc::mark_offset_in_bytes()));
__ lsr(result, result, markWord::klass_shift);
} else {
__ ldrw(result, Address (obj, oopDesc::klass_offset_in_bytes()));
}
__ decode_klass_not_null(result);
} else {
__ ldr(result, Address (obj, oopDesc::klass_offset_in_bytes()));
Expand Down
20 changes: 12 additions & 8 deletions src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,19 @@ void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, i

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

if (UseCompressedClassPointers) { // Take care not to kill klass
encode_klass_not_null(t1, klass);
strw(t1, Address(obj, oopDesc::klass_offset_in_bytes()));
if (UseCompactObjectHeaders) {
ldr(t1, Address(klass, Klass::prototype_header_offset()));
str(t1, Address(obj, oopDesc::mark_offset_in_bytes()));
} else {
str(klass, Address(obj, oopDesc::klass_offset_in_bytes()));
mov(t1, checked_cast<int32_t>(markWord::prototype().value()));
str(t1, Address(obj, oopDesc::mark_offset_in_bytes()));
if (UseCompressedClassPointers) { // Take care not to kill klass
encode_klass_not_null(t1, klass);
strw(t1, Address(obj, oopDesc::klass_offset_in_bytes()));
} else {
str(klass, Address(obj, oopDesc::klass_offset_in_bytes()));
}
}

if (len->is_valid()) {
Expand All @@ -194,7 +198,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
// Clear gap/first 4 bytes following the length field.
strw(zr, Address(obj, base_offset));
}
} else if (UseCompressedClassPointers) {
} else if (UseCompressedClassPointers && !UseCompactObjectHeaders) {
store_klass_gap(obj, zr);
}
}
Expand Down
19 changes: 19 additions & 0 deletions src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2557,3 +2557,22 @@ bool C2_MacroAssembler::in_scratch_emit_size() {
}
return MacroAssembler::in_scratch_emit_size();
}

void C2_MacroAssembler::load_nklass_compact(Register dst, Register obj, Register index, int scale, int disp) {
// Note: Don't clobber obj anywhere in that method!

// The incoming address is pointing into obj-start + klass_offset_in_bytes. We need to extract
// obj-start, so that we can load from the object's mark-word instead. Usually the address
// comes as obj-start in obj and klass_offset_in_bytes in disp. However, sometimes C2
// emits code that pre-computes obj-start + klass_offset_in_bytes into a register, and
// then passes that register as obj and 0 in disp. The following code extracts the base
// and offset to load the mark-word.
int offset = oopDesc::mark_offset_in_bytes() + disp - oopDesc::klass_offset_in_bytes();
if (index == noreg) {
ldr(dst, Address(obj, offset));
} else {
lea(dst, Address(obj, index, Address::lsl(scale)));
ldr(dst, Address(dst, offset));
}
lsr(dst, dst, markWord::klass_shift);
}
2 changes: 2 additions & 0 deletions src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,6 @@
void vector_signum_sve(FloatRegister dst, FloatRegister src, FloatRegister zero,
FloatRegister one, FloatRegister vtmp, PRegister pgtmp, SIMD_RegVariant T);

void load_nklass_compact(Register dst, Register obj, Register index, int scale, int disp);

#endif // CPU_AARCH64_C2_MACROASSEMBLER_AARCH64_HPP
21 changes: 18 additions & 3 deletions src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,31 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size
return result;
}

void CompressedKlassPointers::initialize(address addr, size_t len) {
bool CompressedKlassPointers::pd_initialize(address addr, size_t len) {

if (tiny_classpointer_mode()) {
// In tiny-classpointer mode, we do what all other platforms do.
return false;
}

// Aarch64 uses an own initialization logic that avoids zero-base shifted mode
// (_base=0 _shift>0), instead preferring non-zero-based mode with shift=0
constexpr uintptr_t unscaled_max = nth_bit(32);
assert(len <= unscaled_max, "Klass range larger than 32 bits?");

// Shift is always 0 on aarch64.
_shift = 0;

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

_range = end - _base;

#ifdef ASSERT
_klass_range_start = addr;
_klass_range_end = addr + len;
calc_lowest_highest_narrow_klass_id();
sanity_check_after_initialization();
#endif

return true;
}
Loading

0 comments on commit 96ec3c2

Please sign in to comment.