diff options
Diffstat (limited to 'runtime/entrypoints')
4 files changed, 40 insertions, 19 deletions
diff --git a/runtime/entrypoints/quick/quick_default_init_entrypoints.h b/runtime/entrypoints/quick/quick_default_init_entrypoints.h index 1ee1f818b6..df23f94a31 100644 --- a/runtime/entrypoints/quick/quick_default_init_entrypoints.h +++ b/runtime/entrypoints/quick/quick_default_init_entrypoints.h @@ -78,6 +78,7 @@ void DefaultInitEntryPoints(JniEntryPoints* jpoints, QuickEntryPoints* qpoints) qpoints->pJniMethodEnd = JniMethodEnd; qpoints->pJniMethodEndSynchronized = JniMethodEndSynchronized; qpoints->pJniMethodEndWithReference = JniMethodEndWithReference; + qpoints->pJniMethodFastEndWithReference = JniMethodFastEndWithReference; qpoints->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized; qpoints->pJniMethodFastEnd = JniMethodFastEnd; qpoints->pQuickGenericJniTrampoline = art_quick_generic_jni_trampoline; diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h index 89712a3cc7..915f18ed71 100644 --- a/runtime/entrypoints/quick/quick_entrypoints.h +++ b/runtime/entrypoints/quick/quick_entrypoints.h @@ -65,6 +65,11 @@ extern void JniMethodEndSynchronized(uint32_t saved_local_ref_cookie, jobject lo extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie, Thread* self) NO_THREAD_SAFETY_ANALYSIS HOT_ATTR; +extern mirror::Object* JniMethodFastEndWithReference(jobject result, + uint32_t saved_local_ref_cookie, + Thread* self) + NO_THREAD_SAFETY_ANALYSIS HOT_ATTR; + extern mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result, uint32_t saved_local_ref_cookie, diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h index e4029191d6..3cfee45462 100644 --- a/runtime/entrypoints/quick/quick_entrypoints_list.h +++ b/runtime/entrypoints/quick/quick_entrypoints_list.h @@ -78,6 +78,7 @@ V(JniMethodFastEnd, void, uint32_t, Thread*) \ V(JniMethodEndSynchronized, void, uint32_t, jobject, Thread*) \ V(JniMethodEndWithReference, mirror::Object*, jobject, uint32_t, Thread*) \ + V(JniMethodFastEndWithReference, mirror::Object*, jobject, uint32_t, Thread*) \ V(JniMethodEndWithReferenceSynchronized, mirror::Object*, jobject, uint32_t, jobject, Thread*) \ V(QuickGenericJniTrampoline, void, ArtMethod*) \ \ diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc index b25f447e4b..330c742354 100644 --- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc @@ -22,6 +22,9 @@ namespace art { +template <bool kDynamicFast> +static inline void GoToRunnableFast(Thread* self) NO_THREAD_SAFETY_ANALYSIS; + extern void ReadBarrierJni(mirror::CompressedReference<mirror::Object>* handle_on_stack, Thread* self ATTRIBUTE_UNUSED) { DCHECK(kUseReadBarrier); @@ -78,7 +81,28 @@ static void GoToRunnable(Thread* self) NO_THREAD_SAFETY_ANALYSIS { bool is_fast = native_method->IsFastNative(); if (!is_fast) { self->TransitionFromSuspendedToRunnable(); - } else if (UNLIKELY(self->TestAllFlags())) { + } else { + GoToRunnableFast</*kDynamicFast*/true>(self); + } +} + +// TODO: NO_THREAD_SAFETY_ANALYSIS due to different control paths depending on fast JNI. +template <bool kDynamicFast> +ALWAYS_INLINE static inline void GoToRunnableFast(Thread* self) NO_THREAD_SAFETY_ANALYSIS { + if (kIsDebugBuild) { + // Should only enter here if the method is !Fast JNI or @FastNative. + ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame(); + + if (kDynamicFast) { + CHECK(native_method->IsFastNative()) << native_method->PrettyMethod(); + } else { + CHECK(native_method->IsAnnotatedWithFastNative()) << native_method->PrettyMethod(); + } + } + + // When we are in "fast" JNI or @FastNative, we are already Runnable. + // Only do a suspend check on the way out of JNI. + 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)); @@ -106,20 +130,7 @@ extern void JniMethodEnd(uint32_t saved_local_ref_cookie, Thread* self) { } extern void JniMethodFastEnd(uint32_t saved_local_ref_cookie, Thread* self) { - // inlined fast version of GoToRunnable(self); - - if (kIsDebugBuild) { - ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame(); - CHECK(native_method->IsAnnotatedWithFastNative()) << native_method->PrettyMethod(); - } - - 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)); - self->CheckSuspend(); - } - + GoToRunnableFast</*kDynamicFast*/false>(self); PopLocalReferences(saved_local_ref_cookie, self); } @@ -131,10 +142,6 @@ extern void JniMethodEndSynchronized(uint32_t saved_local_ref_cookie, PopLocalReferences(saved_local_ref_cookie, self); } -// TODO: JniMethodFastEndWithReference -// (Probably don't need to have a synchronized variant since -// it already has to do atomic operations) - // Common result handling for EndWithReference. static mirror::Object* JniMethodEndWithReferenceHandleResult(jobject result, uint32_t saved_local_ref_cookie, @@ -157,6 +164,13 @@ static mirror::Object* JniMethodEndWithReferenceHandleResult(jobject result, return o.Ptr(); } +extern mirror::Object* JniMethodFastEndWithReference(jobject result, + uint32_t saved_local_ref_cookie, + Thread* self) { + GoToRunnableFast</*kDynamicFast*/false>(self); + return JniMethodEndWithReferenceHandleResult(result, saved_local_ref_cookie, self); +} + extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie, Thread* self) { |