stack_map.h revision b331febbab8e916680faba722cc84b66b84218a3
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" 2180afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/bit_utils.h" 2299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#include "memory_region.h" 2399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 2499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffraynamespace art { 2599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 261c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain#define ELEMENT_BYTE_OFFSET_AFTER(PreviousElement) \ 271c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain k ## PreviousElement ## Offset + sizeof(PreviousElement ## Type) 281c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain 291c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain#define ELEMENT_BIT_OFFSET_AFTER(PreviousElement) \ 301c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain k ## PreviousElement ## BitOffset + PreviousElement ## BitSize 311c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain 328f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Markoclass VariableIndentationOutputStream; 338f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko 34a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// Size of a frame slot, in bytes. This constant is a signed value, 35a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// to please the compiler in arithmetic operations involving int32_t 36a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// (signed) values. 37a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainstatic constexpr ssize_t kFrameSlotSize = 4; 38a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 39fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray// Size of Dex virtual registers. 40a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainstatic constexpr size_t kVRegSize = 4; 41fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 42d780c00e554c5b00fc1acf359e4b9c7e761ea0ebRoland Levillain// We encode the number of bytes needed for writing a value on 3 bits 43d780c00e554c5b00fc1acf359e4b9c7e761ea0ebRoland Levillain// (i.e. up to 8 values), for values that we know are maximum 32-bit 44d780c00e554c5b00fc1acf359e4b9c7e761ea0ebRoland Levillain// long. 45d780c00e554c5b00fc1acf359e4b9c7e761ea0ebRoland Levillainstatic constexpr size_t kNumberOfBitForNumberOfBytesForEncoding = 3; 46d780c00e554c5b00fc1acf359e4b9c7e761ea0ebRoland Levillain 47004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffrayclass CodeInfo; 48f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdilclass StackMapEncoding; 49004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray 5099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 5199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Classes in the following file are wrapper on stack map information backed 5299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * by a MemoryRegion. As such they read and write to the region, they don't have 5399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * their own fields. 5499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 5599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 56a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// Dex register location container used by DexRegisterMap and StackMapStream. 57a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillainclass DexRegisterLocation { 58a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain public: 59a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain /* 60a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * The location kind used to populate the Dex register information in a 61a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * StackMapStream can either be: 62d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * - kStack: vreg stored on the stack, value holds the stack offset; 63d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * - kInRegister: vreg stored in low 32 bits of a core physical register, 64d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * value holds the register number; 65d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * - kInRegisterHigh: vreg stored in high 32 bits of a core physical register, 66d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * value holds the register number; 67d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * - kInFpuRegister: vreg stored in low 32 bits of an FPU register, 68d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * value holds the register number; 69d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * - kInFpuRegisterHigh: vreg stored in high 32 bits of an FPU register, 70d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * value holds the register number; 71a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kConstant: value holds the constant; 72a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * 73a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * In addition, DexRegisterMap also uses these values: 74a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kInStackLargeOffset: value holds a "large" stack offset (greater than 75a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * or equal to 128 bytes); 76a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * - kConstantLargeValue: value holds a "large" constant (lower than 0, or 77d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * or greater than or equal to 32); 78d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * - kNone: the register has no location, meaning it has not been set. 79a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain */ 80a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain enum class Kind : uint8_t { 81a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location kinds, for entries fitting on one byte (3 bits 82a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // for the kind, 5 bits for the value) in a DexRegisterMap. 83d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kInStack = 0, // 0b000 84d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kInRegister = 1, // 0b001 85d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kInRegisterHigh = 2, // 0b010 86a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kInFpuRegister = 3, // 0b011 87d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kInFpuRegisterHigh = 4, // 0b100 88d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kConstant = 5, // 0b101 89a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 90a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location kinds, requiring a 5-byte encoding (1 byte for the 91a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // kind, 4 bytes for the value). 92a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 93a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Stack location at a large offset, meaning that the offset value 94a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // divided by the stack frame slot size (4 bytes) cannot fit on a 95a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // 5-bit unsigned integer (i.e., this offset value is greater than 96a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // or equal to 2^5 * 4 = 128 bytes). 97d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kInStackLargeOffset = 6, // 0b110 98a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 99a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large constant, that cannot fit on a 5-bit signed integer (i.e., 100a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // lower than 0, or greater than or equal to 2^5 = 32). 101d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kConstantLargeValue = 7, // 0b111 102d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil 103d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil // Entries with no location are not stored and do not need own marker. 104d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kNone = static_cast<uint8_t>(-1), 105a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 106a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kLastLocationKind = kConstantLargeValue 107a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain }; 108a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 109a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static_assert( 110a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain sizeof(Kind) == 1u, 111a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain "art::DexRegisterLocation::Kind has a size different from one byte."); 112a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 113a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static const char* PrettyDescriptor(Kind kind) { 114a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (kind) { 115a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kNone: 116a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "none"; 117a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStack: 118a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "in stack"; 119a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInRegister: 120a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "in register"; 121d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kInRegisterHigh: 122d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil return "in register high"; 123a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInFpuRegister: 124a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "in fpu register"; 125d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kInFpuRegisterHigh: 126d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil return "in fpu register high"; 127a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstant: 128a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "as constant"; 129a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStackLargeOffset: 130a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "in stack (large offset)"; 131a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstantLargeValue: 132a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return "as constant (large value)"; 133a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 134d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil UNREACHABLE(); 135a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 136a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 137a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static bool IsShortLocationKind(Kind kind) { 138a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (kind) { 139a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStack: 140a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInRegister: 141d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kInRegisterHigh: 142a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInFpuRegister: 143d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kInFpuRegisterHigh: 144a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstant: 145a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return true; 146a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 147a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStackLargeOffset: 148a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstantLargeValue: 149a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return false; 150a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 151d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kNone: 152d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil LOG(FATAL) << "Unexpected location kind " << PrettyDescriptor(kind); 153a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 154d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil UNREACHABLE(); 155a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 156a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 157a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Convert `kind` to a "surface" kind, i.e. one that doesn't include 158a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // any value with a "large" qualifier. 159a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Introduce another enum type for the surface kind? 160a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static Kind ConvertToSurfaceKind(Kind kind) { 161a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (kind) { 162a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStack: 163a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInRegister: 164d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kInRegisterHigh: 165a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInFpuRegister: 166d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kInFpuRegisterHigh: 167a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstant: 168a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return kind; 169a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 170a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStackLargeOffset: 171a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return Kind::kInStack; 172a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 173a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstantLargeValue: 174a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return Kind::kConstant; 175a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 176d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kNone: 177d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil return kind; 178a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 179d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil UNREACHABLE(); 180a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 181a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 182a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Required by art::StackMapStream::LocationCatalogEntriesIndices. 183a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation() : kind_(Kind::kNone), value_(0) {} 184a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 185a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation(Kind kind, int32_t value) : kind_(kind), value_(value) {} 186a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 187fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray static DexRegisterLocation None() { 188fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray return DexRegisterLocation(Kind::kNone, 0); 189fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 190fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 191a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the "surface" kind of the location, i.e., the one that doesn't 192a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // include any value with a "large" qualifier. 193a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain Kind GetKind() const { 194a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return ConvertToSurfaceKind(kind_); 195a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 196a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 197a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the value of the location. 198a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t GetValue() const { return value_; } 199a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 200a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the actual kind of the location. 201a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain Kind GetInternalKind() const { return kind_; } 202a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 2036ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle bool operator==(DexRegisterLocation other) const { 2046ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle return kind_ == other.kind_ && value_ == other.value_; 2056ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle } 2066ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle 2076ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle bool operator!=(DexRegisterLocation other) const { 2086ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle return !(*this == other); 2096ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle } 2106ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle 211a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain private: 212a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain Kind kind_; 213a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value_; 214a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 215a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain friend class DexRegisterLocationHashFn; 216a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain}; 217a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 21899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 219a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * Store information on unique Dex register locations used in a method. 220a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * The information is of the form: 2211c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 2221c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * [DexRegisterLocation+]. 2231c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 224fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind). 22599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 226a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainclass DexRegisterLocationCatalog { 22799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 228a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain explicit DexRegisterLocationCatalog(MemoryRegion region) : region_(region) {} 22999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 230a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short (compressed) location, fitting on one byte. 231a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain typedef uint8_t ShortLocation; 232a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 233a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) { 234a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location); 235a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value = dex_register_location.GetValue(); 236a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 237a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location. Compress the kind and the value as a single byte. 238a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStack) { 239a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Instead of storing stack offsets expressed in bytes for 240a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // short stack locations, store slot offsets. A stack offset 241a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // is a multiple of 4 (kFrameSlotSize). This means that by 242a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // dividing it by 4, we can fit values from the [0, 128) 243a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // interval in a short stack location, and not just values 244a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // from the [0, 32) interval. 245a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(value % kFrameSlotSize, 0); 246a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value /= kFrameSlotSize; 247a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 248a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK(IsShortValue(value)) << value; 249a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value)); 250a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } else { 251a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location. Write the location on one byte and the value 252a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // on 4 bytes. 253a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK(!IsShortValue(value)) << value; 254a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) { 255a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Also divide large stack offsets by 4 for the sake of consistency. 256a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(value % kFrameSlotSize, 0); 257a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value /= kFrameSlotSize; 258a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 259a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Data can be unaligned as the written Dex register locations can 260a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // either be 1-byte or 5-byte wide. Use 261a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // art::MemoryRegion::StoreUnaligned instead of 262a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // art::MemoryRegion::Store to prevent unligned word accesses on ARM. 263a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.StoreUnaligned<DexRegisterLocation::Kind>(offset, kind); 264a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.StoreUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind), value); 265a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 266a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 26799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 268a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Find the offset of the location catalog entry number `location_catalog_entry_index`. 269a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t FindLocationOffset(size_t location_catalog_entry_index) const { 270a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t offset = kFixedSize; 271a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Skip the first `location_catalog_entry_index - 1` entries. 272a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain for (uint16_t i = 0; i < location_catalog_entry_index; ++i) { 273a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Read the first next byte and inspect its first 3 bits to decide 274a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // whether it is a short or a large location. 275a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset); 276a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 277a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Short location. Skip the current byte. 278a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain offset += SingleShortEntrySize(); 279a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } else { 280a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Large location. Skip the 5 next bytes. 281a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain offset += SingleLargeEntrySize(); 282a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 283442b46a087c389a91a0b51547ac9205058432364Roland Levillain } 284a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return offset; 285442b46a087c389a91a0b51547ac9205058432364Roland Levillain } 286442b46a087c389a91a0b51547ac9205058432364Roland Levillain 287a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Get the internal kind of entry at `location_catalog_entry_index`. 288a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation::Kind GetLocationInternalKind(size_t location_catalog_entry_index) const { 289a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (location_catalog_entry_index == kNoLocationEntryIndex) { 290a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return DexRegisterLocation::Kind::kNone; 291a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 292a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return ExtractKindAtOffset(FindLocationOffset(location_catalog_entry_index)); 29399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 29499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 295a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Get the (surface) kind and value of entry at `location_catalog_entry_index`. 296a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation GetDexRegisterLocation(size_t location_catalog_entry_index) const { 297a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (location_catalog_entry_index == kNoLocationEntryIndex) { 298fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray return DexRegisterLocation::None(); 299fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 300a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t offset = FindLocationOffset(location_catalog_entry_index); 301a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Read the first byte and inspect its first 3 bits to get the location. 302a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset); 303a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte); 304a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 305a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location. Extract the value from the remaining 5 bits. 306a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value = ExtractValueFromShortLocation(first_byte); 307a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStack) { 308a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Convert the stack slot (short) offset to a byte offset value. 309a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value *= kFrameSlotSize; 310a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 311a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation(kind, value); 312a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } else { 313a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location. Read the four next bytes to get the value. 314a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value = region_.LoadUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind)); 315a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) { 316a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Convert the stack slot (large) offset to a byte offset value. 317a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value *= kFrameSlotSize; 318a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 319a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation(kind, value); 320a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 32199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 32299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 323a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Compute the compressed kind of `location`. 324a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) { 325d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil DexRegisterLocation::Kind kind = location.GetInternalKind(); 326d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil switch (kind) { 327d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInStack: 328d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil return IsShortStackOffsetValue(location.GetValue()) 329d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil ? DexRegisterLocation::Kind::kInStack 330d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil : DexRegisterLocation::Kind::kInStackLargeOffset; 331a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 332a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInRegister: 333d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInRegisterHigh: 334a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_GE(location.GetValue(), 0); 335a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_LT(location.GetValue(), 1 << kValueBits); 336d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil return kind; 337a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 338a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInFpuRegister: 339d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInFpuRegisterHigh: 340a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_GE(location.GetValue(), 0); 341a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_LT(location.GetValue(), 1 << kValueBits); 342d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil return kind; 343a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 344a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kConstant: 345a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return IsShortConstantValue(location.GetValue()) 346a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ? DexRegisterLocation::Kind::kConstant 347a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain : DexRegisterLocation::Kind::kConstantLargeValue; 348a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 349d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kConstantLargeValue: 350d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInStackLargeOffset: 351d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kNone: 352d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil LOG(FATAL) << "Unexpected location kind " << DexRegisterLocation::PrettyDescriptor(kind); 353a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 354d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil UNREACHABLE(); 355a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 356a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 357a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Can `location` be turned into a short location? 358a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static bool CanBeEncodedAsShortLocation(const DexRegisterLocation& location) { 359d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil DexRegisterLocation::Kind kind = location.GetInternalKind(); 360d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil switch (kind) { 361d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInStack: 362d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil return IsShortStackOffsetValue(location.GetValue()); 363d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil 364a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInRegister: 365d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInRegisterHigh: 366a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInFpuRegister: 367d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInFpuRegisterHigh: 368a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return true; 369a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 370a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kConstant: 371a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return IsShortConstantValue(location.GetValue()); 372a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 373d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kConstantLargeValue: 374d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInStackLargeOffset: 375d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kNone: 376d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil LOG(FATAL) << "Unexpected location kind " << DexRegisterLocation::PrettyDescriptor(kind); 377a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 378d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil UNREACHABLE(); 379a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 380a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 381a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static size_t EntrySize(const DexRegisterLocation& location) { 382a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return CanBeEncodedAsShortLocation(location) ? SingleShortEntrySize() : SingleLargeEntrySize(); 383a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 384a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 385a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static size_t SingleShortEntrySize() { 386a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return sizeof(ShortLocation); 387a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 388a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 389a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static size_t SingleLargeEntrySize() { 390a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return sizeof(DexRegisterLocation::Kind) + sizeof(int32_t); 39199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 39299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 39312baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain size_t Size() const { 39412baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain return region_.size(); 39512baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain } 39612baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain 3978f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko void Dump(VariableIndentationOutputStream* vios, const CodeInfo& code_info); 3980396ed7d3ad30778cb4af19e7086bea0deace9b9Roland Levillain 399a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Special (invalid) Dex register location catalog entry index meaning 400a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // that there is no location for a given Dex register (i.e., it is 401a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // mapped to a DexRegisterLocation::Kind::kNone location). 402a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static constexpr size_t kNoLocationEntryIndex = -1; 40399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 40412baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain private: 405a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static constexpr int kFixedSize = 0; 406a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 407a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Width of the kind "field" in a short location, in bits. 408a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kKindBits = 3; 409a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Width of the value "field" in a short location, in bits. 410a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kValueBits = 5; 411a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 412a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr uint8_t kKindMask = (1 << kKindBits) - 1; 413a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr int32_t kValueMask = (1 << kValueBits) - 1; 414a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kKindOffset = 0; 415a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kValueOffset = kKindBits; 416a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 417a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static bool IsShortStackOffsetValue(int32_t value) { 418a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_EQ(value % kFrameSlotSize, 0); 419a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return IsShortValue(value / kFrameSlotSize); 420a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 421a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 422a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static bool IsShortConstantValue(int32_t value) { 423a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return IsShortValue(value); 424a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 425a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 426a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static bool IsShortValue(int32_t value) { 427a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return IsUint<kValueBits>(value); 428a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 429a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 430a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) { 431a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint8_t kind_integer_value = static_cast<uint8_t>(kind); 432a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK(IsUint<kKindBits>(kind_integer_value)) << kind_integer_value; 433a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK(IsShortValue(value)) << value; 434a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return (kind_integer_value & kKindMask) << kKindOffset 435a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain | (value & kValueMask) << kValueOffset; 436a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 437a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 438a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) { 439a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain uint8_t kind = (location >> kKindOffset) & kKindMask; 440a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind)); 441fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // We do not encode kNone locations in the stack map. 442fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DCHECK_NE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kNone)); 443a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return static_cast<DexRegisterLocation::Kind>(kind); 444a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 445a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 446a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static int32_t ExtractValueFromShortLocation(ShortLocation location) { 447a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return (location >> kValueOffset) & kValueMask; 448a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 449a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 450a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Extract a location kind from the byte at position `offset`. 451a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind ExtractKindAtOffset(size_t offset) const { 452a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset); 453a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return ExtractKindFromShortLocation(first_byte); 454a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 455a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 45699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 457a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 458a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain friend class CodeInfo; 459a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain friend class StackMapStream; 46099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 46199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 462a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain/* Information on Dex register locations for a specific PC, mapping a 463a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * stack map's Dex register to a location entry in a DexRegisterLocationCatalog. 464a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * The information is of the form: 4651c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 4661c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * [live_bit_mask, entries*] 4671c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 468a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * where entries are concatenated unsigned integer values encoded on a number 469a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * of bits (fixed per DexRegisterMap instances of a CodeInfo object) depending 470a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * on the number of entries in the Dex register location catalog 471a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * (see DexRegisterMap::SingleEntrySizeInBits). The map is 1-byte aligned. 472a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain */ 473a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainclass DexRegisterMap { 474a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain public: 475a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain explicit DexRegisterMap(MemoryRegion region) : region_(region) {} 476012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray DexRegisterMap() {} 477012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray 478012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray bool IsValid() const { return region_.pointer() != nullptr; } 479a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 480a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Get the surface kind of Dex register `dex_register_number`. 481a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number, 482a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 483f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const CodeInfo& code_info, 484f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const StackMapEncoding& enc) const { 485a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return DexRegisterLocation::ConvertToSurfaceKind( 486f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info, enc)); 487a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 488a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 489a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Get the internal kind of Dex register `dex_register_number`. 490a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number, 491a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 492f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const CodeInfo& code_info, 493f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const StackMapEncoding& enc) const; 494a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 495a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Get the Dex register location `dex_register_number`. 496a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number, 497a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 498f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const CodeInfo& code_info, 499f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const StackMapEncoding& enc) const; 500a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 501a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain int32_t GetStackOffsetInBytes(uint16_t dex_register_number, 502a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 503f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const CodeInfo& code_info, 504f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const StackMapEncoding& enc) const { 505a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation location = 506f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc); 507a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack); 508a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // GetDexRegisterLocation returns the offset in bytes. 509a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return location.GetValue(); 510a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 511a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 512a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain int32_t GetConstant(uint16_t dex_register_number, 513a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 514f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const CodeInfo& code_info, 515f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const StackMapEncoding& enc) const { 516a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation location = 517f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc); 518b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant) 519b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray << DexRegisterLocation::PrettyDescriptor(location.GetKind()); 520a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return location.GetValue(); 521a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 522a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 523a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain int32_t GetMachineRegister(uint16_t dex_register_number, 524a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 525f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const CodeInfo& code_info, 526f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const StackMapEncoding& enc) const { 527a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation location = 528f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc); 529d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister || 530d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil location.GetInternalKind() == DexRegisterLocation::Kind::kInRegisterHigh || 531d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister || 532d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegisterHigh) 533a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind()); 534a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return location.GetValue(); 535a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 536a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 537a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Get the index of the entry in the Dex register location catalog 538a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // corresponding to `dex_register_number`. 539a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t GetLocationCatalogEntryIndex(uint16_t dex_register_number, 540a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 541a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t number_of_location_catalog_entries) const { 542a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (!IsDexRegisterLive(dex_register_number)) { 543a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return DexRegisterLocationCatalog::kNoLocationEntryIndex; 544a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 545a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 546a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (number_of_location_catalog_entries == 1) { 547a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // We do not allocate space for location maps in the case of a 548a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // single-entry location catalog, as it is useless. The only valid 549a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // entry index is 0; 550a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return 0; 551a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 552a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 553a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // The bit offset of the beginning of the map locations. 554a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t map_locations_offset_in_bits = 555a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte; 556a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t index_in_dex_register_map = GetIndexInDexRegisterMap(dex_register_number); 557a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers)); 558a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // The bit size of an entry. 559a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries); 560a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // The bit offset where `index_in_dex_register_map` is located. 561a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t entry_offset_in_bits = 562a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits; 563a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t location_catalog_entry_index = 564a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain region_.LoadBits(entry_offset_in_bits, map_entry_size_in_bits); 565a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries); 566a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return location_catalog_entry_index; 567a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 568a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 569a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Map entry at `index_in_dex_register_map` to `location_catalog_entry_index`. 570a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain void SetLocationCatalogEntryIndex(size_t index_in_dex_register_map, 571a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t location_catalog_entry_index, 572a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 573a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t number_of_location_catalog_entries) { 574a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers)); 575a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries); 576a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 577a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (number_of_location_catalog_entries == 1) { 578a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // We do not allocate space for location maps in the case of a 579a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // single-entry location catalog, as it is useless. 580a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return; 581a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 582a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 583a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // The bit offset of the beginning of the map locations. 584a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t map_locations_offset_in_bits = 585a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte; 586a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // The bit size of an entry. 587a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries); 588a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // The bit offset where `index_in_dex_register_map` is located. 589a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t entry_offset_in_bits = 590a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits; 591a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain region_.StoreBits(entry_offset_in_bits, location_catalog_entry_index, map_entry_size_in_bits); 592a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 593a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 594a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain void SetLiveBitMask(uint16_t number_of_dex_registers, 595a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain const BitVector& live_dex_registers_mask) { 596a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte; 597a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain for (uint16_t i = 0; i < number_of_dex_registers; ++i) { 598a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain region_.StoreBit(live_bit_mask_offset_in_bits + i, live_dex_registers_mask.IsBitSet(i)); 599a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 600a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 601a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 602a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain bool IsDexRegisterLive(uint16_t dex_register_number) const { 603a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte; 604a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return region_.LoadBit(live_bit_mask_offset_in_bits + dex_register_number); 605a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 606a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 607a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t GetNumberOfLiveDexRegisters(uint16_t number_of_dex_registers) const { 608a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t number_of_live_dex_registers = 0; 609a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain for (size_t i = 0; i < number_of_dex_registers; ++i) { 610a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (IsDexRegisterLive(i)) { 611a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain ++number_of_live_dex_registers; 612a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 613a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 614a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return number_of_live_dex_registers; 615a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 616a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 617a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static size_t GetLiveBitMaskOffset() { 618a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return kFixedSize; 619a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 620a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 621a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Compute the size of the live register bit mask (in bytes), for a 622a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // method having `number_of_dex_registers` Dex registers. 623a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static size_t GetLiveBitMaskSize(uint16_t number_of_dex_registers) { 624a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte; 625a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 626a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 627a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static size_t GetLocationMappingDataOffset(uint16_t number_of_dex_registers) { 628a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return GetLiveBitMaskOffset() + GetLiveBitMaskSize(number_of_dex_registers); 629a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 630a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 631a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t GetLocationMappingDataSize(uint16_t number_of_dex_registers, 632a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t number_of_location_catalog_entries) const { 633a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t location_mapping_data_size_in_bits = 634a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain GetNumberOfLiveDexRegisters(number_of_dex_registers) 635a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * SingleEntrySizeInBits(number_of_location_catalog_entries); 636a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte; 637a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 638a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 639a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Return the size of a map entry in bits. Note that if 640a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // `number_of_location_catalog_entries` equals 1, this function returns 0, 641a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // which is fine, as there is no need to allocate a map for a 642a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // single-entry location catalog; the only valid location catalog entry index 643a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // for a live register in this case is 0 and there is no need to 644a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // store it. 645a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static size_t SingleEntrySizeInBits(size_t number_of_location_catalog_entries) { 646a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Handle the case of 0, as we cannot pass 0 to art::WhichPowerOf2. 647a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return number_of_location_catalog_entries == 0 648a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain ? 0u 649a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain : WhichPowerOf2(RoundUpToPowerOfTwo(number_of_location_catalog_entries)); 650a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 651a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 652a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Return the size of the DexRegisterMap object, in bytes. 653a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t Size() const { 654a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return region_.size(); 655a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 656a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 6578f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko void Dump(VariableIndentationOutputStream* vios, 6588f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko const CodeInfo& code_info, uint16_t number_of_dex_registers) const; 659b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 660a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain private: 661a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Return the index in the Dex register map corresponding to the Dex 662a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // register number `dex_register_number`. 663a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t GetIndexInDexRegisterMap(uint16_t dex_register_number) const { 664a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (!IsDexRegisterLive(dex_register_number)) { 665a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return kInvalidIndexInDexRegisterMap; 666a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 667a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return GetNumberOfLiveDexRegisters(dex_register_number); 668a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 669a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 670a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Special (invalid) Dex register map entry index meaning that there 671a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // is no index in the map for a given Dex register (i.e., it must 672a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // have been mapped to a DexRegisterLocation::Kind::kNone location). 673a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static constexpr size_t kInvalidIndexInDexRegisterMap = -1; 674a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 675a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static constexpr int kFixedSize = 0; 676a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 677a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain MemoryRegion region_; 678a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 679a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain friend class CodeInfo; 680a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain friend class StackMapStream; 681a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain}; 682a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 683f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdilclass StackMapEncoding { 684f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil public: 685f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMapEncoding() {} 686f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 687f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMapEncoding(size_t stack_mask_size, 688f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t bytes_for_inline_info, 689f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t bytes_for_dex_register_map, 690f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t bytes_for_dex_pc, 691f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t bytes_for_native_pc, 692f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t bytes_for_register_mask) 693f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil : bytes_for_stack_mask_(stack_mask_size), 694f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil bytes_for_inline_info_(bytes_for_inline_info), 695f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil bytes_for_dex_register_map_(bytes_for_dex_register_map), 696f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil bytes_for_dex_pc_(bytes_for_dex_pc), 697f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil bytes_for_native_pc_(bytes_for_native_pc), 698f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil bytes_for_register_mask_(bytes_for_register_mask) {} 699f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 700f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil static StackMapEncoding CreateFromSizes(size_t stack_mask_size, 701f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t inline_info_size, 702f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t dex_register_map_size, 703f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t dex_pc_max, 704f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t native_pc_max, 705f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t register_mask_max) { 706f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return StackMapEncoding( 707f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil stack_mask_size, 708f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil // + 1 to also encode kNoInlineInfo: if an inline info offset 709f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil // is at 0xFF, we want to overflow to a larger encoding, because it will 710f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil // conflict with kNoInlineInfo. 711f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil // The offset is relative to the dex register map. TODO: Change this. 712f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil inline_info_size == 0 713f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil ? 0 714f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil : EncodingSizeInBytes(dex_register_map_size + inline_info_size + 1), 715f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil // + 1 to also encode kNoDexRegisterMap: if a dex register map offset 716f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil // is at 0xFF, we want to overflow to a larger encoding, because it will 717f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil // conflict with kNoDexRegisterMap. 718f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil EncodingSizeInBytes(dex_register_map_size + 1), 719f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil EncodingSizeInBytes(dex_pc_max), 720f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil EncodingSizeInBytes(native_pc_max), 721f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil EncodingSizeInBytes(register_mask_max)); 722f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 723f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 724f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil // Get the size of one stack map of this CodeInfo object, in bytes. 725f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil // All stack maps of a CodeInfo have the same size. 726f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t ComputeStackMapSize() const { 727f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return bytes_for_register_mask_ 728f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil + bytes_for_stack_mask_ 729f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil + bytes_for_inline_info_ 730f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil + bytes_for_dex_register_map_ 731f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil + bytes_for_dex_pc_ 732f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil + bytes_for_native_pc_; 733f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 734f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 735f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil bool HasInlineInfo() const { return bytes_for_inline_info_ > 0; } 736f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 737f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t NumberOfBytesForStackMask() const { return bytes_for_stack_mask_; } 738f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t NumberOfBytesForInlineInfo() const { return bytes_for_inline_info_; } 739f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t NumberOfBytesForDexRegisterMap() const { return bytes_for_dex_register_map_; } 740f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t NumberOfBytesForDexPc() const { return bytes_for_dex_pc_; } 741f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t NumberOfBytesForNativePc() const { return bytes_for_native_pc_; } 742f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t NumberOfBytesForRegisterMask() const { return bytes_for_register_mask_; } 743f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 744f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t ComputeStackMapRegisterMaskOffset() const { 745f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return kRegisterMaskOffset; 746f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 747f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 748f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t ComputeStackMapStackMaskOffset() const { 749f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return ComputeStackMapRegisterMaskOffset() + bytes_for_register_mask_; 750f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 751f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 752f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t ComputeStackMapDexPcOffset() const { 753f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return ComputeStackMapStackMaskOffset() + bytes_for_stack_mask_; 754f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 755f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 756f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t ComputeStackMapNativePcOffset() const { 757f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return ComputeStackMapDexPcOffset() + bytes_for_dex_pc_; 758f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 759f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 760f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t ComputeStackMapDexRegisterMapOffset() const { 761f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return ComputeStackMapNativePcOffset() + bytes_for_native_pc_; 762f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 763f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 764f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t ComputeStackMapInlineInfoOffset() const { 765f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return ComputeStackMapDexRegisterMapOffset() + bytes_for_dex_register_map_; 766f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 767f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 768f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil private: 769f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil static size_t EncodingSizeInBytes(size_t max_element) { 770f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil DCHECK(IsUint<32>(max_element)); 771f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return (max_element == 0) ? 0 772f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil : IsUint<8>(max_element) ? 1 773f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil : IsUint<16>(max_element) ? 2 774f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil : IsUint<24>(max_element) ? 3 775f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil : 4; 776f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 777f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 778f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil static constexpr int kRegisterMaskOffset = 0; 779f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 780f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t bytes_for_stack_mask_; 781f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t bytes_for_inline_info_; 782f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t bytes_for_dex_register_map_; 783f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t bytes_for_dex_pc_; 784f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t bytes_for_native_pc_; 785f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t bytes_for_register_mask_; 786f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil}; 787f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 78899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 78999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * A Stack Map holds compilation information for a specific PC necessary for: 79099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Mapping it to a dex PC, 79199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which stack entries are objects, 79299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which registers hold objects, 79399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the inlining information, 79499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the values of dex registers. 79599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * 79699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form: 7971c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 7981c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask, 7991c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * stack_mask]. 80099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 80199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass StackMap { 80299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 803e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray StackMap() {} 804f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil explicit StackMap(MemoryRegion region) : region_(region) {} 805e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray 806e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray bool IsValid() const { return region_.pointer() != nullptr; } 80799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 808f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil uint32_t GetDexPc(const StackMapEncoding& encoding) const { 809f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return LoadAt(encoding.NumberOfBytesForDexPc(), encoding.ComputeStackMapDexPcOffset()); 810f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 81199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 812f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil void SetDexPc(const StackMapEncoding& encoding, uint32_t dex_pc) { 813f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StoreAt(encoding.NumberOfBytesForDexPc(), encoding.ComputeStackMapDexPcOffset(), dex_pc); 814f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 81599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 816f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil uint32_t GetNativePcOffset(const StackMapEncoding& encoding) const { 817f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return LoadAt(encoding.NumberOfBytesForNativePc(), encoding.ComputeStackMapNativePcOffset()); 818f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 81999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 820f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil void SetNativePcOffset(const StackMapEncoding& encoding, uint32_t native_pc_offset) { 821f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StoreAt(encoding.NumberOfBytesForNativePc(), 822f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil encoding.ComputeStackMapNativePcOffset(), 823f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil native_pc_offset); 824f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 82599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 826f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil uint32_t GetDexRegisterMapOffset(const StackMapEncoding& encoding) const { 827f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return LoadAt(encoding.NumberOfBytesForDexRegisterMap(), 828f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil encoding.ComputeStackMapDexRegisterMapOffset(), 829f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil /* check_max */ true); 830f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 83199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 832f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil void SetDexRegisterMapOffset(const StackMapEncoding& encoding, uint32_t offset) { 833f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StoreAt(encoding.NumberOfBytesForDexRegisterMap(), 834f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil encoding.ComputeStackMapDexRegisterMapOffset(), 835f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil offset); 836f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 83799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 838f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil uint32_t GetInlineDescriptorOffset(const StackMapEncoding& encoding) const { 839f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil if (!encoding.HasInlineInfo()) return kNoInlineInfo; 840f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return LoadAt(encoding.NumberOfBytesForInlineInfo(), 841f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil encoding.ComputeStackMapInlineInfoOffset(), 842f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil /* check_max */ true); 843f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 84499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 845f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil void SetInlineDescriptorOffset(const StackMapEncoding& encoding, uint32_t offset) { 846f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil DCHECK(encoding.HasInlineInfo()); 847f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StoreAt(encoding.NumberOfBytesForInlineInfo(), 848f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil encoding.ComputeStackMapInlineInfoOffset(), 849f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil offset); 850f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 85199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 852f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil uint32_t GetRegisterMask(const StackMapEncoding& encoding) const { 853f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return LoadAt(encoding.NumberOfBytesForRegisterMask(), 854f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil encoding.ComputeStackMapRegisterMaskOffset()); 855f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 85699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 857f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil void SetRegisterMask(const StackMapEncoding& encoding, uint32_t mask) { 858f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StoreAt(encoding.NumberOfBytesForRegisterMask(), 859f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil encoding.ComputeStackMapRegisterMaskOffset(), 860f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil mask); 861f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 86299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 863f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil MemoryRegion GetStackMask(const StackMapEncoding& encoding) const { 864f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return region_.Subregion(encoding.ComputeStackMapStackMaskOffset(), 865f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil encoding.NumberOfBytesForStackMask()); 866f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 86799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 868f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil void SetStackMask(const StackMapEncoding& encoding, const BitVector& sp_map) { 869f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil MemoryRegion region = GetStackMask(encoding); 870f10a25f961eb8029c01c84fe8eabd405055cca37David Brazdil sp_map.CopyTo(region.start(), region.size()); 87199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 87299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 873f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil bool HasDexRegisterMap(const StackMapEncoding& encoding) const { 874f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return GetDexRegisterMapOffset(encoding) != kNoDexRegisterMap; 875442b46a087c389a91a0b51547ac9205058432364Roland Levillain } 876442b46a087c389a91a0b51547ac9205058432364Roland Levillain 877f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil bool HasInlineInfo(const StackMapEncoding& encoding) const { 878f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return GetInlineDescriptorOffset(encoding) != kNoInlineInfo; 87999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 88099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 881442b46a087c389a91a0b51547ac9205058432364Roland Levillain bool Equals(const StackMap& other) const { 88299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.pointer() == other.region_.pointer() 88399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray && region_.size() == other.region_.size(); 88499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 88599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 8868f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko void Dump(VariableIndentationOutputStream* vios, 887f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain const CodeInfo& code_info, 888f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const StackMapEncoding& encoding, 889f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain uint32_t code_offset, 890f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain uint16_t number_of_dex_registers, 891f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain const std::string& header_suffix = "") const; 892f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain 893442b46a087c389a91a0b51547ac9205058432364Roland Levillain // Special (invalid) offset for the DexRegisterMapOffset field meaning 894442b46a087c389a91a0b51547ac9205058432364Roland Levillain // that there is no Dex register map for this stack map. 895442b46a087c389a91a0b51547ac9205058432364Roland Levillain static constexpr uint32_t kNoDexRegisterMap = -1; 896442b46a087c389a91a0b51547ac9205058432364Roland Levillain 897442b46a087c389a91a0b51547ac9205058432364Roland Levillain // Special (invalid) offset for the InlineDescriptorOffset field meaning 898442b46a087c389a91a0b51547ac9205058432364Roland Levillain // that there is no inline info for this stack map. 899442b46a087c389a91a0b51547ac9205058432364Roland Levillain static constexpr uint32_t kNoInlineInfo = -1; 900442b46a087c389a91a0b51547ac9205058432364Roland Levillain 90199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private: 902896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray static constexpr int kFixedSize = 0; 90399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 904f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil // Loads `number_of_bytes` at the given `offset` and assemble a uint32_t. If `check_max` is true, 905f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil // this method converts a maximum value of size `number_of_bytes` into a uint32_t 0xFFFFFFFF. 906f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil uint32_t LoadAt(size_t number_of_bytes, size_t offset, bool check_max = false) const; 907f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil void StoreAt(size_t number_of_bytes, size_t offset, uint32_t value) const; 908f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 90999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 91099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 9113946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class StackMapStream; 91299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 91399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 914b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray/** 915b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray * Inline information for a specific PC. The information is of the form: 9161c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 9171c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * [inlining_depth, entry+] 9181c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 9191c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * where `entry` is of the form: 9201c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 9211c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * [dex_pc, method_index, dex_register_map_offset]. 922b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray */ 923b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffrayclass InlineInfo { 924b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray public: 9251c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain // Memory layout: fixed contents. 9261c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain typedef uint8_t DepthType; 9271c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain // Memory layout: single entry contents. 9281c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain typedef uint32_t MethodIndexType; 9291c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain typedef uint32_t DexPcType; 9301c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain typedef uint8_t InvokeTypeType; 9311c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain typedef uint32_t DexRegisterMapType; 9321c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain 933b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray explicit InlineInfo(MemoryRegion region) : region_(region) {} 934b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 9351c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain DepthType GetDepth() const { 9361c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain return region_.LoadUnaligned<DepthType>(kDepthOffset); 937b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 938b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 9391c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain void SetDepth(DepthType depth) { 9401c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain region_.StoreUnaligned<DepthType>(kDepthOffset, depth); 941b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 942b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 9431c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain MethodIndexType GetMethodIndexAtDepth(DepthType depth) const { 9441c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain return region_.LoadUnaligned<MethodIndexType>( 945b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray kFixedSize + depth * SingleEntrySize() + kMethodIndexOffset); 946b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 947b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 9481c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain void SetMethodIndexAtDepth(DepthType depth, MethodIndexType index) { 9491c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain region_.StoreUnaligned<MethodIndexType>( 950b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray kFixedSize + depth * SingleEntrySize() + kMethodIndexOffset, index); 951b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 952b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 9531c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain DexPcType GetDexPcAtDepth(DepthType depth) const { 9541c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain return region_.LoadUnaligned<DexPcType>( 955b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray kFixedSize + depth * SingleEntrySize() + kDexPcOffset); 956b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 957b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 9581c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain void SetDexPcAtDepth(DepthType depth, DexPcType dex_pc) { 9591c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain region_.StoreUnaligned<DexPcType>( 960b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray kFixedSize + depth * SingleEntrySize() + kDexPcOffset, dex_pc); 961b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray } 962b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray 9631c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain InvokeTypeType GetInvokeTypeAtDepth(DepthType depth) const { 9641c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain return region_.LoadUnaligned<InvokeTypeType>( 965b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray kFixedSize + depth * SingleEntrySize() + kInvokeTypeOffset); 966b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray } 967b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray 9681c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain void SetInvokeTypeAtDepth(DepthType depth, InvokeTypeType invoke_type) { 9691c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain region_.StoreUnaligned<InvokeTypeType>( 970b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray kFixedSize + depth * SingleEntrySize() + kInvokeTypeOffset, invoke_type); 971b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 972b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 9731c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain DexRegisterMapType GetDexRegisterMapOffsetAtDepth(DepthType depth) const { 9741c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain return region_.LoadUnaligned<DexRegisterMapType>( 975b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray kFixedSize + depth * SingleEntrySize() + kDexRegisterMapOffset); 976b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 977b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 9781c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain void SetDexRegisterMapOffsetAtDepth(DepthType depth, DexRegisterMapType offset) { 9791c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain region_.StoreUnaligned<DexRegisterMapType>( 980b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray kFixedSize + depth * SingleEntrySize() + kDexRegisterMapOffset, offset); 981b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 982b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 9831c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain bool HasDexRegisterMapAtDepth(DepthType depth) const { 984b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray return GetDexRegisterMapOffsetAtDepth(depth) != StackMap::kNoDexRegisterMap; 985b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 986b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 987b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray static size_t SingleEntrySize() { 988b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray return kFixedEntrySize; 989b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 990b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 9918f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko void Dump(VariableIndentationOutputStream* vios, 9928f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko const CodeInfo& info, uint16_t* number_of_dex_registers) const; 993b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 9941c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain 995b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray private: 996b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray static constexpr int kDepthOffset = 0; 9971c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kFixedSize = ELEMENT_BYTE_OFFSET_AFTER(Depth); 998b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 999b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray static constexpr int kMethodIndexOffset = 0; 10001c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kDexPcOffset = ELEMENT_BYTE_OFFSET_AFTER(MethodIndex); 10011c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kInvokeTypeOffset = ELEMENT_BYTE_OFFSET_AFTER(DexPc); 10021c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kDexRegisterMapOffset = ELEMENT_BYTE_OFFSET_AFTER(InvokeType); 10031c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kFixedEntrySize = ELEMENT_BYTE_OFFSET_AFTER(DexRegisterMap); 1004b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray 1005b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray MemoryRegion region_; 1006b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 1007b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray friend class CodeInfo; 1008b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray friend class StackMap; 1009b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray friend class StackMapStream; 1010b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray}; 101199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 101299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 101399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Wrapper around all compiler information collected for a method. 101499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form: 10151c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 10161c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * [overall_size, encoding_info, number_of_location_catalog_entries, number_of_stack_maps, 10171c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * stack_mask_size, DexRegisterLocationCatalog+, StackMap+, DexRegisterMap+, InlineInfo*] 10181c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 10191c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * where `encoding_info` is of the form: 10201c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 10211c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * [has_inline_info, inline_info_size_in_bytes, dex_register_map_size_in_bytes, 10221c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * dex_pc_size_in_bytes, native_pc_size_in_bytes, register_mask_size_in_bytes]. 102399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 102499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass CodeInfo { 102599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 10261c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain // Memory layout: fixed contents. 10271c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain typedef uint32_t OverallSizeType; 10281c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain typedef uint16_t EncodingInfoType; 10291c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain typedef uint32_t NumberOfLocationCatalogEntriesType; 10301c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain typedef uint32_t NumberOfStackMapsType; 10311c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain typedef uint32_t StackMaskSizeType; 10321c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain 10331c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain // Memory (bit) layout: encoding info. 10341c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int HasInlineInfoBitSize = 1; 10351c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int InlineInfoBitSize = kNumberOfBitForNumberOfBytesForEncoding; 10361c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int DexRegisterMapBitSize = kNumberOfBitForNumberOfBytesForEncoding; 10371c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int DexPcBitSize = kNumberOfBitForNumberOfBytesForEncoding; 10381c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int NativePcBitSize = kNumberOfBitForNumberOfBytesForEncoding; 10391c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int RegisterMaskBitSize = kNumberOfBitForNumberOfBytesForEncoding; 10401c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain 104199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray explicit CodeInfo(MemoryRegion region) : region_(region) {} 104299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 10433946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray explicit CodeInfo(const void* data) { 10443946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray uint32_t size = reinterpret_cast<const uint32_t*>(data)[0]; 10453946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray region_ = MemoryRegion(const_cast<void*>(data), size); 10463946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 10473946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 1048f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMapEncoding ExtractEncoding() const { 1049f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return StackMapEncoding(region_.LoadUnaligned<uint32_t>(kStackMaskSizeOffset), 1050f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetNumberOfBytesForEncoding(kInlineInfoBitOffset), 1051f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetNumberOfBytesForEncoding(kDexRegisterMapBitOffset), 1052f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetNumberOfBytesForEncoding(kDexPcBitOffset), 1053f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetNumberOfBytesForEncoding(kNativePcBitOffset), 1054f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetNumberOfBytesForEncoding(kRegisterMaskBitOffset)); 1055896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray } 1056896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray 1057f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil void SetEncoding(const StackMapEncoding& encoding) { 1058f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil region_.StoreUnaligned<uint32_t>(kStackMaskSizeOffset, encoding.NumberOfBytesForStackMask()); 1059f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil region_.StoreBit(kHasInlineInfoBitOffset, encoding.NumberOfBytesForInlineInfo() != 0); 1060f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil SetEncodingAt(kInlineInfoBitOffset, encoding.NumberOfBytesForInlineInfo()); 1061f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil SetEncodingAt(kDexRegisterMapBitOffset, encoding.NumberOfBytesForDexRegisterMap()); 1062f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil SetEncodingAt(kDexPcBitOffset, encoding.NumberOfBytesForDexPc()); 1063f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil SetEncodingAt(kNativePcBitOffset, encoding.NumberOfBytesForNativePc()); 1064f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil SetEncodingAt(kRegisterMaskBitOffset, encoding.NumberOfBytesForRegisterMask()); 1065896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray } 1066896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray 1067896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray void SetEncodingAt(size_t bit_offset, size_t number_of_bytes) { 1068d780c00e554c5b00fc1acf359e4b9c7e761ea0ebRoland Levillain region_.StoreBits(bit_offset, number_of_bytes, kNumberOfBitForNumberOfBytesForEncoding); 1069896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray } 1070896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray 1071896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray size_t GetNumberOfBytesForEncoding(size_t bit_offset) const { 1072d780c00e554c5b00fc1acf359e4b9c7e761ea0ebRoland Levillain return region_.LoadBits(bit_offset, kNumberOfBitForNumberOfBytesForEncoding); 1073004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray } 1074004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray 1075004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray bool HasInlineInfo() const { 1076004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray return region_.LoadBit(kHasInlineInfoBitOffset); 1077004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray } 1078004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray 1079f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil DexRegisterLocationCatalog GetDexRegisterLocationCatalog(const StackMapEncoding& encoding) const { 1080a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return DexRegisterLocationCatalog(region_.Subregion( 1081f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetDexRegisterLocationCatalogOffset(encoding), 1082f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetDexRegisterLocationCatalogSize(encoding))); 1083a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 1084a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 1085f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMap GetStackMapAt(size_t i, const StackMapEncoding& encoding) const { 1086f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t stack_map_size = encoding.ComputeStackMapSize(); 1087f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return StackMap(GetStackMaps(encoding).Subregion(i * stack_map_size, stack_map_size)); 10883946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 10893946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 10901c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain OverallSizeType GetOverallSize() const { 10911c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain return region_.LoadUnaligned<OverallSizeType>(kOverallSizeOffset); 10923946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 10933946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 10941c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain void SetOverallSize(OverallSizeType size) { 10951c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain region_.StoreUnaligned<OverallSizeType>(kOverallSizeOffset, size); 109699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 109799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 10981c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain NumberOfLocationCatalogEntriesType GetNumberOfLocationCatalogEntries() const { 10991c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain return region_.LoadUnaligned<NumberOfLocationCatalogEntriesType>( 11001c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain kNumberOfLocationCatalogEntriesOffset); 1101a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 1102a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 11031c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain void SetNumberOfLocationCatalogEntries(NumberOfLocationCatalogEntriesType num_entries) { 11041c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain region_.StoreUnaligned<NumberOfLocationCatalogEntriesType>( 11051c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain kNumberOfLocationCatalogEntriesOffset, num_entries); 1106a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 1107a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 1108f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil uint32_t GetDexRegisterLocationCatalogSize(const StackMapEncoding& encoding) const { 1109f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return ComputeDexRegisterLocationCatalogSize(GetDexRegisterLocationCatalogOffset(encoding), 11101c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain GetNumberOfLocationCatalogEntries()); 1111a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 1112a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 11131c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain NumberOfStackMapsType GetNumberOfStackMaps() const { 11141c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain return region_.LoadUnaligned<NumberOfStackMapsType>(kNumberOfStackMapsOffset); 111599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 111699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 11171c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain void SetNumberOfStackMaps(NumberOfStackMapsType number_of_stack_maps) { 11181c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain region_.StoreUnaligned<NumberOfStackMapsType>(kNumberOfStackMapsOffset, number_of_stack_maps); 111999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 112099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 112177a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // Get the size of all the stack maps of this CodeInfo object, in bytes. 1122f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t GetStackMapsSize(const StackMapEncoding& encoding) const { 1123f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return encoding.ComputeStackMapSize() * GetNumberOfStackMaps(); 112429ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain } 112529ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain 1126f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil uint32_t GetDexRegisterLocationCatalogOffset(const StackMapEncoding& encoding) const { 1127f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return GetStackMapsOffset() + GetStackMapsSize(encoding); 1128004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray } 1129004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray 1130f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil size_t GetDexRegisterMapsOffset(const StackMapEncoding& encoding) const { 1131f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return GetDexRegisterLocationCatalogOffset(encoding) 1132f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil + GetDexRegisterLocationCatalogSize(encoding); 1133a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 1134a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 11356530baf76ef7a62f2d76a6735ad461d7d59cf0e4Nicolas Geoffray uint32_t GetStackMapsOffset() const { 11366530baf76ef7a62f2d76a6735ad461d7d59cf0e4Nicolas Geoffray return kFixedSize; 11376530baf76ef7a62f2d76a6735ad461d7d59cf0e4Nicolas Geoffray } 11386530baf76ef7a62f2d76a6735ad461d7d59cf0e4Nicolas Geoffray 1139f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, 1140f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const StackMapEncoding& encoding, 1141f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil uint32_t number_of_dex_registers) const { 1142012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray if (!stack_map.HasDexRegisterMap(encoding)) { 1143012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray return DexRegisterMap(); 1144012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray } else { 1145012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray uint32_t offset = GetDexRegisterMapsOffset(encoding) 1146012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray + stack_map.GetDexRegisterMapOffset(encoding); 1147012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers); 1148012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray return DexRegisterMap(region_.Subregion(offset, size)); 1149012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray } 115099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 115199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 1152b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray // Return the `DexRegisterMap` pointed by `inline_info` at depth `depth`. 1153b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth, 1154b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray InlineInfo inline_info, 1155f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const StackMapEncoding& encoding, 1156b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray uint32_t number_of_dex_registers) const { 1157012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray if (!inline_info.HasDexRegisterMapAtDepth(depth)) { 1158012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray return DexRegisterMap(); 1159012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray } else { 1160012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray uint32_t offset = GetDexRegisterMapsOffset(encoding) 1161012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray + inline_info.GetDexRegisterMapOffsetAtDepth(depth); 1162012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers); 1163012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray return DexRegisterMap(region_.Subregion(offset, size)); 1164012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray } 1165b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 1166b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 1167f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil InlineInfo GetInlineInfoOf(StackMap stack_map, const StackMapEncoding& encoding) const { 1168f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil DCHECK(stack_map.HasInlineInfo(encoding)); 1169f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil uint32_t offset = stack_map.GetInlineDescriptorOffset(encoding) 1170f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil + GetDexRegisterMapsOffset(encoding); 1171004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray uint8_t depth = region_.LoadUnaligned<uint8_t>(offset); 117299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return InlineInfo(region_.Subregion(offset, 117399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray InlineInfo::kFixedSize + depth * InlineInfo::SingleEntrySize())); 117499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 117599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 1176f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMap GetStackMapForDexPc(uint32_t dex_pc, const StackMapEncoding& encoding) const { 117799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { 1178f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMap stack_map = GetStackMapAt(i, encoding); 1179f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil if (stack_map.GetDexPc(encoding) == dex_pc) { 118099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return stack_map; 118199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 118299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 1183e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray return StackMap(); 118499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 118599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 118677a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // Searches the stack map list backwards because catch stack maps are stored 118777a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // at the end. 118877a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil StackMap GetCatchStackMapForDexPc(uint32_t dex_pc, const StackMapEncoding& encoding) const { 118977a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil for (size_t i = GetNumberOfStackMaps(); i > 0; --i) { 119077a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil StackMap stack_map = GetStackMapAt(i - 1, encoding); 119177a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil if (stack_map.GetDexPc(encoding) == dex_pc) { 119277a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil return stack_map; 119377a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil } 119477a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil } 119577a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil return StackMap(); 119677a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil } 119777a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil 1198b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray StackMap GetOsrStackMapForDexPc(uint32_t dex_pc, const StackMapEncoding& encoding) const { 1199b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray size_t e = GetNumberOfStackMaps(); 1200b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (e == 0) { 1201b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // There cannot be OSR stack map if there is no stack map. 1202b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return StackMap(); 1203b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 1204b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // Walk over all stack maps. If two consecutive stack maps are identical, then we 1205b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // have found a stack map suitable for OSR. 1206b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray for (size_t i = 0; i < e - 1; ++i) { 1207b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray StackMap stack_map = GetStackMapAt(i, encoding); 1208b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (stack_map.GetDexPc(encoding) == dex_pc) { 1209b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray StackMap other = GetStackMapAt(i + 1, encoding); 1210b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (other.GetDexPc(encoding) == dex_pc && 1211b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray other.GetNativePcOffset(encoding) == stack_map.GetNativePcOffset(encoding)) { 1212b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray DCHECK_EQ(other.GetDexRegisterMapOffset(encoding), 1213b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray stack_map.GetDexRegisterMapOffset(encoding)); 1214b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray DCHECK(!stack_map.HasInlineInfo(encoding)); 1215b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (i < e - 2) { 1216b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // Make sure there are not three identical stack maps following each other. 1217b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray DCHECK_NE(stack_map.GetNativePcOffset(encoding), 1218b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray GetStackMapAt(i + 2, encoding).GetNativePcOffset(encoding)); 1219b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 1220b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return stack_map; 1221b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 1222b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 1223b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 1224b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return StackMap(); 1225b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 1226b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 1227f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset, 1228f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const StackMapEncoding& encoding) const { 122977a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // TODO: Safepoint stack maps are sorted by native_pc_offset but catch stack 123077a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // maps are not. If we knew that the method does not have try/catch, 123177a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // we could do binary search. 123299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) { 1233f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMap stack_map = GetStackMapAt(i, encoding); 1234f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil if (stack_map.GetNativePcOffset(encoding) == native_pc_offset) { 123599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return stack_map; 123699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 123799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 1238e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray return StackMap(); 123999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 124099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 1241f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain // Dump this CodeInfo object on `os`. `code_offset` is the (absolute) 1242f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain // native PC of the compiled method and `number_of_dex_registers` the 1243f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain // number of Dex virtual registers used in this method. If 1244f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain // `dump_stack_maps` is true, also dump the stack maps and the 1245f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain // associated Dex register maps. 12468f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko void Dump(VariableIndentationOutputStream* vios, 1247f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain uint32_t code_offset, 1248f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain uint16_t number_of_dex_registers, 1249f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain bool dump_stack_maps) const; 1250004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray 125199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private: 12523946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray static constexpr int kOverallSizeOffset = 0; 12531c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kEncodingInfoOffset = ELEMENT_BYTE_OFFSET_AFTER(OverallSize); 12541c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kNumberOfLocationCatalogEntriesOffset = 12551c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain ELEMENT_BYTE_OFFSET_AFTER(EncodingInfo); 1256a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static constexpr int kNumberOfStackMapsOffset = 12571c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain ELEMENT_BYTE_OFFSET_AFTER(NumberOfLocationCatalogEntries); 12581c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kStackMaskSizeOffset = ELEMENT_BYTE_OFFSET_AFTER(NumberOfStackMaps); 12591c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kFixedSize = ELEMENT_BYTE_OFFSET_AFTER(StackMaskSize); 12601c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain 12611c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kHasInlineInfoBitOffset = kEncodingInfoOffset * kBitsPerByte; 12621c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kInlineInfoBitOffset = ELEMENT_BIT_OFFSET_AFTER(HasInlineInfo); 12631c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kDexRegisterMapBitOffset = ELEMENT_BIT_OFFSET_AFTER(InlineInfo); 12641c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kDexPcBitOffset = ELEMENT_BIT_OFFSET_AFTER(DexRegisterMap); 12651c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kNativePcBitOffset = ELEMENT_BIT_OFFSET_AFTER(DexPc); 12661c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kRegisterMaskBitOffset = ELEMENT_BIT_OFFSET_AFTER(NativePc); 12671c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain 12681c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kEncodingInfoPastTheEndBitOffset = ELEMENT_BIT_OFFSET_AFTER(RegisterMask); 12691c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static constexpr int kEncodingInfoOverallBitSize = 12701c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain kEncodingInfoPastTheEndBitOffset - kHasInlineInfoBitOffset; 12711c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain 12721c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain static_assert(kEncodingInfoOverallBitSize <= (sizeof(EncodingInfoType) * kBitsPerByte), 12731c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain "art::CodeInfo::EncodingInfoType is too short to hold all encoding info elements."); 1274004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray 1275f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil MemoryRegion GetStackMaps(const StackMapEncoding& encoding) const { 127699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.size() == 0 127799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray ? MemoryRegion() 1278f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil : region_.Subregion(GetStackMapsOffset(), GetStackMapsSize(encoding)); 1279a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 1280a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 1281a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Compute the size of the Dex register map associated to the stack map at 1282a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // `dex_register_map_offset_in_code_info`. 1283a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t ComputeDexRegisterMapSizeOf(uint32_t dex_register_map_offset_in_code_info, 1284a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers) const { 1285a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Offset where the actual mapping data starts within art::DexRegisterMap. 1286a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t location_mapping_data_offset_in_dex_register_map = 1287a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterMap::GetLocationMappingDataOffset(number_of_dex_registers); 1288a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Create a temporary art::DexRegisterMap to be able to call 1289a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // art::DexRegisterMap::GetNumberOfLiveDexRegisters and 1290a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterMap dex_register_map_without_locations( 1291a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain MemoryRegion(region_.Subregion(dex_register_map_offset_in_code_info, 1292a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain location_mapping_data_offset_in_dex_register_map))); 1293a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t number_of_live_dex_registers = 1294a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain dex_register_map_without_locations.GetNumberOfLiveDexRegisters(number_of_dex_registers); 1295a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t location_mapping_data_size_in_bits = 12961c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain DexRegisterMap::SingleEntrySizeInBits(GetNumberOfLocationCatalogEntries()) 1297a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * number_of_live_dex_registers; 1298a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t location_mapping_data_size_in_bytes = 1299a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte; 1300a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t dex_register_map_size = 1301a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain location_mapping_data_offset_in_dex_register_map + location_mapping_data_size_in_bytes; 1302a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return dex_register_map_size; 1303a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 1304a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 1305a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Compute the size of a Dex register location catalog starting at offset `origin` 1306a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // in `region_` and containing `number_of_dex_locations` entries. 1307a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t ComputeDexRegisterLocationCatalogSize(uint32_t origin, 1308a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint32_t number_of_dex_locations) const { 1309a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // TODO: Ideally, we would like to use art::DexRegisterLocationCatalog::Size or 1310a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // art::DexRegisterLocationCatalog::FindLocationOffset, but the 1311a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // DexRegisterLocationCatalog is not yet built. Try to factor common code. 1312a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t offset = origin + DexRegisterLocationCatalog::kFixedSize; 1313a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 1314a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Skip the first `number_of_dex_locations - 1` entries. 1315a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain for (uint16_t i = 0; i < number_of_dex_locations; ++i) { 1316a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Read the first next byte and inspect its first 3 bits to decide 1317a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // whether it is a short or a large location. 1318a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocationCatalog::ShortLocation first_byte = 1319a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain region_.LoadUnaligned<DexRegisterLocationCatalog::ShortLocation>(offset); 1320a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation::Kind kind = 1321a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocationCatalog::ExtractKindFromShortLocation(first_byte); 1322a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 1323a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Short location. Skip the current byte. 1324a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain offset += DexRegisterLocationCatalog::SingleShortEntrySize(); 1325a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } else { 1326a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Large location. Skip the 5 next bytes. 1327a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain offset += DexRegisterLocationCatalog::SingleLargeEntrySize(); 1328a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 1329a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 1330a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t size = offset - origin; 1331a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return size; 1332a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 1333a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 133499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 13353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class StackMapStream; 133699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 133799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 13381c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain#undef ELEMENT_BYTE_OFFSET_AFTER 13391c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain#undef ELEMENT_BIT_OFFSET_AFTER 13401c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain 134199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray} // namespace art 134299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 134399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#endif // ART_RUNTIME_STACK_MAP_H_ 1344