Support for inlining methods that call/throw.
Mostly fixes here and there to make it working.
Change-Id: I1b535e895105d78b65634636d675b818551f783e
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 625e695..526fb8d 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -38,6 +38,29 @@
namespace art {
+inline mirror::ArtMethod* GetResolvedMethod(mirror::ArtMethod* outer_method,
+ uint32_t method_index,
+ InvokeType invoke_type)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::ArtMethod* caller = outer_method->GetDexCacheResolvedMethod(method_index);
+ if (!caller->IsRuntimeMethod()) {
+ return caller;
+ }
+
+ // The method in the dex cache can be the runtime method responsible for invoking
+ // the stub that will then update the dex cache. Therefore, we need to do the
+ // resolution ourselves.
+
+ StackHandleScope<3> hs(Thread::Current());
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Handle<mirror::ArtMethod> outer(hs.NewHandle(outer_method));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(outer->GetClassLoader()));
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(outer->GetDexCache()));
+ Handle<mirror::ArtMethod> referrer;
+ return class_linker->ResolveMethod(
+ *outer->GetDexFile(), method_index, dex_cache, class_loader, referrer, invoke_type);
+}
+
inline mirror::ArtMethod* GetCalleeSaveMethodCaller(StackReference<mirror::ArtMethod>* sp,
Runtime::CalleeSaveType type,
bool do_caller_check = false)
@@ -47,7 +70,25 @@
const size_t callee_frame_size = GetCalleeSaveFrameSize(kRuntimeISA, type);
auto* caller_sp = reinterpret_cast<StackReference<mirror::ArtMethod>*>(
reinterpret_cast<uintptr_t>(sp) + callee_frame_size);
- auto* caller = caller_sp->AsMirrorPtr();
+ mirror::ArtMethod* outer_method = caller_sp->AsMirrorPtr();
+ mirror::ArtMethod* caller = outer_method;
+
+ if ((outer_method != nullptr) && outer_method->IsOptimized(sizeof(void*))) {
+ const size_t callee_return_pc_offset = GetCalleeSaveReturnPcOffset(kRuntimeISA, type);
+ uintptr_t caller_pc = *reinterpret_cast<uintptr_t*>(
+ (reinterpret_cast<uint8_t*>(sp) + callee_return_pc_offset));
+ uintptr_t native_pc_offset = outer_method->NativeQuickPcOffset(caller_pc);
+ CodeInfo code_info = outer_method->GetOptimizedCodeInfo();
+ StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+ DCHECK(stack_map.IsValid());
+ if (stack_map.HasInlineInfo(code_info)) {
+ InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
+ uint32_t method_index = inline_info.GetMethodIndexAtDepth(inline_info.GetDepth() - 1);
+ InvokeType invoke_type = static_cast<InvokeType>(
+ inline_info.GetInvokeTypeAtDepth(inline_info.GetDepth() - 1));
+ caller = GetResolvedMethod(outer_method, method_index, invoke_type);
+ }
+ }
if (kIsDebugBuild && do_caller_check) {
// Note that do_caller_check is optional, as this method can be called by