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 "dex_file-inl.h" 18 #include "entrypoints/entrypoint_utils.h" 19 #include "mirror/art_method-inl.h" 20 #include "mirror/class-inl.h" 21 #include "mirror/object.h" 22 #include "mirror/object-inl.h" 23 #include "mirror/object_array-inl.h" 24 #include "object_utils.h" 25 #include "scoped_thread_state_change.h" 26 #include "thread.h" 27 28 namespace art { 29 30 // Called on entry to JNI, transition out of Runnable and release share of mutator_lock_. 31 extern uint32_t JniMethodStart(Thread* self) { 32 JNIEnvExt* env = self->GetJniEnv(); 33 DCHECK(env != NULL); 34 uint32_t saved_local_ref_cookie = env->local_ref_cookie; 35 env->local_ref_cookie = env->locals.GetSegmentState(); 36 self->TransitionFromRunnableToSuspended(kNative); 37 return saved_local_ref_cookie; 38 } 39 40 extern uint32_t JniMethodStartSynchronized(jobject to_lock, Thread* self) { 41 self->DecodeJObject(to_lock)->MonitorEnter(self); 42 return JniMethodStart(self); 43 } 44 45 static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) { 46 JNIEnvExt* env = self->GetJniEnv(); 47 env->locals.SetSegmentState(env->local_ref_cookie); 48 env->local_ref_cookie = saved_local_ref_cookie; 49 self->PopSirt(); 50 } 51 52 extern void JniMethodEnd(uint32_t saved_local_ref_cookie, Thread* self) { 53 self->TransitionFromSuspendedToRunnable(); 54 PopLocalReferences(saved_local_ref_cookie, self); 55 } 56 57 58 extern void JniMethodEndSynchronized(uint32_t saved_local_ref_cookie, jobject locked, 59 Thread* self) { 60 self->TransitionFromSuspendedToRunnable(); 61 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop. 62 PopLocalReferences(saved_local_ref_cookie, self); 63 } 64 65 extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie, 66 Thread* self) { 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 mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result, 81 uint32_t saved_local_ref_cookie, 82 jobject locked, Thread* self) { 83 self->TransitionFromSuspendedToRunnable(); 84 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop. 85 mirror::Object* o = self->DecodeJObject(result); 86 PopLocalReferences(saved_local_ref_cookie, self); 87 // Process result. 88 if (UNLIKELY(self->GetJniEnv()->check_jni)) { 89 if (self->IsExceptionPending()) { 90 return NULL; 91 } 92 CheckReferenceResult(o, self); 93 } 94 return o; 95 } 96 97 } // namespace art 98