diff options
Diffstat (limited to 'runtime/entrypoints/entrypoint_utils-inl.h')
-rw-r--r-- | runtime/entrypoints/entrypoint_utils-inl.h | 89 |
1 files changed, 37 insertions, 52 deletions
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 14c9c21356..72dad0cb32 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -52,21 +52,19 @@ inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method, // suspended while executing it. ScopedAssertNoThreadSuspension sants(__FUNCTION__); + if (inline_info.EncodesArtMethodAtDepth(encoding, inlining_depth)) { + return inline_info.GetArtMethodAtDepth(encoding, inlining_depth); + } + uint32_t method_index = inline_info.GetMethodIndexAtDepth(encoding, inlining_depth); - InvokeType invoke_type = static_cast<InvokeType>( - inline_info.GetInvokeTypeAtDepth(encoding, inlining_depth)); - ArtMethod* inlined_method = outer_method->GetDexCacheResolvedMethod(method_index, - kRuntimePointerSize); - if (!inlined_method->IsRuntimeMethod()) { + if (inline_info.GetDexPcAtDepth(encoding, inlining_depth) == static_cast<uint32_t>(-1)) { + // "charAt" special case. It is the only non-leaf method we inline across dex files. + ArtMethod* inlined_method = jni::DecodeArtMethod(WellKnownClasses::java_lang_String_charAt); + DCHECK_EQ(inlined_method->GetDexMethodIndex(), method_index); return inlined_method; } - // The method in the dex cache is the runtime method responsible for invoking - // the stub that will then update the dex cache. Therefore, we need to do the - // resolution ourselves. - - // We first find the dex cache of our caller. If it is the outer method, we can directly - // use its dex cache. Otherwise, we also need to resolve our caller. + // Find which method did the call in the inlining hierarchy. ArtMethod* caller = outer_method; if (inlining_depth != 0) { caller = GetResolvedMethod(outer_method, @@ -74,51 +72,38 @@ inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method, encoding, inlining_depth - 1); } - DCHECK_EQ(caller->GetDexCache(), outer_method->GetDexCache()) - << "Compiler only supports inlining calls within the same dex cache"; - const DexFile* dex_file = outer_method->GetDexFile(); - const DexFile::MethodId& method_id = dex_file->GetMethodId(method_index); - if (inline_info.GetDexPcAtDepth(encoding, inlining_depth) == static_cast<uint32_t>(-1)) { - // "charAt" special case. It is the only non-leaf method we inline across dex files. - if (kIsDebugBuild) { - const char* name = dex_file->StringDataByIdx(method_id.name_idx_); - DCHECK_EQ(std::string(name), "charAt"); - DCHECK_EQ(std::string(dex_file->GetMethodShorty(method_id)), "CI") - << std::string(dex_file->GetMethodShorty(method_id)); - DCHECK_EQ(std::string(dex_file->StringByTypeIdx(method_id.class_idx_)), "Ljava/lang/String;") - << std::string(dex_file->StringByTypeIdx(method_id.class_idx_)); - } - mirror::Class* cls = - Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kJavaLangString); - // Update the dex cache for future lookups. - caller->GetDexCache()->SetResolvedType(method_id.class_idx_, cls); - inlined_method = cls->FindVirtualMethod("charAt", "(I)C", kRuntimePointerSize); - } else { - mirror::Class* klass = caller->GetDexCache()->GetResolvedType(method_id.class_idx_); - DCHECK_EQ(klass->GetDexCache(), caller->GetDexCache()) - << "Compiler only supports inlining calls within the same dex cache"; - switch (invoke_type) { - case kDirect: - case kStatic: - inlined_method = - klass->FindDirectMethod(klass->GetDexCache(), method_index, kRuntimePointerSize); - break; - case kSuper: - case kVirtual: - inlined_method = - klass->FindVirtualMethod(klass->GetDexCache(), method_index, kRuntimePointerSize); - break; - default: - LOG(FATAL) << "Unimplemented inlined invocation type: " << invoke_type; - UNREACHABLE(); + // Lookup the declaring class of the inlined method. + const DexFile* dex_file = caller->GetDexFile(); + const DexFile::MethodId& method_id = dex_file->GetMethodId(method_index); + const char* descriptor = dex_file->StringByTypeIdx(method_id.class_idx_); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Thread* self = Thread::Current(); + mirror::ClassLoader* class_loader = caller->GetDeclaringClass()->GetClassLoader(); + mirror::Class* klass = class_linker->LookupClass(self, descriptor, class_loader); + if (klass == nullptr) { + LOG(FATAL) << "Could not find an inlined method from an .oat file: " + << "the class " << descriptor << " was not found in the class loader of " + << caller->PrettyMethod() << ". " + << "This must be due to playing wrongly with class loaders"; + } + + // Lookup the method. + const char* method_name = dex_file->GetMethodName(method_id); + const Signature signature = dex_file->GetMethodSignature(method_id); + + ArtMethod* inlined_method = + klass->FindDeclaredDirectMethod(method_name, signature, kRuntimePointerSize); + if (inlined_method == nullptr) { + inlined_method = klass->FindDeclaredVirtualMethod(method_name, signature, kRuntimePointerSize); + if (inlined_method == nullptr) { + LOG(FATAL) << "Could not find an inlined method from an .oat file: " + << "the class " << descriptor << " does not have " + << method_name << signature << " declared. " + << "This must be due to duplicate classes or playing wrongly with class loaders"; } } - // Update the dex cache for future lookups. Note that for static methods, this is safe - // when the class is being initialized, as the entrypoint for the ArtMethod is at - // this point still the resolution trampoline. - outer_method->SetDexCacheResolvedMethod(method_index, inlined_method, kRuntimePointerSize); return inlined_method; } |