mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-15 16:09:44 +00:00
8349727: [PPC] C1: Improve Class.isInstance intrinsic
Reviewed-by: rrich, varadam
This commit is contained in:
parent
1e87ff0199
commit
735805d925
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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:
|
||||
{
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user