summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-04-15 02:37:28 -0700
committerAndreas Gampe <agampe@google.com>2015-04-21 15:03:15 -0700
commit70bef0d8f6aa30b0da5c6ca56e1bc5729f74654b (patch)
treeaea4a31294c5a6a30c52ee886d5884a0b5b84fde
parentbbf02afc641a393d33342976e269218668c07386 (diff)
downloadart-70bef0d8f6aa30b0da5c6ca56e1bc5729f74654b.zip
art-70bef0d8f6aa30b0da5c6ca56e1bc5729f74654b.tar.gz
art-70bef0d8f6aa30b0da5c6ca56e1bc5729f74654b.tar.bz2
ART: Add compiled-methods
Add a dex2oat option for compiled-methods, a more granular filter than compiled-classes. Add compiler-driver support for it. Refactor dex2oat to reuse file reading. Add a test to oat_test. Change-Id: I78d0d040bce7738b4bb7aabe7768b5788d2587ac
-rw-r--r--build/Android.gtest.mk2
-rw-r--r--compiler/common_compiler_test.cc26
-rw-r--r--compiler/common_compiler_test.h13
-rw-r--r--compiler/dex/quick/quick_cfi_test.cc2
-rw-r--r--compiler/driver/compiler_driver.cc23
-rw-r--r--compiler/driver/compiler_driver.h9
-rw-r--r--compiler/driver/compiler_driver_test.cc54
-rw-r--r--compiler/jit/jit_compiler.cc2
-rw-r--r--compiler/linker/relative_patcher_test.h2
-rw-r--r--compiler/oat_test.cc4
-rw-r--r--dex2oat/dex2oat.cc133
11 files changed, 222 insertions, 48 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 8c61871..e0f0ae5 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -61,7 +61,7 @@ $(ART_TEST_TARGET_GTEST_MainStripped_DEX): $(ART_TEST_TARGET_GTEST_Main_DEX)
# Dex file dependencies for each gtest.
ART_GTEST_class_linker_test_DEX_DEPS := Interfaces MultiDex MyClass Nested Statics StaticsFromCode
-ART_GTEST_compiler_driver_test_DEX_DEPS := AbstractMethod
+ART_GTEST_compiler_driver_test_DEX_DEPS := AbstractMethod StaticLeafMethods
ART_GTEST_dex_file_test_DEX_DEPS := GetMethodSignature Main Nested
ART_GTEST_exception_test_DEX_DEPS := ExceptionHandle
ART_GTEST_jni_compiler_test_DEX_DEPS := MyClassNatives
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 8ffc86e..05cb8b4 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -140,6 +140,27 @@ void CommonCompilerTest::MakeExecutable(mirror::ClassLoader* class_loader, const
}
}
+// Get the set of image classes given to the compiler-driver in SetUp. Note: the compiler
+// driver assumes ownership of the set, so the test should properly release the set.
+std::unordered_set<std::string>* CommonCompilerTest::GetImageClasses() {
+ // Empty set: by default no classes are retained in the image.
+ return new std::unordered_set<std::string>();
+}
+
+// Get the set of compiled classes given to the compiler-driver in SetUp. Note: the compiler
+// driver assumes ownership of the set, so the test should properly release the set.
+std::unordered_set<std::string>* CommonCompilerTest::GetCompiledClasses() {
+ // Null, no selection of compiled-classes.
+ return nullptr;
+}
+
+// Get the set of compiled methods given to the compiler-driver in SetUp. Note: the compiler
+// driver assumes ownership of the set, so the test should properly release the set.
+std::unordered_set<std::string>* CommonCompilerTest::GetCompiledMethods() {
+ // Null, no selection of compiled-methods.
+ return nullptr;
+}
+
void CommonCompilerTest::SetUp() {
CommonRuntimeTest::SetUp();
{
@@ -165,7 +186,10 @@ void CommonCompilerTest::SetUp() {
method_inliner_map_.get(),
compiler_kind, instruction_set,
instruction_set_features_.get(),
- true, new std::unordered_set<std::string>, nullptr,
+ true,
+ GetImageClasses(),
+ GetCompiledClasses(),
+ GetCompiledMethods(),
2, true, true, "", timer_.get(), -1, ""));
}
// We typically don't generate an image in unit tests, disable this optimization by default.
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index d7b210d..8d80a2d 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -18,6 +18,7 @@
#define ART_COMPILER_COMMON_COMPILER_TEST_H_
#include <list>
+#include <unordered_set>
#include <vector>
#include "common_runtime_test.h"
@@ -56,6 +57,18 @@ class CommonCompilerTest : public CommonRuntimeTest {
virtual void SetUpRuntimeOptions(RuntimeOptions *options);
+ // Get the set of image classes given to the compiler-driver in SetUp. Note: the compiler
+ // driver assumes ownership of the set, so the test should properly release the set.
+ virtual std::unordered_set<std::string>* GetImageClasses();
+
+ // Get the set of compiled classes given to the compiler-driver in SetUp. Note: the compiler
+ // driver assumes ownership of the set, so the test should properly release the set.
+ virtual std::unordered_set<std::string>* GetCompiledClasses();
+
+ // Get the set of compiled methods given to the compiler-driver in SetUp. Note: the compiler
+ // driver assumes ownership of the set, so the test should properly release the set.
+ virtual std::unordered_set<std::string>* GetCompiledMethods();
+
virtual void TearDown();
void CompileClass(mirror::ClassLoader* class_loader, const char* class_name)
diff --git a/compiler/dex/quick/quick_cfi_test.cc b/compiler/dex/quick/quick_cfi_test.cc
index d276457..555d5b9 100644
--- a/compiler/dex/quick/quick_cfi_test.cc
+++ b/compiler/dex/quick/quick_cfi_test.cc
@@ -76,7 +76,7 @@ class QuickCFITest : public CFITest {
isa_features.reset(InstructionSetFeatures::FromVariant(isa, "default", &error));
CompilerDriver driver(&compiler_options, &verification_results, &method_inliner_map,
Compiler::kQuick, isa, isa_features.get(),
- false, 0, 0, 0, false, false, "", 0, -1, "");
+ false, nullptr, nullptr, nullptr, 0, false, false, "", 0, -1, "");
ClassLinker* linker = nullptr;
CompilationUnit cu(&pool, isa, &driver, linker);
DexFile::CodeItem code_item { 0, 0, 0, 0, 0, 0, { 0 } }; // NOLINT
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 1832647..e665e1d 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -76,8 +76,8 @@ static constexpr bool kTimeCompileMethod = !kIsDebugBuild;
// Whether to produce 64-bit ELF files for 64-bit targets. Leave this off for now.
static constexpr bool kProduce64BitELFFiles = false;
-// Whether classes-to-compile is only applied to the boot image, or, when given, too all
-// compilations.
+// Whether classes-to-compile and methods-to-compile are only applied to the boot image, or, when
+// given, too all compilations.
static constexpr bool kRestrictCompilationFiltersToImage = true;
static double Percentage(size_t x, size_t y) {
@@ -349,6 +349,7 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options,
const InstructionSetFeatures* instruction_set_features,
bool image, std::unordered_set<std::string>* image_classes,
std::unordered_set<std::string>* compiled_classes,
+ std::unordered_set<std::string>* compiled_methods,
size_t thread_count, bool dump_stats, bool dump_passes,
const std::string& dump_cfg_file_name, CumulativeLogger* timer,
int swap_fd, const std::string& profile_file)
@@ -369,6 +370,7 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options,
image_(image),
image_classes_(image_classes),
classes_to_compile_(compiled_classes),
+ methods_to_compile_(compiled_methods),
had_hard_verifier_failure_(false),
thread_count_(thread_count),
stats_(new AOTCompilationStats),
@@ -670,6 +672,19 @@ bool CompilerDriver::IsClassToCompile(const char* descriptor) const {
return classes_to_compile_->find(descriptor) != classes_to_compile_->end();
}
+bool CompilerDriver::IsMethodToCompile(const MethodReference& method_ref) const {
+ if (kRestrictCompilationFiltersToImage && !IsImage()) {
+ return true;
+ }
+
+ if (methods_to_compile_ == nullptr) {
+ return true;
+ }
+
+ std::string tmp = PrettyMethod(method_ref.dex_method_index, *method_ref.dex_file, true);
+ return methods_to_compile_->find(tmp.c_str()) != methods_to_compile_->end();
+}
+
static void ResolveExceptionsForMethod(MutableHandle<mirror::ArtMethod> method_handle,
std::set<std::pair<uint16_t, const DexFile*>>& exceptions_to_resolve)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -2232,7 +2247,9 @@ void CompilerDriver::CompileMethod(Thread* self, const DexFile::CodeItem* code_i
// Basic checks, e.g., not <clinit>.
verification_results_->IsCandidateForCompilation(method_ref, access_flags) &&
// Did not fail to create VerifiedMethod metadata.
- has_verified_method;
+ has_verified_method &&
+ // Is eligable for compilation by methods-to-compile filter.
+ IsMethodToCompile(method_ref);
if (compile) {
// NOTE: if compiler declines to compile this method, it will return nullptr.
compiled_method = compiler_->Compile(code_item, access_flags, invoke_type, class_def_idx,
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index ce13a17..50e1fb1 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -104,6 +104,7 @@ class CompilerDriver {
const InstructionSetFeatures* instruction_set_features,
bool image, std::unordered_set<std::string>* image_classes,
std::unordered_set<std::string>* compiled_classes,
+ std::unordered_set<std::string>* compiled_methods,
size_t thread_count, bool dump_stats, bool dump_passes,
const std::string& dump_cfg_file_name,
CumulativeLogger* timer, int swap_fd,
@@ -428,6 +429,9 @@ class CompilerDriver {
// Checks whether the provided class should be compiled, i.e., is in classes_to_compile_.
bool IsClassToCompile(const char* descriptor) const;
+ // Checks whether the provided method should be compiled, i.e., is in method_to_compile_.
+ bool IsMethodToCompile(const MethodReference& method_ref) const;
+
void RecordClassStatus(ClassReference ref, mirror::Class::Status status)
LOCKS_EXCLUDED(compiled_classes_lock_);
@@ -597,6 +601,11 @@ class CompilerDriver {
// This option may be restricted to the boot image, depending on a flag in the implementation.
std::unique_ptr<std::unordered_set<std::string>> classes_to_compile_;
+ // Specifies the methods that will be compiled. Note that if methods_to_compile_ is nullptr,
+ // all methods are eligible for compilation (compilation filters etc. will still apply).
+ // This option may be restricted to the boot image, depending on a flag in the implementation.
+ std::unique_ptr<std::unordered_set<std::string>> methods_to_compile_;
+
bool had_hard_verifier_failure_;
size_t thread_count_;
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index e78ff90..ded50ca 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -175,6 +175,60 @@ TEST_F(CompilerDriverTest, AbstractMethodErrorStub) {
}
}
+class CompilerDriverMethodsTest : public CompilerDriverTest {
+ protected:
+ std::unordered_set<std::string>* GetCompiledMethods() OVERRIDE {
+ return new std::unordered_set<std::string>({
+ "byte StaticLeafMethods.identity(byte)",
+ "int StaticLeafMethods.sum(int, int, int)",
+ "double StaticLeafMethods.sum(double, double, double, double)"
+ });
+ }
+};
+
+TEST_F(CompilerDriverMethodsTest, Selection) {
+ Thread* self = Thread::Current();
+ jobject class_loader;
+ {
+ ScopedObjectAccess soa(self);
+ class_loader = LoadDex("StaticLeafMethods");
+ }
+ ASSERT_NE(class_loader, nullptr);
+
+ // Need to enable dex-file writability. Methods rejected to be compiled will run through the
+ // dex-to-dex compiler.
+ for (const DexFile* dex_file : GetDexFiles(class_loader)) {
+ ASSERT_TRUE(dex_file->EnableWrite());
+ }
+
+ CompileAll(class_loader);
+
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ StackHandleScope<1> hs(self);
+ ScopedObjectAccess soa(self);
+ Handle<mirror::ClassLoader> h_loader(hs.NewHandle(
+ reinterpret_cast<mirror::ClassLoader*>(self->DecodeJObject(class_loader))));
+ mirror::Class* klass = class_linker->FindClass(self, "LStaticLeafMethods;", h_loader);
+ ASSERT_NE(klass, nullptr);
+
+ std::unique_ptr<std::unordered_set<std::string>> expected(GetCompiledMethods());
+
+ for (int32_t i = 0; static_cast<uint32_t>(i) < klass->NumDirectMethods(); i++) {
+ mirror::ArtMethod* m = klass->GetDirectMethod(i);
+ std::string name = PrettyMethod(m, true);
+ const void* code =
+ m->GetEntryPointFromQuickCompiledCodePtrSize(InstructionSetPointerSize(kRuntimeISA));
+ ASSERT_NE(code, nullptr);
+ if (expected->find(name) != expected->end()) {
+ expected->erase(name);
+ EXPECT_FALSE(class_linker->IsQuickToInterpreterBridge(code));
+ } else {
+ EXPECT_TRUE(class_linker->IsQuickToInterpreterBridge(code));
+ }
+ }
+ EXPECT_TRUE(expected->empty());
+}
+
// TODO: need check-cast test (when stub complete & we can throw/catch
} // namespace art
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index 9ff7ab8..6a08548 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -94,7 +94,7 @@ JitCompiler::JitCompiler() : total_time_(0) {
compiler_driver_.reset(new CompilerDriver(
compiler_options_.get(), verification_results_.get(), method_inliner_map_.get(),
Compiler::kQuick, instruction_set, instruction_set_features_.get(), false,
- nullptr, nullptr, 1, false, true,
+ nullptr, nullptr, nullptr, 1, false, true,
std::string(), cumulative_logger_.get(), -1, std::string()));
// Disable dedupe so we can remove compiled methods.
compiler_driver_->SetDedupeEnabled(false);
diff --git a/compiler/linker/relative_patcher_test.h b/compiler/linker/relative_patcher_test.h
index 70630f3..1f7500a 100644
--- a/compiler/linker/relative_patcher_test.h
+++ b/compiler/linker/relative_patcher_test.h
@@ -45,7 +45,7 @@ class RelativePatcherTest : public testing::Test {
inliner_map_(),
driver_(&compiler_options_, &verification_results_, &inliner_map_,
Compiler::kQuick, instruction_set, nullptr,
- false, nullptr, nullptr, 1u,
+ false, nullptr, nullptr, nullptr, 1u,
false, false, "", nullptr, -1, ""),
error_msg_(),
instruction_set_(instruction_set),
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 989b04f..925b507 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -93,8 +93,8 @@ TEST_F(OatTest, WriteRead) {
verification_results_.get(),
method_inliner_map_.get(),
compiler_kind, insn_set,
- insn_features.get(), false, nullptr, nullptr, 2, true,
- true, "", timer_.get(), -1, ""));
+ insn_features.get(), false, nullptr, nullptr, nullptr,
+ 2, true, true, "", timer_.get(), -1, ""));
jobject class_loader = nullptr;
if (kCompile) {
TimingLogger timings2("OatTest::WriteRead", false, false);
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 70b4213..9c01a0f 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -445,6 +445,8 @@ class Dex2Oat FINAL {
image_classes_filename_(nullptr),
compiled_classes_zip_filename_(nullptr),
compiled_classes_filename_(nullptr),
+ compiled_methods_zip_filename_(nullptr),
+ compiled_methods_filename_(nullptr),
image_(false),
is_host_(false),
dump_stats_(false),
@@ -564,6 +566,10 @@ class Dex2Oat FINAL {
compiled_classes_filename_ = option.substr(strlen("--compiled-classes=")).data();
} else if (option.starts_with("--compiled-classes-zip=")) {
compiled_classes_zip_filename_ = option.substr(strlen("--compiled-classes-zip=")).data();
+ } else if (option.starts_with("--compiled-methods=")) {
+ compiled_methods_filename_ = option.substr(strlen("--compiled-methods=")).data();
+ } else if (option.starts_with("--compiled-methods-zip=")) {
+ compiled_methods_zip_filename_ = option.substr(strlen("--compiled-methods-zip=")).data();
} else if (option.starts_with("--base=")) {
const char* image_base_str = option.substr(strlen("--base=")).data();
char* end;
@@ -1092,8 +1098,8 @@ class Dex2Oat FINAL {
std::string error_msg;
if (image_classes_zip_filename_ != nullptr) {
image_classes_.reset(ReadImageClassesFromZip(image_classes_zip_filename_,
- image_classes_filename_,
- &error_msg));
+ image_classes_filename_,
+ &error_msg));
} else {
image_classes_.reset(ReadImageClassesFromFile(image_classes_filename_));
}
@@ -1121,9 +1127,29 @@ class Dex2Oat FINAL {
<< compiled_classes_filename_ << "': " << error_msg;
return false;
}
- } else if (image_) {
+ } else {
compiled_classes_.reset(nullptr); // By default compile everything.
}
+ // If --compiled-methods was specified, read the methods to compile from the given file(s).
+ if (compiled_methods_filename_ != nullptr) {
+ std::string error_msg;
+ if (compiled_methods_zip_filename_ != nullptr) {
+ compiled_methods_.reset(ReadCommentedInputFromZip(compiled_methods_zip_filename_,
+ compiled_methods_filename_,
+ nullptr, // No post-processing.
+ &error_msg));
+ } else {
+ compiled_methods_.reset(ReadCommentedInputFromFile(compiled_methods_filename_,
+ nullptr)); // No post-processing.
+ }
+ if (compiled_methods_.get() == nullptr) {
+ LOG(ERROR) << "Failed to create list of compiled methods from '"
+ << compiled_methods_filename_ << "': " << error_msg;
+ return false;
+ }
+ } else {
+ compiled_methods_.reset(nullptr); // By default compile everything.
+ }
if (boot_image_option_.empty()) {
dex_files_ = Runtime::Current()->GetClassLinker()->GetBootClassPath();
@@ -1258,6 +1284,7 @@ class Dex2Oat FINAL {
image_,
image_classes_.release(),
compiled_classes_.release(),
+ nullptr,
thread_count_,
dump_stats_,
dump_passes_,
@@ -1618,59 +1645,86 @@ class Dex2Oat FINAL {
// Reads the class names (java.lang.Object) and returns a set of descriptors (Ljava/lang/Object;)
static std::unordered_set<std::string>* ReadImageClassesFromFile(
const char* image_classes_filename) {
- std::unique_ptr<std::ifstream> image_classes_file(new std::ifstream(image_classes_filename,
- std::ifstream::in));
- if (image_classes_file.get() == nullptr) {
- LOG(ERROR) << "Failed to open image classes file " << image_classes_filename;
- return nullptr;
- }
- std::unique_ptr<std::unordered_set<std::string>> result(ReadImageClasses(*image_classes_file));
- image_classes_file->close();
- return result.release();
+ std::function<std::string(const char*)> process = DotToDescriptor;
+ return ReadCommentedInputFromFile(image_classes_filename, &process);
}
- static std::unordered_set<std::string>* ReadImageClasses(std::istream& image_classes_stream) {
- std::unique_ptr<std::unordered_set<std::string>> image_classes(
- new std::unordered_set<std::string>);
- while (image_classes_stream.good()) {
- std::string dot;
- std::getline(image_classes_stream, dot);
- if (StartsWith(dot, "#") || dot.empty()) {
- continue;
- }
- std::string descriptor(DotToDescriptor(dot.c_str()));
- image_classes->insert(descriptor);
+ // Reads the class names (java.lang.Object) and returns a set of descriptors (Ljava/lang/Object;)
+ static std::unordered_set<std::string>* ReadImageClassesFromZip(
+ const char* zip_filename,
+ const char* image_classes_filename,
+ std::string* error_msg) {
+ std::function<std::string(const char*)> process = DotToDescriptor;
+ return ReadCommentedInputFromZip(zip_filename, image_classes_filename, &process, error_msg);
+ }
+
+ // Read lines from the given file, dropping comments and empty lines. Post-process each line with
+ // the given function.
+ static std::unordered_set<std::string>* ReadCommentedInputFromFile(
+ const char* input_filename, std::function<std::string(const char*)>* process) {
+ std::unique_ptr<std::ifstream> input_file(new std::ifstream(input_filename, std::ifstream::in));
+ if (input_file.get() == nullptr) {
+ LOG(ERROR) << "Failed to open input file " << input_filename;
+ return nullptr;
}
- return image_classes.release();
+ std::unique_ptr<std::unordered_set<std::string>> result(
+ ReadCommentedInputStream(*input_file, process));
+ input_file->close();
+ return result.release();
}
- // Reads the class names (java.lang.Object) and returns a set of descriptors (Ljava/lang/Object;)
- static std::unordered_set<std::string>* ReadImageClassesFromZip(
+ // Read lines from the given file from the given zip file, dropping comments and empty lines.
+ // Post-process each line with the given function.
+ static std::unordered_set<std::string>* ReadCommentedInputFromZip(
const char* zip_filename,
- const char* image_classes_filename,
+ const char* input_filename,
+ std::function<std::string(const char*)>* process,
std::string* error_msg) {
std::unique_ptr<ZipArchive> zip_archive(ZipArchive::Open(zip_filename, error_msg));
if (zip_archive.get() == nullptr) {
return nullptr;
}
- std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(image_classes_filename, error_msg));
+ std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(input_filename, error_msg));
if (zip_entry.get() == nullptr) {
- *error_msg = StringPrintf("Failed to find '%s' within '%s': %s", image_classes_filename,
+ *error_msg = StringPrintf("Failed to find '%s' within '%s': %s", input_filename,
zip_filename, error_msg->c_str());
return nullptr;
}
- std::unique_ptr<MemMap> image_classes_file(zip_entry->ExtractToMemMap(zip_filename,
- image_classes_filename,
- error_msg));
- if (image_classes_file.get() == nullptr) {
- *error_msg = StringPrintf("Failed to extract '%s' from '%s': %s", image_classes_filename,
+ std::unique_ptr<MemMap> input_file(zip_entry->ExtractToMemMap(zip_filename,
+ input_filename,
+ error_msg));
+ if (input_file.get() == nullptr) {
+ *error_msg = StringPrintf("Failed to extract '%s' from '%s': %s", input_filename,
zip_filename, error_msg->c_str());
return nullptr;
}
- 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 std::string input_string(reinterpret_cast<char*>(input_file->Begin()),
+ input_file->Size());
+ std::istringstream input_stream(input_string);
+ return ReadCommentedInputStream(input_stream, process);
+ }
+
+ // Read lines from the given stream, dropping comments and empty lines. Post-process each line
+ // with the given function.
+ static std::unordered_set<std::string>* ReadCommentedInputStream(
+ std::istream& in_stream,
+ std::function<std::string(const char*)>* process) {
+ std::unique_ptr<std::unordered_set<std::string>> image_classes(
+ new std::unordered_set<std::string>);
+ while (in_stream.good()) {
+ std::string dot;
+ std::getline(in_stream, dot);
+ if (StartsWith(dot, "#") || dot.empty()) {
+ continue;
+ }
+ if (process != nullptr) {
+ std::string descriptor((*process)(dot.c_str()));
+ image_classes->insert(descriptor);
+ } else {
+ image_classes->insert(dot);
+ }
+ }
+ return image_classes.release();
}
void LogCompletionTime() {
@@ -1724,8 +1778,11 @@ class Dex2Oat FINAL {
const char* image_classes_filename_;
const char* compiled_classes_zip_filename_;
const char* compiled_classes_filename_;
+ const char* compiled_methods_zip_filename_;
+ const char* compiled_methods_filename_;
std::unique_ptr<std::unordered_set<std::string>> image_classes_;
std::unique_ptr<std::unordered_set<std::string>> compiled_classes_;
+ std::unique_ptr<std::unordered_set<std::string>> compiled_methods_;
bool image_;
std::unique_ptr<ImageWriter> image_writer_;
bool is_host_;