Fix the legacy version of `GetDexOptNeeded`.
- when `profile_changed` is true but the target compiler filter is worse
than the current:
- Before: returns kDex2OatForFilter
- After: returns kNoDexOptNeeded
- when `downgrade` is true but there is no usable odex/vdex files:
- Before: returns kDex2OatFromScratch
- After: return kNoDexOptNeeded
- when `profile_changed` and `downgrade` are both true:
- Before: kDex2OatForFilter
- After: the same as `profile_changed` is false and `downgrade` is
true.
- when the usable vdex file is in the DM file:
- Before: returns kDex2OatForFilter with an arbitrary sign
- After: returns kDex2OatFromScratch
Bug: 229268202
Test: m test-art-host-gtest-art_dex2oat_tests
Ignore-AOSP-First: Will cherry-pick later.
Change-Id: I752d860adb8c026c762e8878ac060211df22670d
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 3d6d832..4943bf3 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -295,36 +295,21 @@
}
OatFileAssistant::DexOptTrigger OatFileAssistant::GetDexOptTrigger(
- CompilerFilter::Filter target_compiler_filter [[gnu::unused]],
- bool profile_changed,
- bool downgrade) {
- OatFileInfo& info = GetBestInfo();
-
- if (!info.IsUseable()) {
- // Essentially always recompile.
- return OatFileAssistant::DexOptTrigger{.targetFilterIsBetter = true};
- }
-
- const OatFile* file = info.GetFile();
- DCHECK(file != nullptr);
-
- CompilerFilter::Filter current = file->GetCompilerFilter();
- if (profile_changed && CompilerFilter::DependsOnProfile(current)) {
- // Since the profile has been changed, we should re-compile even if the compilation does not
- // make the compiler filter better.
- return OatFileAssistant::DexOptTrigger{
- .targetFilterIsBetter = true, .targetFilterIsSame = true, .targetFilterIsWorse = true};
- }
-
+ CompilerFilter::Filter target_compiler_filter, bool profile_changed, bool downgrade) {
if (downgrade) {
// The caller's intention is to downgrade the compiler filter. We should only re-compile if the
// target compiler filter is worse than the current one.
- return OatFileAssistant::DexOptTrigger{.targetFilterIsWorse = true};
+ return DexOptTrigger{.targetFilterIsWorse = true};
}
// This is the usual case. The caller's intention is to see if a better oat file can be generated.
- return OatFileAssistant::DexOptTrigger{.targetFilterIsBetter = true,
- .primaryBootImageBecomesUsable = true};
+ DexOptTrigger dexopt_trigger{.targetFilterIsBetter = true, .primaryBootImageBecomesUsable = true};
+ if (profile_changed && CompilerFilter::DependsOnProfile(target_compiler_filter)) {
+ // Since the profile has been changed, we should re-compile even if the compilation does not
+ // make the compiler filter better.
+ dexopt_trigger.targetFilterIsSame = true;
+ }
+ return dexopt_trigger;
}
int OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
@@ -333,6 +318,12 @@
OatFileInfo& info = GetBestInfo();
DexOptNeeded dexopt_needed = info.GetDexOptNeeded(
target_compiler_filter, GetDexOptTrigger(target_compiler_filter, profile_changed, downgrade));
+ if (dexopt_needed != kNoDexOptNeeded && (&info == &dm_for_oat_ || &info == &dm_for_odex_)) {
+ // The usable vdex file is in the DM file. This information cannot be encoded in the integer.
+ // Return kDex2OatFromScratch so that neither the vdex in the "oat" location nor the vdex in the
+ // "odex" location will be picked by installd.
+ return kDex2OatFromScratch;
+ }
if (info.IsOatLocation() || dexopt_needed == kDex2OatFromScratch) {
return dexopt_needed;
}
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index f82e0b1..d00e588 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -20,7 +20,6 @@
#include <gtest/gtest.h>
#include <sys/param.h>
-#include <cmath>
#include <functional>
#include <memory>
#include <string>
@@ -933,9 +932,7 @@
/*expected_dexopt_needed=*/false,
/*expected_is_vdex_usable=*/true,
/*expected_location=*/OatFileAssistant::kLocationOat);
- // The legacy implementation is wrong.
- // TODO(jiakaiz): Fix it.
- EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerify, /*profile_changed=*/true));
EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
@@ -1919,8 +1916,6 @@
// Case: We have a DEX file but we don't have an ODEX file for it. The caller's intention is to
// downgrade the compiler filter.
// Expect: Dexopt should never be performed regardless of the target compiler filter.
-// The legacy implementation is wrong.
-// TODO(jiakaiz): Fix it.
TEST_P(OatFileAssistantTest, DowngradeNoOdex) {
std::string dex_location = GetScratchDir() + "/TestDex.jar";
Copy(GetDexSrc1(), dex_location);
@@ -1936,7 +1931,7 @@
/*expected_dexopt_needed=*/false,
/*expected_is_vdex_usable=*/false,
/*expected_location=*/OatFileAssistant::kLocationNoneOrError);
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
oat_file_assistant.GetDexOptNeeded(
CompilerFilter::kSpeed, /*profile_changed=*/false, /*downgrade=*/true));
@@ -1946,7 +1941,7 @@
/*expected_dexopt_needed=*/false,
/*expected_is_vdex_usable=*/false,
/*expected_location=*/OatFileAssistant::kLocationNoneOrError);
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
oat_file_assistant.GetDexOptNeeded(
CompilerFilter::kSpeedProfile, /*profile_changed=*/false, /*downgrade=*/true));
@@ -1956,7 +1951,7 @@
/*expected_dexopt_needed=*/false,
/*expected_is_vdex_usable=*/false,
/*expected_location=*/OatFileAssistant::kLocationNoneOrError);
- EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
oat_file_assistant.GetDexOptNeeded(
CompilerFilter::kVerify, /*profile_changed=*/false, /*downgrade=*/true));
}
@@ -1965,8 +1960,6 @@
// both `profile_changed` and `downgrade` being true. This won't happen in the real case. Just to be
// complete.
// Expect: The behavior should be as `profile_changed` is false and `downgrade` is true.
-// The legacy implementation is wrong.
-// TODO(jiakaiz): Fix it.
TEST_P(OatFileAssistantTest, ProfileChangedDowngrade) {
std::string dex_location = GetScratchDir() + "/TestDex.jar";
std::string odex_location = GetOdexDir() + "/TestDex.odex";
@@ -1977,11 +1970,11 @@
OatFileAssistant oat_file_assistant = CreateOatFileAssistant(dex_location.c_str());
- EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
+ EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
oat_file_assistant.GetDexOptNeeded(
CompilerFilter::kSpeed, /*profile_changed=*/true, /*downgrade=*/true));
- EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
+ EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
oat_file_assistant.GetDexOptNeeded(
CompilerFilter::kSpeedProfile, /*profile_changed=*/true, /*downgrade=*/true));
@@ -2080,9 +2073,8 @@
// Expect: Dexopt should be performed if the compiler filter is better than "verify". The location
// should be kLocationDm.
//
-// The legacy version is wrong this case. It returns kDex2OatForFilter with an arbitrary sign if the
-// target compiler filter is better than "verify".
-// TODO(jiakaiz): Fix it.
+// The legacy version should return kDex2OatFromScratch if the target compiler filter is better than
+// "verify".
TEST_P(OatFileAssistantTest, DmUpToDate) {
std::string dex_location = GetScratchDir() + "/TestDex.jar";
std::string dm_location = GetScratchDir() + "/TestDex.dm";
@@ -2110,8 +2102,8 @@
/*expected_dexopt_needed=*/true,
/*expected_is_vdex_usable=*/true,
/*expected_location=*/OatFileAssistant::kLocationDm);
- EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
- abs(oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)));
+ EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
+ oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
VerifyGetDexOptNeeded(&oat_file_assistant,
CompilerFilter::kSpeedProfile,
@@ -2119,8 +2111,8 @@
/*expected_dexopt_needed=*/true,
/*expected_is_vdex_usable=*/true,
/*expected_location=*/OatFileAssistant::kLocationDm);
- EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
- abs(oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile)));
+ EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
+ oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile));
VerifyGetDexOptNeeded(&oat_file_assistant,
CompilerFilter::kVerify,
@@ -2129,7 +2121,7 @@
/*expected_is_vdex_usable=*/true,
/*expected_location=*/OatFileAssistant::kLocationDm);
EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
- abs(oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerify)));
+ oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerify));
}
// Test that GetLocation of a dex file is the same whether the dex