blob: 741cd906a877dc2f246f666a6bd4169c576a81d5 [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
Roland Levillain0396ed72015-05-27 15:12:19 +010021#include "indenter.h"
Nicolas Geoffray12bdb722015-06-17 09:44:43 +010022#include "invoke_type.h"
Roland Levillain0396ed72015-05-27 15:12:19 +010023
Nicolas Geoffray004c2302015-03-20 10:06:38 +000024namespace art {
25
Roland Levillaina552e1c2015-03-26 15:01:03 +000026constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
Nicolas Geoffray004c2302015-03-20 10:06:38 +000027constexpr uint32_t StackMap::kNoDexRegisterMap;
28constexpr uint32_t StackMap::kNoInlineInfo;
29
Roland Levillaina552e1c2015-03-26 15:01:03 +000030DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(uint16_t dex_register_number,
31 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +010032 const CodeInfo& code_info,
33 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +000034 DexRegisterLocationCatalog dex_register_location_catalog =
David Brazdilf677ebf2015-05-29 16:29:43 +010035 code_info.GetDexRegisterLocationCatalog(enc);
Roland Levillaina552e1c2015-03-26 15:01:03 +000036 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
37 dex_register_number,
38 number_of_dex_registers,
39 code_info.GetNumberOfDexRegisterLocationCatalogEntries());
40 return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index);
41}
42
43DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number,
44 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +010045 const CodeInfo& code_info,
46 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +000047 DexRegisterLocationCatalog dex_register_location_catalog =
David Brazdilf677ebf2015-05-29 16:29:43 +010048 code_info.GetDexRegisterLocationCatalog(enc);
Roland Levillaina552e1c2015-03-26 15:01:03 +000049 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
50 dex_register_number,
51 number_of_dex_registers,
52 code_info.GetNumberOfDexRegisterLocationCatalogEntries());
53 return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index);
54}
55
David Brazdilf677ebf2015-05-29 16:29:43 +010056uint32_t StackMap::LoadAt(size_t number_of_bytes, size_t offset, bool check_max) const {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010057 if (number_of_bytes == 0u) {
58 DCHECK(!check_max);
59 return 0;
60 } else if (number_of_bytes == 1u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010061 uint8_t value = region_.LoadUnaligned<uint8_t>(offset);
62 return (check_max && value == 0xFF) ? -1 : value;
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010063 } else if (number_of_bytes == 2u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010064 uint16_t value = region_.LoadUnaligned<uint16_t>(offset);
65 return (check_max && value == 0xFFFF) ? -1 : value;
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010066 } else if (number_of_bytes == 3u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010067 uint16_t low = region_.LoadUnaligned<uint16_t>(offset);
68 uint16_t high = region_.LoadUnaligned<uint8_t>(offset + sizeof(uint16_t));
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010069 uint32_t value = (high << 16) + low;
David Brazdilf677ebf2015-05-29 16:29:43 +010070 return (check_max && value == 0xFFFFFF) ? -1 : value;
Nicolas Geoffray004c2302015-03-20 10:06:38 +000071 } else {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010072 DCHECK_EQ(number_of_bytes, 4u);
David Brazdilf677ebf2015-05-29 16:29:43 +010073 return region_.LoadUnaligned<uint32_t>(offset);
Nicolas Geoffray004c2302015-03-20 10:06:38 +000074 }
75}
76
David Brazdilf677ebf2015-05-29 16:29:43 +010077void StackMap::StoreAt(size_t number_of_bytes, size_t offset, uint32_t value) const {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010078 if (number_of_bytes == 0u) {
79 DCHECK_EQ(value, 0u);
80 } else if (number_of_bytes == 1u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010081 region_.StoreUnaligned<uint8_t>(offset, value);
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010082 } else if (number_of_bytes == 2u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010083 region_.StoreUnaligned<uint16_t>(offset, value);
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010084 } else if (number_of_bytes == 3u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010085 region_.StoreUnaligned<uint16_t>(offset, Low16Bits(value));
86 region_.StoreUnaligned<uint8_t>(offset + sizeof(uint16_t), High16Bits(value));
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010087 } else {
David Brazdilf677ebf2015-05-29 16:29:43 +010088 region_.StoreUnaligned<uint32_t>(offset, value);
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010089 DCHECK_EQ(number_of_bytes, 4u);
90 }
91}
92
Roland Levillaina552e1c2015-03-26 15:01:03 +000093static void DumpRegisterMapping(std::ostream& os,
94 size_t dex_register_num,
95 DexRegisterLocation location,
96 const std::string& prefix = "v",
97 const std::string& suffix = "") {
Roland Levillain0396ed72015-05-27 15:12:19 +010098 Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
99 std::ostream indented_os(&indent_filter);
100 indented_os << prefix << dex_register_num << ": "
101 << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
102 << " (" << location.GetValue() << ")" << suffix << '\n';
103}
104
Roland Levillain0396ed72015-05-27 15:12:19 +0100105void CodeInfo::Dump(std::ostream& os,
Roland Levillainf2650d12015-05-28 14:53:28 +0100106 uint32_t code_offset,
Roland Levillain0396ed72015-05-27 15:12:19 +0100107 uint16_t number_of_dex_registers,
108 bool dump_stack_maps) const {
David Brazdilf677ebf2015-05-29 16:29:43 +0100109 StackMapEncoding encoding = ExtractEncoding();
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000110 uint32_t code_info_size = GetOverallSize();
111 size_t number_of_stack_maps = GetNumberOfStackMaps();
Roland Levillain0396ed72015-05-27 15:12:19 +0100112 Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
113 std::ostream indented_os(&indent_filter);
114 indented_os << "Optimized CodeInfo (size=" << code_info_size
115 << ", number_of_dex_registers=" << number_of_dex_registers
116 << ", number_of_stack_maps=" << number_of_stack_maps
David Brazdilf677ebf2015-05-29 16:29:43 +0100117 << ", has_inline_info=" << encoding.HasInlineInfo()
118 << ", number_of_bytes_for_inline_info=" << encoding.NumberOfBytesForInlineInfo()
119 << ", number_of_bytes_for_dex_register_map="
120 << encoding.NumberOfBytesForDexRegisterMap()
121 << ", number_of_bytes_for_dex_pc=" << encoding.NumberOfBytesForDexPc()
122 << ", number_of_bytes_for_native_pc=" << encoding.NumberOfBytesForNativePc()
123 << ", number_of_bytes_for_register_mask=" << encoding.NumberOfBytesForRegisterMask()
Roland Levillain0396ed72015-05-27 15:12:19 +0100124 << ")\n";
Roland Levillaina552e1c2015-03-26 15:01:03 +0000125 // Display the Dex register location catalog.
David Brazdilf677ebf2015-05-29 16:29:43 +0100126 GetDexRegisterLocationCatalog(encoding).Dump(indented_os, *this);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000127 // Display stack maps along with (live) Dex register maps.
Roland Levillain0396ed72015-05-27 15:12:19 +0100128 if (dump_stack_maps) {
129 for (size_t i = 0; i < number_of_stack_maps; ++i) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100130 StackMap stack_map = GetStackMapAt(i, encoding);
131 stack_map.Dump(indented_os,
132 *this,
133 encoding,
134 code_offset,
135 number_of_dex_registers,
136 " " + std::to_string(i));
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000137 }
138 }
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100139 // TODO: Dump the stack map's inline information? We need to know more from the caller:
140 // we need to know the number of dex registers for each inlined method.
141}
142
Roland Levillain0396ed72015-05-27 15:12:19 +0100143void DexRegisterLocationCatalog::Dump(std::ostream& os, const CodeInfo& code_info) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100144 StackMapEncoding encoding = code_info.ExtractEncoding();
Roland Levillain0396ed72015-05-27 15:12:19 +0100145 size_t number_of_location_catalog_entries =
146 code_info.GetNumberOfDexRegisterLocationCatalogEntries();
David Brazdilf677ebf2015-05-29 16:29:43 +0100147 size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize(encoding);
Roland Levillain0396ed72015-05-27 15:12:19 +0100148 Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
149 std::ostream indented_os(&indent_filter);
150 indented_os
151 << "DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
152 << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
153 for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
154 DexRegisterLocation location = GetDexRegisterLocation(i);
155 DumpRegisterMapping(indented_os, i, location, "entry ");
156 }
157}
158
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100159void DexRegisterMap::Dump(std::ostream& os,
160 const CodeInfo& code_info,
161 uint16_t number_of_dex_registers) const {
David Brazdilf677ebf2015-05-29 16:29:43 +0100162 StackMapEncoding encoding = code_info.ExtractEncoding();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100163 size_t number_of_location_catalog_entries =
164 code_info.GetNumberOfDexRegisterLocationCatalogEntries();
Roland Levillain0396ed72015-05-27 15:12:19 +0100165 Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
166 std::ostream indented_os(&indent_filter);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100167 // TODO: Display the bit mask of live Dex registers.
168 for (size_t j = 0; j < number_of_dex_registers; ++j) {
169 if (IsDexRegisterLive(j)) {
170 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
171 j, number_of_dex_registers, number_of_location_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100172 DexRegisterLocation location = GetDexRegisterLocation(j,
173 number_of_dex_registers,
174 code_info,
175 encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100176 DumpRegisterMapping(
Roland Levillain0396ed72015-05-27 15:12:19 +0100177 indented_os, j, location, "v",
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100178 "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
179 }
180 }
181}
182
Roland Levillainf2650d12015-05-28 14:53:28 +0100183void StackMap::Dump(std::ostream& os,
184 const CodeInfo& code_info,
David Brazdilf677ebf2015-05-29 16:29:43 +0100185 const StackMapEncoding& encoding,
Roland Levillainf2650d12015-05-28 14:53:28 +0100186 uint32_t code_offset,
187 uint16_t number_of_dex_registers,
188 const std::string& header_suffix) const {
189 Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
190 std::ostream indented_os(&indent_filter);
191 indented_os << "StackMap" << header_suffix
192 << std::hex
David Brazdilf677ebf2015-05-29 16:29:43 +0100193 << " [native_pc=0x" << code_offset + GetNativePcOffset(encoding) << "]"
194 << " (dex_pc=0x" << GetDexPc(encoding)
195 << ", native_pc_offset=0x" << GetNativePcOffset(encoding)
196 << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset(encoding)
197 << ", inline_info_offset=0x" << GetInlineDescriptorOffset(encoding)
198 << ", register_mask=0x" << GetRegisterMask(encoding)
Roland Levillainf2650d12015-05-28 14:53:28 +0100199 << std::dec
200 << ", stack_mask=0b";
David Brazdilf677ebf2015-05-29 16:29:43 +0100201 MemoryRegion stack_mask = GetStackMask(encoding);
Roland Levillainf2650d12015-05-28 14:53:28 +0100202 for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
203 indented_os << stack_mask.LoadBit(e - i - 1);
204 }
205 indented_os << ")\n";
David Brazdilf677ebf2015-05-29 16:29:43 +0100206 if (HasDexRegisterMap(encoding)) {
207 DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(
208 *this, encoding, number_of_dex_registers);
Roland Levillainf2650d12015-05-28 14:53:28 +0100209 dex_register_map.Dump(os, code_info, number_of_dex_registers);
210 }
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100211 if (HasInlineInfo(encoding)) {
212 InlineInfo inline_info = code_info.GetInlineInfoOf(*this, encoding);
213 // We do not know the length of the dex register maps of inlined frames
214 // at this level, so we just pass null to `InlineInfo::Dump` to tell
215 // it not to look at these maps.
216 inline_info.Dump(os, code_info, nullptr);
217 }
Roland Levillainf2650d12015-05-28 14:53:28 +0100218}
219
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100220void InlineInfo::Dump(std::ostream& os,
221 const CodeInfo& code_info,
222 uint16_t number_of_dex_registers[]) const {
Roland Levillain0396ed72015-05-27 15:12:19 +0100223 Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
224 std::ostream indented_os(&indent_filter);
225 indented_os << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100226
227 for (size_t i = 0; i < GetDepth(); ++i) {
Roland Levillain0396ed72015-05-27 15:12:19 +0100228 indented_os << " At depth " << i
229 << std::hex
230 << " (dex_pc=0x" << GetDexPcAtDepth(i)
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100231 << std::dec
232 << ", method_index=" << GetMethodIndexAtDepth(i)
233 << ", invoke_type=" << static_cast<InvokeType>(GetInvokeTypeAtDepth(i))
Roland Levillain0396ed72015-05-27 15:12:19 +0100234 << ")\n";
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100235 if (HasDexRegisterMapAtDepth(i) && (number_of_dex_registers != nullptr)) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100236 StackMapEncoding encoding = code_info.ExtractEncoding();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100237 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100238 code_info.GetDexRegisterMapAtDepth(i, *this, encoding, number_of_dex_registers[i]);
Roland Levillain0396ed72015-05-27 15:12:19 +0100239 dex_register_map.Dump(indented_os, code_info, number_of_dex_registers[i]);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100240 }
241 }
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000242}
243
244} // namespace art