Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
fe39f0a
exps
rwestrel Mar 20, 2026
da019f9
more
rwestrel Mar 23, 2026
b25babb
more
rwestrel Mar 23, 2026
73dca84
more
rwestrel Mar 23, 2026
5db9d9b
more
rwestrel Mar 23, 2026
dd071ce
c1
rwestrel Mar 24, 2026
29de8aa
more
rwestrel Mar 24, 2026
8396d97
more
rwestrel Mar 24, 2026
8847995
more
rwestrel Mar 26, 2026
9b525fd
more
rwestrel Mar 26, 2026
dfd4ac3
more
rwestrel Mar 26, 2026
84464fc
more
rwestrel Mar 30, 2026
d63cf35
more
rwestrel Mar 31, 2026
7ce9983
more
rwestrel Mar 31, 2026
8394612
more
rwestrel Apr 1, 2026
5bfeb70
more
rwestrel Apr 7, 2026
eb897a8
more
rwestrel Apr 23, 2026
22301b8
more
rwestrel Apr 23, 2026
50c2a47
more
rwestrel Apr 24, 2026
bbd588f
more
rwestrel Apr 27, 2026
034d00a
more
rwestrel Apr 29, 2026
5a746c1
more
rwestrel Apr 29, 2026
af4df42
more
rwestrel Apr 29, 2026
e8cb7a8
more
rwestrel Apr 30, 2026
df3f89c
exp
rwestrel Apr 30, 2026
2206592
exp
rwestrel Apr 30, 2026
97c57d0
more
rwestrel Apr 30, 2026
bbf644e
more
rwestrel May 7, 2026
d75156f
more
rwestrel May 7, 2026
e5e144e
more
rwestrel May 11, 2026
21570f4
more
rwestrel May 11, 2026
ba9920d
exps
rwestrel May 12, 2026
a8af613
exps
rwestrel May 13, 2026
032343b
more
rwestrel May 13, 2026
e62c91f
fix
rwestrel May 19, 2026
30f7e21
product build fix
rwestrel May 20, 2026
66ed8bb
build fix
rwestrel May 20, 2026
0bfe8ac
whitespaces
rwestrel May 20, 2026
aa4a304
profile_receiver_type_helper fixes
rwestrel May 21, 2026
1ef6ee8
profile_receiver_type_helper fixes
rwestrel May 21, 2026
0abe39a
merge
rwestrel Jun 1, 2026
42e52e2
more
rwestrel Jun 1, 2026
170c629
Port changes to aarch64
galderz May 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2971,6 +2971,48 @@ void LIR_Assembler::emit_profile_inline_type(LIR_OpProfileInlineType* op) {
__ bind(not_inline_type);
}

void LIR_Assembler::emit_profile_multiple_array_types(LIR_OpProfileMultipleArrayTypes* op) {
Register array = op->array()->as_pointer_register();
Register tmp1 = op->tmp1()->as_pointer_register();
Register tmp2 = op->tmp2()->as_pointer_register();
ciMethodData* md = op->md();

Label not_flat, done;
__ test_non_flat_array_oop (array, tmp1, not_flat);

Register klass = tmp1;
__ load_klass(klass, array);

Register mdo = tmp2;
__ mov_metadata(mdo, md->constant_encoding());

int mdp_offset = md->byte_offset_of_slot(op->load(), in_ByteSize(0));
__ profile_array_type_at_load(tmp1, mdo, mdp_offset);

__ b(done);
__ bind(not_flat);
__ mov_metadata(mdo, md->constant_encoding());

Label null_free;

__ test_null_free_array_oop(array, tmp1, null_free);

{
Address counter_addr(mdo, md->byte_offset_of_slot(op->load(), ArrayLoadData::not_flat_nullable_count_offset()));
__ addptr(counter_addr, DataLayout::counter_increment);
}

__ b(done);
__ bind(null_free);

{
Address counter_addr(mdo, md->byte_offset_of_slot(op->load(), ArrayLoadData::not_flat_null_free_count_offset()));
__ addptr(counter_addr, DataLayout::counter_increment);
}

__ bind(done);
}

