1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "entrypoints/entrypoint_utils-inl.h" 18 #include "mirror/art_method-inl.h" 19 #include "mirror/object-inl.h" 20 #include "thread-inl.h" 21 22 namespace art { 23 24 // Called on entry to JNI, transition out of Runnable and release share of mutator_lock_. 25 extern "C" uint32_t art_portable_jni_method_start(Thread* self) 26 UNLOCK_FUNCTION(Locks::mutator_lock_) { 27 JNIEnvExt* env = self->GetJniEnv(); 28 uint32_t saved_local_ref_cookie = env->local_ref_cookie; 29 env->local_ref_cookie = env->locals.GetSegmentState(); 30 self->TransitionFromRunnableToSuspended(kNative); 31 return saved_local_ref_cookie; 32 } 33 34 extern "C" uint32_t art_portable_jni_method_start_synchronized(jobject to_lock, Thread* self) 35 UNLOCK_FUNCTION(Locks::mutator_lock_) NO_THREAD_SAFETY_ANALYSIS { 36 self->DecodeJObject(to_lock)->MonitorEnter(self); 37 return art_portable_jni_method_start(self); 38 } 39 40 static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) 41 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 42 JNIEnvExt* env = self->GetJniEnv(); 43 env->locals.SetSegmentState(env->local_ref_cookie); 44 env->local_ref_cookie = saved_local_ref_cookie; 45 } 46 47 extern "C" void art_portable_jni_method_end(uint32_t saved_local_ref_cookie, Thread* self) 48 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) { 49 self->TransitionFromSuspendedToRunnable(); 50 PopLocalReferences(saved_local_ref_cookie, self); 51 } 52 53 54 extern "C" void art_portable_jni_method_end_synchronized(uint32_t saved_local_ref_cookie, 55 jobject locked, 56 Thread* self) 57 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) { 58 self->TransitionFromSuspendedToRunnable(); 59 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop. 60 PopLocalReferences(saved_local_ref_cookie, self); 61 } 62 63 extern "C" mirror::Object* art_portable_jni_method_end_with_reference(jobject result, 64 uint32_t saved_local_ref_cookie, 65 Thread* self) 66 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) { 67 self->TransitionFromSuspendedToRunnable(); 68 mirror::Object* o = self->DecodeJObject(result); // Must decode before pop. 69 PopLocalReferences(saved_local_ref_cookie, self); 70 // Process result. 71 if (UNLIKELY(self->GetJniEnv()->check_jni)) { 72 if (self->IsExceptionPending()) { 73 return NULL; 74 } 75 CheckReferenceResult(o, self); 76 } 77 return o; 78 } 79 80 extern "C" mirror::Object* art_portable_jni_method_end_with_reference_synchronized(jobject result, 81 uint32_t saved_local_ref_cookie, 82 jobject locked, 83 Thread* self) 84 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) { 85 self->TransitionFromSuspendedToRunnable(); 86 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop. 87 mirror::Object* o = self->DecodeJObject(result); 88 PopLocalReferences(saved_local_ref_cookie, self); 89 // Process result. 90 if (UNLIKELY(self->GetJniEnv()->check_jni)) { 91 if (self->IsExceptionPending()) { 92 return NULL; 93 } 94 CheckReferenceResult(o, self); 95 } 96 return o; 97 } 98 99 } // namespace art 100