Skip to content

Commit b40f8ee

Browse files
author
Andrew Haley
committed
8337251: C1: Improve Class.isInstance intrinsic
Reviewed-by: vlivanov
1 parent 88a8483 commit b40f8ee

13 files changed

+141
-9
lines changed

src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,11 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) {
13161316
x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci());
13171317
}
13181318

1319+
// Intrinsic for Class::isInstance
1320+
address LIRGenerator::isInstance_entry() {
1321+
return Runtime1::entry_for(C1StubId::is_instance_of_id);
1322+
}
1323+
13191324
void LIRGenerator::do_If(If* x) {
13201325
assert(x->number_of_sux() == 2, "inconsistency");
13211326
ValueTag tag = x->x()->type()->tag();

src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,55 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) {
900900
}
901901
break;
902902

903+
case C1StubId::is_instance_of_id:
904+
{
905+
// Mirror: c_rarg0
906+
// Object: c_rarg1
907+
// Temps: r3, r4, r5, r6
908+
// Result: r0
909+
910+
// Get the Klass* into c_rarg6
911+
Register klass = c_rarg6, obj = c_rarg1, result = r0;
912+
__ ldr(klass, Address(c_rarg0, java_lang_Class::klass_offset()));
913+
914+
Label fail, is_secondary, success;
915+
916+
__ cbz(klass, fail); // Klass is null
917+
__ cbz(obj, fail); // obj is null
918+
919+
__ ldrw(r3, Address(klass, in_bytes(Klass::super_check_offset_offset())));
920+
__ cmpw(r3, in_bytes(Klass::secondary_super_cache_offset()));
921+
__ br(Assembler::EQ, is_secondary); // Klass is a secondary superclass
922+
923+
// Klass is a concrete class
924+
__ load_klass(r5, obj);
925+
__ ldr(rscratch1, Address(r5, r3));
926+
__ cmp(klass, rscratch1);
927+
__ cset(result, Assembler::EQ);
928+
__ ret(lr);
929+
930+
__ bind(is_secondary);
931+
932+
__ load_klass(obj, obj);
933+
934+
// This is necessary because I am never in my own secondary_super list.
935+
__ cmp(obj, klass);
936+
__ br(Assembler::EQ, success);
937+
938+
__ lookup_secondary_supers_table_var(obj, klass,
939+
/*temps*/r3, r4, r5, v0,
940+
result,
941+
&success);
942+
__ bind(fail);
943+
__ mov(result, 0);
944+
__ ret(lr);
945+
946+
__ bind(success);
947+
__ mov(result, 1);
948+
__ ret(lr);
949+
}
950+
break;
951+
903952
case C1StubId::monitorexit_nofpu_id:
904953
save_fpu_registers = false;
905954
// fall through

src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,11 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) {
11251125
x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci());
11261126
}
11271127

1128+
// Intrinsic for Class::isInstance
1129+
address LIRGenerator::isInstance_entry() {
1130+
return CAST_FROM_FN_PTR(address, Runtime1::is_instance_of);
1131+
}
1132+
11281133

11291134
#ifdef __SOFTFP__
11301135
// Turn operator if (f <op> g) into runtime call:

src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,11 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) {
11281128
x->profiled_method(), x->profiled_bci());
11291129
}
11301130

1131+
// Intrinsic for Class::isInstance
1132+
address LIRGenerator::isInstance_entry() {
1133+
return CAST_FROM_FN_PTR(address, Runtime1::is_instance_of);
1134+
}
1135+
11311136

11321137
void LIRGenerator::do_If(If* x) {
11331138
assert(x->number_of_sux() == 2, "inconsistency");

src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,11 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) {
11021102
x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci());
11031103
}
11041104

1105+
// Intrinsic for Class::isInstance
1106+
address LIRGenerator::isInstance_entry() {
1107+
return CAST_FROM_FN_PTR(address, Runtime1::is_instance_of);
1108+
}
1109+
11051110
void LIRGenerator::do_If(If* x) {
11061111
// If should have two successors
11071112
assert(x->number_of_sux() == 2, "inconsistency");

src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,11 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) {
959959
x->profiled_method(), x->profiled_bci());
960960
}
961961

962+
// Intrinsic for Class::isInstance
963+
address LIRGenerator::isInstance_entry() {
964+
return CAST_FROM_FN_PTR(address, Runtime1::is_instance_of);
965+
}
966+
962967

963968
void LIRGenerator::do_If (If* x) {
964969
assert(x->number_of_sux() == 2, "inconsistency");

src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,6 +1490,11 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) {
14901490
x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci());
14911491
}
14921492

1493+
// Intrinsic for Class::isInstance
1494+
address LIRGenerator::isInstance_entry() {
1495+
return Runtime1::entry_for(C1StubId::is_instance_of_id);
1496+
}
1497+
14931498

