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 28namespace art { 29 30// Called on entry to JNI, transition out of Runnable and release share of mutator_lock_. 31extern 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 40extern uint32_t JniMethodStartSynchronized(jobject to_lock, Thread* self) { 41 self->DecodeJObject(to_lock)->MonitorEnter(self); 42 return JniMethodStart(self); 43} 44 45static 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 52extern void JniMethodEnd(uint32_t saved_local_ref_cookie, Thread* self) { 53 self->TransitionFromSuspendedToRunnable(); 54 PopLocalReferences(saved_local_ref_cookie, self); 55} 56 57 58extern 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 65extern 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 80extern 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