1 /* 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 #ifndef ART_RUNTIME_JIT_OFFLINE_PROFILING_INFO_H_ 18 #define ART_RUNTIME_JIT_OFFLINE_PROFILING_INFO_H_ 19 20 #include <set> 21 #include <vector> 22 23 #include "atomic.h" 24 #include "dex_cache_resolved_classes.h" 25 #include "dex_file.h" 26 #include "method_reference.h" 27 #include "safe_map.h" 28 29 namespace art { 30 31 // TODO: rename file. 32 /** 33 * Profile information in a format suitable to be queried by the compiler and 34 * performing profile guided compilation. 35 * It is a serialize-friendly format based on information collected by the 36 * interpreter (ProfileInfo). 37 * Currently it stores only the hot compiled methods. 38 */ 39 class ProfileCompilationInfo { 40 public: 41 static const uint8_t kProfileMagic[]; 42 static const uint8_t kProfileVersion[]; 43 44 // Add the given methods and classes to the current profile object. 45 bool AddMethodsAndClasses(const std::vector<MethodReference>& methods, 46 const std::set<DexCacheResolvedClasses>& resolved_classes); 47 // Loads profile information from the given file descriptor. 48 bool Load(int fd); 49 // Merge the data from another ProfileCompilationInfo into the current object. 50 bool MergeWith(const ProfileCompilationInfo& info); 51 // Saves the profile data to the given file descriptor. 52 bool Save(int fd); 53 // Loads and merges profile information from the given file into the current 54 // object and tries to save it back to disk. 55 // If `force` is true then the save will go through even if the given file 56 // has bad data or its version does not match. In this cases the profile content 57 // is ignored. 58 bool MergeAndSave(const std::string& filename, uint64_t* bytes_written, bool force); 59 60 // Returns the number of methods that were profiled. 61 uint32_t GetNumberOfMethods() const; 62 // Returns the number of resolved classes that were profiled. 63 uint32_t GetNumberOfResolvedClasses() const; 64 65 // Returns true if the method reference is present in the profiling info. 66 bool ContainsMethod(const MethodReference& method_ref) const; 67 68 // Returns true if the class is present in the profiling info. 69 bool ContainsClass(const DexFile& dex_file, uint16_t class_def_idx) const; 70 71 // Dumps all the loaded profile info into a string and returns it. 72 // If dex_files is not null then the method indices will be resolved to their 73 // names. 74 // This is intended for testing and debugging. 75 std::string DumpInfo(const std::vector<const DexFile*>* dex_files, 76 bool print_full_dex_location = true) const; 77 78 bool Equals(const ProfileCompilationInfo& other); 79 80 static std::string GetProfileDexFileKey(const std::string& dex_location); 81 82 // Returns the class descriptors for all of the classes in the profiles' class sets. 83 // Note the dex location is actually the profile key, the caller needs to call back in to the 84 // profile info stuff to generate a map back to the dex location. 85 std::set<DexCacheResolvedClasses> GetResolvedClasses() const; 86 87 // Clears the resolved classes from the current object. 88 void ClearResolvedClasses(); 89 90 private: 91 enum ProfileLoadSatus { 92 kProfileLoadIOError, 93 kProfileLoadVersionMismatch, 94 kProfileLoadBadData, 95 kProfileLoadSuccess 96 }; 97 98 struct DexFileData { DexFileDataDexFileData99 explicit DexFileData(uint32_t location_checksum) : checksum(location_checksum) {} 100 uint32_t checksum; 101 std::set<uint16_t> method_set; 102 std::set<uint16_t> class_set; 103 104 bool operator==(const DexFileData& other) const { 105 return checksum == other.checksum && method_set == other.method_set; 106 } 107 }; 108 109 using DexFileToProfileInfoMap = SafeMap<const std::string, DexFileData>; 110 111 DexFileData* GetOrAddDexFileData(const std::string& dex_location, uint32_t checksum); 112 bool AddMethodIndex(const std::string& dex_location, uint32_t checksum, uint16_t method_idx); 113 bool AddClassIndex(const std::string& dex_location, uint32_t checksum, uint16_t class_idx); 114 bool AddResolvedClasses(const DexCacheResolvedClasses& classes); 115 116 // Parsing functionality. 117 118 struct ProfileLineHeader { 119 std::string dex_location; 120 uint16_t method_set_size; 121 uint16_t class_set_size; 122 uint32_t checksum; 123 }; 124 125 // A helper structure to make sure we don't read past our buffers in the loops. 126 struct SafeBuffer { 127 public: SafeBufferSafeBuffer128 explicit SafeBuffer(size_t size) : storage_(new uint8_t[size]) { 129 ptr_current_ = storage_.get(); 130 ptr_end_ = ptr_current_ + size; 131 } 132 133 // Reads the content of the descriptor at the current position. 134 ProfileLoadSatus FillFromFd(int fd, 135 const std::string& source, 136 /*out*/std::string* error); 137 138 // Reads an uint value (high bits to low bits) and advances the current pointer 139 // with the number of bits read. 140 template <typename T> T ReadUintAndAdvance(); 141 142 // Compares the given data with the content current pointer. If the contents are 143 // equal it advances the current pointer by data_size. 144 bool CompareAndAdvance(const uint8_t* data, size_t data_size); 145 146 // Get the underlying raw buffer. GetSafeBuffer147 uint8_t* Get() { return storage_.get(); } 148 149 private: 150 std::unique_ptr<uint8_t> storage_; 151 uint8_t* ptr_current_; 152 uint8_t* ptr_end_; 153 }; 154 155 ProfileLoadSatus LoadInternal(int fd, std::string* error); 156 157 ProfileLoadSatus ReadProfileHeader(int fd, 158 /*out*/uint16_t* number_of_lines, 159 /*out*/std::string* error); 160 161 ProfileLoadSatus ReadProfileLineHeader(int fd, 162 /*out*/ProfileLineHeader* line_header, 163 /*out*/std::string* error); 164 ProfileLoadSatus ReadProfileLine(int fd, 165 const ProfileLineHeader& line_header, 166 /*out*/std::string* error); 167 168 bool ProcessLine(SafeBuffer& line_buffer, 169 uint16_t method_set_size, 170 uint16_t class_set_size, 171 uint32_t checksum, 172 const std::string& dex_location); 173 174 friend class ProfileCompilationInfoTest; 175 friend class CompilerDriverProfileTest; 176 friend class ProfileAssistantTest; 177 178 DexFileToProfileInfoMap info_; 179 }; 180 181 } // namespace art 182 183 #endif // ART_RUNTIME_JIT_OFFLINE_PROFILING_INFO_H_ 184