stack_map.h revision 29ba1b068fc9f5a8011782c147b1f7732928aac7
199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/* 299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Copyright (C) 2014 The Android Open Source Project 399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * 499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License"); 599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * you may not use this file except in compliance with the License. 699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * You may obtain a copy of the License at 799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * 899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * http://www.apache.org/licenses/LICENSE-2.0 999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * 1099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Unless required by applicable law or agreed to in writing, software 1199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS, 1299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * See the License for the specific language governing permissions and 1499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * limitations under the License. 1599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 1699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 1799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#ifndef ART_RUNTIME_STACK_MAP_H_ 1899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#define ART_RUNTIME_STACK_MAP_H_ 1999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 2099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#include "base/bit_vector.h" 2199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#include "memory_region.h" 22376b2bbf7c39108223a7a01568a7b4b04d84eeacNicolas Geoffray#include "utils.h" 2399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 2499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffraynamespace art { 2599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 26a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// Size of a frame slot, in bytes. This constant is a signed value, 27a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// to please the compiler in arithmetic operations involving int32_t 28a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// (signed) values. 29a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillainstatic ssize_t constexpr kFrameSlotSize = 4; 30a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 319ac0e4d4ed1b45cf8767ef1d339afcdd205bf55aRoland Levillain// Word alignment required on ARM, in bytes. 329ac0e4d4ed1b45cf8767ef1d339afcdd205bf55aRoland Levillainstatic constexpr size_t kWordAlignment = 4; 339ac0e4d4ed1b45cf8767ef1d339afcdd205bf55aRoland Levillain 3499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 3599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Classes in the following file are wrapper on stack map information backed 3699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * by a MemoryRegion. As such they read and write to the region, they don't have 3799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * their own fields. 3899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 3999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 4099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 4199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Inline information for a specific PC. The information is of the form: 4299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * [inlining_depth, [method_dex reference]+] 4399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 4499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass InlineInfo { 4599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 4699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray explicit InlineInfo(MemoryRegion region) : region_(region) {} 4799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 4899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint8_t GetDepth() const { 4999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.Load<uint8_t>(kDepthOffset); 5099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 5199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 5299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetDepth(uint8_t depth) { 5399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray region_.Store<uint8_t>(kDepthOffset, depth); 5499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 5599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 5699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t GetMethodReferenceIndexAtDepth(uint8_t depth) const { 5799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.Load<uint32_t>(kFixedSize + depth * SingleEntrySize()); 5899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 5999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 6099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetMethodReferenceIndexAtDepth(uint8_t depth, uint32_t index) { 6199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray region_.Store<uint32_t>(kFixedSize + depth * SingleEntrySize(), index); 6299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 6399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 6499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static size_t SingleEntrySize() { 6599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return sizeof(uint32_t); 6699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 6799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 6899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private: 69a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Instead of plain types such as "uint8_t", introduce 70a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // typedefs (and document the memory layout of InlineInfo). 7199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kDepthOffset = 0; 7299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kFixedSize = kDepthOffset + sizeof(uint8_t); 7399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 7499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 7599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 763946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class CodeInfo; 773946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class StackMap; 783946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class StackMapStream; 7999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 8099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 81a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// Dex register location container used by DexRegisterMap and StackMapStream. 82a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillainclass DexRegisterLocation { 83a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain public: 84a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain /* 85a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * The location kind used to populate the Dex register information in a 86a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * StackMapStream can either be: 87a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kNone: the register has no location yet, meaning it has not been set; 88a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kConstant: value holds the constant; 89a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kStack: value holds the stack offset; 90a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kRegister: value holds the physical register number; 91a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kFpuRegister: value holds the physical register number. 92a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * 93a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * In addition, DexRegisterMap also uses these values: 94a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kInStackLargeOffset: value holds a "large" stack offset (greater than 95a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * 128 bytes); 96a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kConstantLargeValue: value holds a "large" constant (lower than or 97a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * equal to -16, or greater than 16). 98a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain */ 99a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain enum class Kind : uint8_t { 100a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location kinds, for entries fitting on one byte (3 bits 101a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // for the kind, 5 bits for the value) in a DexRegisterMap. 102a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kNone = 0, // 0b000 103a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kInStack = 1, // 0b001 104a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kInRegister = 2, // 0b010 105a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kInFpuRegister = 3, // 0b011 106a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kConstant = 4, // 0b100 107a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 108a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location kinds, requiring a 5-byte encoding (1 byte for the 109a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // kind, 4 bytes for the value). 110a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 111a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Stack location at a large offset, meaning that the offset value 112a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // divided by the stack frame slot size (4 bytes) cannot fit on a 113a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // 5-bit unsigned integer (i.e., this offset value is greater than 114a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // or equal to 2^5 * 4 = 128 bytes). 115a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kInStackLargeOffset = 5, // 0b101 116a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 117a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large constant, that cannot fit on a 5-bit signed integer (i.e., 118a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // lower than -2^(5-1) = -16, or greater than or equal to 119a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // 2^(5-1) - 1 = 15). 120a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kConstantLargeValue = 6, // 0b110 121a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 122a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kLastLocationKind = kConstantLargeValue 123a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain }; 124a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 125a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static_assert( 126a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain sizeof(Kind) == 1u, 127a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain "art::DexRegisterLocation::Kind has a size different from one byte."); 128a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 129a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static const char* PrettyDescriptor(Kind kind) { 130a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (kind) { 131a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kNone: 132a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "none"; 133a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStack: 134a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "in stack"; 135a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInRegister: 136a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "in register"; 137a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInFpuRegister: 138a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "in fpu register"; 139a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstant: 140a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "as constant"; 141a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStackLargeOffset: 142a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "in stack (large offset)"; 143a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstantLargeValue: 144a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "as constant (large value)"; 145a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain default: 146a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain UNREACHABLE(); 147a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 148a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 149a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 150a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static bool IsShortLocationKind(Kind kind) { 151a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (kind) { 152a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kNone: 153a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStack: 154a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInRegister: 155a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInFpuRegister: 156a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstant: 157a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return true; 158a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 159a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStackLargeOffset: 160a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstantLargeValue: 161a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return false; 162a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 163a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain default: 164a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain UNREACHABLE(); 165a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 166a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 167a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 168a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Convert `kind` to a "surface" kind, i.e. one that doesn't include 169a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // any value with a "large" qualifier. 170a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Introduce another enum type for the surface kind? 171a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static Kind ConvertToSurfaceKind(Kind kind) { 172a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (kind) { 173a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kNone: 174a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStack: 175a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInRegister: 176a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInFpuRegister: 177a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstant: 178a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return kind; 179a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 180a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStackLargeOffset: 181a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return Kind::kInStack; 182a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 183a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstantLargeValue: 184a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return Kind::kConstant; 185a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 186a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain default: 187a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain UNREACHABLE(); 188a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 189a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 190a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 191a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation(Kind kind, int32_t value) 192a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain : kind_(kind), value_(value) {} 193a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 194a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the "surface" kind of the location, i.e., the one that doesn't 195a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // include any value with a "large" qualifier. 196a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain Kind GetKind() const { 197a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return ConvertToSurfaceKind(kind_); 198a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 199a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 200a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the value of the location. 201a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t GetValue() const { return value_; } 202a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 203a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the actual kind of the location. 204a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain Kind GetInternalKind() const { return kind_; } 205a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 206a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain private: 207a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain Kind kind_; 208a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value_; 209a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain}; 210a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 21199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 21299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Information on dex register values for a specific PC. The information is 21399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * of the form: 21499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * [location_kind, register_value]+. 215a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * either on 1 or 5 bytes (see art::DexRegisterLocation::Kind). 21699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 21799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass DexRegisterMap { 21899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 21999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray explicit DexRegisterMap(MemoryRegion region) : region_(region) {} 22099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 221a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short (compressed) location, fitting on one byte. 222a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain typedef uint8_t ShortLocation; 223a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 224a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) { 225a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location); 226a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value = dex_register_location.GetValue(); 227a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 228a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location. Compress the kind and the value as a single byte. 229a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStack) { 230a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Instead of storing stack offsets expressed in bytes for 231a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // short stack locations, store slot offsets. A stack offset 232a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // is a multiple of 4 (kFrameSlotSize). This means that by 233a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // dividing it by 4, we can fit values from the [0, 128) 234a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // interval in a short stack location, and not just values 235a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // from the [0, 32) interval. 236a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(value % kFrameSlotSize, 0); 237a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value /= kFrameSlotSize; 238a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 239a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(IsUint<kValueBits>(value)) << value; 240a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value)); 241a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } else { 242a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location. Write the location on one byte and the value 243a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // on 4 bytes. 244a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(!IsUint<kValueBits>(value)) << value; 245a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) { 246a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Also divide large stack offsets by 4 for the sake of consistency. 247a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(value % kFrameSlotSize, 0); 248a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value /= kFrameSlotSize; 249a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 250a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Data can be unaligned as the written Dex register locations can 251a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // either be 1-byte or 5-byte wide. Use 252a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // art::MemoryRegion::StoreUnaligned instead of 253a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // art::MemoryRegion::Store to prevent unligned word accesses on ARM. 254a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.StoreUnaligned<DexRegisterLocation::Kind>(offset, kind); 255a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.StoreUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind), value); 256a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 257a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 25899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 259a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Find the offset of the Dex register location number `dex_register_index`. 260a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t FindLocationOffset(uint16_t dex_register_index) const { 261a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t offset = kFixedSize; 262a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Skip the first `dex_register_index - 1` entries. 263a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain for (uint16_t i = 0; i < dex_register_index; ++i) { 264a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Read the first next byte and inspect its first 3 bits to decide 265a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // whether it is a short or a large location. 266a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset); 267a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 268a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location. Skip the current byte. 269a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain offset += SingleShortEntrySize(); 270a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } else { 271a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location. Skip the 5 next bytes. 272a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain offset += SingleLargeEntrySize(); 273a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 274442b46a087c389a91a0b51547ac9205058432364Roland Levillain } 275a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return offset; 276442b46a087c389a91a0b51547ac9205058432364Roland Levillain } 277442b46a087c389a91a0b51547ac9205058432364Roland Levillain 278a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the surface kind. 279a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_index) const { 280a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation::ConvertToSurfaceKind(GetLocationInternalKind(dex_register_index)); 28199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 28299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 283a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the internal kind. 284a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_index) const { 285a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t offset = FindLocationOffset(dex_register_index); 286a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return ExtractKindAtOffset(offset); 28799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 28899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 289a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Rename as GetDexRegisterLocation? 290a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation GetLocationKindAndValue(uint16_t dex_register_index) const { 291a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t offset = FindLocationOffset(dex_register_index); 292a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Read the first byte and inspect its first 3 bits to get the location. 293a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset); 294a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte); 295a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 296a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location. Extract the value from the remaining 5 bits. 297a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value = ExtractValueFromShortLocation(first_byte); 298a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStack) { 299a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Convert the stack slot (short) offset to a byte offset value. 300a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value *= kFrameSlotSize; 301a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 302a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation(kind, value); 303a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } else { 304a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location. Read the four next bytes to get the value. 305a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value = region_.LoadUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind)); 306a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) { 307a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Convert the stack slot (large) offset to a byte offset value. 308a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value *= kFrameSlotSize; 309a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 310a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation(kind, value); 311a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 31299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 31399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 314a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t GetStackOffsetInBytes(uint16_t dex_register_index) const { 315a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation location = GetLocationKindAndValue(dex_register_index); 316a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack); 317a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // GetLocationKindAndValue returns the offset in bytes. 318a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return location.GetValue(); 3197cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz } 3207cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz 321a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t GetConstant(uint16_t dex_register_index) const { 322a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation location = GetLocationKindAndValue(dex_register_index); 323a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant); 324a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return location.GetValue(); 3257cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz } 3267cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz 327a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t GetMachineRegister(uint16_t dex_register_index) const { 328a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation location = GetLocationKindAndValue(dex_register_index); 329a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister 330a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain || location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister) 331a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind()); 332a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return location.GetValue(); 3337cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz } 3347cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz 335a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Compute the compressed kind of `location`. 336a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) { 337a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (location.GetInternalKind()) { 338a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kNone: 339a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(location.GetValue(), 0); 340a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation::Kind::kNone; 341a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 342a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInRegister: 343a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_GE(location.GetValue(), 0); 344a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_LT(location.GetValue(), 1 << DexRegisterMap::kValueBits); 345a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation::Kind::kInRegister; 346a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 347a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInFpuRegister: 348a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_GE(location.GetValue(), 0); 349a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_LT(location.GetValue(), 1 << DexRegisterMap::kValueBits); 350a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation::Kind::kInFpuRegister; 351a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 352a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInStack: 353a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(location.GetValue() % kFrameSlotSize, 0); 354a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return IsUint<DexRegisterMap::kValueBits>(location.GetValue() / kFrameSlotSize) 355a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ? DexRegisterLocation::Kind::kInStack 356a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain : DexRegisterLocation::Kind::kInStackLargeOffset; 357a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 358a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kConstant: 359a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return IsUint<DexRegisterMap::kValueBits>(location.GetValue()) 360a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ? DexRegisterLocation::Kind::kConstant 361a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain : DexRegisterLocation::Kind::kConstantLargeValue; 362a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 363a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain default: 364a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain LOG(FATAL) << "Unexpected location kind" 365a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind()); 366a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain UNREACHABLE(); 367a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 368a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 369a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 370a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Can `location` be turned into a short location? 371a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static bool CanBeEncodedAsShortLocation(const DexRegisterLocation& location) { 372a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (location.GetInternalKind()) { 373a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kNone: 374a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInRegister: 375a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInFpuRegister: 376a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return true; 377a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 378a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInStack: 379a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(location.GetValue() % kFrameSlotSize, 0); 380a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return IsUint<kValueBits>(location.GetValue() / kFrameSlotSize); 381a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 382a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kConstant: 383a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return IsUint<kValueBits>(location.GetValue()); 384a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 385a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain default: 386a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain UNREACHABLE(); 387a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 388a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 389a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 390a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static size_t EntrySize(const DexRegisterLocation& location) { 391a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return CanBeEncodedAsShortLocation(location) 392a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ? DexRegisterMap::SingleShortEntrySize() 393a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain : DexRegisterMap::SingleLargeEntrySize(); 394a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 395a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 396a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static size_t SingleShortEntrySize() { 397a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return sizeof(ShortLocation); 398a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 399a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 400a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static size_t SingleLargeEntrySize() { 401a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return sizeof(DexRegisterLocation::Kind) + sizeof(int32_t); 40299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 40399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 40412baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain size_t Size() const { 40512baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain return region_.size(); 40612baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain } 40712baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain 40899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kFixedSize = 0; 40999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 41012baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain private: 411a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Width of the kind "field" in a short location, in bits. 412a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kKindBits = 3; 413a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Width of the value "field" in a short location, in bits. 414a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kValueBits = 5; 415a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 416a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr uint8_t kKindMask = (1 << kKindBits) - 1; 417a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr int32_t kValueMask = (1 << kValueBits) - 1; 418a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kKindOffset = 0; 419a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kValueOffset = kKindBits; 420a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 421a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) { 422a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(IsUint<kKindBits>(static_cast<uint8_t>(kind))) << static_cast<uint8_t>(kind); 423a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(IsUint<kValueBits>(value)) << value; 424a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return (static_cast<uint8_t>(kind) & kKindMask) << kKindOffset 425a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain | (value & kValueMask) << kValueOffset; 426a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 427a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 428a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) { 429a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain uint8_t kind = (location >> kKindOffset) & kKindMask; 430a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind)); 431a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return static_cast<DexRegisterLocation::Kind>(kind); 432a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 433a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 434a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static int32_t ExtractValueFromShortLocation(ShortLocation location) { 435a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return (location >> kValueOffset) & kValueMask; 436a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 437a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 438a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Extract a location kind from the byte at position `offset`. 439a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind ExtractKindAtOffset(size_t offset) const { 440a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset); 441a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return ExtractKindFromShortLocation(first_byte); 442a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 443a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 44499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 445a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 446a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain friend class CodeInfo; 447a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain friend class StackMapStream; 44899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 44999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 45099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 45199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * A Stack Map holds compilation information for a specific PC necessary for: 45299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Mapping it to a dex PC, 45399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which stack entries are objects, 45499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which registers hold objects, 45599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the inlining information, 45699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the values of dex registers. 45799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * 45899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form: 4593946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask, stack_mask]. 46099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * 46199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Note that register_mask is fixed size, but stack_mask is variable size, depending on the 46299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * stack size of a method. 46399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 46499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass StackMap { 46599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 46699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray explicit StackMap(MemoryRegion region) : region_(region) {} 46799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 46899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t GetDexPc() const { 46999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.Load<uint32_t>(kDexPcOffset); 47099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 47199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 47299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetDexPc(uint32_t dex_pc) { 47399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray region_.Store<uint32_t>(kDexPcOffset, dex_pc); 47499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 47599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 4763946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray uint32_t GetNativePcOffset() const { 4773946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray return region_.Load<uint32_t>(kNativePcOffsetOffset); 47899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 47999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 4803946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray void SetNativePcOffset(uint32_t native_pc_offset) { 481a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.Store<uint32_t>(kNativePcOffsetOffset, native_pc_offset); 48299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 48399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 48499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t GetDexRegisterMapOffset() const { 48599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.Load<uint32_t>(kDexRegisterMapOffsetOffset); 48699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 48799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 48899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetDexRegisterMapOffset(uint32_t offset) { 489a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.Store<uint32_t>(kDexRegisterMapOffsetOffset, offset); 49099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 49199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 49299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t GetInlineDescriptorOffset() const { 49399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.Load<uint32_t>(kInlineDescriptorOffsetOffset); 49499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 49599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 49699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetInlineDescriptorOffset(uint32_t offset) { 497a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.Store<uint32_t>(kInlineDescriptorOffsetOffset, offset); 49899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 49999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 50099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t GetRegisterMask() const { 50199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.Load<uint32_t>(kRegisterMaskOffset); 50299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 50399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 50499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetRegisterMask(uint32_t mask) { 50599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray region_.Store<uint32_t>(kRegisterMaskOffset, mask); 50699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 50799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 50899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion GetStackMask() const { 50999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.Subregion(kStackMaskOffset, StackMaskSize()); 51099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 51199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 51299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetStackMask(const BitVector& sp_map) { 51399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region = GetStackMask(); 51499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray for (size_t i = 0; i < region.size_in_bits(); i++) { 51599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray region.StoreBit(i, sp_map.IsBitSet(i)); 51699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 51799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 51899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 519442b46a087c389a91a0b51547ac9205058432364Roland Levillain bool HasDexRegisterMap() const { 520442b46a087c389a91a0b51547ac9205058432364Roland Levillain return GetDexRegisterMapOffset() != kNoDexRegisterMap; 521442b46a087c389a91a0b51547ac9205058432364Roland Levillain } 522442b46a087c389a91a0b51547ac9205058432364Roland Levillain 52399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray bool HasInlineInfo() const { 524442b46a087c389a91a0b51547ac9205058432364Roland Levillain return GetInlineDescriptorOffset() != kNoInlineInfo; 52599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 52699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 527442b46a087c389a91a0b51547ac9205058432364Roland Levillain bool Equals(const StackMap& other) const { 52899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.pointer() == other.region_.pointer() 52999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray && region_.size() == other.region_.size(); 53099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 53199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 5329ac0e4d4ed1b45cf8767ef1d339afcdd205bf55aRoland Levillain static size_t ComputeAlignedStackMapSize(size_t stack_mask_size) { 533376b2bbf7c39108223a7a01568a7b4b04d84eeacNicolas Geoffray // On ARM, the stack maps must be 4-byte aligned. 5349ac0e4d4ed1b45cf8767ef1d339afcdd205bf55aRoland Levillain return RoundUp(StackMap::kFixedSize + stack_mask_size, kWordAlignment); 535376b2bbf7c39108223a7a01568a7b4b04d84eeacNicolas Geoffray } 536376b2bbf7c39108223a7a01568a7b4b04d84eeacNicolas Geoffray 537442b46a087c389a91a0b51547ac9205058432364Roland Levillain // Special (invalid) offset for the DexRegisterMapOffset field meaning 538442b46a087c389a91a0b51547ac9205058432364Roland Levillain // that there is no Dex register map for this stack map. 539442b46a087c389a91a0b51547ac9205058432364Roland Levillain static constexpr uint32_t kNoDexRegisterMap = -1; 540442b46a087c389a91a0b51547ac9205058432364Roland Levillain 541442b46a087c389a91a0b51547ac9205058432364Roland Levillain // Special (invalid) offset for the InlineDescriptorOffset field meaning 542442b46a087c389a91a0b51547ac9205058432364Roland Levillain // that there is no inline info for this stack map. 543442b46a087c389a91a0b51547ac9205058432364Roland Levillain static constexpr uint32_t kNoInlineInfo = -1; 544442b46a087c389a91a0b51547ac9205058432364Roland Levillain 54599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private: 546a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Instead of plain types such as "uint32_t", introduce 547a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // typedefs (and document the memory layout of StackMap). 54899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kDexPcOffset = 0; 5493946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray static constexpr int kNativePcOffsetOffset = kDexPcOffset + sizeof(uint32_t); 5503946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray static constexpr int kDexRegisterMapOffsetOffset = kNativePcOffsetOffset + sizeof(uint32_t); 55199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kInlineDescriptorOffsetOffset = 55299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray kDexRegisterMapOffsetOffset + sizeof(uint32_t); 55399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kRegisterMaskOffset = kInlineDescriptorOffsetOffset + sizeof(uint32_t); 55499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kFixedSize = kRegisterMaskOffset + sizeof(uint32_t); 55599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kStackMaskOffset = kFixedSize; 55699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 55799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray size_t StackMaskSize() const { return region_.size() - kFixedSize; } 55899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 55999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 56099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 5613946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class CodeInfo; 5623946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class StackMapStream; 56399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 56499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 56599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 56699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 56799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Wrapper around all compiler information collected for a method. 56899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form: 5693946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray * [overall_size, number_of_stack_maps, stack_mask_size, StackMap+, DexRegisterInfo+, InlineInfo*]. 57099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 57199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass CodeInfo { 57299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 57399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray explicit CodeInfo(MemoryRegion region) : region_(region) {} 57499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 5753946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray explicit CodeInfo(const void* data) { 5763946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray uint32_t size = reinterpret_cast<const uint32_t*>(data)[0]; 5773946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray region_ = MemoryRegion(const_cast<void*>(data), size); 5783946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 5793946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 5803946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray StackMap GetStackMapAt(size_t i) const { 58199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray size_t size = StackMapSize(); 5823946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray return StackMap(GetStackMaps().Subregion(i * size, size)); 5833946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 5843946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 5853946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray uint32_t GetOverallSize() const { 5863946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray return region_.Load<uint32_t>(kOverallSizeOffset); 5873946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 5883946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 5893946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray void SetOverallSize(uint32_t size) { 5903946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray region_.Store<uint32_t>(kOverallSizeOffset, size); 59199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 59299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 59399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t GetStackMaskSize() const { 59499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.Load<uint32_t>(kStackMaskSizeOffset); 59599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 59699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 59799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetStackMaskSize(uint32_t size) { 59899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray region_.Store<uint32_t>(kStackMaskSizeOffset, size); 59999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 60099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 60199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray size_t GetNumberOfStackMaps() const { 60299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.Load<uint32_t>(kNumberOfStackMapsOffset); 60399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 60499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 60599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetNumberOfStackMaps(uint32_t number_of_stack_maps) { 60699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray region_.Store<uint32_t>(kNumberOfStackMapsOffset, number_of_stack_maps); 60799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 60899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 60929ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain // Get the size of one stack map of this CodeInfo object, in bytes. 61029ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain // All stack maps of a CodeInfo have the same size. 61199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray size_t StackMapSize() const { 612376b2bbf7c39108223a7a01568a7b4b04d84eeacNicolas Geoffray return StackMap::ComputeAlignedStackMapSize(GetStackMaskSize()); 61399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 61499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 61529ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain // Get the size all the stack maps of this CodeInfo object, in bytes. 61629ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain size_t StackMapsSize() const { 61729ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain return StackMapSize() * GetNumberOfStackMaps(); 61829ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain } 61929ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain 620a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain uint32_t GetStackMapsOffset() const { 621a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return kFixedSize; 622a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 623a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 624442b46a087c389a91a0b51547ac9205058432364Roland Levillain DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, uint32_t number_of_dex_registers) const { 625442b46a087c389a91a0b51547ac9205058432364Roland Levillain DCHECK(stack_map.HasDexRegisterMap()); 62699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t offset = stack_map.GetDexRegisterMapOffset(); 627a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t size = ComputeDexRegisterMapSize(offset, number_of_dex_registers); 628a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterMap(region_.Subregion(offset, size)); 62999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 63099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 631442b46a087c389a91a0b51547ac9205058432364Roland Levillain InlineInfo GetInlineInfoOf(StackMap stack_map) const { 632442b46a087c389a91a0b51547ac9205058432364Roland Levillain DCHECK(stack_map.HasInlineInfo()); 63399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t offset = stack_map.GetInlineDescriptorOffset(); 63499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint8_t depth = region_.Load<uint8_t>(offset); 63599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return InlineInfo(region_.Subregion(offset, 63699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize())); 63799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 63899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 639442b46a087c389a91a0b51547ac9205058432364Roland Levillain StackMap GetStackMapForDexPc(uint32_t dex_pc) const { 64099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { 6413946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray StackMap stack_map = GetStackMapAt(i); 64299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray if (stack_map.GetDexPc() == dex_pc) { 64399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return stack_map; 64499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 64599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 64699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray LOG(FATAL) << "Unreachable"; 6472c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers UNREACHABLE(); 64899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 64999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 650442b46a087c389a91a0b51547ac9205058432364Roland Levillain StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) const { 65199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray // TODO: stack maps are sorted by native pc, we can do a binary search. 65299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { 6533946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray StackMap stack_map = GetStackMapAt(i); 6543946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (stack_map.GetNativePcOffset() == native_pc_offset) { 65599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return stack_map; 65699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 65799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 65899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray LOG(FATAL) << "Unreachable"; 6592c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers UNREACHABLE(); 66099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 66199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 66299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private: 663a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Instead of plain types such as "uint32_t", introduce 664a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // typedefs (and document the memory layout of CodeInfo). 6653946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray static constexpr int kOverallSizeOffset = 0; 6663946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray static constexpr int kNumberOfStackMapsOffset = kOverallSizeOffset + sizeof(uint32_t); 66799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kStackMaskSizeOffset = kNumberOfStackMapsOffset + sizeof(uint32_t); 66899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kFixedSize = kStackMaskSizeOffset + sizeof(uint32_t); 66999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 67099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion GetStackMaps() const { 67199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.size() == 0 67299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray ? MemoryRegion() 67329ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain : region_.Subregion(kFixedSize, StackMapsSize()); 67499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 67599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 676a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Compute the size of a Dex register map starting at offset `origin` in 677a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // `region_` and containing `number_of_dex_registers` locations. 678a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t ComputeDexRegisterMapSize(uint32_t origin, uint32_t number_of_dex_registers) const { 679a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Ideally, we would like to use art::DexRegisterMap::Size or 680a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // art::DexRegisterMap::FindLocationOffset, but the DexRegisterMap is not 681a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // yet built. Try to factor common code. 682a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t offset = origin + DexRegisterMap::kFixedSize; 683a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Skip the first `number_of_dex_registers - 1` entries. 684a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain for (uint16_t i = 0; i < number_of_dex_registers; ++i) { 685a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Read the first next byte and inspect its first 3 bits to decide 686a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // whether it is a short or a large location. 687a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterMap::ShortLocation first_byte = 688a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.LoadUnaligned<DexRegisterMap::ShortLocation>(offset); 689a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind kind = 690a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterMap::ExtractKindFromShortLocation(first_byte); 691a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 692a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location. Skip the current byte. 693a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain offset += DexRegisterMap::SingleShortEntrySize(); 694a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } else { 695a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location. Skip the 5 next bytes. 696a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain offset += DexRegisterMap::SingleLargeEntrySize(); 697a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 698a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 699a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t size = offset - origin; 700a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return size; 701a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 702a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 70399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 7043946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class StackMapStream; 70599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 70699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 70799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray} // namespace art 70899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 70999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#endif // ART_RUNTIME_STACK_MAP_H_ 710