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 "profile_assistant.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <sstream>
20*795d594fSAndroid Build Coastguard Worker #include <string>
21*795d594fSAndroid Build Coastguard Worker
22*795d594fSAndroid Build Coastguard Worker #include "android-base/file.h"
23*795d594fSAndroid Build Coastguard Worker #include "android-base/strings.h"
24*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/globals.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/unix_file/fd_file.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
28*795d594fSAndroid Build Coastguard Worker #include "common_runtime_test.h"
29*795d594fSAndroid Build Coastguard Worker #include "dex/descriptors_names.h"
30*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_structs.h"
31*795d594fSAndroid Build Coastguard Worker #include "dex/dex_instruction-inl.h"
32*795d594fSAndroid Build Coastguard Worker #include "dex/dex_instruction_iterator.h"
33*795d594fSAndroid Build Coastguard Worker #include "dex/type_reference.h"
34*795d594fSAndroid Build Coastguard Worker #include "exec_utils.h"
35*795d594fSAndroid Build Coastguard Worker #include "gtest/gtest.h"
36*795d594fSAndroid Build Coastguard Worker #include "linear_alloc.h"
37*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
38*795d594fSAndroid Build Coastguard Worker #include "obj_ptr-inl.h"
39*795d594fSAndroid Build Coastguard Worker #include "profile/profile_compilation_info.h"
40*795d594fSAndroid Build Coastguard Worker #include "profile/profile_test_helper.h"
41*795d594fSAndroid Build Coastguard Worker #include "profman/profman_result.h"
42*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
43*795d594fSAndroid Build Coastguard Worker
44*795d594fSAndroid Build Coastguard Worker namespace art {
45*795d594fSAndroid Build Coastguard Worker
46*795d594fSAndroid Build Coastguard Worker using TypeReferenceSet = std::set<TypeReference, TypeReferenceValueComparator>;
47*795d594fSAndroid Build Coastguard Worker
48*795d594fSAndroid Build Coastguard Worker // TODO(calin): These tests share a lot with the ProfileCompilationInfo tests.
49*795d594fSAndroid Build Coastguard Worker // we should introduce a better abstraction to extract the common parts.
50*795d594fSAndroid Build Coastguard Worker class ProfileAssistantTest : public CommonRuntimeTest, public ProfileTestHelper {
51*795d594fSAndroid Build Coastguard Worker public:
PostRuntimeCreate()52*795d594fSAndroid Build Coastguard Worker void PostRuntimeCreate() override {
53*795d594fSAndroid Build Coastguard Worker allocator_.reset(new ArenaAllocator(Runtime::Current()->GetArenaPool()));
54*795d594fSAndroid Build Coastguard Worker
55*795d594fSAndroid Build Coastguard Worker dex1 = BuildDex("location1", /*location_checksum=*/ 1, "LUnique1;", /*num_method_ids=*/ 10001);
56*795d594fSAndroid Build Coastguard Worker dex2 = BuildDex("location2", /*location_checksum=*/ 2, "LUnique2;", /*num_method_ids=*/ 10002);
57*795d594fSAndroid Build Coastguard Worker dex3 = BuildDex("location3", /*location_checksum=*/ 3, "LUnique3;", /*num_method_ids=*/ 10003);
58*795d594fSAndroid Build Coastguard Worker dex4 = BuildDex("location4", /*location_checksum=*/ 4, "LUnique4;", /*num_method_ids=*/ 10004);
59*795d594fSAndroid Build Coastguard Worker
60*795d594fSAndroid Build Coastguard Worker dex1_checksum_missmatch =
61*795d594fSAndroid Build Coastguard Worker BuildDex("location1", /*location_checksum=*/ 12, "LUnique1;", /*num_method_ids=*/ 10001);
62*795d594fSAndroid Build Coastguard Worker }
63*795d594fSAndroid Build Coastguard Worker
64*795d594fSAndroid Build Coastguard Worker protected:
SetupProfile(const DexFile * dex_file1,const DexFile * dex_file2,uint16_t number_of_methods,uint16_t number_of_classes,const ScratchFile & profile,ProfileCompilationInfo * info,uint16_t start_method_index=0,bool reverse_dex_write_order=false)65*795d594fSAndroid Build Coastguard Worker void SetupProfile(const DexFile* dex_file1,
66*795d594fSAndroid Build Coastguard Worker const DexFile* dex_file2,
67*795d594fSAndroid Build Coastguard Worker uint16_t number_of_methods,
68*795d594fSAndroid Build Coastguard Worker uint16_t number_of_classes,
69*795d594fSAndroid Build Coastguard Worker const ScratchFile& profile,
70*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo* info,
71*795d594fSAndroid Build Coastguard Worker uint16_t start_method_index = 0,
72*795d594fSAndroid Build Coastguard Worker bool reverse_dex_write_order = false) {
73*795d594fSAndroid Build Coastguard Worker for (uint16_t i = start_method_index; i < start_method_index + number_of_methods; i++) {
74*795d594fSAndroid Build Coastguard Worker // reverse_dex_write_order controls the order in which the dex files will be added to
75*795d594fSAndroid Build Coastguard Worker // the profile and thus written to disk.
76*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches =
77*795d594fSAndroid Build Coastguard Worker GetTestInlineCaches(dex_file1, dex_file2, dex3);
78*795d594fSAndroid Build Coastguard Worker Hotness::Flag flags =
79*795d594fSAndroid Build Coastguard Worker static_cast<Hotness::Flag>(Hotness::kFlagHot | Hotness::kFlagPostStartup);
80*795d594fSAndroid Build Coastguard Worker if (reverse_dex_write_order) {
81*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(info, dex_file2, i, inline_caches, flags));
82*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(info, dex_file1, i, inline_caches, flags));
83*795d594fSAndroid Build Coastguard Worker } else {
84*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(info, dex_file1, i, inline_caches, flags));
85*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddMethod(info, dex_file2, i, inline_caches, flags));
86*795d594fSAndroid Build Coastguard Worker }
87*795d594fSAndroid Build Coastguard Worker }
88*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < number_of_classes; i++) {
89*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(AddClass(info, dex_file1, dex::TypeIndex(i)));
90*795d594fSAndroid Build Coastguard Worker }
91*795d594fSAndroid Build Coastguard Worker
92*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info->Save(GetFd(profile)));
93*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
94*795d594fSAndroid Build Coastguard Worker }
95*795d594fSAndroid Build Coastguard Worker
SetupBasicProfile(const DexFile * dex,const std::vector<uint32_t> & hot_methods,const std::vector<uint32_t> & startup_methods,const std::vector<uint32_t> & post_startup_methods,const ScratchFile & profile,ProfileCompilationInfo * info)96*795d594fSAndroid Build Coastguard Worker void SetupBasicProfile(const DexFile* dex,
97*795d594fSAndroid Build Coastguard Worker const std::vector<uint32_t>& hot_methods,
98*795d594fSAndroid Build Coastguard Worker const std::vector<uint32_t>& startup_methods,
99*795d594fSAndroid Build Coastguard Worker const std::vector<uint32_t>& post_startup_methods,
100*795d594fSAndroid Build Coastguard Worker const ScratchFile& profile,
101*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo* info) {
102*795d594fSAndroid Build Coastguard Worker for (uint32_t idx : hot_methods) {
103*795d594fSAndroid Build Coastguard Worker AddMethod(info, dex, idx, Hotness::kFlagHot);
104*795d594fSAndroid Build Coastguard Worker }
105*795d594fSAndroid Build Coastguard Worker for (uint32_t idx : startup_methods) {
106*795d594fSAndroid Build Coastguard Worker AddMethod(info, dex, idx, Hotness::kFlagStartup);
107*795d594fSAndroid Build Coastguard Worker }
108*795d594fSAndroid Build Coastguard Worker for (uint32_t idx : post_startup_methods) {
109*795d594fSAndroid Build Coastguard Worker AddMethod(info, dex, idx, Hotness::kFlagPostStartup);
110*795d594fSAndroid Build Coastguard Worker }
111*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info->Save(GetFd(profile)));
112*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, profile.GetFile()->Flush());
113*795d594fSAndroid Build Coastguard Worker }
114*795d594fSAndroid Build Coastguard Worker
115*795d594fSAndroid Build Coastguard Worker // The dex1_substitute can be used to replace the default dex1 file.
GetTestInlineCaches(const DexFile * dex_file1,const DexFile * dex_file2,const DexFile * dex_file3)116*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> GetTestInlineCaches(
117*795d594fSAndroid Build Coastguard Worker const DexFile* dex_file1, const DexFile* dex_file2, const DexFile* dex_file3) {
118*795d594fSAndroid Build Coastguard Worker std::vector<ProfileInlineCache> inline_caches;
119*795d594fSAndroid Build Coastguard Worker // Monomorphic
120*795d594fSAndroid Build Coastguard Worker for (uint16_t dex_pc = 0; dex_pc < 11; dex_pc++) {
121*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types = {TypeReference(dex_file1, dex::TypeIndex(0))};
122*795d594fSAndroid Build Coastguard Worker inline_caches.push_back(ProfileInlineCache(dex_pc, /* missing_types*/ false, types));
123*795d594fSAndroid Build Coastguard Worker }
124*795d594fSAndroid Build Coastguard Worker // Polymorphic
125*795d594fSAndroid Build Coastguard Worker for (uint16_t dex_pc = 11; dex_pc < 22; dex_pc++) {
126*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types = {
127*795d594fSAndroid Build Coastguard Worker TypeReference(dex_file1, dex::TypeIndex(0)),
128*795d594fSAndroid Build Coastguard Worker TypeReference(dex_file2, dex::TypeIndex(1)),
129*795d594fSAndroid Build Coastguard Worker TypeReference(dex_file3, dex::TypeIndex(2))};
130*795d594fSAndroid Build Coastguard Worker inline_caches.push_back(ProfileInlineCache(dex_pc, /* missing_types*/ false, types));
131*795d594fSAndroid Build Coastguard Worker }
132*795d594fSAndroid Build Coastguard Worker // Megamorphic
133*795d594fSAndroid Build Coastguard Worker for (uint16_t dex_pc = 22; dex_pc < 33; dex_pc++) {
134*795d594fSAndroid Build Coastguard Worker // we need 5 types to make the cache megamorphic
135*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types = {
136*795d594fSAndroid Build Coastguard Worker TypeReference(dex_file1, dex::TypeIndex(0)),
137*795d594fSAndroid Build Coastguard Worker TypeReference(dex_file1, dex::TypeIndex(1)),
138*795d594fSAndroid Build Coastguard Worker TypeReference(dex_file1, dex::TypeIndex(2)),
139*795d594fSAndroid Build Coastguard Worker TypeReference(dex_file1, dex::TypeIndex(3)),
140*795d594fSAndroid Build Coastguard Worker TypeReference(dex_file1, dex::TypeIndex(4))};
141*795d594fSAndroid Build Coastguard Worker inline_caches.push_back(ProfileInlineCache(dex_pc, /* missing_types*/ false, types));
142*795d594fSAndroid Build Coastguard Worker }
143*795d594fSAndroid Build Coastguard Worker // Missing types
144*795d594fSAndroid Build Coastguard Worker for (uint16_t dex_pc = 33; dex_pc < 44; dex_pc++) {
145*795d594fSAndroid Build Coastguard Worker std::vector<TypeReference> types;
146*795d594fSAndroid Build Coastguard Worker inline_caches.push_back(ProfileInlineCache(dex_pc, /* missing_types*/ true, types));
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker
149*795d594fSAndroid Build Coastguard Worker return inline_caches;
150*795d594fSAndroid Build Coastguard Worker }
151*795d594fSAndroid Build Coastguard Worker
GetFd(const ScratchFile & file) const152*795d594fSAndroid Build Coastguard Worker int GetFd(const ScratchFile& file) const {
153*795d594fSAndroid Build Coastguard Worker return static_cast<int>(file.GetFd());
154*795d594fSAndroid Build Coastguard Worker }
155*795d594fSAndroid Build Coastguard Worker
CheckProfileInfo(ScratchFile & file,const ProfileCompilationInfo & info)156*795d594fSAndroid Build Coastguard Worker void CheckProfileInfo(ScratchFile& file, const ProfileCompilationInfo& info) {
157*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo file_info;
158*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(file_info.Load(GetFd(file)));
159*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(file_info.Equals(info));
160*795d594fSAndroid Build Coastguard Worker }
161*795d594fSAndroid Build Coastguard Worker
GetProfmanCmd()162*795d594fSAndroid Build Coastguard Worker std::string GetProfmanCmd() {
163*795d594fSAndroid Build Coastguard Worker std::string file_path = GetArtBinDir() + "/profman";
164*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
165*795d594fSAndroid Build Coastguard Worker file_path += "d";
166*795d594fSAndroid Build Coastguard Worker }
167*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
168*795d594fSAndroid Build Coastguard Worker return file_path;
169*795d594fSAndroid Build Coastguard Worker }
170*795d594fSAndroid Build Coastguard Worker
171*795d594fSAndroid Build Coastguard Worker // Runs test with given arguments.
ProcessProfiles(const std::vector<int> & profiles_fd,int reference_profile_fd,const std::vector<std::string> & extra_args=std::vector<std::string> ())172*795d594fSAndroid Build Coastguard Worker int ProcessProfiles(
173*795d594fSAndroid Build Coastguard Worker const std::vector<int>& profiles_fd,
174*795d594fSAndroid Build Coastguard Worker int reference_profile_fd,
175*795d594fSAndroid Build Coastguard Worker const std::vector<std::string>& extra_args = std::vector<std::string>()) {
176*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
177*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
178*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
179*795d594fSAndroid Build Coastguard Worker for (size_t k = 0; k < profiles_fd.size(); k++) {
180*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--profile-file-fd=" + std::to_string(profiles_fd[k]));
181*795d594fSAndroid Build Coastguard Worker }
182*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile_fd));
183*795d594fSAndroid Build Coastguard Worker argv_str.insert(argv_str.end(), extra_args.begin(), extra_args.end());
184*795d594fSAndroid Build Coastguard Worker
185*795d594fSAndroid Build Coastguard Worker std::string error;
186*795d594fSAndroid Build Coastguard Worker return ExecAndReturnCode(argv_str, &error);
187*795d594fSAndroid Build Coastguard Worker }
188*795d594fSAndroid Build Coastguard Worker
GenerateTestProfile(const std::string & filename)189*795d594fSAndroid Build Coastguard Worker bool GenerateTestProfile(const std::string& filename) {
190*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
191*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
192*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
193*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--generate-test-profile=" + filename);
194*795d594fSAndroid Build Coastguard Worker std::string error;
195*795d594fSAndroid Build Coastguard Worker return ExecAndReturnCode(argv_str, &error);
196*795d594fSAndroid Build Coastguard Worker }
197*795d594fSAndroid Build Coastguard Worker
GenerateTestProfileWithInputDex(const std::string & filename)198*795d594fSAndroid Build Coastguard Worker bool GenerateTestProfileWithInputDex(const std::string& filename) {
199*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
200*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
201*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
202*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--generate-test-profile=" + filename);
203*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--generate-test-profile-seed=0");
204*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--apk=" + GetLibCoreDexFileNames()[0]);
205*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--dex-location=" + GetLibCoreDexFileNames()[0]);
206*795d594fSAndroid Build Coastguard Worker std::string error;
207*795d594fSAndroid Build Coastguard Worker return ExecAndReturnCode(argv_str, &error);
208*795d594fSAndroid Build Coastguard Worker }
209*795d594fSAndroid Build Coastguard Worker
CreateProfile(const std::string & profile_file_contents,const std::string & filename,const std::string & dex_location,bool for_boot_image=false)210*795d594fSAndroid Build Coastguard Worker bool CreateProfile(const std::string& profile_file_contents,
211*795d594fSAndroid Build Coastguard Worker const std::string& filename,
212*795d594fSAndroid Build Coastguard Worker const std::string& dex_location,
213*795d594fSAndroid Build Coastguard Worker bool for_boot_image = false) {
214*795d594fSAndroid Build Coastguard Worker ScratchFile class_names_file;
215*795d594fSAndroid Build Coastguard Worker File* file = class_names_file.GetFile();
216*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(file->WriteFully(profile_file_contents.c_str(), profile_file_contents.length()));
217*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(0, file->Flush());
218*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
219*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
220*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
221*795d594fSAndroid Build Coastguard Worker argv_str.push_back(for_boot_image ? "--output-profile-type=boot" : "--output-profile-type=app");
222*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--create-profile-from=" + class_names_file.GetFilename());
223*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--reference-profile-file=" + filename);
224*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--apk=" + dex_location);
225*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--dex-location=" + dex_location);
226*795d594fSAndroid Build Coastguard Worker std::string error;
227*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ExecAndReturnCode(argv_str, &error), 0) << error;
228*795d594fSAndroid Build Coastguard Worker return true;
229*795d594fSAndroid Build Coastguard Worker }
230*795d594fSAndroid Build Coastguard Worker
RunProfman(const std::string & filename,std::vector<std::string> & extra_args,std::string * output,std::string_view target_apk)231*795d594fSAndroid Build Coastguard Worker bool RunProfman(const std::string& filename,
232*795d594fSAndroid Build Coastguard Worker std::vector<std::string>& extra_args,
233*795d594fSAndroid Build Coastguard Worker std::string* output,
234*795d594fSAndroid Build Coastguard Worker std::string_view target_apk) {
235*795d594fSAndroid Build Coastguard Worker ScratchFile output_file;
236*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
237*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
238*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
239*795d594fSAndroid Build Coastguard Worker argv_str.insert(argv_str.end(), extra_args.begin(), extra_args.end());
240*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--profile-file=" + filename);
241*795d594fSAndroid Build Coastguard Worker argv_str.push_back(std::string("--apk=").append(target_apk));
242*795d594fSAndroid Build Coastguard Worker argv_str.push_back(std::string("--dex-location=").append(target_apk));
243*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--dump-output-to-fd=" + std::to_string(GetFd(output_file)));
244*795d594fSAndroid Build Coastguard Worker std::string error;
245*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ExecAndReturnCode(argv_str, &error), 0) << error;
246*795d594fSAndroid Build Coastguard Worker File* file = output_file.GetFile();
247*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(0, file->Flush());
248*795d594fSAndroid Build Coastguard Worker int64_t length = file->GetLength();
249*795d594fSAndroid Build Coastguard Worker std::unique_ptr<char[]> buf(new char[length]);
250*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(file->Read(buf.get(), length, 0), length);
251*795d594fSAndroid Build Coastguard Worker *output = std::string(buf.get(), length);
252*795d594fSAndroid Build Coastguard Worker return true;
253*795d594fSAndroid Build Coastguard Worker }
254*795d594fSAndroid Build Coastguard Worker
DumpClassesAndMethods(const std::string & filename,std::string * file_contents,std::optional<const std::string_view> target=std::nullopt)255*795d594fSAndroid Build Coastguard Worker bool DumpClassesAndMethods(const std::string& filename,
256*795d594fSAndroid Build Coastguard Worker std::string* file_contents,
257*795d594fSAndroid Build Coastguard Worker std::optional<const std::string_view> target = std::nullopt) {
258*795d594fSAndroid Build Coastguard Worker std::vector<std::string> extra_args;
259*795d594fSAndroid Build Coastguard Worker extra_args.push_back("--dump-classes-and-methods");
260*795d594fSAndroid Build Coastguard Worker return RunProfman(
261*795d594fSAndroid Build Coastguard Worker filename, extra_args, file_contents, target.value_or(GetLibCoreDexFileNames()[0]));
262*795d594fSAndroid Build Coastguard Worker }
263*795d594fSAndroid Build Coastguard Worker
DumpOnly(const std::string & filename,std::string * file_contents)264*795d594fSAndroid Build Coastguard Worker bool DumpOnly(const std::string& filename, std::string* file_contents) {
265*795d594fSAndroid Build Coastguard Worker std::vector<std::string> extra_args;
266*795d594fSAndroid Build Coastguard Worker extra_args.push_back("--dump-only");
267*795d594fSAndroid Build Coastguard Worker return RunProfman(filename, extra_args, file_contents, GetLibCoreDexFileNames()[0]);
268*795d594fSAndroid Build Coastguard Worker }
269*795d594fSAndroid Build Coastguard Worker
CreateAndDump(const std::string & input_file_contents,std::string * output_file_contents,const std::optional<const std::string> & target=std::nullopt)270*795d594fSAndroid Build Coastguard Worker bool CreateAndDump(const std::string& input_file_contents,
271*795d594fSAndroid Build Coastguard Worker std::string* output_file_contents,
272*795d594fSAndroid Build Coastguard Worker const std::optional<const std::string>& target = std::nullopt) {
273*795d594fSAndroid Build Coastguard Worker ScratchFile profile_file;
274*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(CreateProfile(input_file_contents,
275*795d594fSAndroid Build Coastguard Worker profile_file.GetFilename(),
276*795d594fSAndroid Build Coastguard Worker target.value_or(GetLibCoreDexFileNames()[0])));
277*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(DumpClassesAndMethods(profile_file.GetFilename(), output_file_contents, target));
278*795d594fSAndroid Build Coastguard Worker return true;
279*795d594fSAndroid Build Coastguard Worker }
280*795d594fSAndroid Build Coastguard Worker
GetClass(ScopedObjectAccess & soa,jobject class_loader,const std::string & clazz)281*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> GetClass(ScopedObjectAccess& soa,
282*795d594fSAndroid Build Coastguard Worker jobject class_loader,
283*795d594fSAndroid Build Coastguard Worker const std::string& clazz) REQUIRES_SHARED(Locks::mutator_lock_) {
284*795d594fSAndroid Build Coastguard Worker ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
285*795d594fSAndroid Build Coastguard Worker StackHandleScope<1> hs(soa.Self());
286*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> h_loader(hs.NewHandle(
287*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::ClassLoader>::DownCast(soa.Self()->DecodeJObject(class_loader))));
288*795d594fSAndroid Build Coastguard Worker return FindClass(clazz.c_str(), h_loader);
289*795d594fSAndroid Build Coastguard Worker }
290*795d594fSAndroid Build Coastguard Worker
GetVirtualMethod(jobject class_loader,const std::string & clazz,const std::string & name)291*795d594fSAndroid Build Coastguard Worker ArtMethod* GetVirtualMethod(jobject class_loader,
292*795d594fSAndroid Build Coastguard Worker const std::string& clazz,
293*795d594fSAndroid Build Coastguard Worker const std::string& name) {
294*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
295*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> klass = GetClass(soa, class_loader, clazz);
296*795d594fSAndroid Build Coastguard Worker ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
297*795d594fSAndroid Build Coastguard Worker const auto pointer_size = class_linker->GetImagePointerSize();
298*795d594fSAndroid Build Coastguard Worker ArtMethod* method = nullptr;
299*795d594fSAndroid Build Coastguard Worker for (auto& m : klass->GetVirtualMethods(pointer_size)) {
300*795d594fSAndroid Build Coastguard Worker if (name == m.GetName()) {
301*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(method == nullptr);
302*795d594fSAndroid Build Coastguard Worker method = &m;
303*795d594fSAndroid Build Coastguard Worker }
304*795d594fSAndroid Build Coastguard Worker }
305*795d594fSAndroid Build Coastguard Worker return method;
306*795d594fSAndroid Build Coastguard Worker }
307*795d594fSAndroid Build Coastguard Worker
MakeTypeReference(ObjPtr<mirror::Class> klass)308*795d594fSAndroid Build Coastguard Worker static TypeReference MakeTypeReference(ObjPtr<mirror::Class> klass)
309*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
310*795d594fSAndroid Build Coastguard Worker return TypeReference(&klass->GetDexFile(), klass->GetDexTypeIndex());
311*795d594fSAndroid Build Coastguard Worker }
312*795d594fSAndroid Build Coastguard Worker
313*795d594fSAndroid Build Coastguard Worker // Find the first dex-pc in the given method after 'start_pc' (if given) which
314*795d594fSAndroid Build Coastguard Worker // contains a call to any method of 'klass'. If 'start_pc' is not given we
315*795d594fSAndroid Build Coastguard Worker // will search from the first dex-pc.
GetDexPcOfCallTo(ArtMethod * method,Handle<mirror::Class> klass,std::optional<uint32_t> start_pc=std::nullopt)316*795d594fSAndroid Build Coastguard Worker uint16_t GetDexPcOfCallTo(ArtMethod* method,
317*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> klass,
318*795d594fSAndroid Build Coastguard Worker std::optional<uint32_t> start_pc = std::nullopt)
319*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
320*795d594fSAndroid Build Coastguard Worker const DexFile* dex_file = method->GetDexFile();
321*795d594fSAndroid Build Coastguard Worker for (const DexInstructionPcPair& inst :
322*795d594fSAndroid Build Coastguard Worker CodeItemInstructionAccessor(*dex_file, method->GetCodeItem())) {
323*795d594fSAndroid Build Coastguard Worker if (start_pc && inst.DexPc() <= *start_pc) {
324*795d594fSAndroid Build Coastguard Worker continue;
325*795d594fSAndroid Build Coastguard Worker } else if (inst->IsInvoke()) {
326*795d594fSAndroid Build Coastguard Worker const dex::MethodId& method_id = dex_file->GetMethodId(inst->VRegB());
327*795d594fSAndroid Build Coastguard Worker std::string_view desc(
328*795d594fSAndroid Build Coastguard Worker dex_file->GetTypeDescriptor(dex_file->GetTypeId(method_id.class_idx_)));
329*795d594fSAndroid Build Coastguard Worker std::string scratch;
330*795d594fSAndroid Build Coastguard Worker if (desc == klass->GetDescriptor(&scratch)) {
331*795d594fSAndroid Build Coastguard Worker return inst.DexPc();
332*795d594fSAndroid Build Coastguard Worker }
333*795d594fSAndroid Build Coastguard Worker }
334*795d594fSAndroid Build Coastguard Worker }
335*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(false) << "Unable to find dex-pc in " << method->PrettyMethod() << " for call to "
336*795d594fSAndroid Build Coastguard Worker << klass->PrettyClass()
337*795d594fSAndroid Build Coastguard Worker << " after dexpc: " << (start_pc ? static_cast<int64_t>(*start_pc) : -1);
338*795d594fSAndroid Build Coastguard Worker return -1;
339*795d594fSAndroid Build Coastguard Worker }
340*795d594fSAndroid Build Coastguard Worker
AssertInlineCaches(ArtMethod * method,uint16_t dex_pc,const TypeReferenceSet & expected_classes,const ProfileCompilationInfo & info,bool is_megamorphic,bool is_missing_types)341*795d594fSAndroid Build Coastguard Worker void AssertInlineCaches(ArtMethod* method,
342*795d594fSAndroid Build Coastguard Worker uint16_t dex_pc,
343*795d594fSAndroid Build Coastguard Worker const TypeReferenceSet& expected_classes,
344*795d594fSAndroid Build Coastguard Worker const ProfileCompilationInfo& info,
345*795d594fSAndroid Build Coastguard Worker bool is_megamorphic,
346*795d594fSAndroid Build Coastguard Worker bool is_missing_types)
347*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
348*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness hotness =
349*795d594fSAndroid Build Coastguard Worker info.GetMethodHotness(MethodReference(method->GetDexFile(), method->GetDexMethodIndex()));
350*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(hotness.IsHot());
351*795d594fSAndroid Build Coastguard Worker const ProfileCompilationInfo::InlineCacheMap* inline_caches = hotness.GetInlineCacheMap();
352*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inline_caches->find(dex_pc) != inline_caches->end());
353*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(expected_classes,
354*795d594fSAndroid Build Coastguard Worker info,
355*795d594fSAndroid Build Coastguard Worker method,
356*795d594fSAndroid Build Coastguard Worker inline_caches->find(dex_pc)->second,
357*795d594fSAndroid Build Coastguard Worker is_megamorphic,
358*795d594fSAndroid Build Coastguard Worker is_missing_types);
359*795d594fSAndroid Build Coastguard Worker }
AssertInlineCaches(ArtMethod * method,const TypeReferenceSet & expected_classes,const ProfileCompilationInfo & info,bool is_megamorphic,bool is_missing_types)360*795d594fSAndroid Build Coastguard Worker void AssertInlineCaches(ArtMethod* method,
361*795d594fSAndroid Build Coastguard Worker const TypeReferenceSet& expected_classes,
362*795d594fSAndroid Build Coastguard Worker const ProfileCompilationInfo& info,
363*795d594fSAndroid Build Coastguard Worker bool is_megamorphic,
364*795d594fSAndroid Build Coastguard Worker bool is_missing_types)
365*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
366*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness hotness =
367*795d594fSAndroid Build Coastguard Worker info.GetMethodHotness(MethodReference(method->GetDexFile(), method->GetDexMethodIndex()));
368*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(hotness.IsHot());
369*795d594fSAndroid Build Coastguard Worker const ProfileCompilationInfo::InlineCacheMap* inline_caches = hotness.GetInlineCacheMap();
370*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inline_caches->size(), 1u);
371*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(expected_classes,
372*795d594fSAndroid Build Coastguard Worker info,
373*795d594fSAndroid Build Coastguard Worker method,
374*795d594fSAndroid Build Coastguard Worker inline_caches->begin()->second,
375*795d594fSAndroid Build Coastguard Worker is_megamorphic,
376*795d594fSAndroid Build Coastguard Worker is_missing_types);
377*795d594fSAndroid Build Coastguard Worker }
378*795d594fSAndroid Build Coastguard Worker
AssertInlineCaches(const TypeReferenceSet & expected_clases,const ProfileCompilationInfo & info,ArtMethod * method,const ProfileCompilationInfo::DexPcData & dex_pc_data,bool is_megamorphic,bool is_missing_types)379*795d594fSAndroid Build Coastguard Worker void AssertInlineCaches(const TypeReferenceSet& expected_clases,
380*795d594fSAndroid Build Coastguard Worker const ProfileCompilationInfo& info,
381*795d594fSAndroid Build Coastguard Worker ArtMethod* method,
382*795d594fSAndroid Build Coastguard Worker const ProfileCompilationInfo::DexPcData& dex_pc_data,
383*795d594fSAndroid Build Coastguard Worker bool is_megamorphic,
384*795d594fSAndroid Build Coastguard Worker bool is_missing_types)
385*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
386*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(dex_pc_data.is_megamorphic, is_megamorphic);
387*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(dex_pc_data.is_missing_types, is_missing_types);
388*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(expected_clases.size(), dex_pc_data.classes.size());
389*795d594fSAndroid Build Coastguard Worker const DexFile* dex_file = method->GetDexFile();
390*795d594fSAndroid Build Coastguard Worker size_t found = 0;
391*795d594fSAndroid Build Coastguard Worker for (const TypeReference& type_ref : expected_clases) {
392*795d594fSAndroid Build Coastguard Worker if (type_ref.dex_file == dex_file) {
393*795d594fSAndroid Build Coastguard Worker CHECK_LT(type_ref.TypeIndex().index_, dex_file->NumTypeIds());
394*795d594fSAndroid Build Coastguard Worker for (dex::TypeIndex type_index : dex_pc_data.classes) {
395*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(type_index.IsValid());
396*795d594fSAndroid Build Coastguard Worker if (type_ref.TypeIndex() == type_index) {
397*795d594fSAndroid Build Coastguard Worker ++found;
398*795d594fSAndroid Build Coastguard Worker }
399*795d594fSAndroid Build Coastguard Worker }
400*795d594fSAndroid Build Coastguard Worker } else {
401*795d594fSAndroid Build Coastguard Worker // Match by descriptor.
402*795d594fSAndroid Build Coastguard Worker const char* expected_descriptor =
403*795d594fSAndroid Build Coastguard Worker type_ref.dex_file->GetTypeDescriptor(type_ref.TypeIndex());
404*795d594fSAndroid Build Coastguard Worker for (dex::TypeIndex type_index : dex_pc_data.classes) {
405*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(type_index.IsValid());
406*795d594fSAndroid Build Coastguard Worker const char* descriptor = info.GetTypeDescriptor(dex_file, type_index);
407*795d594fSAndroid Build Coastguard Worker if (strcmp(expected_descriptor, descriptor) == 0) {
408*795d594fSAndroid Build Coastguard Worker ++found;
409*795d594fSAndroid Build Coastguard Worker }
410*795d594fSAndroid Build Coastguard Worker }
411*795d594fSAndroid Build Coastguard Worker }
412*795d594fSAndroid Build Coastguard Worker }
413*795d594fSAndroid Build Coastguard Worker
414*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(expected_clases.size(), found);
415*795d594fSAndroid Build Coastguard Worker }
416*795d594fSAndroid Build Coastguard Worker
CheckCompilationMethodPercentChange(uint16_t methods_in_cur_profile,uint16_t methods_in_ref_profile,const std::vector<std::string> & extra_args=std::vector<std::string> ())417*795d594fSAndroid Build Coastguard Worker int CheckCompilationMethodPercentChange(uint16_t methods_in_cur_profile,
418*795d594fSAndroid Build Coastguard Worker uint16_t methods_in_ref_profile,
419*795d594fSAndroid Build Coastguard Worker const std::vector<std::string>& extra_args =
420*795d594fSAndroid Build Coastguard Worker std::vector<std::string>()) {
421*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
422*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
423*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({ GetFd(profile)});
424*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
425*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> hot_methods_cur;
426*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> hot_methods_ref;
427*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> empty_vector;
428*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < methods_in_cur_profile; ++i) {
429*795d594fSAndroid Build Coastguard Worker hot_methods_cur.push_back(i);
430*795d594fSAndroid Build Coastguard Worker }
431*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < methods_in_ref_profile; ++i) {
432*795d594fSAndroid Build Coastguard Worker hot_methods_ref.push_back(i);
433*795d594fSAndroid Build Coastguard Worker }
434*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
435*795d594fSAndroid Build Coastguard Worker SetupBasicProfile(dex1, hot_methods_cur, empty_vector, empty_vector,
436*795d594fSAndroid Build Coastguard Worker profile, &info1);
437*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
438*795d594fSAndroid Build Coastguard Worker SetupBasicProfile(dex1, hot_methods_ref, empty_vector, empty_vector,
439*795d594fSAndroid Build Coastguard Worker reference_profile, &info2);
440*795d594fSAndroid Build Coastguard Worker return ProcessProfiles(profile_fds, reference_profile_fd, extra_args);
441*795d594fSAndroid Build Coastguard Worker }
442*795d594fSAndroid Build Coastguard Worker
CheckCompilationClassPercentChange(uint16_t classes_in_cur_profile,uint16_t classes_in_ref_profile,const std::vector<std::string> & extra_args=std::vector<std::string> ())443*795d594fSAndroid Build Coastguard Worker int CheckCompilationClassPercentChange(uint16_t classes_in_cur_profile,
444*795d594fSAndroid Build Coastguard Worker uint16_t classes_in_ref_profile,
445*795d594fSAndroid Build Coastguard Worker const std::vector<std::string>& extra_args =
446*795d594fSAndroid Build Coastguard Worker std::vector<std::string>()) {
447*795d594fSAndroid Build Coastguard Worker uint16_t max_classes = std::max(classes_in_cur_profile, classes_in_ref_profile);
448*795d594fSAndroid Build Coastguard Worker const DexFile* dex1_x = BuildDex("location1_x",
449*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 0x101,
450*795d594fSAndroid Build Coastguard Worker "LUnique1_x;",
451*795d594fSAndroid Build Coastguard Worker /*num_method_ids=*/ 0,
452*795d594fSAndroid Build Coastguard Worker max_classes);
453*795d594fSAndroid Build Coastguard Worker const DexFile* dex2_x = BuildDex("location2_x",
454*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 0x102,
455*795d594fSAndroid Build Coastguard Worker "LUnique2_x;",
456*795d594fSAndroid Build Coastguard Worker /*num_method_ids=*/ 0,
457*795d594fSAndroid Build Coastguard Worker max_classes);
458*795d594fSAndroid Build Coastguard Worker
459*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
460*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
461*795d594fSAndroid Build Coastguard Worker
462*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({ GetFd(profile)});
463*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
464*795d594fSAndroid Build Coastguard Worker
465*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
466*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1_x, dex2_x, 0, classes_in_cur_profile, profile, &info1);
467*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
468*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1_x, dex2_x, 0, classes_in_ref_profile, reference_profile, &info2);
469*795d594fSAndroid Build Coastguard Worker return ProcessProfiles(profile_fds, reference_profile_fd, extra_args);
470*795d594fSAndroid Build Coastguard Worker }
471*795d594fSAndroid Build Coastguard Worker
472*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ArenaAllocator> allocator_;
473*795d594fSAndroid Build Coastguard Worker
474*795d594fSAndroid Build Coastguard Worker const DexFile* dex1;
475*795d594fSAndroid Build Coastguard Worker const DexFile* dex2;
476*795d594fSAndroid Build Coastguard Worker const DexFile* dex3;
477*795d594fSAndroid Build Coastguard Worker const DexFile* dex4;
478*795d594fSAndroid Build Coastguard Worker const DexFile* dex1_checksum_missmatch;
479*795d594fSAndroid Build Coastguard Worker };
480*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,AdviseCompilationEmptyReferences)481*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, AdviseCompilationEmptyReferences) {
482*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
483*795d594fSAndroid Build Coastguard Worker ScratchFile profile2;
484*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
485*795d594fSAndroid Build Coastguard Worker
486*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({
487*795d594fSAndroid Build Coastguard Worker GetFd(profile1),
488*795d594fSAndroid Build Coastguard Worker GetFd(profile2)});
489*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
490*795d594fSAndroid Build Coastguard Worker
491*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsToEnableCompilation = 100;
492*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
493*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1, dex2, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
494*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
495*795d594fSAndroid Build Coastguard Worker SetupProfile(dex3, dex4, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
496*795d594fSAndroid Build Coastguard Worker
497*795d594fSAndroid Build Coastguard Worker // We should advise compilation.
498*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProfmanResult::kCompile, ProcessProfiles(profile_fds, reference_profile_fd));
499*795d594fSAndroid Build Coastguard Worker // The resulting compilation info must be equal to the merge of the inputs.
500*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result;
501*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(reference_profile_fd));
502*795d594fSAndroid Build Coastguard Worker
503*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo expected;
504*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.MergeWith(info1));
505*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.MergeWith(info2));
506*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.Equals(result));
507*795d594fSAndroid Build Coastguard Worker
508*795d594fSAndroid Build Coastguard Worker // The information from profiles must remain the same.
509*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile1, info1);
510*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile2, info2);
511*795d594fSAndroid Build Coastguard Worker }
512*795d594fSAndroid Build Coastguard Worker
513*795d594fSAndroid Build Coastguard Worker // TODO(calin): Add more tests for classes.
TEST_F(ProfileAssistantTest,AdviseCompilationEmptyReferencesBecauseOfClasses)514*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, AdviseCompilationEmptyReferencesBecauseOfClasses) {
515*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfClassesToEnableCompilation = 100;
516*795d594fSAndroid Build Coastguard Worker const DexFile* dex1_100 = BuildDex("location1_100",
517*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 101,
518*795d594fSAndroid Build Coastguard Worker "LUnique1_100;",
519*795d594fSAndroid Build Coastguard Worker /*num_method_ids=*/ 0,
520*795d594fSAndroid Build Coastguard Worker /*num_class_ids=*/ 100);
521*795d594fSAndroid Build Coastguard Worker const DexFile* dex2_100 = BuildDex("location2_100",
522*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 102,
523*795d594fSAndroid Build Coastguard Worker "LUnique2_100;",
524*795d594fSAndroid Build Coastguard Worker /*num_method_ids=*/ 0,
525*795d594fSAndroid Build Coastguard Worker /*num_class_ids=*/ 100);
526*795d594fSAndroid Build Coastguard Worker
527*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
528*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
529*795d594fSAndroid Build Coastguard Worker
530*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({
531*795d594fSAndroid Build Coastguard Worker GetFd(profile1)});
532*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
533*795d594fSAndroid Build Coastguard Worker
534*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
535*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1_100, dex2_100, 0, kNumberOfClassesToEnableCompilation, profile1, &info1);
536*795d594fSAndroid Build Coastguard Worker
537*795d594fSAndroid Build Coastguard Worker // We should advise compilation.
538*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProfmanResult::kCompile, ProcessProfiles(profile_fds, reference_profile_fd));
539*795d594fSAndroid Build Coastguard Worker // The resulting compilation info must be equal to the merge of the inputs.
540*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result;
541*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(reference_profile_fd));
542*795d594fSAndroid Build Coastguard Worker
543*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo expected;
544*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.MergeWith(info1));
545*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.Equals(result));
546*795d594fSAndroid Build Coastguard Worker
547*795d594fSAndroid Build Coastguard Worker // The information from profiles must remain the same.
548*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile1, info1);
549*795d594fSAndroid Build Coastguard Worker }
550*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,AdviseCompilationNonEmptyReferences)551*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, AdviseCompilationNonEmptyReferences) {
552*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
553*795d594fSAndroid Build Coastguard Worker ScratchFile profile2;
554*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
555*795d594fSAndroid Build Coastguard Worker
556*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({
557*795d594fSAndroid Build Coastguard Worker GetFd(profile1),
558*795d594fSAndroid Build Coastguard Worker GetFd(profile2)});
559*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
560*795d594fSAndroid Build Coastguard Worker
561*795d594fSAndroid Build Coastguard Worker // The new profile info will contain the methods with indices 0-100.
562*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsToEnableCompilation = 100;
563*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
564*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1, dex2, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
565*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
566*795d594fSAndroid Build Coastguard Worker SetupProfile(dex3, dex4, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
567*795d594fSAndroid Build Coastguard Worker
568*795d594fSAndroid Build Coastguard Worker
569*795d594fSAndroid Build Coastguard Worker // The reference profile info will contain the methods with indices 50-150.
570*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsAlreadyCompiled = 100;
571*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo reference_info;
572*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1, dex2, kNumberOfMethodsAlreadyCompiled, 0, reference_profile,
573*795d594fSAndroid Build Coastguard Worker &reference_info, kNumberOfMethodsToEnableCompilation / 2);
574*795d594fSAndroid Build Coastguard Worker
575*795d594fSAndroid Build Coastguard Worker // We should advise compilation.
576*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProfmanResult::kCompile, ProcessProfiles(profile_fds, reference_profile_fd));
577*795d594fSAndroid Build Coastguard Worker
578*795d594fSAndroid Build Coastguard Worker // The resulting compilation info must be equal to the merge of the inputs
579*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result;
580*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(reference_profile_fd));
581*795d594fSAndroid Build Coastguard Worker
582*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo expected;
583*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.MergeWith(info1));
584*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.MergeWith(info2));
585*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.MergeWith(reference_info));
586*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.Equals(result));
587*795d594fSAndroid Build Coastguard Worker
588*795d594fSAndroid Build Coastguard Worker // The information from profiles must remain the same.
589*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile1, info1);
590*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile2, info2);
591*795d594fSAndroid Build Coastguard Worker }
592*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,DoNotAdviseCompilationEmptyProfile)593*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, DoNotAdviseCompilationEmptyProfile) {
594*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
595*795d594fSAndroid Build Coastguard Worker ScratchFile profile2;
596*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
597*795d594fSAndroid Build Coastguard Worker
598*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({
599*795d594fSAndroid Build Coastguard Worker GetFd(profile1),
600*795d594fSAndroid Build Coastguard Worker GetFd(profile2)});
601*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
602*795d594fSAndroid Build Coastguard Worker
603*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
604*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1, dex2, /*number_of_methods=*/ 0, /*number_of_classes*/ 0, profile1, &info1);
605*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
606*795d594fSAndroid Build Coastguard Worker SetupProfile(dex3, dex4, /*number_of_methods=*/ 0, /*number_of_classes*/ 0, profile2, &info2);
607*795d594fSAndroid Build Coastguard Worker
608*795d594fSAndroid Build Coastguard Worker // We should not advise compilation.
609*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProfmanResult::kSkipCompilationEmptyProfiles,
610*795d594fSAndroid Build Coastguard Worker ProcessProfiles(profile_fds, reference_profile_fd));
611*795d594fSAndroid Build Coastguard Worker
612*795d594fSAndroid Build Coastguard Worker // The information from profiles must remain the same.
613*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo file_info1;
614*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(file_info1.Load(GetFd(profile1)));
615*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(file_info1.Equals(info1));
616*795d594fSAndroid Build Coastguard Worker
617*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo file_info2;
618*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(file_info2.Load(GetFd(profile2)));
619*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(file_info2.Equals(info2));
620*795d594fSAndroid Build Coastguard Worker
621*795d594fSAndroid Build Coastguard Worker // Reference profile files must remain empty.
622*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, reference_profile.GetFile()->GetLength());
623*795d594fSAndroid Build Coastguard Worker
624*795d594fSAndroid Build Coastguard Worker // The information from profiles must remain the same.
625*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile1, info1);
626*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile2, info2);
627*795d594fSAndroid Build Coastguard Worker }
628*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,DoNotAdviseCompilation)629*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, DoNotAdviseCompilation) {
630*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
631*795d594fSAndroid Build Coastguard Worker ScratchFile profile2;
632*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
633*795d594fSAndroid Build Coastguard Worker
634*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({
635*795d594fSAndroid Build Coastguard Worker GetFd(profile1),
636*795d594fSAndroid Build Coastguard Worker GetFd(profile2)});
637*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
638*795d594fSAndroid Build Coastguard Worker
639*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsToSkipCompilation = 24; // Threshold is 100.
640*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
641*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1, dex2, kNumberOfMethodsToSkipCompilation, 0, profile1, &info1);
642*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
643*795d594fSAndroid Build Coastguard Worker SetupProfile(dex3, dex4, kNumberOfMethodsToSkipCompilation, 0, profile2, &info2);
644*795d594fSAndroid Build Coastguard Worker
645*795d594fSAndroid Build Coastguard Worker // We should not advise compilation.
646*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProfmanResult::kSkipCompilationSmallDelta,
647*795d594fSAndroid Build Coastguard Worker ProcessProfiles(profile_fds, reference_profile_fd));
648*795d594fSAndroid Build Coastguard Worker
649*795d594fSAndroid Build Coastguard Worker // The information from profiles must remain the same.
650*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo file_info1;
651*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(file_info1.Load(GetFd(profile1)));
652*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(file_info1.Equals(info1));
653*795d594fSAndroid Build Coastguard Worker
654*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo file_info2;
655*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(file_info2.Load(GetFd(profile2)));
656*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(file_info2.Equals(info2));
657*795d594fSAndroid Build Coastguard Worker
658*795d594fSAndroid Build Coastguard Worker // Reference profile files must remain empty.
659*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, reference_profile.GetFile()->GetLength());
660*795d594fSAndroid Build Coastguard Worker
661*795d594fSAndroid Build Coastguard Worker // The information from profiles must remain the same.
662*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile1, info1);
663*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile2, info2);
664*795d594fSAndroid Build Coastguard Worker }
665*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,DoNotAdviseCompilationMethodPercentage)666*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, DoNotAdviseCompilationMethodPercentage) {
667*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsInRefProfile = 6000;
668*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsInCurProfile = 6100; // Threshold is 2%.
669*795d594fSAndroid Build Coastguard Worker std::vector<std::string> extra_args({"--min-new-methods-percent-change=2"});
670*795d594fSAndroid Build Coastguard Worker
671*795d594fSAndroid Build Coastguard Worker // We should not advise compilation.
672*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProfmanResult::kSkipCompilationSmallDelta,
673*795d594fSAndroid Build Coastguard Worker CheckCompilationMethodPercentChange(
674*795d594fSAndroid Build Coastguard Worker kNumberOfMethodsInCurProfile, kNumberOfMethodsInRefProfile, extra_args));
675*795d594fSAndroid Build Coastguard Worker }
676*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,ShouldAdviseCompilationMethodPercentage)677*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, ShouldAdviseCompilationMethodPercentage) {
678*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsInRefProfile = 6000;
679*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsInCurProfile = 6200; // Threshold is 2%.
680*795d594fSAndroid Build Coastguard Worker std::vector<std::string> extra_args({"--min-new-methods-percent-change=2"});
681*795d594fSAndroid Build Coastguard Worker
682*795d594fSAndroid Build Coastguard Worker // We should advise compilation.
683*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProfmanResult::kCompile,
684*795d594fSAndroid Build Coastguard Worker CheckCompilationMethodPercentChange(
685*795d594fSAndroid Build Coastguard Worker kNumberOfMethodsInCurProfile, kNumberOfMethodsInRefProfile, extra_args));
686*795d594fSAndroid Build Coastguard Worker }
687*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,DoNotAdviseCompilationClassPercentage)688*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, DoNotAdviseCompilationClassPercentage) {
689*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfClassesInRefProfile = 6000;
690*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfClassesInCurProfile = 6110; // Threshold is 2%.
691*795d594fSAndroid Build Coastguard Worker std::vector<std::string> extra_args({"--min-new-classes-percent-change=2"});
692*795d594fSAndroid Build Coastguard Worker
693*795d594fSAndroid Build Coastguard Worker // We should not advise compilation.
694*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProfmanResult::kSkipCompilationSmallDelta,
695*795d594fSAndroid Build Coastguard Worker CheckCompilationClassPercentChange(
696*795d594fSAndroid Build Coastguard Worker kNumberOfClassesInCurProfile, kNumberOfClassesInRefProfile, extra_args));
697*795d594fSAndroid Build Coastguard Worker }
698*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,ShouldAdviseCompilationClassPercentage)699*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, ShouldAdviseCompilationClassPercentage) {
700*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfClassesInRefProfile = 6000;
701*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfClassesInCurProfile = 6120; // Threshold is 2%.
702*795d594fSAndroid Build Coastguard Worker std::vector<std::string> extra_args({"--min-new-classes-percent-change=2"});
703*795d594fSAndroid Build Coastguard Worker
704*795d594fSAndroid Build Coastguard Worker // We should advise compilation.
705*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProfmanResult::kCompile,
706*795d594fSAndroid Build Coastguard Worker CheckCompilationClassPercentChange(
707*795d594fSAndroid Build Coastguard Worker kNumberOfClassesInCurProfile, kNumberOfClassesInRefProfile, extra_args));
708*795d594fSAndroid Build Coastguard Worker }
709*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,FailProcessingBecauseOfProfiles)710*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, FailProcessingBecauseOfProfiles) {
711*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
712*795d594fSAndroid Build Coastguard Worker ScratchFile profile2;
713*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
714*795d594fSAndroid Build Coastguard Worker
715*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({
716*795d594fSAndroid Build Coastguard Worker GetFd(profile1),
717*795d594fSAndroid Build Coastguard Worker GetFd(profile2)});
718*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
719*795d594fSAndroid Build Coastguard Worker
720*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsToEnableCompilation = 100;
721*795d594fSAndroid Build Coastguard Worker // Assign different hashes for the same dex file. This will make merging of information to fail.
722*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
723*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1, dex2, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
724*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
725*795d594fSAndroid Build Coastguard Worker SetupProfile(
726*795d594fSAndroid Build Coastguard Worker dex1_checksum_missmatch, dex2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
727*795d594fSAndroid Build Coastguard Worker
728*795d594fSAndroid Build Coastguard Worker // We should fail processing.
729*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProfmanResult::kErrorBadProfiles, ProcessProfiles(profile_fds, reference_profile_fd));
730*795d594fSAndroid Build Coastguard Worker
731*795d594fSAndroid Build Coastguard Worker // The information from profiles must remain the same.
732*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile1, info1);
733*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile2, info2);
734*795d594fSAndroid Build Coastguard Worker
735*795d594fSAndroid Build Coastguard Worker // Reference profile files must still remain empty.
736*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, reference_profile.GetFile()->GetLength());
737*795d594fSAndroid Build Coastguard Worker }
738*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,FailProcessingBecauseOfReferenceProfiles)739*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, FailProcessingBecauseOfReferenceProfiles) {
740*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
741*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
742*795d594fSAndroid Build Coastguard Worker
743*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({
744*795d594fSAndroid Build Coastguard Worker GetFd(profile1)});
745*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
746*795d594fSAndroid Build Coastguard Worker
747*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsToEnableCompilation = 100;
748*795d594fSAndroid Build Coastguard Worker // Assign different hashes for the same dex file. This will make merging of information to fail.
749*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
750*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1, dex2, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
751*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo reference_info;
752*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1_checksum_missmatch,
753*795d594fSAndroid Build Coastguard Worker dex2,
754*795d594fSAndroid Build Coastguard Worker kNumberOfMethodsToEnableCompilation,
755*795d594fSAndroid Build Coastguard Worker 0,
756*795d594fSAndroid Build Coastguard Worker reference_profile,
757*795d594fSAndroid Build Coastguard Worker &reference_info);
758*795d594fSAndroid Build Coastguard Worker
759*795d594fSAndroid Build Coastguard Worker // We should not advise compilation.
760*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProfmanResult::kErrorBadProfiles, ProcessProfiles(profile_fds, reference_profile_fd));
761*795d594fSAndroid Build Coastguard Worker
762*795d594fSAndroid Build Coastguard Worker // The information from profiles must remain the same.
763*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile1, info1);
764*795d594fSAndroid Build Coastguard Worker }
765*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestProfileGeneration)766*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestProfileGeneration) {
767*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
768*795d594fSAndroid Build Coastguard Worker // Generate a test profile.
769*795d594fSAndroid Build Coastguard Worker GenerateTestProfile(profile.GetFilename());
770*795d594fSAndroid Build Coastguard Worker
771*795d594fSAndroid Build Coastguard Worker // Verify that the generated profile is valid and can be loaded.
772*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
773*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Load(GetFd(profile)));
774*795d594fSAndroid Build Coastguard Worker }
775*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestProfileGenerationWithIndexDex)776*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestProfileGenerationWithIndexDex) {
777*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
778*795d594fSAndroid Build Coastguard Worker // Generate a test profile passing in a dex file as reference.
779*795d594fSAndroid Build Coastguard Worker GenerateTestProfileWithInputDex(profile.GetFilename());
780*795d594fSAndroid Build Coastguard Worker
781*795d594fSAndroid Build Coastguard Worker // Verify that the generated profile is valid and can be loaded.
782*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
783*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Load(GetFd(profile)));
784*795d594fSAndroid Build Coastguard Worker }
785*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestProfileCreationAllMatch)786*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestProfileCreationAllMatch) {
787*795d594fSAndroid Build Coastguard Worker // Class names put here need to be in sorted order.
788*795d594fSAndroid Build Coastguard Worker std::vector<std::string> class_names = {
789*795d594fSAndroid Build Coastguard Worker "HLjava/lang/Object;-><init>()V",
790*795d594fSAndroid Build Coastguard Worker "Ljava/lang/Comparable;",
791*795d594fSAndroid Build Coastguard Worker "Ljava/lang/Math;",
792*795d594fSAndroid Build Coastguard Worker "Ljava/lang/Object;",
793*795d594fSAndroid Build Coastguard Worker "SPLjava/lang/Comparable;->compareTo(Ljava/lang/Object;)I",
794*795d594fSAndroid Build Coastguard Worker "[[[[[[[[I", // No `TypeId`s in core-oj with this many array dimensions,
795*795d594fSAndroid Build Coastguard Worker "[[[[[[[[Ljava/lang/Object;", // "extra descriptors" shall be used for these array classes.
796*795d594fSAndroid Build Coastguard Worker };
797*795d594fSAndroid Build Coastguard Worker std::string file_contents;
798*795d594fSAndroid Build Coastguard Worker for (std::string& class_name : class_names) {
799*795d594fSAndroid Build Coastguard Worker file_contents += class_name + std::string("\n");
800*795d594fSAndroid Build Coastguard Worker }
801*795d594fSAndroid Build Coastguard Worker std::string output_file_contents;
802*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateAndDump(file_contents, &output_file_contents));
803*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(output_file_contents, file_contents);
804*795d594fSAndroid Build Coastguard Worker }
805*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestArrayClass)806*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestArrayClass) {
807*795d594fSAndroid Build Coastguard Worker std::vector<std::string> class_names = {
808*795d594fSAndroid Build Coastguard Worker "[Ljava/lang/Comparable;",
809*795d594fSAndroid Build Coastguard Worker };
810*795d594fSAndroid Build Coastguard Worker std::string file_contents;
811*795d594fSAndroid Build Coastguard Worker for (std::string& class_name : class_names) {
812*795d594fSAndroid Build Coastguard Worker file_contents += class_name + std::string("\n");
813*795d594fSAndroid Build Coastguard Worker }
814*795d594fSAndroid Build Coastguard Worker std::string output_file_contents;
815*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateAndDump(file_contents, &output_file_contents));
816*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(output_file_contents, file_contents);
817*795d594fSAndroid Build Coastguard Worker }
818*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestProfileCreationGenerateMethods)819*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestProfileCreationGenerateMethods) {
820*795d594fSAndroid Build Coastguard Worker // Class names put here need to be in sorted order.
821*795d594fSAndroid Build Coastguard Worker std::vector<std::string> class_names = {
822*795d594fSAndroid Build Coastguard Worker "HLjava/lang/Math;->*",
823*795d594fSAndroid Build Coastguard Worker };
824*795d594fSAndroid Build Coastguard Worker std::string input_file_contents;
825*795d594fSAndroid Build Coastguard Worker std::string expected_contents;
826*795d594fSAndroid Build Coastguard Worker for (std::string& class_name : class_names) {
827*795d594fSAndroid Build Coastguard Worker input_file_contents += class_name + std::string("\n");
828*795d594fSAndroid Build Coastguard Worker expected_contents += DescriptorToDot(class_name.c_str()) +
829*795d594fSAndroid Build Coastguard Worker std::string("\n");
830*795d594fSAndroid Build Coastguard Worker }
831*795d594fSAndroid Build Coastguard Worker std::string output_file_contents;
832*795d594fSAndroid Build Coastguard Worker ScratchFile profile_file;
833*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(CreateProfile(input_file_contents,
834*795d594fSAndroid Build Coastguard Worker profile_file.GetFilename(),
835*795d594fSAndroid Build Coastguard Worker GetLibCoreDexFileNames()[0]));
836*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
837*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Load(GetFd(profile_file)));
838*795d594fSAndroid Build Coastguard Worker // Verify that the profile has matching methods.
839*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
840*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> klass = GetClass(soa, /*class_loader=*/ nullptr, "Ljava/lang/Math;");
841*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(klass != nullptr);
842*795d594fSAndroid Build Coastguard Worker size_t method_count = 0;
843*795d594fSAndroid Build Coastguard Worker for (ArtMethod& method : klass->GetMethods(kRuntimePointerSize)) {
844*795d594fSAndroid Build Coastguard Worker if (!method.IsCopied() && method.GetCodeItem() != nullptr) {
845*795d594fSAndroid Build Coastguard Worker ++method_count;
846*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness hotness =
847*795d594fSAndroid Build Coastguard Worker info.GetMethodHotness(MethodReference(method.GetDexFile(), method.GetDexMethodIndex()));
848*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(hotness.IsHot()) << method.PrettyMethod();
849*795d594fSAndroid Build Coastguard Worker }
850*795d594fSAndroid Build Coastguard Worker }
851*795d594fSAndroid Build Coastguard Worker EXPECT_GT(method_count, 0u);
852*795d594fSAndroid Build Coastguard Worker }
853*795d594fSAndroid Build Coastguard Worker
JoinProfileLines(const std::vector<std::string> & lines)854*795d594fSAndroid Build Coastguard Worker static std::string JoinProfileLines(const std::vector<std::string>& lines) {
855*795d594fSAndroid Build Coastguard Worker std::string result = android::base::Join(lines, '\n');
856*795d594fSAndroid Build Coastguard Worker return result + '\n';
857*795d594fSAndroid Build Coastguard Worker }
858*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestBootImageProfile)859*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestBootImageProfile) {
860*795d594fSAndroid Build Coastguard Worker const std::string core_dex = GetLibCoreDexFileNames()[0];
861*795d594fSAndroid Build Coastguard Worker
862*795d594fSAndroid Build Coastguard Worker std::vector<ScratchFile> profiles;
863*795d594fSAndroid Build Coastguard Worker
864*795d594fSAndroid Build Coastguard Worker // In image with enough clean occurrences.
865*795d594fSAndroid Build Coastguard Worker const std::string kCleanClass = "Ljava/lang/CharSequence;";
866*795d594fSAndroid Build Coastguard Worker // In image with enough dirty occurrences.
867*795d594fSAndroid Build Coastguard Worker const std::string kDirtyClass = "Ljava/lang/Object;";
868*795d594fSAndroid Build Coastguard Worker // Not in image becauseof not enough occurrences.
869*795d594fSAndroid Build Coastguard Worker const std::string kUncommonCleanClass = "Ljava/lang/Process;";
870*795d594fSAndroid Build Coastguard Worker const std::string kUncommonDirtyClass = "Ljava/lang/Package;";
871*795d594fSAndroid Build Coastguard Worker // Method that is common and hot. Should end up in profile.
872*795d594fSAndroid Build Coastguard Worker const std::string kCommonHotMethod = "Ljava/lang/Comparable;->compareTo(Ljava/lang/Object;)I";
873*795d594fSAndroid Build Coastguard Worker // Uncommon method, should not end up in profile
874*795d594fSAndroid Build Coastguard Worker const std::string kUncommonMethod = "Ljava/util/HashMap;-><init>()V";
875*795d594fSAndroid Build Coastguard Worker // Method that gets marked as hot since it's in multiple profile and marked as startup.
876*795d594fSAndroid Build Coastguard Worker const std::string kStartupMethodForUpgrade = "Ljava/util/ArrayList;->clear()V";
877*795d594fSAndroid Build Coastguard Worker // Startup method used by a special package which will get a different threshold;
878*795d594fSAndroid Build Coastguard Worker const std::string kSpecialPackageStartupMethod =
879*795d594fSAndroid Build Coastguard Worker "Ljava/lang/Object;->toString()Ljava/lang/String;";
880*795d594fSAndroid Build Coastguard Worker // Method used by a special package which will get a different threshold;
881*795d594fSAndroid Build Coastguard Worker const std::string kUncommonSpecialPackageMethod = "Ljava/lang/Object;->hashCode()I";
882*795d594fSAndroid Build Coastguard Worker // Denylisted class
883*795d594fSAndroid Build Coastguard Worker const std::string kPreloadedDenylistedClass = "Ljava/lang/Thread;";
884*795d594fSAndroid Build Coastguard Worker
885*795d594fSAndroid Build Coastguard Worker // Thresholds for this test.
886*795d594fSAndroid Build Coastguard Worker static const size_t kDirtyThreshold = 100;
887*795d594fSAndroid Build Coastguard Worker static const size_t kCleanThreshold = 50;
888*795d594fSAndroid Build Coastguard Worker static const size_t kPreloadedThreshold = 100;
889*795d594fSAndroid Build Coastguard Worker static const size_t kMethodThreshold = 75;
890*795d594fSAndroid Build Coastguard Worker static const size_t kSpecialThreshold = 50;
891*795d594fSAndroid Build Coastguard Worker const std::string kSpecialPackage = "dex4";
892*795d594fSAndroid Build Coastguard Worker
893*795d594fSAndroid Build Coastguard Worker // Create boot profile content, attributing the classes and methods to different dex files.
894*795d594fSAndroid Build Coastguard Worker std::vector<std::string> input_data = {
895*795d594fSAndroid Build Coastguard Worker "{dex1}" + kCleanClass,
896*795d594fSAndroid Build Coastguard Worker "{dex1}" + kDirtyClass,
897*795d594fSAndroid Build Coastguard Worker "{dex1}" + kUncommonCleanClass,
898*795d594fSAndroid Build Coastguard Worker "{dex1}H" + kCommonHotMethod,
899*795d594fSAndroid Build Coastguard Worker "{dex1}P" + kStartupMethodForUpgrade,
900*795d594fSAndroid Build Coastguard Worker "{dex1}" + kUncommonDirtyClass,
901*795d594fSAndroid Build Coastguard Worker "{dex1}" + kPreloadedDenylistedClass,
902*795d594fSAndroid Build Coastguard Worker
903*795d594fSAndroid Build Coastguard Worker "{dex2}" + kCleanClass,
904*795d594fSAndroid Build Coastguard Worker "{dex2}" + kDirtyClass,
905*795d594fSAndroid Build Coastguard Worker "{dex2}P" + kCommonHotMethod,
906*795d594fSAndroid Build Coastguard Worker "{dex2}P" + kStartupMethodForUpgrade,
907*795d594fSAndroid Build Coastguard Worker "{dex2}" + kUncommonDirtyClass,
908*795d594fSAndroid Build Coastguard Worker "{dex2}" + kPreloadedDenylistedClass,
909*795d594fSAndroid Build Coastguard Worker
910*795d594fSAndroid Build Coastguard Worker "{dex3}P" + kUncommonMethod,
911*795d594fSAndroid Build Coastguard Worker "{dex3}PS" + kStartupMethodForUpgrade,
912*795d594fSAndroid Build Coastguard Worker "{dex3}S" + kCommonHotMethod,
913*795d594fSAndroid Build Coastguard Worker "{dex3}S" + kSpecialPackageStartupMethod,
914*795d594fSAndroid Build Coastguard Worker "{dex3}" + kDirtyClass,
915*795d594fSAndroid Build Coastguard Worker "{dex3}" + kPreloadedDenylistedClass,
916*795d594fSAndroid Build Coastguard Worker
917*795d594fSAndroid Build Coastguard Worker "{dex4}" + kDirtyClass,
918*795d594fSAndroid Build Coastguard Worker "{dex4}P" + kCommonHotMethod,
919*795d594fSAndroid Build Coastguard Worker "{dex4}S" + kSpecialPackageStartupMethod,
920*795d594fSAndroid Build Coastguard Worker "{dex4}P" + kUncommonSpecialPackageMethod,
921*795d594fSAndroid Build Coastguard Worker "{dex4}" + kPreloadedDenylistedClass,
922*795d594fSAndroid Build Coastguard Worker };
923*795d594fSAndroid Build Coastguard Worker std::string input_file_contents = JoinProfileLines(input_data);
924*795d594fSAndroid Build Coastguard Worker
925*795d594fSAndroid Build Coastguard Worker ScratchFile preloaded_class_denylist;
926*795d594fSAndroid Build Coastguard Worker std::string denylist_content = DescriptorToDot(kPreloadedDenylistedClass.c_str());
927*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(preloaded_class_denylist.GetFile()->WriteFully(
928*795d594fSAndroid Build Coastguard Worker denylist_content.c_str(), denylist_content.length()));
929*795d594fSAndroid Build Coastguard Worker
930*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(0, preloaded_class_denylist.GetFile()->Flush());
931*795d594fSAndroid Build Coastguard Worker // Expected data
932*795d594fSAndroid Build Coastguard Worker std::vector<std::string> expected_data = {
933*795d594fSAndroid Build Coastguard Worker kCleanClass,
934*795d594fSAndroid Build Coastguard Worker kDirtyClass,
935*795d594fSAndroid Build Coastguard Worker kPreloadedDenylistedClass,
936*795d594fSAndroid Build Coastguard Worker "HSP" + kCommonHotMethod,
937*795d594fSAndroid Build Coastguard Worker "HS" + kSpecialPackageStartupMethod,
938*795d594fSAndroid Build Coastguard Worker "HSP" + kStartupMethodForUpgrade
939*795d594fSAndroid Build Coastguard Worker };
940*795d594fSAndroid Build Coastguard Worker std::string expected_profile_content = JoinProfileLines(expected_data);
941*795d594fSAndroid Build Coastguard Worker
942*795d594fSAndroid Build Coastguard Worker std::vector<std::string> expected_preloaded_data = {
943*795d594fSAndroid Build Coastguard Worker DescriptorToDot(kDirtyClass.c_str())
944*795d594fSAndroid Build Coastguard Worker };
945*795d594fSAndroid Build Coastguard Worker std::string expected_preloaded_content = JoinProfileLines(expected_preloaded_data);
946*795d594fSAndroid Build Coastguard Worker
947*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
948*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(CreateProfile(input_file_contents,
949*795d594fSAndroid Build Coastguard Worker profile.GetFilename(),
950*795d594fSAndroid Build Coastguard Worker core_dex,
951*795d594fSAndroid Build Coastguard Worker /*for_boot_image=*/ true));
952*795d594fSAndroid Build Coastguard Worker
953*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo bootProfile(/*for_boot_image=*/ true);
954*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(bootProfile.Load(profile.GetFilename(), /*clear_if_invalid=*/ false));
955*795d594fSAndroid Build Coastguard Worker
956*795d594fSAndroid Build Coastguard Worker // Generate the boot profile.
957*795d594fSAndroid Build Coastguard Worker ScratchFile out_profile;
958*795d594fSAndroid Build Coastguard Worker ScratchFile out_preloaded_classes;
959*795d594fSAndroid Build Coastguard Worker std::vector<std::string> args;
960*795d594fSAndroid Build Coastguard Worker args.push_back(GetProfmanCmd());
961*795d594fSAndroid Build Coastguard Worker args.push_back("--generate-boot-image-profile");
962*795d594fSAndroid Build Coastguard Worker args.push_back("--class-threshold=" + std::to_string(kDirtyThreshold));
963*795d594fSAndroid Build Coastguard Worker args.push_back("--clean-class-threshold=" + std::to_string(kCleanThreshold));
964*795d594fSAndroid Build Coastguard Worker args.push_back("--method-threshold=" + std::to_string(kMethodThreshold));
965*795d594fSAndroid Build Coastguard Worker args.push_back("--preloaded-class-threshold=" + std::to_string(kPreloadedThreshold));
966*795d594fSAndroid Build Coastguard Worker args.push_back(
967*795d594fSAndroid Build Coastguard Worker "--special-package=" + kSpecialPackage + ":" + std::to_string(kSpecialThreshold));
968*795d594fSAndroid Build Coastguard Worker args.push_back("--profile-file=" + profile.GetFilename());
969*795d594fSAndroid Build Coastguard Worker args.push_back("--out-profile-path=" + out_profile.GetFilename());
970*795d594fSAndroid Build Coastguard Worker args.push_back("--out-preloaded-classes-path=" + out_preloaded_classes.GetFilename());
971*795d594fSAndroid Build Coastguard Worker args.push_back("--apk=" + core_dex);
972*795d594fSAndroid Build Coastguard Worker args.push_back("--dex-location=" + core_dex);
973*795d594fSAndroid Build Coastguard Worker args.push_back("--preloaded-classes-denylist=" + preloaded_class_denylist.GetFilename());
974*795d594fSAndroid Build Coastguard Worker
975*795d594fSAndroid Build Coastguard Worker std::string error;
976*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ExecAndReturnCode(args, &error), 0) << error;
977*795d594fSAndroid Build Coastguard Worker
978*795d594fSAndroid Build Coastguard Worker // Verify the boot profile contents.
979*795d594fSAndroid Build Coastguard Worker std::string output_profile_contents;
980*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(
981*795d594fSAndroid Build Coastguard Worker out_profile.GetFilename(), &output_profile_contents));
982*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(output_profile_contents, expected_profile_content);
983*795d594fSAndroid Build Coastguard Worker
984*795d594fSAndroid Build Coastguard Worker // Verify the preloaded classes content.
985*795d594fSAndroid Build Coastguard Worker std::string output_preloaded_contents;
986*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(
987*795d594fSAndroid Build Coastguard Worker out_preloaded_classes.GetFilename(), &output_preloaded_contents));
988*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(output_preloaded_contents, expected_preloaded_content);
989*795d594fSAndroid Build Coastguard Worker }
990*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestBootImageProfileWith2RawProfiles)991*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestBootImageProfileWith2RawProfiles) {
992*795d594fSAndroid Build Coastguard Worker const std::string core_dex = GetLibCoreDexFileNames()[0];
993*795d594fSAndroid Build Coastguard Worker
994*795d594fSAndroid Build Coastguard Worker std::vector<ScratchFile> profiles;
995*795d594fSAndroid Build Coastguard Worker
996*795d594fSAndroid Build Coastguard Worker const std::string kCommonClassUsedByDex1 = "Ljava/lang/CharSequence;";
997*795d594fSAndroid Build Coastguard Worker const std::string kCommonClassUsedByDex1Dex2 = "Ljava/lang/Object;";
998*795d594fSAndroid Build Coastguard Worker const std::string kUncommonClass = "Ljava/lang/Process;";
999*795d594fSAndroid Build Coastguard Worker const std::string kCommonHotMethodUsedByDex1 =
1000*795d594fSAndroid Build Coastguard Worker "Ljava/lang/Comparable;->compareTo(Ljava/lang/Object;)I";
1001*795d594fSAndroid Build Coastguard Worker const std::string kCommonHotMethodUsedByDex1Dex2 = "Ljava/lang/Object;->hashCode()I";
1002*795d594fSAndroid Build Coastguard Worker const std::string kUncommonHotMethod = "Ljava/util/HashMap;-><init>()V";
1003*795d594fSAndroid Build Coastguard Worker
1004*795d594fSAndroid Build Coastguard Worker
1005*795d594fSAndroid Build Coastguard Worker // Thresholds for this test.
1006*795d594fSAndroid Build Coastguard Worker static const size_t kDirtyThreshold = 100;
1007*795d594fSAndroid Build Coastguard Worker static const size_t kCleanThreshold = 100;
1008*795d594fSAndroid Build Coastguard Worker static const size_t kMethodThreshold = 100;
1009*795d594fSAndroid Build Coastguard Worker
1010*795d594fSAndroid Build Coastguard Worker // Create boot profile content, attributing the classes and methods to different dex files.
1011*795d594fSAndroid Build Coastguard Worker std::vector<std::string> input_data1 = {
1012*795d594fSAndroid Build Coastguard Worker "{dex1}" + kCommonClassUsedByDex1,
1013*795d594fSAndroid Build Coastguard Worker "{dex1}" + kCommonClassUsedByDex1Dex2,
1014*795d594fSAndroid Build Coastguard Worker "{dex1}" + kUncommonClass,
1015*795d594fSAndroid Build Coastguard Worker "{dex1}H" + kCommonHotMethodUsedByDex1Dex2,
1016*795d594fSAndroid Build Coastguard Worker "{dex1}" + kCommonHotMethodUsedByDex1,
1017*795d594fSAndroid Build Coastguard Worker };
1018*795d594fSAndroid Build Coastguard Worker std::vector<std::string> input_data2 = {
1019*795d594fSAndroid Build Coastguard Worker "{dex1}" + kCommonClassUsedByDex1,
1020*795d594fSAndroid Build Coastguard Worker "{dex2}" + kCommonClassUsedByDex1Dex2,
1021*795d594fSAndroid Build Coastguard Worker "{dex1}H" + kCommonHotMethodUsedByDex1,
1022*795d594fSAndroid Build Coastguard Worker "{dex2}" + kCommonHotMethodUsedByDex1Dex2,
1023*795d594fSAndroid Build Coastguard Worker "{dex1}" + kUncommonHotMethod,
1024*795d594fSAndroid Build Coastguard Worker };
1025*795d594fSAndroid Build Coastguard Worker std::string input_file_contents1 = JoinProfileLines(input_data1);
1026*795d594fSAndroid Build Coastguard Worker std::string input_file_contents2 = JoinProfileLines(input_data2);
1027*795d594fSAndroid Build Coastguard Worker
1028*795d594fSAndroid Build Coastguard Worker // Expected data
1029*795d594fSAndroid Build Coastguard Worker std::vector<std::string> expected_data = {
1030*795d594fSAndroid Build Coastguard Worker kCommonClassUsedByDex1,
1031*795d594fSAndroid Build Coastguard Worker kCommonClassUsedByDex1Dex2,
1032*795d594fSAndroid Build Coastguard Worker "H" + kCommonHotMethodUsedByDex1,
1033*795d594fSAndroid Build Coastguard Worker "H" + kCommonHotMethodUsedByDex1Dex2
1034*795d594fSAndroid Build Coastguard Worker };
1035*795d594fSAndroid Build Coastguard Worker std::string expected_profile_content = JoinProfileLines(expected_data);
1036*795d594fSAndroid Build Coastguard Worker
1037*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
1038*795d594fSAndroid Build Coastguard Worker ScratchFile profile2;
1039*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(CreateProfile(input_file_contents1,
1040*795d594fSAndroid Build Coastguard Worker profile1.GetFilename(),
1041*795d594fSAndroid Build Coastguard Worker core_dex,
1042*795d594fSAndroid Build Coastguard Worker /*for_boot_image=*/ true));
1043*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(CreateProfile(input_file_contents2,
1044*795d594fSAndroid Build Coastguard Worker profile2.GetFilename(),
1045*795d594fSAndroid Build Coastguard Worker core_dex,
1046*795d594fSAndroid Build Coastguard Worker /*for_boot_image=*/ true));
1047*795d594fSAndroid Build Coastguard Worker
1048*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo boot_profile1(/*for_boot_image=*/ true);
1049*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo boot_profile2(/*for_boot_image=*/ true);
1050*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(boot_profile1.Load(profile1.GetFilename(), /*clear_if_invalid=*/ false));
1051*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(boot_profile2.Load(profile2.GetFilename(), /*clear_if_invalid=*/ false));
1052*795d594fSAndroid Build Coastguard Worker
1053*795d594fSAndroid Build Coastguard Worker // Generate the boot profile.
1054*795d594fSAndroid Build Coastguard Worker ScratchFile out_profile;
1055*795d594fSAndroid Build Coastguard Worker ScratchFile out_preloaded_classes;
1056*795d594fSAndroid Build Coastguard Worker std::vector<std::string> args;
1057*795d594fSAndroid Build Coastguard Worker args.push_back(GetProfmanCmd());
1058*795d594fSAndroid Build Coastguard Worker args.push_back("--generate-boot-image-profile");
1059*795d594fSAndroid Build Coastguard Worker args.push_back("--class-threshold=" + std::to_string(kDirtyThreshold));
1060*795d594fSAndroid Build Coastguard Worker args.push_back("--clean-class-threshold=" + std::to_string(kCleanThreshold));
1061*795d594fSAndroid Build Coastguard Worker args.push_back("--method-threshold=" + std::to_string(kMethodThreshold));
1062*795d594fSAndroid Build Coastguard Worker args.push_back("--profile-file=" + profile1.GetFilename());
1063*795d594fSAndroid Build Coastguard Worker args.push_back("--profile-file=" + profile2.GetFilename());
1064*795d594fSAndroid Build Coastguard Worker args.push_back("--out-profile-path=" + out_profile.GetFilename());
1065*795d594fSAndroid Build Coastguard Worker args.push_back("--out-preloaded-classes-path=" + out_preloaded_classes.GetFilename());
1066*795d594fSAndroid Build Coastguard Worker args.push_back("--apk=" + core_dex);
1067*795d594fSAndroid Build Coastguard Worker args.push_back("--dex-location=" + core_dex);
1068*795d594fSAndroid Build Coastguard Worker
1069*795d594fSAndroid Build Coastguard Worker std::string error;
1070*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ExecAndReturnCode(args, &error), 0) << error;
1071*795d594fSAndroid Build Coastguard Worker
1072*795d594fSAndroid Build Coastguard Worker // Verify the boot profile contents.
1073*795d594fSAndroid Build Coastguard Worker std::string output_profile_contents;
1074*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(
1075*795d594fSAndroid Build Coastguard Worker out_profile.GetFilename(), &output_profile_contents));
1076*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(output_profile_contents, expected_profile_content);
1077*795d594fSAndroid Build Coastguard Worker }
1078*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestProfileCreationOneNotMatched)1079*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestProfileCreationOneNotMatched) {
1080*795d594fSAndroid Build Coastguard Worker // Class names put here need to be in sorted order.
1081*795d594fSAndroid Build Coastguard Worker std::vector<std::string> class_names = {
1082*795d594fSAndroid Build Coastguard Worker "Ldoesnt/match/this/one;",
1083*795d594fSAndroid Build Coastguard Worker "Ljava/lang/Comparable;",
1084*795d594fSAndroid Build Coastguard Worker "Ljava/lang/Object;"
1085*795d594fSAndroid Build Coastguard Worker };
1086*795d594fSAndroid Build Coastguard Worker std::string input_file_contents;
1087*795d594fSAndroid Build Coastguard Worker for (std::string& class_name : class_names) {
1088*795d594fSAndroid Build Coastguard Worker input_file_contents += class_name + std::string("\n");
1089*795d594fSAndroid Build Coastguard Worker }
1090*795d594fSAndroid Build Coastguard Worker std::string output_file_contents;
1091*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateAndDump(input_file_contents, &output_file_contents));
1092*795d594fSAndroid Build Coastguard Worker std::string expected_contents =
1093*795d594fSAndroid Build Coastguard Worker class_names[1] + std::string("\n") +
1094*795d594fSAndroid Build Coastguard Worker class_names[2] + std::string("\n");
1095*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(output_file_contents, expected_contents);
1096*795d594fSAndroid Build Coastguard Worker }
1097*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestProfileCreationNoneMatched)1098*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestProfileCreationNoneMatched) {
1099*795d594fSAndroid Build Coastguard Worker // Class names put here need to be in sorted order.
1100*795d594fSAndroid Build Coastguard Worker std::vector<std::string> class_names = {
1101*795d594fSAndroid Build Coastguard Worker "Ldoesnt/match/this/one;",
1102*795d594fSAndroid Build Coastguard Worker "Ldoesnt/match/this/one/either;",
1103*795d594fSAndroid Build Coastguard Worker "Lnor/this/one;"
1104*795d594fSAndroid Build Coastguard Worker };
1105*795d594fSAndroid Build Coastguard Worker std::string input_file_contents;
1106*795d594fSAndroid Build Coastguard Worker for (std::string& class_name : class_names) {
1107*795d594fSAndroid Build Coastguard Worker input_file_contents += class_name + std::string("\n");
1108*795d594fSAndroid Build Coastguard Worker }
1109*795d594fSAndroid Build Coastguard Worker std::string output_file_contents;
1110*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateAndDump(input_file_contents, &output_file_contents));
1111*795d594fSAndroid Build Coastguard Worker std::string expected_contents("");
1112*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(output_file_contents, expected_contents);
1113*795d594fSAndroid Build Coastguard Worker }
1114*795d594fSAndroid Build Coastguard Worker
1115*795d594fSAndroid Build Coastguard Worker // Test that we can dump profiles in a way they can be re-constituted.
1116*795d594fSAndroid Build Coastguard Worker // Test goes 'txt -> prof -> txt -> prof' and then compares the two profs.
TEST_F(ProfileAssistantTest,TestProfileRoundTrip)1117*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestProfileRoundTrip) {
1118*795d594fSAndroid Build Coastguard Worker // Create the profile content.
1119*795d594fSAndroid Build Coastguard Worker std::vector<std::string_view> methods = {
1120*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMonomorphic(LSuper;)I+LSubA;",
1121*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;",
1122*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMegamorphic(LSuper;)I+LSubA;,LSubB;,LSubC;,LSubD;,LSubE;",
1123*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMissingTypes(LSuper;)I+missing_types",
1124*795d594fSAndroid Build Coastguard Worker "HLTestInline;->noInlineCache(LSuper;)I",
1125*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMultiMonomorphic(LSuper;LSecret;)I+]LSuper;LSubA;]LSecret;LSubB;",
1126*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMultiPolymorphic(LSuper;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;]LSecret;LSubB;,LSubC;",
1127*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMultiMegamorphic(LSuper;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;,LSubD;,LSubE;]LSecret;megamorphic_types",
1128*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMultiMissingTypes(LSuper;LSecret;)I+]LSuper;missing_types]LSecret;missing_types",
1129*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineTriplePolymorphic(LSuper;LSecret;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;]LSecret;LSubB;,LSubC;",
1130*795d594fSAndroid Build Coastguard Worker "HLTestInline;->noInlineCacheMulti(LSuper;LSecret;)I",
1131*795d594fSAndroid Build Coastguard Worker };
1132*795d594fSAndroid Build Coastguard Worker std::ostringstream input_file_contents;
1133*795d594fSAndroid Build Coastguard Worker for (const std::string_view& m : methods) {
1134*795d594fSAndroid Build Coastguard Worker input_file_contents << m << "\n";
1135*795d594fSAndroid Build Coastguard Worker }
1136*795d594fSAndroid Build Coastguard Worker
1137*795d594fSAndroid Build Coastguard Worker // Create the profile and save it to disk.
1138*795d594fSAndroid Build Coastguard Worker ScratchFile profile_file;
1139*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateProfile(input_file_contents.str(),
1140*795d594fSAndroid Build Coastguard Worker profile_file.GetFilename(),
1141*795d594fSAndroid Build Coastguard Worker GetTestDexFileName("ProfileTestMultiDex")));
1142*795d594fSAndroid Build Coastguard Worker
1143*795d594fSAndroid Build Coastguard Worker // Dump the file back into text.
1144*795d594fSAndroid Build Coastguard Worker std::string text_two;
1145*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(DumpClassesAndMethods(
1146*795d594fSAndroid Build Coastguard Worker profile_file.GetFilename(), &text_two, GetTestDexFileName("ProfileTestMultiDex")));
1147*795d594fSAndroid Build Coastguard Worker
1148*795d594fSAndroid Build Coastguard Worker // Create another profile and save it to the disk as well.
1149*795d594fSAndroid Build Coastguard Worker ScratchFile profile_two;
1150*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateProfile(
1151*795d594fSAndroid Build Coastguard Worker text_two, profile_two.GetFilename(), GetTestDexFileName("ProfileTestMultiDex")));
1152*795d594fSAndroid Build Coastguard Worker
1153*795d594fSAndroid Build Coastguard Worker // These two profiles should be bit-identical.
1154*795d594fSAndroid Build Coastguard Worker // TODO We could compare the 'text_two' to the methods but since the order is
1155*795d594fSAndroid Build Coastguard Worker // arbitrary for many parts and there are multiple 'correct' dumps we'd need
1156*795d594fSAndroid Build Coastguard Worker // to basically parse everything and this is simply easier.
1157*795d594fSAndroid Build Coastguard Worker std::string error;
1158*795d594fSAndroid Build Coastguard Worker std::vector<std::string> args { kIsTargetBuild ? "/system/bin/cmp" : "/usr/bin/cmp",
1159*795d594fSAndroid Build Coastguard Worker "-s",
1160*795d594fSAndroid Build Coastguard Worker profile_file.GetFilename(),
1161*795d594fSAndroid Build Coastguard Worker profile_two.GetFilename() };
1162*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ExecAndReturnCode(args, &error), 0) << error << " from " << text_two;
1163*795d594fSAndroid Build Coastguard Worker }
1164*795d594fSAndroid Build Coastguard Worker
1165*795d594fSAndroid Build Coastguard Worker
1166*795d594fSAndroid Build Coastguard Worker // Test that we can dump profiles in a way they can be re-constituted and
1167*795d594fSAndroid Build Coastguard Worker // annotations don't interfere. Test goes 'txt -> ProfileWithAnnotations -> txt
1168*795d594fSAndroid Build Coastguard Worker // -> prof' and then compares that to one that is 'txt ->
1169*795d594fSAndroid Build Coastguard Worker // prof_without_annotations'.
TEST_F(ProfileAssistantTest,TestProfileRoundTripWithAnnotations)1170*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestProfileRoundTripWithAnnotations) {
1171*795d594fSAndroid Build Coastguard Worker // Create the profile content.
1172*795d594fSAndroid Build Coastguard Worker std::vector<std::string_view> methods = {
1173*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMonomorphic(LSuper;)I+LSubA;",
1174*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;",
1175*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMegamorphic(LSuper;)I+LSubA;,LSubB;,LSubC;,LSubD;,LSubE;",
1176*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMissingTypes(LSuper;)I+missing_types",
1177*795d594fSAndroid Build Coastguard Worker "HLTestInline;->noInlineCache(LSuper;)I",
1178*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMultiMonomorphic(LSuper;LSecret;)I+]LSuper;LSubA;]LSecret;LSubB;",
1179*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMultiPolymorphic(LSuper;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;]LSecret;LSubB;,LSubC;",
1180*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMultiMegamorphic(LSuper;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;,LSubD;,LSubE;]LSecret;megamorphic_types",
1181*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMultiMissingTypes(LSuper;LSecret;)I+]LSuper;missing_types]LSecret;missing_types",
1182*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineTriplePolymorphic(LSuper;LSecret;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;]LSecret;LSubB;,LSubC;",
1183*795d594fSAndroid Build Coastguard Worker "HLTestInline;->noInlineCacheMulti(LSuper;LSecret;)I",
1184*795d594fSAndroid Build Coastguard Worker };
1185*795d594fSAndroid Build Coastguard Worker std::ostringstream no_annotation_input_file_contents;
1186*795d594fSAndroid Build Coastguard Worker std::ostringstream with_annotation_input_file_contents;
1187*795d594fSAndroid Build Coastguard Worker for (const std::string_view& m : methods) {
1188*795d594fSAndroid Build Coastguard Worker no_annotation_input_file_contents << m << "\n";
1189*795d594fSAndroid Build Coastguard Worker with_annotation_input_file_contents << "{foobar}" << m << "\n";
1190*795d594fSAndroid Build Coastguard Worker }
1191*795d594fSAndroid Build Coastguard Worker
1192*795d594fSAndroid Build Coastguard Worker // Create the profile and save it to disk.
1193*795d594fSAndroid Build Coastguard Worker ScratchFile with_annotation_profile_file;
1194*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateProfile(with_annotation_input_file_contents.str(),
1195*795d594fSAndroid Build Coastguard Worker with_annotation_profile_file.GetFilename(),
1196*795d594fSAndroid Build Coastguard Worker GetTestDexFileName("ProfileTestMultiDex")));
1197*795d594fSAndroid Build Coastguard Worker
1198*795d594fSAndroid Build Coastguard Worker ScratchFile no_annotation_profile_file;
1199*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateProfile(no_annotation_input_file_contents.str(),
1200*795d594fSAndroid Build Coastguard Worker no_annotation_profile_file.GetFilename(),
1201*795d594fSAndroid Build Coastguard Worker GetTestDexFileName("ProfileTestMultiDex")));
1202*795d594fSAndroid Build Coastguard Worker
1203*795d594fSAndroid Build Coastguard Worker // Dump the file back into text.
1204*795d594fSAndroid Build Coastguard Worker std::string text_two;
1205*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(DumpClassesAndMethods(with_annotation_profile_file.GetFilename(),
1206*795d594fSAndroid Build Coastguard Worker &text_two,
1207*795d594fSAndroid Build Coastguard Worker GetTestDexFileName("ProfileTestMultiDex")));
1208*795d594fSAndroid Build Coastguard Worker
1209*795d594fSAndroid Build Coastguard Worker // Create another profile and save it to the disk as well.
1210*795d594fSAndroid Build Coastguard Worker ScratchFile profile_two;
1211*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateProfile(
1212*795d594fSAndroid Build Coastguard Worker text_two, profile_two.GetFilename(), GetTestDexFileName("ProfileTestMultiDex")));
1213*795d594fSAndroid Build Coastguard Worker
1214*795d594fSAndroid Build Coastguard Worker // These two profiles should be bit-identical.
1215*795d594fSAndroid Build Coastguard Worker // TODO We could compare the 'text_two' to the methods but since the order is
1216*795d594fSAndroid Build Coastguard Worker // arbitrary for many parts and there are multiple 'correct' dumps we'd need
1217*795d594fSAndroid Build Coastguard Worker // to basically parse everything and this is simply easier.
1218*795d594fSAndroid Build Coastguard Worker std::string error;
1219*795d594fSAndroid Build Coastguard Worker std::vector<std::string> args { kIsTargetBuild ? "/system/bin/cmp" : "/usr/bin/cmp",
1220*795d594fSAndroid Build Coastguard Worker "-s",
1221*795d594fSAndroid Build Coastguard Worker no_annotation_profile_file.GetFilename(),
1222*795d594fSAndroid Build Coastguard Worker profile_two.GetFilename() };
1223*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ExecAndReturnCode(args, &error), 0) << error << " from " << text_two;
1224*795d594fSAndroid Build Coastguard Worker }
1225*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestProfileCreateInlineCache)1226*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestProfileCreateInlineCache) {
1227*795d594fSAndroid Build Coastguard Worker // Create the profile content.
1228*795d594fSAndroid Build Coastguard Worker std::vector<std::string_view> methods = {
1229*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMonomorphic(LSuper;)I+LSubA;",
1230*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;",
1231*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMegamorphic(LSuper;)I+LSubA;,LSubB;,LSubC;,LSubD;,LSubE;",
1232*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMissingTypes(LSuper;)I+missing_types",
1233*795d594fSAndroid Build Coastguard Worker "HLTestInline;->noInlineCache(LSuper;)I",
1234*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMultiMonomorphic(LSuper;LSecret;)I+]LSuper;LSubA;]LSecret;LSubB;",
1235*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMultiPolymorphic(LSuper;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;]LSecret;LSubB;,LSubC;",
1236*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMultiMegamorphic(LSuper;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;,LSubD;,LSubE;]LSecret;LSubA;,LSubB;,LSubC;,LSubD;,LSubE;",
1237*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMultiMissingTypes(LSuper;LSecret;)I+]LSuper;missing_types]LSecret;missing_types",
1238*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineTriplePolymorphic(LSuper;LSecret;LSecret;)I+]LSuper;LSubA;,LSubB;,LSubC;]LSecret;LSubB;,LSubC;",
1239*795d594fSAndroid Build Coastguard Worker "HLTestInline;->noInlineCacheMulti(LSuper;LSecret;)I",
1240*795d594fSAndroid Build Coastguard Worker };
1241*795d594fSAndroid Build Coastguard Worker std::ostringstream input_file_contents;
1242*795d594fSAndroid Build Coastguard Worker for (const std::string_view& m : methods) {
1243*795d594fSAndroid Build Coastguard Worker input_file_contents << m << "\n";
1244*795d594fSAndroid Build Coastguard Worker }
1245*795d594fSAndroid Build Coastguard Worker
1246*795d594fSAndroid Build Coastguard Worker // Create the profile and save it to disk.
1247*795d594fSAndroid Build Coastguard Worker ScratchFile profile_file;
1248*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateProfile(input_file_contents.str(),
1249*795d594fSAndroid Build Coastguard Worker profile_file.GetFilename(),
1250*795d594fSAndroid Build Coastguard Worker GetTestDexFileName("ProfileTestMultiDex")));
1251*795d594fSAndroid Build Coastguard Worker
1252*795d594fSAndroid Build Coastguard Worker // Load the profile from disk.
1253*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1254*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Load(GetFd(profile_file)));
1255*795d594fSAndroid Build Coastguard Worker
1256*795d594fSAndroid Build Coastguard Worker // Load the dex files and verify that the profile contains the expected methods info.
1257*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
1258*795d594fSAndroid Build Coastguard Worker jobject class_loader = LoadDex("ProfileTestMultiDex");
1259*795d594fSAndroid Build Coastguard Worker ASSERT_NE(class_loader, nullptr);
1260*795d594fSAndroid Build Coastguard Worker
1261*795d594fSAndroid Build Coastguard Worker StackHandleScope<5> hs(soa.Self());
1262*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> super_klass = hs.NewHandle(GetClass(soa, class_loader, "LSuper;"));
1263*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> secret_klass = hs.NewHandle(GetClass(soa, class_loader, "LSecret;"));
1264*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> sub_a = hs.NewHandle(GetClass(soa, class_loader, "LSubA;"));
1265*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> sub_b = hs.NewHandle(GetClass(soa, class_loader, "LSubB;"));
1266*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> sub_c = hs.NewHandle(GetClass(soa, class_loader, "LSubC;"));
1267*795d594fSAndroid Build Coastguard Worker
1268*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(super_klass != nullptr);
1269*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(secret_klass != nullptr);
1270*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(sub_a != nullptr);
1271*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(sub_b != nullptr);
1272*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(sub_c != nullptr);
1273*795d594fSAndroid Build Coastguard Worker
1274*795d594fSAndroid Build Coastguard Worker {
1275*795d594fSAndroid Build Coastguard Worker // Verify that method inlineMonomorphic has the expected inline caches and nothing else.
1276*795d594fSAndroid Build Coastguard Worker ArtMethod* inline_monomorphic = GetVirtualMethod(class_loader,
1277*795d594fSAndroid Build Coastguard Worker "LTestInline;",
1278*795d594fSAndroid Build Coastguard Worker "inlineMonomorphic");
1279*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inline_monomorphic != nullptr);
1280*795d594fSAndroid Build Coastguard Worker TypeReferenceSet expected_monomorphic;
1281*795d594fSAndroid Build Coastguard Worker expected_monomorphic.insert(MakeTypeReference(sub_a.Get()));
1282*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_monomorphic,
1283*795d594fSAndroid Build Coastguard Worker expected_monomorphic,
1284*795d594fSAndroid Build Coastguard Worker info,
1285*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/false,
1286*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/false);
1287*795d594fSAndroid Build Coastguard Worker }
1288*795d594fSAndroid Build Coastguard Worker
1289*795d594fSAndroid Build Coastguard Worker {
1290*795d594fSAndroid Build Coastguard Worker // Verify that method inlinePolymorphic has the expected inline caches and nothing else.
1291*795d594fSAndroid Build Coastguard Worker ArtMethod* inline_polymorhic = GetVirtualMethod(class_loader,
1292*795d594fSAndroid Build Coastguard Worker "LTestInline;",
1293*795d594fSAndroid Build Coastguard Worker "inlinePolymorphic");
1294*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inline_polymorhic != nullptr);
1295*795d594fSAndroid Build Coastguard Worker TypeReferenceSet expected_polymorphic;
1296*795d594fSAndroid Build Coastguard Worker expected_polymorphic.insert(MakeTypeReference(sub_a.Get()));
1297*795d594fSAndroid Build Coastguard Worker expected_polymorphic.insert(MakeTypeReference(sub_b.Get()));
1298*795d594fSAndroid Build Coastguard Worker expected_polymorphic.insert(MakeTypeReference(sub_c.Get()));
1299*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_polymorhic,
1300*795d594fSAndroid Build Coastguard Worker expected_polymorphic,
1301*795d594fSAndroid Build Coastguard Worker info,
1302*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/false,
1303*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/false);
1304*795d594fSAndroid Build Coastguard Worker }
1305*795d594fSAndroid Build Coastguard Worker
1306*795d594fSAndroid Build Coastguard Worker {
1307*795d594fSAndroid Build Coastguard Worker // Verify that method inlineMegamorphic has the expected inline caches and nothing else.
1308*795d594fSAndroid Build Coastguard Worker ArtMethod* inline_megamorphic = GetVirtualMethod(class_loader,
1309*795d594fSAndroid Build Coastguard Worker "LTestInline;",
1310*795d594fSAndroid Build Coastguard Worker "inlineMegamorphic");
1311*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inline_megamorphic != nullptr);
1312*795d594fSAndroid Build Coastguard Worker TypeReferenceSet expected_megamorphic;
1313*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_megamorphic,
1314*795d594fSAndroid Build Coastguard Worker expected_megamorphic,
1315*795d594fSAndroid Build Coastguard Worker info,
1316*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/true,
1317*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/false);
1318*795d594fSAndroid Build Coastguard Worker }
1319*795d594fSAndroid Build Coastguard Worker
1320*795d594fSAndroid Build Coastguard Worker {
1321*795d594fSAndroid Build Coastguard Worker // Verify that method inlineMegamorphic has the expected inline caches and nothing else.
1322*795d594fSAndroid Build Coastguard Worker ArtMethod* inline_missing_types = GetVirtualMethod(class_loader,
1323*795d594fSAndroid Build Coastguard Worker "LTestInline;",
1324*795d594fSAndroid Build Coastguard Worker "inlineMissingTypes");
1325*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inline_missing_types != nullptr);
1326*795d594fSAndroid Build Coastguard Worker TypeReferenceSet expected_missing_Types;
1327*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_missing_types,
1328*795d594fSAndroid Build Coastguard Worker expected_missing_Types,
1329*795d594fSAndroid Build Coastguard Worker info,
1330*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/false,
1331*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/true);
1332*795d594fSAndroid Build Coastguard Worker }
1333*795d594fSAndroid Build Coastguard Worker
1334*795d594fSAndroid Build Coastguard Worker {
1335*795d594fSAndroid Build Coastguard Worker // Verify that method noInlineCache has no inline caches in the profile.
1336*795d594fSAndroid Build Coastguard Worker ArtMethod* no_inline_cache = GetVirtualMethod(class_loader, "LTestInline;", "noInlineCache");
1337*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(no_inline_cache != nullptr);
1338*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness hotness_no_inline_cache = info.GetMethodHotness(
1339*795d594fSAndroid Build Coastguard Worker MethodReference(no_inline_cache->GetDexFile(), no_inline_cache->GetDexMethodIndex()));
1340*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(hotness_no_inline_cache.IsHot());
1341*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(hotness_no_inline_cache.GetInlineCacheMap()->empty());
1342*795d594fSAndroid Build Coastguard Worker }
1343*795d594fSAndroid Build Coastguard Worker
1344*795d594fSAndroid Build Coastguard Worker {
1345*795d594fSAndroid Build Coastguard Worker // Verify that method inlineMonomorphic has the expected inline caches and nothing else.
1346*795d594fSAndroid Build Coastguard Worker ArtMethod* inline_monomorphic = GetVirtualMethod(class_loader,
1347*795d594fSAndroid Build Coastguard Worker "LTestInline;",
1348*795d594fSAndroid Build Coastguard Worker "inlineMultiMonomorphic");
1349*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inline_monomorphic != nullptr);
1350*795d594fSAndroid Build Coastguard Worker TypeReferenceSet expected_monomorphic_super;
1351*795d594fSAndroid Build Coastguard Worker TypeReferenceSet expected_monomorphic_secret;
1352*795d594fSAndroid Build Coastguard Worker expected_monomorphic_super.insert(MakeTypeReference(sub_a.Get()));
1353*795d594fSAndroid Build Coastguard Worker expected_monomorphic_secret.insert(MakeTypeReference(sub_b.Get()));
1354*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_monomorphic,
1355*795d594fSAndroid Build Coastguard Worker GetDexPcOfCallTo(inline_monomorphic, super_klass),
1356*795d594fSAndroid Build Coastguard Worker expected_monomorphic_super,
1357*795d594fSAndroid Build Coastguard Worker info,
1358*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/false,
1359*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/false);
1360*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_monomorphic,
1361*795d594fSAndroid Build Coastguard Worker GetDexPcOfCallTo(inline_monomorphic, secret_klass),
1362*795d594fSAndroid Build Coastguard Worker expected_monomorphic_secret,
1363*795d594fSAndroid Build Coastguard Worker info,
1364*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/false,
1365*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/false);
1366*795d594fSAndroid Build Coastguard Worker }
1367*795d594fSAndroid Build Coastguard Worker
1368*795d594fSAndroid Build Coastguard Worker {
1369*795d594fSAndroid Build Coastguard Worker // Verify that method inlinePolymorphic has the expected inline caches and nothing else.
1370*795d594fSAndroid Build Coastguard Worker ArtMethod* inline_polymorhic = GetVirtualMethod(class_loader,
1371*795d594fSAndroid Build Coastguard Worker "LTestInline;",
1372*795d594fSAndroid Build Coastguard Worker "inlineMultiPolymorphic");
1373*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inline_polymorhic != nullptr);
1374*795d594fSAndroid Build Coastguard Worker TypeReferenceSet expected_polymorphic_super;
1375*795d594fSAndroid Build Coastguard Worker expected_polymorphic_super.insert(MakeTypeReference(sub_a.Get()));
1376*795d594fSAndroid Build Coastguard Worker expected_polymorphic_super.insert(MakeTypeReference(sub_b.Get()));
1377*795d594fSAndroid Build Coastguard Worker expected_polymorphic_super.insert(MakeTypeReference(sub_c.Get()));
1378*795d594fSAndroid Build Coastguard Worker TypeReferenceSet expected_polymorphic_secret;
1379*795d594fSAndroid Build Coastguard Worker expected_polymorphic_secret.insert(MakeTypeReference(sub_b.Get()));
1380*795d594fSAndroid Build Coastguard Worker expected_polymorphic_secret.insert(MakeTypeReference(sub_c.Get()));
1381*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_polymorhic,
1382*795d594fSAndroid Build Coastguard Worker GetDexPcOfCallTo(inline_polymorhic, super_klass),
1383*795d594fSAndroid Build Coastguard Worker expected_polymorphic_super,
1384*795d594fSAndroid Build Coastguard Worker info,
1385*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/false,
1386*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/false);
1387*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_polymorhic,
1388*795d594fSAndroid Build Coastguard Worker GetDexPcOfCallTo(inline_polymorhic, secret_klass),
1389*795d594fSAndroid Build Coastguard Worker expected_polymorphic_secret,
1390*795d594fSAndroid Build Coastguard Worker info,
1391*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/false,
1392*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/false);
1393*795d594fSAndroid Build Coastguard Worker }
1394*795d594fSAndroid Build Coastguard Worker
1395*795d594fSAndroid Build Coastguard Worker {
1396*795d594fSAndroid Build Coastguard Worker // Verify that method inlinePolymorphic has the expected inline caches and nothing else.
1397*795d594fSAndroid Build Coastguard Worker ArtMethod* inline_polymorhic = GetVirtualMethod(class_loader,
1398*795d594fSAndroid Build Coastguard Worker "LTestInline;",
1399*795d594fSAndroid Build Coastguard Worker "inlineTriplePolymorphic");
1400*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inline_polymorhic != nullptr);
1401*795d594fSAndroid Build Coastguard Worker TypeReferenceSet expected_polymorphic_super;
1402*795d594fSAndroid Build Coastguard Worker expected_polymorphic_super.insert(MakeTypeReference(sub_a.Get()));
1403*795d594fSAndroid Build Coastguard Worker expected_polymorphic_super.insert(MakeTypeReference(sub_b.Get()));
1404*795d594fSAndroid Build Coastguard Worker expected_polymorphic_super.insert(MakeTypeReference(sub_c.Get()));
1405*795d594fSAndroid Build Coastguard Worker TypeReferenceSet expected_polymorphic_secret;
1406*795d594fSAndroid Build Coastguard Worker expected_polymorphic_secret.insert(MakeTypeReference(sub_b.Get()));
1407*795d594fSAndroid Build Coastguard Worker expected_polymorphic_secret.insert(MakeTypeReference(sub_c.Get()));
1408*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_polymorhic,
1409*795d594fSAndroid Build Coastguard Worker GetDexPcOfCallTo(inline_polymorhic, super_klass),
1410*795d594fSAndroid Build Coastguard Worker expected_polymorphic_super,
1411*795d594fSAndroid Build Coastguard Worker info,
1412*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/false,
1413*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/false);
1414*795d594fSAndroid Build Coastguard Worker uint16_t first_call = GetDexPcOfCallTo(inline_polymorhic, secret_klass);
1415*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_polymorhic,
1416*795d594fSAndroid Build Coastguard Worker first_call,
1417*795d594fSAndroid Build Coastguard Worker expected_polymorphic_secret,
1418*795d594fSAndroid Build Coastguard Worker info,
1419*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/false,
1420*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/false);
1421*795d594fSAndroid Build Coastguard Worker uint16_t second_call = GetDexPcOfCallTo(inline_polymorhic, secret_klass, first_call);
1422*795d594fSAndroid Build Coastguard Worker ASSERT_LT(first_call, second_call);
1423*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_polymorhic,
1424*795d594fSAndroid Build Coastguard Worker second_call,
1425*795d594fSAndroid Build Coastguard Worker expected_polymorphic_secret,
1426*795d594fSAndroid Build Coastguard Worker info,
1427*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/false,
1428*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/false);
1429*795d594fSAndroid Build Coastguard Worker }
1430*795d594fSAndroid Build Coastguard Worker
1431*795d594fSAndroid Build Coastguard Worker {
1432*795d594fSAndroid Build Coastguard Worker // Verify that method inlineMegamorphic has the expected inline caches and nothing else.
1433*795d594fSAndroid Build Coastguard Worker ArtMethod* inline_megamorphic = GetVirtualMethod(class_loader,
1434*795d594fSAndroid Build Coastguard Worker "LTestInline;",
1435*795d594fSAndroid Build Coastguard Worker "inlineMultiMegamorphic");
1436*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inline_megamorphic != nullptr);
1437*795d594fSAndroid Build Coastguard Worker TypeReferenceSet expected_megamorphic;
1438*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_megamorphic,
1439*795d594fSAndroid Build Coastguard Worker GetDexPcOfCallTo(inline_megamorphic, super_klass),
1440*795d594fSAndroid Build Coastguard Worker expected_megamorphic,
1441*795d594fSAndroid Build Coastguard Worker info,
1442*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/true,
1443*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/false);
1444*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_megamorphic,
1445*795d594fSAndroid Build Coastguard Worker GetDexPcOfCallTo(inline_megamorphic, secret_klass),
1446*795d594fSAndroid Build Coastguard Worker expected_megamorphic,
1447*795d594fSAndroid Build Coastguard Worker info,
1448*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/true,
1449*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/false);
1450*795d594fSAndroid Build Coastguard Worker }
1451*795d594fSAndroid Build Coastguard Worker
1452*795d594fSAndroid Build Coastguard Worker {
1453*795d594fSAndroid Build Coastguard Worker // Verify that method inlineMegamorphic has the expected inline caches and nothing else.
1454*795d594fSAndroid Build Coastguard Worker ArtMethod* inline_missing_types = GetVirtualMethod(class_loader,
1455*795d594fSAndroid Build Coastguard Worker "LTestInline;",
1456*795d594fSAndroid Build Coastguard Worker "inlineMultiMissingTypes");
1457*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inline_missing_types != nullptr);
1458*795d594fSAndroid Build Coastguard Worker TypeReferenceSet expected_missing_Types;
1459*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_missing_types,
1460*795d594fSAndroid Build Coastguard Worker GetDexPcOfCallTo(inline_missing_types, super_klass),
1461*795d594fSAndroid Build Coastguard Worker expected_missing_Types,
1462*795d594fSAndroid Build Coastguard Worker info,
1463*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/false,
1464*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/true);
1465*795d594fSAndroid Build Coastguard Worker AssertInlineCaches(inline_missing_types,
1466*795d594fSAndroid Build Coastguard Worker GetDexPcOfCallTo(inline_missing_types, secret_klass),
1467*795d594fSAndroid Build Coastguard Worker expected_missing_Types,
1468*795d594fSAndroid Build Coastguard Worker info,
1469*795d594fSAndroid Build Coastguard Worker /*is_megamorphic=*/false,
1470*795d594fSAndroid Build Coastguard Worker /*is_missing_types=*/true);
1471*795d594fSAndroid Build Coastguard Worker }
1472*795d594fSAndroid Build Coastguard Worker
1473*795d594fSAndroid Build Coastguard Worker {
1474*795d594fSAndroid Build Coastguard Worker // Verify that method noInlineCacheMulti has no inline caches in the profile.
1475*795d594fSAndroid Build Coastguard Worker ArtMethod* no_inline_cache =
1476*795d594fSAndroid Build Coastguard Worker GetVirtualMethod(class_loader, "LTestInline;", "noInlineCacheMulti");
1477*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(no_inline_cache != nullptr);
1478*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness hotness_no_inline_cache = info.GetMethodHotness(
1479*795d594fSAndroid Build Coastguard Worker MethodReference(no_inline_cache->GetDexFile(), no_inline_cache->GetDexMethodIndex()));
1480*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(hotness_no_inline_cache.IsHot());
1481*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(hotness_no_inline_cache.GetInlineCacheMap()->empty());
1482*795d594fSAndroid Build Coastguard Worker }
1483*795d594fSAndroid Build Coastguard Worker }
1484*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,MergeProfilesWithDifferentDexOrder)1485*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, MergeProfilesWithDifferentDexOrder) {
1486*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
1487*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
1488*795d594fSAndroid Build Coastguard Worker
1489*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({GetFd(profile1)});
1490*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
1491*795d594fSAndroid Build Coastguard Worker
1492*795d594fSAndroid Build Coastguard Worker // The new profile info will contain the methods with indices 0-100.
1493*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsToEnableCompilation = 100;
1494*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
1495*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1, dex2, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1,
1496*795d594fSAndroid Build Coastguard Worker /*start_method_index=*/0, /*reverse_dex_write_order=*/false);
1497*795d594fSAndroid Build Coastguard Worker
1498*795d594fSAndroid Build Coastguard Worker // The reference profile info will contain the methods with indices 50-150.
1499*795d594fSAndroid Build Coastguard Worker // When setting up the profile reverse the order in which the dex files
1500*795d594fSAndroid Build Coastguard Worker // are added to the profile. This will verify that profman merges profiles
1501*795d594fSAndroid Build Coastguard Worker // with a different dex order correctly.
1502*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsAlreadyCompiled = 100;
1503*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo reference_info;
1504*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1, dex2, kNumberOfMethodsAlreadyCompiled, 0, reference_profile,
1505*795d594fSAndroid Build Coastguard Worker &reference_info, kNumberOfMethodsToEnableCompilation / 2, /*reverse_dex_write_order=*/true);
1506*795d594fSAndroid Build Coastguard Worker
1507*795d594fSAndroid Build Coastguard Worker // We should advise compilation.
1508*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProfmanResult::kCompile, ProcessProfiles(profile_fds, reference_profile_fd));
1509*795d594fSAndroid Build Coastguard Worker
1510*795d594fSAndroid Build Coastguard Worker // The resulting compilation info must be equal to the merge of the inputs.
1511*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result;
1512*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(reference_profile_fd));
1513*795d594fSAndroid Build Coastguard Worker
1514*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo expected;
1515*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.MergeWith(reference_info));
1516*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.MergeWith(info1));
1517*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.Equals(result));
1518*795d594fSAndroid Build Coastguard Worker
1519*795d594fSAndroid Build Coastguard Worker // The information from profile must remain the same.
1520*795d594fSAndroid Build Coastguard Worker CheckProfileInfo(profile1, info1);
1521*795d594fSAndroid Build Coastguard Worker }
1522*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestProfileCreateWithSubtype)1523*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestProfileCreateWithSubtype) {
1524*795d594fSAndroid Build Coastguard Worker // Create the profile content.
1525*795d594fSAndroid Build Coastguard Worker std::vector<std::string> profile_methods = {
1526*795d594fSAndroid Build Coastguard Worker "HLTestInlineSubtype;->inlineMonomorphic(LSuper;)I+]LSuper;LSubA;",
1527*795d594fSAndroid Build Coastguard Worker };
1528*795d594fSAndroid Build Coastguard Worker std::string input_file_contents;
1529*795d594fSAndroid Build Coastguard Worker for (std::string& m : profile_methods) {
1530*795d594fSAndroid Build Coastguard Worker input_file_contents += m + std::string("\n");
1531*795d594fSAndroid Build Coastguard Worker }
1532*795d594fSAndroid Build Coastguard Worker
1533*795d594fSAndroid Build Coastguard Worker // Create the profile and save it to disk.
1534*795d594fSAndroid Build Coastguard Worker ScratchFile profile_file;
1535*795d594fSAndroid Build Coastguard Worker std::string dex_filename = GetTestDexFileName("ProfileTestMultiDex");
1536*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateProfile(input_file_contents, profile_file.GetFilename(), dex_filename));
1537*795d594fSAndroid Build Coastguard Worker
1538*795d594fSAndroid Build Coastguard Worker // Load the profile from disk.
1539*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1540*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Load(GetFd(profile_file)));
1541*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << profile_file.GetFilename();
1542*795d594fSAndroid Build Coastguard Worker
1543*795d594fSAndroid Build Coastguard Worker // Load the dex files and verify that the profile contains the expected
1544*795d594fSAndroid Build Coastguard Worker // methods info.
1545*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
1546*795d594fSAndroid Build Coastguard Worker jobject class_loader = LoadDex("ProfileTestMultiDex");
1547*795d594fSAndroid Build Coastguard Worker ASSERT_NE(class_loader, nullptr);
1548*795d594fSAndroid Build Coastguard Worker
1549*795d594fSAndroid Build Coastguard Worker // NB This is the supertype of the declared line!
1550*795d594fSAndroid Build Coastguard Worker ArtMethod* inline_monomorphic_super =
1551*795d594fSAndroid Build Coastguard Worker GetVirtualMethod(class_loader, "LTestInline;", "inlineMonomorphic");
1552*795d594fSAndroid Build Coastguard Worker const DexFile* dex_file = inline_monomorphic_super->GetDexFile();
1553*795d594fSAndroid Build Coastguard Worker
1554*795d594fSAndroid Build Coastguard Worker // Verify that the inline cache is present in the superclass
1555*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness hotness_super = info.GetMethodHotness(
1556*795d594fSAndroid Build Coastguard Worker MethodReference(dex_file, inline_monomorphic_super->GetDexMethodIndex()));
1557*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(hotness_super.IsHot());
1558*795d594fSAndroid Build Coastguard Worker const ProfileCompilationInfo::InlineCacheMap* inline_caches = hotness_super.GetInlineCacheMap();
1559*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inline_caches->size(), 1u);
1560*795d594fSAndroid Build Coastguard Worker const ProfileCompilationInfo::DexPcData& dex_pc_data = inline_caches->begin()->second;
1561*795d594fSAndroid Build Coastguard Worker dex::TypeIndex target_type_index(dex_file->GetIndexForTypeId(*dex_file->FindTypeId("LSubA;")));
1562*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(1u, dex_pc_data.classes.size());
1563*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(target_type_index, *dex_pc_data.classes.begin());
1564*795d594fSAndroid Build Coastguard Worker
1565*795d594fSAndroid Build Coastguard Worker // Verify that the method is present in subclass but there are no
1566*795d594fSAndroid Build Coastguard Worker // inline-caches (since there is no code).
1567*795d594fSAndroid Build Coastguard Worker const dex::MethodId& super_method_id =
1568*795d594fSAndroid Build Coastguard Worker dex_file->GetMethodId(inline_monomorphic_super->GetDexMethodIndex());
1569*795d594fSAndroid Build Coastguard Worker uint32_t sub_method_index = dex_file->GetIndexForMethodId(
1570*795d594fSAndroid Build Coastguard Worker *dex_file->FindMethodId(*dex_file->FindTypeId("LTestInlineSubtype;"),
1571*795d594fSAndroid Build Coastguard Worker dex_file->GetStringId(super_method_id.name_idx_),
1572*795d594fSAndroid Build Coastguard Worker dex_file->GetProtoId(super_method_id.proto_idx_)));
1573*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness hotness_sub =
1574*795d594fSAndroid Build Coastguard Worker info.GetMethodHotness(MethodReference(dex_file, sub_method_index));
1575*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(hotness_sub.IsHot());
1576*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(hotness_sub.GetInlineCacheMap()->size(), 0u);
1577*795d594fSAndroid Build Coastguard Worker }
1578*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestProfileCreateWithSubtypeAndDump)1579*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestProfileCreateWithSubtypeAndDump) {
1580*795d594fSAndroid Build Coastguard Worker // Create the profile content.
1581*795d594fSAndroid Build Coastguard Worker std::vector<std::string> profile_methods = {
1582*795d594fSAndroid Build Coastguard Worker "HLTestInlineSubtype;->inlineMonomorphic(LSuper;)I+]LSuper;LSubA;",
1583*795d594fSAndroid Build Coastguard Worker };
1584*795d594fSAndroid Build Coastguard Worker std::string input_file_contents;
1585*795d594fSAndroid Build Coastguard Worker for (std::string& m : profile_methods) {
1586*795d594fSAndroid Build Coastguard Worker input_file_contents += m + std::string("\n");
1587*795d594fSAndroid Build Coastguard Worker }
1588*795d594fSAndroid Build Coastguard Worker
1589*795d594fSAndroid Build Coastguard Worker // Create the profile and save it to disk.
1590*795d594fSAndroid Build Coastguard Worker ScratchFile profile_file;
1591*795d594fSAndroid Build Coastguard Worker std::string dex_filename = GetTestDexFileName("ProfileTestMultiDex");
1592*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateProfile(input_file_contents, profile_file.GetFilename(), dex_filename));
1593*795d594fSAndroid Build Coastguard Worker
1594*795d594fSAndroid Build Coastguard Worker std::string dump_ic;
1595*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(DumpClassesAndMethods(
1596*795d594fSAndroid Build Coastguard Worker profile_file.GetFilename(), &dump_ic, GetTestDexFileName("ProfileTestMultiDex")));
1597*795d594fSAndroid Build Coastguard Worker
1598*795d594fSAndroid Build Coastguard Worker std::vector<std::string> lines;
1599*795d594fSAndroid Build Coastguard Worker std::stringstream dump_stream(dump_ic);
1600*795d594fSAndroid Build Coastguard Worker std::string cur;
1601*795d594fSAndroid Build Coastguard Worker while (std::getline(dump_stream, cur, '\n')) {
1602*795d594fSAndroid Build Coastguard Worker lines.push_back(std::move(cur));
1603*795d594fSAndroid Build Coastguard Worker }
1604*795d594fSAndroid Build Coastguard Worker
1605*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(lines.size(), 2u);
1606*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(std::find(lines.cbegin(),
1607*795d594fSAndroid Build Coastguard Worker lines.cend(),
1608*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMonomorphic(LSuper;)I+]LSuper;LSubA;") !=
1609*795d594fSAndroid Build Coastguard Worker lines.cend());
1610*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(std::find(lines.cbegin(),
1611*795d594fSAndroid Build Coastguard Worker lines.cend(),
1612*795d594fSAndroid Build Coastguard Worker "HLTestInlineSubtype;->inlineMonomorphic(LSuper;)I") != lines.cend());
1613*795d594fSAndroid Build Coastguard Worker }
1614*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,TestProfileCreateWithInvalidData)1615*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, TestProfileCreateWithInvalidData) {
1616*795d594fSAndroid Build Coastguard Worker // Create the profile content.
1617*795d594fSAndroid Build Coastguard Worker std::vector<std::string> profile_methods = {
1618*795d594fSAndroid Build Coastguard Worker "HLTestInline;->inlineMonomorphic(LSuper;)I+invalid_class", // Invalid descriptor for IC.
1619*795d594fSAndroid Build Coastguard Worker "HLTestInline;->invalid_method", // Invalid method spec (no signature).
1620*795d594fSAndroid Build Coastguard Worker "invalid_class", // Invalid descriptor.
1621*795d594fSAndroid Build Coastguard Worker };
1622*795d594fSAndroid Build Coastguard Worker std::string input_file_contents;
1623*795d594fSAndroid Build Coastguard Worker for (std::string& m : profile_methods) {
1624*795d594fSAndroid Build Coastguard Worker input_file_contents += m + std::string("\n");
1625*795d594fSAndroid Build Coastguard Worker }
1626*795d594fSAndroid Build Coastguard Worker
1627*795d594fSAndroid Build Coastguard Worker // Create the profile and save it to disk.
1628*795d594fSAndroid Build Coastguard Worker ScratchFile profile_file;
1629*795d594fSAndroid Build Coastguard Worker std::string dex_filename = GetTestDexFileName("ProfileTestMultiDex");
1630*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateProfile(input_file_contents,
1631*795d594fSAndroid Build Coastguard Worker profile_file.GetFilename(),
1632*795d594fSAndroid Build Coastguard Worker dex_filename));
1633*795d594fSAndroid Build Coastguard Worker
1634*795d594fSAndroid Build Coastguard Worker // Load the profile from disk.
1635*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info;
1636*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Load(GetFd(profile_file)));
1637*795d594fSAndroid Build Coastguard Worker
1638*795d594fSAndroid Build Coastguard Worker // Load the dex files and verify that the profile contains the expected methods info.
1639*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
1640*795d594fSAndroid Build Coastguard Worker jobject class_loader = LoadDex("ProfileTestMultiDex");
1641*795d594fSAndroid Build Coastguard Worker ASSERT_NE(class_loader, nullptr);
1642*795d594fSAndroid Build Coastguard Worker
1643*795d594fSAndroid Build Coastguard Worker ArtMethod* inline_monomorphic = GetVirtualMethod(class_loader,
1644*795d594fSAndroid Build Coastguard Worker "LTestInline;",
1645*795d594fSAndroid Build Coastguard Worker "inlineMonomorphic");
1646*795d594fSAndroid Build Coastguard Worker const DexFile* dex_file = inline_monomorphic->GetDexFile();
1647*795d594fSAndroid Build Coastguard Worker
1648*795d594fSAndroid Build Coastguard Worker // Invalid descriptor in IC results in rejection of the entire line.
1649*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::MethodHotness hotness =
1650*795d594fSAndroid Build Coastguard Worker info.GetMethodHotness(MethodReference(dex_file, inline_monomorphic->GetDexMethodIndex()));
1651*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(hotness.IsHot());
1652*795d594fSAndroid Build Coastguard Worker
1653*795d594fSAndroid Build Coastguard Worker // No data was recorded, so the dex file does not appear in the profile.
1654*795d594fSAndroid Build Coastguard Worker // TODO: Record all dex files passed to `profman` in the profile. Note that
1655*795d594fSAndroid Build Coastguard Worker // this makes sense only if there are no annotations, otherwise we do not
1656*795d594fSAndroid Build Coastguard Worker // know what annotation to use with each dex file.
1657*795d594fSAndroid Build Coastguard Worker std::set<dex::TypeIndex> classes;
1658*795d594fSAndroid Build Coastguard Worker std::set<uint16_t> hot_methods;
1659*795d594fSAndroid Build Coastguard Worker std::set<uint16_t> startup_methods;
1660*795d594fSAndroid Build Coastguard Worker std::set<uint16_t> post_start_methods;
1661*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(info.GetClassesAndMethods(*dex_file,
1662*795d594fSAndroid Build Coastguard Worker &classes,
1663*795d594fSAndroid Build Coastguard Worker &hot_methods,
1664*795d594fSAndroid Build Coastguard Worker &startup_methods,
1665*795d594fSAndroid Build Coastguard Worker &post_start_methods));
1666*795d594fSAndroid Build Coastguard Worker }
1667*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,DumpOnly)1668*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, DumpOnly) {
1669*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
1670*795d594fSAndroid Build Coastguard Worker
1671*795d594fSAndroid Build Coastguard Worker const uint32_t kNumberOfMethods = 64;
1672*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> hot_methods;
1673*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> startup_methods;
1674*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> post_startup_methods;
1675*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < kNumberOfMethods; ++i) {
1676*795d594fSAndroid Build Coastguard Worker if (i % 2 == 0) {
1677*795d594fSAndroid Build Coastguard Worker hot_methods.push_back(i);
1678*795d594fSAndroid Build Coastguard Worker }
1679*795d594fSAndroid Build Coastguard Worker if (i % 3 == 1) {
1680*795d594fSAndroid Build Coastguard Worker startup_methods.push_back(i);
1681*795d594fSAndroid Build Coastguard Worker }
1682*795d594fSAndroid Build Coastguard Worker if (i % 4 == 2) {
1683*795d594fSAndroid Build Coastguard Worker post_startup_methods.push_back(i);
1684*795d594fSAndroid Build Coastguard Worker }
1685*795d594fSAndroid Build Coastguard Worker }
1686*795d594fSAndroid Build Coastguard Worker EXPECT_GT(hot_methods.size(), 0u);
1687*795d594fSAndroid Build Coastguard Worker EXPECT_GT(startup_methods.size(), 0u);
1688*795d594fSAndroid Build Coastguard Worker EXPECT_GT(post_startup_methods.size(), 0u);
1689*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
1690*795d594fSAndroid Build Coastguard Worker SetupBasicProfile(dex1,
1691*795d594fSAndroid Build Coastguard Worker hot_methods,
1692*795d594fSAndroid Build Coastguard Worker startup_methods,
1693*795d594fSAndroid Build Coastguard Worker post_startup_methods,
1694*795d594fSAndroid Build Coastguard Worker profile,
1695*795d594fSAndroid Build Coastguard Worker &info1);
1696*795d594fSAndroid Build Coastguard Worker std::string output;
1697*795d594fSAndroid Build Coastguard Worker DumpOnly(profile.GetFilename(), &output);
1698*795d594fSAndroid Build Coastguard Worker const size_t hot_offset = output.find("hot methods:");
1699*795d594fSAndroid Build Coastguard Worker const size_t startup_offset = output.find("startup methods:");
1700*795d594fSAndroid Build Coastguard Worker const size_t post_startup_offset = output.find("post startup methods:");
1701*795d594fSAndroid Build Coastguard Worker const size_t classes_offset = output.find("classes:");
1702*795d594fSAndroid Build Coastguard Worker ASSERT_NE(hot_offset, std::string::npos);
1703*795d594fSAndroid Build Coastguard Worker ASSERT_NE(startup_offset, std::string::npos);
1704*795d594fSAndroid Build Coastguard Worker ASSERT_NE(post_startup_offset, std::string::npos);
1705*795d594fSAndroid Build Coastguard Worker ASSERT_LT(hot_offset, startup_offset);
1706*795d594fSAndroid Build Coastguard Worker ASSERT_LT(startup_offset, post_startup_offset);
1707*795d594fSAndroid Build Coastguard Worker // Check the actual contents of the dump by looking at the offsets of the methods.
1708*795d594fSAndroid Build Coastguard Worker for (uint32_t m : hot_methods) {
1709*795d594fSAndroid Build Coastguard Worker const size_t pos = output.find(std::to_string(m) + "[],", hot_offset);
1710*795d594fSAndroid Build Coastguard Worker ASSERT_NE(pos, std::string::npos) << output;
1711*795d594fSAndroid Build Coastguard Worker EXPECT_LT(pos, startup_offset) << output;
1712*795d594fSAndroid Build Coastguard Worker }
1713*795d594fSAndroid Build Coastguard Worker for (uint32_t m : startup_methods) {
1714*795d594fSAndroid Build Coastguard Worker const size_t pos = output.find(std::to_string(m) + ",", startup_offset);
1715*795d594fSAndroid Build Coastguard Worker ASSERT_NE(pos, std::string::npos) << output;
1716*795d594fSAndroid Build Coastguard Worker EXPECT_LT(pos, post_startup_offset) << output;
1717*795d594fSAndroid Build Coastguard Worker }
1718*795d594fSAndroid Build Coastguard Worker for (uint32_t m : post_startup_methods) {
1719*795d594fSAndroid Build Coastguard Worker const size_t pos = output.find(std::to_string(m) + ",", post_startup_offset);
1720*795d594fSAndroid Build Coastguard Worker ASSERT_NE(pos, std::string::npos) << output;
1721*795d594fSAndroid Build Coastguard Worker EXPECT_LT(pos, classes_offset) << output;
1722*795d594fSAndroid Build Coastguard Worker }
1723*795d594fSAndroid Build Coastguard Worker }
1724*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,MergeProfilesWithFilter)1725*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, MergeProfilesWithFilter) {
1726*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
1727*795d594fSAndroid Build Coastguard Worker ScratchFile profile2;
1728*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
1729*795d594fSAndroid Build Coastguard Worker
1730*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({
1731*795d594fSAndroid Build Coastguard Worker GetFd(profile1),
1732*795d594fSAndroid Build Coastguard Worker GetFd(profile2)});
1733*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
1734*795d594fSAndroid Build Coastguard Worker
1735*795d594fSAndroid Build Coastguard Worker // Use a real dex file to generate profile test data.
1736*795d594fSAndroid Build Coastguard Worker // The file will be used during merging to filter unwanted data.
1737*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ProfileTestMultiDex");
1738*795d594fSAndroid Build Coastguard Worker const DexFile& d1 = *dex_files[0];
1739*795d594fSAndroid Build Coastguard Worker const DexFile& d2 = *dex_files[1];
1740*795d594fSAndroid Build Coastguard Worker // The new profile info will contain the methods with indices 0-100.
1741*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsToEnableCompilation = 100;
1742*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
1743*795d594fSAndroid Build Coastguard Worker SetupProfile(&d1, dex1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
1744*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
1745*795d594fSAndroid Build Coastguard Worker SetupProfile(&d2, dex2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
1746*795d594fSAndroid Build Coastguard Worker
1747*795d594fSAndroid Build Coastguard Worker
1748*795d594fSAndroid Build Coastguard Worker // The reference profile info will contain the methods with indices 50-150.
1749*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsAlreadyCompiled = 100;
1750*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo reference_info;
1751*795d594fSAndroid Build Coastguard Worker SetupProfile(&d1, dex1,
1752*795d594fSAndroid Build Coastguard Worker kNumberOfMethodsAlreadyCompiled, 0, reference_profile,
1753*795d594fSAndroid Build Coastguard Worker &reference_info, kNumberOfMethodsToEnableCompilation / 2);
1754*795d594fSAndroid Build Coastguard Worker
1755*795d594fSAndroid Build Coastguard Worker // Run profman and pass the dex file with --apk-fd.
1756*795d594fSAndroid Build Coastguard Worker android::base::unique_fd apk_fd(
1757*795d594fSAndroid Build Coastguard Worker open(GetTestDexFileName("ProfileTestMultiDex").c_str(), O_RDONLY)); // NOLINT
1758*795d594fSAndroid Build Coastguard Worker ASSERT_GE(apk_fd.get(), 0);
1759*795d594fSAndroid Build Coastguard Worker
1760*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
1761*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
1762*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
1763*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--profile-file-fd=" + std::to_string(profile1.GetFd()));
1764*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--profile-file-fd=" + std::to_string(profile2.GetFd()));
1765*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile.GetFd()));
1766*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--apk-fd=" + std::to_string(apk_fd.get()));
1767*795d594fSAndroid Build Coastguard Worker std::string error;
1768*795d594fSAndroid Build Coastguard Worker
1769*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ExecAndReturnCode(argv_str, &error), ProfmanResult::kCompile) << error;
1770*795d594fSAndroid Build Coastguard Worker
1771*795d594fSAndroid Build Coastguard Worker // Verify that we can load the result.
1772*795d594fSAndroid Build Coastguard Worker
1773*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result;
1774*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(reference_profile_fd));
1775*795d594fSAndroid Build Coastguard Worker
1776*795d594fSAndroid Build Coastguard Worker // Verify that the result filtered out data not belonging to the dex file.
1777*795d594fSAndroid Build Coastguard Worker // This is equivalent to checking that the result is equal to the merging of
1778*795d594fSAndroid Build Coastguard Worker // all profiles while filtering out data not belonging to the dex file.
1779*795d594fSAndroid Build Coastguard Worker
1780*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::ProfileLoadFilterFn filter_fn =
1781*795d594fSAndroid Build Coastguard Worker [&d1, &d2](const std::string& dex_location, uint32_t checksum) -> bool {
1782*795d594fSAndroid Build Coastguard Worker return (dex_location == ProfileCompilationInfo::GetProfileDexFileBaseKey(d1.GetLocation())
1783*795d594fSAndroid Build Coastguard Worker && checksum == d1.GetLocationChecksum())
1784*795d594fSAndroid Build Coastguard Worker || (dex_location == ProfileCompilationInfo::GetProfileDexFileBaseKey(d2.GetLocation())
1785*795d594fSAndroid Build Coastguard Worker && checksum == d2.GetLocationChecksum());
1786*795d594fSAndroid Build Coastguard Worker };
1787*795d594fSAndroid Build Coastguard Worker
1788*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1_filter;
1789*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2_filter;
1790*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo expected;
1791*795d594fSAndroid Build Coastguard Worker
1792*795d594fSAndroid Build Coastguard Worker info2_filter.Load(profile1.GetFd(), /*merge_classes=*/ true, filter_fn);
1793*795d594fSAndroid Build Coastguard Worker info2_filter.Load(profile2.GetFd(), /*merge_classes=*/ true, filter_fn);
1794*795d594fSAndroid Build Coastguard Worker expected.Load(reference_profile.GetFd(), /*merge_classes=*/ true, filter_fn);
1795*795d594fSAndroid Build Coastguard Worker
1796*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.MergeWith(info1_filter));
1797*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.MergeWith(info2_filter));
1798*795d594fSAndroid Build Coastguard Worker
1799*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(expected.Equals(result));
1800*795d594fSAndroid Build Coastguard Worker }
1801*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,MergeProfilesNoProfile)1802*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, MergeProfilesNoProfile) {
1803*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
1804*795d594fSAndroid Build Coastguard Worker
1805*795d594fSAndroid Build Coastguard Worker // Use a real dex file to generate profile test data.
1806*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ProfileTestMultiDex");
1807*795d594fSAndroid Build Coastguard Worker const DexFile& d1 = *dex_files[0];
1808*795d594fSAndroid Build Coastguard Worker const DexFile& d2 = *dex_files[0];
1809*795d594fSAndroid Build Coastguard Worker
1810*795d594fSAndroid Build Coastguard Worker // The reference profile info will contain the methods with indices 0-100.
1811*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo reference_info;
1812*795d594fSAndroid Build Coastguard Worker SetupProfile(&d1,
1813*795d594fSAndroid Build Coastguard Worker &d2,
1814*795d594fSAndroid Build Coastguard Worker /*number_of_methods=*/ 100,
1815*795d594fSAndroid Build Coastguard Worker /*number_of_classes=*/ 0,
1816*795d594fSAndroid Build Coastguard Worker reference_profile,
1817*795d594fSAndroid Build Coastguard Worker &reference_info);
1818*795d594fSAndroid Build Coastguard Worker
1819*795d594fSAndroid Build Coastguard Worker std::string content_before;
1820*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(reference_profile.GetFilename(), &content_before));
1821*795d594fSAndroid Build Coastguard Worker
1822*795d594fSAndroid Build Coastguard Worker // Run profman and pass the dex file with --apk-fd.
1823*795d594fSAndroid Build Coastguard Worker android::base::unique_fd apk_fd(
1824*795d594fSAndroid Build Coastguard Worker // NOLINTNEXTLINE - Profman needs file to be opened after fork() and exec()
1825*795d594fSAndroid Build Coastguard Worker open(GetTestDexFileName("ProfileTestMultiDex").c_str(), O_RDONLY));
1826*795d594fSAndroid Build Coastguard Worker ASSERT_GE(apk_fd.get(), 0);
1827*795d594fSAndroid Build Coastguard Worker
1828*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
1829*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
1830*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
1831*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile.GetFd()));
1832*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--apk-fd=" + std::to_string(apk_fd.get()));
1833*795d594fSAndroid Build Coastguard Worker
1834*795d594fSAndroid Build Coastguard Worker // Must return kSkipCompilationSmallDelta.
1835*795d594fSAndroid Build Coastguard Worker std::string error;
1836*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ExecAndReturnCode(argv_str, &error), ProfmanResult::kSkipCompilationSmallDelta)
1837*795d594fSAndroid Build Coastguard Worker << error;
1838*795d594fSAndroid Build Coastguard Worker
1839*795d594fSAndroid Build Coastguard Worker // Verify that the content has not changed.
1840*795d594fSAndroid Build Coastguard Worker std::string content_after;
1841*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(reference_profile.GetFilename(), &content_after));
1842*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(content_before, content_after);
1843*795d594fSAndroid Build Coastguard Worker }
1844*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,MergeProfilesNoProfilePassByFilename)1845*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, MergeProfilesNoProfilePassByFilename) {
1846*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
1847*795d594fSAndroid Build Coastguard Worker
1848*795d594fSAndroid Build Coastguard Worker // Use a real dex file to generate profile test data.
1849*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ProfileTestMultiDex");
1850*795d594fSAndroid Build Coastguard Worker const DexFile& d1 = *dex_files[0];
1851*795d594fSAndroid Build Coastguard Worker const DexFile& d2 = *dex_files[0];
1852*795d594fSAndroid Build Coastguard Worker
1853*795d594fSAndroid Build Coastguard Worker // The reference profile info will contain the methods with indices 0-100.
1854*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo reference_info;
1855*795d594fSAndroid Build Coastguard Worker SetupProfile(&d1,
1856*795d594fSAndroid Build Coastguard Worker &d2,
1857*795d594fSAndroid Build Coastguard Worker /*number_of_methods=*/100,
1858*795d594fSAndroid Build Coastguard Worker /*number_of_classes=*/0,
1859*795d594fSAndroid Build Coastguard Worker reference_profile,
1860*795d594fSAndroid Build Coastguard Worker &reference_info);
1861*795d594fSAndroid Build Coastguard Worker
1862*795d594fSAndroid Build Coastguard Worker std::string content_before;
1863*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(reference_profile.GetFilename(), &content_before));
1864*795d594fSAndroid Build Coastguard Worker
1865*795d594fSAndroid Build Coastguard Worker // Run profman and pass the dex file with --apk-fd.
1866*795d594fSAndroid Build Coastguard Worker android::base::unique_fd apk_fd(
1867*795d594fSAndroid Build Coastguard Worker // NOLINTNEXTLINE - Profman needs file to be opened after fork() and exec()
1868*795d594fSAndroid Build Coastguard Worker open(GetTestDexFileName("ProfileTestMultiDex").c_str(), O_RDONLY));
1869*795d594fSAndroid Build Coastguard Worker ASSERT_GE(apk_fd.get(), 0);
1870*795d594fSAndroid Build Coastguard Worker
1871*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
1872*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
1873*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
1874*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--reference-profile-file=" + reference_profile.GetFilename());
1875*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--apk-fd=" + std::to_string(apk_fd.get()));
1876*795d594fSAndroid Build Coastguard Worker
1877*795d594fSAndroid Build Coastguard Worker // Must return kSkipCompilationSmallDelta.
1878*795d594fSAndroid Build Coastguard Worker std::string error;
1879*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ExecAndReturnCode(argv_str, &error), ProfmanResult::kSkipCompilationSmallDelta)
1880*795d594fSAndroid Build Coastguard Worker << error;
1881*795d594fSAndroid Build Coastguard Worker
1882*795d594fSAndroid Build Coastguard Worker // Verify that the content has not changed.
1883*795d594fSAndroid Build Coastguard Worker std::string content_after;
1884*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(reference_profile.GetFilename(), &content_after));
1885*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(content_before, content_after);
1886*795d594fSAndroid Build Coastguard Worker }
1887*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,MergeProfilesNoProfileEmptyReferenceProfile)1888*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, MergeProfilesNoProfileEmptyReferenceProfile) {
1889*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
1890*795d594fSAndroid Build Coastguard Worker
1891*795d594fSAndroid Build Coastguard Worker // The reference profile info will only contain the header.
1892*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo reference_info;
1893*795d594fSAndroid Build Coastguard Worker SetupProfile(/*dex_file1=*/ nullptr,
1894*795d594fSAndroid Build Coastguard Worker /*dex_file2=*/ nullptr,
1895*795d594fSAndroid Build Coastguard Worker /*number_of_methods=*/ 0,
1896*795d594fSAndroid Build Coastguard Worker /*number_of_classes=*/ 0,
1897*795d594fSAndroid Build Coastguard Worker reference_profile,
1898*795d594fSAndroid Build Coastguard Worker &reference_info);
1899*795d594fSAndroid Build Coastguard Worker
1900*795d594fSAndroid Build Coastguard Worker std::string content_before;
1901*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(reference_profile.GetFilename(), &content_before));
1902*795d594fSAndroid Build Coastguard Worker
1903*795d594fSAndroid Build Coastguard Worker // Run profman and pass the dex file with --apk-fd.
1904*795d594fSAndroid Build Coastguard Worker android::base::unique_fd apk_fd(
1905*795d594fSAndroid Build Coastguard Worker // NOLINTNEXTLINE - Profman needs file to be opened after fork() and exec()
1906*795d594fSAndroid Build Coastguard Worker open(GetTestDexFileName("ProfileTestMultiDex").c_str(), O_RDONLY));
1907*795d594fSAndroid Build Coastguard Worker ASSERT_GE(apk_fd.get(), 0);
1908*795d594fSAndroid Build Coastguard Worker
1909*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
1910*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
1911*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
1912*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile.GetFd()));
1913*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--apk-fd=" + std::to_string(apk_fd.get()));
1914*795d594fSAndroid Build Coastguard Worker
1915*795d594fSAndroid Build Coastguard Worker // Must return kSkipCompilationEmptyProfiles.
1916*795d594fSAndroid Build Coastguard Worker std::string error;
1917*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ExecAndReturnCode(argv_str, &error), ProfmanResult::kSkipCompilationEmptyProfiles)
1918*795d594fSAndroid Build Coastguard Worker << error;
1919*795d594fSAndroid Build Coastguard Worker
1920*795d594fSAndroid Build Coastguard Worker // Verify that the content has not changed.
1921*795d594fSAndroid Build Coastguard Worker std::string content_after;
1922*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(reference_profile.GetFilename(), &content_after));
1923*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(content_before, content_after);
1924*795d594fSAndroid Build Coastguard Worker }
1925*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,MergeProfilesNoProfileEmptyReferenceProfileAfterFiltering)1926*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, MergeProfilesNoProfileEmptyReferenceProfileAfterFiltering) {
1927*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
1928*795d594fSAndroid Build Coastguard Worker
1929*795d594fSAndroid Build Coastguard Worker // Use fake dex files to generate profile test data.
1930*795d594fSAndroid Build Coastguard Worker // All the methods will be filtered out during the profman invocation.
1931*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo reference_info;
1932*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1,
1933*795d594fSAndroid Build Coastguard Worker dex2,
1934*795d594fSAndroid Build Coastguard Worker /*number_of_methods=*/ 100,
1935*795d594fSAndroid Build Coastguard Worker /*number_of_classes=*/ 0,
1936*795d594fSAndroid Build Coastguard Worker reference_profile,
1937*795d594fSAndroid Build Coastguard Worker &reference_info);
1938*795d594fSAndroid Build Coastguard Worker
1939*795d594fSAndroid Build Coastguard Worker std::string content_before;
1940*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(reference_profile.GetFilename(), &content_before));
1941*795d594fSAndroid Build Coastguard Worker
1942*795d594fSAndroid Build Coastguard Worker // Run profman and pass the real dex file with --apk-fd.
1943*795d594fSAndroid Build Coastguard Worker android::base::unique_fd apk_fd(
1944*795d594fSAndroid Build Coastguard Worker // NOLINTNEXTLINE - Profman needs file to be opened after fork() and exec()
1945*795d594fSAndroid Build Coastguard Worker open(GetTestDexFileName("ProfileTestMultiDex").c_str(), O_RDONLY));
1946*795d594fSAndroid Build Coastguard Worker ASSERT_GE(apk_fd.get(), 0);
1947*795d594fSAndroid Build Coastguard Worker
1948*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
1949*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
1950*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
1951*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile.GetFd()));
1952*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--apk-fd=" + std::to_string(apk_fd.get()));
1953*795d594fSAndroid Build Coastguard Worker
1954*795d594fSAndroid Build Coastguard Worker // Must return kSkipCompilationEmptyProfiles.
1955*795d594fSAndroid Build Coastguard Worker std::string error;
1956*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ExecAndReturnCode(argv_str, &error), ProfmanResult::kSkipCompilationEmptyProfiles)
1957*795d594fSAndroid Build Coastguard Worker << error;
1958*795d594fSAndroid Build Coastguard Worker
1959*795d594fSAndroid Build Coastguard Worker // Verify that the content has not changed.
1960*795d594fSAndroid Build Coastguard Worker std::string content_after;
1961*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(reference_profile.GetFilename(), &content_after));
1962*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(content_before, content_after);
1963*795d594fSAndroid Build Coastguard Worker }
1964*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,CopyAndUpdateProfileKey)1965*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, CopyAndUpdateProfileKey) {
1966*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
1967*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
1968*795d594fSAndroid Build Coastguard Worker
1969*795d594fSAndroid Build Coastguard Worker // Use a real dex file to generate profile test data. During the copy-and-update the
1970*795d594fSAndroid Build Coastguard Worker // matching is done based on checksum so we have to match with the real thing.
1971*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ProfileTestMultiDex");
1972*795d594fSAndroid Build Coastguard Worker const DexFile& d1 = *dex_files[0];
1973*795d594fSAndroid Build Coastguard Worker const DexFile& d2 = *dex_files[1];
1974*795d594fSAndroid Build Coastguard Worker
1975*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
1976*795d594fSAndroid Build Coastguard Worker uint16_t num_methods_to_add = std::min(d1.NumMethodIds(), d2.NumMethodIds());
1977*795d594fSAndroid Build Coastguard Worker
1978*795d594fSAndroid Build Coastguard Worker const DexFile* dex_to_be_updated1 = BuildDex(
1979*795d594fSAndroid Build Coastguard Worker "fake-location1", d1.GetLocationChecksum(), "LC;", d1.NumMethodIds(), d1.NumTypeIds());
1980*795d594fSAndroid Build Coastguard Worker const DexFile* dex_to_be_updated2 = BuildDex(
1981*795d594fSAndroid Build Coastguard Worker "fake-location2", d2.GetLocationChecksum(), "LC;", d2.NumMethodIds(), d2.NumTypeIds());
1982*795d594fSAndroid Build Coastguard Worker SetupProfile(dex_to_be_updated1,
1983*795d594fSAndroid Build Coastguard Worker dex_to_be_updated2,
1984*795d594fSAndroid Build Coastguard Worker num_methods_to_add,
1985*795d594fSAndroid Build Coastguard Worker /*number_of_classes=*/ 0,
1986*795d594fSAndroid Build Coastguard Worker profile1,
1987*795d594fSAndroid Build Coastguard Worker &info1);
1988*795d594fSAndroid Build Coastguard Worker
1989*795d594fSAndroid Build Coastguard Worker // Run profman and pass the dex file with --apk-fd.
1990*795d594fSAndroid Build Coastguard Worker android::base::unique_fd apk_fd(
1991*795d594fSAndroid Build Coastguard Worker // NOLINTNEXTLINE - Profman needs file to be opened after fork() and exec()
1992*795d594fSAndroid Build Coastguard Worker open(GetTestDexFileName("ProfileTestMultiDex").c_str(), O_RDONLY));
1993*795d594fSAndroid Build Coastguard Worker ASSERT_GE(apk_fd.get(), 0);
1994*795d594fSAndroid Build Coastguard Worker
1995*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
1996*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
1997*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
1998*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--profile-file-fd=" + std::to_string(profile1.GetFd()));
1999*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile.GetFd()));
2000*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--apk-fd=" + std::to_string(apk_fd.get()));
2001*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--copy-and-update-profile-key");
2002*795d594fSAndroid Build Coastguard Worker std::string error;
2003*795d594fSAndroid Build Coastguard Worker
2004*795d594fSAndroid Build Coastguard Worker // Must return kCopyAndUpdateSuccess.
2005*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ExecAndReturnCode(argv_str, &error), ProfmanResult::kCopyAndUpdateSuccess) << error;
2006*795d594fSAndroid Build Coastguard Worker
2007*795d594fSAndroid Build Coastguard Worker // Verify that we can load the result.
2008*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result;
2009*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(reference_profile.GetFd()));
2010*795d594fSAndroid Build Coastguard Worker
2011*795d594fSAndroid Build Coastguard Worker // Verify that the renaming was done.
2012*795d594fSAndroid Build Coastguard Worker for (uint16_t i = 0; i < num_methods_to_add; i ++) {
2013*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.GetMethodHotness(MethodReference(&d1, i)).IsHot()) << i;
2014*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.GetMethodHotness(MethodReference(&d2, i)).IsHot()) << i;
2015*795d594fSAndroid Build Coastguard Worker
2016*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(result.GetMethodHotness(MethodReference(dex_to_be_updated1, i)).IsHot()) << i;
2017*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(result.GetMethodHotness(MethodReference(dex_to_be_updated2, i)).IsHot()) << i;
2018*795d594fSAndroid Build Coastguard Worker }
2019*795d594fSAndroid Build Coastguard Worker }
2020*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,CopyAndUpdateProfileKeyNoUpdate)2021*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, CopyAndUpdateProfileKeyNoUpdate) {
2022*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
2023*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
2024*795d594fSAndroid Build Coastguard Worker
2025*795d594fSAndroid Build Coastguard Worker // Use fake dex files to generate profile test data.
2026*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
2027*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1,
2028*795d594fSAndroid Build Coastguard Worker dex2,
2029*795d594fSAndroid Build Coastguard Worker /*number_of_methods=*/ 100,
2030*795d594fSAndroid Build Coastguard Worker /*number_of_classes=*/ 0,
2031*795d594fSAndroid Build Coastguard Worker profile1,
2032*795d594fSAndroid Build Coastguard Worker &info1);
2033*795d594fSAndroid Build Coastguard Worker
2034*795d594fSAndroid Build Coastguard Worker // Run profman and pass the real dex file with --apk-fd. It won't match any entry in the profile.
2035*795d594fSAndroid Build Coastguard Worker android::base::unique_fd apk_fd(
2036*795d594fSAndroid Build Coastguard Worker // NOLINTNEXTLINE - Profman needs file to be opened after fork() and exec()
2037*795d594fSAndroid Build Coastguard Worker open(GetTestDexFileName("ProfileTestMultiDex").c_str(), O_RDONLY));
2038*795d594fSAndroid Build Coastguard Worker ASSERT_GE(apk_fd.get(), 0);
2039*795d594fSAndroid Build Coastguard Worker
2040*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
2041*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
2042*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
2043*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--profile-file-fd=" + std::to_string(profile1.GetFd()));
2044*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile.GetFd()));
2045*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--apk-fd=" + std::to_string(apk_fd.get()));
2046*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--copy-and-update-profile-key");
2047*795d594fSAndroid Build Coastguard Worker std::string error;
2048*795d594fSAndroid Build Coastguard Worker
2049*795d594fSAndroid Build Coastguard Worker // Must return kCopyAndUpdateNoMatch.
2050*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ExecAndReturnCode(argv_str, &error), ProfmanResult::kCopyAndUpdateNoMatch) << error;
2051*795d594fSAndroid Build Coastguard Worker
2052*795d594fSAndroid Build Coastguard Worker // Verify that the content is the same.
2053*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result;
2054*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(reference_profile.GetFd()));
2055*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(result.Equals(info1));
2056*795d594fSAndroid Build Coastguard Worker }
2057*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,BootImageMerge)2058*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, BootImageMerge) {
2059*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
2060*795d594fSAndroid Build Coastguard Worker ScratchFile profile2;
2061*795d594fSAndroid Build Coastguard Worker ScratchFile profile3;
2062*795d594fSAndroid Build Coastguard Worker ScratchFile output_profile;
2063*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> hot_methods_1;
2064*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> hot_methods_2;
2065*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> hot_methods_3;
2066*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < 100; ++i) {
2067*795d594fSAndroid Build Coastguard Worker hot_methods_1.push_back(i);
2068*795d594fSAndroid Build Coastguard Worker }
2069*795d594fSAndroid Build Coastguard Worker for (size_t i = 50; i < 150; ++i) {
2070*795d594fSAndroid Build Coastguard Worker hot_methods_2.push_back(i);
2071*795d594fSAndroid Build Coastguard Worker }
2072*795d594fSAndroid Build Coastguard Worker for (size_t i = 100; i < 200; ++i) {
2073*795d594fSAndroid Build Coastguard Worker hot_methods_3.push_back(i);
2074*795d594fSAndroid Build Coastguard Worker }
2075*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1(/*for_boot_image=*/false);
2076*795d594fSAndroid Build Coastguard Worker SetupBasicProfile(
2077*795d594fSAndroid Build Coastguard Worker dex1, hot_methods_1, /*startup_methods=*/{}, /*post_startup_methods=*/{}, profile1, &info1);
2078*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2(/*for_boot_image=*/true);
2079*795d594fSAndroid Build Coastguard Worker SetupBasicProfile(
2080*795d594fSAndroid Build Coastguard Worker dex1, hot_methods_2, /*startup_methods=*/{}, /*post_startup_methods=*/{}, profile2, &info2);
2081*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info3(/*for_boot_image=*/true);
2082*795d594fSAndroid Build Coastguard Worker SetupBasicProfile(
2083*795d594fSAndroid Build Coastguard Worker dex1, hot_methods_3, /*startup_methods=*/{}, /*post_startup_methods=*/{}, profile3, &info3);
2084*795d594fSAndroid Build Coastguard Worker
2085*795d594fSAndroid Build Coastguard Worker {
2086*795d594fSAndroid Build Coastguard Worker int return_code = ProcessProfiles({profile1.GetFd(), profile2.GetFd(), profile3.GetFd()},
2087*795d594fSAndroid Build Coastguard Worker output_profile.GetFd(),
2088*795d594fSAndroid Build Coastguard Worker {"--force-merge-and-analyze", "--boot-image-merge"});
2089*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(return_code, ProfmanResult::kCompile);
2090*795d594fSAndroid Build Coastguard Worker
2091*795d594fSAndroid Build Coastguard Worker // Verify the result: it should be equal to info2 union info3 since info1 is a regular profile
2092*795d594fSAndroid Build Coastguard Worker // and should be ignored.
2093*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result(/*for_boot_image=*/true);
2094*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(output_profile.GetFd()));
2095*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info2.MergeWith(info3));
2096*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Equals(info2));
2097*795d594fSAndroid Build Coastguard Worker }
2098*795d594fSAndroid Build Coastguard Worker
2099*795d594fSAndroid Build Coastguard Worker // Same for the legacy force merge mode.
2100*795d594fSAndroid Build Coastguard Worker {
2101*795d594fSAndroid Build Coastguard Worker int return_code = ProcessProfiles({profile1.GetFd(), profile2.GetFd(), profile3.GetFd()},
2102*795d594fSAndroid Build Coastguard Worker output_profile.GetFd(),
2103*795d594fSAndroid Build Coastguard Worker {"--force-merge", "--boot-image-merge"});
2104*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(return_code, ProfmanResult::kSuccess);
2105*795d594fSAndroid Build Coastguard Worker
2106*795d594fSAndroid Build Coastguard Worker // Verify the result: it should be equal to info2 union info3 since info1 is a regular profile
2107*795d594fSAndroid Build Coastguard Worker // and should be ignored.
2108*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result(/*for_boot_image=*/true);
2109*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(output_profile.GetFd()));
2110*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info2.MergeWith(info3));
2111*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Equals(info2));
2112*795d594fSAndroid Build Coastguard Worker }
2113*795d594fSAndroid Build Coastguard Worker }
2114*795d594fSAndroid Build Coastguard Worker
2115*795d594fSAndroid Build Coastguard Worker // Under default behaviour we should not advice compilation
2116*795d594fSAndroid Build Coastguard Worker // and the reference profile should not be updated.
2117*795d594fSAndroid Build Coastguard Worker // However we pass --force-merge to force aggregation and in this case
2118*795d594fSAndroid Build Coastguard Worker // we should see an update.
TEST_F(ProfileAssistantTest,ForceMerge)2119*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, ForceMerge) {
2120*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfClassesInRefProfile = 6000;
2121*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfClassesInCurProfile = 6110; // Threshold is 2%.
2122*795d594fSAndroid Build Coastguard Worker
2123*795d594fSAndroid Build Coastguard Worker const DexFile* dex1_7000 = BuildDex("location1_7000",
2124*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 7001,
2125*795d594fSAndroid Build Coastguard Worker "LUnique1_7000;",
2126*795d594fSAndroid Build Coastguard Worker /*num_method_ids=*/ 0,
2127*795d594fSAndroid Build Coastguard Worker /*num_class_ids=*/ 7000);
2128*795d594fSAndroid Build Coastguard Worker const DexFile* dex2_7000 = BuildDex("location2_7000",
2129*795d594fSAndroid Build Coastguard Worker /*location_checksum=*/ 7002,
2130*795d594fSAndroid Build Coastguard Worker "LUnique2_7000;",
2131*795d594fSAndroid Build Coastguard Worker /*num_method_ids=*/ 0,
2132*795d594fSAndroid Build Coastguard Worker /*num_class_ids=*/ 7000);
2133*795d594fSAndroid Build Coastguard Worker
2134*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
2135*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
2136*795d594fSAndroid Build Coastguard Worker
2137*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({ GetFd(profile)});
2138*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
2139*795d594fSAndroid Build Coastguard Worker
2140*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1;
2141*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1_7000, dex2_7000, 0, kNumberOfClassesInRefProfile, profile, &info1);
2142*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2;
2143*795d594fSAndroid Build Coastguard Worker SetupProfile(dex1_7000, dex2_7000, 0, kNumberOfClassesInCurProfile, reference_profile, &info2);
2144*795d594fSAndroid Build Coastguard Worker
2145*795d594fSAndroid Build Coastguard Worker std::vector<std::string> extra_args({"--force-merge"});
2146*795d594fSAndroid Build Coastguard Worker int return_code = ProcessProfiles(profile_fds, reference_profile_fd, extra_args);
2147*795d594fSAndroid Build Coastguard Worker
2148*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(return_code, ProfmanResult::kSuccess);
2149*795d594fSAndroid Build Coastguard Worker
2150*795d594fSAndroid Build Coastguard Worker // Check that the result is the aggregation.
2151*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result;
2152*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(reference_profile.GetFd()));
2153*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info1.MergeWith(info2));
2154*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Equals(info1));
2155*795d594fSAndroid Build Coastguard Worker }
2156*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,ForceMergeAndAnalyze)2157*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, ForceMergeAndAnalyze) {
2158*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsInRefProfile = 600;
2159*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsInCurProfile = 601;
2160*795d594fSAndroid Build Coastguard Worker
2161*795d594fSAndroid Build Coastguard Worker ScratchFile ref_profile;
2162*795d594fSAndroid Build Coastguard Worker ScratchFile cur_profile;
2163*795d594fSAndroid Build Coastguard Worker
2164*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo ref_info;
2165*795d594fSAndroid Build Coastguard Worker SetupProfile(
2166*795d594fSAndroid Build Coastguard Worker dex1, dex2, kNumberOfMethodsInRefProfile, /*number_of_classes=*/0, ref_profile, &ref_info);
2167*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo cur_info;
2168*795d594fSAndroid Build Coastguard Worker SetupProfile(
2169*795d594fSAndroid Build Coastguard Worker dex1, dex2, kNumberOfMethodsInCurProfile, /*number_of_classes=*/0, cur_profile, &cur_info);
2170*795d594fSAndroid Build Coastguard Worker
2171*795d594fSAndroid Build Coastguard Worker std::vector<std::string> extra_args({"--force-merge-and-analyze"});
2172*795d594fSAndroid Build Coastguard Worker int return_code = ProcessProfiles({cur_profile.GetFd()}, ref_profile.GetFd(), extra_args);
2173*795d594fSAndroid Build Coastguard Worker
2174*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(return_code, ProfmanResult::kCompile);
2175*795d594fSAndroid Build Coastguard Worker
2176*795d594fSAndroid Build Coastguard Worker // Check that the result is the aggregation.
2177*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result;
2178*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(ref_profile.GetFd()));
2179*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(ref_info.MergeWith(cur_info));
2180*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Equals(ref_info));
2181*795d594fSAndroid Build Coastguard Worker }
2182*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,ForceMergeAndAnalyzeNoDelta)2183*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, ForceMergeAndAnalyzeNoDelta) {
2184*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsInRefProfile = 600;
2185*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsInCurProfile = 600;
2186*795d594fSAndroid Build Coastguard Worker
2187*795d594fSAndroid Build Coastguard Worker ScratchFile ref_profile;
2188*795d594fSAndroid Build Coastguard Worker ScratchFile cur_profile;
2189*795d594fSAndroid Build Coastguard Worker
2190*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo ref_info;
2191*795d594fSAndroid Build Coastguard Worker SetupProfile(
2192*795d594fSAndroid Build Coastguard Worker dex1, dex2, kNumberOfMethodsInRefProfile, /*number_of_classes=*/0, ref_profile, &ref_info);
2193*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo cur_info;
2194*795d594fSAndroid Build Coastguard Worker SetupProfile(
2195*795d594fSAndroid Build Coastguard Worker dex1, dex2, kNumberOfMethodsInCurProfile, /*number_of_classes=*/0, cur_profile, &cur_info);
2196*795d594fSAndroid Build Coastguard Worker
2197*795d594fSAndroid Build Coastguard Worker std::vector<std::string> extra_args({"--force-merge-and-analyze"});
2198*795d594fSAndroid Build Coastguard Worker int return_code = ProcessProfiles({cur_profile.GetFd()}, ref_profile.GetFd(), extra_args);
2199*795d594fSAndroid Build Coastguard Worker
2200*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(return_code, ProfmanResult::kSkipCompilationSmallDelta);
2201*795d594fSAndroid Build Coastguard Worker
2202*795d594fSAndroid Build Coastguard Worker // Check that the reference profile is unchanged.
2203*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result;
2204*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(ref_profile.GetFd()));
2205*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Equals(ref_info));
2206*795d594fSAndroid Build Coastguard Worker }
2207*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,ForceMergeAndAnalyzeEmptyProfiles)2208*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, ForceMergeAndAnalyzeEmptyProfiles) {
2209*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsInRefProfile = 0;
2210*795d594fSAndroid Build Coastguard Worker const uint16_t kNumberOfMethodsInCurProfile = 0;
2211*795d594fSAndroid Build Coastguard Worker
2212*795d594fSAndroid Build Coastguard Worker ScratchFile ref_profile;
2213*795d594fSAndroid Build Coastguard Worker ScratchFile cur_profile;
2214*795d594fSAndroid Build Coastguard Worker
2215*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo ref_info;
2216*795d594fSAndroid Build Coastguard Worker SetupProfile(
2217*795d594fSAndroid Build Coastguard Worker dex1, dex2, kNumberOfMethodsInRefProfile, /*number_of_classes=*/0, ref_profile, &ref_info);
2218*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo cur_info;
2219*795d594fSAndroid Build Coastguard Worker SetupProfile(
2220*795d594fSAndroid Build Coastguard Worker dex1, dex2, kNumberOfMethodsInCurProfile, /*number_of_classes=*/0, cur_profile, &cur_info);
2221*795d594fSAndroid Build Coastguard Worker
2222*795d594fSAndroid Build Coastguard Worker std::vector<std::string> extra_args({"--force-merge-and-analyze"});
2223*795d594fSAndroid Build Coastguard Worker int return_code = ProcessProfiles({cur_profile.GetFd()}, ref_profile.GetFd(), extra_args);
2224*795d594fSAndroid Build Coastguard Worker
2225*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(return_code, ProfmanResult::kSkipCompilationEmptyProfiles);
2226*795d594fSAndroid Build Coastguard Worker
2227*795d594fSAndroid Build Coastguard Worker // Check that the reference profile is unchanged.
2228*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result;
2229*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(ref_profile.GetFd()));
2230*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Equals(ref_info));
2231*795d594fSAndroid Build Coastguard Worker }
2232*795d594fSAndroid Build Coastguard Worker
2233*795d594fSAndroid Build Coastguard Worker // Test that we consider the annations when we merge boot image profiles.
TEST_F(ProfileAssistantTest,BootImageMergeWithAnnotations)2234*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, BootImageMergeWithAnnotations) {
2235*795d594fSAndroid Build Coastguard Worker ScratchFile profile;
2236*795d594fSAndroid Build Coastguard Worker ScratchFile reference_profile;
2237*795d594fSAndroid Build Coastguard Worker
2238*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({GetFd(profile)});
2239*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(reference_profile);
2240*795d594fSAndroid Build Coastguard Worker
2241*795d594fSAndroid Build Coastguard Worker // Use a real dex file to generate profile test data so that we can pass descriptors to profman.
2242*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ProfileTestMultiDex");
2243*795d594fSAndroid Build Coastguard Worker const DexFile& d1 = *dex_files[0];
2244*795d594fSAndroid Build Coastguard Worker const DexFile& d2 = *dex_files[1];
2245*795d594fSAndroid Build Coastguard Worker // The new profile info will contain the methods with indices 0-100.
2246*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info(/*for_boot_image=*/ true);
2247*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::ProfileSampleAnnotation psa1("package1");
2248*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::ProfileSampleAnnotation psa2("package2");
2249*795d594fSAndroid Build Coastguard Worker
2250*795d594fSAndroid Build Coastguard Worker AddMethod(&info, &d1, 0, Hotness::kFlagHot, psa1);
2251*795d594fSAndroid Build Coastguard Worker AddMethod(&info, &d2, 0, Hotness::kFlagHot, psa2);
2252*795d594fSAndroid Build Coastguard Worker info.Save(profile.GetFd());
2253*795d594fSAndroid Build Coastguard Worker
2254*795d594fSAndroid Build Coastguard Worker // Run profman and pass the dex file with --apk-fd.
2255*795d594fSAndroid Build Coastguard Worker android::base::unique_fd apk_fd(
2256*795d594fSAndroid Build Coastguard Worker // NOLINTNEXTLINE - Profman needs file to be opened after fork() and exec()
2257*795d594fSAndroid Build Coastguard Worker open(GetTestDexFileName("ProfileTestMultiDex").c_str(), O_RDONLY));
2258*795d594fSAndroid Build Coastguard Worker ASSERT_GE(apk_fd.get(), 0);
2259*795d594fSAndroid Build Coastguard Worker
2260*795d594fSAndroid Build Coastguard Worker std::string profman_cmd = GetProfmanCmd();
2261*795d594fSAndroid Build Coastguard Worker std::vector<std::string> argv_str;
2262*795d594fSAndroid Build Coastguard Worker argv_str.push_back(profman_cmd);
2263*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--profile-file-fd=" + std::to_string(profile.GetFd()));
2264*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile.GetFd()));
2265*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--apk-fd=" + std::to_string(apk_fd.get()));
2266*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--force-merge");
2267*795d594fSAndroid Build Coastguard Worker argv_str.push_back("--boot-image-merge");
2268*795d594fSAndroid Build Coastguard Worker std::string error;
2269*795d594fSAndroid Build Coastguard Worker
2270*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ExecAndReturnCode(argv_str, &error), ProfmanResult::kSuccess) << error;
2271*795d594fSAndroid Build Coastguard Worker
2272*795d594fSAndroid Build Coastguard Worker // Verify that we can load the result and that it equals to what we saved.
2273*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result(/*for_boot_image=*/ true);
2274*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(reference_profile_fd));
2275*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info.Equals(result));
2276*795d594fSAndroid Build Coastguard Worker }
2277*795d594fSAndroid Build Coastguard Worker
TEST_F(ProfileAssistantTest,DifferentProfileVersions)2278*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, DifferentProfileVersions) {
2279*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
2280*795d594fSAndroid Build Coastguard Worker ScratchFile profile2;
2281*795d594fSAndroid Build Coastguard Worker
2282*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info1(/*for_boot_image=*/ false);
2283*795d594fSAndroid Build Coastguard Worker info1.Save(profile1.GetFd());
2284*795d594fSAndroid Build Coastguard Worker
2285*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2(/*for_boot_image=*/ true);
2286*795d594fSAndroid Build Coastguard Worker info2.Save(profile2.GetFd());
2287*795d594fSAndroid Build Coastguard Worker
2288*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({ GetFd(profile1)});
2289*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(profile2);
2290*795d594fSAndroid Build Coastguard Worker std::vector<std::string> boot_image_args({"--boot-image-merge"});
2291*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd, boot_image_args),
2292*795d594fSAndroid Build Coastguard Worker ProfmanResult::kErrorDifferentVersions);
2293*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd), ProfmanResult::kErrorBadProfiles);
2294*795d594fSAndroid Build Coastguard Worker
2295*795d594fSAndroid Build Coastguard Worker // Reverse the order of the profiles to verify we get the same behaviour.
2296*795d594fSAndroid Build Coastguard Worker profile_fds[0] = GetFd(profile2);
2297*795d594fSAndroid Build Coastguard Worker reference_profile_fd = GetFd(profile1);
2298*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd, boot_image_args),
2299*795d594fSAndroid Build Coastguard Worker ProfmanResult::kErrorBadProfiles);
2300*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd),
2301*795d594fSAndroid Build Coastguard Worker ProfmanResult::kErrorDifferentVersions);
2302*795d594fSAndroid Build Coastguard Worker }
2303*795d594fSAndroid Build Coastguard Worker
2304*795d594fSAndroid Build Coastguard Worker // Under default behaviour we will abort if we cannot load a profile during a merge
2305*795d594fSAndroid Build Coastguard Worker // operation. However, if we pass --force-merge to force aggregation we should
2306*795d594fSAndroid Build Coastguard Worker // ignore files we cannot load
TEST_F(ProfileAssistantTest,ForceMergeIgnoreProfilesItCannotLoad)2307*795d594fSAndroid Build Coastguard Worker TEST_F(ProfileAssistantTest, ForceMergeIgnoreProfilesItCannotLoad) {
2308*795d594fSAndroid Build Coastguard Worker ScratchFile profile1;
2309*795d594fSAndroid Build Coastguard Worker ScratchFile profile2;
2310*795d594fSAndroid Build Coastguard Worker
2311*795d594fSAndroid Build Coastguard Worker // Write corrupt data in the first file.
2312*795d594fSAndroid Build Coastguard Worker std::string content = "giberish";
2313*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(profile1.GetFile()->WriteFully(content.c_str(), content.length()));
2314*795d594fSAndroid Build Coastguard Worker
2315*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo info2(/*for_boot_image=*/true);
2316*795d594fSAndroid Build Coastguard Worker info2.Save(profile2.GetFd());
2317*795d594fSAndroid Build Coastguard Worker
2318*795d594fSAndroid Build Coastguard Worker std::vector<int> profile_fds({GetFd(profile1)});
2319*795d594fSAndroid Build Coastguard Worker int reference_profile_fd = GetFd(profile2);
2320*795d594fSAndroid Build Coastguard Worker
2321*795d594fSAndroid Build Coastguard Worker // With force-merge we should merge successfully.
2322*795d594fSAndroid Build Coastguard Worker {
2323*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(
2324*795d594fSAndroid Build Coastguard Worker ProcessProfiles(
2325*795d594fSAndroid Build Coastguard Worker profile_fds, reference_profile_fd, {"--force-merge-and-analyze", "--boot-image-merge"}),
2326*795d594fSAndroid Build Coastguard Worker ProfmanResult::kSkipCompilationEmptyProfiles);
2327*795d594fSAndroid Build Coastguard Worker
2328*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result(/*for_boot_image=*/true);
2329*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(reference_profile_fd));
2330*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info2.Equals(result));
2331*795d594fSAndroid Build Coastguard Worker }
2332*795d594fSAndroid Build Coastguard Worker
2333*795d594fSAndroid Build Coastguard Worker // Same for the legacy force merge mode.
2334*795d594fSAndroid Build Coastguard Worker {
2335*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(
2336*795d594fSAndroid Build Coastguard Worker ProcessProfiles(profile_fds, reference_profile_fd, {"--force-merge", "--boot-image-merge"}),
2337*795d594fSAndroid Build Coastguard Worker ProfmanResult::kSuccess);
2338*795d594fSAndroid Build Coastguard Worker
2339*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo result(/*for_boot_image=*/true);
2340*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(result.Load(reference_profile_fd));
2341*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(info2.Equals(result));
2342*795d594fSAndroid Build Coastguard Worker }
2343*795d594fSAndroid Build Coastguard Worker
2344*795d594fSAndroid Build Coastguard Worker // Without force-merge we should fail.
2345*795d594fSAndroid Build Coastguard Worker {
2346*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ProcessProfiles(profile_fds, reference_profile_fd, {"--boot-image-merge"}),
2347*795d594fSAndroid Build Coastguard Worker ProfmanResult::kErrorBadProfiles);
2348*795d594fSAndroid Build Coastguard Worker }
2349*795d594fSAndroid Build Coastguard Worker }
2350*795d594fSAndroid Build Coastguard Worker
2351*795d594fSAndroid Build Coastguard Worker } // namespace art
2352