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 #include "runtime_entrypoints_list.h"
28
29 // For methods that monitor JNI invocations and report their begin/end to
30 // palette hooks.
31 #define MONITOR_JNI(kind) \
32 { \
33 bool should_report = false; \
34 PaletteShouldReportJniInvocations(&should_report); \
35 if (should_report) { \
36 kind(self->GetJniEnv()); \
37 } \
38 }
39
40 namespace art HIDDEN {
41
42 static_assert(sizeof(jni::LRTSegmentState) == sizeof(uint32_t), "LRTSegmentState size unexpected");
43 static_assert(std::is_trivial<jni::LRTSegmentState>::value, "LRTSegmentState not trivial");
44
artJniReadBarrier(ArtMethod * method)45 extern "C" void artJniReadBarrier(ArtMethod* method)
46 REQUIRES_SHARED(Locks::mutator_lock_) {
47 DCHECK(gUseReadBarrier);
48 mirror::CompressedReference<mirror::Object>* declaring_class =
49 method->GetDeclaringClassAddressWithoutBarrier();
50 if (kUseBakerReadBarrier) {
51 DCHECK(declaring_class->AsMirrorPtr() != nullptr)
52 << "The class of a static jni call must not be null";
53 // Check the mark bit and return early if it's already marked.
54 if (LIKELY(declaring_class->AsMirrorPtr()->GetMarkBit() != 0)) {
55 return;
56 }
57 }
58 // Call the read barrier and update the handle.
59 mirror::Object* to_ref = ReadBarrier::BarrierForRoot(declaring_class);
60 declaring_class->Assign(to_ref);
61 }
62
63 // Called on entry to JNI, transition out of Runnable and release share of mutator_lock_.
artJniMethodStart(Thread * self)64 extern "C" void artJniMethodStart(Thread* self)
65 UNLOCK_FUNCTION(Locks::mutator_lock_) {
66 if (kIsDebugBuild) {
67 ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
68 CHECK(!native_method->IsFastNative()) << native_method->PrettyMethod();
69 CHECK(!native_method->IsCriticalNative()) << native_method->PrettyMethod();
70 }
71
72 // Transition out of runnable.
73 self->TransitionFromRunnableToSuspended(ThreadState::kNative);
74 }
75
PopLocalReferences(uint32_t saved_local_ref_cookie,Thread * self)76 static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self)
77 REQUIRES_SHARED(Locks::mutator_lock_) {
78 JNIEnvExt* env = self->GetJniEnv();
79 if (UNLIKELY(env->IsCheckJniEnabled())) {
80 env->CheckNoHeldMonitors();
81 }
82 env->PopLocalReferenceFrame(bit_cast<jni::LRTSegmentState>(saved_local_ref_cookie));
83 }
84
85 // TODO: annotalysis disabled as monitor semantics are maintained in Java code.
86 __attribute__((no_sanitize("memtag"))) // TODO(b/305919664)
87 extern "C" void
artJniUnlockObject(mirror::Object * locked,Thread * self)88 artJniUnlockObject(mirror::Object* locked, Thread* self) NO_THREAD_SAFETY_ANALYSIS
89 REQUIRES(!Roles::uninterruptible_) REQUIRES_SHARED(Locks::mutator_lock_) {
90 // Note: No thread suspension is allowed for successful unlocking, otherwise plain
91 // `mirror::Object*` return value saved by the assembly stub would need to be updated.
92 uintptr_t old_poison_object_cookie = kIsDebugBuild ? self->GetPoisonObjectCookie() : 0u;
93 // Save any pending exception over monitor exit call.
94 ObjPtr<mirror::Throwable> saved_exception = nullptr;
95 if (UNLIKELY(self->IsExceptionPending())) {
96 saved_exception = self->GetException();
97 self->ClearException();
98 }
99 // Decode locked object and unlock, before popping local references.
100 locked->MonitorExit(self);
101 if (UNLIKELY(self->IsExceptionPending())) {
102 LOG(FATAL) << "Exception during implicit MonitorExit for synchronized native method:\n"
103 << self->GetException()->Dump()
104 << (saved_exception != nullptr
105 ? "\nAn exception was already pending:\n" + saved_exception->Dump()
106 : "");
107 UNREACHABLE();
108 }
109 // Restore pending exception.
110 if (saved_exception != nullptr) {
111 self->SetException(saved_exception);
112 }
113 if (kIsDebugBuild) {
114 DCHECK_EQ(old_poison_object_cookie, self->GetPoisonObjectCookie());
115 }
116 }
117
118 // TODO: These should probably be templatized or macro-ized.
119 // Otherwise there's just too much repetitive boilerplate.
120
artJniMethodEnd(Thread * self)121 extern "C" void artJniMethodEnd(Thread* self) SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
122 self->TransitionFromSuspendedToRunnable();
123
124 if (kIsDebugBuild) {
125 ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
126 CHECK(!native_method->IsFastNative()) << native_method->PrettyMethod();
127 CHECK(!native_method->IsCriticalNative()) << native_method->PrettyMethod();
128 }
129 }
130
JniDecodeReferenceResult(jobject result,Thread * self)131 extern mirror::Object* JniDecodeReferenceResult(jobject result, Thread* self)
132 REQUIRES_SHARED(Locks::mutator_lock_) {
133 DCHECK(!self->IsExceptionPending());
134 ObjPtr<mirror::Object> o = self->DecodeJObject(result);
135 // Process result.
136 if (UNLIKELY(self->GetJniEnv()->IsCheckJniEnabled())) {
137 // CheckReferenceResult can resolve types.
138 StackHandleScope<1> hs(self);
139 HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&o));
140 CheckReferenceResult(h_obj, self);
141 }
142 VerifyObject(o);
143 return o.Ptr();
144 }
145
GenericJniMethodEnd(Thread * self,uint32_t saved_local_ref_cookie,jvalue result,uint64_t result_f,ArtMethod * called)146 extern uint64_t GenericJniMethodEnd(Thread* self,
147 uint32_t saved_local_ref_cookie,
148 jvalue result,
149 uint64_t result_f,
150 ArtMethod* called)
151 // NO_THREAD_SAFETY_ANALYSIS because we can enter this function with the mutator lock
152 // unlocked for normal JNI, or locked for @FastNative and @CriticalNative.
153 NO_THREAD_SAFETY_ANALYSIS {
154 bool critical_native = called->IsCriticalNative();
155 bool fast_native = called->IsFastNative();
156 bool normal_native = !critical_native && !fast_native;
157
158 // @CriticalNative does not do a state transition. @FastNative usually does not do a state
159 // transition either but it performs a suspend check that may do state transitions.
160 if (LIKELY(normal_native)) {
161 if (UNLIKELY(self->ReadFlag(ThreadFlag::kMonitorJniEntryExit))) {
162 artJniMonitoredMethodEnd(self);
163 } else {
164 artJniMethodEnd(self);
165 }
166 } else if (fast_native) {
167 // When we are in @FastNative, we are already Runnable.
168 DCHECK(Locks::mutator_lock_->IsSharedHeld(self));
169 // Only do a suspend check on the way out of JNI just like compiled stubs.
170 self->CheckSuspend();
171 }
172 // We need the mutator lock (i.e., calling `artJniMethodEnd()`) before accessing
173 // the shorty or the locked object.
174 if (called->IsSynchronized()) {
175 DCHECK(normal_native) << "@FastNative/@CriticalNative and synchronize is not supported";
176 ObjPtr<mirror::Object> lock = GetGenericJniSynchronizationObject(self, called);
177 DCHECK(lock != nullptr);
178 artJniUnlockObject(lock.Ptr(), self);
179 }
180 char return_shorty_char = called->GetShorty()[0];
181 uint64_t ret;
182 if (return_shorty_char == 'L') {
183 ret = reinterpret_cast<uint64_t>(
184 UNLIKELY(self->IsExceptionPending()) ? nullptr : JniDecodeReferenceResult(result.l, self));
185 PopLocalReferences(saved_local_ref_cookie, self);
186 } else {
187 if (LIKELY(!critical_native)) {
188 PopLocalReferences(saved_local_ref_cookie, self);
189 }
190 switch (return_shorty_char) {
191 case 'F': {
192 if (kRuntimeISA == InstructionSet::kX86) {
193 // Convert back the result to float.
194 double d = bit_cast<double, uint64_t>(result_f);
195 ret = bit_cast<uint32_t, float>(static_cast<float>(d));
196 } else {
197 ret = result_f;
198 }
199 }
200 break;
201 case 'D':
202 ret = result_f;
203 break;
204 case 'Z':
205 ret = result.z;
206 break;
207 case 'B':
208 ret = result.b;
209 break;
210 case 'C':
211 ret = result.c;
212 break;
213 case 'S':
214 ret = result.s;
215 break;
216 case 'I':
217 ret = result.i;
218 break;
219 case 'J':
220 ret = result.j;
221 break;
222 case 'V':
223 ret = 0;
224 break;
225 default:
226 LOG(FATAL) << "Unexpected return shorty character " << return_shorty_char;
227 UNREACHABLE();
228 }
229 }
230
231 return ret;
232 }
233
artJniMonitoredMethodStart(Thread * self)234 extern "C" void artJniMonitoredMethodStart(Thread* self) UNLOCK_FUNCTION(Locks::mutator_lock_) {
235 artJniMethodStart(self);
236 MONITOR_JNI(PaletteNotifyBeginJniInvocation);
237 }
238
artJniMonitoredMethodEnd(Thread * self)239 extern "C" void artJniMonitoredMethodEnd(Thread* self) SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
240 MONITOR_JNI(PaletteNotifyEndJniInvocation);
241 artJniMethodEnd(self);
242 }
243
244 } // namespace art
245