blob: 962132b29f6200203f1add6121796375bc1d4d19 [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 = "") {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +010098 os << prefix << dex_register_num << ": "
99 << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
100 << " (" << location.GetValue() << ")" << suffix << '\n';
Roland Levillain0396ed72015-05-27 15:12:19 +0100101}
102
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100103void CodeInfo::Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +0100104 uint32_t code_offset,
Roland Levillain0396ed72015-05-27 15:12:19 +0100105 uint16_t number_of_dex_registers,
106 bool dump_stack_maps) const {
David Brazdilf677ebf2015-05-29 16:29:43 +0100107 StackMapEncoding encoding = ExtractEncoding();
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000108 uint32_t code_info_size = GetOverallSize();
109 size_t number_of_stack_maps = GetNumberOfStackMaps();
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100110 vios->Stream()
111 << "Optimized CodeInfo (size=" << code_info_size
112 << ", number_of_dex_registers=" << number_of_dex_registers
113 << ", number_of_stack_maps=" << number_of_stack_maps
114 << ", has_inline_info=" << encoding.HasInlineInfo()
115 << ", number_of_bytes_for_inline_info=" << encoding.NumberOfBytesForInlineInfo()
116 << ", number_of_bytes_for_dex_register_map=" << encoding.NumberOfBytesForDexRegisterMap()
117 << ", number_of_bytes_for_dex_pc=" << encoding.NumberOfBytesForDexPc()
118 << ", number_of_bytes_for_native_pc=" << encoding.NumberOfBytesForNativePc()
119 << ", number_of_bytes_for_register_mask=" << encoding.NumberOfBytesForRegisterMask()
120 << ")\n";
121 ScopedIndentation indent1(vios);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000122 // Display the Dex register location catalog.
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100123 GetDexRegisterLocationCatalog(encoding).Dump(vios, *this);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000124 // Display stack maps along with (live) Dex register maps.
Roland Levillain0396ed72015-05-27 15:12:19 +0100125 if (dump_stack_maps) {
126 for (size_t i = 0; i < number_of_stack_maps; ++i) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100127 StackMap stack_map = GetStackMapAt(i, encoding);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100128 stack_map.Dump(vios,
David Brazdilf677ebf2015-05-29 16:29:43 +0100129 *this,
130 encoding,
131 code_offset,
132 number_of_dex_registers,
133 " " + std::to_string(i));
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000134 }
135 }
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100136 // TODO: Dump the stack map's inline information? We need to know more from the caller:
137 // we need to know the number of dex registers for each inlined method.
138}
139
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100140void DexRegisterLocationCatalog::Dump(VariableIndentationOutputStream* vios,
141 const CodeInfo& code_info) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100142 StackMapEncoding encoding = code_info.ExtractEncoding();
Roland Levillain0396ed72015-05-27 15:12:19 +0100143 size_t number_of_location_catalog_entries =
144 code_info.GetNumberOfDexRegisterLocationCatalogEntries();
David Brazdilf677ebf2015-05-29 16:29:43 +0100145 size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize(encoding);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100146 vios->Stream()
Roland Levillain0396ed72015-05-27 15:12:19 +0100147 << "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);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100151 ScopedIndentation indent1(vios);
152 DumpRegisterMapping(vios->Stream(), i, location, "entry ");
Roland Levillain0396ed72015-05-27 15:12:19 +0100153 }
154}
155
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100156void DexRegisterMap::Dump(VariableIndentationOutputStream* vios,
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100157 const CodeInfo& code_info,
158 uint16_t number_of_dex_registers) const {
David Brazdilf677ebf2015-05-29 16:29:43 +0100159 StackMapEncoding encoding = code_info.ExtractEncoding();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100160 size_t number_of_location_catalog_entries =
161 code_info.GetNumberOfDexRegisterLocationCatalogEntries();
162 // TODO: Display the bit mask of live Dex registers.
163 for (size_t j = 0; j < number_of_dex_registers; ++j) {
164 if (IsDexRegisterLive(j)) {
165 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
166 j, number_of_dex_registers, number_of_location_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100167 DexRegisterLocation location = GetDexRegisterLocation(j,
168 number_of_dex_registers,
169 code_info,
170 encoding);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100171 ScopedIndentation indent1(vios);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100172 DumpRegisterMapping(
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100173 vios->Stream(), j, location, "v",
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100174 "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
175 }
176 }
177}
178
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100179void StackMap::Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +0100180 const CodeInfo& code_info,
David Brazdilf677ebf2015-05-29 16:29:43 +0100181 const StackMapEncoding& encoding,
Roland Levillainf2650d12015-05-28 14:53:28 +0100182 uint32_t code_offset,
183 uint16_t number_of_dex_registers,
184 const std::string& header_suffix) const {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100185 vios->Stream()
186 << "StackMap" << header_suffix
187 << std::hex
188 << " [native_pc=0x" << code_offset + GetNativePcOffset(encoding) << "]"
189 << " (dex_pc=0x" << GetDexPc(encoding)
190 << ", native_pc_offset=0x" << GetNativePcOffset(encoding)
191 << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset(encoding)
192 << ", inline_info_offset=0x" << GetInlineDescriptorOffset(encoding)
193 << ", register_mask=0x" << GetRegisterMask(encoding)
194 << std::dec
195 << ", stack_mask=0b";
David Brazdilf677ebf2015-05-29 16:29:43 +0100196 MemoryRegion stack_mask = GetStackMask(encoding);
Roland Levillainf2650d12015-05-28 14:53:28 +0100197 for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100198 vios->Stream() << stack_mask.LoadBit(e - i - 1);
Roland Levillainf2650d12015-05-28 14:53:28 +0100199 }
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100200 vios->Stream() << ")\n";
David Brazdilf677ebf2015-05-29 16:29:43 +0100201 if (HasDexRegisterMap(encoding)) {
202 DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(
203 *this, encoding, number_of_dex_registers);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100204 dex_register_map.Dump(vios, code_info, number_of_dex_registers);
Roland Levillainf2650d12015-05-28 14:53:28 +0100205 }
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100206 if (HasInlineInfo(encoding)) {
207 InlineInfo inline_info = code_info.GetInlineInfoOf(*this, encoding);
208 // We do not know the length of the dex register maps of inlined frames
209 // at this level, so we just pass null to `InlineInfo::Dump` to tell
210 // it not to look at these maps.
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100211 inline_info.Dump(vios, code_info, nullptr);
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100212 }
Roland Levillainf2650d12015-05-28 14:53:28 +0100213}
214
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100215void InlineInfo::Dump(VariableIndentationOutputStream* vios,
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100216 const CodeInfo& code_info,
217 uint16_t number_of_dex_registers[]) const {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100218 vios->Stream() << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100219
220 for (size_t i = 0; i < GetDepth(); ++i) {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100221 vios->Stream()
222 << " At depth " << i
223 << std::hex
224 << " (dex_pc=0x" << GetDexPcAtDepth(i)
225 << std::dec
226 << ", method_index=" << GetMethodIndexAtDepth(i)
227 << ", invoke_type=" << static_cast<InvokeType>(GetInvokeTypeAtDepth(i))
228 << ")\n";
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100229 if (HasDexRegisterMapAtDepth(i) && (number_of_dex_registers != nullptr)) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100230 StackMapEncoding encoding = code_info.ExtractEncoding();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100231 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100232 code_info.GetDexRegisterMapAtDepth(i, *this, encoding, number_of_dex_registers[i]);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100233 ScopedIndentation indent1(vios);
234 dex_register_map.Dump(vios, code_info, number_of_dex_registers[i]);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100235 }
236 }
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000237}
238
239} // namespace art