14941499
void LIRGenerator::do_If(If* x) {
14951500
assert(x->number_of_sux() == 2, "inconsistency");

src/hotspot/cpu/x86/c1_Runtime1_x86.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,60 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) {
13171317
}
13181318
break;
13191319

1320+
case C1StubId::is_instance_of_id:
1321+
{
1322+
// Mirror: c_rarg0 (Windows: rcx, SysV: rdi)
1323+
// Object: c_rarg1 (Windows: rdx, SysV: rsi)
1324+
// ObjClass: r9
1325+
// Temps: rcx, r8, r10, r11
1326+
// Result: rax
1327+
1328+
Register klass = r9, obj = c_rarg1, result = rax;
1329+
Register temp0 = rcx, temp1 = r8, temp2 = r10, temp3 = r11;
1330+
1331+
// Get the Klass* into r9. c_rarg0 is now dead.
1332+
__ movptr(klass, Address(c_rarg0, java_lang_Class::klass_offset()));
1333+
1334+
Label done, is_secondary, same;
1335+
1336+
__ xorq(result, result);
1337+
__ testq(klass, klass);
1338+
__ jcc(Assembler::equal, done); // Klass is null
1339+
1340+
__ testq(obj, obj);
1341+
__ jcc(Assembler::equal, done); // obj is null
1342+
1343+
__ movl(temp0, Address(klass, in_bytes(Klass::super_check_offset_offset())));
1344+
__ cmpl(temp0, in_bytes(Klass::secondary_super_cache_offset()));
1345+
__ jcc(Assembler::equal, is_secondary); // Klass is a secondary superclass
1346+
1347+
// Klass is a concrete class
1348+
__ load_klass(temp2, obj, /*tmp*/temp1);
1349+
__ cmpptr(klass, Address(temp2, temp0));
1350+
__ setcc(Assembler::equal, result);
1351+
__ ret(0);
1352+
1353+
__ bind(is_secondary);
1354+
1355+
__ load_klass(obj, obj, /*tmp*/temp1);
1356+
1357+
// This is necessary because I am never in my own secondary_super list.
1358+
__ cmpptr(obj, klass);
1359+
__ jcc(Assembler::equal, same);
1360+
1361+
__ lookup_secondary_supers_table_var(obj, klass,
1362+
/*temps*/temp0, temp1, temp2, temp3,
1363+
result);
1364+
__ testq(result, result);
1365+
1366+
__ bind(same);
1367+
__ setcc(Assembler::equal, result);
1368+
1369+
__ bind(done);
1370+
__ ret(0);
1371+
}
1372+
break;
1373+
13201374
case C1StubId::monitorenter_nofpu_id:
13211375
save_fpu_registers = false;
13221376
// fall through

src/hotspot/share/c1/c1_Canonicalizer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) {
523523
ciType* t = c->value()->java_mirror_type();
524524
if (t->is_klass()) {
525525
// substitute cls.isInstance(obj) of a constant Class into
526-
// an InstantOf instruction
526+
// an InstanceOf instruction
527527
InstanceOf* i = new InstanceOf(t->as_klass(), x->argument_at(1), x->state_before());
528528
set_canonical(i);
529529
// and try to canonicalize even further

src/hotspot/share/c1/c1_LIRGenerator.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,13 +1231,6 @@ void LIRGenerator::do_Reference_get(Intrinsic* x) {
12311231
void LIRGenerator::do_isInstance(Intrinsic* x) {
12321232
assert(x->number_of_arguments() == 2, "wrong type");
12331233

1234-
// TODO could try to substitute this node with an equivalent InstanceOf
1235-
// if clazz is known to be a constant Class. This will pick up newly found
1236-
// constants after HIR construction. I'll leave this to a future change.
1237-
1238-
// as a first cut, make a simple leaf call to runtime to stay platform independent.
1239-
// could follow the aastore example in a future change.
1240-
12411234
LIRItem clazz(x->argument_at(0), this);
12421235
LIRItem object(x->argument_at(1), this);
12431236
clazz.load_item();
@@ -1250,8 +1243,9 @@ void LIRGenerator::do_isInstance(Intrinsic* x) {
12501243
__ null_check(clazz.result(), info);
12511244
}
12521245

1246+
address pd_instanceof_fn = isInstance_entry();
12531247
LIR_Opr call_result = call_runtime(clazz.value(), object.value(),
1254-
CAST_FROM_FN_PTR(address, Runtime1::is_instance_of),
1248+
pd_instanceof_fn,
12551249
x->type(),
12561250
nullptr); // null CodeEmitInfo results in a leaf call
12571251
__ move(call_result, result);

0 commit comments

Comments
 (0)