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 #ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
18 #define ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
19
20 #include "android-base/macros.h"
21 #include "instrumentation.h"
22 #include "interpreter.h"
23 #include "transaction.h"
24
25 #include <math.h>
26
27 #include <atomic>
28 #include <iostream>
29 #include <sstream>
30
31 #include <android-base/logging.h>
32 #include <android-base/stringprintf.h>
33
34 #include "art_field-inl.h"
35 #include "art_method-inl.h"
36 #include "base/enums.h"
37 #include "base/locks.h"
38 #include "base/logging.h"
39 #include "base/macros.h"
40 #include "class_linker-inl.h"
41 #include "class_root-inl.h"
42 #include "common_dex_operations.h"
43 #include "common_throws.h"
44 #include "dex/dex_file-inl.h"
45 #include "dex/dex_instruction-inl.h"
46 #include "entrypoints/entrypoint_utils-inl.h"
47 #include "handle_scope-inl.h"
48 #include "interpreter_cache-inl.h"
49 #include "interpreter_switch_impl.h"
50 #include "jit/jit-inl.h"
51 #include "mirror/call_site.h"
52 #include "mirror/class-inl.h"
53 #include "mirror/dex_cache.h"
54 #include "mirror/method.h"
55 #include "mirror/method_handles_lookup.h"
56 #include "mirror/object-inl.h"
57 #include "mirror/object_array-inl.h"
58 #include "mirror/string-inl.h"
59 #include "obj_ptr.h"
60 #include "stack.h"
61 #include "thread.h"
62 #include "thread-inl.h"
63 #include "unstarted_runtime.h"
64 #include "verifier/method_verifier.h"
65 #include "well_known_classes.h"
66
67 namespace art {
68 namespace interpreter {
69
70 void ThrowNullPointerExceptionFromInterpreter()
71 REQUIRES_SHARED(Locks::mutator_lock_);
72
DoMonitorEnter(Thread * self,ShadowFrame * frame,ObjPtr<mirror::Object> ref)73 static inline void DoMonitorEnter(Thread* self, ShadowFrame* frame, ObjPtr<mirror::Object> ref)
74 NO_THREAD_SAFETY_ANALYSIS
75 REQUIRES(!Roles::uninterruptible_) {
76 DCHECK(!ref.IsNull());
77 StackHandleScope<1> hs(self);
78 Handle<mirror::Object> h_ref(hs.NewHandle(ref));
79 h_ref->MonitorEnter(self);
80 DCHECK(self->HoldsLock(h_ref.Get()));
81 if (UNLIKELY(self->IsExceptionPending())) {
82 bool unlocked = h_ref->MonitorExit(self);
83 DCHECK(unlocked);
84 return;
85 }
86 if (frame->GetMethod()->MustCountLocks()) {
87 DCHECK(!frame->GetMethod()->SkipAccessChecks());
88 frame->GetLockCountData().AddMonitor(self, h_ref.Get());
89 }
90 }
91
DoMonitorExit(Thread * self,ShadowFrame * frame,ObjPtr<mirror::Object> ref)92 static inline void DoMonitorExit(Thread* self, ShadowFrame* frame, ObjPtr<mirror::Object> ref)
93 NO_THREAD_SAFETY_ANALYSIS
94 REQUIRES(!Roles::uninterruptible_) {
95 StackHandleScope<1> hs(self);
96 Handle<mirror::Object> h_ref(hs.NewHandle(ref));
97 h_ref->MonitorExit(self);
98 if (frame->GetMethod()->MustCountLocks()) {
99 DCHECK(!frame->GetMethod()->SkipAccessChecks());
100 frame->GetLockCountData().RemoveMonitorOrThrow(self, h_ref.Get());
101 }
102 }
103
DoMonitorCheckOnExit(Thread * self,ShadowFrame * frame)104 static inline bool DoMonitorCheckOnExit(Thread* self, ShadowFrame* frame)
105 NO_THREAD_SAFETY_ANALYSIS
106 REQUIRES(!Roles::uninterruptible_) {
107 if (frame->GetMethod()->MustCountLocks()) {
108 DCHECK(!frame->GetMethod()->SkipAccessChecks());
109 return frame->GetLockCountData().CheckAllMonitorsReleasedOrThrow(self);
110 }
111 return true;
112 }
113
114 void AbortTransactionF(Thread* self, const char* fmt, ...)
115 __attribute__((__format__(__printf__, 2, 3)))
116 REQUIRES_SHARED(Locks::mutator_lock_);
117
118 void AbortTransactionV(Thread* self, const char* fmt, va_list args)
119 REQUIRES_SHARED(Locks::mutator_lock_);
120
121 void RecordArrayElementsInTransaction(ObjPtr<mirror::Array> array, int32_t count)
122 REQUIRES_SHARED(Locks::mutator_lock_);
123
124 // Invokes the given method. This is part of the invocation support and is used by DoInvoke,
125 // DoFastInvoke and DoInvokeVirtualQuick functions.
126 // Returns true on success, otherwise throws an exception and returns false.
127 template<bool is_range>
128 bool DoCall(ArtMethod* called_method,
129 Thread* self,
130 ShadowFrame& shadow_frame,
131 const Instruction* inst,
132 uint16_t inst_data,
133 bool string_init,
134 JValue* result);
135
136 // Called by the switch interpreter to know if we can stay in it.
137 bool ShouldStayInSwitchInterpreter(ArtMethod* method)
138 REQUIRES_SHARED(Locks::mutator_lock_);
139
140 // Throws exception if we are getting close to the end of the stack.
141 NO_INLINE bool CheckStackOverflow(Thread* self, size_t frame_size)
142 REQUIRES_SHARED(Locks::mutator_lock_);
143
144
145 // Sends the normal method exit event.
146 // Returns true if the events succeeded and false if there is a pending exception.
147 template <typename T> bool SendMethodExitEvents(
148 Thread* self,
149 const instrumentation::Instrumentation* instrumentation,
150 ShadowFrame& frame,
151 ArtMethod* method,
152 T& result) REQUIRES_SHARED(Locks::mutator_lock_);
153
154 static inline ALWAYS_INLINE WARN_UNUSED bool
NeedsMethodExitEvent(const instrumentation::Instrumentation * ins)155 NeedsMethodExitEvent(const instrumentation::Instrumentation* ins)
156 REQUIRES_SHARED(Locks::mutator_lock_) {
157 return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners();
158 }
159
160 COLD_ATTR void UnlockHeldMonitors(Thread* self, ShadowFrame* shadow_frame)
161 REQUIRES_SHARED(Locks::mutator_lock_);
162
163 static inline ALWAYS_INLINE void PerformNonStandardReturn(
164 Thread* self,
165 ShadowFrame& frame,
166 JValue& result,
167 const instrumentation::Instrumentation* instrumentation,
168 uint16_t num_dex_inst,
REQUIRES_SHARED(Locks::mutator_lock_)169 bool unlock_monitors = true) REQUIRES_SHARED(Locks::mutator_lock_) {
170 ObjPtr<mirror::Object> thiz(frame.GetThisObject(num_dex_inst));
171 StackHandleScope<1u> hs(self);
172 if (UNLIKELY(self->IsExceptionPending())) {
173 LOG(WARNING) << "Suppressing exception for non-standard method exit: "
174 << self->GetException()->Dump();
175 self->ClearException();
176 }
177 if (unlock_monitors) {
178 UnlockHeldMonitors(self, &frame);
179 DoMonitorCheckOnExit(self, &frame);
180 }
181 result = JValue();
182 if (UNLIKELY(NeedsMethodExitEvent(instrumentation))) {
183 SendMethodExitEvents(self, instrumentation, frame, frame.GetMethod(), result);
184 }
185 }
186
187 // Handles all invoke-XXX/range instructions except for invoke-polymorphic[/range].
188 // Returns true on success, otherwise throws an exception and returns false.
189 template<InvokeType type, bool is_range>
DoInvoke(Thread * self,ShadowFrame & shadow_frame,const Instruction * inst,uint16_t inst_data,JValue * result)190 static ALWAYS_INLINE bool DoInvoke(Thread* self,
191 ShadowFrame& shadow_frame,
192 const Instruction* inst,
193 uint16_t inst_data,
194 JValue* result)
195 REQUIRES_SHARED(Locks::mutator_lock_) {
196 // Make sure to check for async exceptions before anything else.
197 if (UNLIKELY(self->ObserveAsyncException())) {
198 return false;
199 }
200 const uint32_t vregC = is_range ? inst->VRegC_3rc() : inst->VRegC_35c();
201 ObjPtr<mirror::Object> obj = type == kStatic ? nullptr : shadow_frame.GetVRegReference(vregC);
202 ArtMethod* sf_method = shadow_frame.GetMethod();
203 bool string_init = false;
204 ArtMethod* called_method = FindMethodToCall<type>(
205 self, sf_method, &obj, *inst, /* only_lookup_tls_cache= */ false, &string_init);
206 if (called_method == nullptr) {
207 DCHECK(self->IsExceptionPending());
208 result->SetJ(0);
209 return false;
210 }
211
212 return DoCall<is_range>(
213 called_method, self, shadow_frame, inst, inst_data, string_init, result);
214 }
215
ResolveMethodHandle(Thread * self,uint32_t method_handle_index,ArtMethod * referrer)216 static inline ObjPtr<mirror::MethodHandle> ResolveMethodHandle(Thread* self,
217 uint32_t method_handle_index,
218 ArtMethod* referrer)
219 REQUIRES_SHARED(Locks::mutator_lock_) {
220 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
221 return class_linker->ResolveMethodHandle(self, method_handle_index, referrer);
222 }
223
ResolveMethodType(Thread * self,dex::ProtoIndex method_type_index,ArtMethod * referrer)224 static inline ObjPtr<mirror::MethodType> ResolveMethodType(Thread* self,
225 dex::ProtoIndex method_type_index,
226 ArtMethod* referrer)
227 REQUIRES_SHARED(Locks::mutator_lock_) {
228 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
229 return class_linker->ResolveMethodType(self, method_type_index, referrer);
230 }
231
232 #define DECLARE_SIGNATURE_POLYMORPHIC_HANDLER(Name, ...) \
233 bool Do ## Name(Thread* self, \
234 ShadowFrame& shadow_frame, \
235 const Instruction* inst, \
236 uint16_t inst_data, \
237 JValue* result) REQUIRES_SHARED(Locks::mutator_lock_);
238 #include "intrinsics_list.h"
239 INTRINSICS_LIST(DECLARE_SIGNATURE_POLYMORPHIC_HANDLER)
240 #undef INTRINSICS_LIST
241 #undef DECLARE_SIGNATURE_POLYMORPHIC_HANDLER
242
243 // Performs a invoke-polymorphic or invoke-polymorphic-range.
244 template<bool is_range>
245 bool DoInvokePolymorphic(Thread* self,
246 ShadowFrame& shadow_frame,
247 const Instruction* inst,
248 uint16_t inst_data,
249 JValue* result)
250 REQUIRES_SHARED(Locks::mutator_lock_);
251
252 bool DoInvokeCustom(Thread* self,
253 ShadowFrame& shadow_frame,
254 uint32_t call_site_idx,
255 const InstructionOperands* operands,
256 JValue* result)
257 REQUIRES_SHARED(Locks::mutator_lock_);
258
259 // Performs a custom invoke (invoke-custom/invoke-custom-range).
260 template<bool is_range>
DoInvokeCustom(Thread * self,ShadowFrame & shadow_frame,const Instruction * inst,uint16_t inst_data,JValue * result)261 bool DoInvokeCustom(Thread* self,
262 ShadowFrame& shadow_frame,
263 const Instruction* inst,
264 uint16_t inst_data,
265 JValue* result)
266 REQUIRES_SHARED(Locks::mutator_lock_) {
267 const uint32_t call_site_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
268 if (is_range) {
269 RangeInstructionOperands operands(inst->VRegC_3rc(), inst->VRegA_3rc());
270 return DoInvokeCustom(self, shadow_frame, call_site_idx, &operands, result);
271 } else {
272 uint32_t args[Instruction::kMaxVarArgRegs];
273 inst->GetVarArgs(args, inst_data);
274 VarArgsInstructionOperands operands(args, inst->VRegA_35c());
275 return DoInvokeCustom(self, shadow_frame, call_site_idx, &operands, result);
276 }
277 }
278
279 template<Primitive::Type field_type>
GetFieldValue(const ShadowFrame & shadow_frame,uint32_t vreg)280 ALWAYS_INLINE static JValue GetFieldValue(const ShadowFrame& shadow_frame, uint32_t vreg)
281 REQUIRES_SHARED(Locks::mutator_lock_) {
282 JValue field_value;
283 switch (field_type) {
284 case Primitive::kPrimBoolean:
285 field_value.SetZ(static_cast<uint8_t>(shadow_frame.GetVReg(vreg)));
286 break;
287 case Primitive::kPrimByte:
288 field_value.SetB(static_cast<int8_t>(shadow_frame.GetVReg(vreg)));
289 break;
290 case Primitive::kPrimChar:
291 field_value.SetC(static_cast<uint16_t>(shadow_frame.GetVReg(vreg)));
292 break;
293 case Primitive::kPrimShort:
294 field_value.SetS(static_cast<int16_t>(shadow_frame.GetVReg(vreg)));
295 break;
296 case Primitive::kPrimInt:
297 field_value.SetI(shadow_frame.GetVReg(vreg));
298 break;
299 case Primitive::kPrimLong:
300 field_value.SetJ(shadow_frame.GetVRegLong(vreg));
301 break;
302 case Primitive::kPrimNot:
303 field_value.SetL(shadow_frame.GetVRegReference(vreg));
304 break;
305 default:
306 LOG(FATAL) << "Unreachable: " << field_type;
307 UNREACHABLE();
308 }
309 return field_value;
310 }
311
312 extern "C" size_t NterpGetStaticField(Thread* self,
313 ArtMethod* caller,
314 const uint16_t* dex_pc_ptr,
315 size_t resolve_field_type);
316
317 extern "C" uint32_t NterpGetInstanceFieldOffset(Thread* self,
318 ArtMethod* caller,
319 const uint16_t* dex_pc_ptr,
320 size_t resolve_field_type);
321
GetFieldInfo(Thread * self,ArtMethod * caller,const uint16_t * dex_pc_ptr,bool is_static,bool resolve_field_type,ArtField ** field,bool * is_volatile,MemberOffset * offset)322 static inline void GetFieldInfo(Thread* self,
323 ArtMethod* caller,
324 const uint16_t* dex_pc_ptr,
325 bool is_static,
326 bool resolve_field_type,
327 ArtField** field,
328 bool* is_volatile,
329 MemberOffset* offset) {
330 size_t tls_value = 0u;
331 if (!self->GetInterpreterCache()->Get(self, dex_pc_ptr, &tls_value)) {
332 if (is_static) {
333 tls_value = NterpGetStaticField(self, caller, dex_pc_ptr, resolve_field_type);
334 } else {
335 tls_value = NterpGetInstanceFieldOffset(self, caller, dex_pc_ptr, resolve_field_type);
336 }
337
338 if (self->IsExceptionPending()) {
339 return;
340 }
341 }
342
343 if (is_static) {
344 DCHECK_NE(tls_value, 0u);
345 *is_volatile = ((tls_value & 1) != 0);
346 *field = reinterpret_cast<ArtField*>(tls_value & ~static_cast<size_t>(1u));
347 *offset = (*field)->GetOffset();
348 } else {
349 *is_volatile = (static_cast<int32_t>(tls_value) < 0);
350 *offset = MemberOffset(std::abs(static_cast<int32_t>(tls_value)));
351 }
352 }
353
354 // Handles iget-XXX and sget-XXX instructions.
355 // Returns true on success, otherwise throws an exception and returns false.
356 template<FindFieldType find_type,
357 Primitive::Type field_type,
358 bool transaction_active = false>
DoFieldGet(Thread * self,ShadowFrame & shadow_frame,const Instruction * inst,uint16_t inst_data)359 ALWAYS_INLINE bool DoFieldGet(Thread* self,
360 ShadowFrame& shadow_frame,
361 const Instruction* inst,
362 uint16_t inst_data) REQUIRES_SHARED(Locks::mutator_lock_) {
363 const bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
364 bool should_report = Runtime::Current()->GetInstrumentation()->HasFieldReadListeners();
365 ArtField* field = nullptr;
366 MemberOffset offset(0u);
367 bool is_volatile;
368 GetFieldInfo(self,
369 shadow_frame.GetMethod(),
370 reinterpret_cast<const uint16_t*>(inst),
371 is_static,
372 /*resolve_field_type=*/ false,
373 &field,
374 &is_volatile,
375 &offset);
376 if (self->IsExceptionPending()) {
377 return false;
378 }
379
380 ObjPtr<mirror::Object> obj;
381 if (is_static) {
382 obj = field->GetDeclaringClass();
383 if (transaction_active) {
384 if (Runtime::Current()->GetTransaction()->ReadConstraint(obj)) {
385 Runtime::Current()->AbortTransactionAndThrowAbortError(self, "Can't read static fields of "
386 + obj->PrettyTypeOf() + " since it does not belong to clinit's class.");
387 return false;
388 }
389 }
390 } else {
391 obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
392 if (should_report || obj == nullptr) {
393 field = ResolveFieldWithAccessChecks(self,
394 Runtime::Current()->GetClassLinker(),
395 inst->VRegC_22c(),
396 shadow_frame.GetMethod(),
397 /* is_static= */ false,
398 /* is_put= */ false,
399 /* resolve_field_type= */ false);
400 if (obj == nullptr) {
401 ThrowNullPointerExceptionForFieldAccess(
402 field, shadow_frame.GetMethod(), /* is_read= */ true);
403 return false;
404 }
405 // Reload in case suspension happened during field resolution.
406 obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
407 }
408 }
409
410 uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
411 JValue result;
412 if (should_report) {
413 DCHECK(field != nullptr);
414 if (UNLIKELY(!DoFieldGetCommon<field_type>(self, shadow_frame, obj, field, &result))) {
415 // Instrumentation threw an error!
416 CHECK(self->IsExceptionPending());
417 return false;
418 }
419 }
420
421 #define FIELD_GET(prim, type, jtype, vreg) \
422 case Primitive::kPrim ##prim: \
423 shadow_frame.SetVReg ##vreg(vregA, \
424 should_report ? result.Get ##jtype() \
425 : is_volatile ? obj->GetField ## type ## Volatile(offset) \
426 : obj->GetField ##type(offset)); \
427 break;
428
429 switch (field_type) {
430 FIELD_GET(Boolean, Boolean, Z, )
431 FIELD_GET(Byte, Byte, B, )
432 FIELD_GET(Char, Char, C, )
433 FIELD_GET(Short, Short, S, )
434 FIELD_GET(Int, 32, I, )
435 FIELD_GET(Long, 64, J, Long)
436 #undef FIELD_GET
437 case Primitive::kPrimNot:
438 shadow_frame.SetVRegReference(
439 vregA,
440 should_report ? result.GetL()
441 : is_volatile ? obj->GetFieldObjectVolatile<mirror::Object>(offset)
442 : obj->GetFieldObject<mirror::Object>(offset));
443 break;
444 default:
445 LOG(FATAL) << "Unreachable: " << field_type;
446 UNREACHABLE();
447 }
448 return true;
449 }
450
CheckWriteConstraint(Thread * self,ObjPtr<mirror::Object> obj)451 static inline bool CheckWriteConstraint(Thread* self, ObjPtr<mirror::Object> obj)
452 REQUIRES_SHARED(Locks::mutator_lock_) {
453 Runtime* runtime = Runtime::Current();
454 if (runtime->GetTransaction()->WriteConstraint(obj)) {
455 DCHECK(runtime->GetHeap()->ObjectIsInBootImageSpace(obj) || obj->IsClass());
456 const char* base_msg = runtime->GetHeap()->ObjectIsInBootImageSpace(obj)
457 ? "Can't set fields of boot image "
458 : "Can't set fields of ";
459 runtime->AbortTransactionAndThrowAbortError(self, base_msg + obj->PrettyTypeOf());
460 return false;
461 }
462 return true;
463 }
464
CheckWriteValueConstraint(Thread * self,ObjPtr<mirror::Object> value)465 static inline bool CheckWriteValueConstraint(Thread* self, ObjPtr<mirror::Object> value)
466 REQUIRES_SHARED(Locks::mutator_lock_) {
467 Runtime* runtime = Runtime::Current();
468 if (runtime->GetTransaction()->WriteValueConstraint(value)) {
469 DCHECK(value != nullptr);
470 std::string msg = value->IsClass()
471 ? "Can't store reference to class " + value->AsClass()->PrettyDescriptor()
472 : "Can't store reference to instance of " + value->GetClass()->PrettyDescriptor();
473 runtime->AbortTransactionAndThrowAbortError(self, msg);
474 return false;
475 }
476 return true;
477 }
478
479 // Handles iput-XXX and sput-XXX instructions.
480 // Returns true on success, otherwise throws an exception and returns false.
481 template<FindFieldType find_type, Primitive::Type field_type, bool transaction_active>
DoFieldPut(Thread * self,const ShadowFrame & shadow_frame,const Instruction * inst,uint16_t inst_data)482 ALWAYS_INLINE bool DoFieldPut(Thread* self,
483 const ShadowFrame& shadow_frame,
484 const Instruction* inst,
485 uint16_t inst_data)
486 REQUIRES_SHARED(Locks::mutator_lock_) {
487 bool should_report = Runtime::Current()->GetInstrumentation()->HasFieldWriteListeners();
488 bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
489 uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
490 bool resolve_field_type = (shadow_frame.GetVRegReference(vregA) != nullptr);
491 ArtField* field = nullptr;
492 MemberOffset offset(0u);
493 bool is_volatile;
494 GetFieldInfo(self,
495 shadow_frame.GetMethod(),
496 reinterpret_cast<const uint16_t*>(inst),
497 is_static,
498 resolve_field_type,
499 &field,
500 &is_volatile,
501 &offset);
502 if (self->IsExceptionPending()) {
503 return false;
504 }
505
506 ObjPtr<mirror::Object> obj;
507 if (is_static) {
508 obj = field->GetDeclaringClass();
509 } else {
510 obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
511 if (should_report || obj == nullptr) {
512 field = ResolveFieldWithAccessChecks(self,
513 Runtime::Current()->GetClassLinker(),
514 inst->VRegC_22c(),
515 shadow_frame.GetMethod(),
516 /* is_static= */ false,
517 /* is_put= */ true,
518 resolve_field_type);
519 if (UNLIKELY(obj == nullptr)) {
520 ThrowNullPointerExceptionForFieldAccess(
521 field, shadow_frame.GetMethod(), /* is_read= */ false);
522 return false;
523 }
524 // Reload in case suspension happened during field resolution.
525 obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
526 }
527 }
528 if (transaction_active && !CheckWriteConstraint(self, obj)) {
529 return false;
530 }
531
532 JValue value = GetFieldValue<field_type>(shadow_frame, vregA);
533
534 if (transaction_active &&
535 field_type == Primitive::kPrimNot &&
536 !CheckWriteValueConstraint(self, value.GetL())) {
537 return false;
538 }
539 if (should_report) {
540 return DoFieldPutCommon<field_type, transaction_active>(self,
541 shadow_frame,
542 obj,
543 field,
544 value);
545 }
546 #define FIELD_SET(prim, type, jtype) \
547 case Primitive::kPrim ## prim: \
548 if (is_volatile) { \
549 obj->SetField ## type ## Volatile<transaction_active>(offset, value.Get ## jtype()); \
550 } else { \
551 obj->SetField ## type<transaction_active>(offset, value.Get ## jtype()); \
552 } \
553 break;
554
555 switch (field_type) {
556 FIELD_SET(Boolean, Boolean, Z)
557 FIELD_SET(Byte, Byte, B)
558 FIELD_SET(Char, Char, C)
559 FIELD_SET(Short, Short, S)
560 FIELD_SET(Int, 32, I)
561 FIELD_SET(Long, 64, J)
562 FIELD_SET(Not, Object, L)
563 case Primitive::kPrimVoid: {
564 LOG(FATAL) << "Unreachable " << field_type;
565 break;
566 }
567 }
568 #undef FIELD_SET
569
570 if (transaction_active) {
571 if (UNLIKELY(self->IsExceptionPending())) {
572 return false;
573 }
574 }
575 return true;
576 }
577
578 // Handles string resolution for const-string and const-string-jumbo instructions. Also ensures the
579 // java.lang.String class is initialized.
ResolveString(Thread * self,ShadowFrame & shadow_frame,dex::StringIndex string_idx)580 static inline ObjPtr<mirror::String> ResolveString(Thread* self,
581 ShadowFrame& shadow_frame,
582 dex::StringIndex string_idx)
583 REQUIRES_SHARED(Locks::mutator_lock_) {
584 ObjPtr<mirror::Class> java_lang_string_class = GetClassRoot<mirror::String>();
585 if (UNLIKELY(!java_lang_string_class->IsVisiblyInitialized())) {
586 StackHandleScope<1> hs(self);
587 Handle<mirror::Class> h_class(hs.NewHandle(java_lang_string_class));
588 if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(
589 self, h_class, /*can_init_fields=*/ true, /*can_init_parents=*/ true))) {
590 DCHECK(self->IsExceptionPending());
591 return nullptr;
592 }
593 DCHECK(h_class->IsInitializing());
594 }
595 ArtMethod* method = shadow_frame.GetMethod();
596 ObjPtr<mirror::String> string_ptr =
597 Runtime::Current()->GetClassLinker()->ResolveString(string_idx, method);
598 return string_ptr;
599 }
600
601 // Handles div-int, div-int/2addr, div-int/li16 and div-int/lit8 instructions.
602 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
DoIntDivide(ShadowFrame & shadow_frame,size_t result_reg,int32_t dividend,int32_t divisor)603 static inline bool DoIntDivide(ShadowFrame& shadow_frame, size_t result_reg,
604 int32_t dividend, int32_t divisor)
605 REQUIRES_SHARED(Locks::mutator_lock_) {
606 constexpr int32_t kMinInt = std::numeric_limits<int32_t>::min();
607 if (UNLIKELY(divisor == 0)) {
608 ThrowArithmeticExceptionDivideByZero();
609 return false;
610 }
611 if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
612 shadow_frame.SetVReg(result_reg, kMinInt);
613 } else {
614 shadow_frame.SetVReg(result_reg, dividend / divisor);
615 }
616 return true;
617 }
618
619 // Handles rem-int, rem-int/2addr, rem-int/li16 and rem-int/lit8 instructions.
620 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
DoIntRemainder(ShadowFrame & shadow_frame,size_t result_reg,int32_t dividend,int32_t divisor)621 static inline bool DoIntRemainder(ShadowFrame& shadow_frame, size_t result_reg,
622 int32_t dividend, int32_t divisor)
623 REQUIRES_SHARED(Locks::mutator_lock_) {
624 constexpr int32_t kMinInt = std::numeric_limits<int32_t>::min();
625 if (UNLIKELY(divisor == 0)) {
626 ThrowArithmeticExceptionDivideByZero();
627 return false;
628 }
629 if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
630 shadow_frame.SetVReg(result_reg, 0);
631 } else {
632 shadow_frame.SetVReg(result_reg, dividend % divisor);
633 }
634 return true;
635 }
636
637 // Handles div-long and div-long-2addr instructions.
638 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
DoLongDivide(ShadowFrame & shadow_frame,size_t result_reg,int64_t dividend,int64_t divisor)639 static inline bool DoLongDivide(ShadowFrame& shadow_frame,
640 size_t result_reg,
641 int64_t dividend,
642 int64_t divisor)
643 REQUIRES_SHARED(Locks::mutator_lock_) {
644 const int64_t kMinLong = std::numeric_limits<int64_t>::min();
645 if (UNLIKELY(divisor == 0)) {
646 ThrowArithmeticExceptionDivideByZero();
647 return false;
648 }
649 if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
650 shadow_frame.SetVRegLong(result_reg, kMinLong);
651 } else {
652 shadow_frame.SetVRegLong(result_reg, dividend / divisor);
653 }
654 return true;
655 }
656
657 // Handles rem-long and rem-long-2addr instructions.
658 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
DoLongRemainder(ShadowFrame & shadow_frame,size_t result_reg,int64_t dividend,int64_t divisor)659 static inline bool DoLongRemainder(ShadowFrame& shadow_frame,
660 size_t result_reg,
661 int64_t dividend,
662 int64_t divisor)
663 REQUIRES_SHARED(Locks::mutator_lock_) {
664 const int64_t kMinLong = std::numeric_limits<int64_t>::min();
665 if (UNLIKELY(divisor == 0)) {
666 ThrowArithmeticExceptionDivideByZero();
667 return false;
668 }
669 if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
670 shadow_frame.SetVRegLong(result_reg, 0);
671 } else {
672 shadow_frame.SetVRegLong(result_reg, dividend % divisor);
673 }
674 return true;
675 }
676
677 // Handles filled-new-array and filled-new-array-range instructions.
678 // Returns true on success, otherwise throws an exception and returns false.
679 template <bool is_range, bool transaction_active>
680 bool DoFilledNewArray(const Instruction* inst,
681 const ShadowFrame& shadow_frame,
682 Thread* self,
683 JValue* result);
684
685 // Handles packed-switch instruction.
686 // Returns the branch offset to the next instruction to execute.
DoPackedSwitch(const Instruction * inst,const ShadowFrame & shadow_frame,uint16_t inst_data)687 static inline int32_t DoPackedSwitch(const Instruction* inst,
688 const ShadowFrame& shadow_frame,
689 uint16_t inst_data)
690 REQUIRES_SHARED(Locks::mutator_lock_) {
691 DCHECK(inst->Opcode() == Instruction::PACKED_SWITCH);
692 const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
693 int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
694 DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
695 uint16_t size = switch_data[1];
696 if (size == 0) {
697 // Empty packed switch, move forward by 3 (size of PACKED_SWITCH).
698 return 3;
699 }
700 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
701 DCHECK_ALIGNED(keys, 4);
702 int32_t first_key = keys[0];
703 const int32_t* targets = reinterpret_cast<const int32_t*>(&switch_data[4]);
704 DCHECK_ALIGNED(targets, 4);
705 int32_t index = test_val - first_key;
706 if (index >= 0 && index < size) {
707 return targets[index];
708 } else {
709 // No corresponding value: move forward by 3 (size of PACKED_SWITCH).
710 return 3;
711 }
712 }
713
714 // Handles sparse-switch instruction.
715 // Returns the branch offset to the next instruction to execute.
DoSparseSwitch(const Instruction * inst,const ShadowFrame & shadow_frame,uint16_t inst_data)716 static inline int32_t DoSparseSwitch(const Instruction* inst, const ShadowFrame& shadow_frame,
717 uint16_t inst_data)
718 REQUIRES_SHARED(Locks::mutator_lock_) {
719 DCHECK(inst->Opcode() == Instruction::SPARSE_SWITCH);
720 const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
721 int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
722 DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
723 uint16_t size = switch_data[1];
724 // Return length of SPARSE_SWITCH if size is 0.
725 if (size == 0) {
726 return 3;
727 }
728 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
729 DCHECK_ALIGNED(keys, 4);
730 const int32_t* entries = keys + size;
731 DCHECK_ALIGNED(entries, 4);
732 int lo = 0;
733 int hi = size - 1;
734 while (lo <= hi) {
735 int mid = (lo + hi) / 2;
736 int32_t foundVal = keys[mid];
737 if (test_val < foundVal) {
738 hi = mid - 1;
739 } else if (test_val > foundVal) {
740 lo = mid + 1;
741 } else {
742 return entries[mid];
743 }
744 }
745 // No corresponding value: move forward by 3 (size of SPARSE_SWITCH).
746 return 3;
747 }
748
749 // We execute any instrumentation events triggered by throwing and/or handing the pending exception
750 // and change the shadow_frames dex_pc to the appropriate exception handler if the current method
751 // has one. If the exception has been handled and the shadow_frame is now pointing to a catch clause
752 // we return true. If the current method is unable to handle the exception we return false.
753 // This function accepts a null Instrumentation* as a way to cause instrumentation events not to be
754 // reported.
755 // TODO We might wish to reconsider how we cause some events to be ignored.
756 bool MoveToExceptionHandler(Thread* self,
757 ShadowFrame& shadow_frame,
758 bool skip_listeners,
759 bool skip_throw_listener) REQUIRES_SHARED(Locks::mutator_lock_);
760
761 NO_RETURN void UnexpectedOpcode(const Instruction* inst, const ShadowFrame& shadow_frame)
762 __attribute__((cold))
763 REQUIRES_SHARED(Locks::mutator_lock_);
764
765 // Set true if you want TraceExecution invocation before each bytecode execution.
766 constexpr bool kTraceExecutionEnabled = false;
767
TraceExecution(const ShadowFrame & shadow_frame,const Instruction * inst,const uint32_t dex_pc)768 static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruction* inst,
769 const uint32_t dex_pc)
770 REQUIRES_SHARED(Locks::mutator_lock_) {
771 if (kTraceExecutionEnabled) {
772 #define TRACE_LOG std::cerr
773 std::ostringstream oss;
774 oss << shadow_frame.GetMethod()->PrettyMethod()
775 << android::base::StringPrintf("\n0x%x: ", dex_pc)
776 << inst->DumpString(shadow_frame.GetMethod()->GetDexFile()) << "\n";
777 for (uint32_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
778 uint32_t raw_value = shadow_frame.GetVReg(i);
779 ObjPtr<mirror::Object> ref_value = shadow_frame.GetVRegReference(i);
780 oss << android::base::StringPrintf(" vreg%u=0x%08X", i, raw_value);
781 if (ref_value != nullptr) {
782 if (ref_value->GetClass()->IsStringClass() &&
783 !ref_value->AsString()->IsValueNull()) {
784 oss << "/java.lang.String \"" << ref_value->AsString()->ToModifiedUtf8() << "\"";
785 } else {
786 oss << "/" << ref_value->PrettyTypeOf();
787 }
788 }
789 }
790 TRACE_LOG << oss.str() << "\n";
791 #undef TRACE_LOG
792 }
793 }
794
IsBackwardBranch(int32_t branch_offset)795 static inline bool IsBackwardBranch(int32_t branch_offset) {
796 return branch_offset <= 0;
797 }
798
799 // The arg_offset is the offset to the first input register in the frame.
800 void ArtInterpreterToCompiledCodeBridge(Thread* self,
801 ArtMethod* caller,
802 ShadowFrame* shadow_frame,
803 uint16_t arg_offset,
804 JValue* result);
805
806 // Set string value created from StringFactory.newStringFromXXX() into all aliases of
807 // StringFactory.newEmptyString().
808 void SetStringInitValueToAllAliases(ShadowFrame* shadow_frame,
809 uint16_t this_obj_vreg,
810 JValue result);
811
812 } // namespace interpreter
813 } // namespace art
814
815 #endif // ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
816