1877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle/*
2877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle * Copyright (C) 2016 The Android Open Source Project
3877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle *
4877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle * Licensed under the Apache License, Version 2.0 (the "License");
5877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle * you may not use this file except in compliance with the License.
6877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle * You may obtain a copy of the License at
7877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle *
8877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle *      http://www.apache.org/licenses/LICENSE-2.0
9877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle *
10877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle * Unless required by applicable law or agreed to in writing, software
11877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle * distributed under the License is distributed on an "AS IS" BASIS,
12877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle * See the License for the specific language governing permissions and
14877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle * limitations under the License.
15877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle */
16877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
17877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle#include <gtest/gtest.h>
18877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
19e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle#include "art_method-inl.h"
20877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle#include "base/unix_file/fd_file.h"
21877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle#include "common_runtime_test.h"
2297c381e3ce34cd327c2ec35fa850bd0eaa9b697fDavid Sehr#include "exec_utils.h"
2333083d626dbf2c8b06badfd73f50e98114483059Calin Juravle#include "jit/profile_compilation_info.h"
24e276589f2f14f217018f323f5457790b84569fb4Calin Juravle#include "linear_alloc.h"
25e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle#include "mirror/class-inl.h"
26d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier#include "obj_ptr-inl.h"
27e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle#include "profile_assistant.h"
28e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle#include "scoped_thread_state_change-inl.h"
292e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle#include "utils.h"
30877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
31877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravlenamespace art {
32877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
33877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravleclass ProfileAssistantTest : public CommonRuntimeTest {
34e276589f2f14f217018f323f5457790b84569fb4Calin Juravle public:
35e276589f2f14f217018f323f5457790b84569fb4Calin Juravle  void PostRuntimeCreate() OVERRIDE {
36e276589f2f14f217018f323f5457790b84569fb4Calin Juravle    arena_.reset(new ArenaAllocator(Runtime::Current()->GetArenaPool()));
37e276589f2f14f217018f323f5457790b84569fb4Calin Juravle  }
38e276589f2f14f217018f323f5457790b84569fb4Calin Juravle
39877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle protected:
40877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  void SetupProfile(const std::string& id,
41877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle                    uint32_t checksum,
42877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle                    uint16_t number_of_methods,
43c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle                    uint16_t number_of_classes,
44877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle                    const ScratchFile& profile,
45877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle                    ProfileCompilationInfo* info,
463402101b1351afdff5f963cada14808565c270c8Calin Juravle                    uint16_t start_method_index = 0,
473402101b1351afdff5f963cada14808565c270c8Calin Juravle                    bool reverse_dex_write_order = false) {
48877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle    std::string dex_location1 = "location1" + id;
49877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle    uint32_t dex_location_checksum1 = checksum;
50877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle    std::string dex_location2 = "location2" + id;
51877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle    uint32_t dex_location_checksum2 = 10 * checksum;
52877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle    for (uint16_t i = start_method_index; i < start_method_index + number_of_methods; i++) {
533402101b1351afdff5f963cada14808565c270c8Calin Juravle      // reverse_dex_write_order controls the order in which the dex files will be added to
543402101b1351afdff5f963cada14808565c270c8Calin Juravle      // the profile and thus written to disk.
553402101b1351afdff5f963cada14808565c270c8Calin Juravle      ProfileCompilationInfo::OfflineProfileMethodInfo pmi =
563402101b1351afdff5f963cada14808565c270c8Calin Juravle          GetOfflineProfileMethodInfo(dex_location1, dex_location_checksum1,
573402101b1351afdff5f963cada14808565c270c8Calin Juravle                                      dex_location2, dex_location_checksum2);
583402101b1351afdff5f963cada14808565c270c8Calin Juravle      if (reverse_dex_write_order) {
593402101b1351afdff5f963cada14808565c270c8Calin Juravle        ASSERT_TRUE(info->AddMethod(dex_location2, dex_location_checksum2, i, pmi));
603402101b1351afdff5f963cada14808565c270c8Calin Juravle        ASSERT_TRUE(info->AddMethod(dex_location1, dex_location_checksum1, i, pmi));
613402101b1351afdff5f963cada14808565c270c8Calin Juravle      } else {
623402101b1351afdff5f963cada14808565c270c8Calin Juravle        ASSERT_TRUE(info->AddMethod(dex_location1, dex_location_checksum1, i, pmi));
633402101b1351afdff5f963cada14808565c270c8Calin Juravle        ASSERT_TRUE(info->AddMethod(dex_location2, dex_location_checksum2, i, pmi));
643402101b1351afdff5f963cada14808565c270c8Calin Juravle      }
65877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle    }
66c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle    for (uint16_t i = 0; i < number_of_classes; i++) {
67a5b09a67034e57a6e10231dd4bd92f4cb50b824cAndreas Gampe      ASSERT_TRUE(info->AddClassIndex(dex_location1, dex_location_checksum1, dex::TypeIndex(i)));
68c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle    }
69c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle
70877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle    ASSERT_TRUE(info->Save(GetFd(profile)));
71877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle    ASSERT_EQ(0, profile.GetFile()->Flush());
72877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle    ASSERT_TRUE(profile.GetFile()->ResetOffset());
73877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  }
74877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
75e276589f2f14f217018f323f5457790b84569fb4Calin Juravle  // Creates an inline cache which will be destructed at the end of the test.
76e276589f2f14f217018f323f5457790b84569fb4Calin Juravle  ProfileCompilationInfo::InlineCacheMap* CreateInlineCacheMap() {
77e276589f2f14f217018f323f5457790b84569fb4Calin Juravle    used_inline_caches.emplace_back(new ProfileCompilationInfo::InlineCacheMap(
78e276589f2f14f217018f323f5457790b84569fb4Calin Juravle        std::less<uint16_t>(), arena_->Adapter(kArenaAllocProfile)));
79e276589f2f14f217018f323f5457790b84569fb4Calin Juravle    return used_inline_caches.back().get();
80e276589f2f14f217018f323f5457790b84569fb4Calin Juravle  }
81e276589f2f14f217018f323f5457790b84569fb4Calin Juravle
823402101b1351afdff5f963cada14808565c270c8Calin Juravle  ProfileCompilationInfo::OfflineProfileMethodInfo GetOfflineProfileMethodInfo(
833402101b1351afdff5f963cada14808565c270c8Calin Juravle        const std::string& dex_location1, uint32_t dex_checksum1,
843402101b1351afdff5f963cada14808565c270c8Calin Juravle        const std::string& dex_location2, uint32_t dex_checksum2) {
85e276589f2f14f217018f323f5457790b84569fb4Calin Juravle    ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap();
86e276589f2f14f217018f323f5457790b84569fb4Calin Juravle    ProfileCompilationInfo::OfflineProfileMethodInfo pmi(ic_map);
873402101b1351afdff5f963cada14808565c270c8Calin Juravle    pmi.dex_references.emplace_back(dex_location1, dex_checksum1);
883402101b1351afdff5f963cada14808565c270c8Calin Juravle    pmi.dex_references.emplace_back(dex_location2, dex_checksum2);
893402101b1351afdff5f963cada14808565c270c8Calin Juravle
903402101b1351afdff5f963cada14808565c270c8Calin Juravle    // Monomorphic
913402101b1351afdff5f963cada14808565c270c8Calin Juravle    for (uint16_t dex_pc = 0; dex_pc < 11; dex_pc++) {
92e276589f2f14f217018f323f5457790b84569fb4Calin Juravle      ProfileCompilationInfo::DexPcData dex_pc_data(arena_.get());
933402101b1351afdff5f963cada14808565c270c8Calin Juravle      dex_pc_data.AddClass(0, dex::TypeIndex(0));
94e276589f2f14f217018f323f5457790b84569fb4Calin Juravle      ic_map->Put(dex_pc, dex_pc_data);
953402101b1351afdff5f963cada14808565c270c8Calin Juravle    }
963402101b1351afdff5f963cada14808565c270c8Calin Juravle    // Polymorphic
973402101b1351afdff5f963cada14808565c270c8Calin Juravle    for (uint16_t dex_pc = 11; dex_pc < 22; dex_pc++) {
98e276589f2f14f217018f323f5457790b84569fb4Calin Juravle      ProfileCompilationInfo::DexPcData dex_pc_data(arena_.get());
993402101b1351afdff5f963cada14808565c270c8Calin Juravle      dex_pc_data.AddClass(0, dex::TypeIndex(0));
1003402101b1351afdff5f963cada14808565c270c8Calin Juravle      dex_pc_data.AddClass(1, dex::TypeIndex(1));
1013402101b1351afdff5f963cada14808565c270c8Calin Juravle
102e276589f2f14f217018f323f5457790b84569fb4Calin Juravle      ic_map->Put(dex_pc, dex_pc_data);
1033402101b1351afdff5f963cada14808565c270c8Calin Juravle    }
1043402101b1351afdff5f963cada14808565c270c8Calin Juravle    // Megamorphic
1053402101b1351afdff5f963cada14808565c270c8Calin Juravle    for (uint16_t dex_pc = 22; dex_pc < 33; dex_pc++) {
106e276589f2f14f217018f323f5457790b84569fb4Calin Juravle      ProfileCompilationInfo::DexPcData dex_pc_data(arena_.get());
1073402101b1351afdff5f963cada14808565c270c8Calin Juravle      dex_pc_data.SetIsMegamorphic();
108e276589f2f14f217018f323f5457790b84569fb4Calin Juravle      ic_map->Put(dex_pc, dex_pc_data);
1093402101b1351afdff5f963cada14808565c270c8Calin Juravle    }
1103402101b1351afdff5f963cada14808565c270c8Calin Juravle    // Missing types
1113402101b1351afdff5f963cada14808565c270c8Calin Juravle    for (uint16_t dex_pc = 33; dex_pc < 44; dex_pc++) {
112e276589f2f14f217018f323f5457790b84569fb4Calin Juravle      ProfileCompilationInfo::DexPcData dex_pc_data(arena_.get());
1133402101b1351afdff5f963cada14808565c270c8Calin Juravle      dex_pc_data.SetIsMissingTypes();
114e276589f2f14f217018f323f5457790b84569fb4Calin Juravle      ic_map->Put(dex_pc, dex_pc_data);
1153402101b1351afdff5f963cada14808565c270c8Calin Juravle    }
1163402101b1351afdff5f963cada14808565c270c8Calin Juravle
1173402101b1351afdff5f963cada14808565c270c8Calin Juravle    return pmi;
1183402101b1351afdff5f963cada14808565c270c8Calin Juravle  }
1193402101b1351afdff5f963cada14808565c270c8Calin Juravle
1202e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  int GetFd(const ScratchFile& file) const {
1212e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    return static_cast<int>(file.GetFd());
1222e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  }
1232e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle
1242e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  void CheckProfileInfo(ScratchFile& file, const ProfileCompilationInfo& info) {
1252e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    ProfileCompilationInfo file_info;
1262e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    ASSERT_TRUE(file.GetFile()->ResetOffset());
1272e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    ASSERT_TRUE(file_info.Load(GetFd(file)));
1282e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    ASSERT_TRUE(file_info.Equals(info));
1292e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  }
1302e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle
1317bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  std::string GetProfmanCmd() {
1322e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    std::string file_path = GetTestAndroidRoot();
133de4fb63be26cd561111cad4574cac5e0c2314d11Calin Juravle    file_path += "/bin/profman";
1342e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    if (kIsDebugBuild) {
1352e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle      file_path += "d";
1362e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    }
1377bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle    EXPECT_TRUE(OS::FileExists(file_path.c_str()))
1387bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle        << file_path << " should be a valid file path";
1397bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle    return file_path;
1407bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  }
1417bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  // Runs test with given arguments.
1427bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  int ProcessProfiles(const std::vector<int>& profiles_fd, int reference_profile_fd) {
1437bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle    std::string profman_cmd = GetProfmanCmd();
1442e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    std::vector<std::string> argv_str;
1457bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle    argv_str.push_back(profman_cmd);
1462e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    for (size_t k = 0; k < profiles_fd.size(); k++) {
1472e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle      argv_str.push_back("--profile-file-fd=" + std::to_string(profiles_fd[k]));
1482e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    }
1492e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    argv_str.push_back("--reference-profile-file-fd=" + std::to_string(reference_profile_fd));
1502e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle
1512e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    std::string error;
1522e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle    return ExecAndReturnCode(argv_str, &error);
153877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  }
1547bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle
1557bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  bool GenerateTestProfile(const std::string& filename) {
1567bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle    std::string profman_cmd = GetProfmanCmd();
1577bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle    std::vector<std::string> argv_str;
1587bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle    argv_str.push_back(profman_cmd);
1597bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle    argv_str.push_back("--generate-test-profile=" + filename);
1607bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle    std::string error;
1617bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle    return ExecAndReturnCode(argv_str, &error);
1627bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  }
1637c80f2d716a7931ab66096322fcb6b951426b151David Sehr
164b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao  bool GenerateTestProfileWithInputDex(const std::string& filename) {
165b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao    std::string profman_cmd = GetProfmanCmd();
166b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao    std::vector<std::string> argv_str;
167b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao    argv_str.push_back(profman_cmd);
168b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao    argv_str.push_back("--generate-test-profile=" + filename);
169b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao    argv_str.push_back("--generate-test-profile-seed=0");
170b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao    argv_str.push_back("--apk=" + GetLibCoreDexFileNames()[0]);
171b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao    argv_str.push_back("--dex-location=" + GetLibCoreDexFileNames()[0]);
172b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao    std::string error;
173b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao    return ExecAndReturnCode(argv_str, &error);
174b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao  }
175b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao
176e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  bool CreateProfile(std::string profile_file_contents,
177e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                     const std::string& filename,
178e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                     const std::string& dex_location) {
1797c80f2d716a7931ab66096322fcb6b951426b151David Sehr    ScratchFile class_names_file;
1807c80f2d716a7931ab66096322fcb6b951426b151David Sehr    File* file = class_names_file.GetFile();
181e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    EXPECT_TRUE(file->WriteFully(profile_file_contents.c_str(), profile_file_contents.length()));
1827c80f2d716a7931ab66096322fcb6b951426b151David Sehr    EXPECT_EQ(0, file->Flush());
1837c80f2d716a7931ab66096322fcb6b951426b151David Sehr    EXPECT_TRUE(file->ResetOffset());
1847c80f2d716a7931ab66096322fcb6b951426b151David Sehr    std::string profman_cmd = GetProfmanCmd();
1857c80f2d716a7931ab66096322fcb6b951426b151David Sehr    std::vector<std::string> argv_str;
1867c80f2d716a7931ab66096322fcb6b951426b151David Sehr    argv_str.push_back(profman_cmd);
1877c80f2d716a7931ab66096322fcb6b951426b151David Sehr    argv_str.push_back("--create-profile-from=" + class_names_file.GetFilename());
1887c80f2d716a7931ab66096322fcb6b951426b151David Sehr    argv_str.push_back("--reference-profile-file=" + filename);
189e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    argv_str.push_back("--apk=" + dex_location);
190e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    argv_str.push_back("--dex-location=" + dex_location);
1917c80f2d716a7931ab66096322fcb6b951426b151David Sehr    std::string error;
1927c80f2d716a7931ab66096322fcb6b951426b151David Sehr    EXPECT_EQ(ExecAndReturnCode(argv_str, &error), 0);
1937c80f2d716a7931ab66096322fcb6b951426b151David Sehr    return true;
1947c80f2d716a7931ab66096322fcb6b951426b151David Sehr  }
1957c80f2d716a7931ab66096322fcb6b951426b151David Sehr
19609f6c36c0c5ac055bbb5e36991ab60156be1fb46Mathieu Chartier  bool DumpClassesAndMethods(const std::string& filename, std::string* file_contents) {
1977c80f2d716a7931ab66096322fcb6b951426b151David Sehr    ScratchFile class_names_file;
1987c80f2d716a7931ab66096322fcb6b951426b151David Sehr    std::string profman_cmd = GetProfmanCmd();
1997c80f2d716a7931ab66096322fcb6b951426b151David Sehr    std::vector<std::string> argv_str;
2007c80f2d716a7931ab66096322fcb6b951426b151David Sehr    argv_str.push_back(profman_cmd);
20109f6c36c0c5ac055bbb5e36991ab60156be1fb46Mathieu Chartier    argv_str.push_back("--dump-classes-and-methods");
2027c80f2d716a7931ab66096322fcb6b951426b151David Sehr    argv_str.push_back("--profile-file=" + filename);
2037c80f2d716a7931ab66096322fcb6b951426b151David Sehr    argv_str.push_back("--apk=" + GetLibCoreDexFileNames()[0]);
204e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    argv_str.push_back("--dex-location=" + GetLibCoreDexFileNames()[0]);
2057c80f2d716a7931ab66096322fcb6b951426b151David Sehr    argv_str.push_back("--dump-output-to-fd=" + std::to_string(GetFd(class_names_file)));
2067c80f2d716a7931ab66096322fcb6b951426b151David Sehr    std::string error;
2077c80f2d716a7931ab66096322fcb6b951426b151David Sehr    EXPECT_EQ(ExecAndReturnCode(argv_str, &error), 0);
2087c80f2d716a7931ab66096322fcb6b951426b151David Sehr    File* file = class_names_file.GetFile();
2097c80f2d716a7931ab66096322fcb6b951426b151David Sehr    EXPECT_EQ(0, file->Flush());
2107c80f2d716a7931ab66096322fcb6b951426b151David Sehr    EXPECT_TRUE(file->ResetOffset());
2117c80f2d716a7931ab66096322fcb6b951426b151David Sehr    int64_t length = file->GetLength();
2127c80f2d716a7931ab66096322fcb6b951426b151David Sehr    std::unique_ptr<char[]> buf(new char[length]);
2137c80f2d716a7931ab66096322fcb6b951426b151David Sehr    EXPECT_EQ(file->Read(buf.get(), length, 0), length);
2147c80f2d716a7931ab66096322fcb6b951426b151David Sehr    *file_contents = std::string(buf.get(), length);
2157c80f2d716a7931ab66096322fcb6b951426b151David Sehr    return true;
2167c80f2d716a7931ab66096322fcb6b951426b151David Sehr  }
2177c80f2d716a7931ab66096322fcb6b951426b151David Sehr
218d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  bool CreateAndDump(const std::string& input_file_contents,
219d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier                     std::string* output_file_contents) {
2207c80f2d716a7931ab66096322fcb6b951426b151David Sehr    ScratchFile profile_file;
221e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    EXPECT_TRUE(CreateProfile(input_file_contents,
222e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                              profile_file.GetFilename(),
223e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                              GetLibCoreDexFileNames()[0]));
2247c80f2d716a7931ab66096322fcb6b951426b151David Sehr    profile_file.GetFile()->ResetOffset();
22509f6c36c0c5ac055bbb5e36991ab60156be1fb46Mathieu Chartier    EXPECT_TRUE(DumpClassesAndMethods(profile_file.GetFilename(), output_file_contents));
2267c80f2d716a7931ab66096322fcb6b951426b151David Sehr    return true;
2277c80f2d716a7931ab66096322fcb6b951426b151David Sehr  }
228e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
229e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  mirror::Class* GetClass(jobject class_loader, const std::string& clazz) {
230e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
231e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    Thread* self = Thread::Current();
232e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ScopedObjectAccess soa(self);
233e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    StackHandleScope<1> hs(self);
234e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    Handle<mirror::ClassLoader> h_loader(
235d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier        hs.NewHandle(ObjPtr<mirror::ClassLoader>::DownCast(self->DecodeJObject(class_loader))));
236e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    return class_linker->FindClass(self, clazz.c_str(), h_loader);
237e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  }
238e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
239e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  ArtMethod* GetVirtualMethod(jobject class_loader,
240e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                              const std::string& clazz,
241e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                              const std::string& name) {
242e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    mirror::Class* klass = GetClass(class_loader, clazz);
243e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
244e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    const auto pointer_size = class_linker->GetImagePointerSize();
245e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ArtMethod* method = nullptr;
246e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    Thread* self = Thread::Current();
247e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ScopedObjectAccess soa(self);
248e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    for (auto& m : klass->GetVirtualMethods(pointer_size)) {
249e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle      if (name == m.GetName()) {
250e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle        EXPECT_TRUE(method == nullptr);
251e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle        method = &m;
252e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle      }
253e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    }
254e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    return method;
255e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  }
256e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
257e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  // Verify that given method has the expected inline caches and nothing else.
258e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  void AssertInlineCaches(ArtMethod* method,
259e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                          const std::set<mirror::Class*>& expected_clases,
260e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                          const ProfileCompilationInfo& info,
261589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                          bool is_megamorphic,
262589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                          bool is_missing_types)
263e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle      REQUIRES_SHARED(Locks::mutator_lock_) {
264e276589f2f14f217018f323f5457790b84569fb4Calin Juravle    std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> pmi =
265e276589f2f14f217018f323f5457790b84569fb4Calin Juravle        info.GetMethod(method->GetDexFile()->GetLocation(),
266e276589f2f14f217018f323f5457790b84569fb4Calin Juravle                       method->GetDexFile()->GetLocationChecksum(),
267e276589f2f14f217018f323f5457790b84569fb4Calin Juravle                       method->GetDexMethodIndex());
268e276589f2f14f217018f323f5457790b84569fb4Calin Juravle    ASSERT_TRUE(pmi != nullptr);
269e276589f2f14f217018f323f5457790b84569fb4Calin Juravle    ASSERT_EQ(pmi->inline_caches->size(), 1u);
270e276589f2f14f217018f323f5457790b84569fb4Calin Juravle    const ProfileCompilationInfo::DexPcData& dex_pc_data = pmi->inline_caches->begin()->second;
271e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
272589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle    ASSERT_EQ(dex_pc_data.is_megamorphic, is_megamorphic);
273589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle    ASSERT_EQ(dex_pc_data.is_missing_types, is_missing_types);
274e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ASSERT_EQ(expected_clases.size(), dex_pc_data.classes.size());
275e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    size_t found = 0;
276e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    for (mirror::Class* it : expected_clases) {
277e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle      for (const auto& class_ref : dex_pc_data.classes) {
278e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle        ProfileCompilationInfo::DexReference dex_ref =
279e276589f2f14f217018f323f5457790b84569fb4Calin Juravle            pmi->dex_references[class_ref.dex_profile_index];
280e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle        if (dex_ref.MatchesDex(&(it->GetDexFile())) &&
281e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle            class_ref.type_index == it->GetDexTypeIndex()) {
282e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle          found++;
283e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle        }
284e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle      }
285e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    }
286e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
287e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ASSERT_EQ(expected_clases.size(), found);
288e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  }
289e276589f2f14f217018f323f5457790b84569fb4Calin Juravle
290e276589f2f14f217018f323f5457790b84569fb4Calin Juravle  std::unique_ptr<ArenaAllocator> arena_;
291e276589f2f14f217018f323f5457790b84569fb4Calin Juravle
292e276589f2f14f217018f323f5457790b84569fb4Calin Juravle  // Cache of inline caches generated during tests.
293e276589f2f14f217018f323f5457790b84569fb4Calin Juravle  // This makes it easier to pass data between different utilities and ensure that
294e276589f2f14f217018f323f5457790b84569fb4Calin Juravle  // caches are destructed at the end of the test.
295e276589f2f14f217018f323f5457790b84569fb4Calin Juravle  std::vector<std::unique_ptr<ProfileCompilationInfo::InlineCacheMap>> used_inline_caches;
296877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle};
297877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
298877fd963548a3175665bfef25b0d24bc0e5a0135Calin JuravleTEST_F(ProfileAssistantTest, AdviseCompilationEmptyReferences) {
299877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ScratchFile profile1;
300877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ScratchFile profile2;
3012e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ScratchFile reference_profile;
302877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
3032e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  std::vector<int> profile_fds({
304877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle      GetFd(profile1),
305877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle      GetFd(profile2)});
3062e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  int reference_profile_fd = GetFd(reference_profile);
307877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
308877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  const uint16_t kNumberOfMethodsToEnableCompilation = 100;
309877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo info1;
310c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
311877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo info2;
312c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  SetupProfile("p2", 2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
313877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
314877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // We should advise compilation.
3152e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_EQ(ProfileAssistant::kCompile,
3162e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle            ProcessProfiles(profile_fds, reference_profile_fd));
3173da74687e42de7d33a8e75df9bd64374e650f75eNicolas Geoffray  // The resulting compilation info must be equal to the merge of the inputs.
3182e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ProfileCompilationInfo result;
3192e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
3202e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_TRUE(result.Load(reference_profile_fd));
3212e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle
322877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo expected;
3236726546bf3fd6bdb96a34197119d210bccda7e01Calin Juravle  ASSERT_TRUE(expected.MergeWith(info1));
3246726546bf3fd6bdb96a34197119d210bccda7e01Calin Juravle  ASSERT_TRUE(expected.MergeWith(info2));
3252e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_TRUE(expected.Equals(result));
326877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
3272e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  // The information from profiles must remain the same.
3282e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  CheckProfileInfo(profile1, info1);
3292e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  CheckProfileInfo(profile2, info2);
330877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle}
331877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
332c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle// TODO(calin): Add more tests for classes.
333c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin JuravleTEST_F(ProfileAssistantTest, AdviseCompilationEmptyReferencesBecauseOfClasses) {
334c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  ScratchFile profile1;
335c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  ScratchFile reference_profile;
336c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle
337c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  std::vector<int> profile_fds({
338c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle      GetFd(profile1)});
339c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  int reference_profile_fd = GetFd(reference_profile);
340c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle
341c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  const uint16_t kNumberOfClassesToEnableCompilation = 100;
342c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  ProfileCompilationInfo info1;
343c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  SetupProfile("p1", 1, 0, kNumberOfClassesToEnableCompilation, profile1, &info1);
344c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle
345c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  // We should advise compilation.
346c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  ASSERT_EQ(ProfileAssistant::kCompile,
347c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle            ProcessProfiles(profile_fds, reference_profile_fd));
348c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  // The resulting compilation info must be equal to the merge of the inputs.
349c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  ProfileCompilationInfo result;
350c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
351c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  ASSERT_TRUE(result.Load(reference_profile_fd));
352c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle
353c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  ProfileCompilationInfo expected;
354c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  ASSERT_TRUE(expected.MergeWith(info1));
355c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  ASSERT_TRUE(expected.Equals(result));
356c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle
357c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  // The information from profiles must remain the same.
358c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  CheckProfileInfo(profile1, info1);
359c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle}
360c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle
361877fd963548a3175665bfef25b0d24bc0e5a0135Calin JuravleTEST_F(ProfileAssistantTest, AdviseCompilationNonEmptyReferences) {
362877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ScratchFile profile1;
363877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ScratchFile profile2;
3642e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ScratchFile reference_profile;
365877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
3662e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  std::vector<int> profile_fds({
367877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle      GetFd(profile1),
368877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle      GetFd(profile2)});
3692e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  int reference_profile_fd = GetFd(reference_profile);
370877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
371877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // The new profile info will contain the methods with indices 0-100.
372877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  const uint16_t kNumberOfMethodsToEnableCompilation = 100;
373877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo info1;
374c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
375877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo info2;
376c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  SetupProfile("p2", 2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
377877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
378877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
379877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // The reference profile info will contain the methods with indices 50-150.
380877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  const uint16_t kNumberOfMethodsAlreadyCompiled = 100;
3812e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ProfileCompilationInfo reference_info;
382c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  SetupProfile("p1", 1, kNumberOfMethodsAlreadyCompiled, 0, reference_profile,
3832e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle      &reference_info, kNumberOfMethodsToEnableCompilation / 2);
384877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
385877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // We should advise compilation.
3862e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_EQ(ProfileAssistant::kCompile,
3872e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle            ProcessProfiles(profile_fds, reference_profile_fd));
388877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
389877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // The resulting compilation info must be equal to the merge of the inputs
3902e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ProfileCompilationInfo result;
3912e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
3922e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_TRUE(result.Load(reference_profile_fd));
3932e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle
394877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo expected;
3956726546bf3fd6bdb96a34197119d210bccda7e01Calin Juravle  ASSERT_TRUE(expected.MergeWith(info1));
3966726546bf3fd6bdb96a34197119d210bccda7e01Calin Juravle  ASSERT_TRUE(expected.MergeWith(info2));
3976726546bf3fd6bdb96a34197119d210bccda7e01Calin Juravle  ASSERT_TRUE(expected.MergeWith(reference_info));
3982e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_TRUE(expected.Equals(result));
3993da74687e42de7d33a8e75df9bd64374e650f75eNicolas Geoffray
4002e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  // The information from profiles must remain the same.
4012e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  CheckProfileInfo(profile1, info1);
4022e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  CheckProfileInfo(profile2, info2);
403877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle}
404877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
405877fd963548a3175665bfef25b0d24bc0e5a0135Calin JuravleTEST_F(ProfileAssistantTest, DoNotAdviseCompilation) {
406877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ScratchFile profile1;
407877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ScratchFile profile2;
4082e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ScratchFile reference_profile;
409877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
4102e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  std::vector<int> profile_fds({
411877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle      GetFd(profile1),
412877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle      GetFd(profile2)});
4132e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  int reference_profile_fd = GetFd(reference_profile);
414877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
415877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  const uint16_t kNumberOfMethodsToSkipCompilation = 1;
416877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo info1;
417c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  SetupProfile("p1", 1, kNumberOfMethodsToSkipCompilation, 0, profile1, &info1);
418877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo info2;
419c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  SetupProfile("p2", 2, kNumberOfMethodsToSkipCompilation, 0, profile2, &info2);
420877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
421877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // We should not advise compilation.
4222e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_EQ(ProfileAssistant::kSkipCompilation,
4232e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle            ProcessProfiles(profile_fds, reference_profile_fd));
424877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
425877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // The information from profiles must remain the same.
426877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo file_info1;
427877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ASSERT_TRUE(profile1.GetFile()->ResetOffset());
428877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ASSERT_TRUE(file_info1.Load(GetFd(profile1)));
429877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ASSERT_TRUE(file_info1.Equals(info1));
430877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
431877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo file_info2;
432877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ASSERT_TRUE(profile2.GetFile()->ResetOffset());
433877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ASSERT_TRUE(file_info2.Load(GetFd(profile2)));
434877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ASSERT_TRUE(file_info2.Equals(info2));
435877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
436877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // Reference profile files must remain empty.
4372e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_EQ(0, reference_profile.GetFile()->GetLength());
4382e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle
4392e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  // The information from profiles must remain the same.
4402e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  CheckProfileInfo(profile1, info1);
4412e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  CheckProfileInfo(profile2, info2);
442877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle}
443877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
444877fd963548a3175665bfef25b0d24bc0e5a0135Calin JuravleTEST_F(ProfileAssistantTest, FailProcessingBecauseOfProfiles) {
445877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ScratchFile profile1;
446877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ScratchFile profile2;
4472e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ScratchFile reference_profile;
448877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
4492e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  std::vector<int> profile_fds({
450877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle      GetFd(profile1),
451877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle      GetFd(profile2)});
4522e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  int reference_profile_fd = GetFd(reference_profile);
453877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
454877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  const uint16_t kNumberOfMethodsToEnableCompilation = 100;
455877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // Assign different hashes for the same dex file. This will make merging of information to fail.
456877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo info1;
457c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
458877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo info2;
459c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  SetupProfile("p1", 2, kNumberOfMethodsToEnableCompilation, 0, profile2, &info2);
460877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
461877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // We should fail processing.
4622e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_EQ(ProfileAssistant::kErrorBadProfiles,
4632e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle            ProcessProfiles(profile_fds, reference_profile_fd));
464877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
4652e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  // The information from profiles must remain the same.
4662e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  CheckProfileInfo(profile1, info1);
4672e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  CheckProfileInfo(profile2, info2);
468877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
469877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // Reference profile files must still remain empty.
4702e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_EQ(0, reference_profile.GetFile()->GetLength());
471877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle}
472877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
473877fd963548a3175665bfef25b0d24bc0e5a0135Calin JuravleTEST_F(ProfileAssistantTest, FailProcessingBecauseOfReferenceProfiles) {
474877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ScratchFile profile1;
475877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ScratchFile reference_profile;
476877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
4772e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  std::vector<int> profile_fds({
478877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle      GetFd(profile1)});
4792e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  int reference_profile_fd = GetFd(reference_profile);
480877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
481877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  const uint16_t kNumberOfMethodsToEnableCompilation = 100;
482877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // Assign different hashes for the same dex file. This will make merging of information to fail.
483877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo info1;
484c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1);
485877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ProfileCompilationInfo reference_info;
486c824b51331bdd72c1c45ca4e45a0b025d30a09c9Calin Juravle  SetupProfile("p1", 2, kNumberOfMethodsToEnableCompilation, 0, reference_profile, &reference_info);
487877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
488877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  // We should not advise compilation.
489877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ASSERT_TRUE(profile1.GetFile()->ResetOffset());
490877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
4912e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  ASSERT_EQ(ProfileAssistant::kErrorBadProfiles,
4922e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle            ProcessProfiles(profile_fds, reference_profile_fd));
4933da74687e42de7d33a8e75df9bd64374e650f75eNicolas Geoffray
4942e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  // The information from profiles must remain the same.
4952e2db786b8fbaa4dceb37603a4296b0b2aea4e9eCalin Juravle  CheckProfileInfo(profile1, info1);
496877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle}
497877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle
4987bcdb53803d8e276d374fc7bb74d6dd893b39345Calin JuravleTEST_F(ProfileAssistantTest, TestProfileGeneration) {
4997bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  ScratchFile profile;
5007bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  // Generate a test profile.
5017bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  GenerateTestProfile(profile.GetFilename());
5027bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle
5037bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  // Verify that the generated profile is valid and can be loaded.
5047bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  ASSERT_TRUE(profile.GetFile()->ResetOffset());
5057bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  ProfileCompilationInfo info;
5067bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle  ASSERT_TRUE(info.Load(GetFd(profile)));
5077bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle}
5087bcdb53803d8e276d374fc7bb74d6dd893b39345Calin Juravle
509b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff HaoTEST_F(ProfileAssistantTest, TestProfileGenerationWithIndexDex) {
510b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao  ScratchFile profile;
511b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao  // Generate a test profile passing in a dex file as reference.
512b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao  GenerateTestProfileWithInputDex(profile.GetFilename());
513b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao
514b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao  // Verify that the generated profile is valid and can be loaded.
515b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao  ASSERT_TRUE(profile.GetFile()->ResetOffset());
516b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao  ProfileCompilationInfo info;
517b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao  ASSERT_TRUE(info.Load(GetFd(profile)));
518b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao}
519b3ad82df46e7a0dba0a85eded1cf105496eab52cJeff Hao
5207c80f2d716a7931ab66096322fcb6b951426b151David SehrTEST_F(ProfileAssistantTest, TestProfileCreationAllMatch) {
5217c80f2d716a7931ab66096322fcb6b951426b151David Sehr  // Class names put here need to be in sorted order.
5227c80f2d716a7931ab66096322fcb6b951426b151David Sehr  std::vector<std::string> class_names = {
523e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    "Ljava/lang/Comparable;",
524e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    "Ljava/lang/Math;",
52509f6c36c0c5ac055bbb5e36991ab60156be1fb46Mathieu Chartier    "Ljava/lang/Object;",
52609f6c36c0c5ac055bbb5e36991ab60156be1fb46Mathieu Chartier    "Ljava/lang/Object;-><init>()V"
5277c80f2d716a7931ab66096322fcb6b951426b151David Sehr  };
52809f6c36c0c5ac055bbb5e36991ab60156be1fb46Mathieu Chartier  std::string file_contents;
5297c80f2d716a7931ab66096322fcb6b951426b151David Sehr  for (std::string& class_name : class_names) {
53009f6c36c0c5ac055bbb5e36991ab60156be1fb46Mathieu Chartier    file_contents += class_name + std::string("\n");
5317c80f2d716a7931ab66096322fcb6b951426b151David Sehr  }
5327c80f2d716a7931ab66096322fcb6b951426b151David Sehr  std::string output_file_contents;
53309f6c36c0c5ac055bbb5e36991ab60156be1fb46Mathieu Chartier  ASSERT_TRUE(CreateAndDump(file_contents, &output_file_contents));
53409f6c36c0c5ac055bbb5e36991ab60156be1fb46Mathieu Chartier  ASSERT_EQ(output_file_contents, file_contents);
5357c80f2d716a7931ab66096322fcb6b951426b151David Sehr}
5367c80f2d716a7931ab66096322fcb6b951426b151David Sehr
537d808e8bb070b853639e41245d846f2fd9354b92fMathieu ChartierTEST_F(ProfileAssistantTest, TestProfileCreationGenerateMethods) {
538d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  // Class names put here need to be in sorted order.
539d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  std::vector<std::string> class_names = {
540d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier    "Ljava/lang/Math;->*",
541d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  };
542d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  std::string input_file_contents;
543d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  std::string expected_contents;
544d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  for (std::string& class_name : class_names) {
545d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier    input_file_contents += class_name + std::string("\n");
546d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier    expected_contents += DescriptorToDot(class_name.c_str()) +
547d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier        std::string("\n");
548d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  }
549d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  std::string output_file_contents;
550d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  ScratchFile profile_file;
551d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  EXPECT_TRUE(CreateProfile(input_file_contents,
552d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier                            profile_file.GetFilename(),
553d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier                            GetLibCoreDexFileNames()[0]));
554d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  ProfileCompilationInfo info;
555d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  profile_file.GetFile()->ResetOffset();
556d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  ASSERT_TRUE(info.Load(GetFd(profile_file)));
557d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  // Verify that the profile has matching methods.
558d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  ScopedObjectAccess soa(Thread::Current());
559d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  ObjPtr<mirror::Class> klass = GetClass(nullptr, "Ljava/lang/Math;");
560d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  ASSERT_TRUE(klass != nullptr);
561d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  size_t method_count = 0;
562d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  for (ArtMethod& method : klass->GetMethods(kRuntimePointerSize)) {
563d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier    if (!method.IsCopied() && method.GetCodeItem() != nullptr) {
564d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier      ++method_count;
565e276589f2f14f217018f323f5457790b84569fb4Calin Juravle      std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> pmi =
566e276589f2f14f217018f323f5457790b84569fb4Calin Juravle          info.GetMethod(method.GetDexFile()->GetLocation(),
567e276589f2f14f217018f323f5457790b84569fb4Calin Juravle                         method.GetDexFile()->GetLocationChecksum(),
568e276589f2f14f217018f323f5457790b84569fb4Calin Juravle                         method.GetDexMethodIndex());
569e276589f2f14f217018f323f5457790b84569fb4Calin Juravle      ASSERT_TRUE(pmi != nullptr);
570d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier    }
571d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  }
572d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier  EXPECT_GT(method_count, 0u);
573d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier}
574d808e8bb070b853639e41245d846f2fd9354b92fMathieu Chartier
5757c80f2d716a7931ab66096322fcb6b951426b151David SehrTEST_F(ProfileAssistantTest, TestProfileCreationOneNotMatched) {
5767c80f2d716a7931ab66096322fcb6b951426b151David Sehr  // Class names put here need to be in sorted order.
5777c80f2d716a7931ab66096322fcb6b951426b151David Sehr  std::vector<std::string> class_names = {
578e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    "Ldoesnt/match/this/one;",
579e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    "Ljava/lang/Comparable;",
580e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    "Ljava/lang/Object;"
5817c80f2d716a7931ab66096322fcb6b951426b151David Sehr  };
5827c80f2d716a7931ab66096322fcb6b951426b151David Sehr  std::string input_file_contents;
5837c80f2d716a7931ab66096322fcb6b951426b151David Sehr  for (std::string& class_name : class_names) {
5847c80f2d716a7931ab66096322fcb6b951426b151David Sehr    input_file_contents += class_name + std::string("\n");
5857c80f2d716a7931ab66096322fcb6b951426b151David Sehr  }
5867c80f2d716a7931ab66096322fcb6b951426b151David Sehr  std::string output_file_contents;
5877c80f2d716a7931ab66096322fcb6b951426b151David Sehr  ASSERT_TRUE(CreateAndDump(input_file_contents, &output_file_contents));
5887c80f2d716a7931ab66096322fcb6b951426b151David Sehr  std::string expected_contents =
58909f6c36c0c5ac055bbb5e36991ab60156be1fb46Mathieu Chartier      class_names[1] + std::string("\n") +
59009f6c36c0c5ac055bbb5e36991ab60156be1fb46Mathieu Chartier      class_names[2] + std::string("\n");
5917c80f2d716a7931ab66096322fcb6b951426b151David Sehr  ASSERT_EQ(output_file_contents, expected_contents);
5927c80f2d716a7931ab66096322fcb6b951426b151David Sehr}
5937c80f2d716a7931ab66096322fcb6b951426b151David Sehr
5947c80f2d716a7931ab66096322fcb6b951426b151David SehrTEST_F(ProfileAssistantTest, TestProfileCreationNoneMatched) {
5957c80f2d716a7931ab66096322fcb6b951426b151David Sehr  // Class names put here need to be in sorted order.
5967c80f2d716a7931ab66096322fcb6b951426b151David Sehr  std::vector<std::string> class_names = {
597e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    "Ldoesnt/match/this/one;",
598e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    "Ldoesnt/match/this/one/either;",
599e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    "Lnor/this/one;"
6007c80f2d716a7931ab66096322fcb6b951426b151David Sehr  };
6017c80f2d716a7931ab66096322fcb6b951426b151David Sehr  std::string input_file_contents;
6027c80f2d716a7931ab66096322fcb6b951426b151David Sehr  for (std::string& class_name : class_names) {
6037c80f2d716a7931ab66096322fcb6b951426b151David Sehr    input_file_contents += class_name + std::string("\n");
6047c80f2d716a7931ab66096322fcb6b951426b151David Sehr  }
6057c80f2d716a7931ab66096322fcb6b951426b151David Sehr  std::string output_file_contents;
6067c80f2d716a7931ab66096322fcb6b951426b151David Sehr  ASSERT_TRUE(CreateAndDump(input_file_contents, &output_file_contents));
6077c80f2d716a7931ab66096322fcb6b951426b151David Sehr  std::string expected_contents("");
6087c80f2d716a7931ab66096322fcb6b951426b151David Sehr  ASSERT_EQ(output_file_contents, expected_contents);
6097c80f2d716a7931ab66096322fcb6b951426b151David Sehr}
6107c80f2d716a7931ab66096322fcb6b951426b151David Sehr
611e0ac1151b360be7147fa20320c0b427688b1424fCalin JuravleTEST_F(ProfileAssistantTest, TestProfileCreateInlineCache) {
612e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  // Create the profile content.
613e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  std::vector<std::string> methods = {
614e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    "LTestInline;->inlineMonomorphic(LSuper;)I+LSubA;",
615e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    "LTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;",
616e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    "LTestInline;->inlineMegamorphic(LSuper;)I+LSubA;,LSubB;,LSubC;,LSubD;,LSubE;",
617589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle    "LTestInline;->inlineMissingTypes(LSuper;)I+missing_types",
618e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    "LTestInline;->noInlineCache(LSuper;)I"
619e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  };
620e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  std::string input_file_contents;
621e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  for (std::string& m : methods) {
622e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    input_file_contents += m + std::string("\n");
623e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  }
624e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
625e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  // Create the profile and save it to disk.
626e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  ScratchFile profile_file;
627e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  ASSERT_TRUE(CreateProfile(input_file_contents,
628e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                            profile_file.GetFilename(),
629e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                            GetTestDexFileName("ProfileTestMultiDex")));
630e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
631e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  // Load the profile from disk.
632e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  ProfileCompilationInfo info;
633e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  profile_file.GetFile()->ResetOffset();
634e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  ASSERT_TRUE(info.Load(GetFd(profile_file)));
635e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
636e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  // Load the dex files and verify that the profile contains the expected methods info.
637e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  ScopedObjectAccess soa(Thread::Current());
638e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  jobject class_loader = LoadDex("ProfileTestMultiDex");
639e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  ASSERT_NE(class_loader, nullptr);
640e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
641e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  mirror::Class* sub_a = GetClass(class_loader, "LSubA;");
642e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  mirror::Class* sub_b = GetClass(class_loader, "LSubB;");
643e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  mirror::Class* sub_c = GetClass(class_loader, "LSubC;");
644e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
645e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  ASSERT_TRUE(sub_a != nullptr);
646e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  ASSERT_TRUE(sub_b != nullptr);
647e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  ASSERT_TRUE(sub_c != nullptr);
648e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
649e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  {
650e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    // Verify that method inlineMonomorphic has the expected inline caches and nothing else.
651e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ArtMethod* inline_monomorphic = GetVirtualMethod(class_loader,
652e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                                                     "LTestInline;",
653e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                                                     "inlineMonomorphic");
654e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ASSERT_TRUE(inline_monomorphic != nullptr);
655e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    std::set<mirror::Class*> expected_monomorphic;
656e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    expected_monomorphic.insert(sub_a);
657589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle    AssertInlineCaches(inline_monomorphic,
658589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       expected_monomorphic,
659589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       info,
660589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       /*megamorphic*/false,
661589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       /*missing_types*/false);
662e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  }
663e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
664e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  {
665e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    // Verify that method inlinePolymorphic has the expected inline caches and nothing else.
666e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ArtMethod* inline_polymorhic = GetVirtualMethod(class_loader,
667e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                                                    "LTestInline;",
668e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                                                    "inlinePolymorphic");
669e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ASSERT_TRUE(inline_polymorhic != nullptr);
670e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    std::set<mirror::Class*> expected_polymorphic;
671e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    expected_polymorphic.insert(sub_a);
672e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    expected_polymorphic.insert(sub_b);
673e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    expected_polymorphic.insert(sub_c);
674589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle    AssertInlineCaches(inline_polymorhic,
675589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       expected_polymorphic,
676589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       info,
677589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       /*megamorphic*/false,
678589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       /*missing_types*/false);
679e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  }
680e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
681e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  {
682e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    // Verify that method inlineMegamorphic has the expected inline caches and nothing else.
683e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ArtMethod* inline_megamorphic = GetVirtualMethod(class_loader,
684e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                                                     "LTestInline;",
685e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle                                                     "inlineMegamorphic");
686e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ASSERT_TRUE(inline_megamorphic != nullptr);
687e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    std::set<mirror::Class*> expected_megamorphic;
688589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle    AssertInlineCaches(inline_megamorphic,
689589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       expected_megamorphic,
690589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       info,
691589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       /*megamorphic*/true,
692589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       /*missing_types*/false);
693589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle  }
694589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle
695589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle  {
696589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle    // Verify that method inlineMegamorphic has the expected inline caches and nothing else.
697589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle    ArtMethod* inline_missing_types = GetVirtualMethod(class_loader,
698589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                                                       "LTestInline;",
699589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                                                       "inlineMissingTypes");
700589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle    ASSERT_TRUE(inline_missing_types != nullptr);
701589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle    std::set<mirror::Class*> expected_missing_Types;
702589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle    AssertInlineCaches(inline_missing_types,
703589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       expected_missing_Types,
704589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       info,
705589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       /*megamorphic*/false,
706589e71eb71477603c88b14118b2d3a33508c3c79Calin Juravle                       /*missing_types*/true);
707e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  }
708e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
709e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  {
710e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    // Verify that method noInlineCache has no inline caches in the profile.
711e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ArtMethod* no_inline_cache = GetVirtualMethod(class_loader, "LTestInline;", "noInlineCache");
712e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle    ASSERT_TRUE(no_inline_cache != nullptr);
713e276589f2f14f217018f323f5457790b84569fb4Calin Juravle    std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> pmi_no_inline_cache =
714e276589f2f14f217018f323f5457790b84569fb4Calin Juravle        info.GetMethod(no_inline_cache->GetDexFile()->GetLocation(),
715e276589f2f14f217018f323f5457790b84569fb4Calin Juravle                       no_inline_cache->GetDexFile()->GetLocationChecksum(),
716e276589f2f14f217018f323f5457790b84569fb4Calin Juravle                       no_inline_cache->GetDexMethodIndex());
717e276589f2f14f217018f323f5457790b84569fb4Calin Juravle    ASSERT_TRUE(pmi_no_inline_cache != nullptr);
718e276589f2f14f217018f323f5457790b84569fb4Calin Juravle    ASSERT_TRUE(pmi_no_inline_cache->inline_caches->empty());
719e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle  }
720e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle}
721e0ac1151b360be7147fa20320c0b427688b1424fCalin Juravle
7223402101b1351afdff5f963cada14808565c270c8Calin JuravleTEST_F(ProfileAssistantTest, MergeProfilesWithDifferentDexOrder) {
7233402101b1351afdff5f963cada14808565c270c8Calin Juravle  ScratchFile profile1;
7243402101b1351afdff5f963cada14808565c270c8Calin Juravle  ScratchFile reference_profile;
7253402101b1351afdff5f963cada14808565c270c8Calin Juravle
7263402101b1351afdff5f963cada14808565c270c8Calin Juravle  std::vector<int> profile_fds({GetFd(profile1)});
7273402101b1351afdff5f963cada14808565c270c8Calin Juravle  int reference_profile_fd = GetFd(reference_profile);
7283402101b1351afdff5f963cada14808565c270c8Calin Juravle
7293402101b1351afdff5f963cada14808565c270c8Calin Juravle  // The new profile info will contain the methods with indices 0-100.
7303402101b1351afdff5f963cada14808565c270c8Calin Juravle  const uint16_t kNumberOfMethodsToEnableCompilation = 100;
7313402101b1351afdff5f963cada14808565c270c8Calin Juravle  ProfileCompilationInfo info1;
7323402101b1351afdff5f963cada14808565c270c8Calin Juravle  SetupProfile("p1", 1, kNumberOfMethodsToEnableCompilation, 0, profile1, &info1,
7333402101b1351afdff5f963cada14808565c270c8Calin Juravle      /*start_method_index*/0, /*reverse_dex_write_order*/false);
7343402101b1351afdff5f963cada14808565c270c8Calin Juravle
7353402101b1351afdff5f963cada14808565c270c8Calin Juravle  // The reference profile info will contain the methods with indices 50-150.
7363402101b1351afdff5f963cada14808565c270c8Calin Juravle  // When setting up the profile reverse the order in which the dex files
7373402101b1351afdff5f963cada14808565c270c8Calin Juravle  // are added to the profile. This will verify that profman merges profiles
7383402101b1351afdff5f963cada14808565c270c8Calin Juravle  // with a different dex order correctly.
7393402101b1351afdff5f963cada14808565c270c8Calin Juravle  const uint16_t kNumberOfMethodsAlreadyCompiled = 100;
7403402101b1351afdff5f963cada14808565c270c8Calin Juravle  ProfileCompilationInfo reference_info;
7413402101b1351afdff5f963cada14808565c270c8Calin Juravle  SetupProfile("p1", 1, kNumberOfMethodsAlreadyCompiled, 0, reference_profile,
7423402101b1351afdff5f963cada14808565c270c8Calin Juravle      &reference_info, kNumberOfMethodsToEnableCompilation / 2, /*reverse_dex_write_order*/true);
7433402101b1351afdff5f963cada14808565c270c8Calin Juravle
7443402101b1351afdff5f963cada14808565c270c8Calin Juravle  // We should advise compilation.
7453402101b1351afdff5f963cada14808565c270c8Calin Juravle  ASSERT_EQ(ProfileAssistant::kCompile,
7463402101b1351afdff5f963cada14808565c270c8Calin Juravle            ProcessProfiles(profile_fds, reference_profile_fd));
7473402101b1351afdff5f963cada14808565c270c8Calin Juravle
7483402101b1351afdff5f963cada14808565c270c8Calin Juravle  // The resulting compilation info must be equal to the merge of the inputs.
7493402101b1351afdff5f963cada14808565c270c8Calin Juravle  ProfileCompilationInfo result;
7503402101b1351afdff5f963cada14808565c270c8Calin Juravle  ASSERT_TRUE(reference_profile.GetFile()->ResetOffset());
7513402101b1351afdff5f963cada14808565c270c8Calin Juravle  ASSERT_TRUE(result.Load(reference_profile_fd));
7523402101b1351afdff5f963cada14808565c270c8Calin Juravle
7533402101b1351afdff5f963cada14808565c270c8Calin Juravle  ProfileCompilationInfo expected;
7543402101b1351afdff5f963cada14808565c270c8Calin Juravle  ASSERT_TRUE(expected.MergeWith(reference_info));
7553402101b1351afdff5f963cada14808565c270c8Calin Juravle  ASSERT_TRUE(expected.MergeWith(info1));
7563402101b1351afdff5f963cada14808565c270c8Calin Juravle  ASSERT_TRUE(expected.Equals(result));
7573402101b1351afdff5f963cada14808565c270c8Calin Juravle
7583402101b1351afdff5f963cada14808565c270c8Calin Juravle  // The information from profile must remain the same.
7593402101b1351afdff5f963cada14808565c270c8Calin Juravle  CheckProfileInfo(profile1, info1);
7603402101b1351afdff5f963cada14808565c270c8Calin Juravle}
7613402101b1351afdff5f963cada14808565c270c8Calin Juravle
7621fff148498f68bbfbaa498c92fbc155fbfda4b80Calin JuravleTEST_F(ProfileAssistantTest, TestProfileCreateWithInvalidData) {
7631fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  // Create the profile content.
7641fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  std::vector<std::string> profile_methods = {
7651fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle    "LTestInline;->inlineMonomorphic(LSuper;)I+invalid_class",
7661fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle    "LTestInline;->invalid_method",
7671fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle    "invalid_class"
7681fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  };
7691fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  std::string input_file_contents;
7701fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  for (std::string& m : profile_methods) {
7711fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle    input_file_contents += m + std::string("\n");
7721fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  }
7731fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle
7741fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  // Create the profile and save it to disk.
7751fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ScratchFile profile_file;
7761fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  std::string dex_filename = GetTestDexFileName("ProfileTestMultiDex");
7771fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ASSERT_TRUE(CreateProfile(input_file_contents,
7781fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle                            profile_file.GetFilename(),
7791fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle                            dex_filename));
7801fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle
7811fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  // Load the profile from disk.
7821fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ProfileCompilationInfo info;
7831fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  profile_file.GetFile()->ResetOffset();
7841fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ASSERT_TRUE(info.Load(GetFd(profile_file)));
7851fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle
7861fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  // Load the dex files and verify that the profile contains the expected methods info.
7871fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ScopedObjectAccess soa(Thread::Current());
7881fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  jobject class_loader = LoadDex("ProfileTestMultiDex");
7891fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ASSERT_NE(class_loader, nullptr);
7901fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle
7911fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ArtMethod* inline_monomorphic = GetVirtualMethod(class_loader,
7921fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle                                                   "LTestInline;",
7931fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle                                                   "inlineMonomorphic");
7941fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  const DexFile* dex_file = inline_monomorphic->GetDexFile();
7951fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle
7961fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  // Verify that the inline cache contains the invalid type.
7971fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> pmi =
7981fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle      info.GetMethod(dex_file->GetLocation(),
7991fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle                     dex_file->GetLocationChecksum(),
8001fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle                     inline_monomorphic->GetDexMethodIndex());
8011fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ASSERT_TRUE(pmi != nullptr);
8021fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ASSERT_EQ(pmi->inline_caches->size(), 1u);
8031fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  const ProfileCompilationInfo::DexPcData& dex_pc_data = pmi->inline_caches->begin()->second;
8041fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  dex::TypeIndex invalid_class_index(std::numeric_limits<uint16_t>::max() - 1);
8051fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ASSERT_EQ(1u, dex_pc_data.classes.size());
8061fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ASSERT_EQ(invalid_class_index, dex_pc_data.classes.begin()->type_index);
8071fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle
8081fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  // Verify that the start-up classes contain the invalid class.
8091fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  std::set<dex::TypeIndex> classes;
8101fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  std::set<uint16_t> methods;
8111fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ASSERT_TRUE(info.GetClassesAndMethods(*dex_file, &classes, &methods));
8121fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ASSERT_EQ(1u, classes.size());
8131fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ASSERT_TRUE(classes.find(invalid_class_index) != classes.end());
8141fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle
8151fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  // Verify that the invalid method is in the profile.
8161fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ASSERT_EQ(2u, methods.size());
8171fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  uint16_t invalid_method_index = std::numeric_limits<uint16_t>::max() - 1;
8181fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle  ASSERT_TRUE(methods.find(invalid_method_index) != methods.end());
8191fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle}
8201fff148498f68bbfbaa498c92fbc155fbfda4b80Calin Juravle
821877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle}  // namespace art
822