blob: 85335efcc48c355b96da4b024f040d4a44869af1 [file] [log] [blame]
Calin Juravle998c2162015-12-21 15:39:33 +02001/*
2 * Copyright (C) 2015 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 "profile_assistant.h"
18
Calin Juravle877fd962016-01-05 14:29:29 +000019#include "base/unix_file/fd_file.h"
20#include "os.h"
21
Calin Juravle998c2162015-12-21 15:39:33 +020022namespace art {
23
24// Minimum number of new methods that profiles must contain to enable recompilation.
25static constexpr const uint32_t kMinNewMethodsForCompilation = 10;
26
Calin Juravle877fd962016-01-05 14:29:29 +000027bool ProfileAssistant::ProcessProfilesInternal(
28 const std::vector<ScopedFlock>& profile_files,
29 const std::vector<ScopedFlock>& reference_profile_files,
30 /*out*/ ProfileCompilationInfo** profile_compilation_info) {
Calin Juravle998c2162015-12-21 15:39:33 +020031 DCHECK(!profile_files.empty());
Calin Juravle877fd962016-01-05 14:29:29 +000032 DCHECK(!reference_profile_files.empty() ||
Calin Juravle998c2162015-12-21 15:39:33 +020033 (profile_files.size() == reference_profile_files.size()));
Calin Juravle47c83ea2016-01-20 03:56:12 +000034
Calin Juravle998c2162015-12-21 15:39:33 +020035 std::vector<ProfileCompilationInfo> new_info(profile_files.size());
36 bool should_compile = false;
37 // Read the main profile files.
Calin Juravle877fd962016-01-05 14:29:29 +000038 for (size_t i = 0; i < new_info.size(); i++) {
39 if (!new_info[i].Load(profile_files[i].GetFile()->Fd())) {
40 LOG(WARNING) << "Could not load profile file at index " << i;
Calin Juravle998c2162015-12-21 15:39:33 +020041 return false;
42 }
43 // Do we have enough new profiled methods that will make the compilation worthwhile?
44 should_compile |= (new_info[i].GetNumberOfMethods() > kMinNewMethodsForCompilation);
45 }
Calin Juravle877fd962016-01-05 14:29:29 +000046
Calin Juravle998c2162015-12-21 15:39:33 +020047 if (!should_compile) {
Calin Juravle998c2162015-12-21 15:39:33 +020048 return true;
49 }
50
51 std::unique_ptr<ProfileCompilationInfo> result(new ProfileCompilationInfo());
Calin Juravle877fd962016-01-05 14:29:29 +000052 // Merge information.
Calin Juravle998c2162015-12-21 15:39:33 +020053 for (size_t i = 0; i < new_info.size(); i++) {
Calin Juravle998c2162015-12-21 15:39:33 +020054 if (!reference_profile_files.empty()) {
Calin Juravle877fd962016-01-05 14:29:29 +000055 if (!new_info[i].Load(reference_profile_files[i].GetFile()->Fd())) {
56 LOG(WARNING) << "Could not load reference profile file at index " << i;
Calin Juravle998c2162015-12-21 15:39:33 +020057 return false;
58 }
Calin Juravle877fd962016-01-05 14:29:29 +000059 }
60 // Merge all data into a single object.
61 if (!result->Load(new_info[i])) {
62 LOG(WARNING) << "Could not merge profile data at index " << i;
63 return false;
64 }
65 }
66 // We were successful in merging all profile information. Update the files.
67 for (size_t i = 0; i < new_info.size(); i++) {
68 if (!reference_profile_files.empty()) {
69 if (!reference_profile_files[i].GetFile()->ClearContent()) {
70 PLOG(WARNING) << "Could not clear reference profile file at index " << i;
71 return false;
72 }
73 if (!new_info[i].Save(reference_profile_files[i].GetFile()->Fd())) {
74 LOG(WARNING) << "Could not save reference profile file at index " << i;
75 return false;
76 }
77 if (!profile_files[i].GetFile()->ClearContent()) {
78 PLOG(WARNING) << "Could not clear profile file at index " << i;
Calin Juravle998c2162015-12-21 15:39:33 +020079 return false;
80 }
81 }
82 }
Calin Juravle877fd962016-01-05 14:29:29 +000083
Calin Juravle998c2162015-12-21 15:39:33 +020084 *profile_compilation_info = result.release();
85 return true;
86}
87
Calin Juravle877fd962016-01-05 14:29:29 +000088class ScopedCollectionFlock {
89 public:
90 explicit ScopedCollectionFlock(size_t size) : flocks_(size) {}
91
92 // Will block until all the locks are acquired.
93 bool Init(const std::vector<std::string>& filenames, /* out */ std::string* error) {
94 for (size_t i = 0; i < filenames.size(); i++) {
95 if (!flocks_[i].Init(filenames[i].c_str(), O_RDWR, /* block */ true, error)) {
96 *error += " (index=" + std::to_string(i) + ")";
97 return false;
98 }
99 }
100 return true;
101 }
102
103 // Will block until all the locks are acquired.
104 bool Init(const std::vector<uint32_t>& fds, /* out */ std::string* error) {
105 for (size_t i = 0; i < fds.size(); i++) {
106 // We do not own the descriptor, so disable auto-close and don't check usage.
107 File file(fds[i], false);
108 file.DisableAutoClose();
109 if (!flocks_[i].Init(&file, error)) {
110 *error += " (index=" + std::to_string(i) + ")";
111 return false;
112 }
113 }
114 return true;
115 }
116
117 const std::vector<ScopedFlock>& Get() const { return flocks_; }
118
119 private:
120 std::vector<ScopedFlock> flocks_;
121};
122
123bool ProfileAssistant::ProcessProfiles(
124 const std::vector<uint32_t>& profile_files_fd,
125 const std::vector<uint32_t>& reference_profile_files_fd,
126 /*out*/ ProfileCompilationInfo** profile_compilation_info) {
Calin Juravle47c83ea2016-01-20 03:56:12 +0000127 *profile_compilation_info = nullptr;
128
Calin Juravle877fd962016-01-05 14:29:29 +0000129 std::string error;
130 ScopedCollectionFlock profile_files_flocks(profile_files_fd.size());
131 if (!profile_files_flocks.Init(profile_files_fd, &error)) {
132 LOG(WARNING) << "Could not lock profile files: " << error;
133 return false;
134 }
135 ScopedCollectionFlock reference_profile_files_flocks(reference_profile_files_fd.size());
136 if (!reference_profile_files_flocks.Init(reference_profile_files_fd, &error)) {
137 LOG(WARNING) << "Could not lock reference profile files: " << error;
138 return false;
139 }
140
141 return ProcessProfilesInternal(profile_files_flocks.Get(),
142 reference_profile_files_flocks.Get(),
143 profile_compilation_info);
144}
145
146bool ProfileAssistant::ProcessProfiles(
147 const std::vector<std::string>& profile_files,
148 const std::vector<std::string>& reference_profile_files,
149 /*out*/ ProfileCompilationInfo** profile_compilation_info) {
Calin Juravle47c83ea2016-01-20 03:56:12 +0000150 *profile_compilation_info = nullptr;
151
Calin Juravle877fd962016-01-05 14:29:29 +0000152 std::string error;
153 ScopedCollectionFlock profile_files_flocks(profile_files.size());
154 if (!profile_files_flocks.Init(profile_files, &error)) {
155 LOG(WARNING) << "Could not lock profile files: " << error;
156 return false;
157 }
158 ScopedCollectionFlock reference_profile_files_flocks(reference_profile_files.size());
159 if (!reference_profile_files_flocks.Init(reference_profile_files, &error)) {
160 LOG(WARNING) << "Could not lock reference profile files: " << error;
161 return false;
162 }
163
164 return ProcessProfilesInternal(profile_files_flocks.Get(),
165 reference_profile_files_flocks.Get(),
166 profile_compilation_info);
167}
168
Calin Juravle998c2162015-12-21 15:39:33 +0200169} // namespace art