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