stack_map.cc revision 1c1da4398cca9a828dea885ca1be12adf961d3a3
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 30DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind( 31 uint16_t dex_register_number, 32 uint16_t number_of_dex_registers, 33 const CodeInfo& code_info, 34 const StackMapEncoding& enc) const { 35 DexRegisterLocationCatalog dex_register_location_catalog = 36 code_info.GetDexRegisterLocationCatalog(enc); 37 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex( 38 dex_register_number, 39 number_of_dex_registers, 40 code_info.GetNumberOfLocationCatalogEntries()); 41 return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index); 42} 43 44DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number, 45 uint16_t number_of_dex_registers, 46 const CodeInfo& code_info, 47 const StackMapEncoding& enc) const { 48 DexRegisterLocationCatalog dex_register_location_catalog = 49 code_info.GetDexRegisterLocationCatalog(enc); 50 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex( 51 dex_register_number, 52 number_of_dex_registers, 53 code_info.GetNumberOfLocationCatalogEntries()); 54 return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index); 55} 56 57uint32_t StackMap::LoadAt(size_t number_of_bytes, size_t offset, bool check_max) const { 58 if (number_of_bytes == 0u) { 59 DCHECK(!check_max); 60 return 0; 61 } else if (number_of_bytes == 1u) { 62 uint8_t value = region_.LoadUnaligned<uint8_t>(offset); 63 return (check_max && value == 0xFF) ? -1 : value; 64 } else if (number_of_bytes == 2u) { 65 uint16_t value = region_.LoadUnaligned<uint16_t>(offset); 66 return (check_max && value == 0xFFFF) ? -1 : value; 67 } else if (number_of_bytes == 3u) { 68 uint16_t low = region_.LoadUnaligned<uint16_t>(offset); 69 uint16_t high = region_.LoadUnaligned<uint8_t>(offset + sizeof(uint16_t)); 70 uint32_t value = (high << 16) + low; 71 return (check_max && value == 0xFFFFFF) ? -1 : value; 72 } else { 73 DCHECK_EQ(number_of_bytes, 4u); 74 return region_.LoadUnaligned<uint32_t>(offset); 75 } 76} 77 78void StackMap::StoreAt(size_t number_of_bytes, size_t offset, uint32_t value) const { 79 if (number_of_bytes == 0u) { 80 DCHECK_EQ(value, 0u); 81 } else if (number_of_bytes == 1u) { 82 region_.StoreUnaligned<uint8_t>(offset, value); 83 } else if (number_of_bytes == 2u) { 84 region_.StoreUnaligned<uint16_t>(offset, value); 85 } else if (number_of_bytes == 3u) { 86 region_.StoreUnaligned<uint16_t>(offset, Low16Bits(value)); 87 region_.StoreUnaligned<uint8_t>(offset + sizeof(uint16_t), High16Bits(value)); 88 } else { 89 region_.StoreUnaligned<uint32_t>(offset, value); 90 DCHECK_EQ(number_of_bytes, 4u); 91 } 92} 93 94static void DumpRegisterMapping(std::ostream& os, 95 size_t dex_register_num, 96 DexRegisterLocation location, 97 const std::string& prefix = "v", 98 const std::string& suffix = "") { 99 os << prefix << dex_register_num << ": " 100 << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind()) 101 << " (" << location.GetValue() << ")" << suffix << '\n'; 102} 103 104void CodeInfo::Dump(VariableIndentationOutputStream* vios, 105 uint32_t code_offset, 106 uint16_t number_of_dex_registers, 107 bool dump_stack_maps) const { 108 StackMapEncoding encoding = ExtractEncoding(); 109 uint32_t code_info_size = GetOverallSize(); 110 size_t number_of_stack_maps = GetNumberOfStackMaps(); 111 vios->Stream() 112 << "Optimized CodeInfo (size=" << code_info_size 113 << ", number_of_dex_registers=" << number_of_dex_registers 114 << ", number_of_stack_maps=" << number_of_stack_maps 115 << ", has_inline_info=" << encoding.HasInlineInfo() 116 << ", number_of_bytes_for_inline_info=" << encoding.NumberOfBytesForInlineInfo() 117 << ", number_of_bytes_for_dex_register_map=" << encoding.NumberOfBytesForDexRegisterMap() 118 << ", number_of_bytes_for_dex_pc=" << encoding.NumberOfBytesForDexPc() 119 << ", number_of_bytes_for_native_pc=" << encoding.NumberOfBytesForNativePc() 120 << ", number_of_bytes_for_register_mask=" << encoding.NumberOfBytesForRegisterMask() 121 << ")\n"; 122 ScopedIndentation indent1(vios); 123 // Display the Dex register location catalog. 124 GetDexRegisterLocationCatalog(encoding).Dump(vios, *this); 125 // Display stack maps along with (live) Dex register maps. 126 if (dump_stack_maps) { 127 for (size_t i = 0; i < number_of_stack_maps; ++i) { 128 StackMap stack_map = GetStackMapAt(i, encoding); 129 stack_map.Dump(vios, 130 *this, 131 encoding, 132 code_offset, 133 number_of_dex_registers, 134 " " + std::to_string(i)); 135 } 136 } 137 // TODO: Dump the stack map's inline information? We need to know more from the caller: 138 // we need to know the number of dex registers for each inlined method. 139} 140 141void DexRegisterLocationCatalog::Dump(VariableIndentationOutputStream* vios, 142 const CodeInfo& code_info) { 143 StackMapEncoding encoding = code_info.ExtractEncoding(); 144 size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(); 145 size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize(encoding); 146 vios->Stream() 147 << "DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries 148 << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n"; 149 for (size_t i = 0; i < number_of_location_catalog_entries; ++i) { 150 DexRegisterLocation location = GetDexRegisterLocation(i); 151 ScopedIndentation indent1(vios); 152 DumpRegisterMapping(vios->Stream(), i, location, "entry "); 153 } 154} 155 156void DexRegisterMap::Dump(VariableIndentationOutputStream* vios, 157 const CodeInfo& code_info, 158 uint16_t number_of_dex_registers) const { 159 StackMapEncoding encoding = code_info.ExtractEncoding(); 160 size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(); 161 // TODO: Display the bit mask of live Dex registers. 162 for (size_t j = 0; j < number_of_dex_registers; ++j) { 163 if (IsDexRegisterLive(j)) { 164 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex( 165 j, number_of_dex_registers, number_of_location_catalog_entries); 166 DexRegisterLocation location = GetDexRegisterLocation(j, 167 number_of_dex_registers, 168 code_info, 169 encoding); 170 ScopedIndentation indent1(vios); 171 DumpRegisterMapping( 172 vios->Stream(), j, location, "v", 173 "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]"); 174 } 175 } 176} 177 178void StackMap::Dump(VariableIndentationOutputStream* vios, 179 const CodeInfo& code_info, 180 const StackMapEncoding& encoding, 181 uint32_t code_offset, 182 uint16_t number_of_dex_registers, 183 const std::string& header_suffix) const { 184 vios->Stream() 185 << "StackMap" << header_suffix 186 << std::hex 187 << " [native_pc=0x" << code_offset + GetNativePcOffset(encoding) << "]" 188 << " (dex_pc=0x" << GetDexPc(encoding) 189 << ", native_pc_offset=0x" << GetNativePcOffset(encoding) 190 << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset(encoding) 191 << ", inline_info_offset=0x" << GetInlineDescriptorOffset(encoding) 192 << ", register_mask=0x" << GetRegisterMask(encoding) 193 << std::dec 194 << ", stack_mask=0b"; 195 MemoryRegion stack_mask = GetStackMask(encoding); 196 for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) { 197 vios->Stream() << stack_mask.LoadBit(e - i - 1); 198 } 199 vios->Stream() << ")\n"; 200 if (HasDexRegisterMap(encoding)) { 201 DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf( 202 *this, encoding, number_of_dex_registers); 203 dex_register_map.Dump(vios, code_info, number_of_dex_registers); 204 } 205 if (HasInlineInfo(encoding)) { 206 InlineInfo inline_info = code_info.GetInlineInfoOf(*this, encoding); 207 // We do not know the length of the dex register maps of inlined frames 208 // at this level, so we just pass null to `InlineInfo::Dump` to tell 209 // it not to look at these maps. 210 inline_info.Dump(vios, code_info, nullptr); 211 } 212} 213 214void InlineInfo::Dump(VariableIndentationOutputStream* vios, 215 const CodeInfo& code_info, 216 uint16_t number_of_dex_registers[]) const { 217 vios->Stream() << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n"; 218 219 for (size_t i = 0; i < GetDepth(); ++i) { 220 vios->Stream() 221 << " At depth " << i 222 << std::hex 223 << " (dex_pc=0x" << GetDexPcAtDepth(i) 224 << std::dec 225 << ", method_index=" << GetMethodIndexAtDepth(i) 226 << ", invoke_type=" << static_cast<InvokeType>(GetInvokeTypeAtDepth(i)) 227 << ")\n"; 228 if (HasDexRegisterMapAtDepth(i) && (number_of_dex_registers != nullptr)) { 229 StackMapEncoding encoding = code_info.ExtractEncoding(); 230 DexRegisterMap dex_register_map = 231 code_info.GetDexRegisterMapAtDepth(i, *this, encoding, number_of_dex_registers[i]); 232 ScopedIndentation indent1(vios); 233 dex_register_map.Dump(vios, code_info, number_of_dex_registers[i]); 234 } 235 } 236} 237 238} // namespace art 239