summaryrefslogtreecommitdiffstats
path: root/runtime/entrypoints/quick
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2013-10-18 15:42:20 -0700
committerIan Rogers <irogers@google.com>2013-10-20 14:55:26 -0700
commit1eb512d33f94d1dd7ea38263307ba0f7a0dfa653 (patch)
treeb4d4d9b16013ab90fb4b40d23013d7ef44bb5852 /runtime/entrypoints/quick
parentb917ea1a62aa0ab8eca3f689ef64b5be34e11abb (diff)
downloadart-1eb512d33f94d1dd7ea38263307ba0f7a0dfa653.zip
art-1eb512d33f94d1dd7ea38263307ba0f7a0dfa653.tar.gz
art-1eb512d33f94d1dd7ea38263307ba0f7a0dfa653.tar.bz2
Fast JNI support.
Use a modifier to signal a native method is a fast JNI method. If the modifier is set then don't perform runnable transitions. Change-Id: I7835b4d837bfdd1cb8e2d54b919c0d5e6cf90499
Diffstat (limited to 'runtime/entrypoints/quick')
-rw-r--r--runtime/entrypoints/quick/quick_entrypoints.h13
-rw-r--r--runtime/entrypoints/quick/quick_jni_entrypoints.cc30
2 files changed, 31 insertions, 12 deletions
diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h
index e9964ad..c8a85a0 100644
--- a/runtime/entrypoints/quick/quick_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_entrypoints.h
@@ -142,22 +142,23 @@ struct PACKED(4) QuickEntryPoints {
// JNI entrypoints.
-extern uint32_t JniMethodStart(Thread* self) UNLOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR;
+// TODO: NO_THREAD_SAFETY_ANALYSIS due to different control paths depending on fast JNI.
+extern uint32_t JniMethodStart(Thread* self) NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
extern uint32_t JniMethodStartSynchronized(jobject to_lock, Thread* self)
- UNLOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR;
+ NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
extern void JniMethodEnd(uint32_t saved_local_ref_cookie, Thread* self)
- SHARED_LOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR;
+ NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
extern void JniMethodEndSynchronized(uint32_t saved_local_ref_cookie, jobject locked,
Thread* self)
- SHARED_LOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR;
+ NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie,
Thread* self)
- SHARED_LOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR;
+ NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
extern mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result,
uint32_t saved_local_ref_cookie,
jobject locked, Thread* self)
- SHARED_LOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR;
+ NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
} // namespace art
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index 27ae59b..59da7a0 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -30,10 +30,14 @@ namespace art {
// Called on entry to JNI, transition out of Runnable and release share of mutator_lock_.
extern uint32_t JniMethodStart(Thread* self) {
JNIEnvExt* env = self->GetJniEnv();
- DCHECK(env != NULL);
+ DCHECK(env != nullptr);
uint32_t saved_local_ref_cookie = env->local_ref_cookie;
env->local_ref_cookie = env->locals.GetSegmentState();
- self->TransitionFromRunnableToSuspended(kNative);
+ mirror::ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
+ if (!native_method->IsFastNative()) {
+ // When not fast JNI we transition out of runnable.
+ self->TransitionFromRunnableToSuspended(kNative);
+ }
return saved_local_ref_cookie;
}
@@ -42,6 +46,20 @@ extern uint32_t JniMethodStartSynchronized(jobject to_lock, Thread* self) {
return JniMethodStart(self);
}
+// TODO: NO_THREAD_SAFETY_ANALYSIS due to different control paths depending on fast JNI.
+static void GoToRunnable(Thread* self) NO_THREAD_SAFETY_ANALYSIS {
+ mirror::ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
+ bool is_fast = native_method->IsFastNative();
+ if (!is_fast) {
+ self->TransitionFromSuspendedToRunnable();
+ } else if (UNLIKELY(self->TestAllFlags())) {
+ // In fast JNI mode we never transitioned out of runnable. Perform a suspend check if there
+ // is a flag raised.
+ DCHECK(Locks::mutator_lock_->IsSharedHeld(self));
+ CheckSuspend(self);
+ }
+}
+
static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) {
JNIEnvExt* env = self->GetJniEnv();
env->locals.SetSegmentState(env->local_ref_cookie);
@@ -50,21 +68,21 @@ static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) {
}
extern void JniMethodEnd(uint32_t saved_local_ref_cookie, Thread* self) {
- self->TransitionFromSuspendedToRunnable();
+ GoToRunnable(self);
PopLocalReferences(saved_local_ref_cookie, self);
}
extern void JniMethodEndSynchronized(uint32_t saved_local_ref_cookie, jobject locked,
Thread* self) {
- self->TransitionFromSuspendedToRunnable();
+ GoToRunnable(self);
UnlockJniSynchronizedMethod(locked, self); // Must decode before pop.
PopLocalReferences(saved_local_ref_cookie, self);
}
extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie,
Thread* self) {
- self->TransitionFromSuspendedToRunnable();
+ GoToRunnable(self);
mirror::Object* o = self->DecodeJObject(result); // Must decode before pop.
PopLocalReferences(saved_local_ref_cookie, self);
// Process result.
@@ -80,7 +98,7 @@ extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_
extern mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result,
uint32_t saved_local_ref_cookie,
jobject locked, Thread* self) {
- self->TransitionFromSuspendedToRunnable();
+ GoToRunnable(self);
UnlockJniSynchronizedMethod(locked, self); // Must decode before pop.
mirror::Object* o = self->DecodeJObject(result);
PopLocalReferences(saved_local_ref_cookie, self);