1 /* 2 * Copyright (C) 2017 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_LIBDEXFILE_DEX_DEX_FILE_LAYOUT_H_ 18 #define ART_LIBDEXFILE_DEX_DEX_FILE_LAYOUT_H_ 19 20 #include <algorithm> 21 #include <cstdint> 22 #include <iosfwd> 23 24 #include <android-base/logging.h> 25 26 namespace art { 27 28 class DexFile; 29 30 enum class LayoutType : uint8_t { 31 // Layout of things that are hot (commonly accessed), these should be pinned or madvised will 32 // need. 33 kLayoutTypeHot, 34 // Layout of things that are randomly used. These should be advised to random access. 35 // Without layout, this is the default mode when loading a dex file. 36 kLayoutTypeSometimesUsed, 37 // Layout of things that are only used during startup, these can be madvised after launch. 38 kLayoutTypeStartupOnly, 39 // Layout of things that are needed probably only once (class initializers). These can be 40 // madvised during trim events. 41 kLayoutTypeUsedOnce, 42 // Layout of things that are thought to be unused. These things should be advised to random 43 // access. 44 kLayoutTypeUnused, 45 // Unused value, just the number of elements in the enum. 46 kLayoutTypeCount, 47 }; 48 std::ostream& operator<<(std::ostream& os, const LayoutType& collector_type); 49 50 // Return the "best" layout option if the same item has multiple different layouts. 51 static inline LayoutType MergeLayoutType(LayoutType a, LayoutType b) { 52 return std::min(a, b); 53 } 54 55 enum class MadviseState : uint8_t { 56 // Madvise based on a file that was just loaded. 57 kMadviseStateAtLoad, 58 // Madvise based after launch is finished. 59 kMadviseStateFinishedLaunch, 60 // Trim by madvising code that is unlikely to be too important in the future. 61 kMadviseStateFinishedTrim, 62 }; 63 std::ostream& operator<<(std::ostream& os, const MadviseState& collector_type); 64 65 // A dex layout section such as code items or strings. Each section is composed of subsections 66 // that are laid out adjacently to each other such as (hot, unused, startup, etc...). 67 class DexLayoutSection { 68 public: 69 // A subsection is a a continuous range of dex file that is all part of the same layout hint. 70 class Subsection { 71 public: 72 // Use uint32_t to handle 32/64 bit cross compilation. 73 uint32_t start_offset_ = 0u; 74 uint32_t end_offset_ = 0u; 75 76 bool Contains(uint32_t offset) const { 77 return start_offset_ <= offset && offset < end_offset_; 78 } 79 80 bool Size() const { 81 DCHECK_LE(start_offset_, end_offset_); 82 return end_offset_ - start_offset_; 83 } 84 85 void CombineSection(uint32_t start_offset, uint32_t end_offset) { 86 DCHECK_LE(start_offset, end_offset); 87 if (start_offset_ == end_offset_) { 88 start_offset_ = start_offset; 89 end_offset_ = end_offset; 90 } else { 91 start_offset_ = std::min(start_offset_, start_offset); 92 end_offset_ = std::max(end_offset_, end_offset); 93 } 94 } 95 96 void Madvise(const DexFile* dex_file, int advice) const; 97 }; 98 99 // Madvise the largest page-aligned region contained in [begin, end). 100 static int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice); 101 102 Subsection parts_[static_cast<size_t>(LayoutType::kLayoutTypeCount)]; 103 }; 104 105 // A set of dex layout sections, currently there is only one section for code and one for strings. 106 class DexLayoutSections { 107 public: 108 enum class SectionType : uint8_t { 109 kSectionTypeCode, 110 kSectionTypeStrings, 111 kSectionCount, 112 }; 113 114 // Advise access about the dex file based on layout. The caller is expected to have already 115 // madvised to MADV_RANDOM. 116 void Madvise(const DexFile* dex_file, MadviseState state) const; 117 118 DexLayoutSection sections_[static_cast<size_t>(SectionType::kSectionCount)]; 119 }; 120 121 std::ostream& operator<<(std::ostream& os, const DexLayoutSections::SectionType& collector_type); 122 std::ostream& operator<<(std::ostream& os, const DexLayoutSection& section); 123 std::ostream& operator<<(std::ostream& os, const DexLayoutSections& sections); 124 125 } // namespace art 126 127 #endif // ART_LIBDEXFILE_DEX_DEX_FILE_LAYOUT_H_ 128