blob: 4e7c3f4f9f4a8c1391009ce76444eaa3aedc6377 [file] [log] [blame]
Nicolas Geoffray004c2302015-03-20 10:06:38 +00001/*
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
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010019#include <stdint.h>
20
Nicolas Geoffray5d37c152017-01-12 13:25:19 +000021#include "art_method.h"
Roland Levillain0396ed72015-05-27 15:12:19 +010022#include "indenter.h"
Nicolas Geoffray5d37c152017-01-12 13:25:19 +000023#include "scoped_thread_state_change-inl.h"
Roland Levillain0396ed72015-05-27 15:12:19 +010024
Nicolas Geoffray004c2302015-03-20 10:06:38 +000025namespace art {
26
Roland Levillaina552e1c2015-03-26 15:01:03 +000027constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
Nicolas Geoffray004c2302015-03-20 10:06:38 +000028constexpr uint32_t StackMap::kNoDexRegisterMap;
29constexpr uint32_t StackMap::kNoInlineInfo;
30
David Srbecky7dc11782016-02-25 13:23:56 +000031std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation::Kind& kind) {
32 using Kind = DexRegisterLocation::Kind;
33 switch (kind) {
34 case Kind::kNone:
35 return stream << "none";
36 case Kind::kInStack:
37 return stream << "in stack";
38 case Kind::kInRegister:
39 return stream << "in register";
40 case Kind::kInRegisterHigh:
41 return stream << "in register high";
42 case Kind::kInFpuRegister:
43 return stream << "in fpu register";
44 case Kind::kInFpuRegisterHigh:
45 return stream << "in fpu register high";
46 case Kind::kConstant:
47 return stream << "as constant";
48 case Kind::kInStackLargeOffset:
49 return stream << "in stack (large offset)";
50 case Kind::kConstantLargeValue:
51 return stream << "as constant (large value)";
52 }
53 return stream << "Kind<" << static_cast<uint32_t>(kind) << ">";
54}
55
Roland Levillain1c1da432015-07-16 11:54:44 +010056DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(
57 uint16_t dex_register_number,
58 uint16_t number_of_dex_registers,
59 const CodeInfo& code_info,
David Srbecky09ed0982016-02-12 21:58:43 +000060 const CodeInfoEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +000061 DexRegisterLocationCatalog dex_register_location_catalog =
David Brazdilf677ebf2015-05-29 16:29:43 +010062 code_info.GetDexRegisterLocationCatalog(enc);
Roland Levillaina552e1c2015-03-26 15:01:03 +000063 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
64 dex_register_number,
65 number_of_dex_registers,
David Srbecky09ed0982016-02-12 21:58:43 +000066 code_info.GetNumberOfLocationCatalogEntries(enc));
Roland Levillaina552e1c2015-03-26 15:01:03 +000067 return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index);
68}
69
70DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number,
71 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +010072 const CodeInfo& code_info,
David Srbecky09ed0982016-02-12 21:58:43 +000073 const CodeInfoEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +000074 DexRegisterLocationCatalog dex_register_location_catalog =
David Brazdilf677ebf2015-05-29 16:29:43 +010075 code_info.GetDexRegisterLocationCatalog(enc);
Roland Levillaina552e1c2015-03-26 15:01:03 +000076 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
77 dex_register_number,
78 number_of_dex_registers,
David Srbecky09ed0982016-02-12 21:58:43 +000079 code_info.GetNumberOfLocationCatalogEntries(enc));
Roland Levillaina552e1c2015-03-26 15:01:03 +000080 return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index);
81}
82
Roland Levillaina552e1c2015-03-26 15:01:03 +000083static void DumpRegisterMapping(std::ostream& os,
84 size_t dex_register_num,
85 DexRegisterLocation location,
86 const std::string& prefix = "v",
87 const std::string& suffix = "") {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +010088 os << prefix << dex_register_num << ": "
David Srbecky7dc11782016-02-25 13:23:56 +000089 << location.GetInternalKind()
Vladimir Marko8f1e08a2015-06-26 12:06:30 +010090 << " (" << location.GetValue() << ")" << suffix << '\n';
Roland Levillain0396ed72015-05-27 15:12:19 +010091}
92
David Srbecky09ed0982016-02-12 21:58:43 +000093void StackMapEncoding::Dump(VariableIndentationOutputStream* vios) const {
94 vios->Stream()
95 << "StackMapEncoding"
96 << " (native_pc_bit_offset=" << static_cast<uint32_t>(kNativePcBitOffset)
97 << ", dex_pc_bit_offset=" << static_cast<uint32_t>(dex_pc_bit_offset_)
98 << ", dex_register_map_bit_offset=" << static_cast<uint32_t>(dex_register_map_bit_offset_)
99 << ", inline_info_bit_offset=" << static_cast<uint32_t>(inline_info_bit_offset_)
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800100 << ", register_mask_bit_offset=" << static_cast<uint32_t>(register_mask_index_bit_offset_)
David Srbecky45aa5982016-03-18 02:15:09 +0000101 << ", stack_mask_index_bit_offset=" << static_cast<uint32_t>(stack_mask_index_bit_offset_)
102 << ", total_bit_size=" << static_cast<uint32_t>(total_bit_size_)
David Srbecky09ed0982016-02-12 21:58:43 +0000103 << ")\n";
104}
105
David Srbecky61b28a12016-02-25 21:55:03 +0000106void InlineInfoEncoding::Dump(VariableIndentationOutputStream* vios) const {
107 vios->Stream()
108 << "InlineInfoEncoding"
109 << " (method_index_bit_offset=" << static_cast<uint32_t>(kMethodIndexBitOffset)
110 << ", dex_pc_bit_offset=" << static_cast<uint32_t>(dex_pc_bit_offset_)
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000111 << ", extra_data_bit_offset=" << static_cast<uint32_t>(extra_data_bit_offset_)
David Srbecky61b28a12016-02-25 21:55:03 +0000112 << ", dex_register_map_bit_offset=" << static_cast<uint32_t>(dex_register_map_bit_offset_)
113 << ", total_bit_size=" << static_cast<uint32_t>(total_bit_size_)
114 << ")\n";
115}
116
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100117void CodeInfo::Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +0100118 uint32_t code_offset,
Roland Levillain0396ed72015-05-27 15:12:19 +0100119 uint16_t number_of_dex_registers,
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800120 bool dump_stack_maps,
121 InstructionSet instruction_set) const {
David Srbecky09ed0982016-02-12 21:58:43 +0000122 CodeInfoEncoding encoding = ExtractEncoding();
123 size_t number_of_stack_maps = GetNumberOfStackMaps(encoding);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100124 vios->Stream()
David Srbecky09ed0982016-02-12 21:58:43 +0000125 << "Optimized CodeInfo (number_of_dex_registers=" << number_of_dex_registers
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100126 << ", number_of_stack_maps=" << number_of_stack_maps
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100127 << ")\n";
128 ScopedIndentation indent1(vios);
David Srbecky09ed0982016-02-12 21:58:43 +0000129 encoding.stack_map_encoding.Dump(vios);
David Srbecky61b28a12016-02-25 21:55:03 +0000130 if (HasInlineInfo(encoding)) {
131 encoding.inline_info_encoding.Dump(vios);
132 }
Roland Levillaina552e1c2015-03-26 15:01:03 +0000133 // Display the Dex register location catalog.
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100134 GetDexRegisterLocationCatalog(encoding).Dump(vios, *this);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000135 // Display stack maps along with (live) Dex register maps.
Roland Levillain0396ed72015-05-27 15:12:19 +0100136 if (dump_stack_maps) {
137 for (size_t i = 0; i < number_of_stack_maps; ++i) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100138 StackMap stack_map = GetStackMapAt(i, encoding);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100139 stack_map.Dump(vios,
David Brazdilf677ebf2015-05-29 16:29:43 +0100140 *this,
141 encoding,
142 code_offset,
143 number_of_dex_registers,
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800144 instruction_set,
David Brazdilf677ebf2015-05-29 16:29:43 +0100145 " " + std::to_string(i));
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000146 }
147 }
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100148 // TODO: Dump the stack map's inline information? We need to know more from the caller:
149 // we need to know the number of dex registers for each inlined method.
150}
151
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100152void DexRegisterLocationCatalog::Dump(VariableIndentationOutputStream* vios,
153 const CodeInfo& code_info) {
David Srbecky09ed0982016-02-12 21:58:43 +0000154 CodeInfoEncoding encoding = code_info.ExtractEncoding();
155 size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
David Brazdilf677ebf2015-05-29 16:29:43 +0100156 size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize(encoding);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100157 vios->Stream()
Roland Levillain0396ed72015-05-27 15:12:19 +0100158 << "DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
159 << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
160 for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
161 DexRegisterLocation location = GetDexRegisterLocation(i);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100162 ScopedIndentation indent1(vios);
163 DumpRegisterMapping(vios->Stream(), i, location, "entry ");
Roland Levillain0396ed72015-05-27 15:12:19 +0100164 }
165}
166
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100167void DexRegisterMap::Dump(VariableIndentationOutputStream* vios,
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100168 const CodeInfo& code_info,
169 uint16_t number_of_dex_registers) const {
David Srbecky09ed0982016-02-12 21:58:43 +0000170 CodeInfoEncoding encoding = code_info.ExtractEncoding();
171 size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries(encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100172 // TODO: Display the bit mask of live Dex registers.
173 for (size_t j = 0; j < number_of_dex_registers; ++j) {
174 if (IsDexRegisterLive(j)) {
175 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
176 j, number_of_dex_registers, number_of_location_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100177 DexRegisterLocation location = GetDexRegisterLocation(j,
178 number_of_dex_registers,
179 code_info,
180 encoding);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100181 ScopedIndentation indent1(vios);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100182 DumpRegisterMapping(
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100183 vios->Stream(), j, location, "v",
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100184 "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
185 }
186 }
187}
188
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100189void StackMap::Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +0100190 const CodeInfo& code_info,
David Srbecky09ed0982016-02-12 21:58:43 +0000191 const CodeInfoEncoding& encoding,
Roland Levillainf2650d12015-05-28 14:53:28 +0100192 uint32_t code_offset,
193 uint16_t number_of_dex_registers,
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800194 InstructionSet instruction_set,
Roland Levillainf2650d12015-05-28 14:53:28 +0100195 const std::string& header_suffix) const {
David Srbecky09ed0982016-02-12 21:58:43 +0000196 StackMapEncoding stack_map_encoding = encoding.stack_map_encoding;
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800197 const uint32_t pc_offset = GetNativePcOffset(stack_map_encoding, instruction_set);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100198 vios->Stream()
199 << "StackMap" << header_suffix
200 << std::hex
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800201 << " [native_pc=0x" << code_offset + pc_offset << "]"
David Srbecky45aa5982016-03-18 02:15:09 +0000202 << " [entry_size=0x" << encoding.stack_map_encoding.BitSize() << " bits]"
David Srbecky09ed0982016-02-12 21:58:43 +0000203 << " (dex_pc=0x" << GetDexPc(stack_map_encoding)
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800204 << ", native_pc_offset=0x" << pc_offset
David Srbecky09ed0982016-02-12 21:58:43 +0000205 << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset(stack_map_encoding)
206 << ", inline_info_offset=0x" << GetInlineDescriptorOffset(stack_map_encoding)
Mathieu Chartier1a20b682017-01-31 14:25:16 -0800207 << ", register_mask=0x" << code_info.GetRegisterMaskOf(encoding, *this)
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100208 << std::dec
209 << ", stack_mask=0b";
David Srbecky45aa5982016-03-18 02:15:09 +0000210 BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, *this);
211 for (size_t i = 0, e = encoding.stack_mask_size_in_bits; i < e; ++i) {
212 vios->Stream() << stack_mask.LoadBit(e - i - 1);
Roland Levillainf2650d12015-05-28 14:53:28 +0100213 }
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100214 vios->Stream() << ")\n";
David Srbecky09ed0982016-02-12 21:58:43 +0000215 if (HasDexRegisterMap(stack_map_encoding)) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100216 DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(
217 *this, encoding, number_of_dex_registers);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100218 dex_register_map.Dump(vios, code_info, number_of_dex_registers);
Roland Levillainf2650d12015-05-28 14:53:28 +0100219 }
David Srbecky09ed0982016-02-12 21:58:43 +0000220 if (HasInlineInfo(stack_map_encoding)) {
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100221 InlineInfo inline_info = code_info.GetInlineInfoOf(*this, encoding);
222 // We do not know the length of the dex register maps of inlined frames
223 // at this level, so we just pass null to `InlineInfo::Dump` to tell
224 // it not to look at these maps.
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100225 inline_info.Dump(vios, code_info, nullptr);
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100226 }
Roland Levillainf2650d12015-05-28 14:53:28 +0100227}
228
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100229void InlineInfo::Dump(VariableIndentationOutputStream* vios,
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100230 const CodeInfo& code_info,
231 uint16_t number_of_dex_registers[]) const {
David Srbecky61b28a12016-02-25 21:55:03 +0000232 InlineInfoEncoding inline_info_encoding = code_info.ExtractEncoding().inline_info_encoding;
233 vios->Stream() << "InlineInfo with depth "
234 << static_cast<uint32_t>(GetDepth(inline_info_encoding))
235 << "\n";
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100236
David Srbecky61b28a12016-02-25 21:55:03 +0000237 for (size_t i = 0; i < GetDepth(inline_info_encoding); ++i) {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100238 vios->Stream()
239 << " At depth " << i
240 << std::hex
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000241 << " (dex_pc=0x" << GetDexPcAtDepth(inline_info_encoding, i);
242 if (EncodesArtMethodAtDepth(inline_info_encoding, i)) {
243 ScopedObjectAccess soa(Thread::Current());
244 vios->Stream() << ", method=" << GetArtMethodAtDepth(inline_info_encoding, i)->PrettyMethod();
245 } else {
246 vios->Stream()
247 << std::dec
248 << ", method_index=" << GetMethodIndexAtDepth(inline_info_encoding, i);
249 }
250 vios->Stream() << ")\n";
David Srbecky61b28a12016-02-25 21:55:03 +0000251 if (HasDexRegisterMapAtDepth(inline_info_encoding, i) && (number_of_dex_registers != nullptr)) {
David Srbecky09ed0982016-02-12 21:58:43 +0000252 CodeInfoEncoding encoding = code_info.ExtractEncoding();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100253 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100254 code_info.GetDexRegisterMapAtDepth(i, *this, encoding, number_of_dex_registers[i]);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100255 ScopedIndentation indent1(vios);
256 dex_register_map.Dump(vios, code_info, number_of_dex_registers[i]);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100257 }
258 }
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000259}
260
261} // namespace art