offline_profiling_info.cc revision 998c21661b5074c293cae818d0ab7c44dcda3a66
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" 2766f55237679db90cb0a0a265043a787932b466f8Calin Juravle#include "base/stl_util.h" 2831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include "jit/profiling_info.h" 2931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include "safe_map.h" 3031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 3131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravlenamespace art { 3231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 33998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravlebool ProfileCompilationInfo::SaveProfilingInfo(const std::string& filename, 34998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const std::vector<ArtMethod*>& methods) { 3531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle if (methods.empty()) { 3631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle VLOG(profiler) << "No info to save to " << filename; 37998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return true; 3831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 3931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 40998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle ProfileCompilationInfo info; 41998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (!info.Load(filename)) { 42998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle LOG(WARNING) << "Could not load previous profile data from file " << filename; 43998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return false; 44998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 4531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle { 4631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle ScopedObjectAccess soa(Thread::Current()); 4731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle for (auto it = methods.begin(); it != methods.end(); it++) { 48998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const DexFile* dex_file = (*it)->GetDexFile(); 49998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (!info.AddData(dex_file->GetLocation(), 50998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle dex_file->GetLocationChecksum(), 51998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle (*it)->GetDexMethodIndex())) { 52998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return false; 53998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 5431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 5531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 5631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 5731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle // This doesn't need locking because we are trying to lock the file for exclusive 5831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle // access and fail immediately if we can't. 59998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle bool result = info.Save(filename); 60998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (result) { 614d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle VLOG(profiler) << "Successfully saved profile info to " << filename 624d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle << " Size: " << GetFileSizeBytes(filename); 63998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } else { 64998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle VLOG(profiler) << "Failed to save profile info to " << filename; 6531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 66998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return result; 6731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} 6831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 69226501b317e148aa8a8983355e85acb59c1eee83Calin Juravleenum OpenMode { 70226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle READ, 71226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle READ_WRITE 72226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle}; 73226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 74226501b317e148aa8a8983355e85acb59c1eee83Calin Juravlestatic int OpenFile(const std::string& filename, OpenMode open_mode) { 75226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle int fd = -1; 76226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle switch (open_mode) { 77226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle case READ: 78226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle fd = open(filename.c_str(), O_RDONLY); 79226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle break; 80226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle case READ_WRITE: 81226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // TODO(calin) allow the shared uid of the app to access the file. 825e2b971e468ca73a8e10a120730b3b6f17fad408Calin Juravle fd = open(filename.c_str(), O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC); 83226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle break; 84226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 85226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 8631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle if (fd < 0) { 8731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle PLOG(WARNING) << "Failed to open profile file " << filename; 8831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle return -1; 8931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 9031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 9131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle // Lock the file for exclusive access but don't wait if we can't lock it. 9231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle int err = flock(fd, LOCK_EX | LOCK_NB); 9331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle if (err < 0) { 9431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle PLOG(WARNING) << "Failed to lock profile file " << filename; 9531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle return -1; 9631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 9731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle return fd; 9831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} 9931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 10031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravlestatic bool CloseDescriptorForFile(int fd, const std::string& filename) { 10131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle // Now unlock the file, allowing another process in. 10231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle int err = flock(fd, LOCK_UN); 10331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle if (err < 0) { 10431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle PLOG(WARNING) << "Failed to unlock profile file " << filename; 10531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle return false; 10631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 10731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 10831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle // Done, close the file. 10931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle err = ::close(fd); 11031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle if (err < 0) { 11131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle PLOG(WARNING) << "Failed to close descriptor for profile file" << filename; 11231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle return false; 11331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 11431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 11531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle return true; 11631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} 11731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 11831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravlestatic void WriteToFile(int fd, const std::ostringstream& os) { 11931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle std::string data(os.str()); 12031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle const char *p = data.c_str(); 12131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle size_t length = data.length(); 12231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle do { 12331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle int n = ::write(fd, p, length); 12431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle p += n; 12531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle length -= n; 12631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } while (length > 0); 12731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} 12831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 129226501b317e148aa8a8983355e85acb59c1eee83Calin Juravlestatic constexpr const char kFieldSeparator = ','; 130226501b317e148aa8a8983355e85acb59c1eee83Calin Juravlestatic constexpr const char kLineSeparator = '\n'; 13131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 13231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle/** 13331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * Serialization format: 13466f55237679db90cb0a0a265043a787932b466f8Calin Juravle * dex_location1,dex_location_checksum1,method_id11,method_id12... 13566f55237679db90cb0a0a265043a787932b466f8Calin Juravle * dex_location2,dex_location_checksum2,method_id21,method_id22... 13631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle * e.g. 13766f55237679db90cb0a0a265043a787932b466f8Calin Juravle * /system/priv-app/app/app.apk,131232145,11,23,454,54 13866f55237679db90cb0a0a265043a787932b466f8Calin Juravle * /system/priv-app/app/app.apk:classes5.dex,218490184,39,13,49,1 13931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle **/ 140998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravlebool ProfileCompilationInfo::Save(const std::string& filename) { 141226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle int fd = OpenFile(filename, READ_WRITE); 14231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle if (fd == -1) { 14331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle return false; 14431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 14531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 14631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle // TODO(calin): Merge with a previous existing profile. 14731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle // TODO(calin): Profile this and see how much memory it takes. If too much, 14831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle // write to file directly. 14931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle std::ostringstream os; 150998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (const auto& it : info_) { 151998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const std::string& dex_location = it.first; 152998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const DexFileData& dex_data = it.second; 153998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle 154998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle os << dex_location << kFieldSeparator << dex_data.checksum; 155998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (auto method_it : dex_data.method_set) { 15631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle os << kFieldSeparator << method_it; 15731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 15831f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle os << kLineSeparator; 15931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle } 16031f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 16131f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle WriteToFile(fd, os); 16231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle 16331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle return CloseDescriptorForFile(fd, filename); 16431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} 165226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 166226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// TODO(calin): This a duplicate of Utils::Split fixing the case where the first character 167226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// is the separator. Merge the fix into Utils::Split once verified that it doesn't break its users. 168226501b317e148aa8a8983355e85acb59c1eee83Calin Juravlestatic void SplitString(const std::string& s, char separator, std::vector<std::string>* result) { 169226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle const char* p = s.data(); 170226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle const char* end = p + s.size(); 171226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Check if the first character is the separator. 172226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (p != end && *p ==separator) { 173226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle result->push_back(""); 174226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle ++p; 175226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 176226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Process the rest of the characters. 177226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle while (p != end) { 178226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (*p == separator) { 179226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle ++p; 180226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } else { 181226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle const char* start = p; 182226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle while (++p != end && *p != separator) { 183226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Skip to the next occurrence of the separator. 184226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 185226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle result->push_back(std::string(start, p - start)); 186226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 187226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 188226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle} 189226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 190998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravlebool ProfileCompilationInfo::AddData(const std::string& dex_location, 191998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle uint32_t checksum, 192998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle uint16_t method_idx) { 193998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle auto info_it = info_.find(dex_location); 194998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (info_it == info_.end()) { 195998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle info_it = info_.Put(dex_location, DexFileData(checksum)); 196998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 197998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (info_it->second.checksum != checksum) { 198998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle LOG(WARNING) << "Checksum mismatch for dex " << dex_location; 199998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return false; 200998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 201998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle info_it->second.method_set.insert(method_idx); 202998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return true; 203998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle} 204998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle 205998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravlebool ProfileCompilationInfo::ProcessLine(const std::string& line) { 206226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle std::vector<std::string> parts; 207226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle SplitString(line, kFieldSeparator, &parts); 208226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (parts.size() < 3) { 209226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle LOG(WARNING) << "Invalid line: " << line; 210226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return false; 211226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 212226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 21366f55237679db90cb0a0a265043a787932b466f8Calin Juravle const std::string& dex_location = parts[0]; 214226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle uint32_t checksum; 215226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (!ParseInt(parts[1].c_str(), &checksum)) { 216226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return false; 217226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 218226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 219226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle for (size_t i = 2; i < parts.size(); i++) { 220226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle uint32_t method_idx; 221226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (!ParseInt(parts[i].c_str(), &method_idx)) { 222226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle LOG(WARNING) << "Cannot parse method_idx " << parts[i]; 223226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return false; 224226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 225998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle AddData(dex_location, checksum, method_idx); 226226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 227226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return true; 228226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle} 229226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 230226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// Parses the buffer (of length n) starting from start_from and identify new lines 231226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// based on kLineSeparator marker. 232226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// Returns the first position after kLineSeparator in the buffer (starting from start_from), 233226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// or -1 if the marker doesn't appear. 234226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle// The processed characters are appended to the given line. 235226501b317e148aa8a8983355e85acb59c1eee83Calin Juravlestatic int GetLineFromBuffer(char* buffer, int n, int start_from, std::string& line) { 236226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (start_from >= n) { 237226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return -1; 238226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 239226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle int new_line_pos = -1; 240226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle for (int i = start_from; i < n; i++) { 241226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (buffer[i] == kLineSeparator) { 242226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle new_line_pos = i; 243226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle break; 244226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 245226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 246226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle int append_limit = new_line_pos == -1 ? n : new_line_pos; 247226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle line.append(buffer + start_from, append_limit - start_from); 248226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Jump over kLineSeparator and return the position of the next character. 249226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return new_line_pos == -1 ? new_line_pos : new_line_pos + 1; 250226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle} 251226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 252998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravlebool ProfileCompilationInfo::Load(const std::string& filename) { 253998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle int fd = OpenFile(filename, READ); 254226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (fd == -1) { 255226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return false; 256226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 257226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 258226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle std::string current_line; 259226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle const int kBufferSize = 1024; 260226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle char buffer[kBufferSize]; 261226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle bool success = true; 262226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 263226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle while (success) { 264226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle int n = read(fd, buffer, kBufferSize); 265226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (n < 0) { 266998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle PLOG(WARNING) << "Error when reading profile file " << filename; 267226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle success = false; 268226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle break; 269226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } else if (n == 0) { 270226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle break; 271226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 272226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Detect the new lines from the buffer. If we manage to complete a line, 273226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // process it. Otherwise append to the current line. 274226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle int current_start_pos = 0; 275226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle while (current_start_pos < n) { 276226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle current_start_pos = GetLineFromBuffer(buffer, n, current_start_pos, current_line); 277226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (current_start_pos == -1) { 278226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle break; 279226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 280998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (!ProcessLine(current_line)) { 281226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle success = false; 282226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle break; 283226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 284226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Reset the current line (we just processed it). 285226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle current_line.clear(); 286226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 287226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 288226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (!success) { 289226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle info_.clear(); 290226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 291998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return CloseDescriptorForFile(fd, filename) && success; 292998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle} 293998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle 294998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravlebool ProfileCompilationInfo::Load(const ProfileCompilationInfo& other) { 295998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (const auto& other_it : other.info_) { 296998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const std::string& other_dex_location = other_it.first; 297998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const DexFileData& other_dex_data = other_it.second; 298998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle 299998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle auto info_it = info_.find(other_dex_location); 300998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (info_it == info_.end()) { 301998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle info_it = info_.Put(other_dex_location, DexFileData(other_dex_data.checksum)); 302998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 303998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (info_it->second.checksum != other_dex_data.checksum) { 304998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle LOG(WARNING) << "Checksum mismatch for dex " << other_dex_location; 305998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return false; 306998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 307998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle info_it->second.method_set.insert(other_dex_data.method_set.begin(), 308998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle other_dex_data.method_set.end()); 309998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 310998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return true; 311226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle} 312226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 313226501b317e148aa8a8983355e85acb59c1eee83Calin Juravlebool ProfileCompilationInfo::ContainsMethod(const MethodReference& method_ref) const { 314998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle auto info_it = info_.find(method_ref.dex_file->GetLocation()); 315226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (info_it != info_.end()) { 316998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (method_ref.dex_file->GetLocationChecksum() != info_it->second.checksum) { 317998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return false; 318226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 319998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const std::set<uint16_t>& methods = info_it->second.method_set; 320998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return methods.find(method_ref.dex_method_index) != methods.end(); 321226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 322226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return false; 323226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle} 324226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 325998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravleuint32_t ProfileCompilationInfo::GetNumberOfMethods() const { 326998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle uint32_t total = 0; 327998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (const auto& it : info_) { 328998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle total += it.second.method_set.size(); 329998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 330998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle return total; 331998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle} 332998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle 333998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravlestd::string ProfileCompilationInfo::DumpInfo(const std::vector<const DexFile*>* dex_files, 334998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle bool print_full_dex_location) const { 335226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle std::ostringstream os; 336226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (info_.empty()) { 337226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return "ProfileInfo: empty"; 338226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 339226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 340226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle os << "ProfileInfo:"; 341226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 342226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle const std::string kFirstDexFileKeySubstitute = ":classes.dex"; 343998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (const auto& it : info_) { 344226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle os << "\n"; 345998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const std::string& location = it.first; 346998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const DexFileData& dex_data = it.second; 347226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle if (print_full_dex_location) { 348226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle os << location; 349226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } else { 350226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle // Replace the (empty) multidex suffix of the first key with a substitute for easier reading. 351226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle std::string multidex_suffix = DexFile::GetMultiDexSuffix(location); 352226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle os << (multidex_suffix.empty() ? kFirstDexFileKeySubstitute : multidex_suffix); 353226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 354998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (const auto method_it : dex_data.method_set) { 355998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (dex_files != nullptr) { 356998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle const DexFile* dex_file = nullptr; 357998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle for (size_t i = 0; i < dex_files->size(); i++) { 358998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (location == (*dex_files)[i]->GetLocation()) { 359998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle dex_file = (*dex_files)[i]; 360998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 361998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 362998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle if (dex_file != nullptr) { 363998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle os << "\n " << PrettyMethod(method_it, *dex_file, true); 364998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle } 365226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 366998c21661b5074c293cae818d0ab7c44dcda3a66Calin Juravle os << "\n " << method_it; 367226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 368226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle } 369226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle return os.str(); 370226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle} 371226501b317e148aa8a8983355e85acb59c1eee83Calin Juravle 37231f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle} // namespace art 373