offline_profiling_info.cc revision 31708b736a2d75a9eb21f51038a7703f84f95f31
131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle/* 231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * Copyright (C) 2015 The Android Open Source Project 331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * 431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * Licensed under the Apache License, Version 2.0 (the "License"); 531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * you may not use this file except in compliance with the License. 631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * You may obtain a copy of the License at 731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * 831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * http://www.apache.org/licenses/LICENSE-2.0 931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * 1031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * Unless required by applicable law or agreed to in writing, software 1131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * distributed under the License is distributed on an "AS IS" BASIS, 1231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * See the License for the specific language governing permissions and 1431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * limitations under the License. 1531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle */ 1631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 1731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include "offline_profiling_info.h" 1831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 1931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include <fstream> 204d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle#include <vector> 2131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include <sys/file.h> 2231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include <sys/stat.h> 2331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include <sys/uio.h> 2431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 2531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include "art_method-inl.h" 2631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include "base/mutex.h" 27877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle#include "base/scoped_flock.h" 2866f55237679db90cb0a0a265043a787932b466f8Calin Juravle#include "base/stl_util.h" 29877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle#include "base/unix_file/fd_file.h" 3031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include "jit/profiling_info.h" 31877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle#include "os.h" 3231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include "safe_map.h" 3331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 3431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravlenamespace art { 3531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 3634900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle// Transform the actual dex location into relative paths. 3734900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle// Note: this is OK because we don't store profiles of different apps into the same file. 3834900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle// Apps with split apks don't cause trouble because each split has a different name and will not 3934900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle// collide with other entries. 4031708b736a2d75a9eb21f51038a7703f84f95f31Calin Juravlestd::string ProfileCompilationInfo::GetProfileDexFileKey(const std::string& dex_location) { 4134900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle DCHECK(!dex_location.empty()); 4234900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle size_t last_sep_index = dex_location.find_last_of('/'); 4334900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle if (last_sep_index == std::string::npos) { 4434900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle return dex_location; 4534900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle } else { 4631708b736a2d75a9eb21f51038a7703f84f95f31Calin Juravle DCHECK(last_sep_index < dex_location.size()); 4731708b736a2d75a9eb21f51038a7703f84f95f31Calin Juravle return dex_location.substr(last_sep_index + 1); 4834900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle } 4934900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle} 5034900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle 51998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravlebool ProfileCompilationInfo::SaveProfilingInfo(const std::string& filename, 52998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const std::vector<ArtMethod*>& methods) { 5331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle if (methods.empty()) { 5431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle VLOG(profiler) << "No info to save to " << filename; 55998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return true; 5631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 5731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 58877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle ScopedFlock flock; 59877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle std::string error; 60877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle if (!flock.Init(filename.c_str(), O_RDWR | O_NOFOLLOW | O_CLOEXEC, /* block */ false, &error)) { 61877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle LOG(WARNING) << "Couldn't lock the profile file " << filename << ": " << error; 62877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle return false; 63877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle } 64877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle 65877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle int fd = flock.GetFile()->Fd(); 66877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle 67998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle ProfileCompilationInfo info; 68877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle if (!info.Load(fd)) { 69998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle LOG(WARNING) << "Could not load previous profile data from file " << filename; 70998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return false; 71998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 7231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle { 7331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle ScopedObjectAccess soa(Thread::Current()); 7431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle for (auto it = methods.begin(); it != methods.end(); it++) { 75998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const DexFile* dex_file = (*it)->GetDexFile(); 7634900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle if (!info.AddData(GetProfileDexFileKey(dex_file->GetLocation()), 77998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle dex_file->GetLocationChecksum(), 78998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle (*it)->GetDexMethodIndex())) { 79998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return false; 80998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 8131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 8231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 8331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 84877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle if (!flock.GetFile()->ClearContent()) { 85877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle PLOG(WARNING) << "Could not clear profile file: " << filename; 86877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle return false; 87877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle } 88877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle 8931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle // This doesn't need locking because we are trying to lock the file for exclusive 9031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle // access and fail immediately if we can't. 91877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle bool result = info.Save(fd); 92998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (result) { 934d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle VLOG(profiler) << "Successfully saved profile info to " << filename 944d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle << " Size: " << GetFileSizeBytes(filename); 95998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } else { 96998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle VLOG(profiler) << "Failed to save profile info to " << filename; 9731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 98998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return result; 9931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} 10031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 101877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravlestatic bool WriteToFile(int fd, const std::ostringstream& os) { 10231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle std::string data(os.str()); 10331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle const char *p = data.c_str(); 10431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle size_t length = data.length(); 10531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle do { 106877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle int n = TEMP_FAILURE_RETRY(write(fd, p, length)); 107877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle if (n < 0) { 108877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle PLOG(WARNING) << "Failed to write to descriptor: " << fd; 109877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle return false; 110877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle } 11131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle p += n; 11231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle length -= n; 11331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } while (length > 0); 114877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle return true; 11531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} 11631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 117226501b317e148aa8a8983355e85acb59c1eee83Calin Juravlestatic constexpr const char kFieldSeparator = ','; 118226501b317e148aa8a8983355e85acb59c1eee83Calin Juravlestatic constexpr const char kLineSeparator = '\n'; 11931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 12031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle/** 12131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * Serialization format: 12266f55237679db90cb0a0a265043a787932b466f8Calin Juravle * dex_location1,dex_location_checksum1,method_id11,method_id12... 12366f55237679db90cb0a0a265043a787932b466f8Calin Juravle * dex_location2,dex_location_checksum2,method_id21,method_id22... 12431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * e.g. 12534900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle * app.apk,131232145,11,23,454,54 12634900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle * app.apk:classes5.dex,218490184,39,13,49,1 12731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle **/ 128877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravlebool ProfileCompilationInfo::Save(uint32_t fd) { 129877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle DCHECK_GE(fd, 0u); 13031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle // TODO(calin): Profile this and see how much memory it takes. If too much, 13131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle // write to file directly. 13231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle std::ostringstream os; 133998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (const auto& it : info_) { 134998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const std::string& dex_location = it.first; 135998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const DexFileData& dex_data = it.second; 136998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle 137998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle os << dex_location << kFieldSeparator << dex_data.checksum; 138998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (auto method_it : dex_data.method_set) { 13931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle os << kFieldSeparator << method_it; 14031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 14131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle os << kLineSeparator; 14231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 14331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 144877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle return WriteToFile(fd, os); 14531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} 146226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 147226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// TODO(calin): This a duplicate of Utils::Split fixing the case where the first character 148226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// is the separator. Merge the fix into Utils::Split once verified that it doesn't break its users. 149226501b317e148aa8a8983355e85acb59c1eee83Calin Juravlestatic void SplitString(const std::string& s, char separator, std::vector<std::string>* result) { 150226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle const char* p = s.data(); 151226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle const char* end = p + s.size(); 152226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Check if the first character is the separator. 153226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (p != end && *p ==separator) { 154226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle result->push_back(""); 155226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle ++p; 156226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 157226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Process the rest of the characters. 158226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle while (p != end) { 159226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (*p == separator) { 160226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle ++p; 161226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } else { 162226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle const char* start = p; 163226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle while (++p != end && *p != separator) { 164226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Skip to the next occurrence of the separator. 165226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 166226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle result->push_back(std::string(start, p - start)); 167226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 168226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 169226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle} 170226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 171998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravlebool ProfileCompilationInfo::AddData(const std::string& dex_location, 172998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle uint32_t checksum, 173998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle uint16_t method_idx) { 174998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle auto info_it = info_.find(dex_location); 175998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (info_it == info_.end()) { 176998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle info_it = info_.Put(dex_location, DexFileData(checksum)); 177998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 178998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (info_it->second.checksum != checksum) { 179998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle LOG(WARNING) << "Checksum mismatch for dex " << dex_location; 180998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return false; 181998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 182998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle info_it->second.method_set.insert(method_idx); 183998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return true; 184998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle} 185998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle 186998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravlebool ProfileCompilationInfo::ProcessLine(const std::string& line) { 187226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle std::vector<std::string> parts; 188226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle SplitString(line, kFieldSeparator, &parts); 189226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (parts.size() < 3) { 190226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle LOG(WARNING) << "Invalid line: " << line; 191226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return false; 192226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 193226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 19466f55237679db90cb0a0a265043a787932b466f8Calin Juravle const std::string& dex_location = parts[0]; 195226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle uint32_t checksum; 196226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (!ParseInt(parts[1].c_str(), &checksum)) { 197226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return false; 198226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 199226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 200226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle for (size_t i = 2; i < parts.size(); i++) { 201226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle uint32_t method_idx; 202226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (!ParseInt(parts[i].c_str(), &method_idx)) { 203226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle LOG(WARNING) << "Cannot parse method_idx " << parts[i]; 204226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return false; 205226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 206877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle if (!AddData(dex_location, checksum, method_idx)) { 207877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle return false; 208877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle } 209226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 210226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return true; 211226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle} 212226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 213226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// Parses the buffer (of length n) starting from start_from and identify new lines 214226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// based on kLineSeparator marker. 215226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// Returns the first position after kLineSeparator in the buffer (starting from start_from), 216226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// or -1 if the marker doesn't appear. 217226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// The processed characters are appended to the given line. 218226501b317e148aa8a8983355e85acb59c1eee83Calin Juravlestatic int GetLineFromBuffer(char* buffer, int n, int start_from, std::string& line) { 219226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (start_from >= n) { 220226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return -1; 221226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 222226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle int new_line_pos = -1; 223226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle for (int i = start_from; i < n; i++) { 224226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (buffer[i] == kLineSeparator) { 225226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle new_line_pos = i; 226226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle break; 227226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 228226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 229226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle int append_limit = new_line_pos == -1 ? n : new_line_pos; 230226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle line.append(buffer + start_from, append_limit - start_from); 231226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Jump over kLineSeparator and return the position of the next character. 232226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return new_line_pos == -1 ? new_line_pos : new_line_pos + 1; 233226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle} 234226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 235877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravlebool ProfileCompilationInfo::Load(uint32_t fd) { 236877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle DCHECK_GE(fd, 0u); 237226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 238226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle std::string current_line; 239226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle const int kBufferSize = 1024; 240226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle char buffer[kBufferSize]; 241226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 242877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle while (true) { 243877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle int n = TEMP_FAILURE_RETRY(read(fd, buffer, kBufferSize)); 244226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (n < 0) { 245877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle PLOG(WARNING) << "Error when reading profile file"; 246877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle return false; 247226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } else if (n == 0) { 248226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle break; 249226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 250226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Detect the new lines from the buffer. If we manage to complete a line, 251226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // process it. Otherwise append to the current line. 252226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle int current_start_pos = 0; 253226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle while (current_start_pos < n) { 254226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle current_start_pos = GetLineFromBuffer(buffer, n, current_start_pos, current_line); 255226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (current_start_pos == -1) { 256226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle break; 257226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 258998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (!ProcessLine(current_line)) { 259877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle return false; 260226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 261226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Reset the current line (we just processed it). 262226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle current_line.clear(); 263226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 264226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 265877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle return true; 266998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle} 267998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle 268998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravlebool ProfileCompilationInfo::Load(const ProfileCompilationInfo& other) { 269998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (const auto& other_it : other.info_) { 270998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const std::string& other_dex_location = other_it.first; 271998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const DexFileData& other_dex_data = other_it.second; 272998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle 273998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle auto info_it = info_.find(other_dex_location); 274998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (info_it == info_.end()) { 275998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle info_it = info_.Put(other_dex_location, DexFileData(other_dex_data.checksum)); 276998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 277998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (info_it->second.checksum != other_dex_data.checksum) { 278998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle LOG(WARNING) << "Checksum mismatch for dex " << other_dex_location; 279998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return false; 280998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 281998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle info_it->second.method_set.insert(other_dex_data.method_set.begin(), 282998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle other_dex_data.method_set.end()); 283998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 284998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return true; 285226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle} 286226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 287226501b317e148aa8a8983355e85acb59c1eee83Calin Juravlebool ProfileCompilationInfo::ContainsMethod(const MethodReference& method_ref) const { 28834900cc6d9a14fb29a51daca02fe4b3e47e1b64cCalin Juravle auto info_it = info_.find(GetProfileDexFileKey(method_ref.dex_file->GetLocation())); 289226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (info_it != info_.end()) { 290998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (method_ref.dex_file->GetLocationChecksum() != info_it->second.checksum) { 291998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return false; 292226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 293998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const std::set<uint16_t>& methods = info_it->second.method_set; 294998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return methods.find(method_ref.dex_method_index) != methods.end(); 295226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 296226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return false; 297226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle} 298226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 299998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravleuint32_t ProfileCompilationInfo::GetNumberOfMethods() const { 300998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle uint32_t total = 0; 301998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (const auto& it : info_) { 302998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle total += it.second.method_set.size(); 303998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 304998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return total; 305998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle} 306998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle 307998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravlestd::string ProfileCompilationInfo::DumpInfo(const std::vector<const DexFile*>* dex_files, 308998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle bool print_full_dex_location) const { 309226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle std::ostringstream os; 310226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (info_.empty()) { 311226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return "ProfileInfo: empty"; 312226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 313226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 314226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle os << "ProfileInfo:"; 315226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 316226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle const std::string kFirstDexFileKeySubstitute = ":classes.dex"; 317998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (const auto& it : info_) { 318226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle os << "\n"; 319998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const std::string& location = it.first; 320998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const DexFileData& dex_data = it.second; 321226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (print_full_dex_location) { 322226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle os << location; 323226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } else { 324226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Replace the (empty) multidex suffix of the first key with a substitute for easier reading. 325226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle std::string multidex_suffix = DexFile::GetMultiDexSuffix(location); 326226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle os << (multidex_suffix.empty() ? kFirstDexFileKeySubstitute : multidex_suffix); 327226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 328998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (const auto method_it : dex_data.method_set) { 329998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (dex_files != nullptr) { 330998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const DexFile* dex_file = nullptr; 331998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (size_t i = 0; i < dex_files->size(); i++) { 332998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (location == (*dex_files)[i]->GetLocation()) { 333998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle dex_file = (*dex_files)[i]; 334998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 335998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 336998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (dex_file != nullptr) { 337998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle os << "\n " << PrettyMethod(method_it, *dex_file, true); 338998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 339226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 340998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle os << "\n " << method_it; 341226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 342226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 343226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return os.str(); 344226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle} 345226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 346877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravlebool ProfileCompilationInfo::Equals(ProfileCompilationInfo& other) { 347877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle return info_.Equals(other.info_); 348877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle} 349877fd963548a3175665bfef25b0d24bc0e5a0135Calin Juravle 35031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} // namespace art 351