stack_map.h revision fead4e4f397455aa31905b2982d4d861126ab89d
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 34fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray// Size of Dex virtual registers. 35fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffraystatic size_t constexpr kVRegSize = 4; 36fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 3799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 3899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Classes in the following file are wrapper on stack map information backed 3999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * by a MemoryRegion. As such they read and write to the region, they don't have 4099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * their own fields. 4199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 4299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 4399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 4499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Inline information for a specific PC. The information is of the form: 4599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * [inlining_depth, [method_dex reference]+] 4699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 4799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass InlineInfo { 4899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 4999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray explicit InlineInfo(MemoryRegion region) : region_(region) {} 5099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 5199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint8_t GetDepth() const { 52ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain return region_.LoadUnaligned<uint8_t>(kDepthOffset); 5399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 5499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 5599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetDepth(uint8_t depth) { 56ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain region_.StoreUnaligned<uint8_t>(kDepthOffset, depth); 5799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 5899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 5999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t GetMethodReferenceIndexAtDepth(uint8_t depth) const { 60ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain return region_.LoadUnaligned<uint32_t>(kFixedSize + depth * SingleEntrySize()); 6199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 6299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 6399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetMethodReferenceIndexAtDepth(uint8_t depth, uint32_t index) { 64ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain region_.StoreUnaligned<uint32_t>(kFixedSize + depth * SingleEntrySize(), index); 6599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 6699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 6799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static size_t SingleEntrySize() { 6899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return sizeof(uint32_t); 6999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 7099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 7199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private: 72a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Instead of plain types such as "uint8_t", introduce 73a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // typedefs (and document the memory layout of InlineInfo). 7499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kDepthOffset = 0; 7599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kFixedSize = kDepthOffset + sizeof(uint8_t); 7699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 7799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 7899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 793946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class CodeInfo; 803946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class StackMap; 813946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class StackMapStream; 8299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 8399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 84a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// Dex register location container used by DexRegisterMap and StackMapStream. 85a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillainclass DexRegisterLocation { 86a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain public: 87a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain /* 88a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * The location kind used to populate the Dex register information in a 89a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * StackMapStream can either be: 90a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kNone: the register has no location yet, meaning it has not been set; 91a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kConstant: value holds the constant; 92a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kStack: value holds the stack offset; 93a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kRegister: value holds the physical register number; 94a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kFpuRegister: value holds the physical register number. 95a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * 96a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * In addition, DexRegisterMap also uses these values: 97a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kInStackLargeOffset: value holds a "large" stack offset (greater than 98a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * 128 bytes); 99a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kConstantLargeValue: value holds a "large" constant (lower than or 100a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * equal to -16, or greater than 16). 101a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain */ 102a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain enum class Kind : uint8_t { 103a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location kinds, for entries fitting on one byte (3 bits 104a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // for the kind, 5 bits for the value) in a DexRegisterMap. 105a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kNone = 0, // 0b000 106a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kInStack = 1, // 0b001 107a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kInRegister = 2, // 0b010 108a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kInFpuRegister = 3, // 0b011 109a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kConstant = 4, // 0b100 110a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 111a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location kinds, requiring a 5-byte encoding (1 byte for the 112a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // kind, 4 bytes for the value). 113a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 114a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Stack location at a large offset, meaning that the offset value 115a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // divided by the stack frame slot size (4 bytes) cannot fit on a 116a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // 5-bit unsigned integer (i.e., this offset value is greater than 117a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // or equal to 2^5 * 4 = 128 bytes). 118a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kInStackLargeOffset = 5, // 0b101 119a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 120a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large constant, that cannot fit on a 5-bit signed integer (i.e., 121a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // lower than -2^(5-1) = -16, or greater than or equal to 122a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // 2^(5-1) - 1 = 15). 123a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kConstantLargeValue = 6, // 0b110 124a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 125a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kLastLocationKind = kConstantLargeValue 126a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain }; 127a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 128a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static_assert( 129a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain sizeof(Kind) == 1u, 130a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain "art::DexRegisterLocation::Kind has a size different from one byte."); 131a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 132a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static const char* PrettyDescriptor(Kind kind) { 133a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (kind) { 134a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kNone: 135a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "none"; 136a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStack: 137a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "in stack"; 138a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInRegister: 139a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "in register"; 140a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInFpuRegister: 141a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "in fpu register"; 142a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstant: 143a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "as constant"; 144a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStackLargeOffset: 145a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "in stack (large offset)"; 146a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstantLargeValue: 147a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "as constant (large value)"; 148a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain default: 149a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain UNREACHABLE(); 150a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 151a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 152a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 153a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static bool IsShortLocationKind(Kind kind) { 154a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (kind) { 155a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kNone: 156a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStack: 157a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInRegister: 158a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInFpuRegister: 159a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstant: 160a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return true; 161a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 162a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStackLargeOffset: 163a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstantLargeValue: 164a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return false; 165a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 166a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain default: 167a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain UNREACHABLE(); 168a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 169a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 170a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 171a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Convert `kind` to a "surface" kind, i.e. one that doesn't include 172a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // any value with a "large" qualifier. 173a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Introduce another enum type for the surface kind? 174a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static Kind ConvertToSurfaceKind(Kind kind) { 175a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (kind) { 176a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kNone: 177a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStack: 178a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInRegister: 179a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInFpuRegister: 180a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstant: 181a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return kind; 182a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 183a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStackLargeOffset: 184a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return Kind::kInStack; 185a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 186a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstantLargeValue: 187a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return Kind::kConstant; 188a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 189a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain default: 190a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain UNREACHABLE(); 191a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 192a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 193a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 194a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation(Kind kind, int32_t value) 195a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain : kind_(kind), value_(value) {} 196a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 197fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray static DexRegisterLocation None() { 198fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray return DexRegisterLocation(Kind::kNone, 0); 199fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 200fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 201a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the "surface" kind of the location, i.e., the one that doesn't 202a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // include any value with a "large" qualifier. 203a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain Kind GetKind() const { 204a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return ConvertToSurfaceKind(kind_); 205a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 206a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 207a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the value of the location. 208a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t GetValue() const { return value_; } 209a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 210a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the actual kind of the location. 211a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain Kind GetInternalKind() const { return kind_; } 212a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 213a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain private: 214a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain Kind kind_; 215a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value_; 216a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain}; 217a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 21899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 21999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Information on dex register values for a specific PC. The information is 22099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * of the form: 221fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray * [live_bit_mask, DexRegisterLocation+]. 222fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind). 22399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 22499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass DexRegisterMap { 22599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 22699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray explicit DexRegisterMap(MemoryRegion region) : region_(region) {} 22799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 228a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short (compressed) location, fitting on one byte. 229a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain typedef uint8_t ShortLocation; 230a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 231fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray static size_t LiveBitMaskSize(uint16_t number_of_dex_registers) { 232fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte; 233fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 234fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 235fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray void SetLiveBitMask(size_t offset, 236fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray uint16_t number_of_dex_registers, 237fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray const BitVector& live_dex_registers_mask) { 238fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray for (uint16_t i = 0; i < number_of_dex_registers; i++) { 239fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray region_.StoreBit(offset + i, live_dex_registers_mask.IsBitSet(i)); 240fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 241fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 242fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 243a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) { 244a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location); 245a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value = dex_register_location.GetValue(); 246a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 247a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location. Compress the kind and the value as a single byte. 248a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStack) { 249a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Instead of storing stack offsets expressed in bytes for 250a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // short stack locations, store slot offsets. A stack offset 251a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // is a multiple of 4 (kFrameSlotSize). This means that by 252a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // dividing it by 4, we can fit values from the [0, 128) 253a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // interval in a short stack location, and not just values 254a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // from the [0, 32) interval. 255a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(value % kFrameSlotSize, 0); 256a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value /= kFrameSlotSize; 257a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 258a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(IsUint<kValueBits>(value)) << value; 259a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value)); 260a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } else { 261a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location. Write the location on one byte and the value 262a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // on 4 bytes. 263a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(!IsUint<kValueBits>(value)) << value; 264a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) { 265a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Also divide large stack offsets by 4 for the sake of consistency. 266a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(value % kFrameSlotSize, 0); 267a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value /= kFrameSlotSize; 268a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 269a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Data can be unaligned as the written Dex register locations can 270a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // either be 1-byte or 5-byte wide. Use 271a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // art::MemoryRegion::StoreUnaligned instead of 272a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // art::MemoryRegion::Store to prevent unligned word accesses on ARM. 273a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.StoreUnaligned<DexRegisterLocation::Kind>(offset, kind); 274a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.StoreUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind), value); 275a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 276a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 27799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 278fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray bool IsDexRegisterLive(uint16_t dex_register_index) const { 279a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t offset = kFixedSize; 280fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray return region_.LoadBit(offset + dex_register_index); 281fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 282fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 283fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray static constexpr size_t kNoDexRegisterLocationOffset = -1; 284fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 285fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray static size_t GetDexRegisterMapLocationsOffset(uint16_t number_of_dex_registers) { 286fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray return kLiveBitMaskOffset + LiveBitMaskSize(number_of_dex_registers); 287fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 288fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 289fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // Find the offset of the Dex register location number `dex_register_index`. 290fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray size_t FindLocationOffset(uint16_t dex_register_index, uint16_t number_of_dex_registers) const { 291fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray if (!IsDexRegisterLive(dex_register_index)) return kNoDexRegisterLocationOffset; 292fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray size_t offset = GetDexRegisterMapLocationsOffset(number_of_dex_registers); 293a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Skip the first `dex_register_index - 1` entries. 294a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain for (uint16_t i = 0; i < dex_register_index; ++i) { 295fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray if (IsDexRegisterLive(i)) { 296fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // Read the first next byte and inspect its first 3 bits to decide 297fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // whether it is a short or a large location. 298fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset); 299fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray if (DexRegisterLocation::IsShortLocationKind(kind)) { 300fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // Short location. Skip the current byte. 301fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray offset += SingleShortEntrySize(); 302fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } else { 303fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // Large location. Skip the 5 next bytes. 304fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray offset += SingleLargeEntrySize(); 305fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 306a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 307442b46a087c389a91a0b51547ac9205058432364Roland Levillain } 308a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return offset; 309442b46a087c389a91a0b51547ac9205058432364Roland Levillain } 310442b46a087c389a91a0b51547ac9205058432364Roland Levillain 311a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the surface kind. 312fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_index, 313fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray uint16_t number_of_dex_registers) const { 314fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray return IsDexRegisterLive(dex_register_index) 315fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray ? DexRegisterLocation::ConvertToSurfaceKind( 316fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray GetLocationInternalKind(dex_register_index, number_of_dex_registers)) 317fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray : DexRegisterLocation::Kind::kNone; 31899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 31999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 320a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the internal kind. 321fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_index, 322fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray uint16_t number_of_dex_registers) const { 323fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray return IsDexRegisterLive(dex_register_index) 324fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray ? ExtractKindAtOffset(FindLocationOffset(dex_register_index, number_of_dex_registers)) 325fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray : DexRegisterLocation::Kind::kNone; 32699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 32799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 328a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Rename as GetDexRegisterLocation? 329fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DexRegisterLocation GetLocationKindAndValue(uint16_t dex_register_index, 330fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray uint16_t number_of_dex_registers) const { 331fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray if (!IsDexRegisterLive(dex_register_index)) { 332fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray return DexRegisterLocation::None(); 333fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 334fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray size_t offset = FindLocationOffset(dex_register_index, number_of_dex_registers); 335a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Read the first byte and inspect its first 3 bits to get the location. 336a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset); 337a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte); 338a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 339a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location. Extract the value from the remaining 5 bits. 340a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value = ExtractValueFromShortLocation(first_byte); 341a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStack) { 342a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Convert the stack slot (short) offset to a byte offset value. 343a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value *= kFrameSlotSize; 344a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 345a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation(kind, value); 346a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } else { 347a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location. Read the four next bytes to get the value. 348a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value = region_.LoadUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind)); 349a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) { 350a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Convert the stack slot (large) offset to a byte offset value. 351a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value *= kFrameSlotSize; 352a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 353a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation(kind, value); 354a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 35599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 35699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 357fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray int32_t GetStackOffsetInBytes(uint16_t dex_register_index, 358fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray uint16_t number_of_dex_registers) const { 359fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DexRegisterLocation location = 360fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray GetLocationKindAndValue(dex_register_index, number_of_dex_registers); 361a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack); 362a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // GetLocationKindAndValue returns the offset in bytes. 363a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return location.GetValue(); 3647cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz } 3657cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz 366fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray int32_t GetConstant(uint16_t dex_register_index, uint16_t number_of_dex_registers) const { 367fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DexRegisterLocation location = 368fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray GetLocationKindAndValue(dex_register_index, number_of_dex_registers); 369a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant); 370a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return location.GetValue(); 3717cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz } 3727cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz 373fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray int32_t GetMachineRegister(uint16_t dex_register_index, uint16_t number_of_dex_registers) const { 374fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DexRegisterLocation location = 375fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray GetLocationKindAndValue(dex_register_index, number_of_dex_registers); 376a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister 377a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain || location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister) 378a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind()); 379a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return location.GetValue(); 3807cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz } 3817cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz 382a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Compute the compressed kind of `location`. 383a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) { 384a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (location.GetInternalKind()) { 385a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kNone: 386a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(location.GetValue(), 0); 387a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation::Kind::kNone; 388a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 389a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInRegister: 390a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_GE(location.GetValue(), 0); 391a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_LT(location.GetValue(), 1 << DexRegisterMap::kValueBits); 392a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation::Kind::kInRegister; 393a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 394a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInFpuRegister: 395a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_GE(location.GetValue(), 0); 396a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_LT(location.GetValue(), 1 << DexRegisterMap::kValueBits); 397a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation::Kind::kInFpuRegister; 398a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 399a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInStack: 400a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(location.GetValue() % kFrameSlotSize, 0); 401a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return IsUint<DexRegisterMap::kValueBits>(location.GetValue() / kFrameSlotSize) 402a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ? DexRegisterLocation::Kind::kInStack 403a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain : DexRegisterLocation::Kind::kInStackLargeOffset; 404a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 405a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kConstant: 406a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return IsUint<DexRegisterMap::kValueBits>(location.GetValue()) 407a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ? DexRegisterLocation::Kind::kConstant 408a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain : DexRegisterLocation::Kind::kConstantLargeValue; 409a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 410a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain default: 411a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain LOG(FATAL) << "Unexpected location kind" 412a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind()); 413a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain UNREACHABLE(); 414a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 415a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 416a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 417a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Can `location` be turned into a short location? 418a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static bool CanBeEncodedAsShortLocation(const DexRegisterLocation& location) { 419a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (location.GetInternalKind()) { 420a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kNone: 421a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInRegister: 422a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInFpuRegister: 423a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return true; 424a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 425a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInStack: 426a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(location.GetValue() % kFrameSlotSize, 0); 427a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return IsUint<kValueBits>(location.GetValue() / kFrameSlotSize); 428a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 429a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kConstant: 430a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return IsUint<kValueBits>(location.GetValue()); 431a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 432a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain default: 433a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain UNREACHABLE(); 434a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 435a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 436a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 437a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static size_t EntrySize(const DexRegisterLocation& location) { 438a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return CanBeEncodedAsShortLocation(location) 439a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ? DexRegisterMap::SingleShortEntrySize() 440a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain : DexRegisterMap::SingleLargeEntrySize(); 441a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 442a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 443a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static size_t SingleShortEntrySize() { 444a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return sizeof(ShortLocation); 445a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 446a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 447a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static size_t SingleLargeEntrySize() { 448a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return sizeof(DexRegisterLocation::Kind) + sizeof(int32_t); 44999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 45099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 45112baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain size_t Size() const { 45212baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain return region_.size(); 45312baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain } 45412baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain 455fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray static constexpr int kLiveBitMaskOffset = 0; 456fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray static constexpr int kFixedSize = kLiveBitMaskOffset; 45799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 45812baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain private: 459a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Width of the kind "field" in a short location, in bits. 460a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kKindBits = 3; 461a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Width of the value "field" in a short location, in bits. 462a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kValueBits = 5; 463a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 464a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr uint8_t kKindMask = (1 << kKindBits) - 1; 465a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr int32_t kValueMask = (1 << kValueBits) - 1; 466a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kKindOffset = 0; 467a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kValueOffset = kKindBits; 468a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 469a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) { 470a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(IsUint<kKindBits>(static_cast<uint8_t>(kind))) << static_cast<uint8_t>(kind); 471a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK(IsUint<kValueBits>(value)) << value; 472a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return (static_cast<uint8_t>(kind) & kKindMask) << kKindOffset 473a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain | (value & kValueMask) << kValueOffset; 474a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 475a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 476a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) { 477a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain uint8_t kind = (location >> kKindOffset) & kKindMask; 478a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind)); 479fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // We do not encode kNone locations in the stack map. 480fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DCHECK_NE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kNone)); 481a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return static_cast<DexRegisterLocation::Kind>(kind); 482a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 483a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 484a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static int32_t ExtractValueFromShortLocation(ShortLocation location) { 485a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return (location >> kValueOffset) & kValueMask; 486a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 487a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 488a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Extract a location kind from the byte at position `offset`. 489a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind ExtractKindAtOffset(size_t offset) const { 490a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset); 491a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return ExtractKindFromShortLocation(first_byte); 492a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 493a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 49499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 495a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 496a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain friend class CodeInfo; 497a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain friend class StackMapStream; 49899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 49999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 50099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 50199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * A Stack Map holds compilation information for a specific PC necessary for: 50299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Mapping it to a dex PC, 50399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which stack entries are objects, 50499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which registers hold objects, 50599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the inlining information, 50699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the values of dex registers. 50799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * 50899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form: 5093946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask, stack_mask]. 51099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * 51199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Note that register_mask is fixed size, but stack_mask is variable size, depending on the 51299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * stack size of a method. 51399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 51499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass StackMap { 51599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 51699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray explicit StackMap(MemoryRegion region) : region_(region) {} 51799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 51899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t GetDexPc() const { 519ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain return region_.LoadUnaligned<uint32_t>(kDexPcOffset); 52099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 52199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 52299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetDexPc(uint32_t dex_pc) { 523ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain region_.StoreUnaligned<uint32_t>(kDexPcOffset, dex_pc); 52499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 52599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 5263946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray uint32_t GetNativePcOffset() const { 527ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain return region_.LoadUnaligned<uint32_t>(kNativePcOffsetOffset); 52899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 52999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 5303946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray void SetNativePcOffset(uint32_t native_pc_offset) { 531ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain region_.StoreUnaligned<uint32_t>(kNativePcOffsetOffset, native_pc_offset); 53299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 53399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 53499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t GetDexRegisterMapOffset() const { 535ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain return region_.LoadUnaligned<uint32_t>(kDexRegisterMapOffsetOffset); 53699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 53799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 53899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetDexRegisterMapOffset(uint32_t offset) { 539ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain region_.StoreUnaligned<uint32_t>(kDexRegisterMapOffsetOffset, offset); 54099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 54199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 54299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t GetInlineDescriptorOffset() const { 543ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain return region_.LoadUnaligned<uint32_t>(kInlineDescriptorOffsetOffset); 54499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 54599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 54699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetInlineDescriptorOffset(uint32_t offset) { 547ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain region_.StoreUnaligned<uint32_t>(kInlineDescriptorOffsetOffset, offset); 54899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 54999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 55099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t GetRegisterMask() const { 551ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain return region_.LoadUnaligned<uint32_t>(kRegisterMaskOffset); 55299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 55399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 55499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetRegisterMask(uint32_t mask) { 555ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain region_.StoreUnaligned<uint32_t>(kRegisterMaskOffset, mask); 55699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 55799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 55899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion GetStackMask() const { 55999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.Subregion(kStackMaskOffset, StackMaskSize()); 56099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 56199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 56299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetStackMask(const BitVector& sp_map) { 56399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region = GetStackMask(); 56499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray for (size_t i = 0; i < region.size_in_bits(); i++) { 56599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray region.StoreBit(i, sp_map.IsBitSet(i)); 56699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 56799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 56899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 569442b46a087c389a91a0b51547ac9205058432364Roland Levillain bool HasDexRegisterMap() const { 570442b46a087c389a91a0b51547ac9205058432364Roland Levillain return GetDexRegisterMapOffset() != kNoDexRegisterMap; 571442b46a087c389a91a0b51547ac9205058432364Roland Levillain } 572442b46a087c389a91a0b51547ac9205058432364Roland Levillain 57399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray bool HasInlineInfo() const { 574442b46a087c389a91a0b51547ac9205058432364Roland Levillain return GetInlineDescriptorOffset() != kNoInlineInfo; 57599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 57699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 577442b46a087c389a91a0b51547ac9205058432364Roland Levillain bool Equals(const StackMap& other) const { 57899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.pointer() == other.region_.pointer() 57999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray && region_.size() == other.region_.size(); 58099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 58199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 582ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain static size_t ComputeStackMapSize(size_t stack_mask_size) { 583ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain return StackMap::kFixedSize + stack_mask_size; 584376b2bbf7c39108223a7a01568a7b4b04d84eeacNicolas Geoffray } 585376b2bbf7c39108223a7a01568a7b4b04d84eeacNicolas Geoffray 586442b46a087c389a91a0b51547ac9205058432364Roland Levillain // Special (invalid) offset for the DexRegisterMapOffset field meaning 587442b46a087c389a91a0b51547ac9205058432364Roland Levillain // that there is no Dex register map for this stack map. 588442b46a087c389a91a0b51547ac9205058432364Roland Levillain static constexpr uint32_t kNoDexRegisterMap = -1; 589442b46a087c389a91a0b51547ac9205058432364Roland Levillain 590442b46a087c389a91a0b51547ac9205058432364Roland Levillain // Special (invalid) offset for the InlineDescriptorOffset field meaning 591442b46a087c389a91a0b51547ac9205058432364Roland Levillain // that there is no inline info for this stack map. 592442b46a087c389a91a0b51547ac9205058432364Roland Levillain static constexpr uint32_t kNoInlineInfo = -1; 593442b46a087c389a91a0b51547ac9205058432364Roland Levillain 59499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private: 595a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Instead of plain types such as "uint32_t", introduce 596a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // typedefs (and document the memory layout of StackMap). 59799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kDexPcOffset = 0; 5983946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray static constexpr int kNativePcOffsetOffset = kDexPcOffset + sizeof(uint32_t); 5993946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray static constexpr int kDexRegisterMapOffsetOffset = kNativePcOffsetOffset + sizeof(uint32_t); 60099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kInlineDescriptorOffsetOffset = 60199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray kDexRegisterMapOffsetOffset + sizeof(uint32_t); 60299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kRegisterMaskOffset = kInlineDescriptorOffsetOffset + sizeof(uint32_t); 60399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kFixedSize = kRegisterMaskOffset + sizeof(uint32_t); 60499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kStackMaskOffset = kFixedSize; 60599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 60699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray size_t StackMaskSize() const { return region_.size() - kFixedSize; } 60799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 60899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 60999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 6103946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class CodeInfo; 6113946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class StackMapStream; 61299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 61399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 61499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 61599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 61699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Wrapper around all compiler information collected for a method. 61799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form: 6183946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray * [overall_size, number_of_stack_maps, stack_mask_size, StackMap+, DexRegisterInfo+, InlineInfo*]. 61999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 62099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass CodeInfo { 62199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 62299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray explicit CodeInfo(MemoryRegion region) : region_(region) {} 62399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 6243946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray explicit CodeInfo(const void* data) { 6253946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray uint32_t size = reinterpret_cast<const uint32_t*>(data)[0]; 6263946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray region_ = MemoryRegion(const_cast<void*>(data), size); 6273946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 6283946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 6293946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray StackMap GetStackMapAt(size_t i) const { 63099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray size_t size = StackMapSize(); 6313946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray return StackMap(GetStackMaps().Subregion(i * size, size)); 6323946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 6333946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 6343946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray uint32_t GetOverallSize() const { 6353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray return region_.Load<uint32_t>(kOverallSizeOffset); 6363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 6373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 6383946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray void SetOverallSize(uint32_t size) { 6393946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray region_.Store<uint32_t>(kOverallSizeOffset, size); 64099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 64199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 64299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t GetStackMaskSize() const { 64399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.Load<uint32_t>(kStackMaskSizeOffset); 64499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 64599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 64699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetStackMaskSize(uint32_t size) { 64799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray region_.Store<uint32_t>(kStackMaskSizeOffset, size); 64899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 64999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 65099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray size_t GetNumberOfStackMaps() const { 65199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.Load<uint32_t>(kNumberOfStackMapsOffset); 65299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 65399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 65499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray void SetNumberOfStackMaps(uint32_t number_of_stack_maps) { 65599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray region_.Store<uint32_t>(kNumberOfStackMapsOffset, number_of_stack_maps); 65699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 65799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 65829ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain // Get the size of one stack map of this CodeInfo object, in bytes. 65929ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain // All stack maps of a CodeInfo have the same size. 66099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray size_t StackMapSize() const { 661ede7bf8a5cef965974e7c1edcf46a41fbe50a49dRoland Levillain return StackMap::ComputeStackMapSize(GetStackMaskSize()); 66299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 66399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 66429ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain // Get the size all the stack maps of this CodeInfo object, in bytes. 66529ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain size_t StackMapsSize() const { 66629ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain return StackMapSize() * GetNumberOfStackMaps(); 66729ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain } 66829ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain 669a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain uint32_t GetStackMapsOffset() const { 670a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return kFixedSize; 671a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 672a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 673442b46a087c389a91a0b51547ac9205058432364Roland Levillain DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, uint32_t number_of_dex_registers) const { 674442b46a087c389a91a0b51547ac9205058432364Roland Levillain DCHECK(stack_map.HasDexRegisterMap()); 67599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t offset = stack_map.GetDexRegisterMapOffset(); 676a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t size = ComputeDexRegisterMapSize(offset, number_of_dex_registers); 677a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterMap(region_.Subregion(offset, size)); 67899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 67999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 680442b46a087c389a91a0b51547ac9205058432364Roland Levillain InlineInfo GetInlineInfoOf(StackMap stack_map) const { 681442b46a087c389a91a0b51547ac9205058432364Roland Levillain DCHECK(stack_map.HasInlineInfo()); 68299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint32_t offset = stack_map.GetInlineDescriptorOffset(); 68399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray uint8_t depth = region_.Load<uint8_t>(offset); 68499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return InlineInfo(region_.Subregion(offset, 68599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize())); 68699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 68799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 688442b46a087c389a91a0b51547ac9205058432364Roland Levillain StackMap GetStackMapForDexPc(uint32_t dex_pc) const { 68999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { 6903946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray StackMap stack_map = GetStackMapAt(i); 69199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray if (stack_map.GetDexPc() == dex_pc) { 69299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return stack_map; 69399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 69499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 69599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray LOG(FATAL) << "Unreachable"; 6962c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers UNREACHABLE(); 69799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 69899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 699442b46a087c389a91a0b51547ac9205058432364Roland Levillain StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) const { 70099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray // TODO: stack maps are sorted by native pc, we can do a binary search. 70199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { 7023946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray StackMap stack_map = GetStackMapAt(i); 7033946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray if (stack_map.GetNativePcOffset() == native_pc_offset) { 70499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return stack_map; 70599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 70699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 70799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray LOG(FATAL) << "Unreachable"; 7082c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers UNREACHABLE(); 70999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 71099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 71199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private: 712a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Instead of plain types such as "uint32_t", introduce 713a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // typedefs (and document the memory layout of CodeInfo). 7143946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray static constexpr int kOverallSizeOffset = 0; 7153946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray static constexpr int kNumberOfStackMapsOffset = kOverallSizeOffset + sizeof(uint32_t); 71699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kStackMaskSizeOffset = kNumberOfStackMapsOffset + sizeof(uint32_t); 71799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray static constexpr int kFixedSize = kStackMaskSizeOffset + sizeof(uint32_t); 71899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 71999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion GetStackMaps() const { 72099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.size() == 0 72199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray ? MemoryRegion() 72229ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain : region_.Subregion(kFixedSize, StackMapsSize()); 72399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 72499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 725a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Compute the size of a Dex register map starting at offset `origin` in 726a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // `region_` and containing `number_of_dex_registers` locations. 727a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t ComputeDexRegisterMapSize(uint32_t origin, uint32_t number_of_dex_registers) const { 728a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Ideally, we would like to use art::DexRegisterMap::Size or 729a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // art::DexRegisterMap::FindLocationOffset, but the DexRegisterMap is not 730a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // yet built. Try to factor common code. 731fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray size_t offset = 732fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray origin + DexRegisterMap::GetDexRegisterMapLocationsOffset(number_of_dex_registers); 733fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 734fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // Create a temporary DexRegisterMap to be able to call DexRegisterMap.IsDexRegisterLive. 735fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DexRegisterMap only_live_mask(MemoryRegion(region_.Subregion(origin, offset - origin))); 736fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 737a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Skip the first `number_of_dex_registers - 1` entries. 738a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain for (uint16_t i = 0; i < number_of_dex_registers; ++i) { 739fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray if (only_live_mask.IsDexRegisterLive(i)) { 740fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // Read the first next byte and inspect its first 3 bits to decide 741fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // whether it is a short or a large location. 742fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DexRegisterMap::ShortLocation first_byte = 743fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray region_.LoadUnaligned<DexRegisterMap::ShortLocation>(offset); 744fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DexRegisterLocation::Kind kind = 745fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DexRegisterMap::ExtractKindFromShortLocation(first_byte); 746fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray if (DexRegisterLocation::IsShortLocationKind(kind)) { 747fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // Short location. Skip the current byte. 748fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray offset += DexRegisterMap::SingleShortEntrySize(); 749fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } else { 750fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // Large location. Skip the 5 next bytes. 751fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray offset += DexRegisterMap::SingleLargeEntrySize(); 752fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 753a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 754a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 755a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t size = offset - origin; 756a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return size; 757a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 758a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 75999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 7603946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class StackMapStream; 76199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 76299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 76399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray} // namespace art 76499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 76599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#endif // ART_RUNTIME_STACK_MAP_H_ 766