blob: 52f3b52ee2225b6e3af5d333f7adb82e9c9eec8a [file] [log] [blame]
Calin Juravle2e2db782016-02-23 12:00:03 +00001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
Calin Juravlee0ac1152017-02-13 19:03:47 -080019#include "art_method-inl.h"
Calin Juravle2e2db782016-02-23 12:00:03 +000020#include "base/unix_file/fd_file.h"
21#include "common_runtime_test.h"
David Sehr97c381e2017-02-01 15:09:58 -080022#include "exec_utils.h"
Calin Juravle33083d62017-01-18 15:29:12 -080023#include "jit/profile_compilation_info.h"
Calin Juravlee0ac1152017-02-13 19:03:47 -080024#include "mirror/class-inl.h"
25#include "profile_assistant.h"
26#include "scoped_thread_state_change-inl.h"
Calin Juravle2e2db782016-02-23 12:00:03 +000027#include "utils.h"
28
29namespace art {
30
31class ProfileAssistantTest : public CommonRuntimeTest {
32 protected:
33 void SetupProfile(const std::string& id,
34 uint32_t checksum,
35 uint16_t number_of_methods,
Calin Juravlec824b512016-03-29 20:33:33 +010036 uint16_t number_of_classes,
Calin Juravle2e2db782016-02-23 12:00:03 +000037 const ScratchFile& profile,
38 ProfileCompilationInfo* info,
39 uint16_t start_method_index = 0) {
40 std::string dex_location1 = "location1" + id;
41 uint32_t dex_location_checksum1 = checksum;
42 std::string dex_location2 = "location2" + id;
43 uint32_t dex_location_checksum2 = 10 * checksum;
44 for (uint16_t i = start_method_index; i < start_method_index + number_of_methods; i++) {
Mathieu Chartierc5dd3192015-12-09 16:38:30 -080045 ASSERT_TRUE(info->AddMethodIndex(dex_location1, dex_location_checksum1, i));
46 ASSERT_TRUE(info->AddMethodIndex(dex_location2, dex_location_checksum2, i));
Calin Juravle2e2db782016-02-23 12:00:03 +000047 }
Calin Juravlec824b512016-03-29 20:33:33 +010048 for (uint16_t i = 0; i < number_of_classes; i++) {
Andreas Gampea5b09a62016-11-17 15:21:22 -080049 ASSERT_TRUE(info->AddClassIndex(dex_location1, dex_location_checksum1, dex::TypeIndex(i)));
Calin Juravlec824b512016-03-29 20:33:33 +010050 }
51
Calin Juravle2e2db782016-02-23 12:00:03 +000052 ASSERT_TRUE(info->Save(GetFd(profile)));
53 ASSERT_EQ(0, profile.GetFile()->Flush());
54 ASSERT_TRUE(profile.GetFile()->ResetOffset());
55 }
56
57 int GetFd(const ScratchFile& file) const {
58 return static_cast<int>(file.GetFd());
59 }
60
61 void CheckProfileInfo(ScratchFile& file, const ProfileCompilationInfo& info) {
62 ProfileCompilationInfo file_info;
63 ASSERT_TRUE(file.GetFile()->ResetOffset());
64 ASSERT_TRUE(file_info.Load(GetFd(file)));
65 ASSERT_TRUE(file_info.Equals(info));
66 }
67
Calin Juravle7bcdb532016-06-07 16:14:47 +010068 std::string GetProfmanCmd() {
Calin Juravle2e2db782016-02-23 12:00:03 +000069 std::string file_path = GetTestAndroidRoot();
Calin Juravlede4fb632016-02-23 16:53:30 +000070 file_path += "/bin/profman";
Calin Juravle2e2db782016-02-23 12:00:03 +000071 if (kIsDebugBuild) {
72 file_path += "d";
73 }
Calin Juravle7bcdb532016-06-07 16:14:47 +010074 EXPECT_TRUE(OS::FileExists(file_path.c_str()))
75 << file_path << " should be a valid file path";
76 return file_path;
77 }
78 // Runs test with given arguments.
79 int ProcessProfiles(const std::vector<int>& profiles_fd, int reference_profile_fd) {
80 std::string profman_cmd = GetProfmanCmd();
Calin Juravle2e2db782016-02-23 12:00:03 +000081 std::vector<std::string> argv_str;
Calin Juravle7bcdb532016-06-07 16:14:47 +010082 argv_str.push_back(profman_cmd);
Calin Juravle2e2db782016-02-23 12:00:03 +000083 for (size_t k = 0; k < profiles_fd.size(); k++) {
84 argv_str.push_back("--profile-file-fd=" + std::to_string(profiles_fd[k]));
85 }
86 argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile_fd));
87
88 std::string error;
89 return ExecAndReturnCode(argv_str, &error);
90 }
Calin Juravle7bcdb532016-06-07 16:14:47 +010091
92 bool GenerateTestProfile(const std::string& filename) {
93 std::string profman_cmd = GetProfmanCmd();
94 std::vector<std::string> argv_str;
95 argv_str.push_back(profman_cmd);
96 argv_str.push_back("--generate-test-profile=" + filename);
97 std::string error;
98 return ExecAndReturnCode(argv_str, &error);
99 }
David Sehr7c80f2d2017-02-07 16:47:58 -0800100
Calin Juravlee0ac1152017-02-13 19:03:47 -0800101 bool CreateProfile(std::string profile_file_contents,
102 const std::string& filename,
103 const std::string& dex_location) {
David Sehr7c80f2d2017-02-07 16:47:58 -0800104 ScratchFile class_names_file;
105 File* file = class_names_file.GetFile();
Calin Juravlee0ac1152017-02-13 19:03:47 -0800106 EXPECT_TRUE(file->WriteFully(profile_file_contents.c_str(), profile_file_contents.length()));
David Sehr7c80f2d2017-02-07 16:47:58 -0800107 EXPECT_EQ(0, file->Flush());
108 EXPECT_TRUE(file->ResetOffset());
109 std::string profman_cmd = GetProfmanCmd();
110 std::vector<std::string> argv_str;
111 argv_str.push_back(profman_cmd);
112 argv_str.push_back("--create-profile-from=" + class_names_file.GetFilename());
113 argv_str.push_back("--reference-profile-file=" + filename);
Calin Juravlee0ac1152017-02-13 19:03:47 -0800114 argv_str.push_back("--apk=" + dex_location);
115 argv_str.push_back("--dex-location=" + dex_location);
David Sehr7c80f2d2017-02-07 16:47:58 -0800116 std::string error;
117 EXPECT_EQ(ExecAndReturnCode(argv_str, &error), 0);
118 return true;
119 }
120
121 bool DumpClasses(const std::string& filename, std::string* file_contents) {
122 ScratchFile class_names_file;
123 std::string profman_cmd = GetProfmanCmd();
124 std::vector<std::string> argv_str;
125 argv_str.push_back(profman_cmd);
126 argv_str.push_back("--dump-classes");
127 argv_str.push_back("--profile-file=" + filename);
128 argv_str.push_back("--apk=" + GetLibCoreDexFileNames()[0]);
Calin Juravlee0ac1152017-02-13 19:03:47 -0800129 argv_str.push_back("--dex-location=" + GetLibCoreDexFileNames()[0]);
David Sehr7c80f2d2017-02-07 16:47:58 -0800130 argv_str.push_back("--dump-output-to-fd=" + std::to_string(GetFd(class_names_file)));
131 std::string error;
132 EXPECT_EQ(ExecAndReturnCode(argv_str, &error), 0);
133 File* file = class_names_file.GetFile();
134 EXPECT_EQ(0, file->Flush());
135 EXPECT_TRUE(file->ResetOffset());
136 int64_t length = file->GetLength();
137 std::unique_ptr<char[]> buf(new char[length]);
138 EXPECT_EQ(file->Read(buf.get(), length, 0), length);
139 *file_contents = std::string(buf.get(), length);
140 return true;
141 }
142
143 bool CreateAndDump(const std::string& input_file_contents, std::string* output_file_contents) {
144 ScratchFile profile_file;
Calin Juravlee0ac1152017-02-13 19:03:47 -0800145 EXPECT_TRUE(CreateProfile(input_file_contents,
146 profile_file.GetFilename(),
147 GetLibCoreDexFileNames()[0]));
David Sehr7c80f2d2017-02-07 16:47:58 -0800148 profile_file.GetFile()->ResetOffset();
149 EXPECT_TRUE(DumpClasses(profile_file.GetFilename(), output_file_contents));
150 return true;
151 }
Calin Juravlee0ac1152017-02-13 19:03:47 -0800152
153 mirror::Class* GetClass(jobject class_loader, const std::string& clazz) {
154 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
155 Thread* self = Thread::Current();
156 ScopedObjectAccess soa(self);
157 StackHandleScope<1> hs(self);
158 Handle<mirror::ClassLoader> h_loader(
159 hs.NewHandle(self->DecodeJObject(class_loader)->AsClassLoader()));
160 return class_linker->FindClass(self, clazz.c_str(), h_loader);
161 }
162
163 ArtMethod* GetVirtualMethod(jobject class_loader,
164 const std::string& clazz,
165 const std::string& name) {
166 mirror::Class* klass = GetClass(class_loader, clazz);
167 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
168 const auto pointer_size = class_linker->GetImagePointerSize();
169 ArtMethod* method = nullptr;
170 Thread* self = Thread::Current();
171 ScopedObjectAccess soa(self);
172 for (auto& m : klass->GetVirtualMethods(pointer_size)) {
173 if (name == m.GetName()) {
174 EXPECT_TRUE(method == nullptr);
175 method = &m;
176 }
177 }
178 return method;
179 }
180
181 // Verify that given method has the expected inline caches and nothing else.
182 void AssertInlineCaches(ArtMethod* method,
183 const std::set<mirror::Class*>& expected_clases,
184 const ProfileCompilationInfo& info,
Calin Juravle589e71e2017-03-03 16:05:05 -0800185 bool is_megamorphic,
186 bool is_missing_types)
Calin Juravlee0ac1152017-02-13 19:03:47 -0800187 REQUIRES_SHARED(Locks::mutator_lock_) {
188 ProfileCompilationInfo::OfflineProfileMethodInfo pmi;
189 ASSERT_TRUE(info.GetMethod(method->GetDexFile()->GetLocation(),
190 method->GetDexFile()->GetLocationChecksum(),
191 method->GetDexMethodIndex(),
192 &pmi));
193 ASSERT_EQ(pmi.inline_caches.size(), 1u);
194 ProfileCompilationInfo::DexPcData dex_pc_data = pmi.inline_caches.begin()->second;
195
Calin Juravle589e71e2017-03-03 16:05:05 -0800196 ASSERT_EQ(dex_pc_data.is_megamorphic, is_megamorphic);
197 ASSERT_EQ(dex_pc_data.is_missing_types, is_missing_types);
Calin Juravlee0ac1152017-02-13 19:03:47 -0800198 ASSERT_EQ(expected_clases.size(), dex_pc_data.classes.size());
199 size_t found = 0;
200 for (mirror::Class* it : expected_clases) {
201 for (const auto& class_ref : dex_pc_data.classes) {
202 ProfileCompilationInfo::DexReference dex_ref =
203 pmi.dex_references[class_ref.dex_profile_index];
204 if (dex_ref.MatchesDex(&(it->GetDexFile())) &&
205 class_ref.type_index == it->GetDexTypeIndex()) {
206 found++;
207 }
208 }
209 }
210
211 ASSERT_EQ(expected_clases.size(), found);
212 }
Calin Juravle2e2db782016-02-23 12:00:03 +0000213};
214
215TEST_F(ProfileAssistantTest, AdviseCompilationEmptyReferences) {
216 ScratchFile profile1;
217 ScratchFile profile2;
218 ScratchFile reference_profile;
219
220 std::vector<int> profile_fds({
221 GetFd(profile1),
222 GetFd(profile2)});
223 int reference_profile_fd = GetFd(reference_profile);
224
225 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
226 ProfileCompilationInfo info1;
Calin Juravlec824b512016-03-29 20:33:33 +0100227 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
Calin Juravle2e2db782016-02-23 12:00:03 +0000228 ProfileCompilationInfo info2;
Calin Juravlec824b512016-03-29 20:33:33 +0100229 SetupProfile("p2", 2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
Calin Juravle2e2db782016-02-23 12:00:03 +0000230
231 // We should advise compilation.
232 ASSERT_EQ(ProfileAssistant::kCompile,
233 ProcessProfiles(profile_fds, reference_profile_fd));
234 // The resulting compilation info must be equal to the merge of the inputs.
235 ProfileCompilationInfo result;
236 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
237 ASSERT_TRUE(result.Load(reference_profile_fd));
238
239 ProfileCompilationInfo expected;
Calin Juravle67265462016-03-18 16:23:40 +0000240 ASSERT_TRUE(expected.MergeWith(info1));
241 ASSERT_TRUE(expected.MergeWith(info2));
Calin Juravle2e2db782016-02-23 12:00:03 +0000242 ASSERT_TRUE(expected.Equals(result));
243
244 // The information from profiles must remain the same.
245 CheckProfileInfo(profile1, info1);
246 CheckProfileInfo(profile2, info2);
247}
248
Calin Juravlec824b512016-03-29 20:33:33 +0100249// TODO(calin): Add more tests for classes.
250TEST_F(ProfileAssistantTest, AdviseCompilationEmptyReferencesBecauseOfClasses) {
251 ScratchFile profile1;
252 ScratchFile reference_profile;
253
254 std::vector<int> profile_fds({
255 GetFd(profile1)});
256 int reference_profile_fd = GetFd(reference_profile);
257
258 const uint16_t kNumberOfClassesToEnableCompilation = 100;
259 ProfileCompilationInfo info1;
260 SetupProfile("p1", 1, 0, kNumberOfClassesToEnableCompilation, profile1, &info1);
261
262 // We should advise compilation.
263 ASSERT_EQ(ProfileAssistant::kCompile,
264 ProcessProfiles(profile_fds, reference_profile_fd));
265 // The resulting compilation info must be equal to the merge of the inputs.
266 ProfileCompilationInfo result;
267 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
268 ASSERT_TRUE(result.Load(reference_profile_fd));
269
270 ProfileCompilationInfo expected;
271 ASSERT_TRUE(expected.MergeWith(info1));
272 ASSERT_TRUE(expected.Equals(result));
273
274 // The information from profiles must remain the same.
275 CheckProfileInfo(profile1, info1);
276}
277
Calin Juravle2e2db782016-02-23 12:00:03 +0000278TEST_F(ProfileAssistantTest, AdviseCompilationNonEmptyReferences) {
279 ScratchFile profile1;
280 ScratchFile profile2;
281 ScratchFile reference_profile;
282
283 std::vector<int> profile_fds({
284 GetFd(profile1),
285 GetFd(profile2)});
286 int reference_profile_fd = GetFd(reference_profile);
287
288 // The new profile info will contain the methods with indices 0-100.
289 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
290 ProfileCompilationInfo info1;
Calin Juravlec824b512016-03-29 20:33:33 +0100291 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
Calin Juravle2e2db782016-02-23 12:00:03 +0000292 ProfileCompilationInfo info2;
Calin Juravlec824b512016-03-29 20:33:33 +0100293 SetupProfile("p2", 2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
Calin Juravle2e2db782016-02-23 12:00:03 +0000294
295
296 // The reference profile info will contain the methods with indices 50-150.
297 const uint16_t kNumberOfMethodsAlreadyCompiled = 100;
298 ProfileCompilationInfo reference_info;
Calin Juravlec824b512016-03-29 20:33:33 +0100299 SetupProfile("p1", 1, kNumberOfMethodsAlreadyCompiled, 0, reference_profile,
Calin Juravle2e2db782016-02-23 12:00:03 +0000300 &reference_info, kNumberOfMethodsToEnableCompilation / 2);
301
302 // We should advise compilation.
303 ASSERT_EQ(ProfileAssistant::kCompile,
304 ProcessProfiles(profile_fds, reference_profile_fd));
305
306 // The resulting compilation info must be equal to the merge of the inputs
307 ProfileCompilationInfo result;
308 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
309 ASSERT_TRUE(result.Load(reference_profile_fd));
310
311 ProfileCompilationInfo expected;
Calin Juravle67265462016-03-18 16:23:40 +0000312 ASSERT_TRUE(expected.MergeWith(info1));
313 ASSERT_TRUE(expected.MergeWith(info2));
314 ASSERT_TRUE(expected.MergeWith(reference_info));
Calin Juravle2e2db782016-02-23 12:00:03 +0000315 ASSERT_TRUE(expected.Equals(result));
316
317 // The information from profiles must remain the same.
318 CheckProfileInfo(profile1, info1);
319 CheckProfileInfo(profile2, info2);
320}
321
322TEST_F(ProfileAssistantTest, DoNotAdviseCompilation) {
323 ScratchFile profile1;
324 ScratchFile profile2;
325 ScratchFile reference_profile;
326
327 std::vector<int> profile_fds({
328 GetFd(profile1),
329 GetFd(profile2)});
330 int reference_profile_fd = GetFd(reference_profile);
331
332 const uint16_t kNumberOfMethodsToSkipCompilation = 1;
333 ProfileCompilationInfo info1;
Calin Juravlec824b512016-03-29 20:33:33 +0100334 SetupProfile("p1", 1, kNumberOfMethodsToSkipCompilation, 0, profile1, &info1);
Calin Juravle2e2db782016-02-23 12:00:03 +0000335 ProfileCompilationInfo info2;
Calin Juravlec824b512016-03-29 20:33:33 +0100336 SetupProfile("p2", 2, kNumberOfMethodsToSkipCompilation, 0, profile2, &info2);
Calin Juravle2e2db782016-02-23 12:00:03 +0000337
338 // We should not advise compilation.
339 ASSERT_EQ(ProfileAssistant::kSkipCompilation,
340 ProcessProfiles(profile_fds, reference_profile_fd));
341
342 // The information from profiles must remain the same.
343 ProfileCompilationInfo file_info1;
344 ASSERT_TRUE(profile1.GetFile()->ResetOffset());
345 ASSERT_TRUE(file_info1.Load(GetFd(profile1)));
346 ASSERT_TRUE(file_info1.Equals(info1));
347
348 ProfileCompilationInfo file_info2;
349 ASSERT_TRUE(profile2.GetFile()->ResetOffset());
350 ASSERT_TRUE(file_info2.Load(GetFd(profile2)));
351 ASSERT_TRUE(file_info2.Equals(info2));
352
353 // Reference profile files must remain empty.
354 ASSERT_EQ(0, reference_profile.GetFile()->GetLength());
355
356 // The information from profiles must remain the same.
357 CheckProfileInfo(profile1, info1);
358 CheckProfileInfo(profile2, info2);
359}
360
361TEST_F(ProfileAssistantTest, FailProcessingBecauseOfProfiles) {
362 ScratchFile profile1;
363 ScratchFile profile2;
364 ScratchFile reference_profile;
365
366 std::vector<int> profile_fds({
367 GetFd(profile1),
368 GetFd(profile2)});
369 int reference_profile_fd = GetFd(reference_profile);
370
371 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
372 // Assign different hashes for the same dex file. This will make merging of information to fail.
373 ProfileCompilationInfo info1;
Calin Juravlec824b512016-03-29 20:33:33 +0100374 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
Calin Juravle2e2db782016-02-23 12:00:03 +0000375 ProfileCompilationInfo info2;
Calin Juravlec824b512016-03-29 20:33:33 +0100376 SetupProfile("p1", 2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
Calin Juravle2e2db782016-02-23 12:00:03 +0000377
378 // We should fail processing.
379 ASSERT_EQ(ProfileAssistant::kErrorBadProfiles,
380 ProcessProfiles(profile_fds, reference_profile_fd));
381
382 // The information from profiles must remain the same.
383 CheckProfileInfo(profile1, info1);
384 CheckProfileInfo(profile2, info2);
385
386 // Reference profile files must still remain empty.
387 ASSERT_EQ(0, reference_profile.GetFile()->GetLength());
388}
389
390TEST_F(ProfileAssistantTest, FailProcessingBecauseOfReferenceProfiles) {
391 ScratchFile profile1;
392 ScratchFile reference_profile;
393
394 std::vector<int> profile_fds({
395 GetFd(profile1)});
396 int reference_profile_fd = GetFd(reference_profile);
397
398 const uint16_t kNumberOfMethodsToEnableCompilation = 100;
399 // Assign different hashes for the same dex file. This will make merging of information to fail.
400 ProfileCompilationInfo info1;
Calin Juravlec824b512016-03-29 20:33:33 +0100401 SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
Calin Juravle2e2db782016-02-23 12:00:03 +0000402 ProfileCompilationInfo reference_info;
Calin Juravlec824b512016-03-29 20:33:33 +0100403 SetupProfile("p1", 2, kNumberOfMethodsToEnableCompilation, 0, reference_profile, &reference_info);
Calin Juravle2e2db782016-02-23 12:00:03 +0000404
405 // We should not advise compilation.
406 ASSERT_TRUE(profile1.GetFile()->ResetOffset());
407 ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
408 ASSERT_EQ(ProfileAssistant::kErrorBadProfiles,
409 ProcessProfiles(profile_fds, reference_profile_fd));
410
411 // The information from profiles must remain the same.
412 CheckProfileInfo(profile1, info1);
413}
414
Calin Juravle7bcdb532016-06-07 16:14:47 +0100415TEST_F(ProfileAssistantTest, TestProfileGeneration) {
416 ScratchFile profile;
417 // Generate a test profile.
418 GenerateTestProfile(profile.GetFilename());
419
420 // Verify that the generated profile is valid and can be loaded.
421 ASSERT_TRUE(profile.GetFile()->ResetOffset());
422 ProfileCompilationInfo info;
423 ASSERT_TRUE(info.Load(GetFd(profile)));
424}
425
David Sehr7c80f2d2017-02-07 16:47:58 -0800426TEST_F(ProfileAssistantTest, TestProfileCreationAllMatch) {
427 // Class names put here need to be in sorted order.
428 std::vector<std::string> class_names = {
Calin Juravlee0ac1152017-02-13 19:03:47 -0800429 "Ljava/lang/Comparable;",
430 "Ljava/lang/Math;",
431 "Ljava/lang/Object;"
David Sehr7c80f2d2017-02-07 16:47:58 -0800432 };
433 std::string input_file_contents;
Calin Juravlee0ac1152017-02-13 19:03:47 -0800434 std::string expected_contents;
David Sehr7c80f2d2017-02-07 16:47:58 -0800435 for (std::string& class_name : class_names) {
436 input_file_contents += class_name + std::string("\n");
Calin Juravlee0ac1152017-02-13 19:03:47 -0800437 expected_contents += DescriptorToDot(class_name.c_str()) +
438 std::string("\n");
David Sehr7c80f2d2017-02-07 16:47:58 -0800439 }
440 std::string output_file_contents;
441 ASSERT_TRUE(CreateAndDump(input_file_contents, &output_file_contents));
Calin Juravlee0ac1152017-02-13 19:03:47 -0800442 ASSERT_EQ(output_file_contents, expected_contents);
David Sehr7c80f2d2017-02-07 16:47:58 -0800443}
444
445TEST_F(ProfileAssistantTest, TestProfileCreationOneNotMatched) {
446 // Class names put here need to be in sorted order.
447 std::vector<std::string> class_names = {
Calin Juravlee0ac1152017-02-13 19:03:47 -0800448 "Ldoesnt/match/this/one;",
449 "Ljava/lang/Comparable;",
450 "Ljava/lang/Object;"
David Sehr7c80f2d2017-02-07 16:47:58 -0800451 };
452 std::string input_file_contents;
453 for (std::string& class_name : class_names) {
454 input_file_contents += class_name + std::string("\n");
455 }
456 std::string output_file_contents;
457 ASSERT_TRUE(CreateAndDump(input_file_contents, &output_file_contents));
458 std::string expected_contents =
Calin Juravlee0ac1152017-02-13 19:03:47 -0800459 DescriptorToDot(class_names[1].c_str()) + std::string("\n") +
460 DescriptorToDot(class_names[2].c_str()) + std::string("\n");
David Sehr7c80f2d2017-02-07 16:47:58 -0800461 ASSERT_EQ(output_file_contents, expected_contents);
462}
463
464TEST_F(ProfileAssistantTest, TestProfileCreationNoneMatched) {
465 // Class names put here need to be in sorted order.
466 std::vector<std::string> class_names = {
Calin Juravlee0ac1152017-02-13 19:03:47 -0800467 "Ldoesnt/match/this/one;",
468 "Ldoesnt/match/this/one/either;",
469 "Lnor/this/one;"
David Sehr7c80f2d2017-02-07 16:47:58 -0800470 };
471 std::string input_file_contents;
472 for (std::string& class_name : class_names) {
473 input_file_contents += class_name + std::string("\n");
474 }
475 std::string output_file_contents;
476 ASSERT_TRUE(CreateAndDump(input_file_contents, &output_file_contents));
477 std::string expected_contents("");
478 ASSERT_EQ(output_file_contents, expected_contents);
479}
480
Calin Juravlee0ac1152017-02-13 19:03:47 -0800481TEST_F(ProfileAssistantTest, TestProfileCreateInlineCache) {
482 // Create the profile content.
483 std::vector<std::string> methods = {
484 "LTestInline;->inlineMonomorphic(LSuper;)I+LSubA;",
485 "LTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;",
486 "LTestInline;->inlineMegamorphic(LSuper;)I+LSubA;,LSubB;,LSubC;,LSubD;,LSubE;",
Calin Juravle589e71e2017-03-03 16:05:05 -0800487 "LTestInline;->inlineMissingTypes(LSuper;)I+missing_types",
Calin Juravlee0ac1152017-02-13 19:03:47 -0800488 "LTestInline;->noInlineCache(LSuper;)I"
489 };
490 std::string input_file_contents;
491 for (std::string& m : methods) {
492 input_file_contents += m + std::string("\n");
493 }
494
495 // Create the profile and save it to disk.
496 ScratchFile profile_file;
497 ASSERT_TRUE(CreateProfile(input_file_contents,
498 profile_file.GetFilename(),
499 GetTestDexFileName("ProfileTestMultiDex")));
500
501 // Load the profile from disk.
502 ProfileCompilationInfo info;
503 profile_file.GetFile()->ResetOffset();
504 ASSERT_TRUE(info.Load(GetFd(profile_file)));
505
506 // Load the dex files and verify that the profile contains the expected methods info.
507 ScopedObjectAccess soa(Thread::Current());
508 jobject class_loader = LoadDex("ProfileTestMultiDex");
509 ASSERT_NE(class_loader, nullptr);
510
511 mirror::Class* sub_a = GetClass(class_loader, "LSubA;");
512 mirror::Class* sub_b = GetClass(class_loader, "LSubB;");
513 mirror::Class* sub_c = GetClass(class_loader, "LSubC;");
514
515 ASSERT_TRUE(sub_a != nullptr);
516 ASSERT_TRUE(sub_b != nullptr);
517 ASSERT_TRUE(sub_c != nullptr);
518
519 {
520 // Verify that method inlineMonomorphic has the expected inline caches and nothing else.
521 ArtMethod* inline_monomorphic = GetVirtualMethod(class_loader,
522 "LTestInline;",
523 "inlineMonomorphic");
524 ASSERT_TRUE(inline_monomorphic != nullptr);
525 std::set<mirror::Class*> expected_monomorphic;
526 expected_monomorphic.insert(sub_a);
Calin Juravle589e71e2017-03-03 16:05:05 -0800527 AssertInlineCaches(inline_monomorphic,
528 expected_monomorphic,
529 info,
530 /*megamorphic*/false,
531 /*missing_types*/false);
Calin Juravlee0ac1152017-02-13 19:03:47 -0800532 }
533
534 {
535 // Verify that method inlinePolymorphic has the expected inline caches and nothing else.
536 ArtMethod* inline_polymorhic = GetVirtualMethod(class_loader,
537 "LTestInline;",
538 "inlinePolymorphic");
539 ASSERT_TRUE(inline_polymorhic != nullptr);
540 std::set<mirror::Class*> expected_polymorphic;
541 expected_polymorphic.insert(sub_a);
542 expected_polymorphic.insert(sub_b);
543 expected_polymorphic.insert(sub_c);
Calin Juravle589e71e2017-03-03 16:05:05 -0800544 AssertInlineCaches(inline_polymorhic,
545 expected_polymorphic,
546 info,
547 /*megamorphic*/false,
548 /*missing_types*/false);
Calin Juravlee0ac1152017-02-13 19:03:47 -0800549 }
550
551 {
552 // Verify that method inlineMegamorphic has the expected inline caches and nothing else.
553 ArtMethod* inline_megamorphic = GetVirtualMethod(class_loader,
554 "LTestInline;",
555 "inlineMegamorphic");
556 ASSERT_TRUE(inline_megamorphic != nullptr);
557 std::set<mirror::Class*> expected_megamorphic;
Calin Juravle589e71e2017-03-03 16:05:05 -0800558 AssertInlineCaches(inline_megamorphic,
559 expected_megamorphic,
560 info,
561 /*megamorphic*/true,
562 /*missing_types*/false);
563 }
564
565 {
566 // Verify that method inlineMegamorphic has the expected inline caches and nothing else.
567 ArtMethod* inline_missing_types = GetVirtualMethod(class_loader,
568 "LTestInline;",
569 "inlineMissingTypes");
570 ASSERT_TRUE(inline_missing_types != nullptr);
571 std::set<mirror::Class*> expected_missing_Types;
572 AssertInlineCaches(inline_missing_types,
573 expected_missing_Types,
574 info,
575 /*megamorphic*/false,
576 /*missing_types*/true);
Calin Juravlee0ac1152017-02-13 19:03:47 -0800577 }
578
579 {
580 // Verify that method noInlineCache has no inline caches in the profile.
581 ArtMethod* no_inline_cache = GetVirtualMethod(class_loader, "LTestInline;", "noInlineCache");
582 ASSERT_TRUE(no_inline_cache != nullptr);
583 ProfileCompilationInfo::OfflineProfileMethodInfo pmi_no_inline_cache;
584 ASSERT_TRUE(info.GetMethod(no_inline_cache->GetDexFile()->GetLocation(),
585 no_inline_cache->GetDexFile()->GetLocationChecksum(),
586 no_inline_cache->GetDexMethodIndex(),
587 &pmi_no_inline_cache));
588 ASSERT_TRUE(pmi_no_inline_cache.inline_caches.empty());
589 }
590}
591
Calin Juravle2e2db782016-02-23 12:00:03 +0000592} // namespace art