Use /system/framework/framework.jar:preloaded-classes for on device dex2oat
Change-Id: I30ccbd5295a2979b9c89f00c93ad316d9b6475e9
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 7cf54b4..6397f40 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -18,8 +18,9 @@
#include <stdlib.h>
#include <sys/stat.h>
-#include <iostream>
#include <fstream>
+#include <iostream>
+#include <sstream>
#include <string>
#include <vector>
@@ -164,27 +165,54 @@
// Reads the class names (java.lang.Object) and returns as set of class descriptors (Ljava/lang/Object;)
- CompilerDriver::DescriptorSet* ReadImageClasses(const char* image_classes_filename) {
+ CompilerDriver::DescriptorSet* ReadImageClassesFromFile(const char* image_classes_filename) {
UniquePtr<std::ifstream> image_classes_file(new std::ifstream(image_classes_filename, std::ifstream::in));
if (image_classes_file.get() == NULL) {
LOG(ERROR) << "Failed to open image classes file " << image_classes_filename;
return NULL;
}
+ UniquePtr<CompilerDriver::DescriptorSet> result(ReadImageClasses(*image_classes_file.get()));
+ image_classes_file->close();
+ return result.release();
+ }
+ CompilerDriver::DescriptorSet* ReadImageClasses(std::istream& image_classes_stream) {
UniquePtr<CompilerDriver::DescriptorSet> image_classes(new CompilerDriver::DescriptorSet);
- while (image_classes_file->good()) {
+ while (image_classes_stream.good()) {
std::string dot;
- std::getline(*image_classes_file.get(), dot);
+ std::getline(image_classes_stream, dot);
if (StartsWith(dot, "#") || dot.empty()) {
continue;
}
std::string descriptor(DotToDescriptor(dot.c_str()));
image_classes->insert(descriptor);
}
- image_classes_file->close();
return image_classes.release();
}
+ // Reads the class names (java.lang.Object) and returns as set of class descriptors (Ljava/lang/Object;)
+ CompilerDriver::DescriptorSet* ReadImageClassesFromZip(const std::string& zip_filename, const char* image_classes_filename) {
+ UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(zip_filename));
+ if (zip_archive.get() == NULL) {
+ LOG(ERROR) << "Failed to open zip file " << zip_filename;
+ return NULL;
+ }
+ UniquePtr<ZipEntry> zip_entry(zip_archive->Find(image_classes_filename));
+ if (zip_entry.get() == NULL) {
+ LOG(ERROR) << "Failed to find " << image_classes_filename << " within " << zip_filename;
+ return NULL;
+ }
+ UniquePtr<MemMap> image_classes_file(zip_entry->ExtractToMemMap(image_classes_filename));
+ if (image_classes_file.get() == NULL) {
+ LOG(ERROR) << "Failed to extract " << image_classes_filename << " from " << zip_filename;
+ return NULL;
+ }
+ const std::string image_classes_string(reinterpret_cast<char*>(image_classes_file->Begin()),
+ image_classes_file->Size());
+ std::istringstream image_classes_stream(image_classes_string);
+ return ReadImageClasses(image_classes_stream);
+ }
+
const CompilerDriver* CreateOatFile(const std::string& boot_image_option,
const std::string* host_prefix,
const std::string& android_root,
@@ -558,6 +586,7 @@
std::string oat_location;
int oat_fd = -1;
std::string bitcode_filename;
+ const char* image_classes_zip_filename = NULL;
const char* image_classes_filename = NULL;
std::string image_filename;
std::string boot_image_filename;
@@ -632,6 +661,8 @@
image_filename = option.substr(strlen("--image=")).data();
} else if (option.starts_with("--image-classes=")) {
image_classes_filename = option.substr(strlen("--image-classes=")).data();
+ } else if (option.starts_with("--image-classes-zip=")) {
+ image_classes_zip_filename = option.substr(strlen("--image-classes-zip=")).data();
} else if (option.starts_with("--base=")) {
const char* image_base_str = option.substr(strlen("--base=")).data();
char* end;
@@ -735,6 +766,10 @@
Usage("--image-classes should not be used with --boot-image");
}
+ if (image_classes_zip_filename != NULL && image_classes_filename == NULL) {
+ Usage("--image-classes-zip should be used with --image-classes");
+ }
+
if (dex_filenames.empty() && zip_fd == -1) {
Usage("Input must be supplied with either --dex-file or --zip-fd");
}
@@ -846,7 +881,12 @@
// If --image-classes was specified, calculate the full list of classes to include in the image
UniquePtr<CompilerDriver::DescriptorSet> image_classes(NULL);
if (image_classes_filename != NULL) {
- image_classes.reset(dex2oat->ReadImageClasses(image_classes_filename));
+ if (image_classes_zip_filename != NULL) {
+ image_classes.reset(dex2oat->ReadImageClassesFromZip(image_classes_zip_filename,
+ image_classes_filename));
+ } else {
+ image_classes.reset(dex2oat->ReadImageClassesFromFile(image_classes_filename));
+ }
if (image_classes.get() == NULL) {
LOG(ERROR) << "Failed to create list of image classes from " << image_classes_filename;
return EXIT_FAILURE;
@@ -860,7 +900,7 @@
if (dex_filenames.empty()) {
UniquePtr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(zip_fd));
if (zip_archive.get() == NULL) {
- LOG(ERROR) << "Failed to zip from file descriptor for " << zip_location;
+ LOG(ERROR) << "Failed to open zip from file descriptor for " << zip_location;
return EXIT_FAILURE;
}
const DexFile* dex_file = DexFile::Open(*zip_archive.get(), zip_location);
diff --git a/src/dex_file.cc b/src/dex_file.cc
index 80465f2..1e37dcd 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -206,26 +206,15 @@
CHECK(!location.empty());
UniquePtr<ZipEntry> zip_entry(zip_archive.Find(kClassesDex));
if (zip_entry.get() == NULL) {
- LOG(ERROR) << "Failed to find classes.dex within " << location;
+ LOG(ERROR) << "Failed to find classes.dex within '" << location << "'";
return NULL;
}
- uint32_t length = zip_entry->GetUncompressedLength();
- std::string name("classes.dex extracted in memory from ");
- name += location;
- UniquePtr<MemMap> map(MemMap::MapAnonymous(name.c_str(), NULL, length, PROT_READ | PROT_WRITE));
+ UniquePtr<MemMap> map(zip_entry->ExtractToMemMap(kClassesDex));
if (map.get() == NULL) {
- LOG(ERROR) << "mmap classes.dex for \"" << location << "\" failed";
+ LOG(ERROR) << "Failed to extract '" << kClassesDex << "' from '" << location << "'";
return NULL;
}
-
- // Extract classes.dex
- bool success = zip_entry->ExtractToMemory(*map.get());
- if (!success) {
- LOG(ERROR) << "Failed to extract classes.dex from '" << location << "' to memory";
- return NULL;
- }
-
const DexFile* dex_file = OpenMemory(location, zip_entry->GetCrc32(), map.release());
if (dex_file == NULL) {
LOG(ERROR) << "Failed to open dex file '" << location << "' from memory";
diff --git a/src/gc/heap.cc b/src/gc/heap.cc
index 9ec1f21..7bd8687 100644
--- a/src/gc/heap.cc
+++ b/src/gc/heap.cc
@@ -109,7 +109,10 @@
std::string base_option_string(StringPrintf("--base=0x%x", ART_BASE_ADDRESS));
arg_vector.push_back(strdup(base_option_string.c_str()));
- if (!kIsTargetBuild) {
+ if (kIsTargetBuild) {
+ arg_vector.push_back(strdup("--image-classes-zip=/system/framework/framework.jar"));
+ arg_vector.push_back(strdup("--image-classes=preloaded-classes"));
+ } else {
arg_vector.push_back(strdup("--host"));
}
diff --git a/src/zip_archive.cc b/src/zip_archive.cc
index c9e9c0a..9cf7a09 100644
--- a/src/zip_archive.cc
+++ b/src/zip_archive.cc
@@ -121,8 +121,8 @@
return data_offset;
}
-static bool CopyFdToMemory(MemMap& mem_map, int in, size_t count) {
- uint8_t* dst = mem_map.Begin();
+static bool CopyFdToMemory(uint8_t* begin, size_t size, int in, size_t count) {
+ uint8_t* dst = begin;
std::vector<uint8_t> buf(kBufSize);
while (count != 0) {
size_t bytes_to_read = (count > kBufSize) ? kBufSize : count;
@@ -135,7 +135,7 @@
dst += bytes_to_read;
count -= bytes_to_read;
}
- DCHECK_EQ(dst, mem_map.End());
+ DCHECK_EQ(dst, begin + size);
return true;
}
@@ -165,8 +165,9 @@
z_stream zstream_;
};
-static bool InflateToMemory(MemMap& mem_map, int in, size_t uncompressed_length, size_t compressed_length) {
- uint8_t* dst = mem_map.Begin();
+static bool InflateToMemory(uint8_t* begin, size_t size,
+ int in, size_t uncompressed_length, size_t compressed_length) {
+ uint8_t* dst = begin;
UniquePtr<uint8_t[]> read_buf(new uint8_t[kBufSize]);
UniquePtr<uint8_t[]> write_buf(new uint8_t[kBufSize]);
if (read_buf.get() == NULL || write_buf.get() == NULL) {
@@ -236,7 +237,7 @@
return false;
}
- DCHECK_EQ(dst, mem_map.End());
+ DCHECK_EQ(dst, begin + size);
return true;
}
@@ -254,10 +255,10 @@
return false;
}
- return ExtractToMemory(*map.get());
+ return ExtractToMemory(map->Begin(), map->Size());
}
-bool ZipEntry::ExtractToMemory(MemMap& mem_map) {
+bool ZipEntry::ExtractToMemory(uint8_t* begin, size_t size) {
off_t data_offset = GetDataOffset();
if (data_offset == -1) {
LOG(WARNING) << "Zip: data_offset=" << data_offset;
@@ -272,15 +273,38 @@
// for uncompressed data).
switch (GetCompressionMethod()) {
case kCompressStored:
- return CopyFdToMemory(mem_map, zip_archive_->fd_, GetUncompressedLength());
+ return CopyFdToMemory(begin, size, zip_archive_->fd_, GetUncompressedLength());
case kCompressDeflated:
- return InflateToMemory(mem_map, zip_archive_->fd_, GetUncompressedLength(), GetCompressedLength());
+ return InflateToMemory(begin, size, zip_archive_->fd_,
+ GetUncompressedLength(), GetCompressedLength());
default:
LOG(WARNING) << "Zip: unknown compression method " << std::hex << GetCompressionMethod();
return false;
}
}
+MemMap* ZipEntry::ExtractToMemMap(const char* entry_filename) {
+ std::string name(entry_filename);
+ name += " extracted in memory from ";
+ name += entry_filename;
+ UniquePtr<MemMap> map(MemMap::MapAnonymous(name.c_str(),
+ NULL,
+ GetUncompressedLength(),
+ PROT_READ | PROT_WRITE));
+ if (map.get() == NULL) {
+ LOG(ERROR) << "Zip: mmap for '" << entry_filename << "' failed";
+ return NULL;
+ }
+
+ bool success = ExtractToMemory(map->Begin(), map->Size());
+ if (!success) {
+ LOG(ERROR) << "Zip: Failed to extract '" << entry_filename << "' to memory";
+ return NULL;
+ }
+
+ return map.release();
+}
+
static void SetCloseOnExec(int fd) {
// This dance is more portable than Linux's O_CLOEXEC open(2) flag.
int flags = fcntl(fd, F_GETFD);
diff --git a/src/zip_archive.h b/src/zip_archive.h
index 54835cf..ef31486 100644
--- a/src/zip_archive.h
+++ b/src/zip_archive.h
@@ -37,7 +37,8 @@
class ZipEntry {
public:
bool ExtractToFile(File& file);
- bool ExtractToMemory(MemMap& mem_map);
+ bool ExtractToMemory(uint8_t* begin, size_t size);
+ MemMap* ExtractToMemMap(const char* entry_filename);
uint32_t GetUncompressedLength();
uint32_t GetCrc32();