From 4ad82cbf9f47bf44cd479126b6f44722d91735fa Mon Sep 17 00:00:00 2001 From: zifeihan Date: Tue, 22 Oct 2024 20:02:17 +0800 Subject: [PATCH] Add riscv port v10 --- src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp | 7 +- .../cpu/riscv/macroAssembler_riscv.cpp | 273 ++++++++++++++++-- .../cpu/riscv/macroAssembler_riscv.hpp | 59 +++- src/hotspot/cpu/riscv/riscv.ad | 58 ++-- src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 28 +- 5 files changed, 350 insertions(+), 75 deletions(-) diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp index 5e4031727c827..d42ab9b274230 100644 --- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp @@ -859,7 +859,12 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { __ ld(x10, Address(sp, (sup_k_off) * VMRegImpl::stack_slot_size)); // super klass Label miss; - __ check_klass_subtype_slow_path(x14, x10, x12, x15, nullptr, &miss); + __ check_klass_subtype_slow_path(x14, /*sub_klass*/ + x10, /*super_klass*/ + x12, /*tmp1_reg*/ + x15, /*tmp2_reg*/ + nullptr, /*L_success*/ + &miss /*L_failure*/); // fallthrough on success: __ mv(t0, 1); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 9408481fba144..c73d97ac20fbb 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -2426,6 +2426,24 @@ void MacroAssembler::revb(Register Rd, Register Rs, Register tmp1, Register tmp2 orr(Rd, tmp1, Rd); } +// rotate right with shift bits +void MacroAssembler::ror_reg(Register dst, Register src, Register shift, Register tmp) +{ + if (UseZbb) { + ror(dst, src, shift); + return; + } + + assert_different_registers(dst, tmp); + assert_different_registers(src, tmp); + + li(tmp, 64); + sub(tmp, tmp, shift); + sll(tmp, src, tmp); + srl(dst, src, shift); + orr(dst, dst, tmp); +} + // rotate right with shift bits void MacroAssembler::ror_imm(Register dst, Register src, uint32_t shift, Register tmp) { @@ -3682,12 +3700,10 @@ void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, Label* L_failure, Label* L_slow_path, Register super_check_offset) { - assert_different_registers(sub_klass, super_klass, tmp_reg); - bool must_load_sco = (super_check_offset == noreg); + assert_different_registers(sub_klass, super_klass, tmp_reg, super_check_offset); + bool must_load_sco = !super_check_offset->is_valid(); if (must_load_sco) { assert(tmp_reg != noreg, "supply either a temp or a register offset"); - } else { - assert_different_registers(sub_klass, super_klass, super_check_offset); } Label L_fallthrough; @@ -3764,12 +3780,12 @@ void MacroAssembler::repne_scan(Register addr, Register value, Register count, bind(Lexit); } -void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, - Register super_klass, - Register tmp1_reg, - Register tmp2_reg, - Label* L_success, - Label* L_failure) { +void MacroAssembler::check_klass_subtype_slow_path_linear(Register sub_klass, + Register super_klass, + Register tmp1_reg, + Register tmp2_reg, + Label* L_success, + Label* L_failure) { assert_different_registers(sub_klass, super_klass, tmp1_reg); if (tmp2_reg != noreg) { assert_different_registers(sub_klass, super_klass, tmp1_reg, tmp2_reg, t0); @@ -3843,7 +3859,9 @@ void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, bne(t1, t0, *L_failure); // Success. Cache the super we found an proceed in triumph. - sd(super_klass, super_cache_addr); + if (UseSecondarySupersCache) { + sd(super_klass, super_cache_addr); + } if (L_success != &L_fallthrough) { j(*L_success); @@ -3884,6 +3902,104 @@ void MacroAssembler::population_count(Register dst, Register src, } } +// If Register r is invalid, remove a new register from +// available_regs, and add new register to regs_to_push. +Register MacroAssembler::allocate_if_noreg(Register r, + RegSetIterator &available_regs, + RegSet ®s_to_push) { + if (!r->is_valid()) { + r = *available_regs++; + regs_to_push += r; + } + return r; +} + +// check_klass_subtype_slow_path_table() looks for super_klass in the +// hash table belonging to super_klass, branching to L_success or +// L_failure as appropriate. This is essentially a shim which +// allocates registers as necessary then calls +// lookup_secondary_supers_table() to do the work. Any of the tmp +// regs may be noreg, in which case this logic will chooses some +// registers push and pop them from the stack. +void MacroAssembler::check_klass_subtype_slow_path_table(Register sub_klass, + Register super_klass, + Register tmp1_reg, + Register tmp2_reg, + Label* L_success, + Label* L_failure, + bool set_cond_codes) { + RegSet tmps = RegSet::of(tmp1_reg, tmp2_reg); + + assert_different_registers(sub_klass, super_klass, tmp1_reg, tmp2_reg); + + Label L_fallthrough; + int label_nulls = 0; + if (L_success == nullptr) { L_success = &L_fallthrough; label_nulls++; } + if (L_failure == nullptr) { L_failure = &L_fallthrough; label_nulls++; } + assert(label_nulls <= 1, "at most one null in the batch"); + + BLOCK_COMMENT("check_klass_subtype_slow_path"); + + RegSet caller_save_regs = RegSet::of(x7) + RegSet::range(x10, x17) + RegSet::range(x28, x31); + RegSetIterator available_regs = (caller_save_regs - tmps - sub_klass - super_klass).begin(); + + RegSet pushed_regs; + + tmp1_reg = allocate_if_noreg(tmp1_reg, available_regs, pushed_regs); + tmp2_reg = allocate_if_noreg(tmp2_reg, available_regs, pushed_regs); + + Register tmp3_reg = noreg, tmp4_reg = noreg, tmp5_reg = noreg, result_reg = noreg; + + tmp3_reg = allocate_if_noreg(tmp3_reg, available_regs, pushed_regs); + tmp4_reg = allocate_if_noreg(tmp4_reg, available_regs, pushed_regs); + tmp5_reg = allocate_if_noreg(tmp5_reg, available_regs, pushed_regs); + result_reg = allocate_if_noreg(result_reg, available_regs, pushed_regs); + + push_reg(pushed_regs, sp); + + lookup_secondary_supers_table_var(sub_klass, + super_klass, + result_reg, + tmp1_reg, tmp2_reg, tmp3_reg, + tmp4_reg, nullptr); + + // We will Unspill the tmp registers, so we should mark the result_reg to t1. + mv(t1, result_reg); + + // Unspill the tmp. registers: + pop_reg(pushed_regs, sp); + + // NB! Callers may assume that, when set_cond_codes is true, this + // code sets tmp2_reg to a nonzero value. + if (set_cond_codes) { + mv(tmp2_reg, 1); + } + + bnez(t1, *L_failure); + + if (L_success != &L_fallthrough) { + j(*L_success); + } + + bind(L_fallthrough); +} + +void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register tmp1_reg, + Register tmp2_reg, + Label* L_success, + Label* L_failure, + bool set_cond_codes) { + if (UseSecondarySupersTable) { + check_klass_subtype_slow_path_table + (sub_klass, super_klass, tmp1_reg, tmp2_reg, L_success, L_failure, set_cond_codes); + } else { + check_klass_subtype_slow_path_linear + (sub_klass, super_klass, tmp1_reg, tmp2_reg, L_success, L_failure); + } +} + // Ensure that the inline code and the stub are using the same registers // as we need to call the stub from inline code when there is a collision // in the hashed lookup in the secondary supers array. @@ -3899,17 +4015,16 @@ do { (r_bitmap == x16 || r_bitmap == noreg), "registers must match riscv.ad"); \ } while(0) -// Return true: we succeeded in generating this code -bool MacroAssembler::lookup_secondary_supers_table(Register r_sub_klass, - Register r_super_klass, - Register result, - Register tmp1, - Register tmp2, - Register tmp3, - Register tmp4, - u1 super_klass_slot, - bool stub_is_near) { - assert_different_registers(r_sub_klass, r_super_klass, result, tmp1, tmp2, tmp3, tmp4, t0); +bool MacroAssembler::lookup_secondary_supers_table_const(Register r_sub_klass, + Register r_super_klass, + Register result, + Register tmp1, + Register tmp2, + Register tmp3, + Register tmp4, + u1 super_klass_slot, + bool stub_is_near) { + assert_different_registers(r_sub_klass, r_super_klass, result, tmp1, tmp2, tmp3, tmp4, t0, t1); Label L_fallthrough; @@ -3984,6 +4099,98 @@ bool MacroAssembler::lookup_secondary_supers_table(Register r_sub_klass, return true; } +// At runtime, return 0 in result if r_super_klass is a superclass of +// r_sub_klass, otherwise return nonzero. Use this version of +// lookup_secondary_supers_table() if you don't know ahead of time +// which superclass will be searched for. Used by interpreter and +// runtime stubs. It is larger and has somewhat greater latency than +// the version above, which takes a constant super_klass_slot. +void MacroAssembler::lookup_secondary_supers_table_var(Register r_sub_klass, + Register r_super_klass, + Register result, + Register tmp1, + Register tmp2, + Register tmp3, + Register tmp4, + Label *L_success) { + assert_different_registers(r_sub_klass, r_super_klass, result, tmp1, tmp2, tmp3, tmp4, t0, t1); + + Label L_fallthrough; + + BLOCK_COMMENT("lookup_secondary_supers_table {"); + + const Register + r_array_index = tmp3, + r_bitmap = tmp4, + slot = t1; + + lbu(slot, Address(r_super_klass, Klass::hash_slot_offset())); + + // Make sure that result is nonzero if the test below misses. + mv(result, 1); + + ld(r_bitmap, Address(r_sub_klass, Klass::secondary_supers_bitmap_offset())); + + // First check the bitmap to see if super_klass might be present. If + // the bit is zero, we are certain that super_klass is not one of + // the secondary supers. + + // This next instruction is equivalent to: + // mv(tmp_reg, (u1)(Klass::SECONDARY_SUPERS_TABLE_SIZE - 1)); + // sub(r_array_index, slot, tmp_reg); + xori(r_array_index, slot, (u1)(Klass::SECONDARY_SUPERS_TABLE_SIZE - 1)); + sll(r_array_index, r_bitmap, r_array_index); + test_bit(t0, r_array_index, Klass::SECONDARY_SUPERS_TABLE_SIZE - 1); + beqz(t0, L_fallthrough); + + // Get the first array index that can contain super_klass into r_array_index. + population_count(r_array_index, r_array_index, tmp1, tmp2); + + // NB! r_array_index is off by 1. It is compensated by keeping r_array_base off by 1 word. + + const Register + r_array_base = tmp1, + r_array_length = tmp2; + + // The value i in r_array_index is >= 1, so even though r_array_base + // points to the length, we don't need to adjust it to point to the data. + assert(Array::base_offset_in_bytes() == wordSize, "Adjust this code"); + assert(Array::length_offset_in_bytes() == 0, "Adjust this code"); + + // We will consult the secondary-super array. + ld(r_array_base, Address(r_sub_klass, in_bytes(Klass::secondary_supers_offset()))); + + shadd(result, r_array_index, r_array_base, result, LogBytesPerWord); + ld(result, Address(result)); + xorr(result, result, r_super_klass); + beqz(result, L_success ? *L_success : L_fallthrough); // Found a match + + // Is there another entry to check? Consult the bitmap. + ror_reg(r_bitmap, r_bitmap, slot); + test_bit(t0, r_bitmap, 1); + beqz(t0, L_fallthrough); + + // The slot we just inspected is at secondary_supers[r_array_index - 1]. + // The next slot to be inspected, by the logic we're about to call, + // is secondary_supers[r_array_index]. Bits 0 and 1 in the bitmap + // have been checked. + lookup_secondary_supers_table_slow_path(r_super_klass, r_array_base, r_array_index, + r_bitmap, result, r_array_length, false /*is_stub*/); + + BLOCK_COMMENT("} lookup_secondary_supers_table"); + + bind(L_fallthrough); + + if (VerifySecondarySupers) { + verify_secondary_supers_table(r_sub_klass, r_super_klass, + result, tmp1, tmp2, tmp3); + } + + if (L_success) { + beqz(result, *L_success); + } +} + // Called by code generated by check_klass_subtype_slow_path // above. This is called when there is a collision in the hashed // lookup in the secondary supers array. @@ -3992,15 +4199,18 @@ void MacroAssembler::lookup_secondary_supers_table_slow_path(Register r_super_kl Register r_array_index, Register r_bitmap, Register result, - Register tmp1) { - assert_different_registers(r_super_klass, r_array_base, r_array_index, r_bitmap, tmp1, result, t0); + Register tmp, + bool is_stub) { + assert_different_registers(r_super_klass, r_array_base, r_array_index, r_bitmap, tmp, result, t0); const Register - r_array_length = tmp1, + r_array_length = tmp, r_sub_klass = noreg; // unused - LOOKUP_SECONDARY_SUPERS_TABLE_REGISTERS(r_super_klass, r_array_base, r_array_length, - r_array_index, r_sub_klass, result, r_bitmap); + if (is_stub) { + LOOKUP_SECONDARY_SUPERS_TABLE_REGISTERS(r_super_klass, r_array_base, r_array_length, + r_array_index, r_sub_klass, result, r_bitmap); + } Label L_matched, L_fallthrough, L_bitmap_full; @@ -4027,8 +4237,10 @@ void MacroAssembler::lookup_secondary_supers_table_slow_path(Register r_super_kl { // This is conventional linear probing, but instead of terminating // when a null entry is found in the table, we maintain a bitmap // in which a 0 indicates missing entries. - // The check above guarantees there are 0s in the bitmap, so the loop - // eventually terminates. + // As long as the bitmap is not completely full, + // array_length == popcount(bitmap). The array_length check above + // guarantees there are 0s in the bitmap, so the loop eventually + // terminates. Label L_loop; bind(L_loop); @@ -4080,9 +4292,6 @@ void MacroAssembler::verify_secondary_supers_table(Register r_sub_klass, r_array_index = noreg, // unused r_bitmap = noreg; // unused - LOOKUP_SECONDARY_SUPERS_TABLE_REGISTERS(r_super_klass, r_array_base, r_array_length, - r_array_index, r_sub_klass, result, r_bitmap); - BLOCK_COMMENT("verify_secondary_supers_table {"); // We will consult the secondary-super array. diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index fd174f241eb0b..d0fe3dbe52a01 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -322,21 +322,54 @@ class MacroAssembler: public Assembler { Register tmp1_reg, Register tmp2_reg, Label* L_success, - Label* L_failure); + Label* L_failure, + bool set_cond_codes = false); + + void check_klass_subtype_slow_path_linear(Register sub_klass, + Register super_klass, + Register tmp1_reg, + Register tmp2_reg, + Label* L_success, + Label* L_failure); + + void check_klass_subtype_slow_path_table(Register sub_klass, + Register super_klass, + Register tmp1_reg, + Register tmp2_reg, + Label* L_success, + Label* L_failure, + bool set_cond_codes = false); + + // If r is valid, return r. + // If r is invalid, remove a register r2 from available_regs, add r2 + // to regs_to_push, then return r2. + Register allocate_if_noreg(const Register r, + RegSetIterator &available_regs, + RegSet ®s_to_push); + + // Secondary subtype checking + void lookup_secondary_supers_table_var(Register sub_klass, + Register r_super_klass, + Register result, + Register tmp1, + Register tmp2, + Register tmp3, + Register tmp4, + Label *L_success); void population_count(Register dst, Register src, Register tmp1, Register tmp2); // As above, but with a constant super_klass. // The result is in Register result, not the condition codes. - bool lookup_secondary_supers_table(Register r_sub_klass, - Register r_super_klass, - Register result, - Register tmp1, - Register tmp2, - Register tmp3, - Register tmp4, - u1 super_klass_slot, - bool stub_is_near = false); + bool lookup_secondary_supers_table_const(Register r_sub_klass, + Register r_super_klass, + Register result, + Register tmp1, + Register tmp2, + Register tmp3, + Register tmp4, + u1 super_klass_slot, + bool stub_is_near = false); void verify_secondary_supers_table(Register r_sub_klass, Register r_super_klass, @@ -350,7 +383,8 @@ class MacroAssembler: public Assembler { Register r_array_index, Register r_bitmap, Register result, - Register tmp1); + Register tmp, + bool is_stub = true); void check_klass_subtype(Register sub_klass, Register super_klass, @@ -885,8 +919,9 @@ class MacroAssembler: public Assembler { void revb_w(Register Rd, Register Rs, Register tmp1 = t0, Register tmp2= t1); // reverse bytes in each word void revb(Register Rd, Register Rs, Register tmp1 = t0, Register tmp2 = t1); // reverse bytes in doubleword + void ror_reg(Register dst, Register src, Register shift, Register tmp = t0); void ror_imm(Register dst, Register src, uint32_t shift, Register tmp = t0); - void rolw_imm(Register dst, Register src, uint32_t, Register tmp = t0); + void rolw_imm(Register dst, Register src, uint32_t shift, Register tmp = t0); void andi(Register Rd, Register Rn, int64_t imm, Register tmp = t0); void orptr(Address adr, RegisterOrConstant src, Register tmp1 = t0, Register tmp2 = t1); diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 54d1f1c05736d..b64914fbcc755 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -2402,7 +2402,7 @@ encode %{ Label miss; Label done; __ check_klass_subtype_slow_path(sub_reg, super_reg, temp_reg, result_reg, - nullptr, &miss); + nullptr, &miss, true /*set_cond_codes:*/); if ($primary) { __ mv(result_reg, zr); } else { @@ -10084,10 +10084,11 @@ instruct CallLeafNoFPDirect(method meth, rFlagsReg cr) instruct partialSubtypeCheck(iRegP_R15 result, iRegP_R14 sub, iRegP_R10 super, iRegP_R12 tmp, rFlagsReg cr) %{ + predicate(!UseSecondarySupersTable); match(Set result (PartialSubtypeCheck sub super)); effect(KILL tmp, KILL cr); - ins_cost(11 * DEFAULT_COST); + ins_cost(20 * DEFAULT_COST); format %{ "partialSubtypeCheck $result, $sub, $super\t#@partialSubtypeCheck" %} ins_encode(riscv_enc_partial_subtype_check(sub, super, tmp, result)); @@ -10097,23 +10098,50 @@ instruct partialSubtypeCheck(iRegP_R15 result, iRegP_R14 sub, iRegP_R10 super, i ins_pipe(pipe_class_memory); %} +// Two versions of partialSubtypeCheck, both used when we need to +// search for a super class in the secondary supers array. The first +// is used when we don't know _a priori_ the class being searched +// for. The second, far more common, is used when we do know: this is +// used for instanceof, checkcast, and any case where C2 can determine +// it by constant propagation. + +instruct partialSubtypeCheckVarSuper(iRegP_R14 sub, iRegP_R10 super, iRegP_R15 result, + iRegP_R11 tmpR11, iRegP_R12 tmpR12, iRegP_R13 tmpR13, + iRegP_R16 tmpR16, rFlagsReg cr) +%{ + predicate(UseSecondarySupersTable); + match(Set result (PartialSubtypeCheck sub super)); + effect(TEMP tmpR11, TEMP tmpR12, TEMP tmpR13, TEMP tmpR16, KILL cr); + + ins_cost(10 * DEFAULT_COST); // slightly larger than the next version + format %{ "partialSubtypeCheck $result, $sub, $super" %} + + ins_encode %{ + __ lookup_secondary_supers_table_var($sub$$Register, $super$$Register, $result$$Register, + $tmpR11$$Register, $tmpR12$$Register, $tmpR13$$Register, + $tmpR16$$Register, nullptr /*L_success*/); + %} + + ins_pipe(pipe_class_memory); +%} + instruct partialSubtypeCheckConstSuper(iRegP_R14 sub, iRegP_R10 super_reg, immP super_con, iRegP_R15 result, iRegP_R11 tmpR11, iRegP_R12 tmpR12, iRegP_R13 tmpR13, iRegP_R16 tmpR16) %{ predicate(UseSecondarySupersTable); match(Set result (PartialSubtypeCheck sub (Binary super_reg super_con))); - effect(TEMP tmpR11, TEMP tmpR12, TEMP tmpR13, TEMP tmpR16); + effect(TEMP tmpR11, TEMP tmpR12, TEMP tmpR13, TEMP tmpR16, KILL cr); - ins_cost(7 * DEFAULT_COST); // needs to be less than competing nodes + ins_cost(5 * DEFAULT_COST); // needs to be less than competing nodes format %{ "partialSubtypeCheck $result, $sub, $super_reg, $super_con" %} ins_encode %{ bool success = false; u1 super_klass_slot = ((Klass*)$super_con$$constant)->hash_slot(); if (InlineSecondarySupersTest) { - success = __ lookup_secondary_supers_table($sub$$Register, $super_reg$$Register, $result$$Register, - $tmpR11$$Register, $tmpR12$$Register, $tmpR13$$Register, - $tmpR16$$Register, super_klass_slot); + success = __ lookup_secondary_supers_table_const($sub$$Register, $super_reg$$Register, $result$$Register, + $tmpR11$$Register, $tmpR12$$Register, $tmpR13$$Register, + $tmpR16$$Register, super_klass_slot); } else { address call = __ reloc_call(RuntimeAddress(StubRoutines::lookup_secondary_supers_table_stub(super_klass_slot))); success = (call != nullptr); @@ -10127,22 +10155,6 @@ instruct partialSubtypeCheckConstSuper(iRegP_R14 sub, iRegP_R10 super_reg, immP ins_pipe(pipe_class_memory); %} -instruct partialSubtypeCheckVsZero(iRegP_R15 result, iRegP_R14 sub, iRegP_R10 super, iRegP_R12 tmp, - immP0 zero, rFlagsReg cr) -%{ - match(Set cr (CmpP (PartialSubtypeCheck sub super) zero)); - effect(KILL tmp, KILL result); - - ins_cost(11 * DEFAULT_COST); - format %{ "partialSubtypeCheck $result, $sub, $super == 0\t#@partialSubtypeCheckVsZero" %} - - ins_encode(riscv_enc_partial_subtype_check(sub, super, tmp, result)); - - opcode(0x0); // Don't zero result reg on hit - - ins_pipe(pipe_class_memory); -%} - instruct string_compareU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr) %{ diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index bdb92e0b835f4..e76f15ffcaab0 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -1454,6 +1454,9 @@ class StubGenerator: public StubCodeGenerator { void generate_type_check(Register sub_klass, Register super_check_offset, Register super_klass, + Register result, + Register tmp1, + Register tmp2, Label& L_success) { assert_different_registers(sub_klass, super_check_offset, super_klass); @@ -1462,7 +1465,7 @@ class StubGenerator: public StubCodeGenerator { Label L_miss; __ check_klass_subtype_fast_path(sub_klass, super_klass, noreg, &L_success, &L_miss, nullptr, super_check_offset); - __ check_klass_subtype_slow_path(sub_klass, super_klass, noreg, noreg, &L_success, nullptr); + __ check_klass_subtype_slow_path(sub_klass, super_klass, tmp1, tmp2, &L_success, nullptr); // Fall through on failure! __ BIND(L_miss); @@ -1591,7 +1594,18 @@ class StubGenerator: public StubCodeGenerator { __ beqz(copied_oop, L_store_element); __ load_klass(r9_klass, copied_oop);// query the object klass - generate_type_check(r9_klass, ckoff, ckval, L_store_element); + + BLOCK_COMMENT("type_check:"); + generate_type_check(r9_klass, /*sub_klass*/ + ckoff, /*super_check_offset*/ + ckval, /*super_klass*/ + x10, /*result*/ + gct1, /*tmp1*/ + gct2, /*tmp2*/ + L_store_element); + + // Fall through on failure! + // ======== end loop ======== // It was a real error; we must depend on the caller to finish the job. @@ -1600,7 +1614,7 @@ class StubGenerator: public StubCodeGenerator { // their number to the caller. __ sub(count, count_save, count); // K = partially copied oop count - __ xori(count, count, -1); // report (-1^K) to caller + __ xori(count, count, -1); // report (-1^K) to caller __ beqz(count, L_done_pop); __ BIND(L_do_card_marks); @@ -1965,7 +1979,7 @@ class StubGenerator: public StubCodeGenerator { __ lwu(sco_temp, Address(dst_klass, sco_offset)); // Smashes t0, t1 - generate_type_check(scratch_src_klass, sco_temp, dst_klass, L_plain_copy); + generate_type_check(scratch_src_klass, sco_temp, dst_klass, noreg, noreg, noreg, L_plain_copy); // Fetch destination element klass from the ObjArrayKlass header. int ek_offset = in_bytes(ObjArrayKlass::element_klass_offset()); @@ -2831,9 +2845,9 @@ class StubGenerator: public StubCodeGenerator { Label L_success; __ enter(); - __ lookup_secondary_supers_table(r_sub_klass, r_super_klass, result, - r_array_base, r_array_length, r_array_index, - r_bitmap, super_klass_index, /*stub_is_near*/true); + __ lookup_secondary_supers_table_const(r_sub_klass, r_super_klass, result, + r_array_base, r_array_length, r_array_index, + r_bitmap, super_klass_index, true); __ leave(); __ ret();