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 "callee_save_frame.h" 18#include "common_throws.h" 19#include "dex_file-inl.h" 20#include "dex_instruction-inl.h" 21#include "entrypoints/entrypoint_utils.h" 22#include "interpreter/interpreter.h" 23#include "invoke_arg_array_builder.h" 24#include "mirror/art_method-inl.h" 25#include "mirror/class-inl.h" 26#include "mirror/object-inl.h" 27#include "mirror/object_array-inl.h" 28#include "object_utils.h" 29#include "runtime.h" 30 31 32 33namespace art { 34 35// Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame. 36class QuickArgumentVisitor { 37 public: 38// Offset to first (not the Method*) argument in a Runtime::kRefAndArgs callee save frame. 39// Size of Runtime::kRefAndArgs callee save frame. 40// Size of Method* and register parameters in out stack arguments. 41#if defined(__arm__) 42 // The callee save frame is pointed to by SP. 43 // | argN | | 44 // | ... | | 45 // | arg4 | | 46 // | arg3 spill | | Caller's frame 47 // | arg2 spill | | 48 // | arg1 spill | | 49 // | Method* | --- 50 // | LR | 51 // | ... | callee saves 52 // | R3 | arg3 53 // | R2 | arg2 54 // | R1 | arg1 55 // | R0 | 56 // | Method* | <- sp 57#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 8 58#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET 44 59#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 48 60#define QUICK_STACK_ARG_SKIP 16 61#elif defined(__mips__) 62 // The callee save frame is pointed to by SP. 63 // | argN | | 64 // | ... | | 65 // | arg4 | | 66 // | arg3 spill | | Caller's frame 67 // | arg2 spill | | 68 // | arg1 spill | | 69 // | Method* | --- 70 // | RA | 71 // | ... | callee saves 72 // | A3 | arg3 73 // | A2 | arg2 74 // | A1 | arg1 75 // | A0/Method* | <- sp 76#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4 77#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET 60 78#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 64 79#define QUICK_STACK_ARG_SKIP 16 80#elif defined(__i386__) 81 // The callee save frame is pointed to by SP. 82 // | argN | | 83 // | ... | | 84 // | arg4 | | 85 // | arg3 spill | | Caller's frame 86 // | arg2 spill | | 87 // | arg1 spill | | 88 // | Method* | --- 89 // | Return | 90 // | EBP,ESI,EDI | callee saves 91 // | EBX | arg3 92 // | EDX | arg2 93 // | ECX | arg1 94 // | EAX/Method* | <- sp 95#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4 96#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET 28 97#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 32 98#define QUICK_STACK_ARG_SKIP 16 99#else 100#error "Unsupported architecture" 101#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0 102#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET 0 103#define QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 0 104#define QUICK_STACK_ARG_SKIP 0 105#endif 106 107 static mirror::ArtMethod* GetCallingMethod(mirror::ArtMethod** sp) { 108 byte* previous_sp = reinterpret_cast<byte*>(sp) + 109 QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE; 110 return *reinterpret_cast<mirror::ArtMethod**>(previous_sp); 111 } 112 113 static uintptr_t GetCallingPc(mirror::ArtMethod** sp) { 114 byte* lr = reinterpret_cast<byte*>(sp) + QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__LR_OFFSET; 115 return *reinterpret_cast<uintptr_t*>(lr); 116 } 117 118 QuickArgumentVisitor(mirror::ArtMethod** sp, bool is_static, 119 const char* shorty, uint32_t shorty_len) 120 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : 121 is_static_(is_static), shorty_(shorty), shorty_len_(shorty_len), 122 args_in_regs_(ComputeArgsInRegs(is_static, shorty, shorty_len)), 123 num_params_((is_static ? 0 : 1) + shorty_len - 1), // +1 for this, -1 for return type 124 reg_args_(reinterpret_cast<byte*>(sp) + QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET), 125 stack_args_(reinterpret_cast<byte*>(sp) + QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 126 + QUICK_STACK_ARG_SKIP), 127 cur_args_(reg_args_), 128 cur_arg_index_(0), 129 param_index_(0), 130 is_split_long_or_double_(false) { 131 DCHECK_EQ(static_cast<size_t>(QUICK_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE), 132 Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes()); 133 } 134 135 virtual ~QuickArgumentVisitor() {} 136 137 virtual void Visit() = 0; 138 139 Primitive::Type GetParamPrimitiveType() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 140 size_t index = param_index_; 141 if (is_static_) { 142 index++; // 0th argument must skip return value at start of the shorty 143 } else if (index == 0) { 144 return Primitive::kPrimNot; 145 } 146 CHECK_LT(index, shorty_len_); 147 return Primitive::GetType(shorty_[index]); 148 } 149 150 byte* GetParamAddress() const { 151 return cur_args_ + (cur_arg_index_ * kPointerSize); 152 } 153 154 bool IsSplitLongOrDouble() const { 155 return is_split_long_or_double_; 156 } 157 158 bool IsParamAReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 159 return GetParamPrimitiveType() == Primitive::kPrimNot; 160 } 161 162 bool IsParamALongOrDouble() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 163 Primitive::Type type = GetParamPrimitiveType(); 164 return type == Primitive::kPrimLong || type == Primitive::kPrimDouble; 165 } 166 167 uint64_t ReadSplitLongParam() const { 168 DCHECK(IsSplitLongOrDouble()); 169 uint64_t low_half = *reinterpret_cast<uint32_t*>(GetParamAddress()); 170 uint64_t high_half = *reinterpret_cast<uint32_t*>(stack_args_); 171 return (low_half & 0xffffffffULL) | (high_half << 32); 172 } 173 174 void VisitArguments() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 175 for (cur_arg_index_ = 0; cur_arg_index_ < args_in_regs_ && param_index_ < num_params_; ) { 176 is_split_long_or_double_ = (cur_arg_index_ == 2) && IsParamALongOrDouble(); 177 Visit(); 178 cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1); 179 param_index_++; 180 } 181 cur_args_ = stack_args_; 182 cur_arg_index_ = is_split_long_or_double_ ? 1 : 0; 183 is_split_long_or_double_ = false; 184 while (param_index_ < num_params_) { 185 Visit(); 186 cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1); 187 param_index_++; 188 } 189 } 190 191 private: 192 static size_t ComputeArgsInRegs(bool is_static, const char* shorty, uint32_t shorty_len) 193 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 194 size_t args_in_regs = (is_static ? 0 : 1); 195 for (size_t i = 0; i < shorty_len; i++) { 196 char s = shorty[i]; 197 if (s == 'J' || s == 'D') { 198 args_in_regs += 2; 199 } else { 200 args_in_regs++; 201 } 202 if (args_in_regs > 3) { 203 args_in_regs = 3; 204 break; 205 } 206 } 207 return args_in_regs; 208 } 209 210 const bool is_static_; 211 const char* const shorty_; 212 const uint32_t shorty_len_; 213 const size_t args_in_regs_; 214 const size_t num_params_; 215 byte* const reg_args_; 216 byte* const stack_args_; 217 byte* cur_args_; 218 size_t cur_arg_index_; 219 size_t param_index_; 220 // Does a 64bit parameter straddle the register and stack arguments? 221 bool is_split_long_or_double_; 222}; 223 224// Visits arguments on the stack placing them into the shadow frame. 225class BuildQuickShadowFrameVisitor : public QuickArgumentVisitor { 226 public: 227 BuildQuickShadowFrameVisitor(mirror::ArtMethod** sp, 228 bool is_static, const char* shorty, 229 uint32_t shorty_len, ShadowFrame& sf, size_t first_arg_reg) : 230 QuickArgumentVisitor(sp, is_static, shorty, shorty_len), sf_(sf), cur_reg_(first_arg_reg) {} 231 232 virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 233 Primitive::Type type = GetParamPrimitiveType(); 234 switch (type) { 235 case Primitive::kPrimLong: // Fall-through. 236 case Primitive::kPrimDouble: 237 if (IsSplitLongOrDouble()) { 238 sf_.SetVRegLong(cur_reg_, ReadSplitLongParam()); 239 } else { 240 sf_.SetVRegLong(cur_reg_, *reinterpret_cast<jlong*>(GetParamAddress())); 241 } 242 ++cur_reg_; 243 break; 244 case Primitive::kPrimNot: 245 sf_.SetVRegReference(cur_reg_, *reinterpret_cast<mirror::Object**>(GetParamAddress())); 246 break; 247 case Primitive::kPrimBoolean: // Fall-through. 248 case Primitive::kPrimByte: // Fall-through. 249 case Primitive::kPrimChar: // Fall-through. 250 case Primitive::kPrimShort: // Fall-through. 251 case Primitive::kPrimInt: // Fall-through. 252 case Primitive::kPrimFloat: 253 sf_.SetVReg(cur_reg_, *reinterpret_cast<jint*>(GetParamAddress())); 254 break; 255 case Primitive::kPrimVoid: 256 LOG(FATAL) << "UNREACHABLE"; 257 break; 258 } 259 ++cur_reg_; 260 } 261 262 private: 263 ShadowFrame& sf_; 264 size_t cur_reg_; 265 266 DISALLOW_COPY_AND_ASSIGN(BuildQuickShadowFrameVisitor); 267}; 268 269extern "C" uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Thread* self, 270 mirror::ArtMethod** sp) 271 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 272 // Ensure we don't get thread suspension until the object arguments are safely in the shadow 273 // frame. 274 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs); 275 276 if (method->IsAbstract()) { 277 ThrowAbstractMethodError(method); 278 return 0; 279 } else { 280 const char* old_cause = self->StartAssertNoThreadSuspension("Building interpreter shadow frame"); 281 MethodHelper mh(method); 282 const DexFile::CodeItem* code_item = mh.GetCodeItem(); 283 uint16_t num_regs = code_item->registers_size_; 284 void* memory = alloca(ShadowFrame::ComputeSize(num_regs)); 285 ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, NULL, // No last shadow coming from quick. 286 method, 0, memory)); 287 size_t first_arg_reg = code_item->registers_size_ - code_item->ins_size_; 288 BuildQuickShadowFrameVisitor shadow_frame_builder(sp, mh.IsStatic(), mh.GetShorty(), 289 mh.GetShortyLength(), 290 *shadow_frame, first_arg_reg); 291 shadow_frame_builder.VisitArguments(); 292 // Push a transition back into managed code onto the linked list in thread. 293 ManagedStack fragment; 294 self->PushManagedStackFragment(&fragment); 295 self->PushShadowFrame(shadow_frame); 296 self->EndAssertNoThreadSuspension(old_cause); 297 298 if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) { 299 // Ensure static method's class is initialized. 300 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(), 301 true, true)) { 302 DCHECK(Thread::Current()->IsExceptionPending()); 303 self->PopManagedStackFragment(fragment); 304 return 0; 305 } 306 } 307 308 JValue result = interpreter::EnterInterpreterFromStub(self, mh, code_item, *shadow_frame); 309 // Pop transition. 310 self->PopManagedStackFragment(fragment); 311 return result.GetJ(); 312 } 313} 314 315// Visits arguments on the stack placing them into the args vector, Object* arguments are converted 316// to jobjects. 317class BuildQuickArgumentVisitor : public QuickArgumentVisitor { 318 public: 319 BuildQuickArgumentVisitor(mirror::ArtMethod** sp, bool is_static, const char* shorty, 320 uint32_t shorty_len, ScopedObjectAccessUnchecked* soa, 321 std::vector<jvalue>* args) : 322 QuickArgumentVisitor(sp, is_static, shorty, shorty_len), soa_(soa), args_(args) {} 323 324 virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 325 jvalue val; 326 Primitive::Type type = GetParamPrimitiveType(); 327 switch (type) { 328 case Primitive::kPrimNot: { 329 mirror::Object* obj = *reinterpret_cast<mirror::Object**>(GetParamAddress()); 330 val.l = soa_->AddLocalReference<jobject>(obj); 331 break; 332 } 333 case Primitive::kPrimLong: // Fall-through. 334 case Primitive::kPrimDouble: 335 if (IsSplitLongOrDouble()) { 336 val.j = ReadSplitLongParam(); 337 } else { 338 val.j = *reinterpret_cast<jlong*>(GetParamAddress()); 339 } 340 break; 341 case Primitive::kPrimBoolean: // Fall-through. 342 case Primitive::kPrimByte: // Fall-through. 343 case Primitive::kPrimChar: // Fall-through. 344 case Primitive::kPrimShort: // Fall-through. 345 case Primitive::kPrimInt: // Fall-through. 346 case Primitive::kPrimFloat: 347 val.i = *reinterpret_cast<jint*>(GetParamAddress()); 348 break; 349 case Primitive::kPrimVoid: 350 LOG(FATAL) << "UNREACHABLE"; 351 val.j = 0; 352 break; 353 } 354 args_->push_back(val); 355 } 356 357 private: 358 ScopedObjectAccessUnchecked* soa_; 359 std::vector<jvalue>* args_; 360 361 DISALLOW_COPY_AND_ASSIGN(BuildQuickArgumentVisitor); 362}; 363 364// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method 365// which is responsible for recording callee save registers. We explicitly place into jobjects the 366// incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a 367// field within the proxy object, which will box the primitive arguments and deal with error cases. 368extern "C" uint64_t artQuickProxyInvokeHandler(mirror::ArtMethod* proxy_method, 369 mirror::Object* receiver, 370 Thread* self, mirror::ArtMethod** sp) 371 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 372 DCHECK(proxy_method->IsProxyMethod()) << PrettyMethod(proxy_method); 373 DCHECK(receiver->GetClass()->IsProxyClass()) << PrettyMethod(proxy_method); 374 // Ensure we don't get thread suspension until the object arguments are safely in jobjects. 375 const char* old_cause = 376 self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments"); 377 // Register the top of the managed stack, making stack crawlable. 378 DCHECK_EQ(*sp, proxy_method) << PrettyMethod(proxy_method); 379 self->SetTopOfStack(sp, 0); 380 DCHECK_EQ(proxy_method->GetFrameSizeInBytes(), 381 Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes()) 382 << PrettyMethod(proxy_method); 383 self->VerifyStack(); 384 // Start new JNI local reference state. 385 JNIEnvExt* env = self->GetJniEnv(); 386 ScopedObjectAccessUnchecked soa(env); 387 ScopedJniEnvLocalRefState env_state(env); 388 // Create local ref. copies of proxy method and the receiver. 389 jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver); 390 391 // Placing arguments into args vector and remove the receiver. 392 MethodHelper proxy_mh(proxy_method); 393 DCHECK(!proxy_mh.IsStatic()) << PrettyMethod(proxy_method); 394 std::vector<jvalue> args; 395 BuildQuickArgumentVisitor local_ref_visitor(sp, proxy_mh.IsStatic(), proxy_mh.GetShorty(), 396 proxy_mh.GetShortyLength(), &soa, &args); 397 398 local_ref_visitor.VisitArguments(); 399 DCHECK_GT(args.size(), 0U) << PrettyMethod(proxy_method); 400 args.erase(args.begin()); 401 402 // Convert proxy method into expected interface method. 403 mirror::ArtMethod* interface_method = proxy_method->FindOverriddenMethod(); 404 DCHECK(interface_method != NULL) << PrettyMethod(proxy_method); 405 DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method); 406 jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method); 407 408 // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code 409 // that performs allocations. 410 self->EndAssertNoThreadSuspension(old_cause); 411 JValue result = InvokeProxyInvocationHandler(soa, proxy_mh.GetShorty(), 412 rcvr_jobj, interface_method_jobj, args); 413 return result.GetJ(); 414} 415 416// Read object references held in arguments from quick frames and place in a JNI local references, 417// so they don't get garbage collected. 418class RememberFoGcArgumentVisitor : public QuickArgumentVisitor { 419 public: 420 RememberFoGcArgumentVisitor(mirror::ArtMethod** sp, bool is_static, const char* shorty, 421 uint32_t shorty_len, ScopedObjectAccessUnchecked* soa) : 422 QuickArgumentVisitor(sp, is_static, shorty, shorty_len), soa_(soa) {} 423 424 virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 425 if (IsParamAReference()) { 426 soa_->AddLocalReference<jobject>(*reinterpret_cast<mirror::Object**>(GetParamAddress())); 427 } 428 } 429 430 private: 431 ScopedObjectAccessUnchecked* soa_; 432 433 DISALLOW_COPY_AND_ASSIGN(RememberFoGcArgumentVisitor); 434}; 435 436// Lazily resolve a method for quick. Called by stub code. 437extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called, 438 mirror::Object* receiver, 439 Thread* thread, mirror::ArtMethod** sp) 440 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 441 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs); 442 // Start new JNI local reference state 443 JNIEnvExt* env = thread->GetJniEnv(); 444 ScopedObjectAccessUnchecked soa(env); 445 ScopedJniEnvLocalRefState env_state(env); 446 const char* old_cause = thread->StartAssertNoThreadSuspension("Quick method resolution set up"); 447 448 // Compute details about the called method (avoid GCs) 449 ClassLinker* linker = Runtime::Current()->GetClassLinker(); 450 mirror::ArtMethod* caller = QuickArgumentVisitor::GetCallingMethod(sp); 451 InvokeType invoke_type; 452 const DexFile* dex_file; 453 uint32_t dex_method_idx; 454 if (called->IsRuntimeMethod()) { 455 uint32_t dex_pc = caller->ToDexPc(QuickArgumentVisitor::GetCallingPc(sp)); 456 const DexFile::CodeItem* code; 457 { 458 MethodHelper mh(caller); 459 dex_file = &mh.GetDexFile(); 460 code = mh.GetCodeItem(); 461 } 462 CHECK_LT(dex_pc, code->insns_size_in_code_units_); 463 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]); 464 Instruction::Code instr_code = instr->Opcode(); 465 bool is_range; 466 switch (instr_code) { 467 case Instruction::INVOKE_DIRECT: 468 invoke_type = kDirect; 469 is_range = false; 470 break; 471 case Instruction::INVOKE_DIRECT_RANGE: 472 invoke_type = kDirect; 473 is_range = true; 474 break; 475 case Instruction::INVOKE_STATIC: 476 invoke_type = kStatic; 477 is_range = false; 478 break; 479 case Instruction::INVOKE_STATIC_RANGE: 480 invoke_type = kStatic; 481 is_range = true; 482 break; 483 case Instruction::INVOKE_SUPER: 484 invoke_type = kSuper; 485 is_range = false; 486 break; 487 case Instruction::INVOKE_SUPER_RANGE: 488 invoke_type = kSuper; 489 is_range = true; 490 break; 491 case Instruction::INVOKE_VIRTUAL: 492 invoke_type = kVirtual; 493 is_range = false; 494 break; 495 case Instruction::INVOKE_VIRTUAL_RANGE: 496 invoke_type = kVirtual; 497 is_range = true; 498 break; 499 case Instruction::INVOKE_INTERFACE: 500 invoke_type = kInterface; 501 is_range = false; 502 break; 503 case Instruction::INVOKE_INTERFACE_RANGE: 504 invoke_type = kInterface; 505 is_range = true; 506 break; 507 default: 508 LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL); 509 // Avoid used uninitialized warnings. 510 invoke_type = kDirect; 511 is_range = false; 512 } 513 dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c(); 514 515 } else { 516 invoke_type = kStatic; 517 dex_file = &MethodHelper(called).GetDexFile(); 518 dex_method_idx = called->GetDexMethodIndex(); 519 } 520 uint32_t shorty_len; 521 const char* shorty = 522 dex_file->GetMethodShorty(dex_file->GetMethodId(dex_method_idx), &shorty_len); 523 RememberFoGcArgumentVisitor visitor(sp, invoke_type == kStatic, shorty, shorty_len, &soa); 524 visitor.VisitArguments(); 525 thread->EndAssertNoThreadSuspension(old_cause); 526 // Resolve method filling in dex cache. 527 if (called->IsRuntimeMethod()) { 528 called = linker->ResolveMethod(dex_method_idx, caller, invoke_type); 529 } 530 const void* code = NULL; 531 if (LIKELY(!thread->IsExceptionPending())) { 532 // Incompatible class change should have been handled in resolve method. 533 CHECK(!called->CheckIncompatibleClassChange(invoke_type)); 534 // Refine called method based on receiver. 535 if (invoke_type == kVirtual) { 536 called = receiver->GetClass()->FindVirtualMethodForVirtual(called); 537 } else if (invoke_type == kInterface) { 538 called = receiver->GetClass()->FindVirtualMethodForInterface(called); 539 } 540 // Ensure that the called method's class is initialized. 541 mirror::Class* called_class = called->GetDeclaringClass(); 542 linker->EnsureInitialized(called_class, true, true); 543 if (LIKELY(called_class->IsInitialized())) { 544 code = called->GetEntryPointFromCompiledCode(); 545 } else if (called_class->IsInitializing()) { 546 if (invoke_type == kStatic) { 547 // Class is still initializing, go to oat and grab code (trampoline must be left in place 548 // until class is initialized to stop races between threads). 549 code = linker->GetOatCodeFor(called); 550 } else { 551 // No trampoline for non-static methods. 552 code = called->GetEntryPointFromCompiledCode(); 553 } 554 } else { 555 DCHECK(called_class->IsErroneous()); 556 } 557 } 558 CHECK_EQ(code == NULL, thread->IsExceptionPending()); 559#ifdef MOVING_GARBAGE_COLLECTOR 560 // TODO: locally saved objects may have moved during a GC during resolution. Need to update the 561 // registers so that the stale objects aren't passed to the method we've resolved. 562 UNIMPLEMENTED(WARNING); 563#endif 564 // Place called method in callee-save frame to be placed as first argument to quick method. 565 *sp = called; 566 return code; 567} 568 569} // namespace art 570