diff options
author | Ian Rogers <irogers@google.com> | 2013-10-18 15:42:20 -0700 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2013-10-20 14:55:26 -0700 |
commit | 1eb512d33f94d1dd7ea38263307ba0f7a0dfa653 (patch) | |
tree | b4d4d9b16013ab90fb4b40d23013d7ef44bb5852 /runtime/entrypoints/quick | |
parent | b917ea1a62aa0ab8eca3f689ef64b5be34e11abb (diff) | |
download | art-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.h | 13 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_jni_entrypoints.cc | 30 |
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); |