Skip to content

Commit

Permalink
8305894: Implementation: JEP 450: Compact Object Headers (Experimental)
Browse files Browse the repository at this point in the history
  • Loading branch information
rkennke committed Aug 20, 2024
1 parent f2eae47 commit e63105b
Show file tree
Hide file tree
Showing 110 changed files with 1,465 additions and 438 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
26 changes: 26 additions & 0 deletions make/autoconf/jdk-options.m4
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,32 @@ 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])
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
2 changes: 1 addition & 1 deletion src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "c1/c1_Runtime1.hpp"
#include "classfile/javaClasses.hpp"
#include "nativeInst_aarch64.hpp"
#include "runtime/objectMonitor.hpp"
#include "runtime/sharedRuntime.hpp"
#include "vmreg_aarch64.inline.hpp"

Expand Down Expand Up @@ -233,7 +234,6 @@ void MonitorExitStub::emit_code(LIR_Assembler* ce) {
__ far_jump(RuntimeAddress(Runtime1::entry_for(exit_id)));
}


// Implementation of patching:
// - Copy the code at given offset to an inlined buffer (first the bytes, then the number of bytes)
// - Replace original code with a call to the stub
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
22 changes: 13 additions & 9 deletions src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,17 +175,21 @@ 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()));
// 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()));
} else {
str(klass, Address(obj, oopDesc::klass_offset_in_bytes()));
}
}

if (len->is_valid()) {
strw(len, Address(obj, arrayOopDesc::length_offset_in_bytes()));
int base_offset = arrayOopDesc::length_offset_in_bytes() + BytesPerInt;
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
38 changes: 36 additions & 2 deletions src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4838,8 +4838,19 @@ void MacroAssembler::load_method_holder(Register holder, Register method) {
ldr(holder, Address(holder, ConstantPool::pool_holder_offset())); // InstanceKlass*
}

// Loads the obj's Klass* into dst.
// Preserves all registers (incl src, rscratch1 and rscratch2).
void MacroAssembler::load_nklass_compact(Register dst, Register src) {
assert(UseCompactObjectHeaders, "expects UseCompactObjectHeaders");
ldr(dst, Address(src, oopDesc::mark_offset_in_bytes()));
lsr(dst, dst, markWord::klass_shift);
}

void MacroAssembler::load_klass(Register dst, Register src) {
if (UseCompressedClassPointers) {
if (UseCompactObjectHeaders) {
load_nklass_compact(dst, src);
decode_klass_not_null(dst);
} else if (UseCompressedClassPointers) {
ldrw(dst, Address(src, oopDesc::klass_offset_in_bytes()));
decode_klass_not_null(dst);
} else {
Expand Down Expand Up @@ -4895,8 +4906,13 @@ void MacroAssembler::load_mirror(Register dst, Register method, Register tmp1, R
}

void MacroAssembler::cmp_klass(Register oop, Register trial_klass, Register tmp) {
assert_different_registers(oop, trial_klass, tmp);
if (UseCompressedClassPointers) {
ldrw(tmp, Address(oop, oopDesc::klass_offset_in_bytes()));
if (UseCompactObjectHeaders) {
load_nklass_compact(tmp, oop);
} else {
ldrw(tmp, Address(oop, oopDesc::klass_offset_in_bytes()));
}
if (CompressedKlassPointers::base() == nullptr) {
cmp(trial_klass, tmp, LSL, CompressedKlassPointers::shift());
return;
Expand All @@ -4913,9 +4929,26 @@ void MacroAssembler::cmp_klass(Register oop, Register trial_klass, Register tmp)
cmp(trial_klass, tmp);
}

void MacroAssembler::cmp_klass(Register src, Register dst, Register tmp1, Register tmp2) {
if (UseCompactObjectHeaders) {
load_nklass_compact(tmp1, src);
load_nklass_compact(tmp2, dst);
cmpw(tmp1, tmp2);
} else if (UseCompressedClassPointers) {
ldrw(tmp1, Address(src, oopDesc::klass_offset_in_bytes()));
ldrw(tmp2, Address(dst, oopDesc::klass_offset_in_bytes()));
cmpw(tmp1, tmp2);
} else {
ldr(tmp1, Address(src, oopDesc::klass_offset_in_bytes()));
ldr(tmp2, Address(dst, oopDesc::klass_offset_in_bytes()));
cmp(tmp1, tmp2);
}
}

void MacroAssembler::store_klass(Register dst, Register src) {
// FIXME: Should this be a store release? concurrent gcs assumes
// klass length is valid if klass field is not null.
assert(!UseCompactObjectHeaders, "not with compact headers");
if (UseCompressedClassPointers) {
encode_klass_not_null(src);
strw(src, Address(dst, oopDesc::klass_offset_in_bytes()));
Expand All @@ -4925,6 +4958,7 @@ void MacroAssembler::store_klass(Register dst, Register src) {
}

void MacroAssembler::store_klass_gap(Register dst, Register src) {
assert(!UseCompactObjectHeaders, "not with compact headers");
if (UseCompressedClassPointers) {
// Store to klass gap in destination
strw(src, Address(dst, oopDesc::klass_gap_offset_in_bytes()));
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,9 +875,11 @@ class MacroAssembler: public Assembler {
void load_method_holder(Register holder, Register method);

// oop manipulations
void load_nklass_compact(Register dst, Register src);
void load_klass(Register dst, Register src);
void store_klass(Register dst, Register src);
void cmp_klass(Register oop, Register trial_klass, Register tmp);
void cmp_klass(Register src, Register dst, Register tmp1, Register tmp2);

void resolve_weak_handle(Register result, Register tmp1, Register tmp2);
void resolve_oop_handle(Register result, Register tmp1, Register tmp2);
Expand Down
Loading

0 comments on commit e63105b

Please sign in to comment.