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