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