From b428cda3c6a445ffa638c6f4e86225d86a1876d4 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Thu, 3 Apr 2025 14:47:26 +0000 Subject: [PATCH] 8349686: [s390x] C1: Improve Class.isInstance intrinsic Reviewed-by: lucy, aph --- src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp | 2 +- src/hotspot/cpu/s390/c1_Runtime1_s390.cpp | 61 +++++++++++++++++++ src/hotspot/cpu/s390/macroAssembler_s390.cpp | 50 ++++++++++++--- src/hotspot/cpu/s390/macroAssembler_s390.hpp | 2 + 4 files changed, 104 insertions(+), 11 deletions(-) diff --git a/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp b/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp index 8cb8cef2b6b..94a528a7467 100644 --- a/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp @@ -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); } diff --git a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp index 34b21ff3d15..b5d804d283e 100644 --- a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp +++ b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp @@ -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 diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index 3f61561f5b8..54370a4959b 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -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); + } +} diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.hpp b/src/hotspot/cpu/s390/macroAssembler_s390.hpp index d45f1321e0f..3f7744588d6 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp @@ -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