diff options
author | 2018-10-18 14:18:59 -0700 | |
---|---|---|
committer | 2018-10-19 19:59:32 +0000 | |
commit | 22752770e5e7dd9fb30bb35373b61e76b40ae5c3 (patch) | |
tree | 225ace62d4fba030cf2b5f5e0bbaf02e14e1c886 | |
parent | eca553e1a8a47a23de621d3c998c2f6d5561d033 (diff) |
Resolve const-string of clinit
Resolve the const strings of the clinit for classes that are loaded in the profile.
For Maps, the number of strings is ~4400. This would take ~100k RAM if each string
is around 20 characters. Note that these strings are mostly already loaded during
startup, so there might not be a net RAM usage increase.
Test: test-art-host
Bug: 117621117
Change-Id: I632a91633c1b3757523ef6e655f192305554499b
-rw-r--r-- | compiler/driver/compiler_driver.cc | 15 | ||||
-rw-r--r-- | dex2oat/dex2oat_test.cc | 19 | ||||
-rw-r--r-- | test/StringLiterals/StringLiterals.java | 12 |
3 files changed, 42 insertions, 4 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 89ac308fed..7690e233a7 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -715,6 +715,7 @@ void CompilerDriver::ResolveConstStrings(const std::vector<const DexFile*>& dex_ StackHandleScope<1> hs(soa.Self()); ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); MutableHandle<mirror::DexCache> dex_cache(hs.NewHandle<mirror::DexCache>(nullptr)); + size_t num_instructions = 0u; for (const DexFile* dex_file : dex_files) { dex_cache.Assign(class_linker->FindDexCache(soa.Self(), *dex_file)); @@ -726,10 +727,20 @@ void CompilerDriver::ResolveConstStrings(const std::vector<const DexFile*>& dex_ // FIXME: Make sure that inlining honors this. b/26687569 continue; } + + const bool is_startup_class = + profile_compilation_info_ != nullptr && + profile_compilation_info_->ContainsClass(*dex_file, accessor.GetClassIdx()); + for (const ClassAccessor::Method& method : accessor.GetMethods()) { + const bool is_clinit = (method.GetAccessFlags() & kAccConstructor) != 0 && + (method.GetAccessFlags() & kAccStatic) != 0; + const bool is_startup_clinit = is_startup_class && is_clinit; + if (only_startup_strings && profile_compilation_info_ != nullptr && - !profile_compilation_info_->GetMethodHotness(method.GetReference()).IsStartup()) { + (!profile_compilation_info_->GetMethodHotness(method.GetReference()).IsStartup() && + !is_startup_clinit)) { continue; } @@ -746,6 +757,7 @@ void CompilerDriver::ResolveConstStrings(const std::vector<const DexFile*>& dex_ : inst->VRegB_31c()); ObjPtr<mirror::String> string = class_linker->ResolveString(string_index, dex_cache); CHECK(string != nullptr) << "Could not allocate a string when forcing determinism"; + ++num_instructions; break; } @@ -756,6 +768,7 @@ void CompilerDriver::ResolveConstStrings(const std::vector<const DexFile*>& dex_ } } } + VLOG(compiler) << "Resolved " << num_instructions << " const string instructions"; } // Initialize type check bit strings for check-cast and instance-of in the code. Done to have diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc index b945b2ab0e..c9bd6d2e7f 100644 --- a/dex2oat/dex2oat_test.cc +++ b/dex2oat/dex2oat_test.cc @@ -2091,16 +2091,25 @@ TEST_F(Dex2oatTest, AppImageResolveStrings) { // Create a profile with the startup method marked. ScratchFile profile_file; std::vector<uint16_t> methods; + std::vector<dex::TypeIndex> classes; { std::unique_ptr<const DexFile> dex(OpenTestDexFile("StringLiterals")); - for (size_t method_idx = 0; method_idx < dex->NumMethodIds(); ++method_idx) { - if (std::string(dex->GetMethodName(dex->GetMethodId(method_idx))) == "startUpMethod") { - methods.push_back(method_idx); + for (ClassAccessor accessor : dex->GetClasses()) { + if (accessor.GetDescriptor() == std::string("LStringLiterals$StartupClass;")) { + classes.push_back(accessor.GetClassIdx()); + } + for (const ClassAccessor::Method& method : accessor.GetMethods()) { + std::string method_name(dex->GetMethodName(dex->GetMethodId(method.GetIndex()))); + if (method_name == "startUpMethod") { + methods.push_back(method.GetIndex()); + } } } + ASSERT_GT(classes.size(), 0u); ASSERT_GT(methods.size(), 0u); // Here, we build the profile from the method lists. ProfileCompilationInfo info; + info.AddClassesForDex(dex.get(), classes.begin(), classes.end()); info.AddMethodsForDex(Hotness::kFlagStartup, dex.get(), methods.begin(), methods.end()); // Save the profile since we want to use it with dex2oat to produce an oat file. ASSERT_TRUE(info.Save(profile_file.GetFd())); @@ -2145,11 +2154,15 @@ TEST_F(Dex2oatTest, AppImageResolveStrings) { seen.insert(str.Read()->ToModifiedUtf8()); } }); + // Normal methods EXPECT_TRUE(seen.find("Loading ") != seen.end()); EXPECT_TRUE(seen.find("Starting up") != seen.end()); EXPECT_TRUE(seen.find("abcd.apk") != seen.end()); EXPECT_TRUE(seen.find("Unexpected error") == seen.end()); EXPECT_TRUE(seen.find("Shutting down!") == seen.end()); + // Classes initializers + EXPECT_TRUE(seen.find("Startup init") != seen.end()); + EXPECT_TRUE(seen.find("Other class init") == seen.end()); } } diff --git a/test/StringLiterals/StringLiterals.java b/test/StringLiterals/StringLiterals.java index 8dee666fd7..9ab37ca3de 100644 --- a/test/StringLiterals/StringLiterals.java +++ b/test/StringLiterals/StringLiterals.java @@ -15,6 +15,18 @@ */ class StringLiterals { + static class StartupClass { + static { + System.out.println("Startup init"); + } + } + + static class OtherClass { + static { + System.out.println("Other class init"); + } + } + void startUpMethod() { String resource = "abcd.apk"; System.out.println("Starting up"); |