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 #include "interpreter.h" 18 19 #include <limits> 20 21 #include "common_throws.h" 22 #include "interpreter_common.h" 23 #include "interpreter_mterp_impl.h" 24 #include "interpreter_switch_impl.h" 25 #include "jvalue-inl.h" 26 #include "mirror/string-inl.h" 27 #include "scoped_thread_state_change-inl.h" 28 #include "ScopedLocalRef.h" 29 #include "stack.h" 30 #include "unstarted_runtime.h" 31 #include "mterp/mterp.h" 32 #include "jit/jit.h" 33 #include "jit/jit_code_cache.h" 34 35 namespace art { 36 namespace interpreter { 37 38 ALWAYS_INLINE static ObjPtr<mirror::Object> ObjArg(uint32_t arg) 39 REQUIRES_SHARED(Locks::mutator_lock_) { 40 return ObjPtr<mirror::Object>(reinterpret_cast<mirror::Object*>(arg)); 41 } 42 43 static void InterpreterJni(Thread* self, 44 ArtMethod* method, 45 const StringPiece& shorty, 46 ObjPtr<mirror::Object> receiver, 47 uint32_t* args, 48 JValue* result) 49 REQUIRES_SHARED(Locks::mutator_lock_) { 50 // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler, 51 // it should be removed and JNI compiled stubs used instead. 52 ScopedObjectAccessUnchecked soa(self); 53 if (method->IsStatic()) { 54 if (shorty == "L") { 55 typedef jobject (fntype)(JNIEnv*, jclass); 56 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 57 ScopedLocalRef<jclass> klass(soa.Env(), 58 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 59 jobject jresult; 60 { 61 ScopedThreadStateChange tsc(self, kNative); 62 jresult = fn(soa.Env(), klass.get()); 63 } 64 result->SetL(soa.Decode<mirror::Object>(jresult)); 65 } else if (shorty == "V") { 66 typedef void (fntype)(JNIEnv*, jclass); 67 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 68 ScopedLocalRef<jclass> klass(soa.Env(), 69 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 70 ScopedThreadStateChange tsc(self, kNative); 71 fn(soa.Env(), klass.get()); 72 } else if (shorty == "Z") { 73 typedef jboolean (fntype)(JNIEnv*, jclass); 74 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 75 ScopedLocalRef<jclass> klass(soa.Env(), 76 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 77 ScopedThreadStateChange tsc(self, kNative); 78 result->SetZ(fn(soa.Env(), klass.get())); 79 } else if (shorty == "BI") { 80 typedef jbyte (fntype)(JNIEnv*, jclass, jint); 81 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 82 ScopedLocalRef<jclass> klass(soa.Env(), 83 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 84 ScopedThreadStateChange tsc(self, kNative); 85 result->SetB(fn(soa.Env(), klass.get(), args[0])); 86 } else if (shorty == "II") { 87 typedef jint (fntype)(JNIEnv*, jclass, jint); 88 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 89 ScopedLocalRef<jclass> klass(soa.Env(), 90 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 91 ScopedThreadStateChange tsc(self, kNative); 92 result->SetI(fn(soa.Env(), klass.get(), args[0])); 93 } else if (shorty == "LL") { 94 typedef jobject (fntype)(JNIEnv*, jclass, jobject); 95 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 96 ScopedLocalRef<jclass> klass(soa.Env(), 97 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 98 ScopedLocalRef<jobject> arg0(soa.Env(), 99 soa.AddLocalReference<jobject>(ObjArg(args[0]))); 100 jobject jresult; 101 { 102 ScopedThreadStateChange tsc(self, kNative); 103 jresult = fn(soa.Env(), klass.get(), arg0.get()); 104 } 105 result->SetL(soa.Decode<mirror::Object>(jresult)); 106 } else if (shorty == "IIZ") { 107 typedef jint (fntype)(JNIEnv*, jclass, jint, jboolean); 108 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 109 ScopedLocalRef<jclass> klass(soa.Env(), 110 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 111 ScopedThreadStateChange tsc(self, kNative); 112 result->SetI(fn(soa.Env(), klass.get(), args[0], args[1])); 113 } else if (shorty == "ILI") { 114 typedef jint (fntype)(JNIEnv*, jclass, jobject, jint); 115 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>( 116 method->GetEntryPointFromJni())); 117 ScopedLocalRef<jclass> klass(soa.Env(), 118 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 119 ScopedLocalRef<jobject> arg0(soa.Env(), 120 soa.AddLocalReference<jobject>(ObjArg(args[0]))); 121 ScopedThreadStateChange tsc(self, kNative); 122 result->SetI(fn(soa.Env(), klass.get(), arg0.get(), args[1])); 123 } else if (shorty == "SIZ") { 124 typedef jshort (fntype)(JNIEnv*, jclass, jint, jboolean); 125 fntype* const fn = 126 reinterpret_cast<fntype*>(const_cast<void*>(method->GetEntryPointFromJni())); 127 ScopedLocalRef<jclass> klass(soa.Env(), 128 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 129 ScopedThreadStateChange tsc(self, kNative); 130 result->SetS(fn(soa.Env(), klass.get(), args[0], args[1])); 131 } else if (shorty == "VIZ") { 132 typedef void (fntype)(JNIEnv*, jclass, jint, jboolean); 133 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 134 ScopedLocalRef<jclass> klass(soa.Env(), 135 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 136 ScopedThreadStateChange tsc(self, kNative); 137 fn(soa.Env(), klass.get(), args[0], args[1]); 138 } else if (shorty == "ZLL") { 139 typedef jboolean (fntype)(JNIEnv*, jclass, jobject, jobject); 140 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 141 ScopedLocalRef<jclass> klass(soa.Env(), 142 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 143 ScopedLocalRef<jobject> arg0(soa.Env(), 144 soa.AddLocalReference<jobject>(ObjArg(args[0]))); 145 ScopedLocalRef<jobject> arg1(soa.Env(), 146 soa.AddLocalReference<jobject>(ObjArg(args[1]))); 147 ScopedThreadStateChange tsc(self, kNative); 148 result->SetZ(fn(soa.Env(), klass.get(), arg0.get(), arg1.get())); 149 } else if (shorty == "ZILL") { 150 typedef jboolean (fntype)(JNIEnv*, jclass, jint, jobject, jobject); 151 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 152 ScopedLocalRef<jclass> klass(soa.Env(), 153 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 154 ScopedLocalRef<jobject> arg1(soa.Env(), 155 soa.AddLocalReference<jobject>(ObjArg(args[1]))); 156 ScopedLocalRef<jobject> arg2(soa.Env(), 157 soa.AddLocalReference<jobject>(ObjArg(args[2]))); 158 ScopedThreadStateChange tsc(self, kNative); 159 result->SetZ(fn(soa.Env(), klass.get(), args[0], arg1.get(), arg2.get())); 160 } else if (shorty == "VILII") { 161 typedef void (fntype)(JNIEnv*, jclass, jint, jobject, jint, jint); 162 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 163 ScopedLocalRef<jclass> klass(soa.Env(), 164 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 165 ScopedLocalRef<jobject> arg1(soa.Env(), 166 soa.AddLocalReference<jobject>(ObjArg(args[1]))); 167 ScopedThreadStateChange tsc(self, kNative); 168 fn(soa.Env(), klass.get(), args[0], arg1.get(), args[2], args[3]); 169 } else if (shorty == "VLILII") { 170 typedef void (fntype)(JNIEnv*, jclass, jobject, jint, jobject, jint, jint); 171 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 172 ScopedLocalRef<jclass> klass(soa.Env(), 173 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 174 ScopedLocalRef<jobject> arg0(soa.Env(), 175 soa.AddLocalReference<jobject>(ObjArg(args[0]))); 176 ScopedLocalRef<jobject> arg2(soa.Env(), 177 soa.AddLocalReference<jobject>(ObjArg(args[2]))); 178 ScopedThreadStateChange tsc(self, kNative); 179 fn(soa.Env(), klass.get(), arg0.get(), args[1], arg2.get(), args[3], args[4]); 180 } else { 181 LOG(FATAL) << "Do something with static native method: " << method->PrettyMethod() 182 << " shorty: " << shorty; 183 } 184 } else { 185 if (shorty == "L") { 186 typedef jobject (fntype)(JNIEnv*, jobject); 187 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 188 ScopedLocalRef<jobject> rcvr(soa.Env(), 189 soa.AddLocalReference<jobject>(receiver)); 190 jobject jresult; 191 { 192 ScopedThreadStateChange tsc(self, kNative); 193 jresult = fn(soa.Env(), rcvr.get()); 194 } 195 result->SetL(soa.Decode<mirror::Object>(jresult)); 196 } else if (shorty == "V") { 197 typedef void (fntype)(JNIEnv*, jobject); 198 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 199 ScopedLocalRef<jobject> rcvr(soa.Env(), 200 soa.AddLocalReference<jobject>(receiver)); 201 ScopedThreadStateChange tsc(self, kNative); 202 fn(soa.Env(), rcvr.get()); 203 } else if (shorty == "LL") { 204 typedef jobject (fntype)(JNIEnv*, jobject, jobject); 205 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 206 ScopedLocalRef<jobject> rcvr(soa.Env(), 207 soa.AddLocalReference<jobject>(receiver)); 208 ScopedLocalRef<jobject> arg0(soa.Env(), 209 soa.AddLocalReference<jobject>(ObjArg(args[0]))); 210 jobject jresult; 211 { 212 ScopedThreadStateChange tsc(self, kNative); 213 jresult = fn(soa.Env(), rcvr.get(), arg0.get()); 214 } 215 result->SetL(soa.Decode<mirror::Object>(jresult)); 216 ScopedThreadStateChange tsc(self, kNative); 217 } else if (shorty == "III") { 218 typedef jint (fntype)(JNIEnv*, jobject, jint, jint); 219 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 220 ScopedLocalRef<jobject> rcvr(soa.Env(), 221 soa.AddLocalReference<jobject>(receiver)); 222 ScopedThreadStateChange tsc(self, kNative); 223 result->SetI(fn(soa.Env(), rcvr.get(), args[0], args[1])); 224 } else { 225 LOG(FATAL) << "Do something with native method: " << method->PrettyMethod() 226 << " shorty: " << shorty; 227 } 228 } 229 } 230 231 enum InterpreterImplKind { 232 kSwitchImplKind, // Switch-based interpreter implementation. 233 kMterpImplKind // Assembly interpreter 234 }; 235 236 static constexpr InterpreterImplKind kInterpreterImplKind = kMterpImplKind; 237 238 static inline JValue Execute( 239 Thread* self, 240 const DexFile::CodeItem* code_item, 241 ShadowFrame& shadow_frame, 242 JValue result_register, 243 bool stay_in_interpreter = false) REQUIRES_SHARED(Locks::mutator_lock_) { 244 DCHECK(!shadow_frame.GetMethod()->IsAbstract()); 245 DCHECK(!shadow_frame.GetMethod()->IsNative()); 246 if (LIKELY(shadow_frame.GetDexPC() == 0)) { // Entering the method, but not via deoptimization. 247 if (kIsDebugBuild) { 248 self->AssertNoPendingException(); 249 } 250 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); 251 ArtMethod *method = shadow_frame.GetMethod(); 252 253 if (UNLIKELY(instrumentation->HasMethodEntryListeners())) { 254 instrumentation->MethodEnterEvent(self, shadow_frame.GetThisObject(code_item->ins_size_), 255 method, 0); 256 } 257 258 if (!stay_in_interpreter) { 259 jit::Jit* jit = Runtime::Current()->GetJit(); 260 if (jit != nullptr) { 261 jit->MethodEntered(self, shadow_frame.GetMethod()); 262 if (jit->CanInvokeCompiledCode(method)) { 263 JValue result; 264 265 // Pop the shadow frame before calling into compiled code. 266 self->PopShadowFrame(); 267 ArtInterpreterToCompiledCodeBridge(self, nullptr, code_item, &shadow_frame, &result); 268 // Push the shadow frame back as the caller will expect it. 269 self->PushShadowFrame(&shadow_frame); 270 271 return result; 272 } 273 } 274 } 275 } 276 277 shadow_frame.GetMethod()->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self); 278 279 // Lock counting is a special version of accessibility checks, and for simplicity and 280 // reduction of template parameters, we gate it behind access-checks mode. 281 ArtMethod* method = shadow_frame.GetMethod(); 282 DCHECK(!method->SkipAccessChecks() || !method->MustCountLocks()); 283 284 bool transaction_active = Runtime::Current()->IsActiveTransaction(); 285 if (LIKELY(method->SkipAccessChecks())) { 286 // Enter the "without access check" interpreter. 287 if (kInterpreterImplKind == kMterpImplKind) { 288 if (transaction_active) { 289 // No Mterp variant - just use the switch interpreter. 290 return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register, 291 false); 292 } else if (UNLIKELY(!Runtime::Current()->IsStarted())) { 293 return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register, 294 false); 295 } else { 296 while (true) { 297 // Mterp does not support all instrumentation/debugging. 298 if (MterpShouldSwitchInterpreters() != 0) { 299 return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register, 300 false); 301 } 302 bool returned = ExecuteMterpImpl(self, code_item, &shadow_frame, &result_register); 303 if (returned) { 304 return result_register; 305 } else { 306 // Mterp didn't like that instruction. Single-step it with the reference interpreter. 307 result_register = ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, 308 result_register, true); 309 if (shadow_frame.GetDexPC() == DexFile::kDexNoIndex) { 310 // Single-stepped a return or an exception not handled locally. Return to caller. 311 return result_register; 312 } 313 } 314 } 315 } 316 } else { 317 DCHECK_EQ(kInterpreterImplKind, kSwitchImplKind); 318 if (transaction_active) { 319 return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register, 320 false); 321 } else { 322 return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register, 323 false); 324 } 325 } 326 } else { 327 // Enter the "with access check" interpreter. 328 if (kInterpreterImplKind == kMterpImplKind) { 329 // No access check variants for Mterp. Just use the switch version. 330 if (transaction_active) { 331 return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register, 332 false); 333 } else { 334 return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register, 335 false); 336 } 337 } else { 338 DCHECK_EQ(kInterpreterImplKind, kSwitchImplKind); 339 if (transaction_active) { 340 return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register, 341 false); 342 } else { 343 return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register, 344 false); 345 } 346 } 347 } 348 } 349 350 void EnterInterpreterFromInvoke(Thread* self, 351 ArtMethod* method, 352 ObjPtr<mirror::Object> receiver, 353 uint32_t* args, 354 JValue* result, 355 bool stay_in_interpreter) { 356 DCHECK_EQ(self, Thread::Current()); 357 bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks(); 358 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) { 359 ThrowStackOverflowError(self); 360 return; 361 } 362 363 // This can happen if we are in forced interpreter mode and an obsolete method is called using 364 // reflection. 365 if (UNLIKELY(method->IsObsolete())) { 366 ThrowInternalError("Attempting to invoke obsolete version of '%s'.", 367 method->PrettyMethod().c_str()); 368 return; 369 } 370 371 const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke"); 372 const DexFile::CodeItem* code_item = method->GetCodeItem(); 373 uint16_t num_regs; 374 uint16_t num_ins; 375 if (code_item != nullptr) { 376 num_regs = code_item->registers_size_; 377 num_ins = code_item->ins_size_; 378 } else if (!method->IsInvokable()) { 379 self->EndAssertNoThreadSuspension(old_cause); 380 method->ThrowInvocationTimeError(); 381 return; 382 } else { 383 DCHECK(method->IsNative()); 384 num_regs = num_ins = ArtMethod::NumArgRegisters(method->GetShorty()); 385 if (!method->IsStatic()) { 386 num_regs++; 387 num_ins++; 388 } 389 } 390 // Set up shadow frame with matching number of reference slots to vregs. 391 ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame(); 392 ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr = 393 CREATE_SHADOW_FRAME(num_regs, last_shadow_frame, method, /* dex pc */ 0); 394 ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get(); 395 self->PushShadowFrame(shadow_frame); 396 397 size_t cur_reg = num_regs - num_ins; 398 if (!method->IsStatic()) { 399 CHECK(receiver != nullptr); 400 shadow_frame->SetVRegReference(cur_reg, receiver.Ptr()); 401 ++cur_reg; 402 } 403 uint32_t shorty_len = 0; 404 const char* shorty = method->GetShorty(&shorty_len); 405 for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) { 406 DCHECK_LT(shorty_pos + 1, shorty_len); 407 switch (shorty[shorty_pos + 1]) { 408 case 'L': { 409 ObjPtr<mirror::Object> o = 410 reinterpret_cast<StackReference<mirror::Object>*>(&args[arg_pos])->AsMirrorPtr(); 411 shadow_frame->SetVRegReference(cur_reg, o.Ptr()); 412 break; 413 } 414 case 'J': case 'D': { 415 uint64_t wide_value = (static_cast<uint64_t>(args[arg_pos + 1]) << 32) | args[arg_pos]; 416 shadow_frame->SetVRegLong(cur_reg, wide_value); 417 cur_reg++; 418 arg_pos++; 419 break; 420 } 421 default: 422 shadow_frame->SetVReg(cur_reg, args[arg_pos]); 423 break; 424 } 425 } 426 self->EndAssertNoThreadSuspension(old_cause); 427 // Do this after populating the shadow frame in case EnsureInitialized causes a GC. 428 if (method->IsStatic() && UNLIKELY(!method->GetDeclaringClass()->IsInitialized())) { 429 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 430 StackHandleScope<1> hs(self); 431 Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass())); 432 if (UNLIKELY(!class_linker->EnsureInitialized(self, h_class, true, true))) { 433 CHECK(self->IsExceptionPending()); 434 self->PopShadowFrame(); 435 return; 436 } 437 } 438 if (LIKELY(!method->IsNative())) { 439 JValue r = Execute(self, code_item, *shadow_frame, JValue(), stay_in_interpreter); 440 if (result != nullptr) { 441 *result = r; 442 } 443 } else { 444 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler 445 // generated stub) except during testing and image writing. 446 // Update args to be the args in the shadow frame since the input ones could hold stale 447 // references pointers due to moving GC. 448 args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1); 449 if (!Runtime::Current()->IsStarted()) { 450 UnstartedRuntime::Jni(self, method, receiver.Ptr(), args, result); 451 } else { 452 InterpreterJni(self, method, shorty, receiver, args, result); 453 } 454 } 455 self->PopShadowFrame(); 456 } 457 458 static bool IsStringInit(const Instruction* instr, ArtMethod* caller) 459 REQUIRES_SHARED(Locks::mutator_lock_) { 460 if (instr->Opcode() == Instruction::INVOKE_DIRECT || 461 instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE) { 462 // Instead of calling ResolveMethod() which has suspend point and can trigger 463 // GC, look up the callee method symbolically. 464 uint16_t callee_method_idx = (instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE) ? 465 instr->VRegB_3rc() : instr->VRegB_35c(); 466 const DexFile* dex_file = caller->GetDexFile(); 467 const DexFile::MethodId& method_id = dex_file->GetMethodId(callee_method_idx); 468 const char* class_name = dex_file->StringByTypeIdx(method_id.class_idx_); 469 const char* method_name = dex_file->GetMethodName(method_id); 470 // Compare method's class name and method name against string init. 471 // It's ok since it's not allowed to create your own java/lang/String. 472 // TODO: verify that assumption. 473 if ((strcmp(class_name, "Ljava/lang/String;") == 0) && 474 (strcmp(method_name, "<init>") == 0)) { 475 return true; 476 } 477 } 478 return false; 479 } 480 481 static int16_t GetReceiverRegisterForStringInit(const Instruction* instr) { 482 DCHECK(instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE || 483 instr->Opcode() == Instruction::INVOKE_DIRECT); 484 return (instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE) ? 485 instr->VRegC_3rc() : instr->VRegC_35c(); 486 } 487 488 void EnterInterpreterFromDeoptimize(Thread* self, 489 ShadowFrame* shadow_frame, 490 bool from_code, 491 JValue* ret_val) 492 REQUIRES_SHARED(Locks::mutator_lock_) { 493 JValue value; 494 // Set value to last known result in case the shadow frame chain is empty. 495 value.SetJ(ret_val->GetJ()); 496 // Are we executing the first shadow frame? 497 bool first = true; 498 while (shadow_frame != nullptr) { 499 // We do not want to recover lock state for lock counting when deoptimizing. Currently, 500 // the compiler should not have compiled a method that failed structured-locking checks. 501 DCHECK(!shadow_frame->GetMethod()->MustCountLocks()); 502 503 self->SetTopOfShadowStack(shadow_frame); 504 const DexFile::CodeItem* code_item = shadow_frame->GetMethod()->GetCodeItem(); 505 const uint32_t dex_pc = shadow_frame->GetDexPC(); 506 uint32_t new_dex_pc = dex_pc; 507 if (UNLIKELY(self->IsExceptionPending())) { 508 // If we deoptimize from the QuickExceptionHandler, we already reported the exception to 509 // the instrumentation. To prevent from reporting it a second time, we simply pass a 510 // null Instrumentation*. 511 const instrumentation::Instrumentation* const instrumentation = 512 first ? nullptr : Runtime::Current()->GetInstrumentation(); 513 uint32_t found_dex_pc = FindNextInstructionFollowingException(self, *shadow_frame, dex_pc, 514 instrumentation); 515 new_dex_pc = found_dex_pc; // the dex pc of a matching catch handler 516 // or DexFile::kDexNoIndex if there is none. 517 } else if (!from_code) { 518 // For the debugger and full deoptimization stack, we must go past the invoke 519 // instruction, as it already executed. 520 // TODO: should be tested more once b/17586779 is fixed. 521 const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]); 522 if (instr->IsInvoke()) { 523 if (IsStringInit(instr, shadow_frame->GetMethod())) { 524 uint16_t this_obj_vreg = GetReceiverRegisterForStringInit(instr); 525 // Move the StringFactory.newStringFromChars() result into the register representing 526 // "this object" when invoking the string constructor in the original dex instruction. 527 // Also move the result into all aliases. 528 DCHECK(value.GetL()->IsString()); 529 SetStringInitValueToAllAliases(shadow_frame, this_obj_vreg, value); 530 // Calling string constructor in the original dex code doesn't generate a result value. 531 value.SetJ(0); 532 } 533 new_dex_pc = dex_pc + instr->SizeInCodeUnits(); 534 } else if (instr->Opcode() == Instruction::NEW_INSTANCE) { 535 // It's possible to deoptimize at a NEW_INSTANCE dex instruciton that's for a 536 // java string, which is turned into a call into StringFactory.newEmptyString(); 537 // Move the StringFactory.newEmptyString() result into the destination register. 538 DCHECK(value.GetL()->IsString()); 539 shadow_frame->SetVRegReference(instr->VRegA_21c(), value.GetL()); 540 // new-instance doesn't generate a result value. 541 value.SetJ(0); 542 // Skip the dex instruction since we essentially come back from an invocation. 543 new_dex_pc = dex_pc + instr->SizeInCodeUnits(); 544 if (kIsDebugBuild) { 545 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 546 // This is a suspend point. But it's ok since value has been set into shadow_frame. 547 ObjPtr<mirror::Class> klass = class_linker->ResolveType( 548 dex::TypeIndex(instr->VRegB_21c()), shadow_frame->GetMethod()); 549 DCHECK(klass->IsStringClass()); 550 } 551 } else { 552 CHECK(false) << "Unexpected instruction opcode " << instr->Opcode() 553 << " at dex_pc " << dex_pc 554 << " of method: " << ArtMethod::PrettyMethod(shadow_frame->GetMethod(), false); 555 } 556 } else { 557 // Nothing to do, the dex_pc is the one at which the code requested 558 // the deoptimization. 559 } 560 if (new_dex_pc != DexFile::kDexNoIndex) { 561 shadow_frame->SetDexPC(new_dex_pc); 562 value = Execute(self, code_item, *shadow_frame, value); 563 } 564 ShadowFrame* old_frame = shadow_frame; 565 shadow_frame = shadow_frame->GetLink(); 566 ShadowFrame::DeleteDeoptimizedFrame(old_frame); 567 // Following deoptimizations of shadow frames must pass the invoke instruction. 568 from_code = false; 569 first = false; 570 } 571 ret_val->SetJ(value.GetJ()); 572 } 573 574 JValue EnterInterpreterFromEntryPoint(Thread* self, const DexFile::CodeItem* code_item, 575 ShadowFrame* shadow_frame) { 576 DCHECK_EQ(self, Thread::Current()); 577 bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks(); 578 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) { 579 ThrowStackOverflowError(self); 580 return JValue(); 581 } 582 583 jit::Jit* jit = Runtime::Current()->GetJit(); 584 if (jit != nullptr) { 585 jit->NotifyCompiledCodeToInterpreterTransition(self, shadow_frame->GetMethod()); 586 } 587 return Execute(self, code_item, *shadow_frame, JValue()); 588 } 589 590 void ArtInterpreterToInterpreterBridge(Thread* self, 591 const DexFile::CodeItem* code_item, 592 ShadowFrame* shadow_frame, 593 JValue* result) { 594 bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks(); 595 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) { 596 ThrowStackOverflowError(self); 597 return; 598 } 599 600 self->PushShadowFrame(shadow_frame); 601 ArtMethod* method = shadow_frame->GetMethod(); 602 // Ensure static methods are initialized. 603 const bool is_static = method->IsStatic(); 604 if (is_static) { 605 ObjPtr<mirror::Class> declaring_class = method->GetDeclaringClass(); 606 if (UNLIKELY(!declaring_class->IsInitialized())) { 607 StackHandleScope<1> hs(self); 608 HandleWrapperObjPtr<mirror::Class> h_declaring_class(hs.NewHandleWrapper(&declaring_class)); 609 if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized( 610 self, h_declaring_class, true, true))) { 611 DCHECK(self->IsExceptionPending()); 612 self->PopShadowFrame(); 613 return; 614 } 615 CHECK(h_declaring_class->IsInitializing()); 616 } 617 } 618 619 if (LIKELY(!shadow_frame->GetMethod()->IsNative())) { 620 result->SetJ(Execute(self, code_item, *shadow_frame, JValue()).GetJ()); 621 } else { 622 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler 623 // generated stub) except during testing and image writing. 624 CHECK(!Runtime::Current()->IsStarted()); 625 ObjPtr<mirror::Object> receiver = is_static ? nullptr : shadow_frame->GetVRegReference(0); 626 uint32_t* args = shadow_frame->GetVRegArgs(is_static ? 0 : 1); 627 UnstartedRuntime::Jni(self, shadow_frame->GetMethod(), receiver.Ptr(), args, result); 628 } 629 630 self->PopShadowFrame(); 631 } 632 633 void CheckInterpreterAsmConstants() { 634 CheckMterpAsmConstants(); 635 } 636 637 void InitInterpreterTls(Thread* self) { 638 InitMterpTls(self); 639 } 640 641 } // namespace interpreter 642 } // namespace art 643