Created
May 29, 2012 19:28
-
-
Save rednaxelafx/2830194 to your computer and use it in GitHub Desktop.
First cut: C1 Class.isInstance intrinsic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -r 4d8787136e08 src/share/vm/c1/c1_Canonicalizer.cpp | |
--- a/src/share/vm/c1/c1_Canonicalizer.cpp Fri May 25 11:39:13 2012 -0700 | |
+++ b/src/share/vm/c1/c1_Canonicalizer.cpp Wed May 30 03:21:56 2012 +0800 | |
@@ -451,6 +451,28 @@ | |
} | |
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; | |
+ } | |
} | |
} | |
diff -r 4d8787136e08 src/share/vm/c1/c1_GraphBuilder.cpp | |
--- a/src/share/vm/c1/c1_GraphBuilder.cpp Fri May 25 11:39:13 2012 -0700 | |
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp Wed May 30 03:21:56 2012 +0800 | |
@@ -3170,6 +3170,7 @@ | |
break; | |
case vmIntrinsics::_getClass : | |
+ case vmIntrinsics::_isInstance : | |
if (!InlineClassNatives) return false; | |
preserves_state = true; | |
break; | |
diff -r 4d8787136e08 src/share/vm/c1/c1_LIRGenerator.cpp | |
--- a/src/share/vm/c1/c1_LIRGenerator.cpp Fri May 25 11:39:13 2012 -0700 | |
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp Wed May 30 03:21:56 2012 +0800 | |
@@ -1242,6 +1242,36 @@ | |
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 @@ | |
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; | |
diff -r 4d8787136e08 src/share/vm/c1/c1_LIRGenerator.hpp | |
--- a/src/share/vm/c1/c1_LIRGenerator.hpp Fri May 25 11:39:13 2012 -0700 | |
+++ b/src/share/vm/c1/c1_LIRGenerator.hpp Wed May 30 03:21:56 2012 +0800 | |
@@ -238,6 +238,7 @@ | |
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); | |
diff -r 4d8787136e08 src/share/vm/c1/c1_Runtime1.cpp | |
--- a/src/share/vm/c1/c1_Runtime1.cpp Fri May 25 11:39:13 2012 -0700 | |
+++ b/src/share/vm/c1/c1_Runtime1.cpp Wed May 30 03:21:56 2012 +0800 | |
@@ -294,6 +294,7 @@ | |
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_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:"); | |
diff -r 4d8787136e08 src/share/vm/c1/c1_Runtime1.hpp | |
--- a/src/share/vm/c1/c1_Runtime1.hpp Fri May 25 11:39:13 2012 -0700 | |
+++ b/src/share/vm/c1/c1_Runtime1.hpp Wed May 30 03:21:56 2012 +0800 | |
@@ -186,6 +186,7 @@ | |
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; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment