ART: Allow --no-inline-from to specify multiple dex files.
This will allow tests to specify arbitrary dex files from
which we should not inline, in addition to core-oj, so that
we can test the related functionality. Additionally, should
the core-oj.jar core grow beyond a single classes.dex and
require a multi-dex .jar, this change makes sure that we
prevent inlining also from the extra classes<N>.dex files.
Change-Id: I74da4839bf9bb405dd62ad80563bf646a7a65dd9
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 818d50a..c483f33 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -2582,7 +2582,8 @@
const DexFile* inlined_into) const {
// We're not allowed to inline across dex files if we're the no-inline-from dex file.
if (inlined_from != inlined_into &&
- compiler_options_->GetNoInlineFromDexFile() == inlined_from) {
+ compiler_options_->GetNoInlineFromDexFile() != nullptr &&
+ ContainsElement(*compiler_options_->GetNoInlineFromDexFile(), inlined_from)) {
return false;
}
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index 2644528..4f6e922 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -62,7 +62,7 @@
size_t num_dex_methods_threshold,
size_t inline_depth_limit,
size_t inline_max_code_units,
- const DexFile* no_inline_from,
+ const std::vector<const DexFile*>* no_inline_from,
bool include_patch_information,
double top_k_profile_threshold,
bool debuggable,
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index d47fc2a..9d51b75 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -72,7 +72,7 @@
size_t num_dex_methods_threshold,
size_t inline_depth_limit,
size_t inline_max_code_units,
- const DexFile* no_inline_from,
+ const std::vector<const DexFile*>* no_inline_from,
bool include_patch_information,
double top_k_profile_threshold,
bool debuggable,
@@ -220,7 +220,7 @@
return abort_on_hard_verifier_failure_;
}
- const DexFile* GetNoInlineFromDexFile() const {
+ const std::vector<const DexFile*>* GetNoInlineFromDexFile() const {
return no_inline_from_;
}
@@ -257,8 +257,10 @@
size_t inline_depth_limit_;
size_t inline_max_code_units_;
- // A dex file from which we should not inline code.
- const DexFile* no_inline_from_;
+ // Dex files from which we should not inline code.
+ // This is usually a very short list (i.e. a single dex file), so we
+ // prefer vector<> over a lookup-oriented container, such as set<>.
+ const std::vector<const DexFile*>* no_inline_from_;
bool include_patch_information_;
// When using a profile file only the top K% of the profiled samples will be compiled.
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 86f51e1..917d458 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -548,6 +548,7 @@
driver_(nullptr),
opened_dex_files_maps_(),
opened_dex_files_(),
+ no_inline_from_dex_files_(),
dump_stats_(false),
dump_passes_(false),
dump_timing_(false),
@@ -1452,14 +1453,18 @@
TimingLogger::ScopedTiming t("dex2oat Compile", timings_);
compiler_phases_timings_.reset(new CumulativeLogger("compilation times"));
- // Find the dex file we should not inline from.
+ // Find the dex files we should not inline from.
+
+ std::vector<std::string> no_inline_filters;
+ Split(no_inline_from_string_, ',', &no_inline_filters);
// For now, on the host always have core-oj removed.
- if (!kIsTargetBuild && no_inline_from_string_.empty()) {
- no_inline_from_string_ = "core-oj";
+ const std::string core_oj = "core-oj";
+ if (!kIsTargetBuild && !ContainsElement(no_inline_filters, core_oj)) {
+ no_inline_filters.push_back(core_oj);
}
- if (!no_inline_from_string_.empty()) {
+ if (!no_inline_filters.empty()) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
std::vector<const DexFile*> class_path_files = MakeNonOwningPointerVector(class_path_files_);
std::vector<const std::vector<const DexFile*>*> dex_file_vectors = {
@@ -1468,34 +1473,30 @@
&dex_files_
};
for (const std::vector<const DexFile*>* dex_file_vector : dex_file_vectors) {
- if (dex_file_vector == nullptr) {
- continue;
- }
-
- bool found = false;
-
for (const DexFile* dex_file : *dex_file_vector) {
- // Try the complete location first.
- found = no_inline_from_string_ == dex_file->GetLocation();
- // The try just the name.
- if (!found) {
- size_t last_slash = dex_file->GetLocation().rfind('/');
- if (last_slash != std::string::npos) {
- found = StartsWith(dex_file->GetLocation().substr(last_slash + 1),
- no_inline_from_string_.c_str());
+ for (const std::string& filter : no_inline_filters) {
+ // Use dex_file->GetLocation() rather than dex_file->GetBaseLocation(). This
+ // allows tests to specify <test-dexfile>:classes2.dex if needed but if the
+ // base location passes the StartsWith() test, so do all extra locations.
+ std::string dex_location = dex_file->GetLocation();
+ if (filter.find('/') == std::string::npos) {
+ // The filter does not contain the path. Remove the path from dex_location as well.
+ size_t last_slash = dex_file->GetLocation().rfind('/');
+ if (last_slash != std::string::npos) {
+ dex_location = dex_location.substr(last_slash + 1);
+ }
+ }
+
+ if (StartsWith(dex_location, filter.c_str())) {
+ VLOG(compiler) << "Disabling inlining from " << dex_file->GetLocation();
+ no_inline_from_dex_files_.push_back(dex_file);
+ break;
}
}
-
- if (found) {
- VLOG(compiler) << "Disabling inlining from " << dex_file->GetLocation();
- compiler_options_->no_inline_from_ = dex_file;
- break;
- }
}
-
- if (found) {
- break;
- }
+ }
+ if (!no_inline_from_dex_files_.empty()) {
+ compiler_options_->no_inline_from_ = &no_inline_from_dex_files_;
}
}
@@ -2384,6 +2385,8 @@
std::vector<std::unique_ptr<MemMap>> opened_dex_files_maps_;
std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
+ std::vector<const DexFile*> no_inline_from_dex_files_;
+
std::vector<std::string> verbose_methods_;
bool dump_stats_;
bool dump_passes_;