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 <iostream> 25 #include <sstream> 26 27 #include "art_field-inl.h" 28 #include "art_method-inl.h" 29 #include "base/logging.h" 30 #include "base/macros.h" 31 #include "class_linker-inl.h" 32 #include "common_throws.h" 33 #include "dex_file-inl.h" 34 #include "dex_instruction-inl.h" 35 #include "entrypoints/entrypoint_utils-inl.h" 36 #include "handle_scope-inl.h" 37 #include "jit/jit.h" 38 #include "lambda/art_lambda_method.h" 39 #include "lambda/box_table.h" 40 #include "lambda/closure.h" 41 #include "lambda/closure_builder-inl.h" 42 #include "lambda/leaking_allocator.h" 43 #include "lambda/shorty_field_type.h" 44 #include "mirror/class-inl.h" 45 #include "mirror/method.h" 46 #include "mirror/object-inl.h" 47 #include "mirror/object_array-inl.h" 48 #include "mirror/string-inl.h" 49 #include "stack.h" 50 #include "thread.h" 51 #include "well_known_classes.h" 52 53 using ::art::ArtMethod; 54 using ::art::mirror::Array; 55 using ::art::mirror::BooleanArray; 56 using ::art::mirror::ByteArray; 57 using ::art::mirror::CharArray; 58 using ::art::mirror::Class; 59 using ::art::mirror::ClassLoader; 60 using ::art::mirror::IntArray; 61 using ::art::mirror::LongArray; 62 using ::art::mirror::Object; 63 using ::art::mirror::ObjectArray; 64 using ::art::mirror::ShortArray; 65 using ::art::mirror::String; 66 using ::art::mirror::Throwable; 67 68 namespace art { 69 namespace interpreter { 70 71 // External references to all interpreter implementations. 72 73 template<bool do_access_check, bool transaction_active> 74 extern JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item, 75 ShadowFrame& shadow_frame, JValue result_register, 76 bool interpret_one_instruction); 77 78 template<bool do_access_check, bool transaction_active> 79 extern JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, 80 ShadowFrame& shadow_frame, JValue result_register); 81 82 // Mterp does not support transactions or access check, thus no templated versions. 83 extern "C" bool ExecuteMterpImpl(Thread* self, const DexFile::CodeItem* code_item, 84 ShadowFrame* shadow_frame, JValue* result_register); 85 86 void ThrowNullPointerExceptionFromInterpreter() 87 SHARED_REQUIRES(Locks::mutator_lock_); 88 89 template <bool kMonitorCounting> 90 static inline void DoMonitorEnter(Thread* self, 91 ShadowFrame* frame, 92 Object* ref) 93 NO_THREAD_SAFETY_ANALYSIS 94 REQUIRES(!Roles::uninterruptible_) { 95 StackHandleScope<1> hs(self); 96 Handle<Object> h_ref(hs.NewHandle(ref)); 97 h_ref->MonitorEnter(self); 98 if (kMonitorCounting && frame->GetMethod()->MustCountLocks()) { 99 frame->GetLockCountData().AddMonitor(self, h_ref.Get()); 100 } 101 } 102 103 template <bool kMonitorCounting> 104 static inline void DoMonitorExit(Thread* self, 105 ShadowFrame* frame, 106 Object* ref) 107 NO_THREAD_SAFETY_ANALYSIS 108 REQUIRES(!Roles::uninterruptible_) { 109 StackHandleScope<1> hs(self); 110 Handle<Object> h_ref(hs.NewHandle(ref)); 111 h_ref->MonitorExit(self); 112 if (kMonitorCounting && frame->GetMethod()->MustCountLocks()) { 113 frame->GetLockCountData().RemoveMonitorOrThrow(self, h_ref.Get()); 114 } 115 } 116 117 template <bool kMonitorCounting> 118 static inline bool DoMonitorCheckOnExit(Thread* self, ShadowFrame* frame) 119 NO_THREAD_SAFETY_ANALYSIS 120 REQUIRES(!Roles::uninterruptible_) { 121 if (kMonitorCounting && frame->GetMethod()->MustCountLocks()) { 122 return frame->GetLockCountData().CheckAllMonitorsReleasedOrThrow(self); 123 } 124 return true; 125 } 126 127 void AbortTransactionF(Thread* self, const char* fmt, ...) 128 __attribute__((__format__(__printf__, 2, 3))) 129 SHARED_REQUIRES(Locks::mutator_lock_); 130 131 void AbortTransactionV(Thread* self, const char* fmt, va_list args) 132 SHARED_REQUIRES(Locks::mutator_lock_); 133 134 void RecordArrayElementsInTransaction(mirror::Array* array, int32_t count) 135 SHARED_REQUIRES(Locks::mutator_lock_); 136 137 // Invokes the given method. This is part of the invocation support and is used by DoInvoke and 138 // DoInvokeVirtualQuick functions. 139 // Returns true on success, otherwise throws an exception and returns false. 140 template<bool is_range, bool do_assignability_check> 141 bool DoCall(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame, 142 const Instruction* inst, uint16_t inst_data, JValue* result); 143 144 // Invokes the given lambda closure. This is part of the invocation support and is used by 145 // DoLambdaInvoke functions. 146 // Returns true on success, otherwise throws an exception and returns false. 147 template<bool is_range, bool do_assignability_check> 148 bool DoLambdaCall(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame, 149 const Instruction* inst, uint16_t inst_data, JValue* result); 150 151 // Validates that the art method corresponding to a lambda method target 152 // is semantically valid: 153 // 154 // Must be ACC_STATIC and ACC_LAMBDA. Must be a concrete managed implementation 155 // (i.e. not native, not proxy, not abstract, ...). 156 // 157 // If the validation fails, return false and raise an exception. 158 static inline bool IsValidLambdaTargetOrThrow(ArtMethod* called_method) 159 SHARED_REQUIRES(Locks::mutator_lock_) { 160 bool success = false; 161 162 if (UNLIKELY(called_method == nullptr)) { 163 // The shadow frame should already be pushed, so we don't need to update it. 164 } else if (UNLIKELY(!called_method->IsInvokable())) { 165 called_method->ThrowInvocationTimeError(); 166 // We got an error. 167 // TODO(iam): Also handle the case when the method is non-static, what error do we throw? 168 // TODO(iam): Also make sure that ACC_LAMBDA is set. 169 } else if (UNLIKELY(called_method->GetCodeItem() == nullptr)) { 170 // Method could be native, proxy method, etc. Lambda targets have to be concrete impls, 171 // so don't allow this. 172 } else { 173 success = true; 174 } 175 176 return success; 177 } 178 179 // Write out the 'Closure*' into vreg and vreg+1, as if it was a jlong. 180 static inline void WriteLambdaClosureIntoVRegs(ShadowFrame& shadow_frame, 181 const lambda::Closure& lambda_closure, 182 uint32_t vreg) { 183 // Split the method into a lo and hi 32 bits so we can encode them into 2 virtual registers. 184 uint32_t closure_lo = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(&lambda_closure)); 185 uint32_t closure_hi = static_cast<uint32_t>(reinterpret_cast<uint64_t>(&lambda_closure) 186 >> BitSizeOf<uint32_t>()); 187 // Use uint64_t instead of uintptr_t to allow shifting past the max on 32-bit. 188 static_assert(sizeof(uint64_t) >= sizeof(uintptr_t), "Impossible"); 189 190 DCHECK_NE(closure_lo | closure_hi, 0u); 191 192 shadow_frame.SetVReg(vreg, closure_lo); 193 shadow_frame.SetVReg(vreg + 1, closure_hi); 194 } 195 196 // Handles create-lambda instructions. 197 // Returns true on success, otherwise throws an exception and returns false. 198 // (Exceptions are thrown by creating a new exception and then being put in the thread TLS) 199 // 200 // The closure must be allocated big enough to hold the data, and should not be 201 // pre-initialized. It is initialized with the actual captured variables as a side-effect, 202 // although this should be unimportant to the caller since this function also handles storing it to 203 // the ShadowFrame. 204 // 205 // As a work-in-progress implementation, this shoves the ArtMethod object corresponding 206 // to the target dex method index into the target register vA and vA + 1. 207 template<bool do_access_check> 208 static inline bool DoCreateLambda(Thread* self, 209 const Instruction* inst, 210 /*inout*/ShadowFrame& shadow_frame, 211 /*inout*/lambda::ClosureBuilder* closure_builder, 212 /*inout*/lambda::Closure* uninitialized_closure) { 213 DCHECK(closure_builder != nullptr); 214 DCHECK(uninitialized_closure != nullptr); 215 DCHECK_ALIGNED(uninitialized_closure, alignof(lambda::Closure)); 216 217 using lambda::ArtLambdaMethod; 218 using lambda::LeakingAllocator; 219 220 /* 221 * create-lambda is opcode 0x21c 222 * - vA is the target register where the closure will be stored into 223 * (also stores into vA + 1) 224 * - vB is the method index which will be the target for a later invoke-lambda 225 */ 226 const uint32_t method_idx = inst->VRegB_21c(); 227 mirror::Object* receiver = nullptr; // Always static. (see 'kStatic') 228 ArtMethod* sf_method = shadow_frame.GetMethod(); 229 ArtMethod* const called_method = FindMethodFromCode<kStatic, do_access_check>( 230 method_idx, &receiver, sf_method, self); 231 232 uint32_t vreg_dest_closure = inst->VRegA_21c(); 233 234 if (UNLIKELY(!IsValidLambdaTargetOrThrow(called_method))) { 235 CHECK(self->IsExceptionPending()); 236 shadow_frame.SetVReg(vreg_dest_closure, 0u); 237 shadow_frame.SetVReg(vreg_dest_closure + 1, 0u); 238 return false; 239 } 240 241 ArtLambdaMethod* initialized_lambda_method; 242 // Initialize the ArtLambdaMethod with the right data. 243 { 244 // Allocate enough memory to store a well-aligned ArtLambdaMethod. 245 // This is not the final type yet since the data starts out uninitialized. 246 LeakingAllocator::AlignedMemoryStorage<ArtLambdaMethod>* uninitialized_lambda_method = 247 LeakingAllocator::AllocateMemory<ArtLambdaMethod>(self); 248 249 std::string captured_variables_shorty = closure_builder->GetCapturedVariableShortyTypes(); 250 std::string captured_variables_long_type_desc; 251 252 // Synthesize a long type descriptor from the short one. 253 for (char shorty : captured_variables_shorty) { 254 lambda::ShortyFieldType shorty_field_type(shorty); 255 if (shorty_field_type.IsObject()) { 256 // Not the true type, but good enough until we implement verifier support. 257 captured_variables_long_type_desc += "Ljava/lang/Object;"; 258 UNIMPLEMENTED(FATAL) << "create-lambda with an object captured variable"; 259 } else if (shorty_field_type.IsLambda()) { 260 // Not the true type, but good enough until we implement verifier support. 261 captured_variables_long_type_desc += "Ljava/lang/Runnable;"; 262 UNIMPLEMENTED(FATAL) << "create-lambda with a lambda captured variable"; 263 } else { 264 // The primitive types have the same length shorty or not, so this is always correct. 265 DCHECK(shorty_field_type.IsPrimitive()); 266 captured_variables_long_type_desc += shorty_field_type; 267 } 268 } 269 270 // Copy strings to dynamically allocated storage. This leaks, but that's ok. Fix it later. 271 // TODO: Strings need to come from the DexFile, so they won't need their own allocations. 272 char* captured_variables_type_desc = LeakingAllocator::MakeFlexibleInstance<char>( 273 self, 274 captured_variables_long_type_desc.size() + 1); 275 strcpy(captured_variables_type_desc, captured_variables_long_type_desc.c_str()); 276 char* captured_variables_shorty_copy = LeakingAllocator::MakeFlexibleInstance<char>( 277 self, 278 captured_variables_shorty.size() + 1); 279 strcpy(captured_variables_shorty_copy, captured_variables_shorty.c_str()); 280 281 // After initialization, the object at the storage is well-typed. Use strong type going forward. 282 initialized_lambda_method = 283 new (uninitialized_lambda_method) ArtLambdaMethod(called_method, 284 captured_variables_type_desc, 285 captured_variables_shorty_copy, 286 true); // innate lambda 287 } 288 289 // Write all the closure captured variables and the closure header into the closure. 290 lambda::Closure* initialized_closure = 291 closure_builder->CreateInPlace(uninitialized_closure, initialized_lambda_method); 292 293 WriteLambdaClosureIntoVRegs(/*inout*/shadow_frame, *initialized_closure, vreg_dest_closure); 294 return true; 295 } 296 297 // Reads out the 'ArtMethod*' stored inside of vreg and vreg+1 298 // 299 // Validates that the art method points to a valid lambda function, otherwise throws 300 // an exception and returns null. 301 // (Exceptions are thrown by creating a new exception and then being put in the thread TLS) 302 static inline lambda::Closure* ReadLambdaClosureFromVRegsOrThrow(ShadowFrame& shadow_frame, 303 uint32_t vreg) 304 SHARED_REQUIRES(Locks::mutator_lock_) { 305 // Lambda closures take up a consecutive pair of 2 virtual registers. 306 // On 32-bit the high bits are always 0. 307 uint32_t vc_value_lo = shadow_frame.GetVReg(vreg); 308 uint32_t vc_value_hi = shadow_frame.GetVReg(vreg + 1); 309 310 uint64_t vc_value_ptr = (static_cast<uint64_t>(vc_value_hi) << BitSizeOf<uint32_t>()) 311 | vc_value_lo; 312 313 // Use uint64_t instead of uintptr_t to allow left-shifting past the max on 32-bit. 314 static_assert(sizeof(uint64_t) >= sizeof(uintptr_t), "Impossible"); 315 lambda::Closure* const lambda_closure = reinterpret_cast<lambda::Closure*>(vc_value_ptr); 316 DCHECK_ALIGNED(lambda_closure, alignof(lambda::Closure)); 317 318 // Guard against the user passing a null closure, which is odd but (sadly) semantically valid. 319 if (UNLIKELY(lambda_closure == nullptr)) { 320 ThrowNullPointerExceptionFromInterpreter(); 321 return nullptr; 322 } else if (UNLIKELY(!IsValidLambdaTargetOrThrow(lambda_closure->GetTargetMethod()))) { 323 // Sanity check against data corruption. 324 return nullptr; 325 } 326 327 return lambda_closure; 328 } 329 330 // Forward declaration for lock annotations. See below for documentation. 331 template <bool do_access_check> 332 static inline const char* GetStringDataByDexStringIndexOrThrow(ShadowFrame& shadow_frame, 333 uint32_t string_idx) 334 SHARED_REQUIRES(Locks::mutator_lock_); 335 336 // Find the c-string data corresponding to a dex file's string index. 337 // Otherwise, returns null if not found and throws a VerifyError. 338 // 339 // Note that with do_access_check=false, we never return null because the verifier 340 // must guard against invalid string indices. 341 // (Exceptions are thrown by creating a new exception and then being put in the thread TLS) 342 template <bool do_access_check> 343 static inline const char* GetStringDataByDexStringIndexOrThrow(ShadowFrame& shadow_frame, 344 uint32_t string_idx) { 345 ArtMethod* method = shadow_frame.GetMethod(); 346 const DexFile* dex_file = method->GetDexFile(); 347 348 mirror::Class* declaring_class = method->GetDeclaringClass(); 349 if (!do_access_check) { 350 // MethodVerifier refuses methods with string_idx out of bounds. 351 DCHECK_LT(string_idx, declaring_class->GetDexCache()->NumStrings()); 352 } else { 353 // Access checks enabled: perform string index bounds ourselves. 354 if (string_idx >= dex_file->GetHeader().string_ids_size_) { 355 ThrowVerifyError(declaring_class, "String index '%" PRIu32 "' out of bounds", 356 string_idx); 357 return nullptr; 358 } 359 } 360 361 const char* type_string = dex_file->StringDataByIdx(string_idx); 362 363 if (UNLIKELY(type_string == nullptr)) { 364 CHECK_EQ(false, do_access_check) 365 << " verifier should've caught invalid string index " << string_idx; 366 CHECK_EQ(true, do_access_check) 367 << " string idx size check should've caught invalid string index " << string_idx; 368 } 369 370 return type_string; 371 } 372 373 // Handles capture-variable instructions. 374 // Returns true on success, otherwise throws an exception and returns false. 375 // (Exceptions are thrown by creating a new exception and then being put in the thread TLS) 376 template<bool do_access_check> 377 static inline bool DoCaptureVariable(Thread* self, 378 const Instruction* inst, 379 /*inout*/ShadowFrame& shadow_frame, 380 /*inout*/lambda::ClosureBuilder* closure_builder) { 381 DCHECK(closure_builder != nullptr); 382 using lambda::ShortyFieldType; 383 /* 384 * capture-variable is opcode 0xf6, fmt 0x21c 385 * - vA is the source register of the variable that will be captured 386 * - vB is the string ID of the variable's type that will be captured 387 */ 388 const uint32_t source_vreg = inst->VRegA_21c(); 389 const uint32_t string_idx = inst->VRegB_21c(); 390 // TODO: this should be a proper [type id] instead of a [string ID] pointing to a type. 391 392 const char* type_string = GetStringDataByDexStringIndexOrThrow<do_access_check>(shadow_frame, 393 string_idx); 394 if (UNLIKELY(type_string == nullptr)) { 395 CHECK(self->IsExceptionPending()); 396 return false; 397 } 398 399 char type_first_letter = type_string[0]; 400 ShortyFieldType shorty_type; 401 if (do_access_check && 402 UNLIKELY(!ShortyFieldType::MaybeCreate(type_first_letter, /*out*/&shorty_type))) { // NOLINT: [whitespace/comma] [3] 403 ThrowVerifyError(shadow_frame.GetMethod()->GetDeclaringClass(), 404 "capture-variable vB must be a valid type"); 405 return false; 406 } else { 407 // Already verified that the type is valid. 408 shorty_type = ShortyFieldType(type_first_letter); 409 } 410 411 const size_t captured_variable_count = closure_builder->GetCaptureCount(); 412 413 // Note: types are specified explicitly so that the closure is packed tightly. 414 switch (shorty_type) { 415 case ShortyFieldType::kBoolean: { 416 uint32_t primitive_narrow_value = shadow_frame.GetVReg(source_vreg); 417 closure_builder->CaptureVariablePrimitive<bool>(primitive_narrow_value); 418 break; 419 } 420 case ShortyFieldType::kByte: { 421 uint32_t primitive_narrow_value = shadow_frame.GetVReg(source_vreg); 422 closure_builder->CaptureVariablePrimitive<int8_t>(primitive_narrow_value); 423 break; 424 } 425 case ShortyFieldType::kChar: { 426 uint32_t primitive_narrow_value = shadow_frame.GetVReg(source_vreg); 427 closure_builder->CaptureVariablePrimitive<uint16_t>(primitive_narrow_value); 428 break; 429 } 430 case ShortyFieldType::kShort: { 431 uint32_t primitive_narrow_value = shadow_frame.GetVReg(source_vreg); 432 closure_builder->CaptureVariablePrimitive<int16_t>(primitive_narrow_value); 433 break; 434 } 435 case ShortyFieldType::kInt: { 436 uint32_t primitive_narrow_value = shadow_frame.GetVReg(source_vreg); 437 closure_builder->CaptureVariablePrimitive<int32_t>(primitive_narrow_value); 438 break; 439 } 440 case ShortyFieldType::kDouble: { 441 closure_builder->CaptureVariablePrimitive(shadow_frame.GetVRegDouble(source_vreg)); 442 break; 443 } 444 case ShortyFieldType::kFloat: { 445 closure_builder->CaptureVariablePrimitive(shadow_frame.GetVRegFloat(source_vreg)); 446 break; 447 } 448 case ShortyFieldType::kLambda: { 449 UNIMPLEMENTED(FATAL) << " capture-variable with type kLambda"; 450 // TODO: Capturing lambdas recursively will be done at a later time. 451 UNREACHABLE(); 452 } 453 case ShortyFieldType::kLong: { 454 closure_builder->CaptureVariablePrimitive(shadow_frame.GetVRegLong(source_vreg)); 455 break; 456 } 457 case ShortyFieldType::kObject: { 458 closure_builder->CaptureVariableObject(shadow_frame.GetVRegReference(source_vreg)); 459 UNIMPLEMENTED(FATAL) << " capture-variable with type kObject"; 460 // TODO: finish implementing this. disabled for now since we can't track lambda refs for GC. 461 UNREACHABLE(); 462 } 463 464 default: 465 LOG(FATAL) << "Invalid shorty type value " << shorty_type; 466 UNREACHABLE(); 467 } 468 469 DCHECK_EQ(captured_variable_count + 1, closure_builder->GetCaptureCount()); 470 471 return true; 472 } 473 474 // Handles capture-variable instructions. 475 // Returns true on success, otherwise throws an exception and returns false. 476 // (Exceptions are thrown by creating a new exception and then being put in the thread TLS) 477 template<bool do_access_check> 478 static inline bool DoLiberateVariable(Thread* self, 479 const Instruction* inst, 480 size_t captured_variable_index, 481 /*inout*/ShadowFrame& shadow_frame) { 482 using lambda::ShortyFieldType; 483 /* 484 * liberate-variable is opcode 0xf7, fmt 0x22c 485 * - vA is the destination register 486 * - vB is the register with the lambda closure in it 487 * - vC is the string ID which needs to be a valid field type descriptor 488 */ 489 490 const uint32_t dest_vreg = inst->VRegA_22c(); 491 const uint32_t closure_vreg = inst->VRegB_22c(); 492 const uint32_t string_idx = inst->VRegC_22c(); 493 // TODO: this should be a proper [type id] instead of a [string ID] pointing to a type. 494 495 496 // Synthesize a long type descriptor from a shorty type descriptor list. 497 // TODO: Fix the dex encoding to contain the long and short type descriptors. 498 const char* type_string = GetStringDataByDexStringIndexOrThrow<do_access_check>(shadow_frame, 499 string_idx); 500 if (UNLIKELY(do_access_check && type_string == nullptr)) { 501 CHECK(self->IsExceptionPending()); 502 shadow_frame.SetVReg(dest_vreg, 0); 503 return false; 504 } 505 506 char type_first_letter = type_string[0]; 507 ShortyFieldType shorty_type; 508 if (do_access_check && 509 UNLIKELY(!ShortyFieldType::MaybeCreate(type_first_letter, /*out*/&shorty_type))) { // NOLINT: [whitespace/comma] [3] 510 ThrowVerifyError(shadow_frame.GetMethod()->GetDeclaringClass(), 511 "liberate-variable vC must be a valid type"); 512 shadow_frame.SetVReg(dest_vreg, 0); 513 return false; 514 } else { 515 // Already verified that the type is valid. 516 shorty_type = ShortyFieldType(type_first_letter); 517 } 518 519 // Check for closure being null *after* the type check. 520 // This way we can access the type info in case we fail later, to know how many vregs to clear. 521 const lambda::Closure* lambda_closure = 522 ReadLambdaClosureFromVRegsOrThrow(/*inout*/shadow_frame, closure_vreg); 523 524 // Failed lambda target runtime check, an exception was raised. 525 if (UNLIKELY(lambda_closure == nullptr)) { 526 CHECK(self->IsExceptionPending()); 527 528 // Clear the destination vreg(s) to be safe. 529 shadow_frame.SetVReg(dest_vreg, 0); 530 if (shorty_type.IsPrimitiveWide() || shorty_type.IsLambda()) { 531 shadow_frame.SetVReg(dest_vreg + 1, 0); 532 } 533 return false; 534 } 535 536 if (do_access_check && 537 UNLIKELY(captured_variable_index >= lambda_closure->GetNumberOfCapturedVariables())) { 538 ThrowVerifyError(shadow_frame.GetMethod()->GetDeclaringClass(), 539 "liberate-variable captured variable index %zu out of bounds", 540 lambda_closure->GetNumberOfCapturedVariables()); 541 // Clear the destination vreg(s) to be safe. 542 shadow_frame.SetVReg(dest_vreg, 0); 543 if (shorty_type.IsPrimitiveWide() || shorty_type.IsLambda()) { 544 shadow_frame.SetVReg(dest_vreg + 1, 0); 545 } 546 return false; 547 } 548 549 // Verify that the runtime type of the captured-variable matches the requested dex type. 550 if (do_access_check) { 551 ShortyFieldType actual_type = lambda_closure->GetCapturedShortyType(captured_variable_index); 552 if (actual_type != shorty_type) { 553 ThrowVerifyError(shadow_frame.GetMethod()->GetDeclaringClass(), 554 "cannot liberate-variable of runtime type '%c' to dex type '%c'", 555 static_cast<char>(actual_type), 556 static_cast<char>(shorty_type)); 557 558 shadow_frame.SetVReg(dest_vreg, 0); 559 if (shorty_type.IsPrimitiveWide() || shorty_type.IsLambda()) { 560 shadow_frame.SetVReg(dest_vreg + 1, 0); 561 } 562 return false; 563 } 564 565 if (actual_type.IsLambda() || actual_type.IsObject()) { 566 UNIMPLEMENTED(FATAL) << "liberate-variable type checks needs to " 567 << "parse full type descriptor for objects and lambdas"; 568 } 569 } 570 571 // Unpack the captured variable from the closure into the correct type, then save it to the vreg. 572 if (shorty_type.IsPrimitiveNarrow()) { 573 uint32_t primitive_narrow_value = 574 lambda_closure->GetCapturedPrimitiveNarrow(captured_variable_index); 575 shadow_frame.SetVReg(dest_vreg, primitive_narrow_value); 576 } else if (shorty_type.IsPrimitiveWide()) { 577 uint64_t primitive_wide_value = 578 lambda_closure->GetCapturedPrimitiveWide(captured_variable_index); 579 shadow_frame.SetVRegLong(dest_vreg, static_cast<int64_t>(primitive_wide_value)); 580 } else if (shorty_type.IsObject()) { 581 mirror::Object* unpacked_object = 582 lambda_closure->GetCapturedObject(captured_variable_index); 583 shadow_frame.SetVRegReference(dest_vreg, unpacked_object); 584 585 UNIMPLEMENTED(FATAL) << "liberate-variable cannot unpack objects yet"; 586 } else if (shorty_type.IsLambda()) { 587 UNIMPLEMENTED(FATAL) << "liberate-variable cannot unpack lambdas yet"; 588 } else { 589 LOG(FATAL) << "unreachable"; 590 UNREACHABLE(); 591 } 592 593 return true; 594 } 595 596 template<bool do_access_check> 597 static inline bool DoInvokeLambda(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst, 598 uint16_t inst_data, JValue* result) { 599 /* 600 * invoke-lambda is opcode 0x25 601 * 602 * - vC is the closure register (both vC and vC + 1 will be used to store the closure). 603 * - vB is the number of additional registers up to |{vD,vE,vF,vG}| (4) 604 * - the rest of the registers are always var-args 605 * 606 * - reading var-args for 0x25 gets us vD,vE,vF,vG (but not vB) 607 */ 608 uint32_t vreg_closure = inst->VRegC_25x(); 609 const lambda::Closure* lambda_closure = 610 ReadLambdaClosureFromVRegsOrThrow(shadow_frame, vreg_closure); 611 612 // Failed lambda target runtime check, an exception was raised. 613 if (UNLIKELY(lambda_closure == nullptr)) { 614 CHECK(self->IsExceptionPending()); 615 result->SetJ(0); 616 return false; 617 } 618 619 ArtMethod* const called_method = lambda_closure->GetTargetMethod(); 620 // Invoke a non-range lambda 621 return DoLambdaCall<false, do_access_check>(called_method, self, shadow_frame, inst, inst_data, 622 result); 623 } 624 625 // Handles invoke-XXX/range instructions (other than invoke-lambda[-range]). 626 // Returns true on success, otherwise throws an exception and returns false. 627 template<InvokeType type, bool is_range, bool do_access_check> 628 static inline bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst, 629 uint16_t inst_data, JValue* result) { 630 const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c(); 631 const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c(); 632 Object* receiver = (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC); 633 ArtMethod* sf_method = shadow_frame.GetMethod(); 634 ArtMethod* const called_method = FindMethodFromCode<type, do_access_check>( 635 method_idx, &receiver, sf_method, self); 636 // The shadow frame should already be pushed, so we don't need to update it. 637 if (UNLIKELY(called_method == nullptr)) { 638 CHECK(self->IsExceptionPending()); 639 result->SetJ(0); 640 return false; 641 } else if (UNLIKELY(!called_method->IsInvokable())) { 642 called_method->ThrowInvocationTimeError(); 643 result->SetJ(0); 644 return false; 645 } else { 646 jit::Jit* jit = Runtime::Current()->GetJit(); 647 if (jit != nullptr) { 648 if (type == kVirtual || type == kInterface) { 649 jit->InvokeVirtualOrInterface( 650 self, receiver, sf_method, shadow_frame.GetDexPC(), called_method); 651 } 652 jit->AddSamples(self, sf_method, 1, /*with_backedges*/false); 653 } 654 // TODO: Remove the InvokeVirtualOrInterface instrumentation, as it was only used by the JIT. 655 if (type == kVirtual || type == kInterface) { 656 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); 657 if (UNLIKELY(instrumentation->HasInvokeVirtualOrInterfaceListeners())) { 658 instrumentation->InvokeVirtualOrInterface( 659 self, receiver, sf_method, shadow_frame.GetDexPC(), called_method); 660 } 661 } 662 return DoCall<is_range, do_access_check>(called_method, self, shadow_frame, inst, inst_data, 663 result); 664 } 665 } 666 667 // Handles invoke-virtual-quick and invoke-virtual-quick-range instructions. 668 // Returns true on success, otherwise throws an exception and returns false. 669 template<bool is_range> 670 static inline bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame, 671 const Instruction* inst, uint16_t inst_data, 672 JValue* result) { 673 const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c(); 674 Object* const receiver = shadow_frame.GetVRegReference(vregC); 675 if (UNLIKELY(receiver == nullptr)) { 676 // We lost the reference to the method index so we cannot get a more 677 // precised exception message. 678 ThrowNullPointerExceptionFromDexPC(); 679 return false; 680 } 681 const uint32_t vtable_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c(); 682 CHECK(receiver->GetClass()->ShouldHaveEmbeddedVTable()); 683 ArtMethod* const called_method = receiver->GetClass()->GetEmbeddedVTableEntry( 684 vtable_idx, sizeof(void*)); 685 if (UNLIKELY(called_method == nullptr)) { 686 CHECK(self->IsExceptionPending()); 687 result->SetJ(0); 688 return false; 689 } else if (UNLIKELY(!called_method->IsInvokable())) { 690 called_method->ThrowInvocationTimeError(); 691 result->SetJ(0); 692 return false; 693 } else { 694 jit::Jit* jit = Runtime::Current()->GetJit(); 695 if (jit != nullptr) { 696 jit->InvokeVirtualOrInterface( 697 self, receiver, shadow_frame.GetMethod(), shadow_frame.GetDexPC(), called_method); 698 jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges*/false); 699 } 700 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); 701 // TODO: Remove the InvokeVirtualOrInterface instrumentation, as it was only used by the JIT. 702 if (UNLIKELY(instrumentation->HasInvokeVirtualOrInterfaceListeners())) { 703 instrumentation->InvokeVirtualOrInterface( 704 self, receiver, shadow_frame.GetMethod(), shadow_frame.GetDexPC(), called_method); 705 } 706 // No need to check since we've been quickened. 707 return DoCall<is_range, false>(called_method, self, shadow_frame, inst, inst_data, result); 708 } 709 } 710 711 // Handles iget-XXX and sget-XXX instructions. 712 // Returns true on success, otherwise throws an exception and returns false. 713 template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check> 714 bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst, 715 uint16_t inst_data) SHARED_REQUIRES(Locks::mutator_lock_); 716 717 // Handles iget-quick, iget-wide-quick and iget-object-quick instructions. 718 // Returns true on success, otherwise throws an exception and returns false. 719 template<Primitive::Type field_type> 720 bool DoIGetQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) 721 SHARED_REQUIRES(Locks::mutator_lock_); 722 723 // Handles iput-XXX and sput-XXX instructions. 724 // Returns true on success, otherwise throws an exception and returns false. 725 template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check, 726 bool transaction_active> 727 bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction* inst, 728 uint16_t inst_data) SHARED_REQUIRES(Locks::mutator_lock_); 729 730 // Handles iput-quick, iput-wide-quick and iput-object-quick instructions. 731 // Returns true on success, otherwise throws an exception and returns false. 732 template<Primitive::Type field_type, bool transaction_active> 733 bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) 734 SHARED_REQUIRES(Locks::mutator_lock_); 735 736 737 // Handles string resolution for const-string and const-string-jumbo instructions. Also ensures the 738 // java.lang.String class is initialized. 739 static inline String* ResolveString(Thread* self, ShadowFrame& shadow_frame, uint32_t string_idx) 740 SHARED_REQUIRES(Locks::mutator_lock_) { 741 Class* java_lang_string_class = String::GetJavaLangString(); 742 if (UNLIKELY(!java_lang_string_class->IsInitialized())) { 743 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 744 StackHandleScope<1> hs(self); 745 Handle<mirror::Class> h_class(hs.NewHandle(java_lang_string_class)); 746 if (UNLIKELY(!class_linker->EnsureInitialized(self, h_class, true, true))) { 747 DCHECK(self->IsExceptionPending()); 748 return nullptr; 749 } 750 } 751 ArtMethod* method = shadow_frame.GetMethod(); 752 mirror::Class* declaring_class = method->GetDeclaringClass(); 753 // MethodVerifier refuses methods with string_idx out of bounds. 754 DCHECK_LT(string_idx, declaring_class->GetDexCache()->NumStrings()); 755 mirror::String* s = declaring_class->GetDexCacheStrings()[string_idx].Read(); 756 if (UNLIKELY(s == nullptr)) { 757 StackHandleScope<1> hs(self); 758 Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache())); 759 s = Runtime::Current()->GetClassLinker()->ResolveString(*method->GetDexFile(), string_idx, 760 dex_cache); 761 } 762 return s; 763 } 764 765 // Handles div-int, div-int/2addr, div-int/li16 and div-int/lit8 instructions. 766 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false. 767 static inline bool DoIntDivide(ShadowFrame& shadow_frame, size_t result_reg, 768 int32_t dividend, int32_t divisor) 769 SHARED_REQUIRES(Locks::mutator_lock_) { 770 constexpr int32_t kMinInt = std::numeric_limits<int32_t>::min(); 771 if (UNLIKELY(divisor == 0)) { 772 ThrowArithmeticExceptionDivideByZero(); 773 return false; 774 } 775 if (UNLIKELY(dividend == kMinInt && divisor == -1)) { 776 shadow_frame.SetVReg(result_reg, kMinInt); 777 } else { 778 shadow_frame.SetVReg(result_reg, dividend / divisor); 779 } 780 return true; 781 } 782 783 // Handles rem-int, rem-int/2addr, rem-int/li16 and rem-int/lit8 instructions. 784 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false. 785 static inline bool DoIntRemainder(ShadowFrame& shadow_frame, size_t result_reg, 786 int32_t dividend, int32_t divisor) 787 SHARED_REQUIRES(Locks::mutator_lock_) { 788 constexpr int32_t kMinInt = std::numeric_limits<int32_t>::min(); 789 if (UNLIKELY(divisor == 0)) { 790 ThrowArithmeticExceptionDivideByZero(); 791 return false; 792 } 793 if (UNLIKELY(dividend == kMinInt && divisor == -1)) { 794 shadow_frame.SetVReg(result_reg, 0); 795 } else { 796 shadow_frame.SetVReg(result_reg, dividend % divisor); 797 } 798 return true; 799 } 800 801 // Handles div-long and div-long-2addr instructions. 802 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false. 803 static inline bool DoLongDivide(ShadowFrame& shadow_frame, size_t result_reg, 804 int64_t dividend, int64_t divisor) 805 SHARED_REQUIRES(Locks::mutator_lock_) { 806 const int64_t kMinLong = std::numeric_limits<int64_t>::min(); 807 if (UNLIKELY(divisor == 0)) { 808 ThrowArithmeticExceptionDivideByZero(); 809 return false; 810 } 811 if (UNLIKELY(dividend == kMinLong && divisor == -1)) { 812 shadow_frame.SetVRegLong(result_reg, kMinLong); 813 } else { 814 shadow_frame.SetVRegLong(result_reg, dividend / divisor); 815 } 816 return true; 817 } 818 819 // Handles rem-long and rem-long-2addr instructions. 820 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false. 821 static inline bool DoLongRemainder(ShadowFrame& shadow_frame, size_t result_reg, 822 int64_t dividend, int64_t divisor) 823 SHARED_REQUIRES(Locks::mutator_lock_) { 824 const int64_t kMinLong = std::numeric_limits<int64_t>::min(); 825 if (UNLIKELY(divisor == 0)) { 826 ThrowArithmeticExceptionDivideByZero(); 827 return false; 828 } 829 if (UNLIKELY(dividend == kMinLong && divisor == -1)) { 830 shadow_frame.SetVRegLong(result_reg, 0); 831 } else { 832 shadow_frame.SetVRegLong(result_reg, dividend % divisor); 833 } 834 return true; 835 } 836 837 // Handles filled-new-array and filled-new-array-range instructions. 838 // Returns true on success, otherwise throws an exception and returns false. 839 template <bool is_range, bool do_access_check, bool transaction_active> 840 bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame, 841 Thread* self, JValue* result); 842 843 // Handles packed-switch instruction. 844 // Returns the branch offset to the next instruction to execute. 845 static inline int32_t DoPackedSwitch(const Instruction* inst, const ShadowFrame& shadow_frame, 846 uint16_t inst_data) 847 SHARED_REQUIRES(Locks::mutator_lock_) { 848 DCHECK(inst->Opcode() == Instruction::PACKED_SWITCH); 849 const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t(); 850 int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data)); 851 DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature)); 852 uint16_t size = switch_data[1]; 853 if (size == 0) { 854 // Empty packed switch, move forward by 3 (size of PACKED_SWITCH). 855 return 3; 856 } 857 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]); 858 DCHECK_ALIGNED(keys, 4); 859 int32_t first_key = keys[0]; 860 const int32_t* targets = reinterpret_cast<const int32_t*>(&switch_data[4]); 861 DCHECK_ALIGNED(targets, 4); 862 int32_t index = test_val - first_key; 863 if (index >= 0 && index < size) { 864 return targets[index]; 865 } else { 866 // No corresponding value: move forward by 3 (size of PACKED_SWITCH). 867 return 3; 868 } 869 } 870 871 // Handles sparse-switch instruction. 872 // Returns the branch offset to the next instruction to execute. 873 static inline int32_t DoSparseSwitch(const Instruction* inst, const ShadowFrame& shadow_frame, 874 uint16_t inst_data) 875 SHARED_REQUIRES(Locks::mutator_lock_) { 876 DCHECK(inst->Opcode() == Instruction::SPARSE_SWITCH); 877 const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t(); 878 int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data)); 879 DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature)); 880 uint16_t size = switch_data[1]; 881 // Return length of SPARSE_SWITCH if size is 0. 882 if (size == 0) { 883 return 3; 884 } 885 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]); 886 DCHECK_ALIGNED(keys, 4); 887 const int32_t* entries = keys + size; 888 DCHECK_ALIGNED(entries, 4); 889 int lo = 0; 890 int hi = size - 1; 891 while (lo <= hi) { 892 int mid = (lo + hi) / 2; 893 int32_t foundVal = keys[mid]; 894 if (test_val < foundVal) { 895 hi = mid - 1; 896 } else if (test_val > foundVal) { 897 lo = mid + 1; 898 } else { 899 return entries[mid]; 900 } 901 } 902 // No corresponding value: move forward by 3 (size of SPARSE_SWITCH). 903 return 3; 904 } 905 906 template <bool _do_check> 907 static inline bool DoBoxLambda(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst, 908 uint16_t inst_data) SHARED_REQUIRES(Locks::mutator_lock_) { 909 /* 910 * box-lambda vA, vB /// opcode 0xf8, format 22x 911 * - vA is the target register where the Object representation of the closure will be stored into 912 * - vB is a closure (made by create-lambda) 913 * (also reads vB + 1) 914 */ 915 uint32_t vreg_target_object = inst->VRegA_22x(inst_data); 916 uint32_t vreg_source_closure = inst->VRegB_22x(); 917 918 lambda::Closure* lambda_closure = ReadLambdaClosureFromVRegsOrThrow(shadow_frame, 919 vreg_source_closure); 920 921 // Failed lambda target runtime check, an exception was raised. 922 if (UNLIKELY(lambda_closure == nullptr)) { 923 CHECK(self->IsExceptionPending()); 924 return false; 925 } 926 927 mirror::Object* closure_as_object = 928 Runtime::Current()->GetLambdaBoxTable()->BoxLambda(lambda_closure); 929 930 // Failed to box the lambda, an exception was raised. 931 if (UNLIKELY(closure_as_object == nullptr)) { 932 CHECK(self->IsExceptionPending()); 933 return false; 934 } 935 936 shadow_frame.SetVRegReference(vreg_target_object, closure_as_object); 937 return true; 938 } 939 940 template <bool _do_check> SHARED_REQUIRES(Locks::mutator_lock_) 941 static inline bool DoUnboxLambda(Thread* self, 942 ShadowFrame& shadow_frame, 943 const Instruction* inst, 944 uint16_t inst_data) { 945 /* 946 * unbox-lambda vA, vB, [type id] /// opcode 0xf9, format 22c 947 * - vA is the target register where the closure will be written into 948 * (also writes vA + 1) 949 * - vB is the Object representation of the closure (made by box-lambda) 950 */ 951 uint32_t vreg_target_closure = inst->VRegA_22c(inst_data); 952 uint32_t vreg_source_object = inst->VRegB_22c(); 953 954 // Raise NullPointerException if object is null 955 mirror::Object* boxed_closure_object = shadow_frame.GetVRegReference(vreg_source_object); 956 if (UNLIKELY(boxed_closure_object == nullptr)) { 957 ThrowNullPointerExceptionFromInterpreter(); 958 return false; 959 } 960 961 lambda::Closure* unboxed_closure = nullptr; 962 // Raise an exception if unboxing fails. 963 if (!Runtime::Current()->GetLambdaBoxTable()->UnboxLambda(boxed_closure_object, 964 /*out*/&unboxed_closure)) { 965 CHECK(self->IsExceptionPending()); 966 return false; 967 } 968 969 DCHECK(unboxed_closure != nullptr); 970 WriteLambdaClosureIntoVRegs(/*inout*/shadow_frame, *unboxed_closure, vreg_target_closure); 971 return true; 972 } 973 974 uint32_t FindNextInstructionFollowingException(Thread* self, ShadowFrame& shadow_frame, 975 uint32_t dex_pc, const instrumentation::Instrumentation* instrumentation) 976 SHARED_REQUIRES(Locks::mutator_lock_); 977 978 NO_RETURN void UnexpectedOpcode(const Instruction* inst, const ShadowFrame& shadow_frame) 979 __attribute__((cold)) 980 SHARED_REQUIRES(Locks::mutator_lock_); 981 982 static inline bool TraceExecutionEnabled() { 983 // Return true if you want TraceExecution invocation before each bytecode execution. 984 return false; 985 } 986 987 static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruction* inst, 988 const uint32_t dex_pc) 989 SHARED_REQUIRES(Locks::mutator_lock_) { 990 if (TraceExecutionEnabled()) { 991 #define TRACE_LOG std::cerr 992 std::ostringstream oss; 993 oss << PrettyMethod(shadow_frame.GetMethod()) 994 << StringPrintf("\n0x%x: ", dex_pc) 995 << inst->DumpString(shadow_frame.GetMethod()->GetDexFile()) << "\n"; 996 for (uint32_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) { 997 uint32_t raw_value = shadow_frame.GetVReg(i); 998 Object* ref_value = shadow_frame.GetVRegReference(i); 999 oss << StringPrintf(" vreg%u=0x%08X", i, raw_value); 1000 if (ref_value != nullptr) { 1001 if (ref_value->GetClass()->IsStringClass() && 1002 ref_value->AsString()->GetValue() != nullptr) { 1003 oss << "/java.lang.String \"" << ref_value->AsString()->ToModifiedUtf8() << "\""; 1004 } else { 1005 oss << "/" << PrettyTypeOf(ref_value); 1006 } 1007 } 1008 } 1009 TRACE_LOG << oss.str() << "\n"; 1010 #undef TRACE_LOG 1011 } 1012 } 1013 1014 static inline bool IsBackwardBranch(int32_t branch_offset) { 1015 return branch_offset <= 0; 1016 } 1017 1018 void ArtInterpreterToCompiledCodeBridge(Thread* self, 1019 ArtMethod* caller, 1020 const DexFile::CodeItem* code_item, 1021 ShadowFrame* shadow_frame, 1022 JValue* result); 1023 1024 // Set string value created from StringFactory.newStringFromXXX() into all aliases of 1025 // StringFactory.newEmptyString(). 1026 void SetStringInitValueToAllAliases(ShadowFrame* shadow_frame, 1027 uint16_t this_obj_vreg, 1028 JValue result); 1029 1030 // Explicitly instantiate all DoInvoke functions. 1031 #define EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, _is_range, _do_check) \ 1032 template SHARED_REQUIRES(Locks::mutator_lock_) \ 1033 bool DoInvoke<_type, _is_range, _do_check>(Thread* self, ShadowFrame& shadow_frame, \ 1034 const Instruction* inst, uint16_t inst_data, \ 1035 JValue* result) 1036 1037 #define EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(_type) \ 1038 EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, false, false); \ 1039 EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, false, true); \ 1040 EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, true, false); \ 1041 EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, true, true); 1042 1043 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kStatic) // invoke-static/range. 1044 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kDirect) // invoke-direct/range. 1045 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kVirtual) // invoke-virtual/range. 1046 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kSuper) // invoke-super/range. 1047 EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kInterface) // invoke-interface/range. 1048 #undef EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL 1049 #undef EXPLICIT_DO_INVOKE_TEMPLATE_DECL 1050 1051 // Explicitly instantiate all DoInvokeVirtualQuick functions. 1052 #define EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(_is_range) \ 1053 template SHARED_REQUIRES(Locks::mutator_lock_) \ 1054 bool DoInvokeVirtualQuick<_is_range>(Thread* self, ShadowFrame& shadow_frame, \ 1055 const Instruction* inst, uint16_t inst_data, \ 1056 JValue* result) 1057 1058 EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(false); // invoke-virtual-quick. 1059 EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(true); // invoke-virtual-quick-range. 1060 #undef EXPLICIT_INSTANTIATION_DO_INVOKE_VIRTUAL_QUICK 1061 1062 // Explicitly instantiate all DoCreateLambda functions. 1063 #define EXPLICIT_DO_CREATE_LAMBDA_DECL(_do_check) \ 1064 template SHARED_REQUIRES(Locks::mutator_lock_) \ 1065 bool DoCreateLambda<_do_check>(Thread* self, \ 1066 const Instruction* inst, \ 1067 /*inout*/ShadowFrame& shadow_frame, \ 1068 /*inout*/lambda::ClosureBuilder* closure_builder, \ 1069 /*inout*/lambda::Closure* uninitialized_closure); 1070 1071 EXPLICIT_DO_CREATE_LAMBDA_DECL(false); // create-lambda 1072 EXPLICIT_DO_CREATE_LAMBDA_DECL(true); // create-lambda 1073 #undef EXPLICIT_DO_CREATE_LAMBDA_DECL 1074 1075 // Explicitly instantiate all DoInvokeLambda functions. 1076 #define EXPLICIT_DO_INVOKE_LAMBDA_DECL(_do_check) \ 1077 template SHARED_REQUIRES(Locks::mutator_lock_) \ 1078 bool DoInvokeLambda<_do_check>(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst, \ 1079 uint16_t inst_data, JValue* result); 1080 1081 EXPLICIT_DO_INVOKE_LAMBDA_DECL(false); // invoke-lambda 1082 EXPLICIT_DO_INVOKE_LAMBDA_DECL(true); // invoke-lambda 1083 #undef EXPLICIT_DO_INVOKE_LAMBDA_DECL 1084 1085 // Explicitly instantiate all DoBoxLambda functions. 1086 #define EXPLICIT_DO_BOX_LAMBDA_DECL(_do_check) \ 1087 template SHARED_REQUIRES(Locks::mutator_lock_) \ 1088 bool DoBoxLambda<_do_check>(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst, \ 1089 uint16_t inst_data); 1090 1091 EXPLICIT_DO_BOX_LAMBDA_DECL(false); // box-lambda 1092 EXPLICIT_DO_BOX_LAMBDA_DECL(true); // box-lambda 1093 #undef EXPLICIT_DO_BOX_LAMBDA_DECL 1094 1095 // Explicitly instantiate all DoUnBoxLambda functions. 1096 #define EXPLICIT_DO_UNBOX_LAMBDA_DECL(_do_check) \ 1097 template SHARED_REQUIRES(Locks::mutator_lock_) \ 1098 bool DoUnboxLambda<_do_check>(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst, \ 1099 uint16_t inst_data); 1100 1101 EXPLICIT_DO_UNBOX_LAMBDA_DECL(false); // unbox-lambda 1102 EXPLICIT_DO_UNBOX_LAMBDA_DECL(true); // unbox-lambda 1103 #undef EXPLICIT_DO_BOX_LAMBDA_DECL 1104 1105 // Explicitly instantiate all DoCaptureVariable functions. 1106 #define EXPLICIT_DO_CAPTURE_VARIABLE_DECL(_do_check) \ 1107 template SHARED_REQUIRES(Locks::mutator_lock_) \ 1108 bool DoCaptureVariable<_do_check>(Thread* self, \ 1109 const Instruction* inst, \ 1110 ShadowFrame& shadow_frame, \ 1111 lambda::ClosureBuilder* closure_builder); 1112 1113 EXPLICIT_DO_CAPTURE_VARIABLE_DECL(false); // capture-variable 1114 EXPLICIT_DO_CAPTURE_VARIABLE_DECL(true); // capture-variable 1115 #undef EXPLICIT_DO_CREATE_LAMBDA_DECL 1116 1117 // Explicitly instantiate all DoLiberateVariable functions. 1118 #define EXPLICIT_DO_LIBERATE_VARIABLE_DECL(_do_check) \ 1119 template SHARED_REQUIRES(Locks::mutator_lock_) \ 1120 bool DoLiberateVariable<_do_check>(Thread* self, \ 1121 const Instruction* inst, \ 1122 size_t captured_variable_index, \ 1123 ShadowFrame& shadow_frame); \ 1124 1125 EXPLICIT_DO_LIBERATE_VARIABLE_DECL(false); // liberate-variable 1126 EXPLICIT_DO_LIBERATE_VARIABLE_DECL(true); // liberate-variable 1127 #undef EXPLICIT_DO_LIBERATE_LAMBDA_DECL 1128 } // namespace interpreter 1129 } // namespace art 1130 1131 #endif // ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_ 1132