Revert "Revert "Add support for booting with a boot classpath not fully AOTed.""
This reverts commit 14bfeddf2e434954f0ca36687ac0fc5dc6412bd3.
Reason for revert: Removes obsolete DCHECK
Bug: 119800099
Change-Id: Ia984f95300c6b96165f0179bfc2f66b012bf5dbe
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index d44bd59..69139cd 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -20,9 +20,11 @@
#include "art_method-inl.h"
#include "base/enums.h"
+#include "base/file_utils.h"
#include "base/logging.h" // For VLOG.
#include "base/memory_tool.h"
#include "base/runtime_debug.h"
+#include "base/scoped_flock.h"
#include "base/utils.h"
#include "class_root.h"
#include "debugger.h"
@@ -559,7 +561,7 @@
kCompileOsr,
};
- JitCompileTask(ArtMethod* method, TaskKind kind) : method_(method), kind_(kind) {
+ JitCompileTask(ArtMethod* method, TaskKind kind) : method_(method), kind_(kind), klass_(nullptr) {
ScopedObjectAccess soa(Thread::Current());
// Add a global ref to the class to prevent class unloading until compilation is done.
klass_ = soa.Vm()->AddGlobalRef(soa.Self(), method_->GetDeclaringClass());
@@ -606,6 +608,18 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(JitCompileTask);
};
+class ZygoteTask final : public Task {
+ public:
+ ZygoteTask() {}
+
+ void Run(Thread* self) override {
+ Runtime::Current()->GetJit()->AddNonAotBootMethodsToQueue(self);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ZygoteTask);
+};
+
void Jit::CreateThreadPool() {
// There is a DCHECK in the 'AddSamples' method to ensure the tread pool
// is not null when we instrument.
@@ -616,6 +630,91 @@
thread_pool_->SetPthreadPriority(options_->GetThreadPoolPthreadPriority());
Start();
+
+ // If we're not using the default boot image location, request a JIT task to
+ // compile all methods in the boot image profile.
+ Runtime* runtime = Runtime::Current();
+ if (runtime->IsZygote() && !runtime->IsUsingDefaultBootImageLocation()) {
+ thread_pool_->AddTask(Thread::Current(), new ZygoteTask());
+ }
+}
+
+void Jit::AddNonAotBootMethodsToQueue(Thread* self) {
+ Runtime* runtime = Runtime::Current();
+ std::string profile_location;
+ for (const std::string& option : runtime->GetImageCompilerOptions()) {
+ if (android::base::StartsWith(option, "--profile-file=")) {
+ profile_location = option.substr(strlen("--profile-file="));
+ break;
+ }
+ }
+ if (profile_location.empty()) {
+ LOG(WARNING) << "Expected a profile location in JIT zygote mode";
+ return;
+ }
+
+ std::string error_msg;
+ ScopedFlock profile_file = LockedFile::Open(
+ profile_location.c_str(), O_RDONLY, true, &error_msg);
+
+ // Return early if we're unable to obtain a lock on the profile.
+ if (profile_file.get() == nullptr) {
+ LOG(ERROR) << "Cannot lock profile: " << error_msg;
+ return;
+ }
+
+ ProfileCompilationInfo profile_info;
+ if (!profile_info.Load(profile_file->Fd())) {
+ LOG(ERROR) << "Could not load profile file";
+ return;
+ }
+
+ const std::vector<const DexFile*>& boot_class_path =
+ runtime->GetClassLinker()->GetBootClassPath();
+ ScopedObjectAccess soa(self);
+ StackHandleScope<1> hs(self);
+ MutableHandle<mirror::DexCache> dex_cache = hs.NewHandle<mirror::DexCache>(nullptr);
+ ScopedNullHandle<mirror::ClassLoader> null_handle;
+ ClassLinker* class_linker = runtime->GetClassLinker();
+
+ for (const DexFile* dex_file : boot_class_path) {
+ std::set<dex::TypeIndex> class_types;
+ std::set<uint16_t> hot_methods;
+ std::set<uint16_t> startup_methods;
+ std::set<uint16_t> post_startup_methods;
+ std::set<uint16_t> combined_methods;
+ if (!profile_info.GetClassesAndMethods(*dex_file,
+ &class_types,
+ &hot_methods,
+ &startup_methods,
+ &post_startup_methods)) {
+ LOG(ERROR) << "Unable to get classes and methods for " << dex_file->GetLocation();
+ continue;
+ }
+ dex_cache.Assign(class_linker->FindDexCache(self, *dex_file));
+ CHECK(dex_cache != nullptr) << "Could not find dex cache for " << dex_file->GetLocation();
+ for (uint16_t method_idx : startup_methods) {
+ ArtMethod* method = class_linker->ResolveMethodWithoutInvokeType(
+ method_idx, dex_cache, null_handle);
+ if (method == nullptr) {
+ self->ClearException();
+ continue;
+ }
+ if (!method->IsCompilable() || !method->IsInvokable()) {
+ continue;
+ }
+ const void* entry_point = method->GetEntryPointFromQuickCompiledCode();
+ if (class_linker->IsQuickToInterpreterBridge(entry_point) ||
+ class_linker->IsQuickGenericJniStub(entry_point)) {
+ if (!method->IsNative()) {
+ // The compiler requires a ProfilingInfo object for non-native methods.
+ ProfilingInfo::Create(self, method, /* retry_allocation= */ true);
+ }
+ thread_pool_->AddTask(self,
+ new JitCompileTask(method, JitCompileTask::TaskKind::kCompile));
+ }
+ }
+ }
}
static bool IgnoreSamplesForMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 714db3a..f709de3 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -303,6 +303,10 @@
// Adjust state after forking.
void PostZygoteFork();
+ // In case the boot classpath is not fully AOTed, add methods from the boot profile to the
+ // compilation queue.
+ void AddNonAotBootMethodsToQueue(Thread* self);
+
private:
Jit(JitCodeCache* code_cache, JitOptions* options);
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 891ecef..da0e048 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -287,7 +287,7 @@
runtime_flags &= ~DISABLE_VERIFIER;
}
- if ((runtime_flags & ONLY_USE_SYSTEM_OAT_FILES) != 0) {
+ if ((runtime_flags & ONLY_USE_SYSTEM_OAT_FILES) != 0 || is_system_server) {
Runtime::Current()->GetOatFileManager().SetOnlyUseSystemOatFiles();
runtime_flags &= ~ONLY_USE_SYSTEM_OAT_FILES;
}
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 80ac01f..f1708b4 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -783,6 +783,7 @@
if (executable && oat_file_assistant_->only_load_system_executable_) {
executable = LocationIsOnSystem(filename_.c_str());
}
+ VLOG(oat) << "Loading " << filename_ << " with executable: " << executable;
std::string error_msg;
if (use_fd_) {
if (oat_fd_ >= 0 && vdex_fd_ >= 0) {
@@ -809,6 +810,8 @@
if (file_.get() == nullptr) {
VLOG(oat) << "OatFileAssistant test for existing oat file "
<< filename_ << ": " << error_msg;
+ } else {
+ VLOG(oat) << "Successfully loaded " << filename_ << " with executable: " << executable;
}
}
}
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index b78c152..6423f3b 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -606,8 +606,7 @@
}
if (!args.Exists(M::CompilerCallbacksPtr) && !args.Exists(M::Image)) {
- std::string image = GetAndroidRoot();
- image += "/framework/boot.art";
+ std::string image = GetDefaultBootImageLocation(GetAndroidRoot());
args.Set(M::Image, image);
}
diff --git a/runtime/runtime.h b/runtime/runtime.h
index ed6ee45..ace0eea 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -27,6 +27,7 @@
#include <memory>
#include <vector>
+#include "base/file_utils.h"
#include "base/locks.h"
#include "base/macros.h"
#include "base/mem_map.h"
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index 72c42b9..61cd982 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -178,7 +178,6 @@
reinterpret_cast<DexSectionHeader*>(vdex->mmap_.Begin() + offset)->quickening_info_size_ = 0;
}
- *error_msg = "Success";
return vdex;
}