void LIR_Assembler::align_backward_branch_target() {
}

Expand Down
52 changes: 39 additions & 13 deletions src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1202,44 +1202,70 @@ void InterpreterMacroAssembler::profile_switch_case(Register index,
}
}

template <class ArrayData> void InterpreterMacroAssembler::profile_array_type(Register mdp,
Register array,
Register tmp) {
void InterpreterMacroAssembler::profile_array_type(Register mdp,
Register array,
Register tmp) {
if (ProfileInterpreter) {
Label profile_continue;

// If no method data exists, go to profile_continue.
test_method_data_pointer(mdp, profile_continue);

mov(tmp, array);
profile_obj_type(tmp, Address(mdp, in_bytes(ArrayData::array_offset())));
profile_obj_type(tmp, Address(mdp, in_bytes(ArrayStoreData::array_offset())));

Label not_flat;
test_non_flat_array_oop(array, tmp, not_flat);

set_mdp_flag_at(mdp, ArrayData::flat_array_byte_constant());
set_mdp_flag_at(mdp, ArrayStoreData::flat_array_byte_constant());

bind(not_flat);

Label not_null_free;
test_non_null_free_array_oop(array, tmp, not_null_free);

set_mdp_flag_at(mdp, ArrayData::null_free_array_byte_constant());
set_mdp_flag_at(mdp, ArrayStoreData::null_free_array_byte_constant());

bind(not_null_free);

bind(profile_continue);
}
}

template void InterpreterMacroAssembler::profile_array_type<ArrayLoadData>(Register mdp,
Register array,
Register tmp);
template void InterpreterMacroAssembler::profile_array_type<ArrayStoreData>(Register mdp,
Register array,
Register tmp);
void InterpreterMacroAssembler::profile_multiple_array_types(Register mdp,
Register array,
Register tmp) {
if (ProfileInterpreter) {
Label profile_continue;

// If no method data exists, go to profile_continue.
test_method_data_pointer(mdp, profile_continue);

Label not_flat;
test_non_flat_array_oop(array, tmp, not_flat);

load_klass(tmp, array);
profile_array_type_at_load(tmp, mdp, 0);

b(profile_continue);
bind(not_flat);

Label not_null_free;
test_non_null_free_array_oop(array, tmp, not_null_free);

increment_mdp_data_at(mdp, in_bytes(ArrayLoadData::not_flat_null_free_count_offset()));

b(profile_continue);

bind(not_null_free);

increment_mdp_data_at(mdp, in_bytes(ArrayLoadData::not_flat_nullable_count_offset()));

bind(profile_continue);
}
}

void InterpreterMacroAssembler::profile_multiple_element_types(Register mdp, Register element, Register tmp, const Register tmp2) {
void InterpreterMacroAssembler::profile_multiple_element_types(Register mdp, Register element, Register tmp) {
if (ProfileInterpreter) {
Label profile_continue;

Expand Down
5 changes: 3 additions & 2 deletions src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
void profile_switch_default(Register mdp);
void profile_switch_case(Register index_in_scratch, Register mdp,
Register scratch2);
template <class ArrayData> void profile_array_type(Register mdp, Register array, Register tmp);
void profile_multiple_element_types(Register mdp, Register element, Register tmp, Register tmp2);
void profile_array_type(Register mdp, Register array, Register tmp);
void profile_multiple_array_types(Register mdp, Register array, Register tmp);
void profile_multiple_element_types(Register mdp, Register element, Register tmp);
void profile_element_type(Register mdp, Register element, Register tmp);
void profile_acmp(Register mdp, Register left, Register right, Register tmp);

Expand Down
153 changes: 115 additions & 38 deletions src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2112,56 +2112,32 @@ Address MacroAssembler::argument_address(RegisterOrConstant arg_slot,
}
}

// Handle the receiver type profile update given the "recv" klass.
//
// Normally updates the ReceiverData (RD) that starts at "mdp" + "mdp_offset".
// If there are no matching or claimable receiver entries in RD, updates
// the polymorphic counter.
//
// This code expected to run by either the interpreter or JIT-ed code, without
// extra synchronization. For safety, receiver cells are claimed atomically, which
// avoids grossly misrepresenting the profiles under concurrent updates. For speed,
// counter updates are not atomic.
//
void MacroAssembler::profile_receiver_type(Register recv, Register mdp, int mdp_offset) {
assert_different_registers(recv, mdp, rscratch1, rscratch2);

int base_receiver_offset = in_bytes(ReceiverTypeData::receiver_offset(0));
int end_receiver_offset = in_bytes(ReceiverTypeData::receiver_offset(ReceiverTypeData::row_limit()));
int poly_count_offset = in_bytes(CounterData::count_offset());
int receiver_step = in_bytes(ReceiverTypeData::receiver_offset(1)) - base_receiver_offset;
int receiver_to_count_step = in_bytes(ReceiverTypeData::receiver_count_offset(0)) - base_receiver_offset;
void MacroAssembler::profile_receiver_type_helper(Register recv, Register mdp, Label &L_found_recv, int mdp_offset, int base, uint row_limit) {
int base_receiver_offset = in_bytes(MegamorphicTypeData::receiver_offset(base, 0));
int end_receiver_offset = in_bytes(MegamorphicTypeData::receiver_offset(base, row_limit));
int receiver_step = in_bytes(MegamorphicTypeData::receiver_offset(base, 1)) - base_receiver_offset;
int receiver_to_count_step = in_bytes(MegamorphicTypeData::receiver_count_offset(base, 0)) - base_receiver_offset;

// Adjust for MDP offsets.
base_receiver_offset += mdp_offset;
end_receiver_offset += mdp_offset;
poly_count_offset += mdp_offset;

#ifdef ASSERT
// We are about to walk the MDO slots without asking for offsets.
// Check that our math hits all the right spots.
for (uint c = 0; c < ReceiverTypeData::row_limit(); c++) {
int real_recv_offset = mdp_offset + in_bytes(ReceiverTypeData::receiver_offset(c));
int real_count_offset = mdp_offset + in_bytes(ReceiverTypeData::receiver_count_offset(c));
int real_recv_offset = mdp_offset + in_bytes(MegamorphicTypeData::receiver_offset(base, c));
int real_count_offset = mdp_offset + in_bytes(MegamorphicTypeData::receiver_count_offset(base, c));
int offset = base_receiver_offset + receiver_step*c;
int count_offset = offset + receiver_to_count_step;
assert(offset == real_recv_offset, "receiver slot math");
assert(offset== real_recv_offset, "receiver slot math");
assert(count_offset == real_count_offset, "receiver count math");
}
int real_poly_count_offset = mdp_offset + in_bytes(CounterData::count_offset());
assert(poly_count_offset == real_poly_count_offset, "poly counter math");
#endif

// Corner case: no profile table. Increment poly counter and exit.
if (ReceiverTypeData::row_limit() == 0) {
increment(Address(mdp, poly_count_offset), DataLayout::counter_increment);
return;
}

Register offset = rscratch2;

Label L_loop_search_receiver, L_loop_search_empty;
Label L_restart, L_found_recv, L_found_empty, L_polymorphic, L_count_update;
Label L_restart, L_found_empty, L_polymorphic;

// The code here recognizes three major cases:
// A. Fastest: receiver found in the table
Expand Down Expand Up @@ -2215,18 +2191,18 @@ void MacroAssembler::profile_receiver_type(Register recv, Register mdp, int mdp_
// Fastest: receiver is already installed
mov(offset, base_receiver_offset);
bind(L_loop_search_receiver);
ldr(rscratch1, Address(mdp, offset));
cmp(rscratch1, recv);
br(Assembler::EQ, L_found_recv);
ldr(rscratch1, Address(mdp, offset));
cmp(rscratch1, recv);
br(Assembler::EQ, L_found_recv);
add(offset, offset, receiver_step);
sub(rscratch1, offset, end_receiver_offset);
cbnz(rscratch1, L_loop_search_receiver);

// Fast: no receiver, but profile is full
mov(offset, base_receiver_offset);
bind(L_loop_search_empty);
ldr(rscratch1, Address(mdp, offset));
cbz(rscratch1, L_found_empty);
ldr(rscratch1, Address(mdp, offset));
cbz(rscratch1, L_found_empty);
add(offset, offset, receiver_step);
sub(rscratch1, offset, end_receiver_offset);
cbnz(rscratch1, L_loop_search_empty);
Expand Down Expand Up @@ -2255,7 +2231,46 @@ void MacroAssembler::profile_receiver_type(Register recv, Register mdp, int mdp_

// Increment polymorphic counter instead of receiver slot.
bind(L_polymorphic);
}

// Handle the receiver type profile update given the "recv" klass.
//
// Normally updates the ReceiverData (RD) that starts at "mdp" + "mdp_offset".
// If there are no matching or claimable receiver entries in RD, updates
// the polymorphic counter.
//
// This code expected to run by either the interpreter or JIT-ed code, without
// extra synchronization. For safety, receiver cells are claimed atomically, which
// avoids grossly misrepresenting the profiles under concurrent updates. For speed,
// counter updates are not atomic.
//
void MacroAssembler::profile_receiver_type(Register recv, Register mdp, int mdp_offset) {
assert_different_registers(recv, mdp, rscratch1, rscratch2);

int poly_count_offset = in_bytes(ReceiverTypeData::count_offset());
int base_receiver_offset = in_bytes(ReceiverTypeData::receiver_offset(0));
int receiver_to_count_step = in_bytes(ReceiverTypeData::receiver_count_offset(0)) - base_receiver_offset;

// Adjust for MDP offsets.
poly_count_offset += mdp_offset;

#ifdef ASSERT
int real_poly_count_offset = mdp_offset + in_bytes(ReceiverTypeData::count_offset());
assert(poly_count_offset == real_poly_count_offset, "poly counter math");
#endif

// Corner case: no profile table. Increment poly counter and exit.
if (ReceiverTypeData::row_limit() == 0) {
increment(Address(mdp, poly_count_offset), DataLayout::counter_increment);
return;
}

Label L_found_recv;
profile_receiver_type_helper(recv, mdp, L_found_recv, mdp_offset, ReceiverTypeData::base_of_megamorphic_type_data(), ReceiverTypeData::row_limit());
// Increment polymorphic counter instead of receiver slot.
Register offset = rscratch2;
mov(offset, poly_count_offset);
Label L_count_update;
b(L_count_update);

// Found a receiver, convert its slot offset to corresponding count offset.
Expand All @@ -2266,6 +2281,68 @@ void MacroAssembler::profile_receiver_type(Register recv, Register mdp, int mdp_
increment(Address(mdp, offset), DataLayout::counter_increment);
}

void MacroAssembler::profile_array_type_at_load(Register recv, Register mdp, int mdp_offset) {
int base_receiver_offset = in_bytes(ArrayLoadData::receiver_offset(0));
int receiver_to_count_step = in_bytes(ArrayLoadData::receiver_count_offset(0)) - base_receiver_offset;
int flat_nullable_count_offset = in_bytes(ArrayLoadData::flat_nullable_count_offset());
int flat_nullfree_atomic_count_offset = in_bytes(ArrayLoadData::flat_nullfree_atomic_count_offset());
int flat_nullfree_not_atomic_count_offset = in_bytes(ArrayLoadData::flat_nullfree_not_atomic_count_offset());

// Adjust for MDP offsets. Slots are pointer-sized, so is the global offset.
flat_nullable_count_offset += mdp_offset;
flat_nullfree_atomic_count_offset += mdp_offset;
flat_nullfree_not_atomic_count_offset += mdp_offset;

#ifdef ASSERT
int real_flat_nullable_count_offset = mdp_offset + in_bytes(ArrayLoadData::flat_nullable_count_offset());
assert(flat_nullable_count_offset == real_flat_nullable_count_offset, "poly counter math");
int real_flat_nullfree_atomic_count_offset = mdp_offset + in_bytes(ArrayLoadData::flat_nullfree_atomic_count_offset());
assert(flat_nullfree_atomic_count_offset == real_flat_nullfree_atomic_count_offset, "poly counter math");
int real_flat_nullfree_not_atomic_count_offset = mdp_offset + in_bytes(ArrayLoadData::flat_nullfree_not_atomic_count_offset());
assert(flat_nullfree_not_atomic_count_offset == real_flat_nullfree_not_atomic_count_offset, "poly counter math");
#endif

// Corner case: no profile table. Increment poly counter and exit.
if (ReceiverTypeData::row_limit() == 0) {
ShouldNotReachHere();
return;
}

Label L_found_recv;
profile_receiver_type_helper(recv, mdp, L_found_recv, mdp_offset, ArrayLoadData::base_of_megamorphic_type_data(), ArrayLoadData::row_limit());
Register offset = rscratch2;
int layout_kind_offset = in_bytes(FlatArrayKlass::layout_kind_offset());
Label null_free_non_atomic, null_free_atomic, nullable_atomic_flat, failure, L_count_update;
ldrw(rscratch1, Address(recv, layout_kind_offset));
cmpw(rscratch1, (int)LayoutKind::NULL_FREE_ATOMIC_FLAT);
br(NE, null_free_non_atomic);
mov(offset, flat_nullfree_atomic_count_offset);

b(L_count_update);
bind(null_free_non_atomic);
ldrw(rscratch1, Address(recv, layout_kind_offset));
cmpw(rscratch1, (int)LayoutKind::NULL_FREE_NON_ATOMIC_FLAT);
br(NE, nullable_atomic_flat);
mov(offset, flat_nullfree_not_atomic_count_offset);

b(L_count_update);
bind(nullable_atomic_flat);
ldrw(rscratch1, Address(recv, layout_kind_offset));
cmpw(rscratch1, (int)LayoutKind::NULLABLE_ATOMIC_FLAT);
br(NE, failure);
mov(offset, flat_nullable_count_offset);

b(L_count_update);
bind(failure);
stop("unexpected flat array");

// Found a receiver, convert its slot offset to corresponding count offset.
bind(L_found_recv);
add(offset, offset, receiver_to_count_step);

bind(L_count_update);
increment(Address(mdp, offset), DataLayout::counter_increment);
}

void MacroAssembler::call_VM_leaf_base(address entry_point,
int number_of_arguments,
Expand Down
4 changes: 4 additions & 0 deletions src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1158,7 +1158,11 @@ class MacroAssembler: public Assembler {

Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0);

void profile_receiver_type_helper(Register recv, Register mdp,
Label &L_found_recv, int mdp_offset, int base, uint row_limit);

void profile_receiver_type(Register recv, Register mdp, int mdp_offset);
void profile_array_type_at_load(Register recv, Register mdp, int mdp_offset);

void verify_sve_vector_length(Register tmp = rscratch1);
void reinitialize_ptrue() {
Expand Down
6 changes: 3 additions & 3 deletions src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ void TemplateTable::aaload()
// r0: array
// r1: index
index_check(r0, r1); // leaves index in r1, kills rscratch1
__ profile_array_type<ArrayLoadData>(r2, r0, r4);
__ profile_multiple_array_types(r2, r0, r4);
if (UseArrayFlattening) {
Label is_flat_array, done;

Expand Down Expand Up @@ -1133,8 +1133,8 @@ void TemplateTable::aastore() {

index_check(r3, r2); // kills r1

__ profile_array_type<ArrayStoreData>(r4, r3, r5);
__ profile_multiple_element_types(r4, r0, r5, r6);
__ profile_array_type(r4, r3, r5);
__ profile_multiple_element_types(r4, r0, r5);

__ add(r4, r2, arrayOopDesc::base_offset_in_bytes(T_OBJECT) >> LogBytesPerHeapOop);
Address element_address(r3, r4, Address::uxtw(LogBytesPerHeapOop));
Expand Down
Loading