diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp index 67a4a65b871..cae192982d5 100644 --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp @@ -2839,25 +2839,28 @@ void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest, LIR_Opr tmp) { void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* args, LIR_Opr tmp, CodeEmitInfo* info) { - // Stubs: Called via rt_call, but dest is a stub address (no function descriptor). + // Stubs: Called via rt_call, but dest is a stub address (no FunctionDescriptor). if (dest == Runtime1::entry_for(C1StubId::register_finalizer_id) || - dest == Runtime1::entry_for(C1StubId::new_multi_array_id )) { + dest == Runtime1::entry_for(C1StubId::new_multi_array_id ) || + dest == Runtime1::entry_for(C1StubId::is_instance_of_id )) { + assert(CodeCache::contains(dest), "simplified call is only for special C1 stubs"); //__ load_const_optimized(R0, dest); __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(dest)); __ mtctr(R0); __ bctrl(); - assert(info != nullptr, "sanity"); - add_call_info_here(info); - __ post_call_nop(); + if (info != nullptr) { + add_call_info_here(info); + __ post_call_nop(); + } return; } __ call_c(dest, relocInfo::runtime_call_type); + assert(__ last_calls_return_pc() == __ pc(), "pcn not at return pc"); if (info != nullptr) { add_call_info_here(info); + __ post_call_nop(); } - assert(__ last_calls_return_pc() == __ pc(), "pcn not at return pc"); - __ post_call_nop(); } diff --git a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp index d9ccf63bed3..b9c8ced8ef1 100644 --- a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp @@ -1128,9 +1128,10 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) { x->profiled_method(), x->profiled_bci()); } + // 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/ppc/c1_Runtime1_ppc.cpp b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp index b1ee11317d2..11c01dcdc60 100644 --- a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp @@ -609,6 +609,73 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { } break; + case C1StubId::is_instance_of_id: + { + // Called like a C function, but without FunctionDescriptor (see LIR_Assembler::rt_call). + + // Arguments and return value. + Register mirror = R3_ARG1; + Register obj = R4_ARG2; + Register result = R3_RET; + + // Other argument registers can be used as temp registers. + Register klass = R5; + Register offset = R6; + Register sub_klass = R7; + + Label is_secondary, success; + + // Get the Klass*. + __ ld(klass, java_lang_Class::klass_offset(), mirror); + + // Return false if obj or klass is null. + mirror = noreg; // killed by next instruction + __ li(result, 0); // assume result is false + __ cmpdi(CR0, obj, 0); + __ cmpdi(CR1, klass, 0); + __ cror(CR0, Assembler::equal, CR1, Assembler::equal); + __ bclr(Assembler::bcondCRbiIs1, Assembler::bi0(CR0, Assembler::equal), Assembler::bhintbhBCLRisReturn); + + __ lwz(offset, in_bytes(Klass::super_check_offset_offset()), klass); + __ load_klass(sub_klass, obj); + __ cmpwi(CR0, offset, in_bytes(Klass::secondary_super_cache_offset())); + __ beq(CR0, is_secondary); // Klass is a secondary superclass + + // Klass is a concrete class + __ ldx(R0, sub_klass, offset); + __ cmpd(CR0, klass, R0); + if (VM_Version::has_brw()) { + // Power10 can set the result by one instruction. No need for a branch. + __ setbc(result, CR0, Assembler::equal); + } else { + __ beq(CR0, success); + } + __ blr(); + + __ bind(is_secondary); + + // This is necessary because I am never in my own secondary_super list. + __ cmpd(CR0, sub_klass, klass); + __ beq(CR0, success); + + __ lookup_secondary_supers_table_var(sub_klass, klass, + /*temps*/R9, R10, R11, R12, + /*result*/R8); + __ cmpdi(CR0, R8, 0); // 0 means is subclass + if (VM_Version::has_brw()) { + // Power10 can set the result by one instruction. No need for a branch. + __ setbc(result, CR0, Assembler::equal); + } else { + __ beq(CR0, success); + } + __ blr(); + + __ bind(success); + __ li(result, 1); + __ blr(); + } + break; + case C1StubId::monitorenter_nofpu_id: case C1StubId::monitorenter_id: { diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 1267fa0e516..6bdb4f80266 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -2265,27 +2265,28 @@ void MacroAssembler::check_klass_subtype(Register sub_klass, // generic (count must be >0) // iff found: CR0 eq, scratch == 0 void MacroAssembler::repne_scan(Register addr, Register value, Register count, Register scratch) { - Label Lloop, Lexit; + Label Lloop, Lafter_loop, Lexit; -#ifdef ASSERT - { - Label ok; - cmpdi(CR0, count, 0); - bgt(CR0, ok); - stop("count must be positive"); - bind(ok); - } -#endif + srdi_(scratch, count, 1); + beq(CR0, Lafter_loop); + mtctr(scratch); - mtctr(count); - - bind(Lloop); - ld(scratch, 0 , addr); + bind(Lloop); // 2x unrolled + ld(scratch, 0, addr); xor_(scratch, scratch, value); beq(CR0, Lexit); - addi(addr, addr, wordSize); + ld(scratch, 8, addr); + xor_(scratch, scratch, value); + beq(CR0, Lexit); + addi(addr, addr, 2 * wordSize); bdnz(Lloop); + bind(Lafter_loop); + andi_(scratch, count, 1); + beq(CR0, Lexit); // if taken: CR0 eq and scratch == 0 + ld(scratch, 0, addr); + xor_(scratch, scratch, value); + bind(Lexit); }