1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*795d594fSAndroid Build Coastguard Worker #include <algorithm>
19*795d594fSAndroid Build Coastguard Worker #include <stdio.h>
20*795d594fSAndroid Build Coastguard Worker
21*795d594fSAndroid Build Coastguard Worker #include "base/arena_allocator.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/common_art_test.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/unix_file/fd_file.h"
24*795d594fSAndroid Build Coastguard Worker #include "dex/compact_dex_file.h"
25*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
26*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_loader.h"
27*795d594fSAndroid Build Coastguard Worker #include "dex/method_reference.h"
28*795d594fSAndroid Build Coastguard Worker #include "dex/type_reference.h"
29*795d594fSAndroid Build Coastguard Worker #include "profile/profile_compilation_info.h"
30*795d594fSAndroid Build Coastguard Worker #include "profile/profile_test_helper.h"
31*795d594fSAndroid Build Coastguard Worker #include "ziparchive/zip_writer.h"
32*795d594fSAndroid Build Coastguard Worker
33*795d594fSAndroid Build Coastguard Worker namespace art {
34*795d594fSAndroid Build Coastguard Worker
35*795d594fSAndroid Build Coastguard Worker using ItemMetadata = FlattenProfileData::ItemMetadata;
36*795d594fSAndroid Build Coastguard Worker
37*795d594fSAndroid Build Coastguard Worker class ProfileCompilationInfoTest : public CommonArtTest, public ProfileTestHelper {
38*795d594fSAndroid Build Coastguard Worker public:
SetUp()39*795d594fSAndroid Build Coastguard Worker void SetUp() override {
40*795d594fSAndroid Build Coastguard Worker CommonArtTest::SetUp();
41*795d594fSAndroid Build Coastguard Worker allocator_.reset(new ArenaAllocator(&pool_));
42*795d594fSAndroid Build Coastguard Worker
43*795d594fSAndroid Build Coastguard Worker dex1 = BuildDex("location1", /*location_checksum=*/ 1, "LUnique1;", /*num_method_ids=*/ 101);
44*795d594fSAndroid Build Coastguard Worker dex2 = BuildDex("location2", /*location_checksum=*/ 2, "LUnique2;", /*num_method_ids=*/ 102);
45*795d594fSAndroid Build Coastguard Worker dex3 = BuildDex("location3", /*location_checksum=*/ 3, "LUnique3;", /*num_method_ids=*/ 103);
46*795d594fSAndroid Build Coastguard Worker dex4 = BuildDex("location4", /*location_checksum=*/ 4, "LUnique4;", /*num_method_ids=*/ 104);
47*795d594fSAndroid Build Coastguard Worker
48*795d594fSAndroid Build Coastguard Worker dex1_checksum_missmatch = BuildDex("location1",
49*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 12,
50*795d594fSAndroid Build Coastguard Worker "LUnique1;",
51*795d594fSAndroid Build Coastguard Worker /*num_method_ids=*/ 101);
52*795d594fSAndroid Build Coastguard Worker dex1_renamed = BuildDex("location1-renamed",
53*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 1,
54*795d594fSAndroid Build Coastguard Worker "LUnique1;",
55*795d594fSAndroid Build Coastguard Worker /*num_method_ids=*/ 101);
56*795d594fSAndroid Build Coastguard Worker dex2_renamed = BuildDex("location2-renamed",
57*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 2,
58*795d594fSAndroid Build Coastguard Worker "LUnique2;",
59*795d594fSAndroid Build Coastguard Worker /*num_method_ids=*/ 102);
60*795d594fSAndroid Build Coastguard Worker }
61*795d594fSAndroid Build Coastguard Worker
62*795d594fSAndroid Build Coastguard Worker protected:
GetFd(const ScratchFile & file)63*795d594fSAndroid Build Coastguard Worker uint32_t GetFd(const ScratchFile& file) {
64*795d594fSAndroid Build Coastguard Worker return static_cast<uint32_t>(file.GetFd());
65*795d594fSAndroid Build Coastguard Worker }
66*795d594fSAndroid Build Coastguard Worker
GetMethod(const ProfileCompilationInfo & info,const DexFile * dex,uint16_t method_idx,const ProfileSampleAnnotation & annotation=ProfileSampleAnnotation::kNone)67*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness GetMethod(
68*795d594fSAndroid Build Coastguard Worker const ProfileCompilationInfo& info,
69*795d594fSAndroid Build Coastguard Worker const DexFile* dex,
70*795d594fSAndroid Build Coastguard Worker uint16_t method_idx,
71*795d594fSAndroid Build Coastguard Worker const ProfileSampleAnnotation& annotation = ProfileSampleAnnotation::kNone) {
72*795d594fSAndroid Build Coastguard Worker return info.GetMethodHotness(MethodReference(dex, method_idx), annotation);
73*795d594fSAndroid Build Coastguard Worker }
74*795d594fSAndroid Build Coastguard Worker
75*795d594fSAndroid Build Coastguard Worker // Creates the default inline caches used in tests.
GetTestInlineCaches()76*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> GetTestInlineCaches() {
77*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches;
78*795d594fSAndroid Build Coastguard Worker // Monomorphic
79*795d594fSAndroid Build Coastguard Worker for (uint16_t dex_pc = 0; dex_pc < 11; dex_pc++) {
80*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types = {TypeReference(dex1, dex::TypeIndex(0))};
81*795d594fSAndroid Build Coastguard Worker inline_caches.push_back(ProfileInlineCache(dex_pc, /*missing_types=*/ false, types));
82*795d594fSAndroid Build Coastguard Worker }
83*795d594fSAndroid Build Coastguard Worker // Polymorphic
84*795d594fSAndroid Build Coastguard Worker for (uint16_t dex_pc = 11; dex_pc < 22; dex_pc++) {
85*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types = {
86*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(0)),
87*795d594fSAndroid Build Coastguard Worker TypeReference(dex2, dex::TypeIndex(1)),
88*795d594fSAndroid Build Coastguard Worker TypeReference(dex3, dex::TypeIndex(2))};
89*795d594fSAndroid Build Coastguard Worker inline_caches.push_back(ProfileInlineCache(dex_pc, /*missing_types=*/ false, types));
90*795d594fSAndroid Build Coastguard Worker }
91*795d594fSAndroid Build Coastguard Worker // Megamorphic
92*795d594fSAndroid Build Coastguard Worker for (uint16_t dex_pc = 22; dex_pc < 33; dex_pc++) {
93*795d594fSAndroid Build Coastguard Worker // We need 5 types to make the cache megamorphic.
94*795d594fSAndroid Build Coastguard Worker // The `is_megamorphic` flag shall be `false`; it is not used for testing.
95*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types = {
96*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(0)),
97*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(1)),
98*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(2)),
99*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(3)),
100*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(4))};
101*795d594fSAndroid Build Coastguard Worker inline_caches.push_back(ProfileInlineCache(dex_pc, /*missing_types=*/ false, types));
102*795d594fSAndroid Build Coastguard Worker }
103*795d594fSAndroid Build Coastguard Worker // Missing types
104*795d594fSAndroid Build Coastguard Worker for (uint16_t dex_pc = 33; dex_pc < 44; dex_pc++) {
105*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types;
106*795d594fSAndroid Build Coastguard Worker inline_caches.push_back(ProfileInlineCache(dex_pc, /*missing_types=*/ true, types));
107*795d594fSAndroid Build Coastguard Worker }
108*795d594fSAndroid Build Coastguard Worker
109*795d594fSAndroid Build Coastguard Worker return inline_caches;
110*795d594fSAndroid Build Coastguard Worker }
111*795d594fSAndroid Build Coastguard Worker
MakeMegamorphic(std::vector<ProfileInlineCache> * inline_caches)112*795d594fSAndroid Build Coastguard Worker void MakeMegamorphic(/*out*/std::vector<ProfileInlineCache>* inline_caches) {
113*795d594fSAndroid Build Coastguard Worker for (ProfileInlineCache& cache : *inline_caches) {
114*795d594fSAndroid Build Coastguard Worker uint16_t k = 5;
115*795d594fSAndroid Build Coastguard Worker while (cache.classes.size() < ProfileCompilationInfo::kIndividualInlineCacheSize) {
116*795d594fSAndroid Build Coastguard Worker TypeReference type_ref(dex1, dex::TypeIndex(k++));
117*795d594fSAndroid Build Coastguard Worker if (std::find(cache.classes.begin(), cache.classes.end(), type_ref) ==
118*795d594fSAndroid Build Coastguard Worker cache.classes.end()) {
119*795d594fSAndroid Build Coastguard Worker const_cast<std::vector<TypeReference>*>(&cache.classes)->push_back(type_ref);
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker }
122*795d594fSAndroid Build Coastguard Worker }
123*795d594fSAndroid Build Coastguard Worker }
124*795d594fSAndroid Build Coastguard Worker
SetIsMissingTypes(std::vector<ProfileInlineCache> * inline_caches)125*795d594fSAndroid Build Coastguard Worker void SetIsMissingTypes(/*out*/std::vector<ProfileInlineCache>* inline_caches) {
126*795d594fSAndroid Build Coastguard Worker for (ProfileInlineCache& cache : *inline_caches) {
127*795d594fSAndroid Build Coastguard Worker *(const_cast<bool*>(&(cache.is_missing_types))) = true;
128*795d594fSAndroid Build Coastguard Worker }
129*795d594fSAndroid Build Coastguard Worker }
130*795d594fSAndroid Build Coastguard Worker
TestProfileLoadFromZip(const char * zip_entry,size_t zip_flags,bool should_succeed,bool should_succeed_with_empty_profile=false)131*795d594fSAndroid Build Coastguard Worker void TestProfileLoadFromZip(const char* zip_entry,
132*795d594fSAndroid Build Coastguard Worker size_t zip_flags,
133*795d594fSAndroid Build Coastguard Worker bool should_succeed,
134*795d594fSAndroid Build Coastguard Worker bool should_succeed_with_empty_profile = false) {
135*795d594fSAndroid Build Coastguard Worker // Create a valid profile.
136*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
137*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info;
138*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
139*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex1, /*method_idx=*/ i));
140*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex2, /*method_idx=*/ i));
141*795d594fSAndroid Build Coastguard Worker }
142*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
143*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
144*795d594fSAndroid Build Coastguard Worker
145*795d594fSAndroid Build Coastguard Worker // Prepare the profile content for zipping.
146*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> data(profile.GetFile()->GetLength());
147*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->PreadFully(data.data(), data.size(), /*offset=*/ 0));
148*795d594fSAndroid Build Coastguard Worker
149*795d594fSAndroid Build Coastguard Worker // Zip the profile content.
150*795d594fSAndroid Build Coastguard Worker ScratchFile zip;
151*795d594fSAndroid Build Coastguard Worker FILE* file = fopen(zip.GetFile()->GetPath().c_str(), "wbe");
152*795d594fSAndroid Build Coastguard Worker ZipWriter writer(file);
153*795d594fSAndroid Build Coastguard Worker writer.StartEntry(zip_entry, zip_flags);
154*795d594fSAndroid Build Coastguard Worker writer.WriteBytes(data.data(), data.size());
155*795d594fSAndroid Build Coastguard Worker writer.FinishEntry();
156*795d594fSAndroid Build Coastguard Worker writer.Finish();
157*795d594fSAndroid Build Coastguard Worker fflush(file);
158*795d594fSAndroid Build Coastguard Worker fclose(file);
159*795d594fSAndroid Build Coastguard Worker
160*795d594fSAndroid Build Coastguard Worker // Verify loading from the zip archive.
161*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
162*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(should_succeed, loaded_info.Load(zip.GetFile()->GetPath(), false));
163*795d594fSAndroid Build Coastguard Worker if (should_succeed) {
164*795d594fSAndroid Build Coastguard Worker if (should_succeed_with_empty_profile) {
165*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.IsEmpty());
166*795d594fSAndroid Build Coastguard Worker } else {
167*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(saved_info));
168*795d594fSAndroid Build Coastguard Worker }
169*795d594fSAndroid Build Coastguard Worker }
170*795d594fSAndroid Build Coastguard Worker }
171*795d594fSAndroid Build Coastguard Worker
IsEmpty(const ProfileCompilationInfo & info)172*795d594fSAndroid Build Coastguard Worker bool IsEmpty(const ProfileCompilationInfo& info) {
173*795d594fSAndroid Build Coastguard Worker return info.IsEmpty();
174*795d594fSAndroid Build Coastguard Worker }
175*795d594fSAndroid Build Coastguard Worker
SizeStressTest(bool random)176*795d594fSAndroid Build Coastguard Worker void SizeStressTest(bool random) {
177*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo boot_profile(/*for_boot_image=*/ true);
178*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo reg_profile(/*for_boot_image=*/ false);
179*795d594fSAndroid Build Coastguard Worker
180*795d594fSAndroid Build Coastguard Worker static constexpr size_t kNumDexFiles = 5;
181*795d594fSAndroid Build Coastguard Worker
182*795d594fSAndroid Build Coastguard Worker std::vector<const DexFile*> dex_files;
183*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < kNumDexFiles; i++) {
184*795d594fSAndroid Build Coastguard Worker dex_files.push_back(BuildDex(std::to_string(i), i, "LC;", kMaxMethodIds));
185*795d594fSAndroid Build Coastguard Worker }
186*795d594fSAndroid Build Coastguard Worker
187*795d594fSAndroid Build Coastguard Worker std::srand(0);
188*795d594fSAndroid Build Coastguard Worker // Set a few flags on a 2 different methods in each of the profile.
189*795d594fSAndroid Build Coastguard Worker for (const DexFile* dex_file : dex_files) {
190*795d594fSAndroid Build Coastguard Worker for (uint32_t method_idx = 0; method_idx < kMaxMethodIds; method_idx++) {
191*795d594fSAndroid Build Coastguard Worker for (uint32_t flag_index = 0; flag_index <= kMaxHotnessFlagBootIndex; flag_index++) {
192*795d594fSAndroid Build Coastguard Worker if (!random || rand() % 2 == 0) {
193*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(
194*795d594fSAndroid Build Coastguard Worker &boot_profile,
195*795d594fSAndroid Build Coastguard Worker dex_file,
196*795d594fSAndroid Build Coastguard Worker method_idx,
197*795d594fSAndroid Build Coastguard Worker static_cast<Hotness::Flag>(1 << flag_index)));
198*795d594fSAndroid Build Coastguard Worker }
199*795d594fSAndroid Build Coastguard Worker }
200*795d594fSAndroid Build Coastguard Worker for (uint32_t flag_index = 0; flag_index <= kMaxHotnessFlagRegularIndex; flag_index++) {
201*795d594fSAndroid Build Coastguard Worker if (!random || rand() % 2 == 0) {
202*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(
203*795d594fSAndroid Build Coastguard Worker ®_profile,
204*795d594fSAndroid Build Coastguard Worker dex_file,
205*795d594fSAndroid Build Coastguard Worker method_idx,
206*795d594fSAndroid Build Coastguard Worker static_cast<Hotness::Flag>(1 << flag_index)));
207*795d594fSAndroid Build Coastguard Worker }
208*795d594fSAndroid Build Coastguard Worker }
209*795d594fSAndroid Build Coastguard Worker }
210*795d594fSAndroid Build Coastguard Worker }
211*795d594fSAndroid Build Coastguard Worker
212*795d594fSAndroid Build Coastguard Worker ScratchFile boot_file;
213*795d594fSAndroid Build Coastguard Worker ScratchFile reg_file;
214*795d594fSAndroid Build Coastguard Worker
215*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(boot_profile.Save(GetFd(boot_file)));
216*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(reg_profile.Save(GetFd(reg_file)));
217*795d594fSAndroid Build Coastguard Worker
218*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_boot(/*for_boot_image=*/ true);
219*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_reg;
220*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_boot.Load(GetFd(boot_file)));
221*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_reg.Load(GetFd(reg_file)));
222*795d594fSAndroid Build Coastguard Worker }
223*795d594fSAndroid Build Coastguard Worker
224*795d594fSAndroid Build Coastguard Worker static constexpr size_t kMaxMethodIds = 65535;
225*795d594fSAndroid Build Coastguard Worker static constexpr size_t kMaxClassIds = 65535;
226*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kMaxHotnessFlagBootIndex =
227*795d594fSAndroid Build Coastguard Worker WhichPowerOf2(static_cast<uint32_t>(Hotness::kFlagLastBoot));
228*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kMaxHotnessFlagRegularIndex =
229*795d594fSAndroid Build Coastguard Worker WhichPowerOf2(static_cast<uint32_t>(Hotness::kFlagLastRegular));
230*795d594fSAndroid Build Coastguard Worker
231*795d594fSAndroid Build Coastguard Worker // Cannot sizeof the actual arrays so hard code the values here.
232*795d594fSAndroid Build Coastguard Worker // They should not change anyway.
233*795d594fSAndroid Build Coastguard Worker static constexpr int kProfileMagicSize = 4;
234*795d594fSAndroid Build Coastguard Worker static constexpr int kProfileVersionSize = 4;
235*795d594fSAndroid Build Coastguard Worker
236*795d594fSAndroid Build Coastguard Worker MallocArenaPool pool_;
237*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ArenaAllocator> allocator_;
238*795d594fSAndroid Build Coastguard Worker
239*795d594fSAndroid Build Coastguard Worker const DexFile* dex1;
240*795d594fSAndroid Build Coastguard Worker const DexFile* dex2;
241*795d594fSAndroid Build Coastguard Worker const DexFile* dex3;
242*795d594fSAndroid Build Coastguard Worker const DexFile* dex4;
243*795d594fSAndroid Build Coastguard Worker const DexFile* dex1_checksum_missmatch;
244*795d594fSAndroid Build Coastguard Worker const DexFile* dex1_renamed;
245*795d594fSAndroid Build Coastguard Worker const DexFile* dex2_renamed;
246*795d594fSAndroid Build Coastguard Worker
247*795d594fSAndroid Build Coastguard Worker // Cache of inline caches generated during tests.
248*795d594fSAndroid Build Coastguard Worker // This makes it easier to pass data between different utilities and ensure that
249*795d594fSAndroid Build Coastguard Worker // caches are destructed at the end of the test.
250*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<ProfileCompilationInfo::InlineCacheMap>> used_inline_caches;
251*795d594fSAndroid Build Coastguard Worker };
252*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,AddClasses)253*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, AddClasses) {
254*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
255*795d594fSAndroid Build Coastguard Worker
256*795d594fSAndroid Build Coastguard Worker // Add all classes with a `TypeId` in `dex1`.
257*795d594fSAndroid Build Coastguard Worker uint32_t num_type_ids1 = dex1->NumTypeIds();
258*795d594fSAndroid Build Coastguard Worker for (uint32_t type_index = 0; type_index != num_type_ids1; ++type_index) {
259*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.AddClass(*dex1, dex::TypeIndex(type_index)));
260*795d594fSAndroid Build Coastguard Worker }
261*795d594fSAndroid Build Coastguard Worker // Add classes without `TypeId` in `dex1`.
262*795d594fSAndroid Build Coastguard Worker for (uint32_t type_index = num_type_ids1; type_index != DexFile::kDexNoIndex16; ++type_index) {
263*795d594fSAndroid Build Coastguard Worker std::string descriptor = "LX" + std::to_string(type_index) + ";";
264*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.AddClass(*dex1, descriptor));
265*795d594fSAndroid Build Coastguard Worker }
266*795d594fSAndroid Build Coastguard Worker // Fail to add another class without `TypeId` in `dex1` as we have
267*795d594fSAndroid Build Coastguard Worker // run out of available artificial type indexes.
268*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(info.AddClass(*dex1, "LCannotAddThis;"));
269*795d594fSAndroid Build Coastguard Worker
270*795d594fSAndroid Build Coastguard Worker // Add all classes with a `TypeId` in `dex2`.
271*795d594fSAndroid Build Coastguard Worker uint32_t num_type_ids2 = dex2->NumTypeIds();
272*795d594fSAndroid Build Coastguard Worker for (uint32_t type_index = 0; type_index != num_type_ids2; ++type_index) {
273*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.AddClass(*dex2, dex::TypeIndex(type_index)));
274*795d594fSAndroid Build Coastguard Worker }
275*795d594fSAndroid Build Coastguard Worker // Fail to add another class without `TypeId` in `dex2` as we have
276*795d594fSAndroid Build Coastguard Worker // run out of available artificial type indexes when adding types for `dex1`.
277*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(info.AddClass(*dex2, "LCannotAddThis;"));
278*795d594fSAndroid Build Coastguard Worker // Add classes without `TypeId` in `dex2` for which we already have articial indexes.
279*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(num_type_ids1, num_type_ids2);
280*795d594fSAndroid Build Coastguard Worker for (uint32_t type_index = num_type_ids2; type_index != DexFile::kDexNoIndex16; ++type_index) {
281*795d594fSAndroid Build Coastguard Worker std::string descriptor = "LX" + std::to_string(type_index) + ";";
282*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.AddClass(*dex2, descriptor));
283*795d594fSAndroid Build Coastguard Worker }
284*795d594fSAndroid Build Coastguard Worker }
285*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,SaveFd)286*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, SaveFd) {
287*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
288*795d594fSAndroid Build Coastguard Worker
289*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info;
290*795d594fSAndroid Build Coastguard Worker // Save a few methods.
291*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
292*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex1, /*method_idx=*/ i));
293*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex2, /*method_idx=*/ i));
294*795d594fSAndroid Build Coastguard Worker }
295*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
296*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
297*795d594fSAndroid Build Coastguard Worker
298*795d594fSAndroid Build Coastguard Worker // Check that we get back what we saved.
299*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
300*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
301*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(saved_info));
302*795d594fSAndroid Build Coastguard Worker
303*795d594fSAndroid Build Coastguard Worker // Save more methods.
304*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 100; i++) {
305*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex1, /*method_idx=*/ i));
306*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex2, /*method_idx=*/ i));
307*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex3, /*method_idx=*/ i));
308*795d594fSAndroid Build Coastguard Worker }
309*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->ResetOffset());
310*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
311*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
312*795d594fSAndroid Build Coastguard Worker
313*795d594fSAndroid Build Coastguard Worker // Check that we get back everything we saved.
314*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info2;
315*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info2.Load(GetFd(profile)));
316*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info2.Equals(saved_info));
317*795d594fSAndroid Build Coastguard Worker }
318*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,AddMethodsAndClassesFail)319*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, AddMethodsAndClassesFail) {
320*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
321*795d594fSAndroid Build Coastguard Worker
322*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
323*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ 1));
324*795d594fSAndroid Build Coastguard Worker // Trying to add info for an existing file but with a different checksum.
325*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(AddMethod(&info, dex1_checksum_missmatch, /*method_idx=*/ 2));
326*795d594fSAndroid Build Coastguard Worker }
327*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,MergeFail)328*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, MergeFail) {
329*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
330*795d594fSAndroid Build Coastguard Worker
331*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
332*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info1, dex1, /*method_idx=*/ 1));
333*795d594fSAndroid Build Coastguard Worker // Use the same file, change the checksum.
334*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
335*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info2, dex1_checksum_missmatch, /*method_idx=*/ 2));
336*795d594fSAndroid Build Coastguard Worker
337*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(info1.MergeWith(info2));
338*795d594fSAndroid Build Coastguard Worker }
339*795d594fSAndroid Build Coastguard Worker
340*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,MergeFdFail)341*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, MergeFdFail) {
342*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
343*795d594fSAndroid Build Coastguard Worker
344*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
345*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info1, dex1, /*method_idx=*/ 1));
346*795d594fSAndroid Build Coastguard Worker // Use the same file, change the checksum.
347*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
348*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info2, dex1_checksum_missmatch, /*method_idx=*/ 2));
349*795d594fSAndroid Build Coastguard Worker
350*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info1.Save(profile.GetFd()));
351*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
352*795d594fSAndroid Build Coastguard Worker
353*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(info2.Load(profile.GetFd()));
354*795d594fSAndroid Build Coastguard Worker }
355*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,SaveMaxMethods)356*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, SaveMaxMethods) {
357*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
358*795d594fSAndroid Build Coastguard Worker
359*795d594fSAndroid Build Coastguard Worker const DexFile* dex_max1 = BuildDex("location-max1",
360*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 5,
361*795d594fSAndroid Build Coastguard Worker "LUniqueMax1;",
362*795d594fSAndroid Build Coastguard Worker kMaxMethodIds,
363*795d594fSAndroid Build Coastguard Worker kMaxClassIds);
364*795d594fSAndroid Build Coastguard Worker const DexFile* dex_max2 = BuildDex("location-max2",
365*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 6,
366*795d594fSAndroid Build Coastguard Worker "LUniqueMax2;",
367*795d594fSAndroid Build Coastguard Worker kMaxMethodIds,
368*795d594fSAndroid Build Coastguard Worker kMaxClassIds);
369*795d594fSAndroid Build Coastguard Worker
370*795d594fSAndroid Build Coastguard Worker
371*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info;
372*795d594fSAndroid Build Coastguard Worker // Save the maximum number of methods
373*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < std::numeric_limits<uint16_t>::max(); i++) {
374*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex_max1, /*method_idx=*/ i));
375*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex_max2, /*method_idx=*/ i));
376*795d594fSAndroid Build Coastguard Worker }
377*795d594fSAndroid Build Coastguard Worker // Save the maximum number of classes
378*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < std::numeric_limits<uint16_t>::max(); i++) {
379*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&saved_info, dex_max1, dex::TypeIndex(i)));
380*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&saved_info, dex_max2, dex::TypeIndex(i)));
381*795d594fSAndroid Build Coastguard Worker }
382*795d594fSAndroid Build Coastguard Worker
383*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
384*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
385*795d594fSAndroid Build Coastguard Worker
386*795d594fSAndroid Build Coastguard Worker // Check that we get back what we saved.
387*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
388*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
389*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(saved_info));
390*795d594fSAndroid Build Coastguard Worker }
391*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,SaveEmpty)392*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, SaveEmpty) {
393*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
394*795d594fSAndroid Build Coastguard Worker
395*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info;
396*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
397*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
398*795d594fSAndroid Build Coastguard Worker
399*795d594fSAndroid Build Coastguard Worker // Check that we get back what we saved.
400*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
401*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
402*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(saved_info));
403*795d594fSAndroid Build Coastguard Worker }
404*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,LoadEmpty)405*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, LoadEmpty) {
406*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
407*795d594fSAndroid Build Coastguard Worker
408*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo empty_info;
409*795d594fSAndroid Build Coastguard Worker
410*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
411*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
412*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(empty_info));
413*795d594fSAndroid Build Coastguard Worker }
414*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,BadMagic)415*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, BadMagic) {
416*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
417*795d594fSAndroid Build Coastguard Worker uint8_t buffer[] = { 1, 2, 3, 4 };
418*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(buffer, sizeof(buffer)));
419*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
420*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(loaded_info.Load(GetFd(profile)));
421*795d594fSAndroid Build Coastguard Worker }
422*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,BadVersion)423*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, BadVersion) {
424*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
425*795d594fSAndroid Build Coastguard Worker
426*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(
427*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::kProfileMagic, kProfileMagicSize));
428*795d594fSAndroid Build Coastguard Worker uint8_t version[] = { 'v', 'e', 'r', 's', 'i', 'o', 'n' };
429*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(version, sizeof(version)));
430*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
431*795d594fSAndroid Build Coastguard Worker
432*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
433*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(loaded_info.Load(GetFd(profile)));
434*795d594fSAndroid Build Coastguard Worker }
435*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,Incomplete)436*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, Incomplete) {
437*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
438*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(
439*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::kProfileMagic, kProfileMagicSize));
440*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(
441*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::kProfileVersion, kProfileVersionSize));
442*795d594fSAndroid Build Coastguard Worker // Write that we have one section info.
443*795d594fSAndroid Build Coastguard Worker const uint32_t file_section_count = 1u;
444*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(&file_section_count, sizeof(file_section_count)));
445*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
446*795d594fSAndroid Build Coastguard Worker
447*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
448*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(loaded_info.Load(GetFd(profile)));
449*795d594fSAndroid Build Coastguard Worker }
450*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,TooLongDexLocation)451*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, TooLongDexLocation) {
452*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
453*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(
454*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::kProfileMagic, kProfileMagicSize));
455*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(
456*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::kProfileVersion, kProfileVersionSize));
457*795d594fSAndroid Build Coastguard Worker // Write that we have one section info.
458*795d594fSAndroid Build Coastguard Worker const uint32_t file_section_count = 1u;
459*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(&file_section_count, sizeof(file_section_count)));
460*795d594fSAndroid Build Coastguard Worker
461*795d594fSAndroid Build Coastguard Worker constexpr size_t kInvalidDexFileLocationLength = 1025u;
462*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kDexFilesOffset =
463*795d594fSAndroid Build Coastguard Worker kProfileMagicSize + kProfileVersionSize + sizeof(file_section_count) + 4u * sizeof(uint32_t);
464*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kDexFilesSize =
465*795d594fSAndroid Build Coastguard Worker sizeof(ProfileIndexType) + // number of dex files
466*795d594fSAndroid Build Coastguard Worker 3u * sizeof(uint32_t) + // numeric data
467*795d594fSAndroid Build Coastguard Worker kInvalidDexFileLocationLength + 1u; // null-terminated string
468*795d594fSAndroid Build Coastguard Worker const uint32_t section_info[] = {
469*795d594fSAndroid Build Coastguard Worker 0u, // type = kDexFiles
470*795d594fSAndroid Build Coastguard Worker kDexFilesOffset,
471*795d594fSAndroid Build Coastguard Worker kDexFilesSize,
472*795d594fSAndroid Build Coastguard Worker 0u, // inflated size = 0
473*795d594fSAndroid Build Coastguard Worker };
474*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(section_info, sizeof(section_info)));
475*795d594fSAndroid Build Coastguard Worker
476*795d594fSAndroid Build Coastguard Worker ProfileIndexType num_dex_files = 1u;
477*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(&num_dex_files, sizeof(num_dex_files)));
478*795d594fSAndroid Build Coastguard Worker
479*795d594fSAndroid Build Coastguard Worker uint32_t numeric_data[3] = {
480*795d594fSAndroid Build Coastguard Worker 1234u, // checksum
481*795d594fSAndroid Build Coastguard Worker 1u, // num_type_ids
482*795d594fSAndroid Build Coastguard Worker 2u, // num_method_ids
483*795d594fSAndroid Build Coastguard Worker };
484*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(numeric_data, sizeof(numeric_data)));
485*795d594fSAndroid Build Coastguard Worker
486*795d594fSAndroid Build Coastguard Worker std::string dex_location(kInvalidDexFileLocationLength, 'a');
487*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(dex_location.c_str(), dex_location.size() + 1u));
488*795d594fSAndroid Build Coastguard Worker
489*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
490*795d594fSAndroid Build Coastguard Worker
491*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
492*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(loaded_info.Load(GetFd(profile)));
493*795d594fSAndroid Build Coastguard Worker }
494*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,UnexpectedContent)495*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, UnexpectedContent) {
496*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
497*795d594fSAndroid Build Coastguard Worker
498*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info;
499*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
500*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex1, /*method_idx=*/ i));
501*795d594fSAndroid Build Coastguard Worker }
502*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
503*795d594fSAndroid Build Coastguard Worker
504*795d594fSAndroid Build Coastguard Worker uint8_t random_data[] = { 1, 2, 3};
505*795d594fSAndroid Build Coastguard Worker int64_t file_length = profile.GetFile()->GetLength();
506*795d594fSAndroid Build Coastguard Worker ASSERT_GT(file_length, 0);
507*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->PwriteFully(random_data, sizeof(random_data), file_length));
508*795d594fSAndroid Build Coastguard Worker
509*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
510*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(profile.GetFile()->GetLength(),
511*795d594fSAndroid Build Coastguard Worker file_length + static_cast<int64_t>(sizeof(random_data)));
512*795d594fSAndroid Build Coastguard Worker
513*795d594fSAndroid Build Coastguard Worker // Extra data at the end of the file is OK, loading the profile should succeed.
514*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
515*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
516*795d594fSAndroid Build Coastguard Worker }
517*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,SaveInlineCaches)518*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, SaveInlineCaches) {
519*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
520*795d594fSAndroid Build Coastguard Worker
521*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info;
522*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches = GetTestInlineCaches();
523*795d594fSAndroid Build Coastguard Worker
524*795d594fSAndroid Build Coastguard Worker // Add methods with inline caches.
525*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
526*795d594fSAndroid Build Coastguard Worker // Add a method which is part of the same dex file as one of the
527*795d594fSAndroid Build Coastguard Worker // class from the inline caches.
528*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex1, method_idx, inline_caches));
529*795d594fSAndroid Build Coastguard Worker // Add a method which is outside the set of dex files.
530*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex4, method_idx, inline_caches));
531*795d594fSAndroid Build Coastguard Worker }
532*795d594fSAndroid Build Coastguard Worker
533*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
534*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
535*795d594fSAndroid Build Coastguard Worker
536*795d594fSAndroid Build Coastguard Worker // Check that we get back what we saved.
537*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
538*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
539*795d594fSAndroid Build Coastguard Worker
540*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(saved_info));
541*795d594fSAndroid Build Coastguard Worker
542*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness1 =
543*795d594fSAndroid Build Coastguard Worker GetMethod(loaded_info, dex1, /*method_idx=*/ 3);
544*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness1.IsHot());
545*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(EqualInlineCaches(inline_caches, dex1, loaded_hotness1, loaded_info));
546*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness2 =
547*795d594fSAndroid Build Coastguard Worker GetMethod(loaded_info, dex4, /*method_idx=*/ 3);
548*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness2.IsHot());
549*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(EqualInlineCaches(inline_caches, dex4, loaded_hotness2, loaded_info));
550*795d594fSAndroid Build Coastguard Worker }
551*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,MegamorphicInlineCaches)552*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, MegamorphicInlineCaches) {
553*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info;
554*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches = GetTestInlineCaches();
555*795d594fSAndroid Build Coastguard Worker
556*795d594fSAndroid Build Coastguard Worker // Add methods with inline caches.
557*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
558*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex1, method_idx, inline_caches));
559*795d594fSAndroid Build Coastguard Worker }
560*795d594fSAndroid Build Coastguard Worker
561*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
562*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
563*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
564*795d594fSAndroid Build Coastguard Worker
565*795d594fSAndroid Build Coastguard Worker // Make the inline caches megamorphic and add them to the profile again.
566*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info_extra;
567*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches_extra = GetTestInlineCaches();
568*795d594fSAndroid Build Coastguard Worker MakeMegamorphic(&inline_caches_extra);
569*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
570*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info_extra, dex1, method_idx, inline_caches_extra));
571*795d594fSAndroid Build Coastguard Worker }
572*795d594fSAndroid Build Coastguard Worker
573*795d594fSAndroid Build Coastguard Worker ScratchFile extra_profile;
574*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info_extra.Save(GetFd(extra_profile)));
575*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, extra_profile.GetFile()->Flush());
576*795d594fSAndroid Build Coastguard Worker
577*795d594fSAndroid Build Coastguard Worker // Merge the profiles so that we have the same view as the file.
578*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.MergeWith(saved_info_extra));
579*795d594fSAndroid Build Coastguard Worker
580*795d594fSAndroid Build Coastguard Worker // Check that we get back what we saved.
581*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
582*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(extra_profile)));
583*795d594fSAndroid Build Coastguard Worker
584*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(saved_info));
585*795d594fSAndroid Build Coastguard Worker
586*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness1 =
587*795d594fSAndroid Build Coastguard Worker GetMethod(loaded_info, dex1, /*method_idx=*/ 3);
588*795d594fSAndroid Build Coastguard Worker
589*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness1.IsHot());
590*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(EqualInlineCaches(inline_caches_extra, dex1, loaded_hotness1, loaded_info));
591*795d594fSAndroid Build Coastguard Worker }
592*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,MissingTypesInlineCaches)593*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, MissingTypesInlineCaches) {
594*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info;
595*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches = GetTestInlineCaches();
596*795d594fSAndroid Build Coastguard Worker
597*795d594fSAndroid Build Coastguard Worker // Add methods with inline caches.
598*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
599*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex1, method_idx, inline_caches));
600*795d594fSAndroid Build Coastguard Worker }
601*795d594fSAndroid Build Coastguard Worker
602*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
603*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
604*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
605*795d594fSAndroid Build Coastguard Worker
606*795d594fSAndroid Build Coastguard Worker // Make some inline caches megamorphic and add them to the profile again.
607*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info_extra;
608*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches_extra = GetTestInlineCaches();
609*795d594fSAndroid Build Coastguard Worker MakeMegamorphic(&inline_caches_extra);
610*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 5; method_idx < 10; method_idx++) {
611*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info_extra, dex1, method_idx, inline_caches));
612*795d594fSAndroid Build Coastguard Worker }
613*795d594fSAndroid Build Coastguard Worker
614*795d594fSAndroid Build Coastguard Worker // Mark all inline caches with missing types and add them to the profile again.
615*795d594fSAndroid Build Coastguard Worker // This will verify that all inline caches (megamorphic or not) should be marked as missing types.
616*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> missing_types = GetTestInlineCaches();
617*795d594fSAndroid Build Coastguard Worker SetIsMissingTypes(&missing_types);
618*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
619*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info_extra, dex1, method_idx, missing_types));
620*795d594fSAndroid Build Coastguard Worker }
621*795d594fSAndroid Build Coastguard Worker
622*795d594fSAndroid Build Coastguard Worker ScratchFile extra_profile;
623*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info_extra.Save(GetFd(extra_profile)));
624*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, extra_profile.GetFile()->Flush());
625*795d594fSAndroid Build Coastguard Worker
626*795d594fSAndroid Build Coastguard Worker // Merge the profiles so that we have the same view as the file.
627*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.MergeWith(saved_info_extra));
628*795d594fSAndroid Build Coastguard Worker
629*795d594fSAndroid Build Coastguard Worker // Check that we get back what we saved.
630*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
631*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(extra_profile)));
632*795d594fSAndroid Build Coastguard Worker
633*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(saved_info));
634*795d594fSAndroid Build Coastguard Worker
635*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness1 =
636*795d594fSAndroid Build Coastguard Worker GetMethod(loaded_info, dex1, /*method_idx=*/ 3);
637*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness1.IsHot());
638*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(EqualInlineCaches(missing_types, dex1, loaded_hotness1, loaded_info));
639*795d594fSAndroid Build Coastguard Worker }
640*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,InvalidChecksumInInlineCache)641*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, InvalidChecksumInInlineCache) {
642*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
643*795d594fSAndroid Build Coastguard Worker
644*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
645*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches1 = GetTestInlineCaches();
646*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches2 = GetTestInlineCaches();
647*795d594fSAndroid Build Coastguard Worker // Modify the checksum to trigger a mismatch.
648*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference>* types = const_cast<std::vector<TypeReference>*>(
649*795d594fSAndroid Build Coastguard Worker &inline_caches2[0].classes);
650*795d594fSAndroid Build Coastguard Worker types->front().dex_file = dex1_checksum_missmatch;
651*795d594fSAndroid Build Coastguard Worker
652*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ 0, inline_caches1));
653*795d594fSAndroid Build Coastguard Worker
654*795d594fSAndroid Build Coastguard Worker // The dex files referenced in inline infos do not matter. We are recoding class
655*795d594fSAndroid Build Coastguard Worker // references across dex files by looking up the descriptor in the referencing
656*795d594fSAndroid Build Coastguard Worker // method's dex file. If not found, we create an artificial type index.
657*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex2, /*method_idx=*/ 0, inline_caches2));
658*795d594fSAndroid Build Coastguard Worker }
659*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,InlineCacheAcrossDexFiles)660*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, InlineCacheAcrossDexFiles) {
661*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
662*795d594fSAndroid Build Coastguard Worker
663*795d594fSAndroid Build Coastguard Worker const char kDex1Class[] = "LUnique1;";
664*795d594fSAndroid Build Coastguard Worker const dex::TypeId* dex1_tid = dex1->FindTypeId(kDex1Class);
665*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(dex1_tid != nullptr);
666*795d594fSAndroid Build Coastguard Worker dex::TypeIndex dex1_tidx = dex1->GetIndexForTypeId(*dex1_tid);
667*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(dex2->FindTypeId(kDex1Class) != nullptr);
668*795d594fSAndroid Build Coastguard Worker
669*795d594fSAndroid Build Coastguard Worker const uint16_t dex_pc = 33u;
670*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types = {TypeReference(dex1, dex1_tidx)};
671*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches {
672*795d594fSAndroid Build Coastguard Worker ProfileInlineCache(dex_pc, /*missing_types=*/ false, types)
673*795d594fSAndroid Build Coastguard Worker };
674*795d594fSAndroid Build Coastguard Worker
675*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
676*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex2, /*method_idx=*/ 0, inline_caches));
677*795d594fSAndroid Build Coastguard Worker Hotness hotness = GetMethod(info, dex2, /*method_idx=*/ 0);
678*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(hotness.IsHot());
679*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(EqualInlineCaches(inline_caches, dex2, hotness, info));
680*795d594fSAndroid Build Coastguard Worker const ProfileCompilationInfo::InlineCacheMap* inline_cache_map = hotness.GetInlineCacheMap();
681*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inline_cache_map != nullptr);
682*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(1u, inline_cache_map->size());
683*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(dex_pc, inline_cache_map->begin()->first);
684*795d594fSAndroid Build Coastguard Worker const ProfileCompilationInfo::DexPcData& dex_pc_data = inline_cache_map->begin()->second;
685*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(dex_pc_data.is_missing_types);
686*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(dex_pc_data.is_megamorphic);
687*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(1u, dex_pc_data.classes.size());
688*795d594fSAndroid Build Coastguard Worker dex::TypeIndex type_index = *dex_pc_data.classes.begin();
689*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(dex2->IsTypeIndexValid(type_index));
690*795d594fSAndroid Build Coastguard Worker ASSERT_STREQ(kDex1Class, info.GetTypeDescriptor(dex2, type_index));
691*795d594fSAndroid Build Coastguard Worker }
692*795d594fSAndroid Build Coastguard Worker
693*795d594fSAndroid Build Coastguard Worker // Verify that profiles behave correctly even if the methods are added in a different
694*795d594fSAndroid Build Coastguard Worker // order and with a different dex profile indices for the dex files.
TEST_F(ProfileCompilationInfoTest,MergeInlineCacheTriggerReindex)695*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, MergeInlineCacheTriggerReindex) {
696*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
697*795d594fSAndroid Build Coastguard Worker
698*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
699*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info_reindexed;
700*795d594fSAndroid Build Coastguard Worker
701*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches;
702*795d594fSAndroid Build Coastguard Worker for (uint16_t dex_pc = 1; dex_pc < 5; dex_pc++) {
703*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types = {
704*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(0)),
705*795d594fSAndroid Build Coastguard Worker TypeReference(dex2, dex::TypeIndex(1))};
706*795d594fSAndroid Build Coastguard Worker inline_caches.push_back(ProfileInlineCache(dex_pc, /*missing_types=*/ false, types));
707*795d594fSAndroid Build Coastguard Worker }
708*795d594fSAndroid Build Coastguard Worker
709*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches_reindexed;
710*795d594fSAndroid Build Coastguard Worker for (uint16_t dex_pc = 1; dex_pc < 5; dex_pc++) {
711*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types = {
712*795d594fSAndroid Build Coastguard Worker TypeReference(dex2, dex::TypeIndex(1)),
713*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(0))};
714*795d594fSAndroid Build Coastguard Worker inline_caches_reindexed.push_back(ProfileInlineCache(dex_pc, /*missing_types=*/ false, types));
715*795d594fSAndroid Build Coastguard Worker }
716*795d594fSAndroid Build Coastguard Worker // Profile 1 and Profile 2 get the same methods but in different order.
717*795d594fSAndroid Build Coastguard Worker // This will trigger a different dex numbers.
718*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
719*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex1, method_idx, inline_caches));
720*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex2, method_idx, inline_caches));
721*795d594fSAndroid Build Coastguard Worker }
722*795d594fSAndroid Build Coastguard Worker
723*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
724*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info_reindexed, dex2, method_idx, inline_caches_reindexed));
725*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info_reindexed, dex1, method_idx, inline_caches_reindexed));
726*795d594fSAndroid Build Coastguard Worker }
727*795d594fSAndroid Build Coastguard Worker
728*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info_backup;
729*795d594fSAndroid Build Coastguard Worker info_backup.MergeWith(info);
730*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.MergeWith(info_reindexed));
731*795d594fSAndroid Build Coastguard Worker // Merging should have no effect as we're adding the exact same stuff.
732*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Equals(info_backup));
733*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
734*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness1 = GetMethod(info, dex1, method_idx);
735*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness1.IsHot());
736*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(EqualInlineCaches(inline_caches, dex1, loaded_hotness1, info));
737*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness2 = GetMethod(info, dex2, method_idx);
738*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness2.IsHot());
739*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(EqualInlineCaches(inline_caches, dex2, loaded_hotness2, info));
740*795d594fSAndroid Build Coastguard Worker }
741*795d594fSAndroid Build Coastguard Worker }
742*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,AddMoreDexFileThanLimitRegular)743*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, AddMoreDexFileThanLimitRegular) {
744*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
745*795d594fSAndroid Build Coastguard Worker // Save a few methods.
746*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < std::numeric_limits<ProfileIndexType>::max(); i++) {
747*795d594fSAndroid Build Coastguard Worker std::string location = std::to_string(i);
748*795d594fSAndroid Build Coastguard Worker const DexFile* dex = BuildDex(location, /*location_checksum=*/ 1, "LC;", /*num_method_ids=*/ 1);
749*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex, /*method_idx=*/ 0));
750*795d594fSAndroid Build Coastguard Worker }
751*795d594fSAndroid Build Coastguard Worker // Add an extra dex file.
752*795d594fSAndroid Build Coastguard Worker const DexFile* dex = BuildDex("-1", /*location_checksum=*/ 1, "LC;", /*num_method_ids=*/ 1);
753*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(AddMethod(&info, dex, /*method_idx=*/ 0));
754*795d594fSAndroid Build Coastguard Worker }
755*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,AddMoreDexFileThanLimitBoot)756*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, AddMoreDexFileThanLimitBoot) {
757*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info(/*for_boot_image=*/true);
758*795d594fSAndroid Build Coastguard Worker // Save a few methods.
759*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < std::numeric_limits<ProfileIndexType>::max(); i++) {
760*795d594fSAndroid Build Coastguard Worker std::string location = std::to_string(i);
761*795d594fSAndroid Build Coastguard Worker const DexFile* dex = BuildDex(location, /*location_checksum=*/ 1, "LC;", /*num_method_ids=*/ 1);
762*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex, /*method_idx=*/ 0));
763*795d594fSAndroid Build Coastguard Worker }
764*795d594fSAndroid Build Coastguard Worker // Add an extra dex file.
765*795d594fSAndroid Build Coastguard Worker const DexFile* dex = BuildDex("-1", /*location_checksum=*/ 1, "LC;", /*num_method_ids=*/ 1);
766*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(AddMethod(&info, dex, /*method_idx=*/ 0));
767*795d594fSAndroid Build Coastguard Worker }
768*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,MegamorphicInlineCachesMerge)769*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, MegamorphicInlineCachesMerge) {
770*795d594fSAndroid Build Coastguard Worker // Create a megamorphic inline cache.
771*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches;
772*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types = {
773*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(0)),
774*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(1)),
775*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(2)),
776*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(3)),
777*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(4))};
778*795d594fSAndroid Build Coastguard Worker inline_caches.push_back(ProfileInlineCache(0, /*missing_types=*/ false, types));
779*795d594fSAndroid Build Coastguard Worker
780*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info_megamorphic;
781*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info_megamorphic, dex1, 0, inline_caches));
782*795d594fSAndroid Build Coastguard Worker
783*795d594fSAndroid Build Coastguard Worker // Create a profile with no inline caches (for the same method).
784*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info_no_inline_cache;
785*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info_no_inline_cache, dex1, 0));
786*795d594fSAndroid Build Coastguard Worker
787*795d594fSAndroid Build Coastguard Worker // Merge the megamorphic cache into the empty one.
788*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info_no_inline_cache.MergeWith(info_megamorphic));
789*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
790*795d594fSAndroid Build Coastguard Worker // Saving profile should work without crashing (b/35644850).
791*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info_no_inline_cache.Save(GetFd(profile)));
792*795d594fSAndroid Build Coastguard Worker }
793*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,MissingTypesInlineCachesMerge)794*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, MissingTypesInlineCachesMerge) {
795*795d594fSAndroid Build Coastguard Worker // Create an inline cache with missing types
796*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches;
797*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types = {};
798*795d594fSAndroid Build Coastguard Worker inline_caches.push_back(ProfileInlineCache(0, /*missing_types=*/ true, types));
799*795d594fSAndroid Build Coastguard Worker
800*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info_missing_types;
801*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info_missing_types, dex1, /*method_idx=*/ 0, inline_caches));
802*795d594fSAndroid Build Coastguard Worker
803*795d594fSAndroid Build Coastguard Worker // Create a profile with no inline caches (for the same method).
804*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info_no_inline_cache;
805*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info_no_inline_cache, dex1, /*method_idx=*/ 0));
806*795d594fSAndroid Build Coastguard Worker
807*795d594fSAndroid Build Coastguard Worker // Merge the missing type cache into the empty one.
808*795d594fSAndroid Build Coastguard Worker // Everything should be saved without errors.
809*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info_no_inline_cache.MergeWith(info_missing_types));
810*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
811*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info_no_inline_cache.Save(GetFd(profile)));
812*795d594fSAndroid Build Coastguard Worker }
813*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,SampledMethodsTest)814*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, SampledMethodsTest) {
815*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo test_info;
816*795d594fSAndroid Build Coastguard Worker AddMethod(&test_info, dex1, 1, Hotness::kFlagStartup);
817*795d594fSAndroid Build Coastguard Worker AddMethod(&test_info, dex1, 5, Hotness::kFlagPostStartup);
818*795d594fSAndroid Build Coastguard Worker AddMethod(&test_info, dex2, 2, Hotness::kFlagStartup);
819*795d594fSAndroid Build Coastguard Worker AddMethod(&test_info, dex2, 4, Hotness::kFlagPostStartup);
820*795d594fSAndroid Build Coastguard Worker auto run_test = [&dex1 = dex1, &dex2 = dex2](const ProfileCompilationInfo& info) {
821*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, 2)).IsInProfile());
822*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, 4)).IsInProfile());
823*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, 1)).IsStartup());
824*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, 3)).IsStartup());
825*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, 5)).IsPostStartup());
826*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, 6)).IsStartup());
827*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex2, 2)).IsStartup());
828*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex2, 4)).IsPostStartup());
829*795d594fSAndroid Build Coastguard Worker };
830*795d594fSAndroid Build Coastguard Worker run_test(test_info);
831*795d594fSAndroid Build Coastguard Worker
832*795d594fSAndroid Build Coastguard Worker // Save the profile.
833*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
834*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(test_info.Save(GetFd(profile)));
835*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
836*795d594fSAndroid Build Coastguard Worker
837*795d594fSAndroid Build Coastguard Worker // Load the profile and make sure we can read the data and it matches what we expect.
838*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
839*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
840*795d594fSAndroid Build Coastguard Worker run_test(loaded_info);
841*795d594fSAndroid Build Coastguard Worker
842*795d594fSAndroid Build Coastguard Worker // Test that the bitmap gets merged properly.
843*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(test_info.GetMethodHotness(MethodReference(dex1, 11)).IsStartup());
844*795d594fSAndroid Build Coastguard Worker {
845*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo merge_info;
846*795d594fSAndroid Build Coastguard Worker AddMethod(&merge_info, dex1, 11, Hotness::kFlagStartup);
847*795d594fSAndroid Build Coastguard Worker test_info.MergeWith(merge_info);
848*795d594fSAndroid Build Coastguard Worker }
849*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(test_info.GetMethodHotness(MethodReference(dex1, 11)).IsStartup());
850*795d594fSAndroid Build Coastguard Worker
851*795d594fSAndroid Build Coastguard Worker // Test bulk adding.
852*795d594fSAndroid Build Coastguard Worker {
853*795d594fSAndroid Build Coastguard Worker std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
854*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
855*795d594fSAndroid Build Coastguard Worker std::vector<uint16_t> hot_methods = {1, 3, 5};
856*795d594fSAndroid Build Coastguard Worker std::vector<uint16_t> startup_methods = {1, 2};
857*795d594fSAndroid Build Coastguard Worker std::vector<uint16_t> post_methods = {0, 2, 6};
858*795d594fSAndroid Build Coastguard Worker ASSERT_GE(dex->NumMethodIds(), 7u);
859*795d594fSAndroid Build Coastguard Worker info.AddMethodsForDex(static_cast<Hotness::Flag>(Hotness::kFlagHot | Hotness::kFlagStartup),
860*795d594fSAndroid Build Coastguard Worker dex.get(),
861*795d594fSAndroid Build Coastguard Worker hot_methods.begin(),
862*795d594fSAndroid Build Coastguard Worker hot_methods.end());
863*795d594fSAndroid Build Coastguard Worker info.AddMethodsForDex(Hotness::kFlagStartup,
864*795d594fSAndroid Build Coastguard Worker dex.get(),
865*795d594fSAndroid Build Coastguard Worker startup_methods.begin(),
866*795d594fSAndroid Build Coastguard Worker startup_methods.end());
867*795d594fSAndroid Build Coastguard Worker info.AddMethodsForDex(Hotness::kFlagPostStartup,
868*795d594fSAndroid Build Coastguard Worker dex.get(),
869*795d594fSAndroid Build Coastguard Worker post_methods.begin(),
870*795d594fSAndroid Build Coastguard Worker post_methods.end());
871*795d594fSAndroid Build Coastguard Worker for (uint16_t id : hot_methods) {
872*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsHot());
873*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsStartup());
874*795d594fSAndroid Build Coastguard Worker }
875*795d594fSAndroid Build Coastguard Worker for (uint16_t id : startup_methods) {
876*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsStartup());
877*795d594fSAndroid Build Coastguard Worker }
878*795d594fSAndroid Build Coastguard Worker for (uint16_t id : post_methods) {
879*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), id)).IsPostStartup());
880*795d594fSAndroid Build Coastguard Worker }
881*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), 6)).IsPostStartup());
882*795d594fSAndroid Build Coastguard Worker // Check that methods that shouldn't have been touched are OK.
883*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex.get(), 0)).IsInProfile());
884*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex.get(), 4)).IsInProfile());
885*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex.get(), 7)).IsInProfile());
886*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex.get(), 1)).IsPostStartup());
887*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex.get(), 4)).IsStartup());
888*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex.get(), 6)).IsStartup());
889*795d594fSAndroid Build Coastguard Worker }
890*795d594fSAndroid Build Coastguard Worker }
891*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,LoadFromZipCompress)892*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, LoadFromZipCompress) {
893*795d594fSAndroid Build Coastguard Worker TestProfileLoadFromZip("primary.prof",
894*795d594fSAndroid Build Coastguard Worker ZipWriter::kCompress | ZipWriter::kAlign32,
895*795d594fSAndroid Build Coastguard Worker /*should_succeed=*/true);
896*795d594fSAndroid Build Coastguard Worker }
897*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,LoadFromZipUnCompress)898*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, LoadFromZipUnCompress) {
899*795d594fSAndroid Build Coastguard Worker TestProfileLoadFromZip("primary.prof",
900*795d594fSAndroid Build Coastguard Worker ZipWriter::kAlign32,
901*795d594fSAndroid Build Coastguard Worker /*should_succeed=*/true);
902*795d594fSAndroid Build Coastguard Worker }
903*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,LoadFromZipUnAligned)904*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, LoadFromZipUnAligned) {
905*795d594fSAndroid Build Coastguard Worker TestProfileLoadFromZip("primary.prof",
906*795d594fSAndroid Build Coastguard Worker 0,
907*795d594fSAndroid Build Coastguard Worker /*should_succeed=*/true);
908*795d594fSAndroid Build Coastguard Worker }
909*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,LoadFromZipFailBadZipEntry)910*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, LoadFromZipFailBadZipEntry) {
911*795d594fSAndroid Build Coastguard Worker TestProfileLoadFromZip("invalid.profile.entry",
912*795d594fSAndroid Build Coastguard Worker 0,
913*795d594fSAndroid Build Coastguard Worker /*should_succeed=*/true,
914*795d594fSAndroid Build Coastguard Worker /*should_succeed_with_empty_profile=*/true);
915*795d594fSAndroid Build Coastguard Worker }
916*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,LoadFromZipFailBadProfile)917*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, LoadFromZipFailBadProfile) {
918*795d594fSAndroid Build Coastguard Worker // Create a bad profile.
919*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
920*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(
921*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::kProfileMagic, kProfileMagicSize));
922*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(
923*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::kProfileVersion, kProfileVersionSize));
924*795d594fSAndroid Build Coastguard Worker // Write that we have one section info.
925*795d594fSAndroid Build Coastguard Worker const uint32_t file_section_count = 1u;
926*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->WriteFully(&file_section_count, sizeof(file_section_count)));
927*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
928*795d594fSAndroid Build Coastguard Worker
929*795d594fSAndroid Build Coastguard Worker // Prepare the profile content for zipping.
930*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> data(profile.GetFile()->GetLength());
931*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile.GetFile()->PreadFully(data.data(), data.size(), /*offset=*/ 0));
932*795d594fSAndroid Build Coastguard Worker
933*795d594fSAndroid Build Coastguard Worker // Zip the profile content.
934*795d594fSAndroid Build Coastguard Worker ScratchFile zip;
935*795d594fSAndroid Build Coastguard Worker FILE* file = fopen(zip.GetFile()->GetPath().c_str(), "wbe");
936*795d594fSAndroid Build Coastguard Worker ZipWriter writer(file);
937*795d594fSAndroid Build Coastguard Worker writer.StartEntry("primary.prof", ZipWriter::kAlign32);
938*795d594fSAndroid Build Coastguard Worker writer.WriteBytes(data.data(), data.size());
939*795d594fSAndroid Build Coastguard Worker writer.FinishEntry();
940*795d594fSAndroid Build Coastguard Worker writer.Finish();
941*795d594fSAndroid Build Coastguard Worker fflush(file);
942*795d594fSAndroid Build Coastguard Worker fclose(file);
943*795d594fSAndroid Build Coastguard Worker
944*795d594fSAndroid Build Coastguard Worker // Check that we failed to load.
945*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
946*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(loaded_info.Load(GetFd(zip)));
947*795d594fSAndroid Build Coastguard Worker }
948*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,UpdateProfileKeyOk)949*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, UpdateProfileKeyOk) {
950*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files;
951*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex1_renamed));
952*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex2_renamed));
953*795d594fSAndroid Build Coastguard Worker
954*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
955*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex1, /*method_idx=*/ 0);
956*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex2, /*method_idx=*/ 0);
957*795d594fSAndroid Build Coastguard Worker
958*795d594fSAndroid Build Coastguard Worker // Update the profile keys based on the original dex files
959*795d594fSAndroid Build Coastguard Worker bool matched = false;
960*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.UpdateProfileKeys(dex_files, &matched));
961*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(matched);
962*795d594fSAndroid Build Coastguard Worker
963*795d594fSAndroid Build Coastguard Worker // Verify that we find the methods when searched with the original dex files.
964*795d594fSAndroid Build Coastguard Worker for (const std::unique_ptr<const DexFile>& dex : dex_files) {
965*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness =
966*795d594fSAndroid Build Coastguard Worker GetMethod(info, dex.get(), /*method_idx=*/ 0);
967*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness.IsHot());
968*795d594fSAndroid Build Coastguard Worker }
969*795d594fSAndroid Build Coastguard Worker
970*795d594fSAndroid Build Coastguard Worker // Release the ownership as this is held by the test class;
971*795d594fSAndroid Build Coastguard Worker for (std::unique_ptr<const DexFile>& dex : dex_files) {
972*795d594fSAndroid Build Coastguard Worker UNUSED(dex.release());
973*795d594fSAndroid Build Coastguard Worker }
974*795d594fSAndroid Build Coastguard Worker }
975*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,UpdateProfileKeyOkWithAnnotation)976*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, UpdateProfileKeyOkWithAnnotation) {
977*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files;
978*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex1_renamed));
979*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex2_renamed));
980*795d594fSAndroid Build Coastguard Worker
981*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
982*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::ProfileSampleAnnotation annotation("test.package");
983*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex1, /*method_idx=*/ 0, Hotness::kFlagHot, annotation);
984*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex2, /*method_idx=*/ 0, Hotness::kFlagHot, annotation);
985*795d594fSAndroid Build Coastguard Worker
986*795d594fSAndroid Build Coastguard Worker // Update the profile keys based on the original dex files
987*795d594fSAndroid Build Coastguard Worker bool matched = false;
988*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.UpdateProfileKeys(dex_files, &matched));
989*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(matched);
990*795d594fSAndroid Build Coastguard Worker
991*795d594fSAndroid Build Coastguard Worker // Verify that we find the methods when searched with the original dex files.
992*795d594fSAndroid Build Coastguard Worker for (const std::unique_ptr<const DexFile>& dex : dex_files) {
993*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness =
994*795d594fSAndroid Build Coastguard Worker GetMethod(info, dex.get(), /*method_idx=*/ 0, annotation);
995*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness.IsHot());
996*795d594fSAndroid Build Coastguard Worker }
997*795d594fSAndroid Build Coastguard Worker
998*795d594fSAndroid Build Coastguard Worker // Release the ownership as this is held by the test class;
999*795d594fSAndroid Build Coastguard Worker for (std::unique_ptr<const DexFile>& dex : dex_files) {
1000*795d594fSAndroid Build Coastguard Worker UNUSED(dex.release());
1001*795d594fSAndroid Build Coastguard Worker }
1002*795d594fSAndroid Build Coastguard Worker }
1003*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,UpdateProfileKeyOkMatchedButNoUpdate)1004*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, UpdateProfileKeyOkMatchedButNoUpdate) {
1005*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files;
1006*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex1));
1007*795d594fSAndroid Build Coastguard Worker
1008*795d594fSAndroid Build Coastguard Worker // Both the checksum and the location match the original dex file.
1009*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1010*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex1, /*method_idx=*/0);
1011*795d594fSAndroid Build Coastguard Worker
1012*795d594fSAndroid Build Coastguard Worker // No update should happen, but this should be considered as a happy case.
1013*795d594fSAndroid Build Coastguard Worker bool matched = false;
1014*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.UpdateProfileKeys(dex_files, &matched));
1015*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(matched);
1016*795d594fSAndroid Build Coastguard Worker
1017*795d594fSAndroid Build Coastguard Worker // Verify that we find the methods when searched with the original dex files.
1018*795d594fSAndroid Build Coastguard Worker for (const std::unique_ptr<const DexFile>& dex : dex_files) {
1019*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness =
1020*795d594fSAndroid Build Coastguard Worker GetMethod(info, dex.get(), /*method_idx=*/ 0);
1021*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness.IsHot());
1022*795d594fSAndroid Build Coastguard Worker }
1023*795d594fSAndroid Build Coastguard Worker
1024*795d594fSAndroid Build Coastguard Worker // Release the ownership as this is held by the test class;
1025*795d594fSAndroid Build Coastguard Worker for (std::unique_ptr<const DexFile>& dex : dex_files) {
1026*795d594fSAndroid Build Coastguard Worker UNUSED(dex.release());
1027*795d594fSAndroid Build Coastguard Worker }
1028*795d594fSAndroid Build Coastguard Worker }
1029*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,UpdateProfileKeyOkButNoMatch)1030*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, UpdateProfileKeyOkButNoMatch) {
1031*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files;
1032*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex1_renamed));
1033*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex2_renamed));
1034*795d594fSAndroid Build Coastguard Worker
1035*795d594fSAndroid Build Coastguard Worker // This is a partial match: `dex1` matches `dex1_renamed`, but `dex3` matches nothing. It should
1036*795d594fSAndroid Build Coastguard Worker // be treated as a match failure.
1037*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1038*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex1, /*method_idx=*/0);
1039*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex3, /*method_idx=*/0);
1040*795d594fSAndroid Build Coastguard Worker
1041*795d594fSAndroid Build Coastguard Worker // Update the profile keys based on the original dex files.
1042*795d594fSAndroid Build Coastguard Worker bool matched = false;
1043*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.UpdateProfileKeys(dex_files, &matched));
1044*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(matched);
1045*795d594fSAndroid Build Coastguard Worker
1046*795d594fSAndroid Build Coastguard Worker // Verify that the unmatched entry is kept.
1047*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness = GetMethod(info, dex3, /*method_idx=*/0);
1048*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness.IsHot());
1049*795d594fSAndroid Build Coastguard Worker
1050*795d594fSAndroid Build Coastguard Worker // Verify that we can find the updated entry.
1051*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness_2 =
1052*795d594fSAndroid Build Coastguard Worker GetMethod(info, dex1_renamed, /*method_idx=*/0);
1053*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness_2.IsHot());
1054*795d594fSAndroid Build Coastguard Worker
1055*795d594fSAndroid Build Coastguard Worker // Release the ownership as this is held by the test class;
1056*795d594fSAndroid Build Coastguard Worker for (std::unique_ptr<const DexFile>& dex : dex_files) {
1057*795d594fSAndroid Build Coastguard Worker UNUSED(dex.release());
1058*795d594fSAndroid Build Coastguard Worker }
1059*795d594fSAndroid Build Coastguard Worker }
1060*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,UpdateProfileKeyOkButEmpty)1061*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, UpdateProfileKeyOkButEmpty) {
1062*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files;
1063*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex1_renamed));
1064*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex2_renamed));
1065*795d594fSAndroid Build Coastguard Worker
1066*795d594fSAndroid Build Coastguard Worker // Empty profile.
1067*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1068*795d594fSAndroid Build Coastguard Worker
1069*795d594fSAndroid Build Coastguard Worker // Update the profile keys based on the original dex files.
1070*795d594fSAndroid Build Coastguard Worker bool matched = false;
1071*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.UpdateProfileKeys(dex_files, &matched));
1072*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(matched);
1073*795d594fSAndroid Build Coastguard Worker
1074*795d594fSAndroid Build Coastguard Worker // Verify that the updated profile is still empty.
1075*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.IsEmpty());
1076*795d594fSAndroid Build Coastguard Worker
1077*795d594fSAndroid Build Coastguard Worker // Release the ownership as this is held by the test class;
1078*795d594fSAndroid Build Coastguard Worker for (std::unique_ptr<const DexFile>& dex : dex_files) {
1079*795d594fSAndroid Build Coastguard Worker UNUSED(dex.release());
1080*795d594fSAndroid Build Coastguard Worker }
1081*795d594fSAndroid Build Coastguard Worker }
1082*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,UpdateProfileKeyFail)1083*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, UpdateProfileKeyFail) {
1084*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files;
1085*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex1_renamed));
1086*795d594fSAndroid Build Coastguard Worker
1087*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1088*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex1, /*method_idx=*/ 0);
1089*795d594fSAndroid Build Coastguard Worker
1090*795d594fSAndroid Build Coastguard Worker // Add a method index using the location we want to rename to.
1091*795d594fSAndroid Build Coastguard Worker // This will cause the rename to fail because an existing entry would already have that name.
1092*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex1_renamed, /*method_idx=*/ 0);
1093*795d594fSAndroid Build Coastguard Worker
1094*795d594fSAndroid Build Coastguard Worker bool matched = false;
1095*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(info.UpdateProfileKeys(dex_files, &matched));
1096*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(matched);
1097*795d594fSAndroid Build Coastguard Worker
1098*795d594fSAndroid Build Coastguard Worker // Release the ownership as this is held by the test class;
1099*795d594fSAndroid Build Coastguard Worker for (std::unique_ptr<const DexFile>& dex : dex_files) {
1100*795d594fSAndroid Build Coastguard Worker UNUSED(dex.release());
1101*795d594fSAndroid Build Coastguard Worker }
1102*795d594fSAndroid Build Coastguard Worker }
1103*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,FilteredLoading)1104*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, FilteredLoading) {
1105*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
1106*795d594fSAndroid Build Coastguard Worker
1107*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info;
1108*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches = GetTestInlineCaches();
1109*795d594fSAndroid Build Coastguard Worker
1110*795d594fSAndroid Build Coastguard Worker // Add methods with inline caches.
1111*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
1112*795d594fSAndroid Build Coastguard Worker // Add a method which is part of the same dex file as one of the class from the inline caches.
1113*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex1, method_idx, inline_caches));
1114*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex2, method_idx, inline_caches));
1115*795d594fSAndroid Build Coastguard Worker // Add a method which is outside the set of dex files.
1116*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex4, method_idx, inline_caches));
1117*795d594fSAndroid Build Coastguard Worker }
1118*795d594fSAndroid Build Coastguard Worker
1119*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
1120*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
1121*795d594fSAndroid Build Coastguard Worker
1122*795d594fSAndroid Build Coastguard Worker // Check that we get back what we saved.
1123*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
1124*795d594fSAndroid Build Coastguard Worker
1125*795d594fSAndroid Build Coastguard Worker // Filter out dex locations. Keep only dex_location1 and dex_location3.
1126*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::ProfileLoadFilterFn filter_fn =
1127*795d594fSAndroid Build Coastguard Worker [&dex1 = dex1, &dex3 = dex3](const std::string& dex_location, uint32_t checksum) -> bool {
1128*795d594fSAndroid Build Coastguard Worker return (dex_location == dex1->GetLocation() && checksum == dex1->GetLocationChecksum())
1129*795d594fSAndroid Build Coastguard Worker || (dex_location == dex3->GetLocation() && checksum == dex3->GetLocationChecksum());
1130*795d594fSAndroid Build Coastguard Worker };
1131*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile), true, filter_fn));
1132*795d594fSAndroid Build Coastguard Worker
1133*795d594fSAndroid Build Coastguard Worker // Verify that we filtered out locations during load.
1134*795d594fSAndroid Build Coastguard Worker // Note that `dex3` did not have any data recorded in the profile.
1135*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(1u, loaded_info.GetNumberOfDexFiles());
1136*795d594fSAndroid Build Coastguard Worker
1137*795d594fSAndroid Build Coastguard Worker // Dex location 2 and 4 should have been filtered out
1138*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
1139*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(GetMethod(loaded_info, dex2, method_idx).IsHot());
1140*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(GetMethod(loaded_info, dex4, method_idx).IsHot());
1141*795d594fSAndroid Build Coastguard Worker }
1142*795d594fSAndroid Build Coastguard Worker
1143*795d594fSAndroid Build Coastguard Worker // Dex location 1 should have all all the inline caches referencing dex location 2 set to
1144*795d594fSAndroid Build Coastguard Worker // missing types.
1145*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
1146*795d594fSAndroid Build Coastguard Worker // The methods for dex location 1 should be in the profile data.
1147*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness1 =
1148*795d594fSAndroid Build Coastguard Worker GetMethod(loaded_info, dex1, method_idx);
1149*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness1.IsHot());
1150*795d594fSAndroid Build Coastguard Worker
1151*795d594fSAndroid Build Coastguard Worker // Verify the inline cache. Note that references to other dex files are translated
1152*795d594fSAndroid Build Coastguard Worker // to use type indexes within the referencing dex file and artificial type indexes
1153*795d594fSAndroid Build Coastguard Worker // referencing "extra descriptors" are used when there is no `dex::TypeId` for
1154*795d594fSAndroid Build Coastguard Worker // these types. `EqualInlineCaches()` compares descriptors when necessary.
1155*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(EqualInlineCaches(inline_caches, dex1, loaded_hotness1, loaded_info));
1156*795d594fSAndroid Build Coastguard Worker }
1157*795d594fSAndroid Build Coastguard Worker }
1158*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,FilteredLoadingRemoveAll)1159*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, FilteredLoadingRemoveAll) {
1160*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
1161*795d594fSAndroid Build Coastguard Worker
1162*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info;
1163*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches = GetTestInlineCaches();
1164*795d594fSAndroid Build Coastguard Worker
1165*795d594fSAndroid Build Coastguard Worker // Add methods with inline caches.
1166*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
1167*795d594fSAndroid Build Coastguard Worker // Add a method which is part of the same dex file as one of the class from the inline caches.
1168*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex1, method_idx, inline_caches));
1169*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex2, method_idx, inline_caches));
1170*795d594fSAndroid Build Coastguard Worker // Add a method which is outside the set of dex files.
1171*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex4, method_idx, inline_caches));
1172*795d594fSAndroid Build Coastguard Worker }
1173*795d594fSAndroid Build Coastguard Worker
1174*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
1175*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
1176*795d594fSAndroid Build Coastguard Worker
1177*795d594fSAndroid Build Coastguard Worker // Check that we get back what we saved.
1178*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
1179*795d594fSAndroid Build Coastguard Worker
1180*795d594fSAndroid Build Coastguard Worker // Remove all elements.
1181*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::ProfileLoadFilterFn filter_fn =
1182*795d594fSAndroid Build Coastguard Worker [](const std::string&, uint32_t) -> bool { return false; };
1183*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile), true, filter_fn));
1184*795d594fSAndroid Build Coastguard Worker
1185*795d594fSAndroid Build Coastguard Worker // Verify that we filtered out everything.
1186*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(IsEmpty(loaded_info));
1187*795d594fSAndroid Build Coastguard Worker }
1188*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,FilteredLoadingKeepAll)1189*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, FilteredLoadingKeepAll) {
1190*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
1191*795d594fSAndroid Build Coastguard Worker
1192*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info;
1193*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches = GetTestInlineCaches();
1194*795d594fSAndroid Build Coastguard Worker
1195*795d594fSAndroid Build Coastguard Worker // Add methods with inline caches.
1196*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
1197*795d594fSAndroid Build Coastguard Worker // Add a method which is part of the same dex file as one of the
1198*795d594fSAndroid Build Coastguard Worker // class from the inline caches.
1199*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex1, method_idx, inline_caches));
1200*795d594fSAndroid Build Coastguard Worker // Add a method which is outside the set of dex files.
1201*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&saved_info, dex4, method_idx, inline_caches));
1202*795d594fSAndroid Build Coastguard Worker }
1203*795d594fSAndroid Build Coastguard Worker
1204*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
1205*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
1206*795d594fSAndroid Build Coastguard Worker
1207*795d594fSAndroid Build Coastguard Worker // Check that we get back what we saved.
1208*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
1209*795d594fSAndroid Build Coastguard Worker
1210*795d594fSAndroid Build Coastguard Worker // Keep all elements.
1211*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::ProfileLoadFilterFn filter_fn =
1212*795d594fSAndroid Build Coastguard Worker [](const std::string&, uint32_t) -> bool { return true; };
1213*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile), true, filter_fn));
1214*795d594fSAndroid Build Coastguard Worker
1215*795d594fSAndroid Build Coastguard Worker
1216*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(saved_info));
1217*795d594fSAndroid Build Coastguard Worker
1218*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
1219*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness1 =
1220*795d594fSAndroid Build Coastguard Worker GetMethod(loaded_info, dex1, method_idx);
1221*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness1.IsHot());
1222*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(EqualInlineCaches(inline_caches, dex1, loaded_hotness1, loaded_info));
1223*795d594fSAndroid Build Coastguard Worker }
1224*795d594fSAndroid Build Coastguard Worker for (uint16_t method_idx = 0; method_idx < 10; method_idx++) {
1225*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_hotness2 =
1226*795d594fSAndroid Build Coastguard Worker GetMethod(loaded_info, dex4, method_idx);
1227*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_hotness2.IsHot());
1228*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(EqualInlineCaches(inline_caches, dex4, loaded_hotness2, loaded_info));
1229*795d594fSAndroid Build Coastguard Worker }
1230*795d594fSAndroid Build Coastguard Worker }
1231*795d594fSAndroid Build Coastguard Worker
1232*795d594fSAndroid Build Coastguard Worker // Regression test: we were failing to do a filtering loading when the filtered dex file
1233*795d594fSAndroid Build Coastguard Worker // contained profiled classes.
TEST_F(ProfileCompilationInfoTest,FilteredLoadingWithClasses)1234*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, FilteredLoadingWithClasses) {
1235*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
1236*795d594fSAndroid Build Coastguard Worker
1237*795d594fSAndroid Build Coastguard Worker const DexFile* dex1_1000 = BuildDex("location1_1000",
1238*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 7,
1239*795d594fSAndroid Build Coastguard Worker "LC1_1000;",
1240*795d594fSAndroid Build Coastguard Worker /*num_method_ids=*/ 1u,
1241*795d594fSAndroid Build Coastguard Worker /*num_class_ids=*/ 1000u);
1242*795d594fSAndroid Build Coastguard Worker const DexFile* dex2_1000 = BuildDex("location2_1000",
1243*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 8,
1244*795d594fSAndroid Build Coastguard Worker "LC2_1000;",
1245*795d594fSAndroid Build Coastguard Worker /*num_method_ids=*/ 1u,
1246*795d594fSAndroid Build Coastguard Worker /*num_class_ids=*/ 1000u);
1247*795d594fSAndroid Build Coastguard Worker
1248*795d594fSAndroid Build Coastguard Worker // Save a profile with 2 dex files containing just classes.
1249*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo saved_info;
1250*795d594fSAndroid Build Coastguard Worker uint16_t item_count = 1000;
1251*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < item_count; i++) {
1252*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&saved_info, dex1_1000, dex::TypeIndex(i)));
1253*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&saved_info, dex2_1000, dex::TypeIndex(i)));
1254*795d594fSAndroid Build Coastguard Worker }
1255*795d594fSAndroid Build Coastguard Worker
1256*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(saved_info.Save(GetFd(profile)));
1257*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
1258*795d594fSAndroid Build Coastguard Worker
1259*795d594fSAndroid Build Coastguard Worker
1260*795d594fSAndroid Build Coastguard Worker // Filter out dex locations: keep only `dex2_1000->GetLocation()`.
1261*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
1262*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::ProfileLoadFilterFn filter_fn =
1263*795d594fSAndroid Build Coastguard Worker [dex2_1000](const std::string& dex_location, uint32_t checksum) -> bool {
1264*795d594fSAndroid Build Coastguard Worker return dex_location == dex2_1000->GetLocation() &&
1265*795d594fSAndroid Build Coastguard Worker checksum == dex2_1000->GetLocationChecksum();
1266*795d594fSAndroid Build Coastguard Worker };
1267*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile), true, filter_fn));
1268*795d594fSAndroid Build Coastguard Worker
1269*795d594fSAndroid Build Coastguard Worker // Compute the expectation.
1270*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo expected_info;
1271*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < item_count; i++) {
1272*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&expected_info, dex2_1000, dex::TypeIndex(i)));
1273*795d594fSAndroid Build Coastguard Worker }
1274*795d594fSAndroid Build Coastguard Worker
1275*795d594fSAndroid Build Coastguard Worker // Validate the expectation.
1276*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(expected_info));
1277*795d594fSAndroid Build Coastguard Worker }
1278*795d594fSAndroid Build Coastguard Worker
1279*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,ClearData)1280*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, ClearData) {
1281*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1282*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1283*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i));
1284*795d594fSAndroid Build Coastguard Worker }
1285*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(IsEmpty(info));
1286*795d594fSAndroid Build Coastguard Worker info.ClearData();
1287*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(IsEmpty(info));
1288*795d594fSAndroid Build Coastguard Worker }
1289*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,ClearDataAndSave)1290*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, ClearDataAndSave) {
1291*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1292*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1293*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i));
1294*795d594fSAndroid Build Coastguard Worker }
1295*795d594fSAndroid Build Coastguard Worker info.ClearData();
1296*795d594fSAndroid Build Coastguard Worker
1297*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
1298*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Save(GetFd(profile)));
1299*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
1300*795d594fSAndroid Build Coastguard Worker
1301*795d594fSAndroid Build Coastguard Worker // Check that we get back what we saved.
1302*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
1303*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
1304*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(info));
1305*795d594fSAndroid Build Coastguard Worker }
1306*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,InitProfiles)1307*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, InitProfiles) {
1308*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1309*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(
1310*795d594fSAndroid Build Coastguard Worker memcmp(info.GetVersion(),
1311*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::kProfileVersion,
1312*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::kProfileVersionSize),
1313*795d594fSAndroid Build Coastguard Worker 0);
1314*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(info.IsForBootImage());
1315*795d594fSAndroid Build Coastguard Worker
1316*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1(/*for_boot_image=*/ true);
1317*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(
1318*795d594fSAndroid Build Coastguard Worker memcmp(info1.GetVersion(),
1319*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::kProfileVersionForBootImage,
1320*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::kProfileVersionSize),
1321*795d594fSAndroid Build Coastguard Worker 0);
1322*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info1.IsForBootImage());
1323*795d594fSAndroid Build Coastguard Worker }
1324*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,VersionEquality)1325*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, VersionEquality) {
1326*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info(/*for_boot_image=*/ false);
1327*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1(/*for_boot_image=*/ true);
1328*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(info.Equals(info1));
1329*795d594fSAndroid Build Coastguard Worker }
1330*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,AllMethodFlags)1331*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, AllMethodFlags) {
1332*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info(/*for_boot_image=*/ true);
1333*795d594fSAndroid Build Coastguard Worker
1334*795d594fSAndroid Build Coastguard Worker for (uint32_t index = 0; index <= kMaxHotnessFlagBootIndex; index++) {
1335*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex1, index, static_cast<Hotness::Flag>(1 << index));
1336*795d594fSAndroid Build Coastguard Worker }
1337*795d594fSAndroid Build Coastguard Worker
1338*795d594fSAndroid Build Coastguard Worker auto run_test = [&dex1 = dex1](const ProfileCompilationInfo& info) {
1339*795d594fSAndroid Build Coastguard Worker for (uint32_t index = 0; index <= kMaxHotnessFlagBootIndex; index++) {
1340*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, index)).IsInProfile());
1341*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, index))
1342*795d594fSAndroid Build Coastguard Worker .HasFlagSet(static_cast<Hotness::Flag>(1 << index))) << index << " "
1343*795d594fSAndroid Build Coastguard Worker << info.GetMethodHotness(MethodReference(dex1, index)).GetFlags();
1344*795d594fSAndroid Build Coastguard Worker }
1345*795d594fSAndroid Build Coastguard Worker };
1346*795d594fSAndroid Build Coastguard Worker run_test(info);
1347*795d594fSAndroid Build Coastguard Worker
1348*795d594fSAndroid Build Coastguard Worker // Save the profile.
1349*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
1350*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Save(GetFd(profile)));
1351*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
1352*795d594fSAndroid Build Coastguard Worker
1353*795d594fSAndroid Build Coastguard Worker // Load the profile and make sure we can read the data and it matches what we expect.
1354*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info(/*for_boot_image=*/ true);
1355*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
1356*795d594fSAndroid Build Coastguard Worker run_test(loaded_info);
1357*795d594fSAndroid Build Coastguard Worker }
1358*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,AllMethodFlagsOnOneMethod)1359*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, AllMethodFlagsOnOneMethod) {
1360*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info(/*for_boot_image=*/ true);
1361*795d594fSAndroid Build Coastguard Worker
1362*795d594fSAndroid Build Coastguard Worker // Set all flags on a single method.
1363*795d594fSAndroid Build Coastguard Worker for (uint32_t index = 0; index <= kMaxHotnessFlagBootIndex; index++) {
1364*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex1, 0, static_cast<Hotness::Flag>(1 << index));
1365*795d594fSAndroid Build Coastguard Worker }
1366*795d594fSAndroid Build Coastguard Worker
1367*795d594fSAndroid Build Coastguard Worker auto run_test = [&dex1 = dex1](const ProfileCompilationInfo& info) {
1368*795d594fSAndroid Build Coastguard Worker for (uint32_t index = 0; index <= kMaxHotnessFlagBootIndex; index++) {
1369*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, 0)).IsInProfile());
1370*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, 0))
1371*795d594fSAndroid Build Coastguard Worker .HasFlagSet(static_cast<Hotness::Flag>(1 << index)));
1372*795d594fSAndroid Build Coastguard Worker }
1373*795d594fSAndroid Build Coastguard Worker };
1374*795d594fSAndroid Build Coastguard Worker run_test(info);
1375*795d594fSAndroid Build Coastguard Worker
1376*795d594fSAndroid Build Coastguard Worker // Save the profile.
1377*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
1378*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Save(GetFd(profile)));
1379*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
1380*795d594fSAndroid Build Coastguard Worker
1381*795d594fSAndroid Build Coastguard Worker // Load the profile and make sure we can read the data and it matches what we expect.
1382*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info(/*for_boot_image=*/ true);
1383*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
1384*795d594fSAndroid Build Coastguard Worker run_test(loaded_info);
1385*795d594fSAndroid Build Coastguard Worker }
1386*795d594fSAndroid Build Coastguard Worker
1387*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,MethodFlagsMerge)1388*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, MethodFlagsMerge) {
1389*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1(/*for_boot_image=*/ true);
1390*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2(/*for_boot_image=*/ true);
1391*795d594fSAndroid Build Coastguard Worker
1392*795d594fSAndroid Build Coastguard Worker // Set a few flags on a 2 different methods in each of the profile.
1393*795d594fSAndroid Build Coastguard Worker for (uint32_t index = 0; index <= kMaxHotnessFlagBootIndex / 4; index++) {
1394*795d594fSAndroid Build Coastguard Worker AddMethod(&info1, dex1, 0, static_cast<Hotness::Flag>(1 << index));
1395*795d594fSAndroid Build Coastguard Worker AddMethod(&info2, dex1, 1, static_cast<Hotness::Flag>(1 << index));
1396*795d594fSAndroid Build Coastguard Worker }
1397*795d594fSAndroid Build Coastguard Worker
1398*795d594fSAndroid Build Coastguard Worker // Set a few more flags on the method 1.
1399*795d594fSAndroid Build Coastguard Worker for (uint32_t index = kMaxHotnessFlagBootIndex / 4 + 1;
1400*795d594fSAndroid Build Coastguard Worker index <= kMaxHotnessFlagBootIndex / 2;
1401*795d594fSAndroid Build Coastguard Worker index++) {
1402*795d594fSAndroid Build Coastguard Worker AddMethod(&info2, dex1, 1, static_cast<Hotness::Flag>(1 << index));
1403*795d594fSAndroid Build Coastguard Worker }
1404*795d594fSAndroid Build Coastguard Worker
1405*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info1.MergeWith(info2));
1406*795d594fSAndroid Build Coastguard Worker
1407*795d594fSAndroid Build Coastguard Worker auto run_test = [&dex1 = dex1](const ProfileCompilationInfo& info) {
1408*795d594fSAndroid Build Coastguard Worker // Assert that the flags were merged correctly for both methods.
1409*795d594fSAndroid Build Coastguard Worker for (uint32_t index = 0; index <= kMaxHotnessFlagBootIndex / 4; index++) {
1410*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, 0)).IsInProfile());
1411*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, 0))
1412*795d594fSAndroid Build Coastguard Worker .HasFlagSet(static_cast<Hotness::Flag>(1 << index)));
1413*795d594fSAndroid Build Coastguard Worker
1414*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, 1)).IsInProfile());
1415*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, 1))
1416*795d594fSAndroid Build Coastguard Worker .HasFlagSet(static_cast<Hotness::Flag>(1 << index)));
1417*795d594fSAndroid Build Coastguard Worker }
1418*795d594fSAndroid Build Coastguard Worker
1419*795d594fSAndroid Build Coastguard Worker // Assert that no flags were merged unnecessary.
1420*795d594fSAndroid Build Coastguard Worker for (uint32_t index = kMaxHotnessFlagBootIndex / 4 + 1;
1421*795d594fSAndroid Build Coastguard Worker index <= kMaxHotnessFlagBootIndex / 2;
1422*795d594fSAndroid Build Coastguard Worker index++) {
1423*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, 0)).IsInProfile());
1424*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, 0))
1425*795d594fSAndroid Build Coastguard Worker .HasFlagSet(static_cast<Hotness::Flag>(1 << index)));
1426*795d594fSAndroid Build Coastguard Worker
1427*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, 1)).IsInProfile());
1428*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, 1))
1429*795d594fSAndroid Build Coastguard Worker .HasFlagSet(static_cast<Hotness::Flag>(1 << index)));
1430*795d594fSAndroid Build Coastguard Worker }
1431*795d594fSAndroid Build Coastguard Worker
1432*795d594fSAndroid Build Coastguard Worker // Assert that no extra flags were added.
1433*795d594fSAndroid Build Coastguard Worker for (uint32_t index = kMaxHotnessFlagBootIndex / 2 + 1;
1434*795d594fSAndroid Build Coastguard Worker index <= kMaxHotnessFlagBootIndex;
1435*795d594fSAndroid Build Coastguard Worker index++) {
1436*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, 0))
1437*795d594fSAndroid Build Coastguard Worker .HasFlagSet(static_cast<Hotness::Flag>(1 << index)));
1438*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, 1))
1439*795d594fSAndroid Build Coastguard Worker .HasFlagSet(static_cast<Hotness::Flag>(1 << index)));
1440*795d594fSAndroid Build Coastguard Worker }
1441*795d594fSAndroid Build Coastguard Worker };
1442*795d594fSAndroid Build Coastguard Worker
1443*795d594fSAndroid Build Coastguard Worker run_test(info1);
1444*795d594fSAndroid Build Coastguard Worker
1445*795d594fSAndroid Build Coastguard Worker // Save the profile.
1446*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
1447*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info1.Save(GetFd(profile)));
1448*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
1449*795d594fSAndroid Build Coastguard Worker
1450*795d594fSAndroid Build Coastguard Worker // Load the profile and make sure we can read the data and it matches what we expect.
1451*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info(/*for_boot_image=*/ true);
1452*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
1453*795d594fSAndroid Build Coastguard Worker run_test(loaded_info);
1454*795d594fSAndroid Build Coastguard Worker }
1455*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,SizeStressTestAllIn)1456*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, SizeStressTestAllIn) {
1457*795d594fSAndroid Build Coastguard Worker SizeStressTest(/*random=*/ false);
1458*795d594fSAndroid Build Coastguard Worker }
1459*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,SizeStressTestAllInRandom)1460*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, SizeStressTestAllInRandom) {
1461*795d594fSAndroid Build Coastguard Worker SizeStressTest(/*random=*/ true);
1462*795d594fSAndroid Build Coastguard Worker }
1463*795d594fSAndroid Build Coastguard Worker
1464*795d594fSAndroid Build Coastguard Worker // Verifies that we correctly add methods to the profile according to their flags.
TEST_F(ProfileCompilationInfoTest,AddMethodsProfileMethodInfoBasic)1465*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, AddMethodsProfileMethodInfoBasic) {
1466*795d594fSAndroid Build Coastguard Worker std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1467*795d594fSAndroid Build Coastguard Worker
1468*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1469*795d594fSAndroid Build Coastguard Worker
1470*795d594fSAndroid Build Coastguard Worker MethodReference hot(dex.get(), 0);
1471*795d594fSAndroid Build Coastguard Worker MethodReference hot_startup(dex.get(), 1);
1472*795d594fSAndroid Build Coastguard Worker MethodReference startup(dex.get(), 2);
1473*795d594fSAndroid Build Coastguard Worker
1474*795d594fSAndroid Build Coastguard Worker // Add methods
1475*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.AddMethod(ProfileMethodInfo(hot), Hotness::kFlagHot));
1476*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.AddMethod(
1477*795d594fSAndroid Build Coastguard Worker ProfileMethodInfo(hot_startup),
1478*795d594fSAndroid Build Coastguard Worker static_cast<Hotness::Flag>(Hotness::kFlagHot | Hotness::kFlagStartup)));
1479*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.AddMethod(ProfileMethodInfo(startup), Hotness::kFlagStartup));
1480*795d594fSAndroid Build Coastguard Worker
1481*795d594fSAndroid Build Coastguard Worker // Verify the profile recorded them correctly.
1482*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(hot).IsInProfile());
1483*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(info.GetMethodHotness(hot).GetFlags(), Hotness::kFlagHot);
1484*795d594fSAndroid Build Coastguard Worker
1485*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(hot_startup).IsInProfile());
1486*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(info.GetMethodHotness(hot_startup).GetFlags(),
1487*795d594fSAndroid Build Coastguard Worker static_cast<uint32_t>(Hotness::kFlagHot | Hotness::kFlagStartup));
1488*795d594fSAndroid Build Coastguard Worker
1489*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(startup).IsInProfile());
1490*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(info.GetMethodHotness(startup).GetFlags(), Hotness::kFlagStartup);
1491*795d594fSAndroid Build Coastguard Worker }
1492*795d594fSAndroid Build Coastguard Worker
1493*795d594fSAndroid Build Coastguard Worker // Verifies that we correctly add inline caches to the profile only for hot methods.
TEST_F(ProfileCompilationInfoTest,AddMethodsProfileMethodInfoInlineCaches)1494*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, AddMethodsProfileMethodInfoInlineCaches) {
1495*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1496*795d594fSAndroid Build Coastguard Worker MethodReference hot(dex1, 0);
1497*795d594fSAndroid Build Coastguard Worker MethodReference startup(dex1, 2);
1498*795d594fSAndroid Build Coastguard Worker
1499*795d594fSAndroid Build Coastguard Worker // Add inline caches with the methods. The profile should record only the one for the hot method.
1500*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types = {};
1501*795d594fSAndroid Build Coastguard Worker ProfileMethodInfo::ProfileInlineCache ic(/*pc=*/0, /*missing_types=*/true, types);
1502*795d594fSAndroid Build Coastguard Worker std::vector<ProfileMethodInfo::ProfileInlineCache> inline_caches = {ic};
1503*795d594fSAndroid Build Coastguard Worker info.AddMethod(ProfileMethodInfo(hot, inline_caches),
1504*795d594fSAndroid Build Coastguard Worker Hotness::kFlagHot,
1505*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation::kNone,
1506*795d594fSAndroid Build Coastguard Worker /*is_test=*/ true);
1507*795d594fSAndroid Build Coastguard Worker info.AddMethod(ProfileMethodInfo(startup, inline_caches),
1508*795d594fSAndroid Build Coastguard Worker Hotness::kFlagStartup,
1509*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation::kNone,
1510*795d594fSAndroid Build Coastguard Worker /*is_test=*/ true);
1511*795d594fSAndroid Build Coastguard Worker
1512*795d594fSAndroid Build Coastguard Worker // Check the hot method's inline cache.
1513*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness hot_hotness = GetMethod(info, dex1, hot.index);
1514*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(hot_hotness.IsHot());
1515*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(hot_hotness.GetInlineCacheMap()->size(), 1u);
1516*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(hot_hotness.GetInlineCacheMap()->Get(0).is_missing_types);
1517*795d594fSAndroid Build Coastguard Worker
1518*795d594fSAndroid Build Coastguard Worker // Check there's no inline caches for the startup method.
1519*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(GetMethod(info, dex1, startup.index).IsHot());
1520*795d594fSAndroid Build Coastguard Worker }
1521*795d594fSAndroid Build Coastguard Worker
1522*795d594fSAndroid Build Coastguard Worker // Verifies that we correctly add methods to the profile according to their flags.
TEST_F(ProfileCompilationInfoTest,AddMethodsProfileMethodInfoFail)1523*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, AddMethodsProfileMethodInfoFail) {
1524*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1525*795d594fSAndroid Build Coastguard Worker
1526*795d594fSAndroid Build Coastguard Worker MethodReference hot(dex1, 0);
1527*795d594fSAndroid Build Coastguard Worker MethodReference bad_ref(dex1, kMaxMethodIds);
1528*795d594fSAndroid Build Coastguard Worker
1529*795d594fSAndroid Build Coastguard Worker std::vector<ProfileMethodInfo> pmis = {ProfileMethodInfo(hot), ProfileMethodInfo(bad_ref)};
1530*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(info.AddMethods(pmis, Hotness::kFlagHot));
1531*795d594fSAndroid Build Coastguard Worker }
1532*795d594fSAndroid Build Coastguard Worker
1533*795d594fSAndroid Build Coastguard Worker // Verify that we can add methods with annotations.
TEST_F(ProfileCompilationInfoTest,AddAnnotationsToMethods)1534*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, AddAnnotationsToMethods) {
1535*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1536*795d594fSAndroid Build Coastguard Worker
1537*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa1("test1");
1538*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa2("test2");
1539*795d594fSAndroid Build Coastguard Worker // Save a few methods using different annotations, some overlapping, some not.
1540*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1541*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa1));
1542*795d594fSAndroid Build Coastguard Worker }
1543*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 5; i < 15; i++) {
1544*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa2));
1545*795d594fSAndroid Build Coastguard Worker }
1546*795d594fSAndroid Build Coastguard Worker
1547*795d594fSAndroid Build Coastguard Worker auto run_test = [&dex1 = dex1, &psa1 = psa1, &psa2 = psa2](const ProfileCompilationInfo& info) {
1548*795d594fSAndroid Build Coastguard Worker // Check that all methods are in.
1549*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1550*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i), psa1).IsInProfile());
1551*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i), psa1).IsHot());
1552*795d594fSAndroid Build Coastguard Worker }
1553*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 5; i < 15; i++) {
1554*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i), psa2).IsInProfile());
1555*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i), psa2).IsHot());
1556*795d594fSAndroid Build Coastguard Worker }
1557*795d594fSAndroid Build Coastguard Worker // Check that the non-overlapping methods are not added with a wrong annotation.
1558*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 10; i < 15; i++) {
1559*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i), psa1).IsInProfile());
1560*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i), psa1).IsHot());
1561*795d594fSAndroid Build Coastguard Worker }
1562*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 5; i++) {
1563*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i), psa2).IsInProfile());
1564*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i), psa2).IsHot());
1565*795d594fSAndroid Build Coastguard Worker }
1566*795d594fSAndroid Build Coastguard Worker // Check that when querying without an annotation only the first one is searched.
1567*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1568*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i)).IsInProfile());
1569*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i)).IsHot());
1570*795d594fSAndroid Build Coastguard Worker }
1571*795d594fSAndroid Build Coastguard Worker // ... this should be false because they belong the second appearance of dex1.
1572*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 10; i < 15; i++) {
1573*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i)).IsInProfile());
1574*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i)).IsHot());
1575*795d594fSAndroid Build Coastguard Worker }
1576*795d594fSAndroid Build Coastguard Worker
1577*795d594fSAndroid Build Coastguard Worker // Check that the methods cannot be found with a non existing annotation.
1578*795d594fSAndroid Build Coastguard Worker MethodReference ref(dex1, 0);
1579*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation not_existing("A");
1580*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(ref, not_existing).IsInProfile());
1581*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(ref, not_existing).IsHot());
1582*795d594fSAndroid Build Coastguard Worker };
1583*795d594fSAndroid Build Coastguard Worker
1584*795d594fSAndroid Build Coastguard Worker // Run the test before save.
1585*795d594fSAndroid Build Coastguard Worker run_test(info);
1586*795d594fSAndroid Build Coastguard Worker
1587*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
1588*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Save(GetFd(profile)));
1589*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
1590*795d594fSAndroid Build Coastguard Worker
1591*795d594fSAndroid Build Coastguard Worker // Check that we get back what we saved.
1592*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
1593*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
1594*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(info));
1595*795d594fSAndroid Build Coastguard Worker
1596*795d594fSAndroid Build Coastguard Worker // Run the test after save and load.
1597*795d594fSAndroid Build Coastguard Worker run_test(loaded_info);
1598*795d594fSAndroid Build Coastguard Worker }
1599*795d594fSAndroid Build Coastguard Worker
1600*795d594fSAndroid Build Coastguard Worker // Verify that we can add classes with annotations.
TEST_F(ProfileCompilationInfoTest,AddAnnotationsToClasses)1601*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, AddAnnotationsToClasses) {
1602*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1603*795d594fSAndroid Build Coastguard Worker
1604*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa1("test1");
1605*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa2("test2");
1606*795d594fSAndroid Build Coastguard Worker // Save a few classes using different annotations, some overlapping, some not.
1607*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 7; i++) {
1608*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info, dex1, dex::TypeIndex(i), psa1));
1609*795d594fSAndroid Build Coastguard Worker }
1610*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 3; i < 10; i++) {
1611*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info, dex1, dex::TypeIndex(i), psa2));
1612*795d594fSAndroid Build Coastguard Worker }
1613*795d594fSAndroid Build Coastguard Worker
1614*795d594fSAndroid Build Coastguard Worker auto run_test = [&dex1 = dex1, &psa1 = psa1, &psa2 = psa2](const ProfileCompilationInfo& info) {
1615*795d594fSAndroid Build Coastguard Worker // Check that all classes are in.
1616*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 7; i++) {
1617*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa1));
1618*795d594fSAndroid Build Coastguard Worker }
1619*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 3; i < 10; i++) {
1620*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa2));
1621*795d594fSAndroid Build Coastguard Worker }
1622*795d594fSAndroid Build Coastguard Worker // Check that the non-overlapping classes are not added with a wrong annotation.
1623*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 7; i < 10; i++) {
1624*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa1));
1625*795d594fSAndroid Build Coastguard Worker }
1626*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 3; i++) {
1627*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa2));
1628*795d594fSAndroid Build Coastguard Worker }
1629*795d594fSAndroid Build Coastguard Worker // Check that when querying without an annotation only the first one is searched.
1630*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 7; i++) {
1631*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.ContainsClass(*dex1, dex::TypeIndex(i)));
1632*795d594fSAndroid Build Coastguard Worker }
1633*795d594fSAndroid Build Coastguard Worker // ... this should be false because they belong the second appearance of dex1.
1634*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 7; i < 10; i++) {
1635*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.ContainsClass(*dex1, dex::TypeIndex(i)));
1636*795d594fSAndroid Build Coastguard Worker }
1637*795d594fSAndroid Build Coastguard Worker
1638*795d594fSAndroid Build Coastguard Worker // Check that the classes cannot be found with a non existing annotation.
1639*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.ContainsClass(*dex1, dex::TypeIndex(0), ProfileSampleAnnotation("new_test")));
1640*795d594fSAndroid Build Coastguard Worker };
1641*795d594fSAndroid Build Coastguard Worker
1642*795d594fSAndroid Build Coastguard Worker // Run the test before save.
1643*795d594fSAndroid Build Coastguard Worker run_test(info);
1644*795d594fSAndroid Build Coastguard Worker
1645*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
1646*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Save(GetFd(profile)));
1647*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
1648*795d594fSAndroid Build Coastguard Worker
1649*795d594fSAndroid Build Coastguard Worker // Check that we get back what we saved.
1650*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo loaded_info;
1651*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
1652*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_info.Equals(info));
1653*795d594fSAndroid Build Coastguard Worker
1654*795d594fSAndroid Build Coastguard Worker // Run the test after save and load.
1655*795d594fSAndroid Build Coastguard Worker run_test(loaded_info);
1656*795d594fSAndroid Build Coastguard Worker }
1657*795d594fSAndroid Build Coastguard Worker
1658*795d594fSAndroid Build Coastguard Worker // Verify we can merge samples with annotations.
TEST_F(ProfileCompilationInfoTest,MergeWithAnnotations)1659*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, MergeWithAnnotations) {
1660*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
1661*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
1662*795d594fSAndroid Build Coastguard Worker
1663*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa1("test1");
1664*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa2("test2");
1665*795d594fSAndroid Build Coastguard Worker
1666*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 7; i++) {
1667*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info1, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa1));
1668*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info1, dex1, dex::TypeIndex(i), psa1));
1669*795d594fSAndroid Build Coastguard Worker }
1670*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 3; i < 10; i++) {
1671*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info2, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa1));
1672*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info2, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa2));
1673*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info2, dex2, /*method_idx=*/ i, Hotness::kFlagHot, psa2));
1674*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info2, dex1, dex::TypeIndex(i), psa1));
1675*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info2, dex1, dex::TypeIndex(i), psa2));
1676*795d594fSAndroid Build Coastguard Worker }
1677*795d594fSAndroid Build Coastguard Worker
1678*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1679*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.MergeWith(info1));
1680*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.MergeWith(info2));
1681*795d594fSAndroid Build Coastguard Worker
1682*795d594fSAndroid Build Coastguard Worker // Check that all items are in.
1683*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1684*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i), psa1).IsInProfile());
1685*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa1));
1686*795d594fSAndroid Build Coastguard Worker }
1687*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 3; i < 10; i++) {
1688*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex1, i), psa2).IsInProfile());
1689*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(MethodReference(dex2, i), psa2).IsInProfile());
1690*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa2));
1691*795d594fSAndroid Build Coastguard Worker }
1692*795d594fSAndroid Build Coastguard Worker
1693*795d594fSAndroid Build Coastguard Worker // Check that the non-overlapping items are not added with a wrong annotation.
1694*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 3; i++) {
1695*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex1, i), psa2).IsInProfile());
1696*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(MethodReference(dex2, i), psa2).IsInProfile());
1697*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.ContainsClass(*dex1, dex::TypeIndex(i), psa2));
1698*795d594fSAndroid Build Coastguard Worker }
1699*795d594fSAndroid Build Coastguard Worker }
1700*795d594fSAndroid Build Coastguard Worker
1701*795d594fSAndroid Build Coastguard Worker // Verify we can merge samples with annotations.
TEST_F(ProfileCompilationInfoTest,MergeWithInlineCaches)1702*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, MergeWithInlineCaches) {
1703*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1(/*for_boot_image=*/ true);
1704*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2(/*for_boot_image=*/ true);
1705*795d594fSAndroid Build Coastguard Worker // TODO This should be something other than 'kNone'
1706*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa1(ProfileSampleAnnotation::kNone);
1707*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> dex1_type_12 { TypeReference(dex1, dex::TypeIndex(1)),
1708*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(2)) };
1709*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> dex1_type_48 { TypeReference(dex1, dex::TypeIndex(4)),
1710*795d594fSAndroid Build Coastguard Worker TypeReference(dex1, dex::TypeIndex(8)) };
1711*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> dex2_type_12 { TypeReference(dex2, dex::TypeIndex(1)),
1712*795d594fSAndroid Build Coastguard Worker TypeReference(dex2, dex::TypeIndex(2)) };
1713*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> dex2_type_48 { TypeReference(dex2, dex::TypeIndex(4)),
1714*795d594fSAndroid Build Coastguard Worker TypeReference(dex2, dex::TypeIndex(8)) };
1715*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> ic1 { ProfileInlineCache(
1716*795d594fSAndroid Build Coastguard Worker /*pc=*/ 12,
1717*795d594fSAndroid Build Coastguard Worker /*missing_types=*/ false,
1718*795d594fSAndroid Build Coastguard Worker /*profile_classes=*/ dex1_type_12),
1719*795d594fSAndroid Build Coastguard Worker ProfileInlineCache(
1720*795d594fSAndroid Build Coastguard Worker /*pc=*/ 15,
1721*795d594fSAndroid Build Coastguard Worker /*missing_types=*/ false,
1722*795d594fSAndroid Build Coastguard Worker /*profile_classes=*/ dex1_type_48) };
1723*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> ic2 { ProfileInlineCache(
1724*795d594fSAndroid Build Coastguard Worker /*pc=*/ 12,
1725*795d594fSAndroid Build Coastguard Worker /*missing_types=*/ false,
1726*795d594fSAndroid Build Coastguard Worker /*profile_classes=*/ dex2_type_48),
1727*795d594fSAndroid Build Coastguard Worker ProfileInlineCache(
1728*795d594fSAndroid Build Coastguard Worker /*pc=*/ 15,
1729*795d594fSAndroid Build Coastguard Worker /*missing_types=*/ false,
1730*795d594fSAndroid Build Coastguard Worker /*profile_classes=*/ dex2_type_12) };
1731*795d594fSAndroid Build Coastguard Worker
1732*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1733*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info1, dex1, /*method_idx=*/ i, ic1, psa1));
1734*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info1, dex1, dex::TypeIndex(i), psa1));
1735*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info1, dex2, dex::TypeIndex(i), psa1));
1736*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info2, dex1, /*method_idx=*/ i, ic2, psa1));
1737*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info2, dex1, dex::TypeIndex(i), psa1));
1738*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info2, dex2, dex::TypeIndex(i), psa1));
1739*795d594fSAndroid Build Coastguard Worker }
1740*795d594fSAndroid Build Coastguard Worker
1741*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info_12(/*for_boot_image=*/ true);
1742*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info_12.MergeWith(info1));
1743*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info_12.MergeWith(info2));
1744*795d594fSAndroid Build Coastguard Worker
1745*795d594fSAndroid Build Coastguard Worker // Check that all items are in.
1746*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1747*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info_12.GetMethodHotness(MethodReference(dex1, i), psa1).IsInProfile());
1748*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info_12.ContainsClass(*dex1, dex::TypeIndex(i), psa1));
1749*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness loaded_ic_12 =
1750*795d594fSAndroid Build Coastguard Worker GetMethod(info_12, dex1, /*method_idx=*/ i);
1751*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(loaded_ic_12.IsHot());
1752*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> cls_pc12;
1753*795d594fSAndroid Build Coastguard Worker cls_pc12.resize(dex1_type_12.size() + dex2_type_48.size(),
1754*795d594fSAndroid Build Coastguard Worker TypeReference(nullptr, dex::TypeIndex(-1)));
1755*795d594fSAndroid Build Coastguard Worker auto copy_end_12 = std::copy(dex1_type_12.begin(), dex1_type_12.end(), cls_pc12.begin());
1756*795d594fSAndroid Build Coastguard Worker std::copy(dex2_type_48.begin(), dex2_type_48.end(), copy_end_12);
1757*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> cls_pc15;
1758*795d594fSAndroid Build Coastguard Worker cls_pc15.resize(dex2_type_12.size() + dex1_type_48.size(),
1759*795d594fSAndroid Build Coastguard Worker TypeReference(nullptr, dex::TypeIndex(-1)));
1760*795d594fSAndroid Build Coastguard Worker auto copy_end_15 = std::copy(dex2_type_12.begin(), dex2_type_12.end(), cls_pc15.begin());
1761*795d594fSAndroid Build Coastguard Worker std::copy(dex1_type_48.begin(), dex1_type_48.end(), copy_end_15);
1762*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> expected{ ProfileInlineCache(
1763*795d594fSAndroid Build Coastguard Worker /*pc=*/ 12,
1764*795d594fSAndroid Build Coastguard Worker /*missing_types=*/ false,
1765*795d594fSAndroid Build Coastguard Worker /*profile_classes=*/ cls_pc12),
1766*795d594fSAndroid Build Coastguard Worker ProfileInlineCache(
1767*795d594fSAndroid Build Coastguard Worker /*pc=*/ 15,
1768*795d594fSAndroid Build Coastguard Worker /*missing_types=*/ false,
1769*795d594fSAndroid Build Coastguard Worker /*profile_classes=*/ cls_pc15) };
1770*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(loaded_ic_12.GetInlineCacheMap()->size(), expected.size());
1771*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(EqualInlineCaches(expected, dex1, loaded_ic_12, info_12)) << i;
1772*795d594fSAndroid Build Coastguard Worker }
1773*795d594fSAndroid Build Coastguard Worker }
1774*795d594fSAndroid Build Coastguard Worker
1775*795d594fSAndroid Build Coastguard Worker // Verify the bulk extraction API.
TEST_F(ProfileCompilationInfoTest,ExtractInfoWithAnnations)1776*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, ExtractInfoWithAnnations) {
1777*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1778*795d594fSAndroid Build Coastguard Worker
1779*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa1("test1");
1780*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa2("test2");
1781*795d594fSAndroid Build Coastguard Worker
1782*795d594fSAndroid Build Coastguard Worker std::set<dex::TypeIndex> expected_classes;
1783*795d594fSAndroid Build Coastguard Worker std::set<uint16_t> expected_hot_methods;
1784*795d594fSAndroid Build Coastguard Worker std::set<uint16_t> expected_startup_methods;
1785*795d594fSAndroid Build Coastguard Worker std::set<uint16_t> expected_post_startup_methods;
1786*795d594fSAndroid Build Coastguard Worker
1787*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1788*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa1));
1789*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info, dex1, dex::TypeIndex(i), psa1));
1790*795d594fSAndroid Build Coastguard Worker expected_hot_methods.insert(i);
1791*795d594fSAndroid Build Coastguard Worker expected_classes.insert(dex::TypeIndex(i));
1792*795d594fSAndroid Build Coastguard Worker }
1793*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 5; i < 15; i++) {
1794*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa2));
1795*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagStartup, psa1));
1796*795d594fSAndroid Build Coastguard Worker expected_startup_methods.insert(i);
1797*795d594fSAndroid Build Coastguard Worker }
1798*795d594fSAndroid Build Coastguard Worker
1799*795d594fSAndroid Build Coastguard Worker std::set<dex::TypeIndex> classes;
1800*795d594fSAndroid Build Coastguard Worker std::set<uint16_t> hot_methods;
1801*795d594fSAndroid Build Coastguard Worker std::set<uint16_t> startup_methods;
1802*795d594fSAndroid Build Coastguard Worker std::set<uint16_t> post_startup_methods;
1803*795d594fSAndroid Build Coastguard Worker
1804*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetClassesAndMethods(
1805*795d594fSAndroid Build Coastguard Worker *dex1, &classes, &hot_methods, &startup_methods, &post_startup_methods, psa1));
1806*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(expected_classes, classes);
1807*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(expected_hot_methods, hot_methods);
1808*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(expected_startup_methods, startup_methods);
1809*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(expected_post_startup_methods, post_startup_methods);
1810*795d594fSAndroid Build Coastguard Worker
1811*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetClassesAndMethods(
1812*795d594fSAndroid Build Coastguard Worker *dex1,
1813*795d594fSAndroid Build Coastguard Worker &classes,
1814*795d594fSAndroid Build Coastguard Worker &hot_methods,
1815*795d594fSAndroid Build Coastguard Worker &startup_methods,
1816*795d594fSAndroid Build Coastguard Worker &post_startup_methods,
1817*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation("new_test")));
1818*795d594fSAndroid Build Coastguard Worker }
1819*795d594fSAndroid Build Coastguard Worker
1820*795d594fSAndroid Build Coastguard Worker // Verify the behavior for adding methods with annotations and different dex checksums.
TEST_F(ProfileCompilationInfoTest,AddMethodsWithAnnotationAndDifferentChecksum)1821*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, AddMethodsWithAnnotationAndDifferentChecksum) {
1822*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1823*795d594fSAndroid Build Coastguard Worker
1824*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa1("test1");
1825*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa2("test2");
1826*795d594fSAndroid Build Coastguard Worker
1827*795d594fSAndroid Build Coastguard Worker MethodReference ref(dex1, 0);
1828*795d594fSAndroid Build Coastguard Worker MethodReference ref_checksum_missmatch(dex1_checksum_missmatch, 1);
1829*795d594fSAndroid Build Coastguard Worker
1830*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.AddMethod(ProfileMethodInfo(ref), Hotness::kFlagHot, psa1));
1831*795d594fSAndroid Build Coastguard Worker // Adding a method with a different dex checksum and the same annotation should fail.
1832*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(info.AddMethod(ProfileMethodInfo(ref_checksum_missmatch), Hotness::kFlagHot, psa1));
1833*795d594fSAndroid Build Coastguard Worker // However, a method with a different dex checksum and a different annotation should be ok.
1834*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.AddMethod(ProfileMethodInfo(ref_checksum_missmatch), Hotness::kFlagHot, psa2));
1835*795d594fSAndroid Build Coastguard Worker }
1836*795d594fSAndroid Build Coastguard Worker
1837*795d594fSAndroid Build Coastguard Worker // Verify the behavior for searching method with annotations and different dex checksums.
TEST_F(ProfileCompilationInfoTest,FindMethodsWithAnnotationAndDifferentChecksum)1838*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, FindMethodsWithAnnotationAndDifferentChecksum) {
1839*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1840*795d594fSAndroid Build Coastguard Worker
1841*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa1("test1");
1842*795d594fSAndroid Build Coastguard Worker
1843*795d594fSAndroid Build Coastguard Worker MethodReference ref(dex1, 0);
1844*795d594fSAndroid Build Coastguard Worker MethodReference ref_checksum_missmatch(dex1_checksum_missmatch, 0);
1845*795d594fSAndroid Build Coastguard Worker
1846*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.AddMethod(ProfileMethodInfo(ref), Hotness::kFlagHot, psa1));
1847*795d594fSAndroid Build Coastguard Worker
1848*795d594fSAndroid Build Coastguard Worker // The method should be in the profile when searched with the correct data.
1849*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(ref, psa1).IsInProfile());
1850*795d594fSAndroid Build Coastguard Worker // We should get a negative result if the dex checksum does not match.
1851*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(ref_checksum_missmatch, psa1).IsInProfile());
1852*795d594fSAndroid Build Coastguard Worker
1853*795d594fSAndroid Build Coastguard Worker // If we search without annotation we should have the same behaviour.
1854*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(info.GetMethodHotness(ref).IsInProfile());
1855*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(info.GetMethodHotness(ref_checksum_missmatch).IsInProfile());
1856*795d594fSAndroid Build Coastguard Worker }
1857*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,ClearDataAndAdjustVersionRegularToBoot)1858*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, ClearDataAndAdjustVersionRegularToBoot) {
1859*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1860*795d594fSAndroid Build Coastguard Worker
1861*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex1, /*method_idx=*/ 0, Hotness::kFlagHot);
1862*795d594fSAndroid Build Coastguard Worker
1863*795d594fSAndroid Build Coastguard Worker info.ClearDataAndAdjustVersion(/*for_boot_image=*/true);
1864*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.IsEmpty());
1865*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.IsForBootImage());
1866*795d594fSAndroid Build Coastguard Worker }
1867*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileCompilationInfoTest,ClearDataAndAdjustVersionBootToRegular)1868*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, ClearDataAndAdjustVersionBootToRegular) {
1869*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info(/*for_boot_image=*/true);
1870*795d594fSAndroid Build Coastguard Worker
1871*795d594fSAndroid Build Coastguard Worker AddMethod(&info, dex1, /*method_idx=*/ 0, Hotness::kFlagHot);
1872*795d594fSAndroid Build Coastguard Worker
1873*795d594fSAndroid Build Coastguard Worker info.ClearDataAndAdjustVersion(/*for_boot_image=*/false);
1874*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.IsEmpty());
1875*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(info.IsForBootImage());
1876*795d594fSAndroid Build Coastguard Worker }
1877*795d594fSAndroid Build Coastguard Worker
1878*795d594fSAndroid Build Coastguard Worker template<class T>
sort(const std::list<T> & list)1879*795d594fSAndroid Build Coastguard Worker static std::list<T> sort(const std::list<T>& list) {
1880*795d594fSAndroid Build Coastguard Worker std::list<T> copy(list);
1881*795d594fSAndroid Build Coastguard Worker copy.sort();
1882*795d594fSAndroid Build Coastguard Worker return copy;
1883*795d594fSAndroid Build Coastguard Worker }
1884*795d594fSAndroid Build Coastguard Worker
1885*795d594fSAndroid Build Coastguard Worker // Verify we can extract profile data
TEST_F(ProfileCompilationInfoTest,ExtractProfileData)1886*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, ExtractProfileData) {
1887*795d594fSAndroid Build Coastguard Worker // Setup test data
1888*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1889*795d594fSAndroid Build Coastguard Worker
1890*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa1("test1");
1891*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa2("test2");
1892*795d594fSAndroid Build Coastguard Worker
1893*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1894*795d594fSAndroid Build Coastguard Worker // Add dex1 data with different annotations so that we can check the annotation count.
1895*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa1));
1896*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info, dex1, dex::TypeIndex(i), psa1));
1897*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex1, /*method_idx=*/ i, Hotness::kFlagStartup, psa2));
1898*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info, dex1, dex::TypeIndex(i), psa2));
1899*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex2, /*method_idx=*/ i, Hotness::kFlagHot, psa2));
1900*795d594fSAndroid Build Coastguard Worker // dex3 will not be used in the data extraction
1901*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info, dex3, /*method_idx=*/ i, Hotness::kFlagHot, psa2));
1902*795d594fSAndroid Build Coastguard Worker }
1903*795d594fSAndroid Build Coastguard Worker
1904*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files;
1905*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex1));
1906*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex2));
1907*795d594fSAndroid Build Coastguard Worker
1908*795d594fSAndroid Build Coastguard Worker // Run the test: extract the data for dex1 and dex2
1909*795d594fSAndroid Build Coastguard Worker std::unique_ptr<FlattenProfileData> flattenProfileData = info.ExtractProfileData(dex_files);
1910*795d594fSAndroid Build Coastguard Worker
1911*795d594fSAndroid Build Coastguard Worker // Check the results
1912*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(flattenProfileData != nullptr);
1913*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(flattenProfileData->GetMaxAggregationForMethods(), 2u);
1914*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(flattenProfileData->GetMaxAggregationForClasses(), 2u);
1915*795d594fSAndroid Build Coastguard Worker
1916*795d594fSAndroid Build Coastguard Worker const SafeMap<MethodReference, ItemMetadata>& methods = flattenProfileData->GetMethodData();
1917*795d594fSAndroid Build Coastguard Worker const SafeMap<TypeReference, ItemMetadata>& classes = flattenProfileData->GetClassData();
1918*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(methods.size(), 20u); // 10 methods in dex1, 10 in dex2
1919*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(classes.size(), 10u); // 10 methods in dex1
1920*795d594fSAndroid Build Coastguard Worker
1921*795d594fSAndroid Build Coastguard Worker std::list<ProfileSampleAnnotation> expectedAnnotations1({psa1, psa2});
1922*795d594fSAndroid Build Coastguard Worker std::list<ProfileSampleAnnotation> expectedAnnotations2({psa2});
1923*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1924*795d594fSAndroid Build Coastguard Worker // Check dex1 methods.
1925*795d594fSAndroid Build Coastguard Worker auto mIt1 = methods.find(MethodReference(dex1, i));
1926*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(mIt1 != methods.end());
1927*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(mIt1->second.GetFlags(), Hotness::kFlagHot | Hotness::kFlagStartup);
1928*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(sort(mIt1->second.GetAnnotations()), expectedAnnotations1);
1929*795d594fSAndroid Build Coastguard Worker // Check dex1 classes
1930*795d594fSAndroid Build Coastguard Worker auto cIt1 = classes.find(TypeReference(dex1, dex::TypeIndex(i)));
1931*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(cIt1 != classes.end());
1932*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(cIt1->second.GetFlags(), 0);
1933*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(sort(cIt1->second.GetAnnotations()), expectedAnnotations1);
1934*795d594fSAndroid Build Coastguard Worker // Check dex2 methods.
1935*795d594fSAndroid Build Coastguard Worker auto mIt2 = methods.find(MethodReference(dex2, i));
1936*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(mIt2 != methods.end());
1937*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(mIt2->second.GetFlags(), Hotness::kFlagHot);
1938*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(sort(mIt2->second.GetAnnotations()), expectedAnnotations2);
1939*795d594fSAndroid Build Coastguard Worker }
1940*795d594fSAndroid Build Coastguard Worker
1941*795d594fSAndroid Build Coastguard Worker // Release the ownership as this is held by the test class;
1942*795d594fSAndroid Build Coastguard Worker for (std::unique_ptr<const DexFile>& dex : dex_files) {
1943*795d594fSAndroid Build Coastguard Worker UNUSED(dex.release());
1944*795d594fSAndroid Build Coastguard Worker }
1945*795d594fSAndroid Build Coastguard Worker }
1946*795d594fSAndroid Build Coastguard Worker
1947*795d594fSAndroid Build Coastguard Worker // Verify we can merge 2 previously flatten data.
TEST_F(ProfileCompilationInfoTest,MergeFlattenData)1948*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileCompilationInfoTest, MergeFlattenData) {
1949*795d594fSAndroid Build Coastguard Worker // Setup test data: two profiles with different content which will be used
1950*795d594fSAndroid Build Coastguard Worker // to extract FlattenProfileData, later to be merged.
1951*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
1952*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
1953*795d594fSAndroid Build Coastguard Worker
1954*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa1("test1");
1955*795d594fSAndroid Build Coastguard Worker ProfileSampleAnnotation psa2("test2");
1956*795d594fSAndroid Build Coastguard Worker
1957*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1958*795d594fSAndroid Build Coastguard Worker // Add dex1 data with different annotations so that we can check the annotation count.
1959*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info1, dex1, /*method_idx=*/ i, Hotness::kFlagHot, psa1));
1960*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info2, dex1, dex::TypeIndex(i), psa1));
1961*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(&info1, dex1, /*method_idx=*/ i, Hotness::kFlagStartup, psa2));
1962*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(&info1, dex1, dex::TypeIndex(i), psa2));
1963*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(i % 2 == 0 ? &info1 : &info2, dex2,
1964*795d594fSAndroid Build Coastguard Worker /*method_idx=*/ i,
1965*795d594fSAndroid Build Coastguard Worker Hotness::kFlagHot,
1966*795d594fSAndroid Build Coastguard Worker psa2));
1967*795d594fSAndroid Build Coastguard Worker }
1968*795d594fSAndroid Build Coastguard Worker
1969*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files;
1970*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex1));
1971*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::unique_ptr<const DexFile>(dex2));
1972*795d594fSAndroid Build Coastguard Worker
1973*795d594fSAndroid Build Coastguard Worker // Run the test: extract the data for dex1 and dex2 and then merge it into
1974*795d594fSAndroid Build Coastguard Worker std::unique_ptr<FlattenProfileData> flattenProfileData1 = info1.ExtractProfileData(dex_files);
1975*795d594fSAndroid Build Coastguard Worker std::unique_ptr<FlattenProfileData> flattenProfileData2 = info2.ExtractProfileData(dex_files);
1976*795d594fSAndroid Build Coastguard Worker
1977*795d594fSAndroid Build Coastguard Worker flattenProfileData1->MergeData(*flattenProfileData2);
1978*795d594fSAndroid Build Coastguard Worker // Check the results
1979*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(flattenProfileData1->GetMaxAggregationForMethods(), 2u);
1980*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(flattenProfileData1->GetMaxAggregationForClasses(), 2u);
1981*795d594fSAndroid Build Coastguard Worker
1982*795d594fSAndroid Build Coastguard Worker const SafeMap<MethodReference, ItemMetadata>& methods = flattenProfileData1->GetMethodData();
1983*795d594fSAndroid Build Coastguard Worker const SafeMap<TypeReference, ItemMetadata>& classes = flattenProfileData1->GetClassData();
1984*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(methods.size(), 20u); // 10 methods in dex1, 10 in dex2
1985*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(classes.size(), 10u); // 10 methods in dex1
1986*795d594fSAndroid Build Coastguard Worker
1987*795d594fSAndroid Build Coastguard Worker std::list<ProfileSampleAnnotation> expectedAnnotations1({psa1, psa2});
1988*795d594fSAndroid Build Coastguard Worker std::list<ProfileSampleAnnotation> expectedAnnotations2({psa2});
1989*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < 10; i++) {
1990*795d594fSAndroid Build Coastguard Worker // Check dex1 methods.
1991*795d594fSAndroid Build Coastguard Worker auto mIt1 = methods.find(MethodReference(dex1, i));
1992*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(mIt1 != methods.end());
1993*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(mIt1->second.GetFlags(), Hotness::kFlagHot | Hotness::kFlagStartup);
1994*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(sort(mIt1->second.GetAnnotations()), expectedAnnotations1);
1995*795d594fSAndroid Build Coastguard Worker // Check dex1 classes
1996*795d594fSAndroid Build Coastguard Worker auto cIt1 = classes.find(TypeReference(dex1, dex::TypeIndex(i)));
1997*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(cIt1 != classes.end());
1998*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(cIt1->second.GetFlags(), 0);
1999*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(sort(cIt1->second.GetAnnotations()).size(), expectedAnnotations1.size());
2000*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(sort(cIt1->second.GetAnnotations()), expectedAnnotations1);
2001*795d594fSAndroid Build Coastguard Worker // Check dex2 methods.
2002*795d594fSAndroid Build Coastguard Worker auto mIt2 = methods.find(MethodReference(dex2, i));
2003*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(mIt2 != methods.end());
2004*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(mIt2->second.GetFlags(), Hotness::kFlagHot);
2005*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(sort(mIt2->second.GetAnnotations()), expectedAnnotations2);
2006*795d594fSAndroid Build Coastguard Worker }
2007*795d594fSAndroid Build Coastguard Worker
2008*795d594fSAndroid Build Coastguard Worker // Release the ownership as this is held by the test class;
2009*795d594fSAndroid Build Coastguard Worker for (std::unique_ptr<const DexFile>& dex : dex_files) {
2010*795d594fSAndroid Build Coastguard Worker UNUSED(dex.release());
2011*795d594fSAndroid Build Coastguard Worker }
2012*795d594fSAndroid Build Coastguard Worker }
2013*795d594fSAndroid Build Coastguard Worker
2014*795d594fSAndroid Build Coastguard Worker } // namespace art
2015