1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_OAT_STACK_MAP_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_OAT_STACK_MAP_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <limits> 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h" 23*795d594fSAndroid Build Coastguard Worker #include "base/array_ref.h" 24*795d594fSAndroid Build Coastguard Worker #include "base/bit_memory_region.h" 25*795d594fSAndroid Build Coastguard Worker #include "base/bit_table.h" 26*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h" 27*795d594fSAndroid Build Coastguard Worker #include "base/globals.h" 28*795d594fSAndroid Build Coastguard Worker #include "base/logging.h" 29*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 30*795d594fSAndroid Build Coastguard Worker #include "base/memory_region.h" 31*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h" 32*795d594fSAndroid Build Coastguard Worker #include "dex_register_location.h" 33*795d594fSAndroid Build Coastguard Worker #include "quick/quick_method_frame_info.h" 34*795d594fSAndroid Build Coastguard Worker 35*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 36*795d594fSAndroid Build Coastguard Worker 37*795d594fSAndroid Build Coastguard Worker namespace linker { 38*795d594fSAndroid Build Coastguard Worker class CodeInfoTableDeduper; 39*795d594fSAndroid Build Coastguard Worker } // namespace linker 40*795d594fSAndroid Build Coastguard Worker 41*795d594fSAndroid Build Coastguard Worker class OatQuickMethodHeader; 42*795d594fSAndroid Build Coastguard Worker class VariableIndentationOutputStream; 43*795d594fSAndroid Build Coastguard Worker 44*795d594fSAndroid Build Coastguard Worker // Size of a frame slot, in bytes. This constant is a signed value, 45*795d594fSAndroid Build Coastguard Worker // to please the compiler in arithmetic operations involving int32_t 46*795d594fSAndroid Build Coastguard Worker // (signed) values. 47*795d594fSAndroid Build Coastguard Worker static constexpr ssize_t kFrameSlotSize = 4; 48*795d594fSAndroid Build Coastguard Worker 49*795d594fSAndroid Build Coastguard Worker // The delta compression of dex register maps means we need to scan the stackmaps backwards. 50*795d594fSAndroid Build Coastguard Worker // We compress the data in such a way so that there is an upper bound on the search distance. 51*795d594fSAndroid Build Coastguard Worker // Max distance 0 means each stack map must be fully defined and no scanning back is allowed. 52*795d594fSAndroid Build Coastguard Worker // If this value is changed, the oat file version should be incremented (for DCHECK to pass). 53*795d594fSAndroid Build Coastguard Worker static constexpr size_t kMaxDexRegisterMapSearchDistance = 32; 54*795d594fSAndroid Build Coastguard Worker 55*795d594fSAndroid Build Coastguard Worker class ArtMethod; 56*795d594fSAndroid Build Coastguard Worker class CodeInfo; 57*795d594fSAndroid Build Coastguard Worker class Stats; 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation& reg); 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker // Information on Dex register locations for a specific PC. 62*795d594fSAndroid Build Coastguard Worker // Effectively just a convenience wrapper for DexRegisterLocation vector. 63*795d594fSAndroid Build Coastguard Worker // If the size is small enough, it keeps the data on the stack. 64*795d594fSAndroid Build Coastguard Worker // TODO: Replace this with generic purpose "small-vector" implementation. 65*795d594fSAndroid Build Coastguard Worker class DexRegisterMap { 66*795d594fSAndroid Build Coastguard Worker public: 67*795d594fSAndroid Build Coastguard Worker using iterator = DexRegisterLocation*; 68*795d594fSAndroid Build Coastguard Worker using const_iterator = const DexRegisterLocation*; 69*795d594fSAndroid Build Coastguard Worker 70*795d594fSAndroid Build Coastguard Worker // Create map for given number of registers and initialize them to the given value. DexRegisterMap(size_t count,DexRegisterLocation value)71*795d594fSAndroid Build Coastguard Worker DexRegisterMap(size_t count, DexRegisterLocation value) : count_(count), regs_small_{} { 72*795d594fSAndroid Build Coastguard Worker if (count_ <= kSmallCount) { 73*795d594fSAndroid Build Coastguard Worker std::fill_n(regs_small_.begin(), count, value); 74*795d594fSAndroid Build Coastguard Worker } else { 75*795d594fSAndroid Build Coastguard Worker regs_large_.resize(count, value); 76*795d594fSAndroid Build Coastguard Worker } 77*795d594fSAndroid Build Coastguard Worker } 78*795d594fSAndroid Build Coastguard Worker data()79*795d594fSAndroid Build Coastguard Worker DexRegisterLocation* data() { 80*795d594fSAndroid Build Coastguard Worker return count_ <= kSmallCount ? regs_small_.data() : regs_large_.data(); 81*795d594fSAndroid Build Coastguard Worker } data()82*795d594fSAndroid Build Coastguard Worker const DexRegisterLocation* data() const { 83*795d594fSAndroid Build Coastguard Worker return count_ <= kSmallCount ? regs_small_.data() : regs_large_.data(); 84*795d594fSAndroid Build Coastguard Worker } 85*795d594fSAndroid Build Coastguard Worker begin()86*795d594fSAndroid Build Coastguard Worker iterator begin() { return data(); } end()87*795d594fSAndroid Build Coastguard Worker iterator end() { return data() + count_; } begin()88*795d594fSAndroid Build Coastguard Worker const_iterator begin() const { return data(); } end()89*795d594fSAndroid Build Coastguard Worker const_iterator end() const { return data() + count_; } size()90*795d594fSAndroid Build Coastguard Worker size_t size() const { return count_; } empty()91*795d594fSAndroid Build Coastguard Worker bool empty() const { return count_ == 0; } 92*795d594fSAndroid Build Coastguard Worker 93*795d594fSAndroid Build Coastguard Worker DexRegisterLocation& operator[](size_t index) { 94*795d594fSAndroid Build Coastguard Worker DCHECK_LT(index, count_); 95*795d594fSAndroid Build Coastguard Worker return data()[index]; 96*795d594fSAndroid Build Coastguard Worker } 97*795d594fSAndroid Build Coastguard Worker const DexRegisterLocation& operator[](size_t index) const { 98*795d594fSAndroid Build Coastguard Worker DCHECK_LT(index, count_); 99*795d594fSAndroid Build Coastguard Worker return data()[index]; 100*795d594fSAndroid Build Coastguard Worker } 101*795d594fSAndroid Build Coastguard Worker GetNumberOfLiveDexRegisters()102*795d594fSAndroid Build Coastguard Worker size_t GetNumberOfLiveDexRegisters() const { 103*795d594fSAndroid Build Coastguard Worker return std::count_if(begin(), end(), [](auto& loc) { return loc.IsLive(); }); 104*795d594fSAndroid Build Coastguard Worker } 105*795d594fSAndroid Build Coastguard Worker HasAnyLiveDexRegisters()106*795d594fSAndroid Build Coastguard Worker bool HasAnyLiveDexRegisters() const { 107*795d594fSAndroid Build Coastguard Worker return std::any_of(begin(), end(), [](auto& loc) { return loc.IsLive(); }); 108*795d594fSAndroid Build Coastguard Worker } 109*795d594fSAndroid Build Coastguard Worker 110*795d594fSAndroid Build Coastguard Worker void Dump(VariableIndentationOutputStream* vios) const; 111*795d594fSAndroid Build Coastguard Worker 112*795d594fSAndroid Build Coastguard Worker private: 113*795d594fSAndroid Build Coastguard Worker // Store the data inline if the number of registers is small to avoid memory allocations. 114*795d594fSAndroid Build Coastguard Worker // If count_ <= kSmallCount, we use the regs_small_ array, and regs_large_ otherwise. 115*795d594fSAndroid Build Coastguard Worker static constexpr size_t kSmallCount = 16; 116*795d594fSAndroid Build Coastguard Worker size_t count_; 117*795d594fSAndroid Build Coastguard Worker std::array<DexRegisterLocation, kSmallCount> regs_small_; 118*795d594fSAndroid Build Coastguard Worker dchecked_vector<DexRegisterLocation> regs_large_; 119*795d594fSAndroid Build Coastguard Worker }; 120*795d594fSAndroid Build Coastguard Worker 121*795d594fSAndroid Build Coastguard Worker /** 122*795d594fSAndroid Build Coastguard Worker * A Stack Map holds compilation information for a specific PC necessary for: 123*795d594fSAndroid Build Coastguard Worker * - Mapping it to a dex PC, 124*795d594fSAndroid Build Coastguard Worker * - Knowing which stack entries are objects, 125*795d594fSAndroid Build Coastguard Worker * - Knowing which registers hold objects, 126*795d594fSAndroid Build Coastguard Worker * - Knowing the inlining information, 127*795d594fSAndroid Build Coastguard Worker * - Knowing the values of dex registers. 128*795d594fSAndroid Build Coastguard Worker */ 129*795d594fSAndroid Build Coastguard Worker class StackMap : public BitTableAccessor<8> { 130*795d594fSAndroid Build Coastguard Worker public: 131*795d594fSAndroid Build Coastguard Worker enum Kind { 132*795d594fSAndroid Build Coastguard Worker Default = -1, 133*795d594fSAndroid Build Coastguard Worker Catch = 0, 134*795d594fSAndroid Build Coastguard Worker OSR = 1, 135*795d594fSAndroid Build Coastguard Worker Debug = 2, 136*795d594fSAndroid Build Coastguard Worker }; 137*795d594fSAndroid Build Coastguard Worker BIT_TABLE_HEADER(StackMap) 138*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(0, Kind) 139*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(1, PackedNativePc) 140*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(2, DexPc) 141*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(3, RegisterMaskIndex) 142*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(4, StackMaskIndex) 143*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(5, InlineInfoIndex) 144*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(6, DexRegisterMaskIndex) 145*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(7, DexRegisterMapIndex) 146*795d594fSAndroid Build Coastguard Worker GetNativePcOffset(InstructionSet instruction_set)147*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE uint32_t GetNativePcOffset(InstructionSet instruction_set) const { 148*795d594fSAndroid Build Coastguard Worker return UnpackNativePc(GetPackedNativePc(), instruction_set); 149*795d594fSAndroid Build Coastguard Worker } 150*795d594fSAndroid Build Coastguard Worker HasInlineInfo()151*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE bool HasInlineInfo() const { 152*795d594fSAndroid Build Coastguard Worker return HasInlineInfoIndex(); 153*795d594fSAndroid Build Coastguard Worker } 154*795d594fSAndroid Build Coastguard Worker HasDexRegisterMap()155*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE bool HasDexRegisterMap() const { 156*795d594fSAndroid Build Coastguard Worker return HasDexRegisterMapIndex(); 157*795d594fSAndroid Build Coastguard Worker } 158*795d594fSAndroid Build Coastguard Worker PackNativePc(uint32_t native_pc,InstructionSet isa)159*795d594fSAndroid Build Coastguard Worker static uint32_t PackNativePc(uint32_t native_pc, InstructionSet isa) { 160*795d594fSAndroid Build Coastguard Worker DCHECK_ALIGNED_PARAM(native_pc, GetInstructionSetInstructionAlignment(isa)); 161*795d594fSAndroid Build Coastguard Worker return native_pc / GetInstructionSetInstructionAlignment(isa); 162*795d594fSAndroid Build Coastguard Worker } 163*795d594fSAndroid Build Coastguard Worker UnpackNativePc(uint32_t packed_native_pc,InstructionSet isa)164*795d594fSAndroid Build Coastguard Worker static uint32_t UnpackNativePc(uint32_t packed_native_pc, InstructionSet isa) { 165*795d594fSAndroid Build Coastguard Worker uint32_t native_pc = packed_native_pc * GetInstructionSetInstructionAlignment(isa); 166*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(native_pc / GetInstructionSetInstructionAlignment(isa), packed_native_pc); 167*795d594fSAndroid Build Coastguard Worker return native_pc; 168*795d594fSAndroid Build Coastguard Worker } 169*795d594fSAndroid Build Coastguard Worker 170*795d594fSAndroid Build Coastguard Worker EXPORT void Dump(VariableIndentationOutputStream* vios, 171*795d594fSAndroid Build Coastguard Worker const CodeInfo& code_info, 172*795d594fSAndroid Build Coastguard Worker uint32_t code_offset, 173*795d594fSAndroid Build Coastguard Worker InstructionSet instruction_set) const; 174*795d594fSAndroid Build Coastguard Worker }; 175*795d594fSAndroid Build Coastguard Worker 176*795d594fSAndroid Build Coastguard Worker /** 177*795d594fSAndroid Build Coastguard Worker * Inline information for a specific PC. 178*795d594fSAndroid Build Coastguard Worker * The row referenced from the StackMap holds information at depth 0. 179*795d594fSAndroid Build Coastguard Worker * Following rows hold information for further depths. 180*795d594fSAndroid Build Coastguard Worker */ 181*795d594fSAndroid Build Coastguard Worker class InlineInfo : public BitTableAccessor<6> { 182*795d594fSAndroid Build Coastguard Worker public: 183*795d594fSAndroid Build Coastguard Worker BIT_TABLE_HEADER(InlineInfo) 184*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(0, IsLast) // Determines if there are further rows for further depths. 185*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(1, DexPc) 186*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(2, MethodInfoIndex) 187*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(3, ArtMethodHi) // High bits of ArtMethod*. 188*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(4, ArtMethodLo) // Low bits of ArtMethod*. 189*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(5, NumberOfDexRegisters) // Includes outer levels and the main method. 190*795d594fSAndroid Build Coastguard Worker 191*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kLast = -1; 192*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kMore = 0; 193*795d594fSAndroid Build Coastguard Worker EncodesArtMethod()194*795d594fSAndroid Build Coastguard Worker bool EncodesArtMethod() const { 195*795d594fSAndroid Build Coastguard Worker return HasArtMethodLo(); 196*795d594fSAndroid Build Coastguard Worker } 197*795d594fSAndroid Build Coastguard Worker GetArtMethod()198*795d594fSAndroid Build Coastguard Worker ArtMethod* GetArtMethod() const { 199*795d594fSAndroid Build Coastguard Worker uint64_t lo = GetArtMethodLo(); 200*795d594fSAndroid Build Coastguard Worker uint64_t hi = GetArtMethodHi(); 201*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<ArtMethod*>((hi << 32) | lo); 202*795d594fSAndroid Build Coastguard Worker } 203*795d594fSAndroid Build Coastguard Worker 204*795d594fSAndroid Build Coastguard Worker void Dump(VariableIndentationOutputStream* vios, 205*795d594fSAndroid Build Coastguard Worker const CodeInfo& info, 206*795d594fSAndroid Build Coastguard Worker const StackMap& stack_map) const; 207*795d594fSAndroid Build Coastguard Worker }; 208*795d594fSAndroid Build Coastguard Worker 209*795d594fSAndroid Build Coastguard Worker class StackMask : public BitTableAccessor<1> { 210*795d594fSAndroid Build Coastguard Worker public: 211*795d594fSAndroid Build Coastguard Worker BIT_TABLE_HEADER(StackMask) 212*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(0, Mask) 213*795d594fSAndroid Build Coastguard Worker }; 214*795d594fSAndroid Build Coastguard Worker 215*795d594fSAndroid Build Coastguard Worker class DexRegisterMask : public BitTableAccessor<1> { 216*795d594fSAndroid Build Coastguard Worker public: 217*795d594fSAndroid Build Coastguard Worker BIT_TABLE_HEADER(DexRegisterMask) 218*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(0, Mask) 219*795d594fSAndroid Build Coastguard Worker }; 220*795d594fSAndroid Build Coastguard Worker 221*795d594fSAndroid Build Coastguard Worker class DexRegisterMapInfo : public BitTableAccessor<1> { 222*795d594fSAndroid Build Coastguard Worker public: 223*795d594fSAndroid Build Coastguard Worker BIT_TABLE_HEADER(DexRegisterMapInfo) 224*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(0, CatalogueIndex) 225*795d594fSAndroid Build Coastguard Worker }; 226*795d594fSAndroid Build Coastguard Worker 227*795d594fSAndroid Build Coastguard Worker class DexRegisterInfo : public BitTableAccessor<2> { 228*795d594fSAndroid Build Coastguard Worker public: BIT_TABLE_HEADER(DexRegisterInfo)229*795d594fSAndroid Build Coastguard Worker BIT_TABLE_HEADER(DexRegisterInfo) 230*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(0, Kind) 231*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(1, PackedValue) 232*795d594fSAndroid Build Coastguard Worker 233*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE DexRegisterLocation GetLocation() const { 234*795d594fSAndroid Build Coastguard Worker DexRegisterLocation::Kind kind = static_cast<DexRegisterLocation::Kind>(GetKind()); 235*795d594fSAndroid Build Coastguard Worker return DexRegisterLocation(kind, UnpackValue(kind, GetPackedValue())); 236*795d594fSAndroid Build Coastguard Worker } 237*795d594fSAndroid Build Coastguard Worker PackValue(DexRegisterLocation::Kind kind,uint32_t value)238*795d594fSAndroid Build Coastguard Worker static uint32_t PackValue(DexRegisterLocation::Kind kind, uint32_t value) { 239*795d594fSAndroid Build Coastguard Worker uint32_t packed_value = value; 240*795d594fSAndroid Build Coastguard Worker if (kind == DexRegisterLocation::Kind::kInStack) { 241*795d594fSAndroid Build Coastguard Worker DCHECK(IsAligned<kFrameSlotSize>(packed_value)); 242*795d594fSAndroid Build Coastguard Worker packed_value /= kFrameSlotSize; 243*795d594fSAndroid Build Coastguard Worker } 244*795d594fSAndroid Build Coastguard Worker return packed_value; 245*795d594fSAndroid Build Coastguard Worker } 246*795d594fSAndroid Build Coastguard Worker UnpackValue(DexRegisterLocation::Kind kind,uint32_t packed_value)247*795d594fSAndroid Build Coastguard Worker static uint32_t UnpackValue(DexRegisterLocation::Kind kind, uint32_t packed_value) { 248*795d594fSAndroid Build Coastguard Worker uint32_t value = packed_value; 249*795d594fSAndroid Build Coastguard Worker if (kind == DexRegisterLocation::Kind::kInStack) { 250*795d594fSAndroid Build Coastguard Worker value *= kFrameSlotSize; 251*795d594fSAndroid Build Coastguard Worker } 252*795d594fSAndroid Build Coastguard Worker return value; 253*795d594fSAndroid Build Coastguard Worker } 254*795d594fSAndroid Build Coastguard Worker }; 255*795d594fSAndroid Build Coastguard Worker 256*795d594fSAndroid Build Coastguard Worker // Register masks tend to have many trailing zero bits (caller-saves are usually not encoded), 257*795d594fSAndroid Build Coastguard Worker // therefore it is worth encoding the mask as value+shift. 258*795d594fSAndroid Build Coastguard Worker class RegisterMask : public BitTableAccessor<2> { 259*795d594fSAndroid Build Coastguard Worker public: BIT_TABLE_HEADER(RegisterMask)260*795d594fSAndroid Build Coastguard Worker BIT_TABLE_HEADER(RegisterMask) 261*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(0, Value) 262*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(1, Shift) 263*795d594fSAndroid Build Coastguard Worker 264*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE uint32_t GetMask() const { 265*795d594fSAndroid Build Coastguard Worker return GetValue() << GetShift(); 266*795d594fSAndroid Build Coastguard Worker } 267*795d594fSAndroid Build Coastguard Worker }; 268*795d594fSAndroid Build Coastguard Worker 269*795d594fSAndroid Build Coastguard Worker // Method indices are not very dedup friendly. 270*795d594fSAndroid Build Coastguard Worker // Separating them greatly improves dedup efficiency of the other tables. 271*795d594fSAndroid Build Coastguard Worker class MethodInfo : public BitTableAccessor<3> { 272*795d594fSAndroid Build Coastguard Worker public: 273*795d594fSAndroid Build Coastguard Worker BIT_TABLE_HEADER(MethodInfo) 274*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(0, MethodIndex) 275*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(1, DexFileIndexKind) 276*795d594fSAndroid Build Coastguard Worker BIT_TABLE_COLUMN(2, DexFileIndex) 277*795d594fSAndroid Build Coastguard Worker 278*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kKindNonBCP = -1; 279*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kKindBCP = 0; 280*795d594fSAndroid Build Coastguard Worker 281*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kSameDexFile = -1; 282*795d594fSAndroid Build Coastguard Worker }; 283*795d594fSAndroid Build Coastguard Worker 284*795d594fSAndroid Build Coastguard Worker /** 285*795d594fSAndroid Build Coastguard Worker * Wrapper around all compiler information collected for a method. 286*795d594fSAndroid Build Coastguard Worker * See the Decode method at the end for the precise binary format. 287*795d594fSAndroid Build Coastguard Worker */ 288*795d594fSAndroid Build Coastguard Worker class CodeInfo { 289*795d594fSAndroid Build Coastguard Worker public: CodeInfo()290*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE CodeInfo() {} 291*795d594fSAndroid Build Coastguard Worker EXPORT ALWAYS_INLINE explicit CodeInfo(const uint8_t* data, size_t* num_read_bits = nullptr); 292*795d594fSAndroid Build Coastguard Worker EXPORT ALWAYS_INLINE explicit CodeInfo(const OatQuickMethodHeader* header); 293*795d594fSAndroid Build Coastguard Worker 294*795d594fSAndroid Build Coastguard Worker // The following methods decode only part of the data. 295*795d594fSAndroid Build Coastguard Worker static CodeInfo DecodeGcMasksOnly(const OatQuickMethodHeader* header); 296*795d594fSAndroid Build Coastguard Worker static CodeInfo DecodeInlineInfoOnly(const OatQuickMethodHeader* header); 297*795d594fSAndroid Build Coastguard Worker DecodeCodeSize(const uint8_t * code_info_data)298*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static uint32_t DecodeCodeSize(const uint8_t* code_info_data) { 299*795d594fSAndroid Build Coastguard Worker return DecodeHeaderOnly(code_info_data).code_size_; 300*795d594fSAndroid Build Coastguard Worker } 301*795d594fSAndroid Build Coastguard Worker DecodeFrameInfo(const uint8_t * code_info_data)302*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static QuickMethodFrameInfo DecodeFrameInfo(const uint8_t* code_info_data) { 303*795d594fSAndroid Build Coastguard Worker CodeInfo code_info = DecodeHeaderOnly(code_info_data); 304*795d594fSAndroid Build Coastguard Worker return QuickMethodFrameInfo(code_info.packed_frame_size_ * kStackAlignment, 305*795d594fSAndroid Build Coastguard Worker code_info.core_spill_mask_, 306*795d594fSAndroid Build Coastguard Worker code_info.fp_spill_mask_); 307*795d594fSAndroid Build Coastguard Worker } 308*795d594fSAndroid Build Coastguard Worker DecodeHeaderOnly(const uint8_t * code_info_data)309*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static CodeInfo DecodeHeaderOnly(const uint8_t* code_info_data) { 310*795d594fSAndroid Build Coastguard Worker CodeInfo code_info; 311*795d594fSAndroid Build Coastguard Worker BitMemoryReader reader(code_info_data); 312*795d594fSAndroid Build Coastguard Worker std::array<uint32_t, kNumHeaders> header = reader.ReadInterleavedVarints<kNumHeaders>(); 313*795d594fSAndroid Build Coastguard Worker ForEachHeaderField([&code_info, &header](size_t i, auto member_pointer) { 314*795d594fSAndroid Build Coastguard Worker code_info.*member_pointer = header[i]; 315*795d594fSAndroid Build Coastguard Worker }); 316*795d594fSAndroid Build Coastguard Worker return code_info; 317*795d594fSAndroid Build Coastguard Worker } 318*795d594fSAndroid Build Coastguard Worker GetStackMaps()319*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE const BitTable<StackMap>& GetStackMaps() const { 320*795d594fSAndroid Build Coastguard Worker return stack_maps_; 321*795d594fSAndroid Build Coastguard Worker } 322*795d594fSAndroid Build Coastguard Worker GetStackMapAt(size_t index)323*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE StackMap GetStackMapAt(size_t index) const { 324*795d594fSAndroid Build Coastguard Worker return stack_maps_.GetRow(index); 325*795d594fSAndroid Build Coastguard Worker } 326*795d594fSAndroid Build Coastguard Worker GetStackMask(size_t index)327*795d594fSAndroid Build Coastguard Worker BitMemoryRegion GetStackMask(size_t index) const { 328*795d594fSAndroid Build Coastguard Worker return stack_masks_.GetBitMemoryRegion(index); 329*795d594fSAndroid Build Coastguard Worker } 330*795d594fSAndroid Build Coastguard Worker GetStackMaskOf(const StackMap & stack_map)331*795d594fSAndroid Build Coastguard Worker BitMemoryRegion GetStackMaskOf(const StackMap& stack_map) const { 332*795d594fSAndroid Build Coastguard Worker uint32_t index = stack_map.GetStackMaskIndex(); 333*795d594fSAndroid Build Coastguard Worker return (index == StackMap::kNoValue) ? BitMemoryRegion() : GetStackMask(index); 334*795d594fSAndroid Build Coastguard Worker } 335*795d594fSAndroid Build Coastguard Worker GetRegisterMaskOf(const StackMap & stack_map)336*795d594fSAndroid Build Coastguard Worker uint32_t GetRegisterMaskOf(const StackMap& stack_map) const { 337*795d594fSAndroid Build Coastguard Worker uint32_t index = stack_map.GetRegisterMaskIndex(); 338*795d594fSAndroid Build Coastguard Worker return (index == StackMap::kNoValue) ? 0 : register_masks_.GetRow(index).GetMask(); 339*795d594fSAndroid Build Coastguard Worker } 340*795d594fSAndroid Build Coastguard Worker GetNumberOfLocationCatalogEntries()341*795d594fSAndroid Build Coastguard Worker uint32_t GetNumberOfLocationCatalogEntries() const { 342*795d594fSAndroid Build Coastguard Worker return dex_register_catalog_.NumRows(); 343*795d594fSAndroid Build Coastguard Worker } 344*795d594fSAndroid Build Coastguard Worker GetDexRegisterCatalogEntry(size_t index)345*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE DexRegisterLocation GetDexRegisterCatalogEntry(size_t index) const { 346*795d594fSAndroid Build Coastguard Worker return (index == StackMap::kNoValue) 347*795d594fSAndroid Build Coastguard Worker ? DexRegisterLocation::None() 348*795d594fSAndroid Build Coastguard Worker : dex_register_catalog_.GetRow(index).GetLocation(); 349*795d594fSAndroid Build Coastguard Worker } 350*795d594fSAndroid Build Coastguard Worker HasInlineInfo()351*795d594fSAndroid Build Coastguard Worker bool HasInlineInfo() const { 352*795d594fSAndroid Build Coastguard Worker return inline_infos_.NumRows() > 0; 353*795d594fSAndroid Build Coastguard Worker } 354*795d594fSAndroid Build Coastguard Worker GetNumberOfStackMaps()355*795d594fSAndroid Build Coastguard Worker uint32_t GetNumberOfStackMaps() const { 356*795d594fSAndroid Build Coastguard Worker return stack_maps_.NumRows(); 357*795d594fSAndroid Build Coastguard Worker } 358*795d594fSAndroid Build Coastguard Worker GetMethodInfoOf(InlineInfo inline_info)359*795d594fSAndroid Build Coastguard Worker MethodInfo GetMethodInfoOf(InlineInfo inline_info) const { 360*795d594fSAndroid Build Coastguard Worker return method_infos_.GetRow(inline_info.GetMethodInfoIndex()); 361*795d594fSAndroid Build Coastguard Worker } 362*795d594fSAndroid Build Coastguard Worker GetMethodIndexOf(InlineInfo inline_info)363*795d594fSAndroid Build Coastguard Worker uint32_t GetMethodIndexOf(InlineInfo inline_info) const { 364*795d594fSAndroid Build Coastguard Worker return GetMethodInfoOf(inline_info).GetMethodIndex(); 365*795d594fSAndroid Build Coastguard Worker } 366*795d594fSAndroid Build Coastguard Worker 367*795d594fSAndroid Build Coastguard Worker // Returns the dex registers for `stack_map`, ignoring any inlined dex registers. GetDexRegisterMapOf(StackMap stack_map)368*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE DexRegisterMap GetDexRegisterMapOf(StackMap stack_map) const { 369*795d594fSAndroid Build Coastguard Worker return GetDexRegisterMapOf(stack_map, /* first= */ 0, number_of_dex_registers_); 370*795d594fSAndroid Build Coastguard Worker } 371*795d594fSAndroid Build Coastguard Worker 372*795d594fSAndroid Build Coastguard Worker // Returns the dex register map of `inline_info`, and just those registers. GetInlineDexRegisterMapOf(StackMap stack_map,InlineInfo inline_info)373*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE DexRegisterMap GetInlineDexRegisterMapOf(StackMap stack_map, 374*795d594fSAndroid Build Coastguard Worker InlineInfo inline_info) const { 375*795d594fSAndroid Build Coastguard Worker if (stack_map.HasDexRegisterMap()) { 376*795d594fSAndroid Build Coastguard Worker DCHECK(stack_map.HasInlineInfoIndex()); 377*795d594fSAndroid Build Coastguard Worker uint32_t depth = inline_info.Row() - stack_map.GetInlineInfoIndex(); 378*795d594fSAndroid Build Coastguard Worker // The register counts are commutative and include all outer levels. 379*795d594fSAndroid Build Coastguard Worker // This allows us to determine the range [first, last) in just two lookups. 380*795d594fSAndroid Build Coastguard Worker // If we are at depth 0 (the first inlinee), the count from the main method is used. 381*795d594fSAndroid Build Coastguard Worker uint32_t first = (depth == 0) 382*795d594fSAndroid Build Coastguard Worker ? number_of_dex_registers_ 383*795d594fSAndroid Build Coastguard Worker : inline_infos_.GetRow(inline_info.Row() - 1).GetNumberOfDexRegisters(); 384*795d594fSAndroid Build Coastguard Worker uint32_t last = inline_info.GetNumberOfDexRegisters(); 385*795d594fSAndroid Build Coastguard Worker return GetDexRegisterMapOf(stack_map, first, last); 386*795d594fSAndroid Build Coastguard Worker } 387*795d594fSAndroid Build Coastguard Worker return DexRegisterMap(0, DexRegisterLocation::None()); 388*795d594fSAndroid Build Coastguard Worker } 389*795d594fSAndroid Build Coastguard Worker 390*795d594fSAndroid Build Coastguard Worker // Returns the dex register map of `stack_map` in the range the range [first, last). GetDexRegisterMapOf(StackMap stack_map,uint32_t first,uint32_t last)391*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, 392*795d594fSAndroid Build Coastguard Worker uint32_t first, 393*795d594fSAndroid Build Coastguard Worker uint32_t last) const { 394*795d594fSAndroid Build Coastguard Worker if (stack_map.HasDexRegisterMap()) { 395*795d594fSAndroid Build Coastguard Worker DCHECK_LE(first, last); 396*795d594fSAndroid Build Coastguard Worker DexRegisterMap map(last - first, DexRegisterLocation::Invalid()); 397*795d594fSAndroid Build Coastguard Worker DecodeDexRegisterMap(stack_map.Row(), first, &map); 398*795d594fSAndroid Build Coastguard Worker return map; 399*795d594fSAndroid Build Coastguard Worker } 400*795d594fSAndroid Build Coastguard Worker return DexRegisterMap(0, DexRegisterLocation::None()); 401*795d594fSAndroid Build Coastguard Worker } 402*795d594fSAndroid Build Coastguard Worker GetInlineInfosOf(StackMap stack_map)403*795d594fSAndroid Build Coastguard Worker BitTableRange<InlineInfo> GetInlineInfosOf(StackMap stack_map) const { 404*795d594fSAndroid Build Coastguard Worker uint32_t index = stack_map.GetInlineInfoIndex(); 405*795d594fSAndroid Build Coastguard Worker if (index != StackMap::kNoValue) { 406*795d594fSAndroid Build Coastguard Worker auto begin = inline_infos_.begin() + index; 407*795d594fSAndroid Build Coastguard Worker auto end = begin; 408*795d594fSAndroid Build Coastguard Worker while ((*end++).GetIsLast() == InlineInfo::kMore) { } 409*795d594fSAndroid Build Coastguard Worker return BitTableRange<InlineInfo>(begin, end); 410*795d594fSAndroid Build Coastguard Worker } else { 411*795d594fSAndroid Build Coastguard Worker return BitTableRange<InlineInfo>(); 412*795d594fSAndroid Build Coastguard Worker } 413*795d594fSAndroid Build Coastguard Worker } 414*795d594fSAndroid Build Coastguard Worker GetStackMapForDexPc(uint32_t dex_pc)415*795d594fSAndroid Build Coastguard Worker StackMap GetStackMapForDexPc(uint32_t dex_pc) const { 416*795d594fSAndroid Build Coastguard Worker for (StackMap stack_map : stack_maps_) { 417*795d594fSAndroid Build Coastguard Worker if (stack_map.GetDexPc() == dex_pc && stack_map.GetKind() != StackMap::Kind::Debug) { 418*795d594fSAndroid Build Coastguard Worker return stack_map; 419*795d594fSAndroid Build Coastguard Worker } 420*795d594fSAndroid Build Coastguard Worker } 421*795d594fSAndroid Build Coastguard Worker return stack_maps_.GetInvalidRow(); 422*795d594fSAndroid Build Coastguard Worker } 423*795d594fSAndroid Build Coastguard Worker GetCatchStackMapForDexPc(ArrayRef<const uint32_t> dex_pcs)424*795d594fSAndroid Build Coastguard Worker StackMap GetCatchStackMapForDexPc(ArrayRef<const uint32_t> dex_pcs) const { 425*795d594fSAndroid Build Coastguard Worker // Searches the stack map list backwards because catch stack maps are stored at the end. 426*795d594fSAndroid Build Coastguard Worker for (size_t i = GetNumberOfStackMaps(); i > 0; --i) { 427*795d594fSAndroid Build Coastguard Worker StackMap stack_map = GetStackMapAt(i - 1); 428*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(stack_map.GetKind() != StackMap::Kind::Catch)) { 429*795d594fSAndroid Build Coastguard Worker // Early break since we should have catch stack maps only at the end. 430*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) { 431*795d594fSAndroid Build Coastguard Worker for (size_t j = i - 1; j > 0; --j) { 432*795d594fSAndroid Build Coastguard Worker DCHECK(GetStackMapAt(j - 1).GetKind() != StackMap::Kind::Catch); 433*795d594fSAndroid Build Coastguard Worker } 434*795d594fSAndroid Build Coastguard Worker } 435*795d594fSAndroid Build Coastguard Worker break; 436*795d594fSAndroid Build Coastguard Worker } 437*795d594fSAndroid Build Coastguard Worker 438*795d594fSAndroid Build Coastguard Worker // Both the handler dex_pc and all of the inline dex_pcs have to match i.e. we want dex_pcs to 439*795d594fSAndroid Build Coastguard Worker // be [stack_map_dex_pc, inline_dex_pc_1, ..., inline_dex_pc_n]. 440*795d594fSAndroid Build Coastguard Worker if (stack_map.GetDexPc() != dex_pcs.front()) { 441*795d594fSAndroid Build Coastguard Worker continue; 442*795d594fSAndroid Build Coastguard Worker } 443*795d594fSAndroid Build Coastguard Worker 444*795d594fSAndroid Build Coastguard Worker const BitTableRange<InlineInfo>& inline_infos = GetInlineInfosOf(stack_map); 445*795d594fSAndroid Build Coastguard Worker if (inline_infos.size() == dex_pcs.size() - 1) { 446*795d594fSAndroid Build Coastguard Worker bool matching_dex_pcs = true; 447*795d594fSAndroid Build Coastguard Worker for (size_t inline_info_index = 0; inline_info_index < inline_infos.size(); 448*795d594fSAndroid Build Coastguard Worker ++inline_info_index) { 449*795d594fSAndroid Build Coastguard Worker if (inline_infos[inline_info_index].GetDexPc() != dex_pcs[inline_info_index + 1]) { 450*795d594fSAndroid Build Coastguard Worker matching_dex_pcs = false; 451*795d594fSAndroid Build Coastguard Worker break; 452*795d594fSAndroid Build Coastguard Worker } 453*795d594fSAndroid Build Coastguard Worker } 454*795d594fSAndroid Build Coastguard Worker if (matching_dex_pcs) { 455*795d594fSAndroid Build Coastguard Worker return stack_map; 456*795d594fSAndroid Build Coastguard Worker } 457*795d594fSAndroid Build Coastguard Worker } 458*795d594fSAndroid Build Coastguard Worker } 459*795d594fSAndroid Build Coastguard Worker return stack_maps_.GetInvalidRow(); 460*795d594fSAndroid Build Coastguard Worker } 461*795d594fSAndroid Build Coastguard Worker GetOsrStackMapForDexPc(uint32_t dex_pc)462*795d594fSAndroid Build Coastguard Worker StackMap GetOsrStackMapForDexPc(uint32_t dex_pc) const { 463*795d594fSAndroid Build Coastguard Worker for (StackMap stack_map : stack_maps_) { 464*795d594fSAndroid Build Coastguard Worker if (stack_map.GetDexPc() == dex_pc && stack_map.GetKind() == StackMap::Kind::OSR) { 465*795d594fSAndroid Build Coastguard Worker return stack_map; 466*795d594fSAndroid Build Coastguard Worker } 467*795d594fSAndroid Build Coastguard Worker } 468*795d594fSAndroid Build Coastguard Worker return stack_maps_.GetInvalidRow(); 469*795d594fSAndroid Build Coastguard Worker } 470*795d594fSAndroid Build Coastguard Worker 471*795d594fSAndroid Build Coastguard Worker EXPORT StackMap GetStackMapForNativePcOffset(uintptr_t pc, 472*795d594fSAndroid Build Coastguard Worker InstructionSet isa = kRuntimeQuickCodeISA) const; 473*795d594fSAndroid Build Coastguard Worker 474*795d594fSAndroid Build Coastguard Worker // Dump this CodeInfo object on `vios`. 475*795d594fSAndroid Build Coastguard Worker // `code_offset` is the (absolute) native PC of the compiled method. 476*795d594fSAndroid Build Coastguard Worker EXPORT void Dump(VariableIndentationOutputStream* vios, 477*795d594fSAndroid Build Coastguard Worker uint32_t code_offset, 478*795d594fSAndroid Build Coastguard Worker bool verbose, 479*795d594fSAndroid Build Coastguard Worker InstructionSet instruction_set) const; 480*795d594fSAndroid Build Coastguard Worker 481*795d594fSAndroid Build Coastguard Worker // Accumulate code info size statistics into the given Stats tree. 482*795d594fSAndroid Build Coastguard Worker EXPORT static void CollectSizeStats(const uint8_t* code_info, /*out*/ Stats& parent); 483*795d594fSAndroid Build Coastguard Worker 484*795d594fSAndroid Build Coastguard Worker template <uint32_t kFlag> HasFlag(const uint8_t * code_info_data)485*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static bool HasFlag(const uint8_t* code_info_data) { 486*795d594fSAndroid Build Coastguard Worker // Fast path - read just the one specific bit from the header. 487*795d594fSAndroid Build Coastguard Worker bool result; 488*795d594fSAndroid Build Coastguard Worker uint8_t varint = (*code_info_data) & MaxInt<uint8_t>(kVarintBits); 489*795d594fSAndroid Build Coastguard Worker if (LIKELY(varint <= kVarintMax)) { 490*795d594fSAndroid Build Coastguard Worker result = (varint & kFlag) != 0; 491*795d594fSAndroid Build Coastguard Worker } else { 492*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(varint, kVarintMax + 1); // Only up to 8 flags are supported for now. 493*795d594fSAndroid Build Coastguard Worker constexpr uint32_t bit_offset = kNumHeaders * kVarintBits + WhichPowerOf2(kFlag); 494*795d594fSAndroid Build Coastguard Worker result = (code_info_data[bit_offset / kBitsPerByte] & (1 << bit_offset % kBitsPerByte)) != 0; 495*795d594fSAndroid Build Coastguard Worker } 496*795d594fSAndroid Build Coastguard Worker // Slow path - dcheck that we got the correct result against the naive implementation. 497*795d594fSAndroid Build Coastguard Worker BitMemoryReader reader(code_info_data); 498*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(result, (reader.ReadInterleavedVarints<kNumHeaders>()[0] & kFlag) != 0); 499*795d594fSAndroid Build Coastguard Worker return result; 500*795d594fSAndroid Build Coastguard Worker } 501*795d594fSAndroid Build Coastguard Worker HasInlineInfo(const uint8_t * code_info_data)502*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static bool HasInlineInfo(const uint8_t* code_info_data) { 503*795d594fSAndroid Build Coastguard Worker return HasFlag<kHasInlineInfo>(code_info_data); 504*795d594fSAndroid Build Coastguard Worker } 505*795d594fSAndroid Build Coastguard Worker HasShouldDeoptimizeFlag(const uint8_t * code_info_data)506*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static bool HasShouldDeoptimizeFlag(const uint8_t* code_info_data) { 507*795d594fSAndroid Build Coastguard Worker return HasFlag<kHasShouldDeoptimizeFlag>(code_info_data); 508*795d594fSAndroid Build Coastguard Worker } 509*795d594fSAndroid Build Coastguard Worker IsBaseline(const uint8_t * code_info_data)510*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static bool IsBaseline(const uint8_t* code_info_data) { 511*795d594fSAndroid Build Coastguard Worker return HasFlag<kIsBaseline>(code_info_data); 512*795d594fSAndroid Build Coastguard Worker } 513*795d594fSAndroid Build Coastguard Worker IsDebuggable(const uint8_t * code_info_data)514*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static bool IsDebuggable(const uint8_t* code_info_data) { 515*795d594fSAndroid Build Coastguard Worker return HasFlag<kIsDebuggable>(code_info_data); 516*795d594fSAndroid Build Coastguard Worker } 517*795d594fSAndroid Build Coastguard Worker GetNumberOfDexRegisters()518*795d594fSAndroid Build Coastguard Worker uint32_t GetNumberOfDexRegisters() { 519*795d594fSAndroid Build Coastguard Worker return number_of_dex_registers_; 520*795d594fSAndroid Build Coastguard Worker } 521*795d594fSAndroid Build Coastguard Worker 522*795d594fSAndroid Build Coastguard Worker private: 523*795d594fSAndroid Build Coastguard Worker // Scan backward to determine dex register locations at given stack map. 524*795d594fSAndroid Build Coastguard Worker EXPORT void DecodeDexRegisterMap(uint32_t stack_map_index, 525*795d594fSAndroid Build Coastguard Worker uint32_t first_dex_register, 526*795d594fSAndroid Build Coastguard Worker /*out*/ DexRegisterMap* map) const; 527*795d594fSAndroid Build Coastguard Worker 528*795d594fSAndroid Build Coastguard Worker template<typename DecodeCallback> // (size_t index, BitTable<...>*, BitMemoryRegion). 529*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE CodeInfo(const uint8_t* data, size_t* num_read_bits, DecodeCallback callback); 530*795d594fSAndroid Build Coastguard Worker 531*795d594fSAndroid Build Coastguard Worker // Invokes the callback with index and member pointer of each header field. 532*795d594fSAndroid Build Coastguard Worker template<typename Callback> ForEachHeaderField(Callback callback)533*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static void ForEachHeaderField(Callback callback) { 534*795d594fSAndroid Build Coastguard Worker size_t index = 0; 535*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::flags_); 536*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::code_size_); 537*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::packed_frame_size_); 538*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::core_spill_mask_); 539*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::fp_spill_mask_); 540*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::number_of_dex_registers_); 541*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::bit_table_flags_); 542*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(index, kNumHeaders); 543*795d594fSAndroid Build Coastguard Worker } 544*795d594fSAndroid Build Coastguard Worker 545*795d594fSAndroid Build Coastguard Worker // Invokes the callback with index and member pointer of each BitTable field. 546*795d594fSAndroid Build Coastguard Worker template<typename Callback> ForEachBitTableField(Callback callback)547*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static void ForEachBitTableField(Callback callback) { 548*795d594fSAndroid Build Coastguard Worker size_t index = 0; 549*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::stack_maps_); 550*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::register_masks_); 551*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::stack_masks_); 552*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::inline_infos_); 553*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::method_infos_); 554*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::dex_register_masks_); 555*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::dex_register_maps_); 556*795d594fSAndroid Build Coastguard Worker callback(index++, &CodeInfo::dex_register_catalog_); 557*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(index, kNumBitTables); 558*795d594fSAndroid Build Coastguard Worker } 559*795d594fSAndroid Build Coastguard Worker HasBitTable(size_t i)560*795d594fSAndroid Build Coastguard Worker bool HasBitTable(size_t i) { return ((bit_table_flags_ >> i) & 1) != 0; } IsBitTableDeduped(size_t i)561*795d594fSAndroid Build Coastguard Worker bool IsBitTableDeduped(size_t i) { return ((bit_table_flags_ >> (kNumBitTables + i)) & 1) != 0; } SetBitTableDeduped(size_t i)562*795d594fSAndroid Build Coastguard Worker void SetBitTableDeduped(size_t i) { bit_table_flags_ |= 1 << (kNumBitTables + i); } HasDedupedBitTables()563*795d594fSAndroid Build Coastguard Worker bool HasDedupedBitTables() { return (bit_table_flags_ >> kNumBitTables) != 0u; } 564*795d594fSAndroid Build Coastguard Worker 565*795d594fSAndroid Build Coastguard Worker // NB: The first three flags should be the most common ones. 566*795d594fSAndroid Build Coastguard Worker // Maximum of 8 flags is supported right now (see the HasFlag method). 567*795d594fSAndroid Build Coastguard Worker enum Flags { 568*795d594fSAndroid Build Coastguard Worker kHasInlineInfo = 1 << 0, 569*795d594fSAndroid Build Coastguard Worker kHasShouldDeoptimizeFlag = 1 << 1, 570*795d594fSAndroid Build Coastguard Worker kIsBaseline = 1 << 2, 571*795d594fSAndroid Build Coastguard Worker kIsDebuggable = 1 << 3, 572*795d594fSAndroid Build Coastguard Worker }; 573*795d594fSAndroid Build Coastguard Worker 574*795d594fSAndroid Build Coastguard Worker // The CodeInfo starts with sequence of variable-length bit-encoded integers. 575*795d594fSAndroid Build Coastguard Worker // (Please see kVarintMax for more details about encoding). 576*795d594fSAndroid Build Coastguard Worker static constexpr size_t kNumHeaders = 7; 577*795d594fSAndroid Build Coastguard Worker uint32_t flags_ = 0; 578*795d594fSAndroid Build Coastguard Worker uint32_t code_size_ = 0; // The size of native PC range in bytes. 579*795d594fSAndroid Build Coastguard Worker uint32_t packed_frame_size_ = 0; // Frame size in kStackAlignment units. 580*795d594fSAndroid Build Coastguard Worker uint32_t core_spill_mask_ = 0; 581*795d594fSAndroid Build Coastguard Worker uint32_t fp_spill_mask_ = 0; 582*795d594fSAndroid Build Coastguard Worker uint32_t number_of_dex_registers_ = 0; 583*795d594fSAndroid Build Coastguard Worker uint32_t bit_table_flags_ = 0; 584*795d594fSAndroid Build Coastguard Worker 585*795d594fSAndroid Build Coastguard Worker // The encoded bit-tables follow the header. Based on the above flags field, 586*795d594fSAndroid Build Coastguard Worker // bit-tables might be omitted or replaced by relative bit-offset if deduped. 587*795d594fSAndroid Build Coastguard Worker static constexpr size_t kNumBitTables = 8; 588*795d594fSAndroid Build Coastguard Worker BitTable<StackMap> stack_maps_; 589*795d594fSAndroid Build Coastguard Worker BitTable<RegisterMask> register_masks_; 590*795d594fSAndroid Build Coastguard Worker BitTable<StackMask> stack_masks_; 591*795d594fSAndroid Build Coastguard Worker BitTable<InlineInfo> inline_infos_; 592*795d594fSAndroid Build Coastguard Worker BitTable<MethodInfo> method_infos_; 593*795d594fSAndroid Build Coastguard Worker BitTable<DexRegisterMask> dex_register_masks_; 594*795d594fSAndroid Build Coastguard Worker BitTable<DexRegisterMapInfo> dex_register_maps_; 595*795d594fSAndroid Build Coastguard Worker BitTable<DexRegisterInfo> dex_register_catalog_; 596*795d594fSAndroid Build Coastguard Worker 597*795d594fSAndroid Build Coastguard Worker friend class linker::CodeInfoTableDeduper; 598*795d594fSAndroid Build Coastguard Worker friend class StackMapStream; 599*795d594fSAndroid Build Coastguard Worker }; 600*795d594fSAndroid Build Coastguard Worker 601*795d594fSAndroid Build Coastguard Worker #undef ELEMENT_BYTE_OFFSET_AFTER 602*795d594fSAndroid Build Coastguard Worker #undef ELEMENT_BIT_OFFSET_AFTER 603*795d594fSAndroid Build Coastguard Worker 604*795d594fSAndroid Build Coastguard Worker } // namespace art 605*795d594fSAndroid Build Coastguard Worker 606*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_OAT_STACK_MAP_H_ 607