Home | History | Annotate | Download | only in dex
      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