Home | History | Annotate | Download | only in quick
      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