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