ART: Add compiler option for code deduplication
Add --deduplicate-code and --no-deduplicate-code to ease in
experiments with deduplication, e.g., profiling.
Add dex2oat test.
Test: m test-art-host
Change-Id: Ib6c7fe082f43c5f76c8463cc563e2503c9a50480
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index b2d214e..7769aad 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -100,7 +100,7 @@
$(HOST_OUT_EXECUTABLES)/smali assemble --output $@ $(filter %.smali,$^)
# Dex file dependencies for each gtest.
-ART_GTEST_dex2oat_environment_tests_DEX_DEPS := Main MainStripped MultiDex MultiDexModifiedSecondary Nested VerifierDeps VerifierDepsMulti
+ART_GTEST_dex2oat_environment_tests_DEX_DEPS := Main MainStripped MultiDex MultiDexModifiedSecondary MyClassNatives Nested VerifierDeps VerifierDepsMulti
ART_GTEST_atomic_dex_ref_map_test_DEX_DEPS := Interfaces
ART_GTEST_class_linker_test_DEX_DEPS := AllFields ErroneousA ErroneousB ErroneousInit ForClassLoaderA ForClassLoaderB ForClassLoaderC ForClassLoaderD Interfaces MethodTypes MultiDex MyClass Nested Statics StaticsFromCode
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index bd78af4..a9d27ef 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -320,6 +320,8 @@
if (GetCompilerOptions().IsBootImage()) {
CHECK(image_classes_.get() != nullptr) << "Expected image classes for boot image";
}
+
+ compiled_method_storage_.SetDedupeEnabled(compiler_options_->DeduplicateCode());
}
CompilerDriver::~CompilerDriver() {
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index f789314..032763c 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -56,6 +56,7 @@
dump_cfg_file_name_(""),
dump_cfg_append_(false),
force_determinism_(false),
+ deduplicate_code_(true),
register_allocation_strategy_(RegisterAllocator::kRegisterAllocatorDefault),
passes_to_run_(nullptr) {
}
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index 12de9be..ab2a681 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -254,6 +254,10 @@
return force_determinism_;
}
+ bool DeduplicateCode() const {
+ return deduplicate_code_;
+ }
+
RegisterAllocator::Strategy GetRegisterAllocationStrategy() const {
return register_allocation_strategy_;
}
@@ -319,6 +323,9 @@
// outcomes.
bool force_determinism_;
+ // Whether code should be deduplicated.
+ bool deduplicate_code_;
+
RegisterAllocator::Strategy register_allocation_strategy_;
// If not null, specifies optimization passes which will be run instead of defaults.
diff --git a/compiler/driver/compiler_options_map-inl.h b/compiler/driver/compiler_options_map-inl.h
index 772d1b4..e28d499 100644
--- a/compiler/driver/compiler_options_map-inl.h
+++ b/compiler/driver/compiler_options_map-inl.h
@@ -76,6 +76,7 @@
}
}
map.AssignIfExists(Base::VerboseMethods, &options->verbose_methods_);
+ options->deduplicate_code_ = map.GetOrDefault(Base::DeduplicateCode);
return true;
}
@@ -123,6 +124,11 @@
.WithValues({true, false})
.IntoKey(Map::GenerateBuildID)
+ .Define({"--deduplicate-code=_"})
+ .template WithType<bool>()
+ .WithValueMap({{"false", false}, {"true", true}})
+ .IntoKey(Map::DeduplicateCode)
+
.Define("--debuggable")
.IntoKey(Map::Debuggable)
diff --git a/compiler/driver/compiler_options_map.def b/compiler/driver/compiler_options_map.def
index cc75634..cccd618 100644
--- a/compiler/driver/compiler_options_map.def
+++ b/compiler/driver/compiler_options_map.def
@@ -57,5 +57,6 @@
// TODO: Add type parser.
COMPILER_OPTIONS_KEY (std::string, RegisterAllocationStrategy)
COMPILER_OPTIONS_KEY (ParseStringList<','>, VerboseMethods)
+COMPILER_OPTIONS_KEY (bool, DeduplicateCode, true)
#undef COMPILER_OPTIONS_KEY
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 46474d2..29228a3 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -452,6 +452,9 @@
UsageError(" --compact-dex-level=none|fast: None avoids generating compact dex, fast");
UsageError(" generates compact dex with low compile time.");
UsageError("");
+ UsageError(" --deduplicate-code|--no-deduplicate-code: enable|disable code deduplication.");
+ UsageError(" Deduplicated code will have an arbitrary symbol tagged with [DEDUPED].");
+ UsageError("");
std::cerr << "See log for usage error information\n";
exit(EXIT_FAILURE);
}
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index cb91978..99be111 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -1481,4 +1481,36 @@
EXPECT_EQ(0, res_no_fail);
}
+class Dex2oatDedupeCode : public Dex2oatTest {};
+
+TEST_F(Dex2oatDedupeCode, DedupeTest) {
+ // Use MyClassNatives. It has lots of native methods that will produce deduplicate-able code.
+ std::unique_ptr<const DexFile> dex(OpenTestDexFile("MyClassNatives"));
+ std::string out_dir = GetScratchDir();
+ const std::string base_oat_name = out_dir + "/base.oat";
+ size_t no_dedupe_size = 0;
+ GenerateOdexForTest(dex->GetLocation(),
+ base_oat_name,
+ CompilerFilter::Filter::kSpeed,
+ { "--deduplicate-code=false" },
+ true, // expect_success
+ false, // use_fd
+ [&no_dedupe_size](const OatFile& o) {
+ no_dedupe_size = o.Size();
+ });
+
+ size_t dedupe_size = 0;
+ GenerateOdexForTest(dex->GetLocation(),
+ base_oat_name,
+ CompilerFilter::Filter::kSpeed,
+ { "--deduplicate-code=true" },
+ true, // expect_success
+ false, // use_fd
+ [&dedupe_size](const OatFile& o) {
+ dedupe_size = o.Size();
+ });
+
+ EXPECT_LT(dedupe_size, no_dedupe_size);
+}
+
} // namespace art