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