1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "stack_map.h" 18 19#include <stdint.h> 20 21#include "indenter.h" 22#include "invoke_type.h" 23 24namespace art { 25 26constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex; 27constexpr uint32_t StackMap::kNoDexRegisterMap; 28constexpr uint32_t StackMap::kNoInlineInfo; 29 30std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation::Kind& kind) { 31 using Kind = DexRegisterLocation::Kind; 32 switch (kind) { 33 case Kind::kNone: 34 return stream << "none"; 35 case Kind::kInStack: 36 return stream << "in stack"; 37 case Kind::kInRegister: 38 return stream << "in register"; 39 case Kind::kInRegisterHigh: 40 return stream << "in register high"; 41 case Kind::kInFpuRegister: 42 return stream << "in fpu register"; 43 case Kind::kInFpuRegisterHigh: 44 return stream << "in fpu register high"; 45 case Kind::kConstant: 46 return stream << "as constant"; 47 case Kind::kInStackLargeOffset: 48 return stream << "in stack (large offset)"; 49 case Kind::kConstantLargeValue: 50 return stream << "as constant (large value)"; 51 } 52 return stream << "Kind<" << static_cast<uint32_t>(kind) << ">"; 53} 54 55DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind( 56 uint16_t dex_register_number, 57 uint16_t number_of_dex_registers, 58 const CodeInfo& code_info, 59 const CodeInfoEncoding& enc) const { 60 DexRegisterLocationCatalog dex_register_location_catalog = 61 code_info.GetDexRegisterLocationCatalog(enc); 62 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex( 63 dex_register_number, 64 number_of_dex_registers, 65 code_info.GetNumberOfLocationCatalogEntries(enc)); 66 return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index); 67} 68 69DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number, 70 uint16_t number_of_dex_registers, 71 const CodeInfo& code_info, 72 const CodeInfoEncoding& enc) const { 73 DexRegisterLocationCatalog dex_register_location_catalog = 74 code_info.GetDexRegisterLocationCatalog(enc); 75 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex( 76 dex_register_number, 77 number_of_dex_registers, 78 code_info.GetNumberOfLocationCatalogEntries(enc)); 79 return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index); 80} 81 82static void DumpRegisterMapping(std::ostream& os, 83 size_t dex_register_num, 84 DexRegisterLocation location, 85 const std::string& prefix = "v", 86 const std::string& suffix = "") { 87 os << prefix << dex_register_num << ": " 88 << location.GetInternalKind() 89 << " (" << location.GetValue() << ")" << suffix << '\n'; 90} 91 92void StackMapEncoding::Dump(VariableIndentationOutputStream* vios) const { 93 vios->Stream() 94 << "StackMapEncoding" 95 << " (native_pc_bit_offset=" << static_cast<uint32_t>(kNativePcBitOffset) 96 << ", dex_pc_bit_offset=" << static_cast<uint32_t>(dex_pc_bit_offset_) 97 << ", dex_register_map_bit_offset=" << static_cast<uint32_t>(dex_register_map_bit_offset_) 98 << ", inline_info_bit_offset=" << static_cast<uint32_t>(inline_info_bit_offset_) 99 << ", register_mask_bit_offset=" << static_cast<uint32_t>(register_mask_bit_offset_) 100 << ", stack_mask_bit_offset=" << static_cast<uint32_t>(stack_mask_bit_offset_) 101 << ")\n"; 102} 103 104void InlineInfoEncoding::Dump(VariableIndentationOutputStream* vios) const { 105 vios->Stream() 106 << "InlineInfoEncoding" 107 << " (method_index_bit_offset=" << static_cast<uint32_t>(kMethodIndexBitOffset) 108 << ", dex_pc_bit_offset=" << static_cast<uint32_t>(dex_pc_bit_offset_) 109 << ", invoke_type_bit_offset=" << static_cast<uint32_t>(invoke_type_bit_offset_) 110 << ", dex_register_map_bit_offset=" << static_cast<uint32_t>(dex_register_map_bit_offset_) 111 << ", total_bit_size=" << static_cast<uint32_t>(total_bit_size_) 112 << ")\n"; 113} 114 115void CodeInfo::Dump(VariableIndentationOutputStream* vios, 116 uint32_t code_offset, 117 uint16_t number_of_dex_registers, 118 bool dump_stack_maps) const { 119 CodeInfoEncoding encoding = ExtractEncoding(); 120 size_t number_of_stack_maps = GetNumberOfStackMaps(encoding); 121 vios->Stream() 122 << "Optimized CodeInfo (number_of_dex_registers=" << number_of_dex_registers 123 << ", number_of_stack_maps=" << number_of_stack_maps 124 << ")\n"; 125 ScopedIndentation indent1(vios); 126 encoding.stack_map_encoding.Dump(vios); 127 if (HasInlineInfo(encoding)) { 128 encoding.inline_info_encoding.Dump(vios); 129 } 130 // Display the Dex register location catalog. 131 GetDexRegisterLocationCatalog(encoding).Dump(vios, *this); 132 // Display stack maps along with (live) Dex register maps. 133 if (dump_stack_maps) { 134 for (size_t i = 0; i < number_of_stack_maps; ++i) { 135 StackMap stack_map = GetStackMapAt(i, encoding); 136 stack_map.Dump(vios, 137 *this, 138 encoding, 139 code_offset, 140 number_of_dex_registers, 141 " " + std::to_string(i)); 142 } 143 } 144 // TODO: Dump the stack map's inline information? We need to know more from the caller: 145 // we need to know the number of dex registers for each inlined method. 146} 147 148void DexRegisterLocationCatalog::Dump(VariableIndentationOutputStream* vios, 149 const CodeInfo& code_info) { 150 CodeInfoEncoding encoding = code_info.ExtractEncoding(); 151 size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding); 152 size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize(encoding); 153 vios->Stream() 154 << "DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries 155 << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n"; 156 for (size_t i = 0; i < number_of_location_catalog_entries; ++i) { 157 DexRegisterLocation location = GetDexRegisterLocation(i); 158 ScopedIndentation indent1(vios); 159 DumpRegisterMapping(vios->Stream(), i, location, "entry "); 160 } 161} 162 163void DexRegisterMap::Dump(VariableIndentationOutputStream* vios, 164 const CodeInfo& code_info, 165 uint16_t number_of_dex_registers) const { 166 CodeInfoEncoding encoding = code_info.ExtractEncoding(); 167 size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding); 168 // TODO: Display the bit mask of live Dex registers. 169 for (size_t j = 0; j < number_of_dex_registers; ++j) { 170 if (IsDexRegisterLive(j)) { 171 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex( 172 j, number_of_dex_registers, number_of_location_catalog_entries); 173 DexRegisterLocation location = GetDexRegisterLocation(j, 174 number_of_dex_registers, 175 code_info, 176 encoding); 177 ScopedIndentation indent1(vios); 178 DumpRegisterMapping( 179 vios->Stream(), j, location, "v", 180 "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]"); 181 } 182 } 183} 184 185void StackMap::Dump(VariableIndentationOutputStream* vios, 186 const CodeInfo& code_info, 187 const CodeInfoEncoding& encoding, 188 uint32_t code_offset, 189 uint16_t number_of_dex_registers, 190 const std::string& header_suffix) const { 191 StackMapEncoding stack_map_encoding = encoding.stack_map_encoding; 192 vios->Stream() 193 << "StackMap" << header_suffix 194 << std::hex 195 << " [native_pc=0x" << code_offset + GetNativePcOffset(stack_map_encoding) << "]" 196 << " (dex_pc=0x" << GetDexPc(stack_map_encoding) 197 << ", native_pc_offset=0x" << GetNativePcOffset(stack_map_encoding) 198 << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset(stack_map_encoding) 199 << ", inline_info_offset=0x" << GetInlineDescriptorOffset(stack_map_encoding) 200 << ", register_mask=0x" << GetRegisterMask(stack_map_encoding) 201 << std::dec 202 << ", stack_mask=0b"; 203 for (size_t i = 0, e = GetNumberOfStackMaskBits(stack_map_encoding); i < e; ++i) { 204 vios->Stream() << GetStackMaskBit(stack_map_encoding, e - i - 1); 205 } 206 vios->Stream() << ")\n"; 207 if (HasDexRegisterMap(stack_map_encoding)) { 208 DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf( 209 *this, encoding, number_of_dex_registers); 210 dex_register_map.Dump(vios, code_info, number_of_dex_registers); 211 } 212 if (HasInlineInfo(stack_map_encoding)) { 213 InlineInfo inline_info = code_info.GetInlineInfoOf(*this, encoding); 214 // We do not know the length of the dex register maps of inlined frames 215 // at this level, so we just pass null to `InlineInfo::Dump` to tell 216 // it not to look at these maps. 217 inline_info.Dump(vios, code_info, nullptr); 218 } 219} 220 221void InlineInfo::Dump(VariableIndentationOutputStream* vios, 222 const CodeInfo& code_info, 223 uint16_t number_of_dex_registers[]) const { 224 InlineInfoEncoding inline_info_encoding = code_info.ExtractEncoding().inline_info_encoding; 225 vios->Stream() << "InlineInfo with depth " 226 << static_cast<uint32_t>(GetDepth(inline_info_encoding)) 227 << "\n"; 228 229 for (size_t i = 0; i < GetDepth(inline_info_encoding); ++i) { 230 vios->Stream() 231 << " At depth " << i 232 << std::hex 233 << " (dex_pc=0x" << GetDexPcAtDepth(inline_info_encoding, i) 234 << std::dec 235 << ", method_index=" << GetMethodIndexAtDepth(inline_info_encoding, i) 236 << ", invoke_type=" << static_cast<InvokeType>(GetInvokeTypeAtDepth(inline_info_encoding, 237 i)) 238 << ")\n"; 239 if (HasDexRegisterMapAtDepth(inline_info_encoding, i) && (number_of_dex_registers != nullptr)) { 240 CodeInfoEncoding encoding = code_info.ExtractEncoding(); 241 DexRegisterMap dex_register_map = 242 code_info.GetDexRegisterMapAtDepth(i, *this, encoding, number_of_dex_registers[i]); 243 ScopedIndentation indent1(vios); 244 dex_register_map.Dump(vios, code_info, number_of_dex_registers[i]); 245 } 246 } 247} 248 249} // namespace art 250