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