interpreter.cc revision 73be1e8f8609708f6624bb297c9628de44fd8b6f
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 "interpreter_common.h" 22#include "mirror/string-inl.h" 23#include "scoped_thread_state_change.h" 24#include "ScopedLocalRef.h" 25#include "stack.h" 26#include "unstarted_runtime.h" 27 28namespace art { 29namespace interpreter { 30 31static void InterpreterJni(Thread* self, ArtMethod* method, const StringPiece& shorty, 32 Object* receiver, uint32_t* args, JValue* result) 33 SHARED_REQUIRES(Locks::mutator_lock_) { 34 // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler, 35 // it should be removed and JNI compiled stubs used instead. 36 ScopedObjectAccessUnchecked soa(self); 37 if (method->IsStatic()) { 38 if (shorty == "L") { 39 typedef jobject (fntype)(JNIEnv*, jclass); 40 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 41 ScopedLocalRef<jclass> klass(soa.Env(), 42 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 43 jobject jresult; 44 { 45 ScopedThreadStateChange tsc(self, kNative); 46 jresult = fn(soa.Env(), klass.get()); 47 } 48 result->SetL(soa.Decode<Object*>(jresult)); 49 } else if (shorty == "V") { 50 typedef void (fntype)(JNIEnv*, jclass); 51 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 52 ScopedLocalRef<jclass> klass(soa.Env(), 53 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 54 ScopedThreadStateChange tsc(self, kNative); 55 fn(soa.Env(), klass.get()); 56 } else if (shorty == "Z") { 57 typedef jboolean (fntype)(JNIEnv*, jclass); 58 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 59 ScopedLocalRef<jclass> klass(soa.Env(), 60 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 61 ScopedThreadStateChange tsc(self, kNative); 62 result->SetZ(fn(soa.Env(), klass.get())); 63 } else if (shorty == "BI") { 64 typedef jbyte (fntype)(JNIEnv*, jclass, jint); 65 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 66 ScopedLocalRef<jclass> klass(soa.Env(), 67 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 68 ScopedThreadStateChange tsc(self, kNative); 69 result->SetB(fn(soa.Env(), klass.get(), args[0])); 70 } else if (shorty == "II") { 71 typedef jint (fntype)(JNIEnv*, jclass, jint); 72 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 73 ScopedLocalRef<jclass> klass(soa.Env(), 74 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 75 ScopedThreadStateChange tsc(self, kNative); 76 result->SetI(fn(soa.Env(), klass.get(), args[0])); 77 } else if (shorty == "LL") { 78 typedef jobject (fntype)(JNIEnv*, jclass, jobject); 79 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 80 ScopedLocalRef<jclass> klass(soa.Env(), 81 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 82 ScopedLocalRef<jobject> arg0(soa.Env(), 83 soa.AddLocalReference<jobject>( 84 reinterpret_cast<Object*>(args[0]))); 85 jobject jresult; 86 { 87 ScopedThreadStateChange tsc(self, kNative); 88 jresult = fn(soa.Env(), klass.get(), arg0.get()); 89 } 90 result->SetL(soa.Decode<Object*>(jresult)); 91 } else if (shorty == "IIZ") { 92 typedef jint (fntype)(JNIEnv*, jclass, jint, jboolean); 93 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 94 ScopedLocalRef<jclass> klass(soa.Env(), 95 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 96 ScopedThreadStateChange tsc(self, kNative); 97 result->SetI(fn(soa.Env(), klass.get(), args[0], args[1])); 98 } else if (shorty == "ILI") { 99 typedef jint (fntype)(JNIEnv*, jclass, jobject, jint); 100 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>( 101 method->GetEntryPointFromJni())); 102 ScopedLocalRef<jclass> klass(soa.Env(), 103 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 104 ScopedLocalRef<jobject> arg0(soa.Env(), 105 soa.AddLocalReference<jobject>( 106 reinterpret_cast<Object*>(args[0]))); 107 ScopedThreadStateChange tsc(self, kNative); 108 result->SetI(fn(soa.Env(), klass.get(), arg0.get(), args[1])); 109 } else if (shorty == "SIZ") { 110 typedef jshort (fntype)(JNIEnv*, jclass, jint, jboolean); 111 fntype* const fn = 112 reinterpret_cast<fntype*>(const_cast<void*>(method->GetEntryPointFromJni())); 113 ScopedLocalRef<jclass> klass(soa.Env(), 114 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 115 ScopedThreadStateChange tsc(self, kNative); 116 result->SetS(fn(soa.Env(), klass.get(), args[0], args[1])); 117 } else if (shorty == "VIZ") { 118 typedef void (fntype)(JNIEnv*, jclass, jint, jboolean); 119 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 120 ScopedLocalRef<jclass> klass(soa.Env(), 121 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 122 ScopedThreadStateChange tsc(self, kNative); 123 fn(soa.Env(), klass.get(), args[0], args[1]); 124 } else if (shorty == "ZLL") { 125 typedef jboolean (fntype)(JNIEnv*, jclass, jobject, jobject); 126 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 127 ScopedLocalRef<jclass> klass(soa.Env(), 128 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 129 ScopedLocalRef<jobject> arg0(soa.Env(), 130 soa.AddLocalReference<jobject>( 131 reinterpret_cast<Object*>(args[0]))); 132 ScopedLocalRef<jobject> arg1(soa.Env(), 133 soa.AddLocalReference<jobject>( 134 reinterpret_cast<Object*>(args[1]))); 135 ScopedThreadStateChange tsc(self, kNative); 136 result->SetZ(fn(soa.Env(), klass.get(), arg0.get(), arg1.get())); 137 } else if (shorty == "ZILL") { 138 typedef jboolean (fntype)(JNIEnv*, jclass, jint, jobject, jobject); 139 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 140 ScopedLocalRef<jclass> klass(soa.Env(), 141 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 142 ScopedLocalRef<jobject> arg1(soa.Env(), 143 soa.AddLocalReference<jobject>( 144 reinterpret_cast<Object*>(args[1]))); 145 ScopedLocalRef<jobject> arg2(soa.Env(), 146 soa.AddLocalReference<jobject>( 147 reinterpret_cast<Object*>(args[2]))); 148 ScopedThreadStateChange tsc(self, kNative); 149 result->SetZ(fn(soa.Env(), klass.get(), args[0], arg1.get(), arg2.get())); 150 } else if (shorty == "VILII") { 151 typedef void (fntype)(JNIEnv*, jclass, jint, jobject, jint, jint); 152 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 153 ScopedLocalRef<jclass> klass(soa.Env(), 154 soa.AddLocalReference<jclass>(method->GetDeclaringClass())); 155 ScopedLocalRef<jobject> arg1(soa.Env(), 156 soa.AddLocalReference<jobject>( 157 reinterpret_cast<Object*>(args[1]))); 158 ScopedThreadStateChange tsc(self, kNative); 159 fn(soa.Env(), klass.get(), args[0], arg1.get(), args[2], args[3]); 160 } else if (shorty == "VLILII") { 161 typedef void (fntype)(JNIEnv*, jclass, jobject, 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> arg0(soa.Env(), 166 soa.AddLocalReference<jobject>( 167 reinterpret_cast<Object*>(args[0]))); 168 ScopedLocalRef<jobject> arg2(soa.Env(), 169 soa.AddLocalReference<jobject>( 170 reinterpret_cast<Object*>(args[2]))); 171 ScopedThreadStateChange tsc(self, kNative); 172 fn(soa.Env(), klass.get(), arg0.get(), args[1], arg2.get(), args[3], args[4]); 173 } else { 174 LOG(FATAL) << "Do something with static native method: " << PrettyMethod(method) 175 << " shorty: " << shorty; 176 } 177 } else { 178 if (shorty == "L") { 179 typedef jobject (fntype)(JNIEnv*, jobject); 180 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 181 ScopedLocalRef<jobject> rcvr(soa.Env(), 182 soa.AddLocalReference<jobject>(receiver)); 183 jobject jresult; 184 { 185 ScopedThreadStateChange tsc(self, kNative); 186 jresult = fn(soa.Env(), rcvr.get()); 187 } 188 result->SetL(soa.Decode<Object*>(jresult)); 189 } else if (shorty == "V") { 190 typedef void (fntype)(JNIEnv*, jobject); 191 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 192 ScopedLocalRef<jobject> rcvr(soa.Env(), 193 soa.AddLocalReference<jobject>(receiver)); 194 ScopedThreadStateChange tsc(self, kNative); 195 fn(soa.Env(), rcvr.get()); 196 } else if (shorty == "LL") { 197 typedef jobject (fntype)(JNIEnv*, jobject, jobject); 198 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 199 ScopedLocalRef<jobject> rcvr(soa.Env(), 200 soa.AddLocalReference<jobject>(receiver)); 201 ScopedLocalRef<jobject> arg0(soa.Env(), 202 soa.AddLocalReference<jobject>( 203 reinterpret_cast<Object*>(args[0]))); 204 jobject jresult; 205 { 206 ScopedThreadStateChange tsc(self, kNative); 207 jresult = fn(soa.Env(), rcvr.get(), arg0.get()); 208 } 209 result->SetL(soa.Decode<Object*>(jresult)); 210 ScopedThreadStateChange tsc(self, kNative); 211 } else if (shorty == "III") { 212 typedef jint (fntype)(JNIEnv*, jobject, jint, jint); 213 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni()); 214 ScopedLocalRef<jobject> rcvr(soa.Env(), 215 soa.AddLocalReference<jobject>(receiver)); 216 ScopedThreadStateChange tsc(self, kNative); 217 result->SetI(fn(soa.Env(), rcvr.get(), args[0], args[1])); 218 } else { 219 LOG(FATAL) << "Do something with native method: " << PrettyMethod(method) 220 << " shorty: " << shorty; 221 } 222 } 223} 224 225enum InterpreterImplKind { 226 kSwitchImpl, // Switch-based interpreter implementation. 227 kComputedGotoImplKind // Computed-goto-based interpreter implementation. 228}; 229static std::ostream& operator<<(std::ostream& os, const InterpreterImplKind& rhs) { 230 os << ((rhs == kSwitchImpl) ? "Switch-based interpreter" : "Computed-goto-based interpreter"); 231 return os; 232} 233 234#if !defined(__clang__) 235static constexpr InterpreterImplKind kInterpreterImplKind = kComputedGotoImplKind; 236#else 237// Clang 3.4 fails to build the goto interpreter implementation. 238static constexpr InterpreterImplKind kInterpreterImplKind = kSwitchImpl; 239template<bool do_access_check, bool transaction_active> 240JValue ExecuteGotoImpl(Thread*, const DexFile::CodeItem*, ShadowFrame&, JValue) { 241 LOG(FATAL) << "UNREACHABLE"; 242 UNREACHABLE(); 243} 244// Explicit definitions of ExecuteGotoImpl. 245template<> SHARED_REQUIRES(Locks::mutator_lock_) 246JValue ExecuteGotoImpl<true, false>(Thread* self, const DexFile::CodeItem* code_item, 247 ShadowFrame& shadow_frame, JValue result_register); 248template<> SHARED_REQUIRES(Locks::mutator_lock_) 249JValue ExecuteGotoImpl<false, false>(Thread* self, const DexFile::CodeItem* code_item, 250 ShadowFrame& shadow_frame, JValue result_register); 251template<> SHARED_REQUIRES(Locks::mutator_lock_) 252JValue ExecuteGotoImpl<true, true>(Thread* self, const DexFile::CodeItem* code_item, 253 ShadowFrame& shadow_frame, JValue result_register); 254template<> SHARED_REQUIRES(Locks::mutator_lock_) 255JValue ExecuteGotoImpl<false, true>(Thread* self, const DexFile::CodeItem* code_item, 256 ShadowFrame& shadow_frame, JValue result_register); 257#endif 258 259static JValue Execute(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, 260 JValue result_register) 261 SHARED_REQUIRES(Locks::mutator_lock_); 262 263static inline JValue Execute(Thread* self, const DexFile::CodeItem* code_item, 264 ShadowFrame& shadow_frame, JValue result_register) { 265 DCHECK(shadow_frame.GetMethod()->IsInvokable()); 266 DCHECK(!shadow_frame.GetMethod()->IsNative()); 267 shadow_frame.GetMethod()->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self); 268 269 bool transaction_active = Runtime::Current()->IsActiveTransaction(); 270 if (LIKELY(shadow_frame.GetMethod()->IsPreverified())) { 271 // Enter the "without access check" interpreter. 272 if (kInterpreterImplKind == kSwitchImpl) { 273 if (transaction_active) { 274 return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register); 275 } else { 276 return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register); 277 } 278 } else { 279 DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind); 280 if (transaction_active) { 281 return ExecuteGotoImpl<false, true>(self, code_item, shadow_frame, result_register); 282 } else { 283 return ExecuteGotoImpl<false, false>(self, code_item, shadow_frame, result_register); 284 } 285 } 286 } else { 287 // Enter the "with access check" interpreter. 288 if (kInterpreterImplKind == kSwitchImpl) { 289 if (transaction_active) { 290 return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register); 291 } else { 292 return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register); 293 } 294 } else { 295 DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind); 296 if (transaction_active) { 297 return ExecuteGotoImpl<true, true>(self, code_item, shadow_frame, result_register); 298 } else { 299 return ExecuteGotoImpl<true, false>(self, code_item, shadow_frame, result_register); 300 } 301 } 302 } 303} 304 305void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receiver, 306 uint32_t* args, JValue* result) { 307 DCHECK_EQ(self, Thread::Current()); 308 bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks(); 309 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) { 310 ThrowStackOverflowError(self); 311 return; 312 } 313 314 const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke"); 315 const DexFile::CodeItem* code_item = method->GetCodeItem(); 316 uint16_t num_regs; 317 uint16_t num_ins; 318 if (code_item != nullptr) { 319 num_regs = code_item->registers_size_; 320 num_ins = code_item->ins_size_; 321 } else if (!method->IsInvokable()) { 322 self->EndAssertNoThreadSuspension(old_cause); 323 method->ThrowInvocationTimeError(); 324 return; 325 } else { 326 DCHECK(method->IsNative()); 327 num_regs = num_ins = ArtMethod::NumArgRegisters(method->GetShorty()); 328 if (!method->IsStatic()) { 329 num_regs++; 330 num_ins++; 331 } 332 } 333 // Set up shadow frame with matching number of reference slots to vregs. 334 ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame(); 335 ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr = 336 CREATE_SHADOW_FRAME(num_regs, last_shadow_frame, method, /* dex pc */ 0); 337 ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get(); 338 self->PushShadowFrame(shadow_frame); 339 340 size_t cur_reg = num_regs - num_ins; 341 if (!method->IsStatic()) { 342 CHECK(receiver != nullptr); 343 shadow_frame->SetVRegReference(cur_reg, receiver); 344 ++cur_reg; 345 } 346 uint32_t shorty_len = 0; 347 const char* shorty = method->GetShorty(&shorty_len); 348 for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) { 349 DCHECK_LT(shorty_pos + 1, shorty_len); 350 switch (shorty[shorty_pos + 1]) { 351 case 'L': { 352 Object* o = reinterpret_cast<StackReference<Object>*>(&args[arg_pos])->AsMirrorPtr(); 353 shadow_frame->SetVRegReference(cur_reg, o); 354 break; 355 } 356 case 'J': case 'D': { 357 uint64_t wide_value = (static_cast<uint64_t>(args[arg_pos + 1]) << 32) | args[arg_pos]; 358 shadow_frame->SetVRegLong(cur_reg, wide_value); 359 cur_reg++; 360 arg_pos++; 361 break; 362 } 363 default: 364 shadow_frame->SetVReg(cur_reg, args[arg_pos]); 365 break; 366 } 367 } 368 self->EndAssertNoThreadSuspension(old_cause); 369 // Do this after populating the shadow frame in case EnsureInitialized causes a GC. 370 if (method->IsStatic() && UNLIKELY(!method->GetDeclaringClass()->IsInitialized())) { 371 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 372 StackHandleScope<1> hs(self); 373 Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass())); 374 if (UNLIKELY(!class_linker->EnsureInitialized(self, h_class, true, true))) { 375 CHECK(self->IsExceptionPending()); 376 self->PopShadowFrame(); 377 return; 378 } 379 } 380 if (LIKELY(!method->IsNative())) { 381 JValue r = Execute(self, code_item, *shadow_frame, JValue()); 382 if (result != nullptr) { 383 *result = r; 384 } 385 } else { 386 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler 387 // generated stub) except during testing and image writing. 388 // Update args to be the args in the shadow frame since the input ones could hold stale 389 // references pointers due to moving GC. 390 args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1); 391 if (!Runtime::Current()->IsStarted()) { 392 UnstartedRuntime::Jni(self, method, receiver, args, result); 393 } else { 394 InterpreterJni(self, method, shorty, receiver, args, result); 395 } 396 } 397 self->PopShadowFrame(); 398} 399 400void EnterInterpreterFromDeoptimize(Thread* self, 401 ShadowFrame* shadow_frame, 402 bool from_code, 403 JValue* ret_val) 404 SHARED_REQUIRES(Locks::mutator_lock_) { 405 JValue value; 406 // Set value to last known result in case the shadow frame chain is empty. 407 value.SetJ(ret_val->GetJ()); 408 // Are we executing the first shadow frame? 409 bool first = true; 410 while (shadow_frame != nullptr) { 411 self->SetTopOfShadowStack(shadow_frame); 412 const DexFile::CodeItem* code_item = shadow_frame->GetMethod()->GetCodeItem(); 413 const uint32_t dex_pc = shadow_frame->GetDexPC(); 414 uint32_t new_dex_pc = dex_pc; 415 if (UNLIKELY(self->IsExceptionPending())) { 416 // If we deoptimize from the QuickExceptionHandler, we already reported the exception to 417 // the instrumentation. To prevent from reporting it a second time, we simply pass a 418 // null Instrumentation*. 419 const instrumentation::Instrumentation* const instrumentation = 420 first ? nullptr : Runtime::Current()->GetInstrumentation(); 421 uint32_t found_dex_pc = FindNextInstructionFollowingException(self, *shadow_frame, dex_pc, 422 instrumentation); 423 new_dex_pc = found_dex_pc; // the dex pc of a matching catch handler 424 // or DexFile::kDexNoIndex if there is none. 425 } else if (!from_code) { 426 // For the debugger and full deoptimization stack, we must go past the invoke 427 // instruction, as it already executed. 428 // TODO: should be tested more once b/17586779 is fixed. 429 const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]); 430 DCHECK(instr->IsInvoke()); 431 new_dex_pc = dex_pc + instr->SizeInCodeUnits(); 432 } else { 433 // Nothing to do, the dex_pc is the one at which the code requested 434 // the deoptimization. 435 } 436 if (new_dex_pc != DexFile::kDexNoIndex) { 437 shadow_frame->SetDexPC(new_dex_pc); 438 value = Execute(self, code_item, *shadow_frame, value); 439 } 440 ShadowFrame* old_frame = shadow_frame; 441 shadow_frame = shadow_frame->GetLink(); 442 ShadowFrame::DeleteDeoptimizedFrame(old_frame); 443 // Following deoptimizations of shadow frames must pass the invoke instruction. 444 from_code = false; 445 first = false; 446 } 447 ret_val->SetJ(value.GetJ()); 448} 449 450JValue EnterInterpreterFromEntryPoint(Thread* self, const DexFile::CodeItem* code_item, 451 ShadowFrame* shadow_frame) { 452 DCHECK_EQ(self, Thread::Current()); 453 bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks(); 454 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) { 455 ThrowStackOverflowError(self); 456 return JValue(); 457 } 458 459 return Execute(self, code_item, *shadow_frame, JValue()); 460} 461 462void ArtInterpreterToInterpreterBridge(Thread* self, const DexFile::CodeItem* code_item, 463 ShadowFrame* shadow_frame, JValue* result) { 464 bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks(); 465 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) { 466 ThrowStackOverflowError(self); 467 return; 468 } 469 470 self->PushShadowFrame(shadow_frame); 471 ArtMethod* method = shadow_frame->GetMethod(); 472 // Ensure static methods are initialized. 473 const bool is_static = method->IsStatic(); 474 if (is_static) { 475 mirror::Class* declaring_class = method->GetDeclaringClass(); 476 if (UNLIKELY(!declaring_class->IsInitialized())) { 477 StackHandleScope<1> hs(self); 478 HandleWrapper<Class> h_declaring_class(hs.NewHandleWrapper(&declaring_class)); 479 if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized( 480 self, h_declaring_class, true, true))) { 481 DCHECK(self->IsExceptionPending()); 482 self->PopShadowFrame(); 483 return; 484 } 485 CHECK(h_declaring_class->IsInitializing()); 486 } 487 } 488 489 if (LIKELY(!shadow_frame->GetMethod()->IsNative())) { 490 result->SetJ(Execute(self, code_item, *shadow_frame, JValue()).GetJ()); 491 } else { 492 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler 493 // generated stub) except during testing and image writing. 494 CHECK(!Runtime::Current()->IsStarted()); 495 Object* receiver = is_static ? nullptr : shadow_frame->GetVRegReference(0); 496 uint32_t* args = shadow_frame->GetVRegArgs(is_static ? 0 : 1); 497 UnstartedRuntime::Jni(self, shadow_frame->GetMethod(), receiver, args, result); 498 } 499 500 self->PopShadowFrame(); 501} 502 503} // namespace interpreter 504} // namespace art 505