blob: f8fc2a9e90025802f26ba34689cb6a262a915c60 [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"
22
Nicolas Geoffray004c2302015-03-20 10:06:38 +000023namespace art {
24
Roland Levillaina552e1c2015-03-26 15:01:03 +000025constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
Nicolas Geoffray004c2302015-03-20 10:06:38 +000026constexpr uint32_t StackMap::kNoDexRegisterMap;
27constexpr uint32_t StackMap::kNoInlineInfo;
28
Roland Levillaina552e1c2015-03-26 15:01:03 +000029DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(uint16_t dex_register_number,
30 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +010031 const CodeInfo& code_info,
32 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +000033 DexRegisterLocationCatalog dex_register_location_catalog =
David Brazdilf677ebf2015-05-29 16:29:43 +010034 code_info.GetDexRegisterLocationCatalog(enc);
Roland Levillaina552e1c2015-03-26 15:01:03 +000035 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
36 dex_register_number,
37 number_of_dex_registers,
38 code_info.GetNumberOfDexRegisterLocationCatalogEntries());
39 return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index);
40}
41
42DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number,
43 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +010044 const CodeInfo& code_info,
45 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +000046 DexRegisterLocationCatalog dex_register_location_catalog =
David Brazdilf677ebf2015-05-29 16:29:43 +010047 code_info.GetDexRegisterLocationCatalog(enc);
Roland Levillaina552e1c2015-03-26 15:01:03 +000048 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
49 dex_register_number,
50 number_of_dex_registers,
51 code_info.GetNumberOfDexRegisterLocationCatalogEntries());
52 return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index);
53}
54
David Brazdilf677ebf2015-05-29 16:29:43 +010055uint32_t StackMap::LoadAt(size_t number_of_bytes, size_t offset, bool check_max) const {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010056 if (number_of_bytes == 0u) {
57 DCHECK(!check_max);
58 return 0;
59 } else if (number_of_bytes == 1u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010060 uint8_t value = region_.LoadUnaligned<uint8_t>(offset);
61 return (check_max && value == 0xFF) ? -1 : value;
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010062 } else if (number_of_bytes == 2u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010063 uint16_t value = region_.LoadUnaligned<uint16_t>(offset);
64 return (check_max && value == 0xFFFF) ? -1 : value;
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010065 } else if (number_of_bytes == 3u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010066 uint16_t low = region_.LoadUnaligned<uint16_t>(offset);
67 uint16_t high = region_.LoadUnaligned<uint8_t>(offset + sizeof(uint16_t));
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010068 uint32_t value = (high << 16) + low;
David Brazdilf677ebf2015-05-29 16:29:43 +010069 return (check_max && value == 0xFFFFFF) ? -1 : value;
Nicolas Geoffray004c2302015-03-20 10:06:38 +000070 } else {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010071 DCHECK_EQ(number_of_bytes, 4u);
David Brazdilf677ebf2015-05-29 16:29:43 +010072 return region_.LoadUnaligned<uint32_t>(offset);
Nicolas Geoffray004c2302015-03-20 10:06:38 +000073 }
74}
75
David Brazdilf677ebf2015-05-29 16:29:43 +010076void StackMap::StoreAt(size_t number_of_bytes, size_t offset, uint32_t value) const {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010077 if (number_of_bytes == 0u) {
78 DCHECK_EQ(value, 0u);
79 } else if (number_of_bytes == 1u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010080 region_.StoreUnaligned<uint8_t>(offset, value);
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010081 } else if (number_of_bytes == 2u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010082 region_.StoreUnaligned<uint16_t>(offset, value);
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010083 } else if (number_of_bytes == 3u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010084 region_.StoreUnaligned<uint16_t>(offset, Low16Bits(value));
85 region_.StoreUnaligned<uint8_t>(offset + sizeof(uint16_t), High16Bits(value));
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010086 } else {
David Brazdilf677ebf2015-05-29 16:29:43 +010087 region_.StoreUnaligned<uint32_t>(offset, value);
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010088 DCHECK_EQ(number_of_bytes, 4u);
89 }
90}
91
Roland Levillaina552e1c2015-03-26 15:01:03 +000092static void DumpRegisterMapping(std::ostream& os,
93 size_t dex_register_num,
94 DexRegisterLocation location,
95 const std::string& prefix = "v",
96 const std::string& suffix = "") {
Roland Levillain0396ed72015-05-27 15:12:19 +010097 Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
98 std::ostream indented_os(&indent_filter);
99 indented_os << prefix << dex_register_num << ": "
100 << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
101 << " (" << location.GetValue() << ")" << suffix << '\n';
102}
103
Roland Levillain0396ed72015-05-27 15:12:19 +0100104void CodeInfo::Dump(std::ostream& os,
Roland Levillainf2650d12015-05-28 14:53:28 +0100105 uint32_t code_offset,
Roland Levillain0396ed72015-05-27 15:12:19 +0100106 uint16_t number_of_dex_registers,
107 bool dump_stack_maps) const {
David Brazdilf677ebf2015-05-29 16:29:43 +0100108 StackMapEncoding encoding = ExtractEncoding();
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000109 uint32_t code_info_size = GetOverallSize();
110 size_t number_of_stack_maps = GetNumberOfStackMaps();
Roland Levillain0396ed72015-05-27 15:12:19 +0100111 Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
112 std::ostream indented_os(&indent_filter);
113 indented_os << "Optimized CodeInfo (size=" << code_info_size
114 << ", number_of_dex_registers=" << number_of_dex_registers
115 << ", number_of_stack_maps=" << number_of_stack_maps
David Brazdilf677ebf2015-05-29 16:29:43 +0100116 << ", has_inline_info=" << encoding.HasInlineInfo()
117 << ", number_of_bytes_for_inline_info=" << encoding.NumberOfBytesForInlineInfo()
118 << ", number_of_bytes_for_dex_register_map="
119 << encoding.NumberOfBytesForDexRegisterMap()
120 << ", number_of_bytes_for_dex_pc=" << encoding.NumberOfBytesForDexPc()
121 << ", number_of_bytes_for_native_pc=" << encoding.NumberOfBytesForNativePc()
122 << ", number_of_bytes_for_register_mask=" << encoding.NumberOfBytesForRegisterMask()
Roland Levillain0396ed72015-05-27 15:12:19 +0100123 << ")\n";
Roland Levillaina552e1c2015-03-26 15:01:03 +0000124 // Display the Dex register location catalog.
David Brazdilf677ebf2015-05-29 16:29:43 +0100125 GetDexRegisterLocationCatalog(encoding).Dump(indented_os, *this);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000126 // Display stack maps along with (live) Dex register maps.
Roland Levillain0396ed72015-05-27 15:12:19 +0100127 if (dump_stack_maps) {
128 for (size_t i = 0; i < number_of_stack_maps; ++i) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100129 StackMap stack_map = GetStackMapAt(i, encoding);
130 stack_map.Dump(indented_os,
131 *this,
132 encoding,
133 code_offset,
134 number_of_dex_registers,
135 " " + std::to_string(i));
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000136 }
137 }
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100138 // TODO: Dump the stack map's inline information? We need to know more from the caller:
139 // we need to know the number of dex registers for each inlined method.
140}
141
Roland Levillain0396ed72015-05-27 15:12:19 +0100142void DexRegisterLocationCatalog::Dump(std::ostream& os, const CodeInfo& code_info) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100143 StackMapEncoding encoding = code_info.ExtractEncoding();
Roland Levillain0396ed72015-05-27 15:12:19 +0100144 size_t number_of_location_catalog_entries =
145 code_info.GetNumberOfDexRegisterLocationCatalogEntries();
David Brazdilf677ebf2015-05-29 16:29:43 +0100146 size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize(encoding);
Roland Levillain0396ed72015-05-27 15:12:19 +0100147 Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
148 std::ostream indented_os(&indent_filter);
149 indented_os
150 << "DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
151 << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
152 for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
153 DexRegisterLocation location = GetDexRegisterLocation(i);
154 DumpRegisterMapping(indented_os, i, location, "entry ");
155 }
156}
157
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100158void DexRegisterMap::Dump(std::ostream& os,
159 const CodeInfo& code_info,
160 uint16_t number_of_dex_registers) const {
David Brazdilf677ebf2015-05-29 16:29:43 +0100161 StackMapEncoding encoding = code_info.ExtractEncoding();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100162 size_t number_of_location_catalog_entries =
163 code_info.GetNumberOfDexRegisterLocationCatalogEntries();
Roland Levillain0396ed72015-05-27 15:12:19 +0100164 Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
165 std::ostream indented_os(&indent_filter);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100166 // TODO: Display the bit mask of live Dex registers.
167 for (size_t j = 0; j < number_of_dex_registers; ++j) {
168 if (IsDexRegisterLive(j)) {
169 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
170 j, number_of_dex_registers, number_of_location_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100171 DexRegisterLocation location = GetDexRegisterLocation(j,
172 number_of_dex_registers,
173 code_info,
174 encoding);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100175 DumpRegisterMapping(
Roland Levillain0396ed72015-05-27 15:12:19 +0100176 indented_os, j, location, "v",
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100177 "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
178 }
179 }
180}
181
Roland Levillainf2650d12015-05-28 14:53:28 +0100182void StackMap::Dump(std::ostream& os,
183 const CodeInfo& code_info,
David Brazdilf677ebf2015-05-29 16:29:43 +0100184 const StackMapEncoding& encoding,
Roland Levillainf2650d12015-05-28 14:53:28 +0100185 uint32_t code_offset,
186 uint16_t number_of_dex_registers,
187 const std::string& header_suffix) const {
188 Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
189 std::ostream indented_os(&indent_filter);
190 indented_os << "StackMap" << header_suffix
191 << std::hex
David Brazdilf677ebf2015-05-29 16:29:43 +0100192 << " [native_pc=0x" << code_offset + GetNativePcOffset(encoding) << "]"
193 << " (dex_pc=0x" << GetDexPc(encoding)
194 << ", native_pc_offset=0x" << GetNativePcOffset(encoding)
195 << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset(encoding)
196 << ", inline_info_offset=0x" << GetInlineDescriptorOffset(encoding)
197 << ", register_mask=0x" << GetRegisterMask(encoding)
Roland Levillainf2650d12015-05-28 14:53:28 +0100198 << std::dec
199 << ", stack_mask=0b";
David Brazdilf677ebf2015-05-29 16:29:43 +0100200 MemoryRegion stack_mask = GetStackMask(encoding);
Roland Levillainf2650d12015-05-28 14:53:28 +0100201 for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
202 indented_os << stack_mask.LoadBit(e - i - 1);
203 }
204 indented_os << ")\n";
David Brazdilf677ebf2015-05-29 16:29:43 +0100205 if (HasDexRegisterMap(encoding)) {
206 DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(
207 *this, encoding, number_of_dex_registers);
Roland Levillainf2650d12015-05-28 14:53:28 +0100208 dex_register_map.Dump(os, code_info, number_of_dex_registers);
209 }
210}
211
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100212void InlineInfo::Dump(std::ostream& os,
213 const CodeInfo& code_info,
214 uint16_t number_of_dex_registers[]) const {
Roland Levillain0396ed72015-05-27 15:12:19 +0100215 Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
216 std::ostream indented_os(&indent_filter);
217 indented_os << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100218
219 for (size_t i = 0; i < GetDepth(); ++i) {
Roland Levillain0396ed72015-05-27 15:12:19 +0100220 indented_os << " At depth " << i
221 << std::hex
222 << " (dex_pc=0x" << GetDexPcAtDepth(i)
223 << ", method_index=0x" << GetMethodIndexAtDepth(i)
224 << ")\n";
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100225 if (HasDexRegisterMapAtDepth(i)) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100226 StackMapEncoding encoding = code_info.ExtractEncoding();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100227 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100228 code_info.GetDexRegisterMapAtDepth(i, *this, encoding, number_of_dex_registers[i]);
Roland Levillain0396ed72015-05-27 15:12:19 +0100229 dex_register_map.Dump(indented_os, code_info, number_of_dex_registers[i]);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100230 }
231 }
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000232}
233
234} // namespace art