• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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