Home | History | Annotate | Download | only in utils
      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_UTILS_DEX_CACHE_ARRAYS_LAYOUT_INL_H_
     18 #define ART_RUNTIME_UTILS_DEX_CACHE_ARRAYS_LAYOUT_INL_H_
     19 
     20 #include "dex_cache_arrays_layout.h"
     21 
     22 #include <android-base/logging.h>
     23 
     24 #include "base/bit_utils.h"
     25 #include "dex/primitive.h"
     26 #include "gc_root.h"
     27 #include "mirror/dex_cache.h"
     28 #include "runtime_globals.h"
     29 
     30 namespace art {
     31 
     32 inline DexCacheArraysLayout::DexCacheArraysLayout(PointerSize pointer_size,
     33                                                   const DexFile::Header& header,
     34                                                   uint32_t num_call_sites)
     35     : pointer_size_(pointer_size),
     36       /* types_offset_ is always 0u, so it's constexpr */
     37       methods_offset_(
     38           RoundUp(types_offset_ + TypesSize(header.type_ids_size_), MethodsAlignment())),
     39       strings_offset_(
     40           RoundUp(methods_offset_ + MethodsSize(header.method_ids_size_), StringsAlignment())),
     41       fields_offset_(
     42           RoundUp(strings_offset_ + StringsSize(header.string_ids_size_), FieldsAlignment())),
     43       method_types_offset_(
     44           RoundUp(fields_offset_ + FieldsSize(header.field_ids_size_), MethodTypesAlignment())),
     45     call_sites_offset_(
     46         RoundUp(method_types_offset_ + MethodTypesSize(header.proto_ids_size_),
     47                 MethodTypesAlignment())),
     48       size_(RoundUp(call_sites_offset_ + CallSitesSize(num_call_sites), Alignment())) {
     49 }
     50 
     51 inline DexCacheArraysLayout::DexCacheArraysLayout(PointerSize pointer_size, const DexFile* dex_file)
     52     : DexCacheArraysLayout(pointer_size, dex_file->GetHeader(), dex_file->NumCallSiteIds()) {
     53 }
     54 
     55 inline size_t DexCacheArraysLayout::Alignment() const {
     56   return Alignment(pointer_size_);
     57 }
     58 
     59 inline constexpr size_t DexCacheArraysLayout::Alignment(PointerSize pointer_size) {
     60   // mirror::Type/String/MethodTypeDexCacheType alignment is 8,
     61   // i.e. higher than or equal to the pointer alignment.
     62   static_assert(alignof(mirror::TypeDexCacheType) == 8,
     63                 "Expecting alignof(ClassDexCacheType) == 8");
     64   static_assert(alignof(mirror::StringDexCacheType) == 8,
     65                 "Expecting alignof(StringDexCacheType) == 8");
     66   static_assert(alignof(mirror::MethodTypeDexCacheType) == 8,
     67                 "Expecting alignof(MethodTypeDexCacheType) == 8");
     68   // This is the same as alignof({Field,Method}DexCacheType) for the given pointer size.
     69   return 2u * static_cast<size_t>(pointer_size);
     70 }
     71 
     72 template <typename T>
     73 constexpr PointerSize GcRootAsPointerSize() {
     74   static_assert(sizeof(GcRoot<T>) == 4U, "Unexpected GcRoot size");
     75   return PointerSize::k32;
     76 }
     77 
     78 inline size_t DexCacheArraysLayout::TypeOffset(dex::TypeIndex type_idx) const {
     79   return types_offset_ + ElementOffset(PointerSize::k64,
     80                                        type_idx.index_ % mirror::DexCache::kDexCacheTypeCacheSize);
     81 }
     82 
     83 inline size_t DexCacheArraysLayout::TypesSize(size_t num_elements) const {
     84   size_t cache_size = mirror::DexCache::kDexCacheTypeCacheSize;
     85   if (num_elements < cache_size) {
     86     cache_size = num_elements;
     87   }
     88   return PairArraySize(GcRootAsPointerSize<mirror::Class>(), cache_size);
     89 }
     90 
     91 inline size_t DexCacheArraysLayout::TypesAlignment() const {
     92   return alignof(GcRoot<mirror::Class>);
     93 }
     94 
     95 inline size_t DexCacheArraysLayout::MethodOffset(uint32_t method_idx) const {
     96   return methods_offset_ + ElementOffset(pointer_size_, method_idx);
     97 }
     98 
     99 inline size_t DexCacheArraysLayout::MethodsSize(size_t num_elements) const {
    100   size_t cache_size = mirror::DexCache::kDexCacheMethodCacheSize;
    101   if (num_elements < cache_size) {
    102     cache_size = num_elements;
    103   }
    104   return PairArraySize(pointer_size_, cache_size);
    105 }
    106 
    107 inline size_t DexCacheArraysLayout::MethodsAlignment() const {
    108   return 2u * static_cast<size_t>(pointer_size_);
    109 }
    110 
    111 inline size_t DexCacheArraysLayout::StringOffset(uint32_t string_idx) const {
    112   uint32_t string_hash = string_idx % mirror::DexCache::kDexCacheStringCacheSize;
    113   return strings_offset_ + ElementOffset(PointerSize::k64, string_hash);
    114 }
    115 
    116 inline size_t DexCacheArraysLayout::StringsSize(size_t num_elements) const {
    117   size_t cache_size = mirror::DexCache::kDexCacheStringCacheSize;
    118   if (num_elements < cache_size) {
    119     cache_size = num_elements;
    120   }
    121   return PairArraySize(GcRootAsPointerSize<mirror::String>(), cache_size);
    122 }
    123 
    124 inline size_t DexCacheArraysLayout::StringsAlignment() const {
    125   static_assert(alignof(mirror::StringDexCacheType) == 8,
    126                 "Expecting alignof(StringDexCacheType) == 8");
    127   return alignof(mirror::StringDexCacheType);
    128 }
    129 
    130 inline size_t DexCacheArraysLayout::FieldOffset(uint32_t field_idx) const {
    131   uint32_t field_hash = field_idx % mirror::DexCache::kDexCacheFieldCacheSize;
    132   return fields_offset_ + 2u * static_cast<size_t>(pointer_size_) * field_hash;
    133 }
    134 
    135 inline size_t DexCacheArraysLayout::FieldsSize(size_t num_elements) const {
    136   size_t cache_size = mirror::DexCache::kDexCacheFieldCacheSize;
    137   if (num_elements < cache_size) {
    138     cache_size = num_elements;
    139   }
    140   return PairArraySize(pointer_size_, cache_size);
    141 }
    142 
    143 inline size_t DexCacheArraysLayout::FieldsAlignment() const {
    144   return 2u * static_cast<size_t>(pointer_size_);
    145 }
    146 
    147 inline size_t DexCacheArraysLayout::MethodTypesSize(size_t num_elements) const {
    148   size_t cache_size = mirror::DexCache::kDexCacheMethodTypeCacheSize;
    149   if (num_elements < cache_size) {
    150     cache_size = num_elements;
    151   }
    152 
    153   return ArraySize(PointerSize::k64, cache_size);
    154 }
    155 
    156 inline size_t DexCacheArraysLayout::MethodTypesAlignment() const {
    157   static_assert(alignof(mirror::MethodTypeDexCacheType) == 8,
    158                 "Expecting alignof(MethodTypeDexCacheType) == 8");
    159   return alignof(mirror::MethodTypeDexCacheType);
    160 }
    161 
    162 inline size_t DexCacheArraysLayout::CallSitesSize(size_t num_elements) const {
    163   return ArraySize(GcRootAsPointerSize<mirror::CallSite>(), num_elements);
    164 }
    165 
    166 inline size_t DexCacheArraysLayout::CallSitesAlignment() const {
    167   return alignof(GcRoot<mirror::CallSite>);
    168 }
    169 
    170 inline size_t DexCacheArraysLayout::ElementOffset(PointerSize element_size, uint32_t idx) {
    171   return static_cast<size_t>(element_size) * idx;
    172 }
    173 
    174 inline size_t DexCacheArraysLayout::ArraySize(PointerSize element_size, uint32_t num_elements) {
    175   return static_cast<size_t>(element_size) * num_elements;
    176 }
    177 
    178 inline size_t DexCacheArraysLayout::PairArraySize(PointerSize element_size, uint32_t num_elements) {
    179   return 2u * static_cast<size_t>(element_size) * num_elements;
    180 }
    181 
    182 }  // namespace art
    183 
    184 #endif  // ART_RUNTIME_UTILS_DEX_CACHE_ARRAYS_LAYOUT_INL_H_
    185