• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 namespace art {
25 
26 constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
27 constexpr uint32_t StackMap::kNoDexRegisterMap;
28 constexpr uint32_t StackMap::kNoInlineInfo;
29 
operator <<(std::ostream & stream,const DexRegisterLocation::Kind & kind)30 std::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 
GetLocationInternalKind(uint16_t dex_register_number,uint16_t number_of_dex_registers,const CodeInfo & code_info,const CodeInfoEncoding & enc) const55 DexRegisterLocation::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 
GetDexRegisterLocation(uint16_t dex_register_number,uint16_t number_of_dex_registers,const CodeInfo & code_info,const CodeInfoEncoding & enc) const69 DexRegisterLocation 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 
DumpRegisterMapping(std::ostream & os,size_t dex_register_num,DexRegisterLocation location,const std::string & prefix="v",const std::string & suffix="")82 static 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 
Dump(VariableIndentationOutputStream * vios) const92 void 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 
Dump(VariableIndentationOutputStream * vios) const104 void 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 
Dump(VariableIndentationOutputStream * vios,uint32_t code_offset,uint16_t number_of_dex_registers,bool dump_stack_maps) const115 void 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 
Dump(VariableIndentationOutputStream * vios,const CodeInfo & code_info)148 void 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 
Dump(VariableIndentationOutputStream * vios,const CodeInfo & code_info,uint16_t number_of_dex_registers) const163 void 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 
Dump(VariableIndentationOutputStream * vios,const CodeInfo & code_info,const CodeInfoEncoding & encoding,uint32_t code_offset,uint16_t number_of_dex_registers,const std::string & header_suffix) const185 void 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 
Dump(VariableIndentationOutputStream * vios,const CodeInfo & code_info,uint16_t number_of_dex_registers[]) const221 void 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