8349686: [s390x] C1: Improve Class.isInstance intrinsic

Reviewed-by: lucy, aph
This commit is contained in:
Amit Kumar 2025-04-03 14:47:26 +00:00
parent 70e3250045
commit b428cda3c6
4 changed files with 104 additions and 11 deletions

View File

@ -961,7 +961,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) {
// Intrinsic for Class::isInstance
address LIRGenerator::isInstance_entry() {
return CAST_FROM_FN_PTR(address, Runtime1::is_instance_of);
return Runtime1::entry_for(C1StubId::is_instance_of_id);
}

View File

@ -589,6 +589,67 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) {
__ z_br(Z_R14);
}
break;
case C1StubId::is_instance_of_id:
{
// Mirror: Z_ARG1(R2)
// Object: Z_ARG2
// Temps: Z_ARG3, Z_ARG4, Z_ARG5, Z_R10, Z_R11
// Result: Z_RET(R2)
// Get the Klass* into Z_ARG3
Register klass = Z_ARG3 , obj = Z_ARG2, result = Z_RET;
Register temp0 = Z_ARG4, temp1 = Z_ARG5, temp2 = Z_R10, temp3 = Z_R11;
__ z_ltg(klass, Address(Z_ARG1, java_lang_Class::klass_offset())); // Klass is null
Label is_secondary;
__ clear_reg(result /* Z_R2 */, true /* whole_reg */, false /* set_cc */); // sets result=0 (failure)
__ z_bcr(Assembler::bcondEqual, Z_R14); // cc set by z_ltg above
__ z_ltgr(obj, obj); // obj is null
__ z_bcr(Assembler::bcondEqual, Z_R14);
__ z_llgf(temp0, Address(klass, in_bytes(Klass::super_check_offset_offset())));
__ compare32_and_branch(temp0, in_bytes(Klass::secondary_super_cache_offset()), Assembler::bcondEqual, is_secondary); // Klass is a secondary superclass
// Klass is a concrete class
__ load_klass(temp1, obj);
__ z_cg(klass, Address(temp1, temp0));
// result is already holding 0, denoting NotEqual case
__ load_on_condition_imm_32(result, 1, Assembler::bcondEqual);
__ z_br(Z_R14);
__ bind(is_secondary);
__ load_klass(obj, obj);
// This is necessary because I am never in my own secondary_super list.
__ z_cgr(obj, klass);
__ load_on_condition_imm_32(result, 1, Assembler::bcondEqual);
__ z_bcr(Assembler::bcondEqual, Z_R14);
// Z_R10 and Z_R11 are callee saved, so we must need to preserve them before any use
__ z_ldgr(Z_F1, Z_R10);
__ z_ldgr(Z_F3, Z_R11);
__ lookup_secondary_supers_table_var(obj, klass,
/*temps*/ temp0, temp1, temp2, temp3,
result);
// lookup_secondary_supers_table_var return 0 on success and 1 on failure.
// but this method returns 0 on failure and 1 on success.
// so we have to invert the result from lookup_secondary_supers_table_var.
__ z_xilf(result, 1); // invert the result
__ z_lgdr(Z_R10, Z_F1);
__ z_lgdr(Z_R11, Z_F3);
__ z_br(Z_R14);
}
case C1StubId::monitorenter_nofpu_id:
case C1StubId::monitorenter_id:
{ // Z_R1_scratch : object

View File

@ -3679,9 +3679,6 @@ void MacroAssembler::verify_secondary_supers_table(Register r_sub_klass,
r_array_index = r_temp3,
r_bitmap = noreg; // unused
const Register r_one = Z_R0_scratch;
z_lghi(r_one, 1); // for locgr down there, to a load result for failure
BLOCK_COMMENT("verify_secondary_supers_table {");
Label L_passed, L_failure;
@ -3697,7 +3694,7 @@ void MacroAssembler::verify_secondary_supers_table(Register r_sub_klass,
const Register r_linear_result = r_array_index; // reuse
z_chi(r_array_length, 0);
z_locgr(r_linear_result, r_one, bcondNotHigh); // load failure if array_length <= 0
load_on_condition_imm_32(r_linear_result, 1, bcondNotHigh); // load failure if array_length <= 0
z_brc(bcondNotHigh, L_failure);
repne_scan(r_array_base, r_super_klass, r_array_length, r_linear_result);
bind(L_failure);
@ -3705,13 +3702,20 @@ void MacroAssembler::verify_secondary_supers_table(Register r_sub_klass,
z_cr(r_result, r_linear_result);
z_bre(L_passed);
assert_different_registers(Z_ARG1, r_sub_klass, r_linear_result, r_result);
lgr_if_needed(Z_ARG1, r_super_klass);
assert_different_registers(Z_ARG2, r_linear_result, r_result);
lgr_if_needed(Z_ARG2, r_sub_klass);
assert_different_registers(Z_ARG3, r_result);
z_lgr(Z_ARG3, r_linear_result);
// report fatal error and terminate VM
// Argument shuffle
// Z_F1, Z_F3, Z_F5 are volatile regs
z_ldgr(Z_F1, r_super_klass);
z_ldgr(Z_F3, r_sub_klass);
z_ldgr(Z_F5, r_linear_result);
z_lgr(Z_ARG4, r_result);
z_lgdr(Z_ARG1, Z_F1); // r_super_klass
z_lgdr(Z_ARG2, Z_F3); // r_sub_klass
z_lgdr(Z_ARG3, Z_F5); // r_linear_result
const char* msg = "mismatch";
load_const_optimized(Z_ARG5, (address)msg);
@ -6944,3 +6948,29 @@ void MacroAssembler::pop_count_int_with_ext3(Register r_dst, Register r_src) {
BLOCK_COMMENT("} pop_count_int_with_ext3");
}
// LOAD HALFWORD IMMEDIATE ON CONDITION (32 <- 16)
void MacroAssembler::load_on_condition_imm_32(Register dst, int64_t i2, branch_condition cc) {
if (VM_Version::has_LoadStoreConditional2()) { // z_lochi works on z13 or above
assert(Assembler::is_simm16(i2), "sanity");
z_lochi(dst, i2, cc);
} else {
NearLabel done;
z_brc(Assembler::inverse_condition(cc), done);
z_lhi(dst, i2);
bind(done);
}
}
// LOAD HALFWORD IMMEDIATE ON CONDITION (64 <- 16)
void MacroAssembler::load_on_condition_imm_64(Register dst, int64_t i2, branch_condition cc) {
if (VM_Version::has_LoadStoreConditional2()) { // z_locghi works on z13 or above
assert(Assembler::is_simm16(i2), "sanity");
z_locghi(dst, i2, cc);
} else {
NearLabel done;
z_brc(Assembler::inverse_condition(cc), done);
z_lghi(dst, i2);
bind(done);
}
}

View File

@ -1109,6 +1109,8 @@ class MacroAssembler: public Assembler {
void pop_count_int_with_ext3(Register dst, Register src);
void pop_count_long_with_ext3(Register dst, Register src);
void load_on_condition_imm_32(Register dst, int64_t i2, branch_condition cc);
void load_on_condition_imm_64(Register dst, int64_t i2, branch_condition cc);
};
#ifdef ASSERT