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" 2309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky#include "leb128.h" 2499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 2599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffraynamespace art { 2699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 278f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Markoclass VariableIndentationOutputStream; 288f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko 29a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// Size of a frame slot, in bytes. This constant is a signed value, 30a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// to please the compiler in arithmetic operations involving int32_t 31a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// (signed) values. 32a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainstatic constexpr ssize_t kFrameSlotSize = 4; 33a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 34fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray// Size of Dex virtual registers. 35a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainstatic constexpr size_t kVRegSize = 4; 36fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 37004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffrayclass CodeInfo; 38f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdilclass StackMapEncoding; 3909ed09866da6d8c7448ef297c148bfa577a247c2David Srbeckystruct CodeInfoEncoding; 40004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray 4199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 4299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Classes in the following file are wrapper on stack map information backed 4399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * by a MemoryRegion. As such they read and write to the region, they don't have 4499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * their own fields. 4599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 4699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 47a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain// Dex register location container used by DexRegisterMap and StackMapStream. 48a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillainclass DexRegisterLocation { 49a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain public: 50a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain /* 51a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * The location kind used to populate the Dex register information in a 52a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * StackMapStream can either be: 53d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * - kStack: vreg stored on the stack, value holds the stack offset; 54d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * - kInRegister: vreg stored in low 32 bits of a core physical register, 55d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * value holds the register number; 56d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * - kInRegisterHigh: vreg stored in high 32 bits of a core physical register, 57d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * value holds the register number; 58d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * - kInFpuRegister: vreg stored in low 32 bits of an FPU register, 59d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * value holds the register number; 60d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * - kInFpuRegisterHigh: vreg stored in high 32 bits of an FPU register, 61d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * value holds the register number; 62a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kConstant: value holds the constant; 63a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * 64a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * In addition, DexRegisterMap also uses these values: 65a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain * - kInStackLargeOffset: value holds a "large" stack offset (greater than 66a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * or equal to 128 bytes); 67a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * - kConstantLargeValue: value holds a "large" constant (lower than 0, or 68d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * or greater than or equal to 32); 69d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil * - kNone: the register has no location, meaning it has not been set. 70a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain */ 71a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain enum class Kind : uint8_t { 72a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location kinds, for entries fitting on one byte (3 bits 73a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // for the kind, 5 bits for the value) in a DexRegisterMap. 74d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kInStack = 0, // 0b000 75d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kInRegister = 1, // 0b001 76d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kInRegisterHigh = 2, // 0b010 77a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kInFpuRegister = 3, // 0b011 78d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kInFpuRegisterHigh = 4, // 0b100 79d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kConstant = 5, // 0b101 80a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 81a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location kinds, requiring a 5-byte encoding (1 byte for the 82a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // kind, 4 bytes for the value). 83a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 84a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Stack location at a large offset, meaning that the offset value 85a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // divided by the stack frame slot size (4 bytes) cannot fit on a 86a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // 5-bit unsigned integer (i.e., this offset value is greater than 87a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // or equal to 2^5 * 4 = 128 bytes). 88d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kInStackLargeOffset = 6, // 0b110 89a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 90a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large constant, that cannot fit on a 5-bit signed integer (i.e., 91a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // lower than 0, or greater than or equal to 2^5 = 32). 92d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kConstantLargeValue = 7, // 0b111 93d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil 94d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil // Entries with no location are not stored and do not need own marker. 95d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil kNone = static_cast<uint8_t>(-1), 96a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 97a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain kLastLocationKind = kConstantLargeValue 98a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain }; 99a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 100a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static_assert( 101a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain sizeof(Kind) == 1u, 102a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain "art::DexRegisterLocation::Kind has a size different from one byte."); 103a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 104a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static bool IsShortLocationKind(Kind kind) { 105a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (kind) { 106a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStack: 107a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInRegister: 108d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kInRegisterHigh: 109a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInFpuRegister: 110d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kInFpuRegisterHigh: 111a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstant: 112a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return true; 113a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 114a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStackLargeOffset: 115a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstantLargeValue: 116a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return false; 117a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 118d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kNone: 1197dc11782ff0a5dffcd8108f256f8975f0b3e8076David Srbecky LOG(FATAL) << "Unexpected location kind"; 120a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 121d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil UNREACHABLE(); 122a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 123a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 124a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Convert `kind` to a "surface" kind, i.e. one that doesn't include 125a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // any value with a "large" qualifier. 126a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // TODO: Introduce another enum type for the surface kind? 127a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static Kind ConvertToSurfaceKind(Kind kind) { 128a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (kind) { 129a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStack: 130a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInRegister: 131d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kInRegisterHigh: 132a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInFpuRegister: 133d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kInFpuRegisterHigh: 134a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstant: 135a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return kind; 136a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 137a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kInStackLargeOffset: 138a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return Kind::kInStack; 139a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 140a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case Kind::kConstantLargeValue: 141a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return Kind::kConstant; 142a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 143d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case Kind::kNone: 144d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil return kind; 145a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 146d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil UNREACHABLE(); 147a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 148a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 149a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Required by art::StackMapStream::LocationCatalogEntriesIndices. 150a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation() : kind_(Kind::kNone), value_(0) {} 151a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 152a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation(Kind kind, int32_t value) : kind_(kind), value_(value) {} 153a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 154fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray static DexRegisterLocation None() { 155fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray return DexRegisterLocation(Kind::kNone, 0); 156fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 157fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray 158a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the "surface" kind of the location, i.e., the one that doesn't 159a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // include any value with a "large" qualifier. 160a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain Kind GetKind() const { 161a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return ConvertToSurfaceKind(kind_); 162a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 163a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 164a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the value of the location. 165a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t GetValue() const { return value_; } 166a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 167a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Get the actual kind of the location. 168a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain Kind GetInternalKind() const { return kind_; } 169a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 1706ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle bool operator==(DexRegisterLocation other) const { 1716ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle return kind_ == other.kind_ && value_ == other.value_; 1726ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle } 1736ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle 1746ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle bool operator!=(DexRegisterLocation other) const { 1756ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle return !(*this == other); 1766ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle } 1776ae70962089e4af9718cc9b7c2b79a0c501c1844Calin Juravle 178a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain private: 179a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain Kind kind_; 180a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value_; 181a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 182a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain friend class DexRegisterLocationHashFn; 183a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain}; 184a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 1857dc11782ff0a5dffcd8108f256f8975f0b3e8076David Srbeckystd::ostream& operator<<(std::ostream& stream, const DexRegisterLocation::Kind& kind); 1867dc11782ff0a5dffcd8108f256f8975f0b3e8076David Srbecky 18799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 188a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * Store information on unique Dex register locations used in a method. 189a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * The information is of the form: 1901c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 1911c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * [DexRegisterLocation+]. 1921c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 193fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray * DexRegisterLocations are either 1- or 5-byte wide (see art::DexRegisterLocation::Kind). 19499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 195a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainclass DexRegisterLocationCatalog { 19699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 197a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain explicit DexRegisterLocationCatalog(MemoryRegion region) : region_(region) {} 19899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 199a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short (compressed) location, fitting on one byte. 200a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain typedef uint8_t ShortLocation; 201a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 202a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain void SetRegisterInfo(size_t offset, const DexRegisterLocation& dex_register_location) { 203a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind kind = ComputeCompressedKind(dex_register_location); 204a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value = dex_register_location.GetValue(); 205a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 206a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location. Compress the kind and the value as a single byte. 207a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStack) { 208a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Instead of storing stack offsets expressed in bytes for 209a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // short stack locations, store slot offsets. A stack offset 210a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // is a multiple of 4 (kFrameSlotSize). This means that by 211a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // dividing it by 4, we can fit values from the [0, 128) 212a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // interval in a short stack location, and not just values 213a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // from the [0, 32) interval. 214a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(value % kFrameSlotSize, 0); 215a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value /= kFrameSlotSize; 216a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 217a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK(IsShortValue(value)) << value; 218a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.StoreUnaligned<ShortLocation>(offset, MakeShortLocation(kind, value)); 219a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } else { 220a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location. Write the location on one byte and the value 221a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // on 4 bytes. 222a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK(!IsShortValue(value)) << value; 223a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) { 224a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Also divide large stack offsets by 4 for the sake of consistency. 225a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(value % kFrameSlotSize, 0); 226a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value /= kFrameSlotSize; 227a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 228a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Data can be unaligned as the written Dex register locations can 229a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // either be 1-byte or 5-byte wide. Use 230a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // art::MemoryRegion::StoreUnaligned instead of 231a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // art::MemoryRegion::Store to prevent unligned word accesses on ARM. 232a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.StoreUnaligned<DexRegisterLocation::Kind>(offset, kind); 233a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain region_.StoreUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind), value); 234a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 235a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 23699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 237a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Find the offset of the location catalog entry number `location_catalog_entry_index`. 238a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t FindLocationOffset(size_t location_catalog_entry_index) const { 239a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t offset = kFixedSize; 240a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Skip the first `location_catalog_entry_index - 1` entries. 241a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain for (uint16_t i = 0; i < location_catalog_entry_index; ++i) { 242a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Read the first next byte and inspect its first 3 bits to decide 243a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // whether it is a short or a large location. 244a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation::Kind kind = ExtractKindAtOffset(offset); 245a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 246a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Short location. Skip the current byte. 247a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain offset += SingleShortEntrySize(); 248a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } else { 249a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Large location. Skip the 5 next bytes. 250a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain offset += SingleLargeEntrySize(); 251a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 252442b46a087c389a91a0b51547ac9205058432364Roland Levillain } 253a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return offset; 254442b46a087c389a91a0b51547ac9205058432364Roland Levillain } 255442b46a087c389a91a0b51547ac9205058432364Roland Levillain 256a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Get the internal kind of entry at `location_catalog_entry_index`. 257a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation::Kind GetLocationInternalKind(size_t location_catalog_entry_index) const { 258a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (location_catalog_entry_index == kNoLocationEntryIndex) { 259a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return DexRegisterLocation::Kind::kNone; 260a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 261a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return ExtractKindAtOffset(FindLocationOffset(location_catalog_entry_index)); 26299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 26399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 264a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Get the (surface) kind and value of entry at `location_catalog_entry_index`. 265a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation GetDexRegisterLocation(size_t location_catalog_entry_index) const { 266a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (location_catalog_entry_index == kNoLocationEntryIndex) { 267fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray return DexRegisterLocation::None(); 268fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray } 269a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t offset = FindLocationOffset(location_catalog_entry_index); 270a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Read the first byte and inspect its first 3 bits to get the location. 271a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset); 272a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind kind = ExtractKindFromShortLocation(first_byte); 273a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 274a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Short location. Extract the value from the remaining 5 bits. 275a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value = ExtractValueFromShortLocation(first_byte); 276a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStack) { 277a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Convert the stack slot (short) offset to a byte offset value. 278a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value *= kFrameSlotSize; 279a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 280a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation(kind, value); 281a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } else { 282a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Large location. Read the four next bytes to get the value. 283a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain int32_t value = region_.LoadUnaligned<int32_t>(offset + sizeof(DexRegisterLocation::Kind)); 284a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain if (kind == DexRegisterLocation::Kind::kInStackLargeOffset) { 285a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Convert the stack slot (large) offset to a byte offset value. 286a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain value *= kFrameSlotSize; 287a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 288a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return DexRegisterLocation(kind, value); 289a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 29099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 29199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 292a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Compute the compressed kind of `location`. 293a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static DexRegisterLocation::Kind ComputeCompressedKind(const DexRegisterLocation& location) { 294d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil DexRegisterLocation::Kind kind = location.GetInternalKind(); 295d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil switch (kind) { 296d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInStack: 297d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil return IsShortStackOffsetValue(location.GetValue()) 298d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil ? DexRegisterLocation::Kind::kInStack 299d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil : DexRegisterLocation::Kind::kInStackLargeOffset; 300a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 301a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInRegister: 302d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInRegisterHigh: 303a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_GE(location.GetValue(), 0); 304a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_LT(location.GetValue(), 1 << kValueBits); 305d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil return kind; 306a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 307a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInFpuRegister: 308d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInFpuRegisterHigh: 309a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_GE(location.GetValue(), 0); 310a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_LT(location.GetValue(), 1 << kValueBits); 311d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil return kind; 312a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 313a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kConstant: 314a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return IsShortConstantValue(location.GetValue()) 315a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ? DexRegisterLocation::Kind::kConstant 316a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain : DexRegisterLocation::Kind::kConstantLargeValue; 317a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 318d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kConstantLargeValue: 319d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInStackLargeOffset: 320d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kNone: 3217dc11782ff0a5dffcd8108f256f8975f0b3e8076David Srbecky LOG(FATAL) << "Unexpected location kind " << kind; 322a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 323d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil UNREACHABLE(); 324a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 325a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 326a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Can `location` be turned into a short location? 327a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static bool CanBeEncodedAsShortLocation(const DexRegisterLocation& location) { 328d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil DexRegisterLocation::Kind kind = location.GetInternalKind(); 329d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil switch (kind) { 330d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInStack: 331d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil return IsShortStackOffsetValue(location.GetValue()); 332d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil 333a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInRegister: 334d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInRegisterHigh: 335a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInFpuRegister: 336d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInFpuRegisterHigh: 337a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return true; 338a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 339a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kConstant: 340a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return IsShortConstantValue(location.GetValue()); 341a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 342d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kConstantLargeValue: 343d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInStackLargeOffset: 344d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kNone: 3457dc11782ff0a5dffcd8108f256f8975f0b3e8076David Srbecky LOG(FATAL) << "Unexpected location kind " << kind; 346a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 347d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil UNREACHABLE(); 348a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 349a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 350a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static size_t EntrySize(const DexRegisterLocation& location) { 351a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return CanBeEncodedAsShortLocation(location) ? SingleShortEntrySize() : SingleLargeEntrySize(); 352a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 353a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 354a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static size_t SingleShortEntrySize() { 355a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return sizeof(ShortLocation); 356a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 357a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 358a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static size_t SingleLargeEntrySize() { 359a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return sizeof(DexRegisterLocation::Kind) + sizeof(int32_t); 36099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 36199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 36212baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain size_t Size() const { 36312baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain return region_.size(); 36412baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain } 36512baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain 3668f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko void Dump(VariableIndentationOutputStream* vios, const CodeInfo& code_info); 3670396ed7d3ad30778cb4af19e7086bea0deace9b9Roland Levillain 368a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Special (invalid) Dex register location catalog entry index meaning 369a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // that there is no location for a given Dex register (i.e., it is 370a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // mapped to a DexRegisterLocation::Kind::kNone location). 371a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static constexpr size_t kNoLocationEntryIndex = -1; 37299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 37312baf476389359d54ae04d7898190ef6f81ab0b2Roland Levillain private: 374a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static constexpr int kFixedSize = 0; 375a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 376a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Width of the kind "field" in a short location, in bits. 377a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kKindBits = 3; 378a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Width of the value "field" in a short location, in bits. 379a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kValueBits = 5; 380a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 381a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr uint8_t kKindMask = (1 << kKindBits) - 1; 382a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr int32_t kValueMask = (1 << kValueBits) - 1; 383a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kKindOffset = 0; 384a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static constexpr size_t kValueOffset = kKindBits; 385a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 386a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static bool IsShortStackOffsetValue(int32_t value) { 387a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_EQ(value % kFrameSlotSize, 0); 388a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return IsShortValue(value / kFrameSlotSize); 389a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 390a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 391a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static bool IsShortConstantValue(int32_t value) { 392a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return IsShortValue(value); 393a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 394a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 395a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static bool IsShortValue(int32_t value) { 396a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return IsUint<kValueBits>(value); 397a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 398a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 399a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static ShortLocation MakeShortLocation(DexRegisterLocation::Kind kind, int32_t value) { 400a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint8_t kind_integer_value = static_cast<uint8_t>(kind); 401a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK(IsUint<kKindBits>(kind_integer_value)) << kind_integer_value; 402a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK(IsShortValue(value)) << value; 403a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return (kind_integer_value & kKindMask) << kKindOffset 404a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain | (value & kValueMask) << kValueOffset; 405a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 406a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 407a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static DexRegisterLocation::Kind ExtractKindFromShortLocation(ShortLocation location) { 408a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain uint8_t kind = (location >> kKindOffset) & kKindMask; 409a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_LE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kLastLocationKind)); 410fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray // We do not encode kNone locations in the stack map. 411fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray DCHECK_NE(kind, static_cast<uint8_t>(DexRegisterLocation::Kind::kNone)); 412a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return static_cast<DexRegisterLocation::Kind>(kind); 413a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 414a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 415a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain static int32_t ExtractValueFromShortLocation(ShortLocation location) { 416a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return (location >> kValueOffset) & kValueMask; 417a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 418a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 419a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain // Extract a location kind from the byte at position `offset`. 420a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterLocation::Kind ExtractKindAtOffset(size_t offset) const { 421a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain ShortLocation first_byte = region_.LoadUnaligned<ShortLocation>(offset); 422a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return ExtractKindFromShortLocation(first_byte); 423a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 424a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 42599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 426a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 427a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain friend class CodeInfo; 428a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain friend class StackMapStream; 42999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 43099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 431a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain/* Information on Dex register locations for a specific PC, mapping a 432a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * stack map's Dex register to a location entry in a DexRegisterLocationCatalog. 433a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * The information is of the form: 4341c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 4351c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * [live_bit_mask, entries*] 4361c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 437a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * where entries are concatenated unsigned integer values encoded on a number 438a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * of bits (fixed per DexRegisterMap instances of a CodeInfo object) depending 439a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * on the number of entries in the Dex register location catalog 440a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * (see DexRegisterMap::SingleEntrySizeInBits). The map is 1-byte aligned. 441a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain */ 442a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillainclass DexRegisterMap { 443a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain public: 444a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain explicit DexRegisterMap(MemoryRegion region) : region_(region) {} 445012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray DexRegisterMap() {} 446012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray 447012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray bool IsValid() const { return region_.pointer() != nullptr; } 448a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 449a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Get the surface kind of Dex register `dex_register_number`. 450a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation::Kind GetLocationKind(uint16_t dex_register_number, 451a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 452f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const CodeInfo& code_info, 45309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const CodeInfoEncoding& enc) const { 454a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return DexRegisterLocation::ConvertToSurfaceKind( 455f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetLocationInternalKind(dex_register_number, number_of_dex_registers, code_info, enc)); 456a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 457a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 458a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Get the internal kind of Dex register `dex_register_number`. 459a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation::Kind GetLocationInternalKind(uint16_t dex_register_number, 460a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 461f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const CodeInfo& code_info, 46209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const CodeInfoEncoding& enc) const; 463a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 464a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Get the Dex register location `dex_register_number`. 465a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation GetDexRegisterLocation(uint16_t dex_register_number, 466a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 467f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const CodeInfo& code_info, 46809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const CodeInfoEncoding& enc) const; 469a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 470a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain int32_t GetStackOffsetInBytes(uint16_t dex_register_number, 471a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 472f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const CodeInfo& code_info, 47309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const CodeInfoEncoding& enc) const { 474a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation location = 475f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc); 476a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK(location.GetKind() == DexRegisterLocation::Kind::kInStack); 477a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // GetDexRegisterLocation returns the offset in bytes. 478a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return location.GetValue(); 479a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 480a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 481a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain int32_t GetConstant(uint16_t dex_register_number, 482a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 483f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const CodeInfo& code_info, 48409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const CodeInfoEncoding& enc) const { 485a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation location = 486f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc); 4877dc11782ff0a5dffcd8108f256f8975f0b3e8076David Srbecky DCHECK_EQ(location.GetKind(), DexRegisterLocation::Kind::kConstant); 488a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return location.GetValue(); 489a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 490a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 491a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain int32_t GetMachineRegister(uint16_t dex_register_number, 492a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 493f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil const CodeInfo& code_info, 49409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const CodeInfoEncoding& enc) const { 495a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation location = 496f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info, enc); 497d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil DCHECK(location.GetInternalKind() == DexRegisterLocation::Kind::kInRegister || 498d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil location.GetInternalKind() == DexRegisterLocation::Kind::kInRegisterHigh || 499d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegister || 500d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil location.GetInternalKind() == DexRegisterLocation::Kind::kInFpuRegisterHigh) 5017dc11782ff0a5dffcd8108f256f8975f0b3e8076David Srbecky << location.GetInternalKind(); 502a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return location.GetValue(); 503a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 504a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 505a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Get the index of the entry in the Dex register location catalog 506a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // corresponding to `dex_register_number`. 507a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t GetLocationCatalogEntryIndex(uint16_t dex_register_number, 508a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 509a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t number_of_location_catalog_entries) const { 510a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (!IsDexRegisterLive(dex_register_number)) { 511a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return DexRegisterLocationCatalog::kNoLocationEntryIndex; 512a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 513a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 514a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (number_of_location_catalog_entries == 1) { 515a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // We do not allocate space for location maps in the case of a 516a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // single-entry location catalog, as it is useless. The only valid 517a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // entry index is 0; 518a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return 0; 519a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 520a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 521a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // The bit offset of the beginning of the map locations. 522a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t map_locations_offset_in_bits = 523a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte; 524a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t index_in_dex_register_map = GetIndexInDexRegisterMap(dex_register_number); 525a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers)); 526a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // The bit size of an entry. 527a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries); 528a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // The bit offset where `index_in_dex_register_map` is located. 529a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t entry_offset_in_bits = 530a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits; 531a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t location_catalog_entry_index = 532a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain region_.LoadBits(entry_offset_in_bits, map_entry_size_in_bits); 533a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries); 534a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return location_catalog_entry_index; 535a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 536a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 537a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Map entry at `index_in_dex_register_map` to `location_catalog_entry_index`. 538a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain void SetLocationCatalogEntryIndex(size_t index_in_dex_register_map, 539a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t location_catalog_entry_index, 540a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers, 541a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t number_of_location_catalog_entries) { 542a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_LT(index_in_dex_register_map, GetNumberOfLiveDexRegisters(number_of_dex_registers)); 543a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DCHECK_LT(location_catalog_entry_index, number_of_location_catalog_entries); 544a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 545a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (number_of_location_catalog_entries == 1) { 546a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // We do not allocate space for location maps in the case of a 547a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // single-entry location catalog, as it is useless. 548a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return; 549a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 550a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 551a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // The bit offset of the beginning of the map locations. 552a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t map_locations_offset_in_bits = 553a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain GetLocationMappingDataOffset(number_of_dex_registers) * kBitsPerByte; 554a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // The bit size of an entry. 555a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t map_entry_size_in_bits = SingleEntrySizeInBits(number_of_location_catalog_entries); 556a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // The bit offset where `index_in_dex_register_map` is located. 557a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t entry_offset_in_bits = 558a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain map_locations_offset_in_bits + index_in_dex_register_map * map_entry_size_in_bits; 559a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain region_.StoreBits(entry_offset_in_bits, location_catalog_entry_index, map_entry_size_in_bits); 560a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 561a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 562a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain void SetLiveBitMask(uint16_t number_of_dex_registers, 563a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain const BitVector& live_dex_registers_mask) { 564a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte; 565a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain for (uint16_t i = 0; i < number_of_dex_registers; ++i) { 566a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain region_.StoreBit(live_bit_mask_offset_in_bits + i, live_dex_registers_mask.IsBitSet(i)); 567a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 568a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 569a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 570a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain bool IsDexRegisterLive(uint16_t dex_register_number) const { 571a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t live_bit_mask_offset_in_bits = GetLiveBitMaskOffset() * kBitsPerByte; 572a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return region_.LoadBit(live_bit_mask_offset_in_bits + dex_register_number); 573a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 574a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 575a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t GetNumberOfLiveDexRegisters(uint16_t number_of_dex_registers) const { 576a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t number_of_live_dex_registers = 0; 577a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain for (size_t i = 0; i < number_of_dex_registers; ++i) { 578a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (IsDexRegisterLive(i)) { 579a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain ++number_of_live_dex_registers; 580a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 581a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 582a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return number_of_live_dex_registers; 583a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 584a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 585a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static size_t GetLiveBitMaskOffset() { 586a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return kFixedSize; 587a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 588a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 589a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Compute the size of the live register bit mask (in bytes), for a 590a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // method having `number_of_dex_registers` Dex registers. 591a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static size_t GetLiveBitMaskSize(uint16_t number_of_dex_registers) { 592a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return RoundUp(number_of_dex_registers, kBitsPerByte) / kBitsPerByte; 593a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 594a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 595a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static size_t GetLocationMappingDataOffset(uint16_t number_of_dex_registers) { 596a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return GetLiveBitMaskOffset() + GetLiveBitMaskSize(number_of_dex_registers); 597a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 598a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 599a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t GetLocationMappingDataSize(uint16_t number_of_dex_registers, 600a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t number_of_location_catalog_entries) const { 601a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t location_mapping_data_size_in_bits = 602a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain GetNumberOfLiveDexRegisters(number_of_dex_registers) 603a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * SingleEntrySizeInBits(number_of_location_catalog_entries); 604a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte; 605a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 606a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 607a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Return the size of a map entry in bits. Note that if 608a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // `number_of_location_catalog_entries` equals 1, this function returns 0, 609a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // which is fine, as there is no need to allocate a map for a 610a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // single-entry location catalog; the only valid location catalog entry index 611a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // for a live register in this case is 0 and there is no need to 612a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // store it. 613a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static size_t SingleEntrySizeInBits(size_t number_of_location_catalog_entries) { 614a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Handle the case of 0, as we cannot pass 0 to art::WhichPowerOf2. 615a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return number_of_location_catalog_entries == 0 616a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain ? 0u 617a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain : WhichPowerOf2(RoundUpToPowerOfTwo(number_of_location_catalog_entries)); 618a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 619a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 620a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Return the size of the DexRegisterMap object, in bytes. 621a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t Size() const { 622a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return region_.size(); 623a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 624a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 6258f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko void Dump(VariableIndentationOutputStream* vios, 6268f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko const CodeInfo& code_info, uint16_t number_of_dex_registers) const; 627b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 628a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain private: 629a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Return the index in the Dex register map corresponding to the Dex 630a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // register number `dex_register_number`. 631a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t GetIndexInDexRegisterMap(uint16_t dex_register_number) const { 632a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (!IsDexRegisterLive(dex_register_number)) { 633a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return kInvalidIndexInDexRegisterMap; 634a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 635a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return GetNumberOfLiveDexRegisters(dex_register_number); 636a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 637a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 638a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Special (invalid) Dex register map entry index meaning that there 639a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // is no index in the map for a given Dex register (i.e., it must 640a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // have been mapped to a DexRegisterLocation::Kind::kNone location). 641a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static constexpr size_t kInvalidIndexInDexRegisterMap = -1; 642a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 643a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain static constexpr int kFixedSize = 0; 644a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 645a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain MemoryRegion region_; 646a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 647a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain friend class CodeInfo; 648a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain friend class StackMapStream; 649a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain}; 650a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 65109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky// Represents bit range of bit-packed integer field. 65209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky// We reuse the idea from ULEB128p1 to support encoding of -1 (aka 0xFFFFFFFF). 65309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky// If min_value is set to -1, we implicitly subtract one from any loaded value, 65409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky// and add one to any stored value. This is generalized to any negative values. 65509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky// In other words, min_value acts as a base and the stored value is added to it. 65609ed09866da6d8c7448ef297c148bfa577a247c2David Srbeckystruct FieldEncoding { 65709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky FieldEncoding(size_t start_offset, size_t end_offset, int32_t min_value = 0) 65809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky : start_offset_(start_offset), end_offset_(end_offset), min_value_(min_value) { 65909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky DCHECK_LE(start_offset_, end_offset_); 66009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky DCHECK_LE(BitSize(), 32u); 66109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 66209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 66309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE size_t BitSize() const { return end_offset_ - start_offset_; } 66409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 66509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE int32_t Load(const MemoryRegion& region) const { 66609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky DCHECK_LE(end_offset_, region.size_in_bits()); 66709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const size_t bit_count = BitSize(); 66809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (bit_count == 0) { 66909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky // Do not touch any memory if the range is empty. 67009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return min_value_; 67109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 67209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint8_t* address = region.start() + start_offset_ / kBitsPerByte; 67309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const uint32_t shift = start_offset_ & (kBitsPerByte - 1); 67409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky // Load the value (reading only the strictly needed bytes). 67509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const uint32_t load_bit_count = shift + bit_count; 67609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t value = *address++ >> shift; 67709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (load_bit_count > 8) { 67809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky value |= static_cast<uint32_t>(*address++) << (8 - shift); 67909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (load_bit_count > 16) { 68009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky value |= static_cast<uint32_t>(*address++) << (16 - shift); 68109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (load_bit_count > 24) { 68209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky value |= static_cast<uint32_t>(*address++) << (24 - shift); 68309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (load_bit_count > 32) { 68409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky value |= static_cast<uint32_t>(*address++) << (32 - shift); 68509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 68609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 68709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 68809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 68909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky // Clear unwanted most significant bits. 69009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t clear_bit_count = 32 - bit_count; 69109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky value = (value << clear_bit_count) >> clear_bit_count; 69209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return value + min_value_; 69309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 69409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 69509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE void Store(MemoryRegion region, int32_t value) const { 69609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky region.StoreBits(start_offset_, value - min_value_, BitSize()); 69709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky DCHECK_EQ(Load(region), value); 69809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 69909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 70009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky private: 70109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t start_offset_; 70209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t end_offset_; 70309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky int32_t min_value_; 70409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky}; 70509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 706f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdilclass StackMapEncoding { 707f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil public: 708f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMapEncoding() {} 709f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 71009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky // Set stack map bit layout based on given sizes. 71109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky // Returns the size of stack map in bytes. 71209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t SetFromSizes(size_t native_pc_max, 71309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t dex_pc_max, 71409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t dex_register_map_size, 71509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t inline_info_size, 71609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t register_mask_max, 71709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t stack_mask_bit_size) { 71809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t bit_offset = 0; 71909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky DCHECK_EQ(kNativePcBitOffset, bit_offset); 72009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky bit_offset += MinimumBitsToStore(native_pc_max); 72109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 72209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky dex_pc_bit_offset_ = dchecked_integral_cast<uint8_t>(bit_offset); 72309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky bit_offset += MinimumBitsToStore(1 /* kNoDexPc */ + dex_pc_max); 72409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 72509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky // We also need +1 for kNoDexRegisterMap, but since the size is strictly 72609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky // greater than any offset we might try to encode, we already implicitly have it. 72709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky dex_register_map_bit_offset_ = dchecked_integral_cast<uint8_t>(bit_offset); 72809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky bit_offset += MinimumBitsToStore(dex_register_map_size); 72909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 73009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky // We also need +1 for kNoInlineInfo, but since the inline_info_size is strictly 73109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky // greater than the offset we might try to encode, we already implicitly have it. 73209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky // If inline_info_size is zero, we can encode only kNoInlineInfo (in zero bits). 73309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky inline_info_bit_offset_ = dchecked_integral_cast<uint8_t>(bit_offset); 73409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (inline_info_size != 0) { 73509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky bit_offset += MinimumBitsToStore(dex_register_map_size + inline_info_size); 73609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 737f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 73809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky register_mask_bit_offset_ = dchecked_integral_cast<uint8_t>(bit_offset); 73909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky bit_offset += MinimumBitsToStore(register_mask_max); 740f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 74109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky stack_mask_bit_offset_ = dchecked_integral_cast<uint8_t>(bit_offset); 74209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky bit_offset += stack_mask_bit_size; 743f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 74409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return RoundUp(bit_offset, kBitsPerByte) / kBitsPerByte; 745f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 746f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 74709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE FieldEncoding GetNativePcEncoding() const { 74809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return FieldEncoding(kNativePcBitOffset, dex_pc_bit_offset_); 749f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 75009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE FieldEncoding GetDexPcEncoding() const { 75109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return FieldEncoding(dex_pc_bit_offset_, dex_register_map_bit_offset_, -1 /* min_value */); 752f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 75309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE FieldEncoding GetDexRegisterMapEncoding() const { 75409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return FieldEncoding(dex_register_map_bit_offset_, inline_info_bit_offset_, -1 /* min_value */); 755f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 75609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE FieldEncoding GetInlineInfoEncoding() const { 75709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return FieldEncoding(inline_info_bit_offset_, register_mask_bit_offset_, -1 /* min_value */); 758f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 75909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE FieldEncoding GetRegisterMaskEncoding() const { 76009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return FieldEncoding(register_mask_bit_offset_, stack_mask_bit_offset_); 76109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 76209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE size_t GetStackMaskBitOffset() const { 76309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky // The end offset is not encoded. It is implicitly the end of stack map entry. 76409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return stack_mask_bit_offset_; 765f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 766f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 76709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky void Dump(VariableIndentationOutputStream* vios) const; 76809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 769f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil private: 77009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky static constexpr size_t kNativePcBitOffset = 0; 77109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint8_t dex_pc_bit_offset_; 77209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint8_t dex_register_map_bit_offset_; 77309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint8_t inline_info_bit_offset_; 77409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint8_t register_mask_bit_offset_; 77509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint8_t stack_mask_bit_offset_; 776f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil}; 777f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil 77899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 77999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * A Stack Map holds compilation information for a specific PC necessary for: 78099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Mapping it to a dex PC, 78199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which stack entries are objects, 78299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing which registers hold objects, 78399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the inlining information, 78499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * - Knowing the values of dex registers. 78599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * 78699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form: 7871c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 78809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky * [native_pc_offset, dex_pc, dex_register_map_offset, inlining_info_offset, register_mask, 7891c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * stack_mask]. 79099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 79199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass StackMap { 79299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 793e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray StackMap() {} 794f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil explicit StackMap(MemoryRegion region) : region_(region) {} 795e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray 79609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE bool IsValid() const { return region_.pointer() != nullptr; } 79709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 79809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE uint32_t GetDexPc(const StackMapEncoding& encoding) const { 79909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return encoding.GetDexPcEncoding().Load(region_); 80009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 80199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 80209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE void SetDexPc(const StackMapEncoding& encoding, uint32_t dex_pc) { 80309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky encoding.GetDexPcEncoding().Store(region_, dex_pc); 804f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 80599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 80609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE uint32_t GetNativePcOffset(const StackMapEncoding& encoding) const { 80709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return encoding.GetNativePcEncoding().Load(region_); 808f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 80999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 81009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE void SetNativePcOffset(const StackMapEncoding& encoding, uint32_t native_pc_offset) { 81109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky encoding.GetNativePcEncoding().Store(region_, native_pc_offset); 812f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 81399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 81409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE uint32_t GetDexRegisterMapOffset(const StackMapEncoding& encoding) const { 81509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return encoding.GetDexRegisterMapEncoding().Load(region_); 816f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 81799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 81809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE void SetDexRegisterMapOffset(const StackMapEncoding& encoding, uint32_t offset) { 81909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky encoding.GetDexRegisterMapEncoding().Store(region_, offset); 820f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 82199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 82209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE uint32_t GetInlineDescriptorOffset(const StackMapEncoding& encoding) const { 82309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return encoding.GetInlineInfoEncoding().Load(region_); 824f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 82599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 82609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE void SetInlineDescriptorOffset(const StackMapEncoding& encoding, uint32_t offset) { 82709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky encoding.GetInlineInfoEncoding().Store(region_, offset); 828f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 82999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 83009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE uint32_t GetRegisterMask(const StackMapEncoding& encoding) const { 83109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return encoding.GetRegisterMaskEncoding().Load(region_); 832f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 83399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 83409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE void SetRegisterMask(const StackMapEncoding& encoding, uint32_t mask) { 83509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky encoding.GetRegisterMaskEncoding().Store(region_, mask); 836f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 83799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 83809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE size_t GetNumberOfStackMaskBits(const StackMapEncoding& encoding) const { 83909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return region_.size_in_bits() - encoding.GetStackMaskBitOffset(); 840f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 84199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 84209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE bool GetStackMaskBit(const StackMapEncoding& encoding, size_t index) const { 84309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return region_.LoadBit(encoding.GetStackMaskBitOffset() + index); 844f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil } 84599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 84609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE void SetStackMaskBit(const StackMapEncoding& encoding, size_t index, bool value) { 84709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky region_.StoreBit(encoding.GetStackMaskBitOffset() + index, value); 84899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 84999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 85009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE bool HasDexRegisterMap(const StackMapEncoding& encoding) const { 851f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return GetDexRegisterMapOffset(encoding) != kNoDexRegisterMap; 852442b46a087c389a91a0b51547ac9205058432364Roland Levillain } 853442b46a087c389a91a0b51547ac9205058432364Roland Levillain 85409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE bool HasInlineInfo(const StackMapEncoding& encoding) const { 855f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return GetInlineDescriptorOffset(encoding) != kNoInlineInfo; 85699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 85799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 85809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ALWAYS_INLINE bool Equals(const StackMap& other) const { 85909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return region_.pointer() == other.region_.pointer() && region_.size() == other.region_.size(); 86099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 86199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 8628f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko void Dump(VariableIndentationOutputStream* vios, 863f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain const CodeInfo& code_info, 86409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const CodeInfoEncoding& encoding, 865f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain uint32_t code_offset, 866f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain uint16_t number_of_dex_registers, 867f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain const std::string& header_suffix = "") const; 868f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain 869442b46a087c389a91a0b51547ac9205058432364Roland Levillain // Special (invalid) offset for the DexRegisterMapOffset field meaning 870442b46a087c389a91a0b51547ac9205058432364Roland Levillain // that there is no Dex register map for this stack map. 871442b46a087c389a91a0b51547ac9205058432364Roland Levillain static constexpr uint32_t kNoDexRegisterMap = -1; 872442b46a087c389a91a0b51547ac9205058432364Roland Levillain 873442b46a087c389a91a0b51547ac9205058432364Roland Levillain // Special (invalid) offset for the InlineDescriptorOffset field meaning 874442b46a087c389a91a0b51547ac9205058432364Roland Levillain // that there is no inline info for this stack map. 875442b46a087c389a91a0b51547ac9205058432364Roland Levillain static constexpr uint32_t kNoInlineInfo = -1; 876442b46a087c389a91a0b51547ac9205058432364Roland Levillain 87799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private: 878896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray static constexpr int kFixedSize = 0; 87999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 88099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 88199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 8823946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class StackMapStream; 88399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 88499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 88561b28a17d9b6e8e998103646e98e4a9772e11927David Srbeckyclass InlineInfoEncoding { 88661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky public: 88761b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky void SetFromSizes(size_t method_index_max, 88861b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky size_t dex_pc_max, 88961b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky size_t invoke_type_max, 89061b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky size_t dex_register_map_size) { 89161b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky total_bit_size_ = kMethodIndexBitOffset; 89261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky total_bit_size_ += MinimumBitsToStore(method_index_max); 89361b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky 89461b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky dex_pc_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_); 89561b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky total_bit_size_ += MinimumBitsToStore(1 /* kNoDexPc */ + dex_pc_max); 89661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky 89761b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky invoke_type_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_); 89861b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky total_bit_size_ += MinimumBitsToStore(invoke_type_max); 89961b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky 90061b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky // We also need +1 for kNoDexRegisterMap, but since the size is strictly 90161b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky // greater than any offset we might try to encode, we already implicitly have it. 90261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky dex_register_map_bit_offset_ = dchecked_integral_cast<uint8_t>(total_bit_size_); 90361b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky total_bit_size_ += MinimumBitsToStore(dex_register_map_size); 90461b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky } 90561b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky 90661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE FieldEncoding GetMethodIndexEncoding() const { 90761b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return FieldEncoding(kMethodIndexBitOffset, dex_pc_bit_offset_); 90861b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky } 90961b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE FieldEncoding GetDexPcEncoding() const { 91061b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return FieldEncoding(dex_pc_bit_offset_, invoke_type_bit_offset_, -1 /* min_value */); 91161b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky } 91261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE FieldEncoding GetInvokeTypeEncoding() const { 91361b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return FieldEncoding(invoke_type_bit_offset_, dex_register_map_bit_offset_); 91461b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky } 91561b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE FieldEncoding GetDexRegisterMapEncoding() const { 91661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return FieldEncoding(dex_register_map_bit_offset_, total_bit_size_, -1 /* min_value */); 91761b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky } 91861b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE size_t GetEntrySize() const { 91961b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return RoundUp(total_bit_size_, kBitsPerByte) / kBitsPerByte; 92061b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky } 92161b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky 92261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky void Dump(VariableIndentationOutputStream* vios) const; 92361b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky 92461b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky private: 92561b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky static constexpr uint8_t kIsLastBitOffset = 0; 92661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky static constexpr uint8_t kMethodIndexBitOffset = 1; 92761b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint8_t dex_pc_bit_offset_; 92861b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint8_t invoke_type_bit_offset_; 92961b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint8_t dex_register_map_bit_offset_; 93061b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint8_t total_bit_size_; 93161b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky}; 93261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky 933b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray/** 934b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray * Inline information for a specific PC. The information is of the form: 9351c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 93661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky * [is_last, method_index, dex_pc, invoke_type, dex_register_map_offset]+. 937b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray */ 938b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffrayclass InlineInfo { 939b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray public: 94061b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky explicit InlineInfo(MemoryRegion region) : region_(region) { 941b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 942b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 94361b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE uint32_t GetDepth(const InlineInfoEncoding& encoding) const { 94461b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky size_t depth = 0; 94561b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky while (!GetRegionAtDepth(encoding, depth++).LoadBit(0)) { } // Check is_last bit. 94661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return depth; 947b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 948b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 94961b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE void SetDepth(const InlineInfoEncoding& encoding, uint32_t depth) { 95061b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky DCHECK_GT(depth, 0u); 95161b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky for (size_t d = 0; d < depth; ++d) { 95261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky GetRegionAtDepth(encoding, d).StoreBit(0, d == depth - 1); // Set is_last bit. 95361b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky } 954b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 955b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 95661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE uint32_t GetMethodIndexAtDepth(const InlineInfoEncoding& encoding, 95761b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t depth) const { 95861b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return encoding.GetMethodIndexEncoding().Load(GetRegionAtDepth(encoding, depth)); 959b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 960b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 96161b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE void SetMethodIndexAtDepth(const InlineInfoEncoding& encoding, 96261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t depth, 96361b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t index) { 96461b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky encoding.GetMethodIndexEncoding().Store(GetRegionAtDepth(encoding, depth), index); 965b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 966b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 96761b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE uint32_t GetDexPcAtDepth(const InlineInfoEncoding& encoding, 96861b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t depth) const { 96961b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return encoding.GetDexPcEncoding().Load(GetRegionAtDepth(encoding, depth)); 970b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray } 971b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray 97261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE void SetDexPcAtDepth(const InlineInfoEncoding& encoding, 97361b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t depth, 97461b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t dex_pc) { 97561b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky encoding.GetDexPcEncoding().Store(GetRegionAtDepth(encoding, depth), dex_pc); 976b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray } 977b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray 97861b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE uint32_t GetInvokeTypeAtDepth(const InlineInfoEncoding& encoding, 97961b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t depth) const { 98061b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return encoding.GetInvokeTypeEncoding().Load(GetRegionAtDepth(encoding, depth)); 981b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 982b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 98361b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE void SetInvokeTypeAtDepth(const InlineInfoEncoding& encoding, 98461b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t depth, 98561b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t invoke_type) { 98661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky encoding.GetInvokeTypeEncoding().Store(GetRegionAtDepth(encoding, depth), invoke_type); 987b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 988b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 98961b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE uint32_t GetDexRegisterMapOffsetAtDepth(const InlineInfoEncoding& encoding, 99061b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t depth) const { 99161b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return encoding.GetDexRegisterMapEncoding().Load(GetRegionAtDepth(encoding, depth)); 992b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 993b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 99461b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE void SetDexRegisterMapOffsetAtDepth(const InlineInfoEncoding& encoding, 99561b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t depth, 99661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t offset) { 99761b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky encoding.GetDexRegisterMapEncoding().Store(GetRegionAtDepth(encoding, depth), offset); 998b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 999b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 100061b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE bool HasDexRegisterMapAtDepth(const InlineInfoEncoding& encoding, 100161b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t depth) const { 100261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return GetDexRegisterMapOffsetAtDepth(encoding, depth) != StackMap::kNoDexRegisterMap; 1003b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 1004b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 10058f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko void Dump(VariableIndentationOutputStream* vios, 100661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky const CodeInfo& info, 100761b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint16_t* number_of_dex_registers) const; 10081c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain 1009b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray private: 101061b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ALWAYS_INLINE MemoryRegion GetRegionAtDepth(const InlineInfoEncoding& encoding, 101161b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t depth) const { 101261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky size_t entry_size = encoding.GetEntrySize(); 101361b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky DCHECK_GT(entry_size, 0u); 101461b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return region_.Subregion(depth * entry_size, entry_size); 101561b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky } 1016b176d7c6c8c01a50317f837a78de5da57ee84fb2Nicolas Geoffray 1017b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray MemoryRegion region_; 1018b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray}; 101999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 102009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky// Most of the fields are encoded as ULEB128 to save space. 102109ed09866da6d8c7448ef297c148bfa577a247c2David Srbeckystruct CodeInfoEncoding { 102209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t non_header_size; 102309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t number_of_stack_maps; 102409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t stack_map_size_in_bytes; 102509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t number_of_location_catalog_entries; 102609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky StackMapEncoding stack_map_encoding; 102761b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky InlineInfoEncoding inline_info_encoding; 102809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint8_t header_size; 102909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 103009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky CodeInfoEncoding() { } 103109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 103209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky explicit CodeInfoEncoding(const void* data) { 103309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data); 103409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky non_header_size = DecodeUnsignedLeb128(&ptr); 103509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky number_of_stack_maps = DecodeUnsignedLeb128(&ptr); 103609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky stack_map_size_in_bytes = DecodeUnsignedLeb128(&ptr); 103709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky number_of_location_catalog_entries = DecodeUnsignedLeb128(&ptr); 103861b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky static_assert(alignof(StackMapEncoding) == 1, 103961b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky "StackMapEncoding should not require alignment"); 104009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky stack_map_encoding = *reinterpret_cast<const StackMapEncoding*>(ptr); 104109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky ptr += sizeof(StackMapEncoding); 104261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky if (stack_map_encoding.GetInlineInfoEncoding().BitSize() > 0) { 104361b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky static_assert(alignof(InlineInfoEncoding) == 1, 104461b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky "InlineInfoEncoding should not require alignment"); 104561b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky inline_info_encoding = *reinterpret_cast<const InlineInfoEncoding*>(ptr); 104661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky ptr += sizeof(InlineInfoEncoding); 104761b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky } else { 104861b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky inline_info_encoding = InlineInfoEncoding{}; // NOLINT. 104961b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky } 105009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky header_size = dchecked_integral_cast<uint8_t>(ptr - reinterpret_cast<const uint8_t*>(data)); 105109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 105209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 105309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky template<typename Vector> 105409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky void Compress(Vector* dest) const { 105509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky EncodeUnsignedLeb128(dest, non_header_size); 105609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky EncodeUnsignedLeb128(dest, number_of_stack_maps); 105709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky EncodeUnsignedLeb128(dest, stack_map_size_in_bytes); 105809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky EncodeUnsignedLeb128(dest, number_of_location_catalog_entries); 105961b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky const uint8_t* stack_map_ptr = reinterpret_cast<const uint8_t*>(&stack_map_encoding); 106061b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky dest->insert(dest->end(), stack_map_ptr, stack_map_ptr + sizeof(StackMapEncoding)); 106161b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky if (stack_map_encoding.GetInlineInfoEncoding().BitSize() > 0) { 106261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky const uint8_t* inline_info_ptr = reinterpret_cast<const uint8_t*>(&inline_info_encoding); 106361b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky dest->insert(dest->end(), inline_info_ptr, inline_info_ptr + sizeof(InlineInfoEncoding)); 106461b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky } 106509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky } 106609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky}; 106709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky 106899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray/** 106999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * Wrapper around all compiler information collected for a method. 107099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray * The information is of the form: 10711c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 107209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky * [CodeInfoEncoding, StackMap+, DexRegisterLocationCatalog+, DexRegisterMap+, InlineInfo*] 10731c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 107409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky * where CodeInfoEncoding is of the form: 10751c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain * 107609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky * [non_header_size, number_of_stack_maps, stack_map_size_in_bytes, 107709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky * number_of_location_catalog_entries, StackMapEncoding] 107899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray */ 107999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffrayclass CodeInfo { 108099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray public: 108109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky explicit CodeInfo(MemoryRegion region) : region_(region) { 1082896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray } 1083896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray 108409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky explicit CodeInfo(const void* data) { 108509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky CodeInfoEncoding encoding = CodeInfoEncoding(data); 108609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky region_ = MemoryRegion(const_cast<void*>(data), 108709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky encoding.header_size + encoding.non_header_size); 1088896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray } 1089896f8f7fe562f6e59119cb32531da9f0a5f13d18Nicolas Geoffray 109009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky CodeInfoEncoding ExtractEncoding() const { 109109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return CodeInfoEncoding(region_.start()); 1092004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray } 1093004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray 109409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky bool HasInlineInfo(const CodeInfoEncoding& encoding) const { 109509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return encoding.stack_map_encoding.GetInlineInfoEncoding().BitSize() > 0; 1096004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray } 1097004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray 109809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky DexRegisterLocationCatalog GetDexRegisterLocationCatalog(const CodeInfoEncoding& encoding) const { 1099a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return DexRegisterLocationCatalog(region_.Subregion( 1100f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetDexRegisterLocationCatalogOffset(encoding), 1101f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil GetDexRegisterLocationCatalogSize(encoding))); 1102a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 1103a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 110409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky StackMap GetStackMapAt(size_t i, const CodeInfoEncoding& encoding) const { 110509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t stack_map_size = encoding.stack_map_size_in_bytes; 1106f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return StackMap(GetStackMaps(encoding).Subregion(i * stack_map_size, stack_map_size)); 11073946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray } 11083946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray 110909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t GetNumberOfLocationCatalogEntries(const CodeInfoEncoding& encoding) const { 111009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return encoding.number_of_location_catalog_entries; 1111a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 1112a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 111309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t GetDexRegisterLocationCatalogSize(const CodeInfoEncoding& encoding) const { 1114f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return ComputeDexRegisterLocationCatalogSize(GetDexRegisterLocationCatalogOffset(encoding), 111509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky GetNumberOfLocationCatalogEntries(encoding)); 1116a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 1117a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 111809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t GetNumberOfStackMaps(const CodeInfoEncoding& encoding) const { 111909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return encoding.number_of_stack_maps; 112099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 112199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 112277a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // Get the size of all the stack maps of this CodeInfo object, in bytes. 112309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t GetStackMapsSize(const CodeInfoEncoding& encoding) const { 112409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return encoding.stack_map_size_in_bytes * GetNumberOfStackMaps(encoding); 112529ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain } 112629ba1b068fc9f5a8011782c147b1f7732928aac7Roland Levillain 112709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t GetDexRegisterLocationCatalogOffset(const CodeInfoEncoding& encoding) const { 112809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return GetStackMapsOffset(encoding) + GetStackMapsSize(encoding); 1129004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray } 1130004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray 113109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t GetDexRegisterMapsOffset(const CodeInfoEncoding& encoding) const { 1132f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil return GetDexRegisterLocationCatalogOffset(encoding) 1133f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil + GetDexRegisterLocationCatalogSize(encoding); 1134a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 1135a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 113609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t GetStackMapsOffset(const CodeInfoEncoding& encoding) const { 113709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return encoding.header_size; 11386530baf76ef7a62f2d76a6735ad461d7d59cf0e4Nicolas Geoffray } 11396530baf76ef7a62f2d76a6735ad461d7d59cf0e4Nicolas Geoffray 1140f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, 114109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const CodeInfoEncoding& encoding, 1142f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil uint32_t number_of_dex_registers) const { 114309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (!stack_map.HasDexRegisterMap(encoding.stack_map_encoding)) { 1144012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray return DexRegisterMap(); 1145012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray } else { 1146012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray uint32_t offset = GetDexRegisterMapsOffset(encoding) 114709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky + stack_map.GetDexRegisterMapOffset(encoding.stack_map_encoding); 114809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t size = ComputeDexRegisterMapSizeOf(encoding, offset, number_of_dex_registers); 1149012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray return DexRegisterMap(region_.Subregion(offset, size)); 1150012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray } 115199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 115299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 1153b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray // Return the `DexRegisterMap` pointed by `inline_info` at depth `depth`. 1154b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth, 1155b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray InlineInfo inline_info, 115609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const CodeInfoEncoding& encoding, 1157b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray uint32_t number_of_dex_registers) const { 115861b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky if (!inline_info.HasDexRegisterMapAtDepth(encoding.inline_info_encoding, depth)) { 1159012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray return DexRegisterMap(); 1160012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray } else { 116161b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky uint32_t offset = GetDexRegisterMapsOffset(encoding) + 116261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky inline_info.GetDexRegisterMapOffsetAtDepth(encoding.inline_info_encoding, depth); 116309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t size = ComputeDexRegisterMapSizeOf(encoding, offset, number_of_dex_registers); 1164012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray return DexRegisterMap(region_.Subregion(offset, size)); 1165012fc4e9d9b66b3ffb7838b0e29dadbb4863ee69Nicolas Geoffray } 1166b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray } 1167b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray 116809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky InlineInfo GetInlineInfoOf(StackMap stack_map, const CodeInfoEncoding& encoding) const { 116909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky DCHECK(stack_map.HasInlineInfo(encoding.stack_map_encoding)); 117009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t offset = stack_map.GetInlineDescriptorOffset(encoding.stack_map_encoding) 1171f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil + GetDexRegisterMapsOffset(encoding); 117261b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return InlineInfo(region_.Subregion(offset, region_.size() - offset)); 117399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 117499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 117509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky StackMap GetStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const { 117609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky for (size_t i = 0, e = GetNumberOfStackMaps(encoding); i < e; ++i) { 1177f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMap stack_map = GetStackMapAt(i, encoding); 117809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (stack_map.GetDexPc(encoding.stack_map_encoding) == dex_pc) { 117999ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return stack_map; 118099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 118199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 1182e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray return StackMap(); 118399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 118499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 118577a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // Searches the stack map list backwards because catch stack maps are stored 118677a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // at the end. 118709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky StackMap GetCatchStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const { 118809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky for (size_t i = GetNumberOfStackMaps(encoding); i > 0; --i) { 118977a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil StackMap stack_map = GetStackMapAt(i - 1, encoding); 119009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (stack_map.GetDexPc(encoding.stack_map_encoding) == dex_pc) { 119177a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil return stack_map; 119277a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil } 119377a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil } 119477a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil return StackMap(); 119577a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil } 119677a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil 119709ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky StackMap GetOsrStackMapForDexPc(uint32_t dex_pc, const CodeInfoEncoding& encoding) const { 119809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t e = GetNumberOfStackMaps(encoding); 1199b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (e == 0) { 1200b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // There cannot be OSR stack map if there is no stack map. 1201b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return StackMap(); 1202b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 1203b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // Walk over all stack maps. If two consecutive stack maps are identical, then we 1204b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // have found a stack map suitable for OSR. 120509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const StackMapEncoding& stack_map_encoding = encoding.stack_map_encoding; 1206b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray for (size_t i = 0; i < e - 1; ++i) { 1207b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray StackMap stack_map = GetStackMapAt(i, encoding); 120809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (stack_map.GetDexPc(stack_map_encoding) == dex_pc) { 1209b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray StackMap other = GetStackMapAt(i + 1, encoding); 121009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (other.GetDexPc(stack_map_encoding) == dex_pc && 121109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky other.GetNativePcOffset(stack_map_encoding) == 121209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky stack_map.GetNativePcOffset(stack_map_encoding)) { 121309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky DCHECK_EQ(other.GetDexRegisterMapOffset(stack_map_encoding), 121409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky stack_map.GetDexRegisterMapOffset(stack_map_encoding)); 121509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky DCHECK(!stack_map.HasInlineInfo(stack_map_encoding)); 1216b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray if (i < e - 2) { 1217b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray // Make sure there are not three identical stack maps following each other. 121809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky DCHECK_NE(stack_map.GetNativePcOffset(stack_map_encoding), 121909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky GetStackMapAt(i + 2, encoding).GetNativePcOffset(stack_map_encoding)); 1220b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 1221b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return stack_map; 1222b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 1223b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 1224b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 1225b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray return StackMap(); 1226b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray } 1227b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray 1228f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset, 122909ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const CodeInfoEncoding& encoding) const { 123077a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // TODO: Safepoint stack maps are sorted by native_pc_offset but catch stack 123177a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // maps are not. If we knew that the method does not have try/catch, 123277a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // we could do binary search. 123309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky for (size_t i = 0, e = GetNumberOfStackMaps(encoding); i < e; ++i) { 1234f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMap stack_map = GetStackMapAt(i, encoding); 123509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (stack_map.GetNativePcOffset(encoding.stack_map_encoding) == native_pc_offset) { 123699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return stack_map; 123799ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 123899ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 1239e12997fbce8e22431be58cac9db2535f7b4a7ac3Nicolas Geoffray return StackMap(); 124099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray } 124199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 1242f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain // Dump this CodeInfo object on `os`. `code_offset` is the (absolute) 1243f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain // native PC of the compiled method and `number_of_dex_registers` the 1244f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain // number of Dex virtual registers used in this method. If 1245f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain // `dump_stack_maps` is true, also dump the stack maps and the 1246f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain // associated Dex register maps. 12478f1e08af6172781f91a17fce0a5a4183a9f70aa9Vladimir Marko void Dump(VariableIndentationOutputStream* vios, 1248f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain uint32_t code_offset, 1249f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain uint16_t number_of_dex_registers, 1250f2650d1f957b158496de8016bc43fb575e81d6bcRoland Levillain bool dump_stack_maps) const; 1251004c230b4cfc856690c61faabc41864061813c88Nicolas Geoffray 125299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray private: 125309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky MemoryRegion GetStackMaps(const CodeInfoEncoding& encoding) const { 125499ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray return region_.size() == 0 125599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray ? MemoryRegion() 125609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky : region_.Subregion(GetStackMapsOffset(encoding), GetStackMapsSize(encoding)); 1257a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 1258a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 1259a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Compute the size of the Dex register map associated to the stack map at 1260a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // `dex_register_map_offset_in_code_info`. 126109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky size_t ComputeDexRegisterMapSizeOf(const CodeInfoEncoding& encoding, 126209ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t dex_register_map_offset_in_code_info, 1263a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint16_t number_of_dex_registers) const { 1264a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Offset where the actual mapping data starts within art::DexRegisterMap. 1265a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t location_mapping_data_offset_in_dex_register_map = 1266a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterMap::GetLocationMappingDataOffset(number_of_dex_registers); 1267a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Create a temporary art::DexRegisterMap to be able to call 1268a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // art::DexRegisterMap::GetNumberOfLiveDexRegisters and 1269a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterMap dex_register_map_without_locations( 1270a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain MemoryRegion(region_.Subregion(dex_register_map_offset_in_code_info, 1271a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain location_mapping_data_offset_in_dex_register_map))); 1272a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t number_of_live_dex_registers = 1273a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain dex_register_map_without_locations.GetNumberOfLiveDexRegisters(number_of_dex_registers); 1274a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t location_mapping_data_size_in_bits = 127509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky DexRegisterMap::SingleEntrySizeInBits(GetNumberOfLocationCatalogEntries(encoding)) 1276a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain * number_of_live_dex_registers; 1277a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t location_mapping_data_size_in_bytes = 1278a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain RoundUp(location_mapping_data_size_in_bits, kBitsPerByte) / kBitsPerByte; 1279a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t dex_register_map_size = 1280a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain location_mapping_data_offset_in_dex_register_map + location_mapping_data_size_in_bytes; 1281a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain return dex_register_map_size; 1282a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } 1283a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 1284a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Compute the size of a Dex register location catalog starting at offset `origin` 1285a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // in `region_` and containing `number_of_dex_locations` entries. 1286a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t ComputeDexRegisterLocationCatalogSize(uint32_t origin, 1287a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain uint32_t number_of_dex_locations) const { 1288a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // TODO: Ideally, we would like to use art::DexRegisterLocationCatalog::Size or 1289a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // art::DexRegisterLocationCatalog::FindLocationOffset, but the 1290a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // DexRegisterLocationCatalog is not yet built. Try to factor common code. 1291a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain size_t offset = origin + DexRegisterLocationCatalog::kFixedSize; 1292a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain 1293a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Skip the first `number_of_dex_locations - 1` entries. 1294a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain for (uint16_t i = 0; i < number_of_dex_locations; ++i) { 1295a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Read the first next byte and inspect its first 3 bits to decide 1296a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // whether it is a short or a large location. 1297a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocationCatalog::ShortLocation first_byte = 1298a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain region_.LoadUnaligned<DexRegisterLocationCatalog::ShortLocation>(offset); 1299a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocation::Kind kind = 1300a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain DexRegisterLocationCatalog::ExtractKindFromShortLocation(first_byte); 1301a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain if (DexRegisterLocation::IsShortLocationKind(kind)) { 1302a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Short location. Skip the current byte. 1303a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain offset += DexRegisterLocationCatalog::SingleShortEntrySize(); 1304a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain } else { 1305a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain // Large location. Skip the 5 next bytes. 1306a552e1c0584b8ab63150510286478c68cdbce13fRoland Levillain offset += DexRegisterLocationCatalog::SingleLargeEntrySize(); 1307a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 1308a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 1309a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain size_t size = offset - origin; 1310a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain return size; 1311a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain } 1312a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain 131399ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray MemoryRegion region_; 13143946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray friend class StackMapStream; 131599ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray}; 131699ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 13171c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain#undef ELEMENT_BYTE_OFFSET_AFTER 13181c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain#undef ELEMENT_BIT_OFFSET_AFTER 13191c1da4398cca9a828dea885ca1be12adf961d3a3Roland Levillain 132099ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray} // namespace art 132199ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray 132299ea58cc68b51837c065f4a2a54efbf208dd76faNicolas Geoffray#endif // ART_RUNTIME_STACK_MAP_H_ 1323