// Determines the location of the code pointer.
enum class CodePtrLocation {
// Recursive call, use local PC-relative call instruction.
kCallSelf,
// Use PC-relative call instruction patched at link time.
// Used for calls within an oat file, boot->boot or app->app.
kCallPCRelative,
// Call to a known target address, embed the direct address in code.
// Used for app->boot call with non-relocatable image and for JIT-compiled calls.
kCallDirect,
// Call to a target address that will be known at link time, embed the direct
// address in code. If the image is relocatable, emit .patch_oat entry.
// Used for app->boot calls with relocatable image and boot->boot calls, whether
// the image relocatable or not.
kCallDirectWithFixup,
// Use code pointer from the ArtMethod*.
// Used when we don't know the target code. This is also the last-resort-kind used when
// other kinds are unimplemented or impractical (i.e. slow) on a particular architecture.
kCallArtMethod,
};
void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) {
//处理 ArtMethod 加载位置
...........
//生成跳转代码
switch (invoke->GetCodePtrLocation()) {
case HInvokeStaticOrDirect::CodePtrLocation::kCallSelf:
__ Bl(&frame_entry_label_);
break;
case HInvokeStaticOrDirect::CodePtrLocation::kCallPCRelative: {
relative_call_patches_.emplace_back(invoke->GetTargetMethod());
vixl::Label* label = &relative_call_patches_.back().label;
vixl::SingleEmissionCheckScope guard(GetVIXLAssembler());
__ Bind(label);
__ bl(0); // Branch and link to itself. This will be overriden at link time.
break;
}
case HInvokeStaticOrDirect::CodePtrLocation::kCallDirectWithFixup:
case HInvokeStaticOrDirect::CodePtrLocation::kCallDirect:
// LR prepared above for better instruction scheduling.
DCHECK(direct_code_loaded);
// lr()
__ Blr(lr);
break;
case HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod:
// LR = callee_method->entry_point_from_quick_compiled_code_;
__ Ldr(lr, MemOperand(
XRegisterFrom(callee_method),
ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize).Int32Value()));
// lr()
__ Blr(lr);
break;
}
}