blob: 482ea063953ab745989b467056ba20ac9ca9d170 [file] [log] [blame]
Calin Juravle877fd962016-01-05 14:29:29 +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
19#include "base/unix_file/fd_file.h"
20#include "art_method-inl.h"
21#include "class_linker-inl.h"
22#include "common_runtime_test.h"
23#include "dex_file.h"
24#include "mirror/class-inl.h"
25#include "mirror/class_loader.h"
26#include "handle_scope-inl.h"
27#include "jit/offline_profiling_info.h"
28#include "scoped_thread_state_change.h"
29
30namespace art {
31
32class ProfileCompilationInfoTest : public CommonRuntimeTest {
33 protected:
34 std::vector<ArtMethod*> GetVirtualMethods(jobject class_loader,
35 const std::string& clazz) {
36 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
37 Thread* self = Thread::Current();
38 ScopedObjectAccess soa(self);
39 StackHandleScope<1> hs(self);
40 Handle<mirror::ClassLoader> h_loader(hs.NewHandle(
41 reinterpret_cast<mirror::ClassLoader*>(self->DecodeJObject(class_loader))));
42 mirror::Class* klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
43
44 const auto pointer_size = class_linker->GetImagePointerSize();
45 std::vector<ArtMethod*> methods;
46 for (auto& m : klass->GetVirtualMethods(pointer_size)) {
47 methods.push_back(&m);
48 }
49 return methods;
50 }
51
52 bool AddData(const std::string& dex_location,
53 uint32_t checksum,
54 uint16_t method_index,
55 ProfileCompilationInfo* info) {
56 return info->AddData(dex_location, checksum, method_index);
57 }
58
59 uint32_t GetFd(const ScratchFile& file) {
60 return static_cast<uint32_t>(file.GetFd());
61 }
62};
63
64TEST_F(ProfileCompilationInfoTest, SaveArtMethods) {
65 ScratchFile profile;
66
67 Thread* self = Thread::Current();
68 jobject class_loader;
69 {
70 ScopedObjectAccess soa(self);
71 class_loader = LoadDex("ProfileTestMultiDex");
72 }
73 ASSERT_NE(class_loader, nullptr);
74
75 // Save virtual methods from Main.
76 std::vector<ArtMethod*> main_methods = GetVirtualMethods(class_loader, "LMain;");
77 ASSERT_TRUE(ProfileCompilationInfo::SaveProfilingInfo(profile.GetFilename(), main_methods));
78
79 // Check that what we saved is in the profile.
80 ProfileCompilationInfo info1;
81 ASSERT_TRUE(info1.Load(GetFd(profile)));
82 ASSERT_EQ(info1.GetNumberOfMethods(), main_methods.size());
83 {
84 ScopedObjectAccess soa(self);
85 for (ArtMethod* m : main_methods) {
86 ASSERT_TRUE(info1.ContainsMethod(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())));
87 }
88 }
89
90 // Save virtual methods from Second.
91 std::vector<ArtMethod*> second_methods = GetVirtualMethods(class_loader, "LSecond;");
92 ASSERT_TRUE(ProfileCompilationInfo::SaveProfilingInfo(profile.GetFilename(), second_methods));
93
94 // Check that what we saved is in the profile (methods form Main and Second).
95 ProfileCompilationInfo info2;
96 ASSERT_TRUE(profile.GetFile()->ResetOffset());
97 ASSERT_TRUE(info2.Load(GetFd(profile)));
98 ASSERT_EQ(info2.GetNumberOfMethods(), main_methods.size() + second_methods.size());
99 {
100 ScopedObjectAccess soa(self);
101 for (ArtMethod* m : main_methods) {
102 ASSERT_TRUE(info2.ContainsMethod(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())));
103 }
104 for (ArtMethod* m : second_methods) {
105 ASSERT_TRUE(info2.ContainsMethod(MethodReference(m->GetDexFile(), m->GetDexMethodIndex())));
106 }
107 }
108}
109
110TEST_F(ProfileCompilationInfoTest, SaveFd) {
111 ScratchFile profile;
112
113 ProfileCompilationInfo saved_info;
114 // Save a few methods.
115 for (uint16_t i = 0; i < 10; i++) {
116 ASSERT_TRUE(AddData("dex_location1", /* checksum */ 1, /* method_idx */ i, &saved_info));
117 ASSERT_TRUE(AddData("dex_location2", /* checksum */ 2, /* method_idx */ i, &saved_info));
118 }
119 ASSERT_TRUE(saved_info.Save(GetFd(profile)));
120 ASSERT_EQ(0, profile.GetFile()->Flush());
121
122 // Check that we get back what we saved.
123 ProfileCompilationInfo loaded_info;
124 ASSERT_TRUE(profile.GetFile()->ResetOffset());
125 ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
126 ASSERT_TRUE(loaded_info.Equals(saved_info));
127
128 // Save more methods.
129 for (uint16_t i = 0; i < 100; i++) {
130 ASSERT_TRUE(AddData("dex_location1", /* checksum */ 1, /* method_idx */ i, &saved_info));
131 ASSERT_TRUE(AddData("dex_location2", /* checksum */ 2, /* method_idx */ i, &saved_info));
132 ASSERT_TRUE(AddData("dex_location3", /* checksum */ 3, /* method_idx */ i, &saved_info));
133 }
134 ASSERT_TRUE(profile.GetFile()->ResetOffset());
135 ASSERT_TRUE(saved_info.Save(GetFd(profile)));
136 ASSERT_EQ(0, profile.GetFile()->Flush());
137
138 // Check that we get back everything we saved.
139 ProfileCompilationInfo loaded_info2;
140 ASSERT_TRUE(profile.GetFile()->ResetOffset());
141 ASSERT_TRUE(loaded_info2.Load(GetFd(profile)));
142 ASSERT_TRUE(loaded_info2.Equals(saved_info));
143}
144
145TEST_F(ProfileCompilationInfoTest, AddDataFail) {
146 ScratchFile profile;
147
148 ProfileCompilationInfo info;
149 ASSERT_TRUE(AddData("dex_location", /* checksum */ 1, /* method_idx */ 1, &info));
150 // Trying to add info for an existing file but with a different checksum.
151 ASSERT_FALSE(AddData("dex_location", /* checksum */ 2, /* method_idx */ 2, &info));
152}
153
154TEST_F(ProfileCompilationInfoTest, LoadFail) {
155 ScratchFile profile;
156
157 ProfileCompilationInfo info1;
158 ASSERT_TRUE(AddData("dex_location", /* checksum */ 1, /* method_idx */ 1, &info1));
159 // Use the same file, change the checksum.
160 ProfileCompilationInfo info2;
161 ASSERT_TRUE(AddData("dex_location", /* checksum */ 2, /* method_idx */ 2, &info2));
162
163 ASSERT_FALSE(info1.Load(info2));
164}
165
166} // namespace art