Merge "Prevent spurious dexopts in 32-64 builds."
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 703229c..18afa02 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -803,13 +803,29 @@
bool ClassLinker::VerifyOatFileChecksums(const OatFile* oat_file,
const char* dex_location,
uint32_t dex_location_checksum,
+ const InstructionSet instruction_set,
std::string* error_msg) {
Runtime* runtime = Runtime::Current();
- const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
- uint32_t image_oat_checksum = image_header.GetOatChecksum();
- uintptr_t image_oat_data_begin = reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin());
- bool image_check = ((oat_file->GetOatHeader().GetImageFileLocationOatChecksum() == image_oat_checksum)
- && (oat_file->GetOatHeader().GetImageFileLocationOatDataBegin() == image_oat_data_begin));
+ const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace();
+
+ // If the requested instruction set is the same as the current runtime,
+ // we can use the checksums directly. If it isn't, we'll have to read the
+ // image header from the image for the right instruction set.
+ uint32_t image_oat_checksum = 0;
+ uintptr_t image_oat_data_begin = 0;
+ if (instruction_set == kRuntimeISA) {
+ const ImageHeader& image_header = image_space->GetImageHeader();
+ image_oat_checksum = image_header.GetOatChecksum();
+ image_oat_data_begin = reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin());
+ } else {
+ UniquePtr<ImageHeader> image_header(gc::space::ImageSpace::ReadImageHeaderOrDie(
+ image_space->GetImageLocation().c_str(), instruction_set));
+ image_oat_checksum = image_header->GetOatChecksum();
+ image_oat_data_begin = reinterpret_cast<uintptr_t>(image_header->GetOatDataBegin());
+ }
+ const OatHeader& oat_header = oat_file->GetOatHeader();
+ bool image_check = ((oat_header.GetImageFileLocationOatChecksum() == image_oat_checksum)
+ && (oat_header.GetImageFileLocationOatDataBegin() == image_oat_data_begin));
const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location, &dex_location_checksum);
if (oat_dex_file == NULL) {
@@ -873,7 +889,7 @@
dex_file = oat_dex_file->OpenDexFile(error_msg);
} else {
bool verified = VerifyOatFileChecksums(oat_file.get(), dex_location, dex_location_checksum,
- error_msg);
+ kRuntimeISA, error_msg);
if (!verified) {
return nullptr;
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index a23add0..2c6873e 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -288,6 +288,7 @@
static bool VerifyOatFileChecksums(const OatFile* oat_file,
const char* dex_location,
uint32_t dex_location_checksum,
+ const InstructionSet instruction_set,
std::string* error_msg);
// TODO: replace this with multiple methods that allocate the correct managed type.
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 3de1ba4..858582e 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -33,15 +33,16 @@
Atomic<uint32_t> ImageSpace::bitmap_index_(0);
-ImageSpace::ImageSpace(const std::string& name, MemMap* mem_map,
- accounting::ContinuousSpaceBitmap* live_bitmap)
- : MemMapSpace(name, mem_map, mem_map->Begin(), mem_map->End(), mem_map->End(),
- kGcRetentionPolicyNeverCollect) {
+ImageSpace::ImageSpace(const std::string& image_filename, const char* image_location,
+ MemMap* mem_map, accounting::ContinuousSpaceBitmap* live_bitmap)
+ : MemMapSpace(image_filename, mem_map, mem_map->Begin(), mem_map->End(), mem_map->End(),
+ kGcRetentionPolicyNeverCollect),
+ image_location_(image_location) {
DCHECK(live_bitmap != nullptr);
live_bitmap_.reset(live_bitmap);
}
-static bool GenerateImage(const std::string& image_file_name, std::string* error_msg) {
+static bool GenerateImage(const std::string& image_filename, std::string* error_msg) {
const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString());
std::vector<std::string> boot_class_path;
Split(boot_class_path_string, ':', boot_class_path);
@@ -57,7 +58,7 @@
arg_vector.push_back(dex2oat);
std::string image_option_string("--image=");
- image_option_string += image_file_name;
+ image_option_string += image_filename;
arg_vector.push_back(image_option_string);
arg_vector.push_back("--runtime-arg");
@@ -72,7 +73,7 @@
}
std::string oat_file_option_string("--oat-file=");
- oat_file_option_string += image_file_name;
+ oat_file_option_string += image_filename;
oat_file_option_string.erase(oat_file_option_string.size() - 3);
oat_file_option_string += "oat";
arg_vector.push_back(oat_file_option_string);
@@ -98,37 +99,72 @@
return Exec(arg_vector, error_msg);
}
-ImageSpace* ImageSpace::Create(const char* original_image_file_name,
- const InstructionSet image_isa) {
- if (OS::FileExists(original_image_file_name)) {
- // If the /system file exists, it should be up-to-date, don't try to generate
- std::string error_msg;
- ImageSpace* space = ImageSpace::Init(original_image_file_name, false, &error_msg);
- if (space == nullptr) {
- LOG(FATAL) << "Failed to load image '" << original_image_file_name << "': " << error_msg;
- }
- return space;
+bool ImageSpace::FindImageFilename(const char* image_location,
+ const InstructionSet image_isa,
+ std::string* image_filename,
+ bool *is_system) {
+ if (OS::FileExists(image_location)) {
+ *image_filename = image_location;
+ *is_system = true;
+ return true;
}
- // If the /system file didn't exist, we need to use one from the dalvik-cache.
- // If the cache file exists, try to open, but if it fails, regenerate.
- // If it does not exist, generate.
+
const std::string dalvik_cache = GetDalvikCacheOrDie(GetInstructionSetString(image_isa));
- std::string image_file_name(GetDalvikCacheFilenameOrDie(original_image_file_name,
- dalvik_cache.c_str()));
+
+ // Always set output location even if it does not exist,
+ // so that the caller knows where to create the image.
+ *image_filename = GetDalvikCacheFilenameOrDie(image_location, dalvik_cache.c_str());
+ *is_system = false;
+ return OS::FileExists(image_filename->c_str());
+}
+
+ImageHeader* ImageSpace::ReadImageHeaderOrDie(const char* image_location,
+ const InstructionSet image_isa) {
+ std::string image_filename;
+ bool is_system = false;
+ if (FindImageFilename(image_location, image_isa, &image_filename, &is_system)) {
+ UniquePtr<File> image_file(OS::OpenFileForReading(image_filename.c_str()));
+ UniquePtr<ImageHeader> image_header(new ImageHeader);
+ const bool success = image_file->ReadFully(image_header.get(), sizeof(ImageHeader));
+ if (!success || !image_header->IsValid()) {
+ LOG(FATAL) << "Invalid Image header for: " << image_filename;
+ return nullptr;
+ }
+
+ return image_header.release();
+ }
+
+ LOG(FATAL) << "Unable to find image file for: " << image_location;
+ return nullptr;
+}
+
+ImageSpace* ImageSpace::Create(const char* image_location,
+ const InstructionSet image_isa) {
+ std::string image_filename;
std::string error_msg;
- if (OS::FileExists(image_file_name.c_str())) {
- space::ImageSpace* image_space = ImageSpace::Init(image_file_name.c_str(), true, &error_msg);
- if (image_space != nullptr) {
- return image_space;
+ bool is_system = false;
+ if (FindImageFilename(image_location, image_isa, &image_filename, &is_system)) {
+ ImageSpace* space = ImageSpace::Init(image_filename.c_str(), image_location,
+ !is_system, &error_msg);
+ if (space != nullptr) {
+ return space;
+ }
+
+ // If the /system file exists, it should be up-to-date, don't try to generate it.
+ // If it's not the /system file, log a warning and fall through to GenerateImage.
+ if (is_system) {
+ LOG(FATAL) << "Failed to load image '" << image_filename << "': " << error_msg;
+ return nullptr;
} else {
LOG(WARNING) << error_msg;
}
}
- CHECK(GenerateImage(image_file_name, &error_msg))
- << "Failed to generate image '" << image_file_name << "': " << error_msg;
- ImageSpace* space = ImageSpace::Init(image_file_name.c_str(), true, &error_msg);
+
+ CHECK(GenerateImage(image_filename, &error_msg))
+ << "Failed to generate image '" << image_filename << "': " << error_msg;
+ ImageSpace* space = ImageSpace::Init(image_filename.c_str(), image_location, true, &error_msg);
if (space == nullptr) {
- LOG(FATAL) << "Failed to load image '" << original_image_file_name << "': " << error_msg;
+ LOG(FATAL) << "Failed to load image '" << image_filename << "': " << error_msg;
}
return space;
}
@@ -147,25 +183,26 @@
}
}
-ImageSpace* ImageSpace::Init(const char* image_file_name, bool validate_oat_file,
- std::string* error_msg) {
- CHECK(image_file_name != nullptr);
+ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_location,
+ bool validate_oat_file, std::string* error_msg) {
+ CHECK(image_filename != nullptr);
+ CHECK(image_location != nullptr);
uint64_t start_time = 0;
if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
start_time = NanoTime();
- LOG(INFO) << "ImageSpace::Init entering image_file_name=" << image_file_name;
+ LOG(INFO) << "ImageSpace::Init entering image_filename=" << image_filename;
}
- UniquePtr<File> file(OS::OpenFileForReading(image_file_name));
+ UniquePtr<File> file(OS::OpenFileForReading(image_filename));
if (file.get() == NULL) {
- *error_msg = StringPrintf("Failed to open '%s'", image_file_name);
+ *error_msg = StringPrintf("Failed to open '%s'", image_filename);
return nullptr;
}
ImageHeader image_header;
bool success = file->ReadFully(&image_header, sizeof(image_header));
if (!success || !image_header.IsValid()) {
- *error_msg = StringPrintf("Invalid image header in '%s'", image_file_name);
+ *error_msg = StringPrintf("Invalid image header in '%s'", image_filename);
return nullptr;
}
@@ -177,7 +214,7 @@
file->Fd(),
0,
false,
- image_file_name,
+ image_filename,
error_msg));
if (map.get() == NULL) {
DCHECK(!error_msg->empty());
@@ -190,14 +227,14 @@
PROT_READ, MAP_PRIVATE,
file->Fd(), image_header.GetBitmapOffset(),
false,
- image_file_name,
+ image_filename,
error_msg));
if (image_map.get() == nullptr) {
*error_msg = StringPrintf("Failed to map image bitmap: %s", error_msg->c_str());
return nullptr;
}
uint32_t bitmap_index = bitmap_index_.FetchAndAdd(1);
- std::string bitmap_name(StringPrintf("imagespace %s live-bitmap %u", image_file_name,
+ std::string bitmap_name(StringPrintf("imagespace %s live-bitmap %u", image_filename,
bitmap_index));
UniquePtr<accounting::ContinuousSpaceBitmap> bitmap(
accounting::ContinuousSpaceBitmap::CreateFromMemMap(bitmap_name, image_map.release(),
@@ -223,12 +260,13 @@
callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsAndArgsSaveMethod);
runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kRefsAndArgs);
- UniquePtr<ImageSpace> space(new ImageSpace(image_file_name, map.release(), bitmap.release()));
+ UniquePtr<ImageSpace> space(new ImageSpace(image_filename, image_location,
+ map.release(), bitmap.release()));
if (kIsDebugBuild) {
space->VerifyImageAllocations();
}
- space->oat_file_.reset(space->OpenOatFile(image_file_name, error_msg));
+ space->oat_file_.reset(space->OpenOatFile(image_filename, error_msg));
if (space->oat_file_.get() == nullptr) {
DCHECK(!error_msg->empty());
return nullptr;
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index 1652ec9..622371f 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -46,6 +46,11 @@
static ImageSpace* Create(const char* image, const InstructionSet image_isa)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Reads the image header from the specified image location for the
+ // instruction set image_isa.
+ static ImageHeader* ReadImageHeaderOrDie(const char* image_location,
+ const InstructionSet image_isa);
+
// Releases the OatFile from the ImageSpace so it can be transfer to
// the caller, presumably the ClassLinker.
OatFile* ReleaseOatFile()
@@ -58,10 +63,18 @@
return *reinterpret_cast<ImageHeader*>(Begin());
}
+ // Actual filename where image was loaded from.
+ // For example: /data/dalvik-cache/arm/system@framework@boot.art
const std::string GetImageFilename() const {
return GetName();
}
+ // Symbolic location for image.
+ // For example: /system/framework/boot.art
+ const std::string GetImageLocation() const {
+ return image_location_;
+ }
+
accounting::ContinuousSpaceBitmap* GetLiveBitmap() const OVERRIDE {
return live_bitmap_.get();
}
@@ -90,9 +103,21 @@
// image's OatFile is up-to-date relative to its DexFile
// inputs. Otherwise (for /data), validate the inputs and generate
// the OatFile in /data/dalvik-cache if necessary.
- static ImageSpace* Init(const char* image, bool validate_oat_file, std::string* error_msg)
+ static ImageSpace* Init(const char* image_filename, const char* image_location,
+ bool validate_oat_file, std::string* error_msg)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Returns the filename of the image corresponding to
+ // requested image_location, or the filename where a new image
+ // should be written if one doesn't exist. Looks for a generated
+ // image in the specified location and then in the dalvik-cache.
+ //
+ // Returns true if an image was found, false otherwise.
+ static bool FindImageFilename(const char* image_location,
+ const InstructionSet image_isa,
+ std::string* location,
+ bool* is_system);
+
OatFile* OpenOatFile(const char* image, std::string* error_msg) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -105,14 +130,16 @@
UniquePtr<accounting::ContinuousSpaceBitmap> live_bitmap_;
- ImageSpace(const std::string& name, MemMap* mem_map,
- accounting::ContinuousSpaceBitmap* live_bitmap);
+ ImageSpace(const std::string& name, const char* image_location,
+ MemMap* mem_map, accounting::ContinuousSpaceBitmap* live_bitmap);
// The OatFile associated with the image during early startup to
// reserve space contiguous to the image. It is later released to
// the ClassLinker during it's initialization.
UniquePtr<OatFile> oat_file_;
+ const std::string image_location_;
+
DISALLOW_COPY_AND_ASSIGN(ImageSpace);
};
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index d9c1309..ed1ee7a 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -377,6 +377,8 @@
}
}
+ const InstructionSet target_instruction_set = GetInstructionSetFromString(instruction_set);
+
// Check if we have an odex file next to the dex file.
std::string odex_filename(OatFile::DexFilenameToOdexFilename(filename));
std::string error_msg;
@@ -403,6 +405,7 @@
return JNI_FALSE;
}
if (ClassLinker::VerifyOatFileChecksums(oat_file.get(), filename, location_checksum,
+ target_instruction_set,
&error_msg)) {
if (kVerboseLogging) {
LOG(INFO) << "DexFile_isDexOptNeeded precompiled file " << odex_filename
@@ -433,33 +436,6 @@
return JNI_TRUE;
}
- for (const auto& space : runtime->GetHeap()->GetContinuousSpaces()) {
- if (space->IsImageSpace()) {
- // TODO: Ensure this works with multiple image spaces.
- const ImageHeader& image_header = space->AsImageSpace()->GetImageHeader();
- if (oat_file->GetOatHeader().GetImageFileLocationOatChecksum() !=
- image_header.GetOatChecksum()) {
- if (kReasonLogging) {
- ScopedObjectAccess soa(env);
- LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
- << " has out-of-date oat checksum compared to "
- << oat_file->GetLocation();
- }
- return JNI_TRUE;
- }
- if (oat_file->GetOatHeader().GetImageFileLocationOatDataBegin()
- != reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin())) {
- if (kReasonLogging) {
- ScopedObjectAccess soa(env);
- LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
- << " has out-of-date oat begin compared to "
- << oat_file->GetLocation();
- }
- return JNI_TRUE;
- }
- }
- }
-
uint32_t location_checksum;
if (!DexFile::GetChecksum(filename, &location_checksum, &error_msg)) {
if (kReasonLogging) {
@@ -470,7 +446,7 @@
}
if (!ClassLinker::VerifyOatFileChecksums(oat_file.get(), filename, location_checksum,
- &error_msg)) {
+ target_instruction_set, &error_msg)) {
if (kReasonLogging) {
LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
<< " has out-of-date checksum compared to " << filename