Home | History | Annotate | Download | only in interpreter
      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 "interpreter.h"
     21 
     22 #include <math.h>
     23 
     24 #include "base/logging.h"
     25 #include "class_linker-inl.h"
     26 #include "common_throws.h"
     27 #include "dex_file-inl.h"
     28 #include "dex_instruction-inl.h"
     29 #include "dex_instruction.h"
     30 #include "entrypoints/entrypoint_utils-inl.h"
     31 #include "gc/accounting/card_table-inl.h"
     32 #include "handle_scope-inl.h"
     33 #include "method_helper-inl.h"
     34 #include "nth_caller_visitor.h"
     35 #include "mirror/art_field-inl.h"
     36 #include "mirror/art_method.h"
     37 #include "mirror/art_method-inl.h"
     38 #include "mirror/class.h"
     39 #include "mirror/class-inl.h"
     40 #include "mirror/object-inl.h"
     41 #include "mirror/object_array-inl.h"
     42 #include "mirror/string-inl.h"
     43 #include "ScopedLocalRef.h"
     44 #include "scoped_thread_state_change.h"
     45 #include "thread.h"
     46 #include "well_known_classes.h"
     47 
     48 using ::art::mirror::ArtField;
     49 using ::art::mirror::ArtMethod;
     50 using ::art::mirror::Array;
     51 using ::art::mirror::BooleanArray;
     52 using ::art::mirror::ByteArray;
     53 using ::art::mirror::CharArray;
     54 using ::art::mirror::Class;
     55 using ::art::mirror::ClassLoader;
     56 using ::art::mirror::IntArray;
     57 using ::art::mirror::LongArray;
     58 using ::art::mirror::Object;
     59 using ::art::mirror::ObjectArray;
     60 using ::art::mirror::ShortArray;
     61 using ::art::mirror::String;
     62 using ::art::mirror::Throwable;
     63 
     64 namespace art {
     65 namespace interpreter {
     66 
     67 // External references to both interpreter implementations.
     68 
     69 template<bool do_access_check, bool transaction_active>
     70 extern JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh,
     71                                 const DexFile::CodeItem* code_item,
     72                                 ShadowFrame& shadow_frame, JValue result_register);
     73 
     74 template<bool do_access_check, bool transaction_active>
     75 extern JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh,
     76                               const DexFile::CodeItem* code_item,
     77                               ShadowFrame& shadow_frame, JValue result_register);
     78 
     79 void ThrowNullPointerExceptionFromInterpreter(const ShadowFrame& shadow_frame)
     80     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     81 
     82 static inline void DoMonitorEnter(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
     83   ref->MonitorEnter(self);
     84 }
     85 
     86 static inline void DoMonitorExit(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
     87   ref->MonitorExit(self);
     88 }
     89 
     90 void AbortTransaction(Thread* self, const char* fmt, ...)
     91     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     92 
     93 void RecordArrayElementsInTransaction(mirror::Array* array, int32_t count)
     94     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     95 
     96 // Invokes the given method. This is part of the invocation support and is used by DoInvoke and
     97 // DoInvokeVirtualQuick functions.
     98 // Returns true on success, otherwise throws an exception and returns false.
     99 template<bool is_range, bool do_assignability_check>
    100 bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame,
    101             const Instruction* inst, uint16_t inst_data, JValue* result);
    102 
    103 // Handles invoke-XXX/range instructions.
    104 // Returns true on success, otherwise throws an exception and returns false.
    105 template<InvokeType type, bool is_range, bool do_access_check>
    106 static inline bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
    107                             uint16_t inst_data, JValue* result) {
    108   const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
    109   const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
    110   Object* receiver = (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC);
    111   mirror::ArtMethod* sf_method = shadow_frame.GetMethod();
    112   ArtMethod* const method = FindMethodFromCode<type, do_access_check>(
    113       method_idx, &receiver, &sf_method, self);
    114   // The shadow frame should already be pushed, so we don't need to update it.
    115   if (UNLIKELY(method == nullptr)) {
    116     CHECK(self->IsExceptionPending());
    117     result->SetJ(0);
    118     return false;
    119   } else if (UNLIKELY(method->IsAbstract())) {
    120     ThrowAbstractMethodError(method);
    121     result->SetJ(0);
    122     return false;
    123   } else {
    124     return DoCall<is_range, do_access_check>(method, self, shadow_frame, inst, inst_data, result);
    125   }
    126 }
    127 
    128 // Handles invoke-virtual-quick and invoke-virtual-quick-range instructions.
    129 // Returns true on success, otherwise throws an exception and returns false.
    130 template<bool is_range>
    131 static inline bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
    132                                         const Instruction* inst, uint16_t inst_data,
    133                                         JValue* result) {
    134   const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
    135   Object* const receiver = shadow_frame.GetVRegReference(vregC);
    136   if (UNLIKELY(receiver == nullptr)) {
    137     // We lost the reference to the method index so we cannot get a more
    138     // precised exception message.
    139     ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
    140     return false;
    141   }
    142   const uint32_t vtable_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
    143   CHECK(receiver->GetClass()->ShouldHaveEmbeddedImtAndVTable());
    144   ArtMethod* const method = receiver->GetClass()->GetEmbeddedVTableEntry(vtable_idx);
    145   if (UNLIKELY(method == nullptr)) {
    146     CHECK(self->IsExceptionPending());
    147     result->SetJ(0);
    148     return false;
    149   } else if (UNLIKELY(method->IsAbstract())) {
    150     ThrowAbstractMethodError(method);
    151     result->SetJ(0);
    152     return false;
    153   } else {
    154     // No need to check since we've been quickened.
    155     return DoCall<is_range, false>(method, self, shadow_frame, inst, inst_data, result);
    156   }
    157 }
    158 
    159 // Handles iget-XXX and sget-XXX instructions.
    160 // Returns true on success, otherwise throws an exception and returns false.
    161 template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
    162 bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
    163                 uint16_t inst_data) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    164 
    165 // Handles iget-quick, iget-wide-quick and iget-object-quick instructions.
    166 // Returns true on success, otherwise throws an exception and returns false.
    167 template<Primitive::Type field_type>
    168 bool DoIGetQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data)
    169     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    170 
    171 // Handles iput-XXX and sput-XXX instructions.
    172 // Returns true on success, otherwise throws an exception and returns false.
    173 template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check,
    174          bool transaction_active>
    175 bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction* inst,
    176                 uint16_t inst_data) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    177 
    178 // Handles iput-quick, iput-wide-quick and iput-object-quick instructions.
    179 // Returns true on success, otherwise throws an exception and returns false.
    180 template<Primitive::Type field_type, bool transaction_active>
    181 bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data)
    182     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    183 
    184 
    185 // Handles string resolution for const-string and const-string-jumbo instructions. Also ensures the
    186 // java.lang.String class is initialized.
    187 static inline String* ResolveString(Thread* self, MethodHelper& mh, uint32_t string_idx)
    188     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    189   CHECK(!kMovingMethods);
    190   Class* java_lang_string_class = String::GetJavaLangString();
    191   if (UNLIKELY(!java_lang_string_class->IsInitialized())) {
    192     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    193     StackHandleScope<1> hs(self);
    194     Handle<mirror::Class> h_class(hs.NewHandle(java_lang_string_class));
    195     if (UNLIKELY(!class_linker->EnsureInitialized(h_class, true, true))) {
    196       DCHECK(self->IsExceptionPending());
    197       return nullptr;
    198     }
    199   }
    200   return mh.ResolveString(string_idx);
    201 }
    202 
    203 // Handles div-int, div-int/2addr, div-int/li16 and div-int/lit8 instructions.
    204 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
    205 static inline bool DoIntDivide(ShadowFrame& shadow_frame, size_t result_reg,
    206                                int32_t dividend, int32_t divisor)
    207     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    208   const int32_t kMinInt = std::numeric_limits<int32_t>::min();
    209   if (UNLIKELY(divisor == 0)) {
    210     ThrowArithmeticExceptionDivideByZero();
    211     return false;
    212   }
    213   if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
    214     shadow_frame.SetVReg(result_reg, kMinInt);
    215   } else {
    216     shadow_frame.SetVReg(result_reg, dividend / divisor);
    217   }
    218   return true;
    219 }
    220 
    221 // Handles rem-int, rem-int/2addr, rem-int/li16 and rem-int/lit8 instructions.
    222 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
    223 static inline bool DoIntRemainder(ShadowFrame& shadow_frame, size_t result_reg,
    224                                   int32_t dividend, int32_t divisor)
    225     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    226   const int32_t kMinInt = std::numeric_limits<int32_t>::min();
    227   if (UNLIKELY(divisor == 0)) {
    228     ThrowArithmeticExceptionDivideByZero();
    229     return false;
    230   }
    231   if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
    232     shadow_frame.SetVReg(result_reg, 0);
    233   } else {
    234     shadow_frame.SetVReg(result_reg, dividend % divisor);
    235   }
    236   return true;
    237 }
    238 
    239 // Handles div-long and div-long-2addr instructions.
    240 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
    241 static inline bool DoLongDivide(ShadowFrame& shadow_frame, size_t result_reg,
    242                                 int64_t dividend, int64_t divisor)
    243     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    244   const int64_t kMinLong = std::numeric_limits<int64_t>::min();
    245   if (UNLIKELY(divisor == 0)) {
    246     ThrowArithmeticExceptionDivideByZero();
    247     return false;
    248   }
    249   if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
    250     shadow_frame.SetVRegLong(result_reg, kMinLong);
    251   } else {
    252     shadow_frame.SetVRegLong(result_reg, dividend / divisor);
    253   }
    254   return true;
    255 }
    256 
    257 // Handles rem-long and rem-long-2addr instructions.
    258 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
    259 static inline bool DoLongRemainder(ShadowFrame& shadow_frame, size_t result_reg,
    260                                    int64_t dividend, int64_t divisor)
    261     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    262   const int64_t kMinLong = std::numeric_limits<int64_t>::min();
    263   if (UNLIKELY(divisor == 0)) {
    264     ThrowArithmeticExceptionDivideByZero();
    265     return false;
    266   }
    267   if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
    268     shadow_frame.SetVRegLong(result_reg, 0);
    269   } else {
    270     shadow_frame.SetVRegLong(result_reg, dividend % divisor);
    271   }
    272   return true;
    273 }
    274 
    275 // Handles filled-new-array and filled-new-array-range instructions.
    276 // Returns true on success, otherwise throws an exception and returns false.
    277 template <bool is_range, bool do_access_check, bool transaction_active>
    278 bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame,
    279                       Thread* self, JValue* result);
    280 
    281 // Handles packed-switch instruction.
    282 // Returns the branch offset to the next instruction to execute.
    283 static inline int32_t DoPackedSwitch(const Instruction* inst, const ShadowFrame& shadow_frame,
    284                                      uint16_t inst_data)
    285     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    286   DCHECK(inst->Opcode() == Instruction::PACKED_SWITCH);
    287   const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
    288   int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
    289   DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
    290   uint16_t size = switch_data[1];
    291   DCHECK_GT(size, 0);
    292   const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
    293   DCHECK(IsAligned<4>(keys));
    294   int32_t first_key = keys[0];
    295   const int32_t* targets = reinterpret_cast<const int32_t*>(&switch_data[4]);
    296   DCHECK(IsAligned<4>(targets));
    297   int32_t index = test_val - first_key;
    298   if (index >= 0 && index < size) {
    299     return targets[index];
    300   } else {
    301     // No corresponding value: move forward by 3 (size of PACKED_SWITCH).
    302     return 3;
    303   }
    304 }
    305 
    306 // Handles sparse-switch instruction.
    307 // Returns the branch offset to the next instruction to execute.
    308 static inline int32_t DoSparseSwitch(const Instruction* inst, const ShadowFrame& shadow_frame,
    309                                      uint16_t inst_data)
    310     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    311   DCHECK(inst->Opcode() == Instruction::SPARSE_SWITCH);
    312   const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
    313   int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
    314   DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
    315   uint16_t size = switch_data[1];
    316   DCHECK_GT(size, 0);
    317   const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
    318   DCHECK(IsAligned<4>(keys));
    319   const int32_t* entries = keys + size;
    320   DCHECK(IsAligned<4>(entries));
    321   int lo = 0;
    322   int hi = size - 1;
    323   while (lo <= hi) {
    324     int mid = (lo + hi) / 2;
    325     int32_t foundVal = keys[mid];
    326     if (test_val < foundVal) {
    327       hi = mid - 1;
    328     } else if (test_val > foundVal) {
    329       lo = mid + 1;
    330     } else {
    331       return entries[mid];
    332     }
    333   }
    334   // No corresponding value: move forward by 3 (size of SPARSE_SWITCH).
    335   return 3;
    336 }
    337 
    338 uint32_t FindNextInstructionFollowingException(Thread* self, ShadowFrame& shadow_frame,
    339     uint32_t dex_pc, const instrumentation::Instrumentation* instrumentation)
    340         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    341 
    342 void UnexpectedOpcode(const Instruction* inst, MethodHelper& mh)
    343   __attribute__((cold, noreturn))
    344   SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    345 
    346 static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruction* inst,
    347                                   const uint32_t dex_pc, MethodHelper& mh)
    348     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    349   constexpr bool kTracing = false;
    350   if (kTracing) {
    351 #define TRACE_LOG std::cerr
    352     std::ostringstream oss;
    353     oss << PrettyMethod(shadow_frame.GetMethod())
    354         << StringPrintf("\n0x%x: ", dex_pc)
    355         << inst->DumpString(mh.GetMethod()->GetDexFile()) << "\n";
    356     for (uint32_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
    357       uint32_t raw_value = shadow_frame.GetVReg(i);
    358       Object* ref_value = shadow_frame.GetVRegReference(i);
    359       oss << StringPrintf(" vreg%u=0x%08X", i, raw_value);
    360       if (ref_value != NULL) {
    361         if (ref_value->GetClass()->IsStringClass() &&
    362             ref_value->AsString()->GetCharArray() != NULL) {
    363           oss << "/java.lang.String \"" << ref_value->AsString()->ToModifiedUtf8() << "\"";
    364         } else {
    365           oss << "/" << PrettyTypeOf(ref_value);
    366         }
    367       }
    368     }
    369     TRACE_LOG << oss.str() << "\n";
    370 #undef TRACE_LOG
    371   }
    372 }
    373 
    374 static inline bool IsBackwardBranch(int32_t branch_offset) {
    375   return branch_offset <= 0;
    376 }
    377 
    378 // Explicitly instantiate all DoInvoke functions.
    379 #define EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, _is_range, _do_check)                      \
    380   template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)                                     \
    381   bool DoInvoke<_type, _is_range, _do_check>(Thread* self, ShadowFrame& shadow_frame,      \
    382                                              const Instruction* inst, uint16_t inst_data,  \
    383                                              JValue* result)
    384 
    385 #define EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(_type)       \
    386   EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, false, false);  \
    387   EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, false, true);   \
    388   EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, true, false);   \
    389   EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, true, true);
    390 
    391 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kStatic);      // invoke-static/range.
    392 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kDirect);      // invoke-direct/range.
    393 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kVirtual);     // invoke-virtual/range.
    394 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kSuper);       // invoke-super/range.
    395 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kInterface);   // invoke-interface/range.
    396 #undef EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL
    397 #undef EXPLICIT_DO_INVOKE_TEMPLATE_DECL
    398 
    399 // Explicitly instantiate all DoInvokeVirtualQuick functions.
    400 #define EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(_is_range)                    \
    401   template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)                               \
    402   bool DoInvokeVirtualQuick<_is_range>(Thread* self, ShadowFrame& shadow_frame,      \
    403                                        const Instruction* inst, uint16_t inst_data,  \
    404                                        JValue* result)
    405 
    406 EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(false);  // invoke-virtual-quick.
    407 EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(true);   // invoke-virtual-quick-range.
    408 #undef EXPLICIT_INSTANTIATION_DO_INVOKE_VIRTUAL_QUICK
    409 
    410 
    411 }  // namespace interpreter
    412 }  // namespace art
    413 
    414 #endif  // ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
    415