stack_map.h revision 102cbed1e52b7c5f09458b44903fe97bb3e14d5f
1/* 2 * Copyright (C) 2014 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_STACK_MAP_H_ 18#define ART_RUNTIME_STACK_MAP_H_ 19 20#include "base/bit_vector.h" 21#include "memory_region.h" 22 23namespace art { 24 25/** 26 * Classes in the following file are wrapper on stack map information backed 27 * by a MemoryRegion. As such they read and write to the region, they don't have 28 * their own fields. 29 */ 30 31/** 32 * Inline information for a specific PC. The information is of the form: 33 * [inlining_depth, [method_dex reference]+] 34 */ 35class InlineInfo { 36 public: 37 explicit InlineInfo(MemoryRegion region) : region_(region) {} 38 39 uint8_t GetDepth() const { 40 return region_.Load<uint8_t>(kDepthOffset); 41 } 42 43 void SetDepth(uint8_t depth) { 44 region_.Store<uint8_t>(kDepthOffset, depth); 45 } 46 47 uint32_t GetMethodReferenceIndexAtDepth(uint8_t depth) const { 48 return region_.Load<uint32_t>(kFixedSize + depth * SingleEntrySize()); 49 } 50 51 void SetMethodReferenceIndexAtDepth(uint8_t depth, uint32_t index) { 52 region_.Store<uint32_t>(kFixedSize + depth * SingleEntrySize(), index); 53 } 54 55 static size_t SingleEntrySize() { 56 return sizeof(uint32_t); 57 } 58 59 private: 60 static constexpr int kDepthOffset = 0; 61 static constexpr int kFixedSize = kDepthOffset + sizeof(uint8_t); 62 63 static constexpr uint32_t kNoInlineInfo = -1; 64 65 MemoryRegion region_; 66 67 friend class CodeInfo; 68 friend class StackMap; 69 friend class StackMapStream; 70}; 71 72/** 73 * Information on dex register values for a specific PC. The information is 74 * of the form: 75 * [location_kind, register_value]+. 76 * 77 * The location_kind for a Dex register can either be: 78 * - Constant: register_value holds the constant, 79 * - Stack: register_value holds the stack offset, 80 * - Register: register_value holds the physical register number. 81 * - None: the register has no location yet, meaning it has not been set. 82 */ 83class DexRegisterMap { 84 public: 85 explicit DexRegisterMap(MemoryRegion region) : region_(region) {} 86 87 enum LocationKind { 88 kNone, 89 kInStack, 90 kInRegister, 91 kInFpuRegister, 92 kConstant 93 }; 94 95 LocationKind GetLocationKind(uint16_t register_index) const { 96 return region_.Load<LocationKind>( 97 kFixedSize + register_index * SingleEntrySize()); 98 } 99 100 void SetRegisterInfo(uint16_t register_index, LocationKind kind, int32_t value) { 101 size_t entry = kFixedSize + register_index * SingleEntrySize(); 102 region_.Store<LocationKind>(entry, kind); 103 region_.Store<int32_t>(entry + sizeof(LocationKind), value); 104 } 105 106 int32_t GetValue(uint16_t register_index) const { 107 return region_.Load<int32_t>( 108 kFixedSize + sizeof(LocationKind) + register_index * SingleEntrySize()); 109 } 110 111 static size_t SingleEntrySize() { 112 return sizeof(LocationKind) + sizeof(int32_t); 113 } 114 115 private: 116 static constexpr int kFixedSize = 0; 117 118 MemoryRegion region_; 119 120 friend class CodeInfo; 121 friend class StackMapStream; 122}; 123 124/** 125 * A Stack Map holds compilation information for a specific PC necessary for: 126 * - Mapping it to a dex PC, 127 * - Knowing which stack entries are objects, 128 * - Knowing which registers hold objects, 129 * - Knowing the inlining information, 130 * - Knowing the values of dex registers. 131 * 132 * The information is of the form: 133 * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask, stack_mask]. 134 * 135 * Note that register_mask is fixed size, but stack_mask is variable size, depending on the 136 * stack size of a method. 137 */ 138class StackMap { 139 public: 140 explicit StackMap(MemoryRegion region) : region_(region) {} 141 142 uint32_t GetDexPc() const { 143 return region_.Load<uint32_t>(kDexPcOffset); 144 } 145 146 void SetDexPc(uint32_t dex_pc) { 147 region_.Store<uint32_t>(kDexPcOffset, dex_pc); 148 } 149 150 uint32_t GetNativePcOffset() const { 151 return region_.Load<uint32_t>(kNativePcOffsetOffset); 152 } 153 154 void SetNativePcOffset(uint32_t native_pc_offset) { 155 return region_.Store<uint32_t>(kNativePcOffsetOffset, native_pc_offset); 156 } 157 158 uint32_t GetDexRegisterMapOffset() const { 159 return region_.Load<uint32_t>(kDexRegisterMapOffsetOffset); 160 } 161 162 void SetDexRegisterMapOffset(uint32_t offset) { 163 return region_.Store<uint32_t>(kDexRegisterMapOffsetOffset, offset); 164 } 165 166 uint32_t GetInlineDescriptorOffset() const { 167 return region_.Load<uint32_t>(kInlineDescriptorOffsetOffset); 168 } 169 170 void SetInlineDescriptorOffset(uint32_t offset) { 171 return region_.Store<uint32_t>(kInlineDescriptorOffsetOffset, offset); 172 } 173 174 uint32_t GetRegisterMask() const { 175 return region_.Load<uint32_t>(kRegisterMaskOffset); 176 } 177 178 void SetRegisterMask(uint32_t mask) { 179 region_.Store<uint32_t>(kRegisterMaskOffset, mask); 180 } 181 182 MemoryRegion GetStackMask() const { 183 return region_.Subregion(kStackMaskOffset, StackMaskSize()); 184 } 185 186 void SetStackMask(const BitVector& sp_map) { 187 MemoryRegion region = GetStackMask(); 188 for (size_t i = 0; i < region.size_in_bits(); i++) { 189 region.StoreBit(i, sp_map.IsBitSet(i)); 190 } 191 } 192 193 bool HasInlineInfo() const { 194 return GetInlineDescriptorOffset() != InlineInfo::kNoInlineInfo; 195 } 196 197 bool Equals(const StackMap& other) { 198 return region_.pointer() == other.region_.pointer() 199 && region_.size() == other.region_.size(); 200 } 201 202 private: 203 static constexpr int kDexPcOffset = 0; 204 static constexpr int kNativePcOffsetOffset = kDexPcOffset + sizeof(uint32_t); 205 static constexpr int kDexRegisterMapOffsetOffset = kNativePcOffsetOffset + sizeof(uint32_t); 206 static constexpr int kInlineDescriptorOffsetOffset = 207 kDexRegisterMapOffsetOffset + sizeof(uint32_t); 208 static constexpr int kRegisterMaskOffset = kInlineDescriptorOffsetOffset + sizeof(uint32_t); 209 static constexpr int kFixedSize = kRegisterMaskOffset + sizeof(uint32_t); 210 static constexpr int kStackMaskOffset = kFixedSize; 211 212 size_t StackMaskSize() const { return region_.size() - kFixedSize; } 213 214 MemoryRegion region_; 215 216 friend class CodeInfo; 217 friend class StackMapStream; 218}; 219 220 221/** 222 * Wrapper around all compiler information collected for a method. 223 * The information is of the form: 224 * [overall_size, number_of_stack_maps, stack_mask_size, StackMap+, DexRegisterInfo+, InlineInfo*]. 225 */ 226class CodeInfo { 227 public: 228 explicit CodeInfo(MemoryRegion region) : region_(region) {} 229 230 explicit CodeInfo(const void* data) { 231 uint32_t size = reinterpret_cast<const uint32_t*>(data)[0]; 232 region_ = MemoryRegion(const_cast<void*>(data), size); 233 } 234 235 StackMap GetStackMapAt(size_t i) const { 236 size_t size = StackMapSize(); 237 return StackMap(GetStackMaps().Subregion(i * size, size)); 238 } 239 240 uint32_t GetOverallSize() const { 241 return region_.Load<uint32_t>(kOverallSizeOffset); 242 } 243 244 void SetOverallSize(uint32_t size) { 245 region_.Store<uint32_t>(kOverallSizeOffset, size); 246 } 247 248 uint32_t GetStackMaskSize() const { 249 return region_.Load<uint32_t>(kStackMaskSizeOffset); 250 } 251 252 void SetStackMaskSize(uint32_t size) { 253 region_.Store<uint32_t>(kStackMaskSizeOffset, size); 254 } 255 256 size_t GetNumberOfStackMaps() const { 257 return region_.Load<uint32_t>(kNumberOfStackMapsOffset); 258 } 259 260 void SetNumberOfStackMaps(uint32_t number_of_stack_maps) { 261 region_.Store<uint32_t>(kNumberOfStackMapsOffset, number_of_stack_maps); 262 } 263 264 size_t StackMapSize() const { 265 return StackMap::kFixedSize + GetStackMaskSize(); 266 } 267 268 DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, uint32_t number_of_dex_registers) { 269 uint32_t offset = stack_map.GetDexRegisterMapOffset(); 270 return DexRegisterMap(region_.Subregion(offset, 271 DexRegisterMap::kFixedSize + number_of_dex_registers * DexRegisterMap::SingleEntrySize())); 272 } 273 274 InlineInfo GetInlineInfoOf(StackMap stack_map) { 275 uint32_t offset = stack_map.GetInlineDescriptorOffset(); 276 uint8_t depth = region_.Load<uint8_t>(offset); 277 return InlineInfo(region_.Subregion(offset, 278 InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize())); 279 } 280 281 StackMap GetStackMapForDexPc(uint32_t dex_pc) { 282 for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { 283 StackMap stack_map = GetStackMapAt(i); 284 if (stack_map.GetDexPc() == dex_pc) { 285 return stack_map; 286 } 287 } 288 LOG(FATAL) << "Unreachable"; 289 return StackMap(MemoryRegion()); 290 } 291 292 StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) { 293 // TODO: stack maps are sorted by native pc, we can do a binary search. 294 for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { 295 StackMap stack_map = GetStackMapAt(i); 296 if (stack_map.GetNativePcOffset() == native_pc_offset) { 297 return stack_map; 298 } 299 } 300 LOG(FATAL) << "Unreachable"; 301 return StackMap(MemoryRegion()); 302 } 303 304 private: 305 static constexpr int kOverallSizeOffset = 0; 306 static constexpr int kNumberOfStackMapsOffset = kOverallSizeOffset + sizeof(uint32_t); 307 static constexpr int kStackMaskSizeOffset = kNumberOfStackMapsOffset + sizeof(uint32_t); 308 static constexpr int kFixedSize = kStackMaskSizeOffset + sizeof(uint32_t); 309 310 MemoryRegion GetStackMaps() const { 311 return region_.size() == 0 312 ? MemoryRegion() 313 : region_.Subregion(kFixedSize, StackMapSize() * GetNumberOfStackMaps()); 314 } 315 316 MemoryRegion region_; 317 friend class StackMapStream; 318}; 319 320} // namespace art 321 322#endif // ART_RUNTIME_STACK_MAP_H_ 323