mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-09 06:28:49 +00:00
7171890: C1: add Class.isInstance intrinsic
Class.cast which calls Class.isInstance is heavily used by the new JSR 292 implementation Reviewed-by: roland
This commit is contained in:
parent
33799389d4
commit
6d29429c4e
@ -456,6 +456,28 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case vmIntrinsics::_isInstance : {
|
||||
assert(x->number_of_arguments() == 2, "wrong type");
|
||||
|
||||
InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant();
|
||||
if (c != NULL && !c->value()->is_null_object()) {
|
||||
// ciInstance::java_mirror_type() returns non-NULL only for Java mirrors
|
||||
ciType* t = c->value()->as_instance()->java_mirror_type();
|
||||
if (t->is_klass()) {
|
||||
// substitute cls.isInstance(obj) of a constant Class into
|
||||
// an InstantOf instruction
|
||||
InstanceOf* i = new InstanceOf(t->as_klass(), x->argument_at(1), x->state());
|
||||
set_canonical(i);
|
||||
// and try to canonicalize even further
|
||||
do_InstanceOf(i);
|
||||
} else {
|
||||
assert(t->is_primitive_type(), "should be a primitive type");
|
||||
// cls.isInstance(obj) always returns false for primitive classes
|
||||
set_constant(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3170,6 +3170,7 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
|
||||
break;
|
||||
|
||||
case vmIntrinsics::_getClass :
|
||||
case vmIntrinsics::_isInstance :
|
||||
if (!InlineClassNatives) return false;
|
||||
preserves_state = true;
|
||||
break;
|
||||
|
||||
@ -1242,6 +1242,36 @@ void LIRGenerator::do_Reference_get(Intrinsic* x) {
|
||||
NULL /* info */);
|
||||
}
|
||||
|
||||
// Example: clazz.isInstance(object)
|
||||
void LIRGenerator::do_isInstance(Intrinsic* x) {
|
||||
assert(x->number_of_arguments() == 2, "wrong type");
|
||||
|
||||
// TODO could try to substitute this node with an equivalent InstanceOf
|
||||
// if clazz is known to be a constant Class. This will pick up newly found
|
||||
// constants after HIR construction. I'll leave this to a future change.
|
||||
|
||||
// as a first cut, make a simple leaf call to runtime to stay platform independent.
|
||||
// could follow the aastore example in a future change.
|
||||
|
||||
LIRItem clazz(x->argument_at(0), this);
|
||||
LIRItem object(x->argument_at(1), this);
|
||||
clazz.load_item();
|
||||
object.load_item();
|
||||
LIR_Opr result = rlock_result(x);
|
||||
|
||||
// need to perform null check on clazz
|
||||
if (x->needs_null_check()) {
|
||||
CodeEmitInfo* info = state_for(x);
|
||||
__ null_check(clazz.result(), info);
|
||||
}
|
||||
|
||||
LIR_Opr call_result = call_runtime(clazz.value(), object.value(),
|
||||
CAST_FROM_FN_PTR(address, Runtime1::is_instance_of),
|
||||
x->type(),
|
||||
NULL); // NULL CodeEmitInfo results in a leaf call
|
||||
__ move(call_result, result);
|
||||
}
|
||||
|
||||
// Example: object.getClass ()
|
||||
void LIRGenerator::do_getClass(Intrinsic* x) {
|
||||
assert(x->number_of_arguments() == 1, "wrong type");
|
||||
@ -2951,6 +2981,7 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) {
|
||||
break;
|
||||
|
||||
case vmIntrinsics::_Object_init: do_RegisterFinalizer(x); break;
|
||||
case vmIntrinsics::_isInstance: do_isInstance(x); break;
|
||||
case vmIntrinsics::_getClass: do_getClass(x); break;
|
||||
case vmIntrinsics::_currentThread: do_currentThread(x); break;
|
||||
|
||||
|
||||
@ -238,6 +238,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
|
||||
LIR_Opr getThreadPointer();
|
||||
|
||||
void do_RegisterFinalizer(Intrinsic* x);
|
||||
void do_isInstance(Intrinsic* x);
|
||||
void do_getClass(Intrinsic* x);
|
||||
void do_currentThread(Intrinsic* x);
|
||||
void do_MathIntrinsic(Intrinsic* x);
|
||||
|
||||
@ -294,6 +294,7 @@ const char* Runtime1::name_for_address(address entry) {
|
||||
FUNCTION_CASE(entry, SharedRuntime::lrem);
|
||||
FUNCTION_CASE(entry, SharedRuntime::dtrace_method_entry);
|
||||
FUNCTION_CASE(entry, SharedRuntime::dtrace_method_exit);
|
||||
FUNCTION_CASE(entry, is_instance_of);
|
||||
FUNCTION_CASE(entry, trace_block_entry);
|
||||
#ifdef TRACE_HAVE_INTRINSICS
|
||||
FUNCTION_CASE(entry, TRACE_TIME_METHOD);
|
||||
@ -1270,6 +1271,19 @@ JRT_LEAF(void, Runtime1::oop_arraycopy(HeapWord* src, HeapWord* dst, int num))
|
||||
JRT_END
|
||||
|
||||
|
||||
JRT_LEAF(int, Runtime1::is_instance_of(oopDesc* mirror, oopDesc* obj))
|
||||
// had to return int instead of bool, otherwise there may be a mismatch
|
||||
// between the C calling convention and the Java one.
|
||||
// e.g., on x86, GCC may clear only %al when returning a bool false, but
|
||||
// JVM takes the whole %eax as the return value, which may misinterpret
|
||||
// the return value as a boolean true.
|
||||
|
||||
assert(mirror != NULL, "should null-check on mirror before calling");
|
||||
klassOop k = java_lang_Class::as_klassOop(mirror);
|
||||
return (k != NULL && obj != NULL && obj->is_a(k)) ? 1 : 0;
|
||||
JRT_END
|
||||
|
||||
|
||||
#ifndef PRODUCT
|
||||
void Runtime1::print_statistics() {
|
||||
tty->print_cr("C1 Runtime statistics:");
|
||||
|
||||
@ -186,6 +186,7 @@ class Runtime1: public AllStatic {
|
||||
static int arraycopy(oopDesc* src, int src_pos, oopDesc* dst, int dst_pos, int length);
|
||||
static void primitive_arraycopy(HeapWord* src, HeapWord* dst, int length);
|
||||
static void oop_arraycopy(HeapWord* src, HeapWord* dst, int length);
|
||||
static int is_instance_of(oopDesc* mirror, oopDesc* obj);
|
||||
|
||||
static void print_statistics() PRODUCT_RETURN;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user