Use full profile in Dex2OatImageTest#TestExtension.
Test: m test-art-host-gtest-dex2oat_image_test
Bug: 119800099
Change-Id: I120f71f98b4df7fae88764e5215e06a6e151b7a2
diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc
index 1a0a9c8..9b96494 100644
--- a/dex2oat/dex2oat_image_test.cc
+++ b/dex2oat/dex2oat_image_test.cc
@@ -74,9 +74,20 @@
const ClassVisitor& class_visitor,
size_t method_frequency = 1,
size_t class_frequency = 1) {
+ std::vector<std::string> dexes = GetLibCoreDexFileNames();
+ VisitDexes(dexes, method_visitor, class_visitor, method_frequency, class_frequency);
+ }
+
+ // Visitors take method and type references
+ template <typename MethodVisitor, typename ClassVisitor>
+ void VisitDexes(const std::vector<std::string>& dexes,
+ const MethodVisitor& method_visitor,
+ const ClassVisitor& class_visitor,
+ size_t method_frequency = 1,
+ size_t class_frequency = 1) {
size_t method_counter = 0;
size_t class_counter = 0;
- for (const std::string& dex : GetLibCoreDexFileNames()) {
+ for (const std::string& dex : dexes) {
std::vector<std::unique_ptr<const DexFile>> dex_files;
std::string error_msg;
const ArtDexFileLoader dex_file_loader;
@@ -107,19 +118,27 @@
EXPECT_TRUE(file->WriteFully(&line[0], line.length()));
}
- void GenerateProfile(File* out_file, size_t method_frequency, size_t type_frequency) {
+ void GenerateProfile(const std::vector<std::string>& dexes,
+ File* out_file,
+ size_t method_frequency,
+ size_t type_frequency) {
ProfileCompilationInfo profile;
- VisitLibcoreDexes([&profile](MethodReference ref) {
- uint32_t flags = ProfileCompilationInfo::MethodHotness::kFlagHot |
- ProfileCompilationInfo::MethodHotness::kFlagStartup;
- EXPECT_TRUE(profile.AddMethod(
- ProfileMethodInfo(ref),
- static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags)));
- }, [&profile](TypeReference ref) {
- std::set<dex::TypeIndex> classes;
- classes.insert(ref.TypeIndex());
- EXPECT_TRUE(profile.AddClassesForDex(ref.dex_file, classes.begin(), classes.end()));
- }, method_frequency, type_frequency);
+ VisitDexes(
+ dexes,
+ [&profile](MethodReference ref) {
+ uint32_t flags = ProfileCompilationInfo::MethodHotness::kFlagHot |
+ ProfileCompilationInfo::MethodHotness::kFlagStartup;
+ EXPECT_TRUE(profile.AddMethod(
+ ProfileMethodInfo(ref),
+ static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags)));
+ },
+ [&profile](TypeReference ref) {
+ std::set<dex::TypeIndex> classes;
+ classes.insert(ref.TypeIndex());
+ EXPECT_TRUE(profile.AddClassesForDex(ref.dex_file, classes.begin(), classes.end()));
+ },
+ method_frequency,
+ type_frequency);
ScratchFile profile_file;
profile.Save(out_file->Fd());
EXPECT_EQ(out_file->Flush(), 0);
@@ -241,7 +260,10 @@
// Compile all methods and classes
{
ScratchFile profile_file;
- GenerateProfile(profile_file.GetFile(), /*method_frequency=*/ 1u, /*type_frequency=*/ 1u);
+ GenerateProfile(GetLibCoreDexFileNames(),
+ profile_file.GetFile(),
+ /*method_frequency=*/ 1u,
+ /*type_frequency=*/ 1u);
everything_sizes = CompileImageAndGetSizes(
{"--profile-file=" + profile_file.GetFilename(),
"--compiler-filter=speed-profile"});
@@ -257,7 +279,10 @@
// Test compiling fewer methods and classes.
{
ScratchFile profile_file;
- GenerateProfile(profile_file.GetFile(), kMethodFrequency, kTypeFrequency);
+ GenerateProfile(GetLibCoreDexFileNames(),
+ profile_file.GetFile(),
+ kMethodFrequency,
+ kTypeFrequency);
filter_sizes = CompileImageAndGetSizes(
{"--profile-file=" + profile_file.GetFilename(),
"--compiler-filter=speed-profile"});
@@ -328,19 +353,30 @@
dex_file = new_location;
}
+ // Create a profile.
+ ScratchFile profile_file;
+ GenerateProfile(libcore_dex_files,
+ profile_file.GetFile(),
+ /*method_frequency=*/ 1u,
+ /*type_frequency=*/ 1u);
+ std::vector<std::string> extra_args;
+ extra_args.push_back("--profile-file=" + profile_file.GetFilename());
+
ArrayRef<const std::string> full_bcp(libcore_dex_files);
size_t total_dex_files = full_bcp.size();
- ASSERT_GE(total_dex_files, 4u); // 2 for "head", 1 for "tail", at least one for "mid", see below.
+ ASSERT_GE(total_dex_files, 5u); // 3 for "head", 1 for "tail", at least one for "mid", see below.
- // The primary image must contain at least core-oj and core-libart to initialize the runtime.
+ // The primary image must contain at least core-oj and core-libart to initialize the runtime
+ // and we also need the core-icu4j if we want to compile these with full profile.
ASSERT_NE(std::string::npos, full_bcp[0].find("core-oj"));
ASSERT_NE(std::string::npos, full_bcp[1].find("core-libart"));
- ArrayRef<const std::string> head_dex_files = full_bcp.SubArray(/*pos=*/ 0u, /*length=*/ 2u);
+ ASSERT_NE(std::string::npos, full_bcp[2].find("core-icu4j"));
+ ArrayRef<const std::string> head_dex_files = full_bcp.SubArray(/*pos=*/ 0u, /*length=*/ 3u);
// Middle part is everything else except for conscrypt.
ASSERT_NE(std::string::npos, full_bcp[full_bcp.size() - 1u].find("conscrypt"));
ArrayRef<const std::string> mid_bcp =
full_bcp.SubArray(/*pos=*/ 0u, /*length=*/ total_dex_files - 1u);
- ArrayRef<const std::string> mid_dex_files = mid_bcp.SubArray(/*pos=*/ 2u);
+ ArrayRef<const std::string> mid_dex_files = mid_bcp.SubArray(/*pos=*/ 3u);
// Tail is just the conscrypt.
ArrayRef<const std::string> tail_dex_files =
full_bcp.SubArray(/*pos=*/ total_dex_files - 1u, /*length=*/ 1u);
@@ -367,13 +403,13 @@
std::string tail_name = tail_location.substr(tail_slash_pos + 1u);
// Compile the "head", i.e. the primary boot image.
- std::string base = android::base::StringPrintf("--base=0x%08x", kBaseAddress);
- bool head_ok = CompileBootImage({base}, filename_prefix, head_dex_files, &error_msg);
+ extra_args.push_back(android::base::StringPrintf("--base=0x%08x", kBaseAddress));
+ bool head_ok = CompileBootImage(extra_args, filename_prefix, head_dex_files, &error_msg);
ASSERT_TRUE(head_ok) << error_msg;
+ extra_args.pop_back();
// Compile the "mid", i.e. the first extension.
std::string mid_bcp_string = android::base::Join(mid_bcp, ':');
- std::vector<std::string> extra_args;
AddRuntimeArg(extra_args, "-Xbootclasspath:" + mid_bcp_string);
AddRuntimeArg(extra_args, "-Xbootclasspath-locations:" + mid_bcp_string);
extra_args.push_back("--boot-image=" + base_location);
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index f3c103b..c3801f4 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -1050,7 +1050,7 @@
}
TimingLogger::ScopedTiming t("LoadImageClasses", timings);
- // Make a first class to load all classes explicitly listed in the file
+ // Make a first pass to load all classes explicitly listed in the file
Thread* self = Thread::Current();
ScopedObjectAccess soa(self);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 4584dd3..13f22d9 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -2181,6 +2181,16 @@
CHECK(field->GetObject(ref) == nullptr);
return;
}
+ if (obj->IsString()) {
+ // Ignore interned strings. These may come from reflection interning method names.
+ // TODO: Make dex file strings weak interns and GC them before writing the image.
+ Runtime* runtime = Runtime::Current();
+ ObjPtr<mirror::String> interned =
+ runtime->GetInternTable()->LookupStrong(Thread::Current(), obj->AsString());
+ if (interned == obj) {
+ return;
+ }
+ }
LOG(FATAL) << "Image object without assigned bin slot: "
<< mirror::Object::PrettyTypeOf(obj) << " " << obj;
}