blob: 5544507c06f2e873e037cde199066a20e0b4a40a [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 Levillain1c1da432015-07-16 11:54:44 +010030DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(
31 uint16_t dex_register_number,
32 uint16_t number_of_dex_registers,
33 const CodeInfo& code_info,
34 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +000035 DexRegisterLocationCatalog dex_register_location_catalog =
David Brazdilf677ebf2015-05-29 16:29:43 +010036 code_info.GetDexRegisterLocationCatalog(enc);
Roland Levillaina552e1c2015-03-26 15:01:03 +000037 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
38 dex_register_number,
39 number_of_dex_registers,
Roland Levillain1c1da432015-07-16 11:54:44 +010040 code_info.GetNumberOfLocationCatalogEntries());
Roland Levillaina552e1c2015-03-26 15:01:03 +000041 return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index);
42}
43
44DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number,
45 uint16_t number_of_dex_registers,
David Brazdilf677ebf2015-05-29 16:29:43 +010046 const CodeInfo& code_info,
47 const StackMapEncoding& enc) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +000048 DexRegisterLocationCatalog dex_register_location_catalog =
David Brazdilf677ebf2015-05-29 16:29:43 +010049 code_info.GetDexRegisterLocationCatalog(enc);
Roland Levillaina552e1c2015-03-26 15:01:03 +000050 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
51 dex_register_number,
52 number_of_dex_registers,
Roland Levillain1c1da432015-07-16 11:54:44 +010053 code_info.GetNumberOfLocationCatalogEntries());
Roland Levillaina552e1c2015-03-26 15:01:03 +000054 return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index);
55}
56
David Brazdilf677ebf2015-05-29 16:29:43 +010057uint32_t StackMap::LoadAt(size_t number_of_bytes, size_t offset, bool check_max) const {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010058 if (number_of_bytes == 0u) {
59 DCHECK(!check_max);
60 return 0;
61 } else if (number_of_bytes == 1u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010062 uint8_t value = region_.LoadUnaligned<uint8_t>(offset);
63 return (check_max && value == 0xFF) ? -1 : value;
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010064 } else if (number_of_bytes == 2u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010065 uint16_t value = region_.LoadUnaligned<uint16_t>(offset);
66 return (check_max && value == 0xFFFF) ? -1 : value;
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010067 } else if (number_of_bytes == 3u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010068 uint16_t low = region_.LoadUnaligned<uint16_t>(offset);
69 uint16_t high = region_.LoadUnaligned<uint8_t>(offset + sizeof(uint16_t));
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010070 uint32_t value = (high << 16) + low;
David Brazdilf677ebf2015-05-29 16:29:43 +010071 return (check_max && value == 0xFFFFFF) ? -1 : value;
Nicolas Geoffray004c2302015-03-20 10:06:38 +000072 } else {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010073 DCHECK_EQ(number_of_bytes, 4u);
David Brazdilf677ebf2015-05-29 16:29:43 +010074 return region_.LoadUnaligned<uint32_t>(offset);
Nicolas Geoffray004c2302015-03-20 10:06:38 +000075 }
76}
77
David Brazdilf677ebf2015-05-29 16:29:43 +010078void StackMap::StoreAt(size_t number_of_bytes, size_t offset, uint32_t value) const {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010079 if (number_of_bytes == 0u) {
80 DCHECK_EQ(value, 0u);
81 } else if (number_of_bytes == 1u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010082 region_.StoreUnaligned<uint8_t>(offset, value);
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010083 } else if (number_of_bytes == 2u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010084 region_.StoreUnaligned<uint16_t>(offset, value);
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010085 } else if (number_of_bytes == 3u) {
David Brazdilf677ebf2015-05-29 16:29:43 +010086 region_.StoreUnaligned<uint16_t>(offset, Low16Bits(value));
87 region_.StoreUnaligned<uint8_t>(offset + sizeof(uint16_t), High16Bits(value));
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010088 } else {
David Brazdilf677ebf2015-05-29 16:29:43 +010089 region_.StoreUnaligned<uint32_t>(offset, value);
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010090 DCHECK_EQ(number_of_bytes, 4u);
91 }
92}
93
Roland Levillaina552e1c2015-03-26 15:01:03 +000094static void DumpRegisterMapping(std::ostream& os,
95 size_t dex_register_num,
96 DexRegisterLocation location,
97 const std::string& prefix = "v",
98 const std::string& suffix = "") {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +010099 os << prefix << dex_register_num << ": "
100 << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
101 << " (" << location.GetValue() << ")" << suffix << '\n';
Roland Levillain0396ed72015-05-27 15:12:19 +0100102}
103
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100104void CodeInfo::Dump(VariableIndentationOutputStream* vios,
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();
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100111 vios->Stream()
112 << "Optimized CodeInfo (size=" << code_info_size
113 << ", number_of_dex_registers=" << number_of_dex_registers
114 << ", number_of_stack_maps=" << number_of_stack_maps
115 << ", has_inline_info=" << encoding.HasInlineInfo()
116 << ", number_of_bytes_for_inline_info=" << encoding.NumberOfBytesForInlineInfo()
117 << ", number_of_bytes_for_dex_register_map=" << encoding.NumberOfBytesForDexRegisterMap()
118 << ", number_of_bytes_for_dex_pc=" << encoding.NumberOfBytesForDexPc()
119 << ", number_of_bytes_for_native_pc=" << encoding.NumberOfBytesForNativePc()
120 << ", number_of_bytes_for_register_mask=" << encoding.NumberOfBytesForRegisterMask()
121 << ")\n";
122 ScopedIndentation indent1(vios);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000123 // Display the Dex register location catalog.
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100124 GetDexRegisterLocationCatalog(encoding).Dump(vios, *this);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000125 // Display stack maps along with (live) Dex register maps.
Roland Levillain0396ed72015-05-27 15:12:19 +0100126 if (dump_stack_maps) {
127 for (size_t i = 0; i < number_of_stack_maps; ++i) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100128 StackMap stack_map = GetStackMapAt(i, encoding);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100129 stack_map.Dump(vios,
David Brazdilf677ebf2015-05-29 16:29:43 +0100130 *this,
131 encoding,
132 code_offset,
133 number_of_dex_registers,
134 " " + std::to_string(i));
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000135 }
136 }
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100137 // TODO: Dump the stack map's inline information? We need to know more from the caller:
138 // we need to know the number of dex registers for each inlined method.
139}
140
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100141void DexRegisterLocationCatalog::Dump(VariableIndentationOutputStream* vios,
142 const CodeInfo& code_info) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100143 StackMapEncoding encoding = code_info.ExtractEncoding();
Roland Levillain1c1da432015-07-16 11:54:44 +0100144 size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
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();
Roland Levillain1c1da432015-07-16 11:54:44 +0100160 size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100161 // TODO: Display the bit mask of live Dex registers.
162 for (size_t j = 0; j < number_of_dex_registers; ++j) {
163 if (IsDexRegisterLive(j)) {
164 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
165 j, number_of_dex_registers, number_of_location_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100166 DexRegisterLocation location = GetDexRegisterLocation(j,
167 number_of_dex_registers,
168 code_info,
169 encoding);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100170 ScopedIndentation indent1(vios);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100171 DumpRegisterMapping(
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100172 vios->Stream(), j, location, "v",
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100173 "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
174 }
175 }
176}
177
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100178void StackMap::Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +0100179 const CodeInfo& code_info,
David Brazdilf677ebf2015-05-29 16:29:43 +0100180 const StackMapEncoding& encoding,
Roland Levillainf2650d12015-05-28 14:53:28 +0100181 uint32_t code_offset,
182 uint16_t number_of_dex_registers,
183 const std::string& header_suffix) const {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100184 vios->Stream()
185 << "StackMap" << header_suffix
186 << std::hex
187 << " [native_pc=0x" << code_offset + GetNativePcOffset(encoding) << "]"
188 << " (dex_pc=0x" << GetDexPc(encoding)
189 << ", native_pc_offset=0x" << GetNativePcOffset(encoding)
190 << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset(encoding)
191 << ", inline_info_offset=0x" << GetInlineDescriptorOffset(encoding)
192 << ", register_mask=0x" << GetRegisterMask(encoding)
193 << std::dec
194 << ", stack_mask=0b";
David Brazdilf677ebf2015-05-29 16:29:43 +0100195 MemoryRegion stack_mask = GetStackMask(encoding);
Roland Levillainf2650d12015-05-28 14:53:28 +0100196 for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100197 vios->Stream() << stack_mask.LoadBit(e - i - 1);
Roland Levillainf2650d12015-05-28 14:53:28 +0100198 }
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100199 vios->Stream() << ")\n";
David Brazdilf677ebf2015-05-29 16:29:43 +0100200 if (HasDexRegisterMap(encoding)) {
201 DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(
202 *this, encoding, number_of_dex_registers);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100203 dex_register_map.Dump(vios, code_info, number_of_dex_registers);
Roland Levillainf2650d12015-05-28 14:53:28 +0100204 }
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100205 if (HasInlineInfo(encoding)) {
206 InlineInfo inline_info = code_info.GetInlineInfoOf(*this, encoding);
207 // We do not know the length of the dex register maps of inlined frames
208 // at this level, so we just pass null to `InlineInfo::Dump` to tell
209 // it not to look at these maps.
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100210 inline_info.Dump(vios, code_info, nullptr);
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100211 }
Roland Levillainf2650d12015-05-28 14:53:28 +0100212}
213
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100214void InlineInfo::Dump(VariableIndentationOutputStream* vios,
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100215 const CodeInfo& code_info,
216 uint16_t number_of_dex_registers[]) const {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100217 vios->Stream() << "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) {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100220 vios->Stream()
221 << " At depth " << i
222 << std::hex
223 << " (dex_pc=0x" << GetDexPcAtDepth(i)
224 << std::dec
225 << ", method_index=" << GetMethodIndexAtDepth(i)
226 << ", invoke_type=" << static_cast<InvokeType>(GetInvokeTypeAtDepth(i))
227 << ")\n";
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100228 if (HasDexRegisterMapAtDepth(i) && (number_of_dex_registers != nullptr)) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100229 StackMapEncoding encoding = code_info.ExtractEncoding();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100230 DexRegisterMap dex_register_map =
David Brazdilf677ebf2015-05-29 16:29:43 +0100231 code_info.GetDexRegisterMapAtDepth(i, *this, encoding, number_of_dex_registers[i]);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100232 ScopedIndentation indent1(vios);
233 dex_register_map.Dump(vios, code_info, number_of_dex_registers[i]);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100234 }
235 }
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000236}
237
238} // namespace art