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 <android-base/logging.h>
18 
19 #include "art_method-inl.h"
20 #include "base/casts.h"
21 #include "entrypoints/entrypoint_utils-inl.h"
22 #include "indirect_reference_table.h"
23 #include "mirror/object-inl.h"
24 #include "thread-inl.h"
25 #include "verify_object.h"
26 
27 namespace art {
28 
29 static_assert(sizeof(IRTSegmentState) == sizeof(uint32_t), "IRTSegmentState size unexpected");
30 static_assert(std::is_trivial<IRTSegmentState>::value, "IRTSegmentState not trivial");
31 
32 static inline void GoToRunnableFast(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
33 
ReadBarrierJni(mirror::CompressedReference<mirror::Object> * handle_on_stack,Thread * self ATTRIBUTE_UNUSED)34 extern void ReadBarrierJni(mirror::CompressedReference<mirror::Object>* handle_on_stack,
35                            Thread* self ATTRIBUTE_UNUSED) {
36   DCHECK(kUseReadBarrier);
37   if (kUseBakerReadBarrier) {
38     DCHECK(handle_on_stack->AsMirrorPtr() != nullptr)
39         << "The class of a static jni call must not be null";
40     // Check the mark bit and return early if it's already marked.
41     if (LIKELY(handle_on_stack->AsMirrorPtr()->GetMarkBit() != 0)) {
42       return;
43     }
44   }
45   // Call the read barrier and update the handle.
46   mirror::Object* to_ref = ReadBarrier::BarrierForRoot(handle_on_stack);
47   handle_on_stack->Assign(to_ref);
48 }
49 
50 // Called on entry to fast JNI, push a new local reference table only.
JniMethodFastStart(Thread * self)51 extern uint32_t JniMethodFastStart(Thread* self) {
52   JNIEnvExt* env = self->GetJniEnv();
53   DCHECK(env != nullptr);
54   uint32_t saved_local_ref_cookie = bit_cast<uint32_t>(env->GetLocalRefCookie());
55   env->SetLocalRefCookie(env->GetLocalsSegmentState());
56 
57   if (kIsDebugBuild) {
58     ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
59     CHECK(native_method->IsFastNative()) << native_method->PrettyMethod();
60   }
61 
62   return saved_local_ref_cookie;
63 }
64 
65 // Called on entry to JNI, transition out of Runnable and release share of mutator_lock_.
JniMethodStart(Thread * self)66 extern uint32_t JniMethodStart(Thread* self) {
67   JNIEnvExt* env = self->GetJniEnv();
68   DCHECK(env != nullptr);
69   uint32_t saved_local_ref_cookie = bit_cast<uint32_t>(env->GetLocalRefCookie());
70   env->SetLocalRefCookie(env->GetLocalsSegmentState());
71   ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
72   // TODO: Introduce special entrypoint for synchronized @FastNative methods?
73   //       Or ban synchronized @FastNative outright to avoid the extra check here?
74   DCHECK(!native_method->IsFastNative() || native_method->IsSynchronized());
75   if (!native_method->IsFastNative()) {
76     // When not fast JNI we transition out of runnable.
77     self->TransitionFromRunnableToSuspended(kNative);
78   }
79   return saved_local_ref_cookie;
80 }
81 
JniMethodStartSynchronized(jobject to_lock,Thread * self)82 extern uint32_t JniMethodStartSynchronized(jobject to_lock, Thread* self) {
83   self->DecodeJObject(to_lock)->MonitorEnter(self);
84   return JniMethodStart(self);
85 }
86 
87 // TODO: NO_THREAD_SAFETY_ANALYSIS due to different control paths depending on fast JNI.
GoToRunnable(Thread * self)88 static void GoToRunnable(Thread* self) NO_THREAD_SAFETY_ANALYSIS {
89   ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
90   bool is_fast = native_method->IsFastNative();
91   if (!is_fast) {
92     self->TransitionFromSuspendedToRunnable();
93   } else {
94     GoToRunnableFast(self);
95   }
96 }
97 
GoToRunnableFast(Thread * self)98 ALWAYS_INLINE static inline void GoToRunnableFast(Thread* self) {
99   if (kIsDebugBuild) {
100     // Should only enter here if the method is @FastNative.
101     ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
102     CHECK(native_method->IsFastNative()) << native_method->PrettyMethod();
103   }
104 
105   // When we are in @FastNative, we are already Runnable.
106   // Only do a suspend check on the way out of JNI.
107   if (UNLIKELY(self->TestAllFlags())) {
108     // In fast JNI mode we never transitioned out of runnable. Perform a suspend check if there
109     // is a flag raised.
110     DCHECK(Locks::mutator_lock_->IsSharedHeld(self));
111     self->CheckSuspend();
112   }
113 }
114 
PopLocalReferences(uint32_t saved_local_ref_cookie,Thread * self)115 static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self)
116     REQUIRES_SHARED(Locks::mutator_lock_) {
117   JNIEnvExt* env = self->GetJniEnv();
118   if (UNLIKELY(env->IsCheckJniEnabled())) {
119     env->CheckNoHeldMonitors();
120   }
121   env->SetLocalSegmentState(env->GetLocalRefCookie());
122   env->SetLocalRefCookie(bit_cast<IRTSegmentState>(saved_local_ref_cookie));
123   self->PopHandleScope();
124 }
125 
126 // TODO: annotalysis disabled as monitor semantics are maintained in Java code.
UnlockJniSynchronizedMethod(jobject locked,Thread * self)127 static inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self)
128     NO_THREAD_SAFETY_ANALYSIS REQUIRES(!Roles::uninterruptible_) {
129   // Save any pending exception over monitor exit call.
130   ObjPtr<mirror::Throwable> saved_exception = nullptr;
131   if (UNLIKELY(self->IsExceptionPending())) {
132     saved_exception = self->GetException();
133     self->ClearException();
134   }
135   // Decode locked object and unlock, before popping local references.
136   self->DecodeJObject(locked)->MonitorExit(self);
137   if (UNLIKELY(self->IsExceptionPending())) {
138     LOG(FATAL) << "Synchronized JNI code returning with an exception:\n"
139         << saved_exception->Dump()
140         << "\nEncountered second exception during implicit MonitorExit:\n"
141         << self->GetException()->Dump();
142   }
143   // Restore pending exception.
144   if (saved_exception != nullptr) {
145     self->SetException(saved_exception);
146   }
147 }
148 
149 // TODO: These should probably be templatized or macro-ized.
150 // Otherwise there's just too much repetitive boilerplate.
151 
JniMethodEnd(uint32_t saved_local_ref_cookie,Thread * self)152 extern void JniMethodEnd(uint32_t saved_local_ref_cookie, Thread* self) {
153   GoToRunnable(self);
154   PopLocalReferences(saved_local_ref_cookie, self);
155 }
156 
JniMethodFastEnd(uint32_t saved_local_ref_cookie,Thread * self)157 extern void JniMethodFastEnd(uint32_t saved_local_ref_cookie, Thread* self) {
158   GoToRunnableFast(self);
159   PopLocalReferences(saved_local_ref_cookie, self);
160 }
161 
JniMethodEndSynchronized(uint32_t saved_local_ref_cookie,jobject locked,Thread * self)162 extern void JniMethodEndSynchronized(uint32_t saved_local_ref_cookie,
163                                      jobject locked,
164                                      Thread* self) {
165   GoToRunnable(self);
166   UnlockJniSynchronizedMethod(locked, self);  // Must decode before pop.
167   PopLocalReferences(saved_local_ref_cookie, self);
168 }
169 
170 // Common result handling for EndWithReference.
JniMethodEndWithReferenceHandleResult(jobject result,uint32_t saved_local_ref_cookie,Thread * self)171 static mirror::Object* JniMethodEndWithReferenceHandleResult(jobject result,
172                                                              uint32_t saved_local_ref_cookie,
173                                                              Thread* self)
174     NO_THREAD_SAFETY_ANALYSIS {
175   // Must decode before pop. The 'result' may not be valid in case of an exception, though.
176   ObjPtr<mirror::Object> o;
177   if (!self->IsExceptionPending()) {
178     o = self->DecodeJObject(result);
179   }
180   PopLocalReferences(saved_local_ref_cookie, self);
181   // Process result.
182   if (UNLIKELY(self->GetJniEnv()->IsCheckJniEnabled())) {
183     // CheckReferenceResult can resolve types.
184     StackHandleScope<1> hs(self);
185     HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&o));
186     CheckReferenceResult(h_obj, self);
187   }
188   VerifyObject(o);
189   return o.Ptr();
190 }
191 
JniMethodFastEndWithReference(jobject result,uint32_t saved_local_ref_cookie,Thread * self)192 extern mirror::Object* JniMethodFastEndWithReference(jobject result,
193                                                      uint32_t saved_local_ref_cookie,
194                                                      Thread* self) {
195   GoToRunnableFast(self);
196   return JniMethodEndWithReferenceHandleResult(result, saved_local_ref_cookie, self);
197 }
198 
JniMethodEndWithReference(jobject result,uint32_t saved_local_ref_cookie,Thread * self)199 extern mirror::Object* JniMethodEndWithReference(jobject result,
200                                                  uint32_t saved_local_ref_cookie,
201                                                  Thread* self) {
202   GoToRunnable(self);
203   return JniMethodEndWithReferenceHandleResult(result, saved_local_ref_cookie, self);
204 }
205 
JniMethodEndWithReferenceSynchronized(jobject result,uint32_t saved_local_ref_cookie,jobject locked,Thread * self)206 extern mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result,
207                                                              uint32_t saved_local_ref_cookie,
208                                                              jobject locked,
209                                                              Thread* self) {
210   GoToRunnable(self);
211   UnlockJniSynchronizedMethod(locked, self);
212   return JniMethodEndWithReferenceHandleResult(result, saved_local_ref_cookie, self);
213 }
214 
GenericJniMethodEnd(Thread * self,uint32_t saved_local_ref_cookie,jvalue result,uint64_t result_f,ArtMethod * called)215 extern uint64_t GenericJniMethodEnd(Thread* self,
216                                     uint32_t saved_local_ref_cookie,
217                                     jvalue result,
218                                     uint64_t result_f,
219                                     ArtMethod* called)
220     // TODO: NO_THREAD_SAFETY_ANALYSIS as GoToRunnable() is NO_THREAD_SAFETY_ANALYSIS
221     NO_THREAD_SAFETY_ANALYSIS {
222   bool critical_native = called->IsCriticalNative();
223   bool fast_native = called->IsFastNative();
224   bool normal_native = !critical_native && !fast_native;
225 
226   // @Fast and @CriticalNative do not do a state transition.
227   if (LIKELY(normal_native)) {
228     GoToRunnable(self);
229   }
230   // We need the mutator lock (i.e., calling GoToRunnable()) before accessing the shorty or the
231   // locked object.
232   if (called->IsSynchronized()) {
233     DCHECK(normal_native) << "@FastNative/@CriticalNative and synchronize is not supported";
234     HandleScope* handle_scope = down_cast<HandleScope*>(self->GetTopHandleScope());
235     jobject lock = handle_scope->GetHandle(0).ToJObject();
236     DCHECK(lock != nullptr);
237     UnlockJniSynchronizedMethod(lock, self);
238   }
239   char return_shorty_char = called->GetShorty()[0];
240   if (return_shorty_char == 'L') {
241     return reinterpret_cast<uint64_t>(JniMethodEndWithReferenceHandleResult(
242         result.l, saved_local_ref_cookie, self));
243   } else {
244     if (LIKELY(!critical_native)) {
245       PopLocalReferences(saved_local_ref_cookie, self);  // Invalidates top handle scope.
246     }
247     switch (return_shorty_char) {
248       case 'F': {
249         if (kRuntimeISA == InstructionSet::kX86) {
250           // Convert back the result to float.
251           double d = bit_cast<double, uint64_t>(result_f);
252           return bit_cast<uint32_t, float>(static_cast<float>(d));
253         } else {
254           return result_f;
255         }
256       }
257       case 'D':
258         return result_f;
259       case 'Z':
260         return result.z;
261       case 'B':
262         return result.b;
263       case 'C':
264         return result.c;
265       case 'S':
266         return result.s;
267       case 'I':
268         return result.i;
269       case 'J':
270         return result.j;
271       case 'V':
272         return 0;
273       default:
274         LOG(FATAL) << "Unexpected return shorty character " << return_shorty_char;
275         UNREACHABLE();
276     }
277   }
278 }
279 
280 }  // namespace art
281