blob: 11e7e444ff7cdf10f97407ae29a5a18e16964dd9 [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 Geoffray004c2302015-03-20 10:06:38 +000021namespace art {
22
Roland Levillaina552e1c2015-03-26 15:01:03 +000023constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
Nicolas Geoffray004c2302015-03-20 10:06:38 +000024constexpr uint32_t StackMap::kNoDexRegisterMap;
25constexpr uint32_t StackMap::kNoInlineInfo;
26
Roland Levillaina552e1c2015-03-26 15:01:03 +000027DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(uint16_t dex_register_number,
28 uint16_t number_of_dex_registers,
29 const CodeInfo& code_info) const {
30 DexRegisterLocationCatalog dex_register_location_catalog =
31 code_info.GetDexRegisterLocationCatalog();
32 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
33 dex_register_number,
34 number_of_dex_registers,
35 code_info.GetNumberOfDexRegisterLocationCatalogEntries());
36 return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index);
37}
38
39DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number,
40 uint16_t number_of_dex_registers,
41 const CodeInfo& code_info) const {
42 DexRegisterLocationCatalog dex_register_location_catalog =
43 code_info.GetDexRegisterLocationCatalog();
44 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
45 dex_register_number,
46 number_of_dex_registers,
47 code_info.GetNumberOfDexRegisterLocationCatalogEntries());
48 return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index);
49}
50
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010051// Loads `number_of_bytes` at the given `offset` and assemble a uint32_t. If `check_max` is true,
52// this method converts a maximum value of size `number_of_bytes` into a uint32_t 0xFFFFFFFF.
53static uint32_t LoadAt(MemoryRegion region,
54 size_t number_of_bytes,
55 size_t offset,
56 bool check_max = false) {
57 if (number_of_bytes == 0u) {
58 DCHECK(!check_max);
59 return 0;
60 } else if (number_of_bytes == 1u) {
61 uint8_t value = region.LoadUnaligned<uint8_t>(offset);
62 if (check_max && value == 0xFF) {
63 return -1;
64 } else {
65 return value;
66 }
67 } else if (number_of_bytes == 2u) {
68 uint16_t value = region.LoadUnaligned<uint16_t>(offset);
69 if (check_max && value == 0xFFFF) {
70 return -1;
71 } else {
72 return value;
73 }
74 } else if (number_of_bytes == 3u) {
75 uint16_t low = region.LoadUnaligned<uint16_t>(offset);
76 uint16_t high = region.LoadUnaligned<uint8_t>(offset + sizeof(uint16_t));
77 uint32_t value = (high << 16) + low;
78 if (check_max && value == 0xFFFFFF) {
79 return -1;
Nicolas Geoffray004c2302015-03-20 10:06:38 +000080 } else {
81 return value;
82 }
83 } else {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010084 DCHECK_EQ(number_of_bytes, 4u);
85 return region.LoadUnaligned<uint32_t>(offset);
Nicolas Geoffray004c2302015-03-20 10:06:38 +000086 }
87}
88
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010089static void StoreAt(MemoryRegion region, size_t number_of_bytes, size_t offset, uint32_t value) {
90 if (number_of_bytes == 0u) {
91 DCHECK_EQ(value, 0u);
92 } else if (number_of_bytes == 1u) {
93 region.StoreUnaligned<uint8_t>(offset, value);
94 } else if (number_of_bytes == 2u) {
95 region.StoreUnaligned<uint16_t>(offset, value);
96 } else if (number_of_bytes == 3u) {
97 region.StoreUnaligned<uint16_t>(offset, Low16Bits(value));
98 region.StoreUnaligned<uint8_t>(offset + sizeof(uint16_t), High16Bits(value));
99 } else {
100 region.StoreUnaligned<uint32_t>(offset, value);
101 DCHECK_EQ(number_of_bytes, 4u);
102 }
103}
104
105uint32_t StackMap::GetDexPc(const CodeInfo& info) const {
106 return LoadAt(region_, info.NumberOfBytesForDexPc(), info.ComputeStackMapDexPcOffset());
107}
108
109void StackMap::SetDexPc(const CodeInfo& info, uint32_t dex_pc) {
110 StoreAt(region_, info.NumberOfBytesForDexPc(), info.ComputeStackMapDexPcOffset(), dex_pc);
111}
112
113uint32_t StackMap::GetNativePcOffset(const CodeInfo& info) const {
114 return LoadAt(region_, info.NumberOfBytesForNativePc(), info.ComputeStackMapNativePcOffset());
115}
116
117void StackMap::SetNativePcOffset(const CodeInfo& info, uint32_t native_pc_offset) {
118 StoreAt(region_, info.NumberOfBytesForNativePc(), info.ComputeStackMapNativePcOffset(), native_pc_offset);
119}
120
121uint32_t StackMap::GetDexRegisterMapOffset(const CodeInfo& info) const {
122 return LoadAt(region_,
123 info.NumberOfBytesForDexRegisterMap(),
124 info.ComputeStackMapDexRegisterMapOffset(),
125 /* check_max */ true);
126}
127
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000128void StackMap::SetDexRegisterMapOffset(const CodeInfo& info, uint32_t offset) {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +0100129 StoreAt(region_,
130 info.NumberOfBytesForDexRegisterMap(),
131 info.ComputeStackMapDexRegisterMapOffset(),
132 offset);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000133}
134
135uint32_t StackMap::GetInlineDescriptorOffset(const CodeInfo& info) const {
136 if (!info.HasInlineInfo()) return kNoInlineInfo;
Nicolas Geoffray896f8f72015-03-30 15:44:25 +0100137 return LoadAt(region_,
138 info.NumberOfBytesForInlineInfo(),
139 info.ComputeStackMapInlineInfoOffset(),
140 /* check_max */ true);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000141}
142
143void StackMap::SetInlineDescriptorOffset(const CodeInfo& info, uint32_t offset) {
144 DCHECK(info.HasInlineInfo());
Nicolas Geoffray896f8f72015-03-30 15:44:25 +0100145 StoreAt(region_,
146 info.NumberOfBytesForInlineInfo(),
147 info.ComputeStackMapInlineInfoOffset(),
148 offset);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000149}
150
151uint32_t StackMap::GetRegisterMask(const CodeInfo& info) const {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +0100152 return LoadAt(region_,
153 info.NumberOfBytesForRegisterMask(),
154 info.ComputeStackMapRegisterMaskOffset());
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000155}
156
157void StackMap::SetRegisterMask(const CodeInfo& info, uint32_t mask) {
Nicolas Geoffray896f8f72015-03-30 15:44:25 +0100158 StoreAt(region_,
159 info.NumberOfBytesForRegisterMask(),
160 info.ComputeStackMapRegisterMaskOffset(),
161 mask);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000162}
163
Nicolas Geoffray896f8f72015-03-30 15:44:25 +0100164size_t StackMap::ComputeStackMapSizeInternal(size_t stack_mask_size,
165 size_t number_of_bytes_for_inline_info,
166 size_t number_of_bytes_for_dex_map,
167 size_t number_of_bytes_for_dex_pc,
168 size_t number_of_bytes_for_native_pc,
169 size_t number_of_bytes_for_register_mask) {
170 return stack_mask_size
171 + number_of_bytes_for_inline_info
172 + number_of_bytes_for_dex_map
173 + number_of_bytes_for_dex_pc
174 + number_of_bytes_for_native_pc
175 + number_of_bytes_for_register_mask;
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000176}
177
178size_t StackMap::ComputeStackMapSize(size_t stack_mask_size,
179 size_t inline_info_size,
180 size_t dex_register_map_size,
181 size_t dex_pc_max,
Nicolas Geoffray896f8f72015-03-30 15:44:25 +0100182 size_t native_pc_max,
183 size_t register_mask_max) {
184 return ComputeStackMapSizeInternal(
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000185 stack_mask_size,
Nicolas Geoffray896f8f72015-03-30 15:44:25 +0100186 inline_info_size == 0
187 ? 0
188 // + 1 to also encode kNoInlineInfo.
189 : CodeInfo::EncodingSizeInBytes(inline_info_size + dex_register_map_size + 1),
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000190 // + 1 to also encode kNoDexRegisterMap.
Nicolas Geoffray896f8f72015-03-30 15:44:25 +0100191 CodeInfo::EncodingSizeInBytes(dex_register_map_size + 1),
192 CodeInfo::EncodingSizeInBytes(dex_pc_max),
193 CodeInfo::EncodingSizeInBytes(native_pc_max),
194 CodeInfo::EncodingSizeInBytes(register_mask_max));
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000195}
196
197MemoryRegion StackMap::GetStackMask(const CodeInfo& info) const {
198 return region_.Subregion(info.ComputeStackMapStackMaskOffset(), info.GetStackMaskSize());
199}
200
Roland Levillaina552e1c2015-03-26 15:01:03 +0000201static void DumpRegisterMapping(std::ostream& os,
202 size_t dex_register_num,
203 DexRegisterLocation location,
204 const std::string& prefix = "v",
205 const std::string& suffix = "") {
206 os << " " << prefix << dex_register_num << ": "
207 << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
208 << " (" << location.GetValue() << ")" << suffix << '\n';
209}
210
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000211void CodeInfo::DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const {
212 StackMap stack_map = GetStackMapAt(stack_map_num);
213 os << " StackMap " << stack_map_num
214 << std::hex
215 << " (dex_pc=0x" << stack_map.GetDexPc(*this)
216 << ", native_pc_offset=0x" << stack_map.GetNativePcOffset(*this)
217 << ", dex_register_map_offset=0x" << stack_map.GetDexRegisterMapOffset(*this)
218 << ", inline_info_offset=0x" << stack_map.GetInlineDescriptorOffset(*this)
219 << ", register_mask=0x" << stack_map.GetRegisterMask(*this)
220 << std::dec
221 << ", stack_mask=0b";
222 MemoryRegion stack_mask = stack_map.GetStackMask(*this);
223 for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
224 os << stack_mask.LoadBit(e - i - 1);
225 }
226 os << ")\n";
227};
228
229void CodeInfo::Dump(std::ostream& os, uint16_t number_of_dex_registers) const {
230 uint32_t code_info_size = GetOverallSize();
231 size_t number_of_stack_maps = GetNumberOfStackMaps();
232 os << " Optimized CodeInfo (size=" << code_info_size
233 << ", number_of_dex_registers=" << number_of_dex_registers
234 << ", number_of_stack_maps=" << number_of_stack_maps
235 << ", has_inline_info=" << HasInlineInfo()
Nicolas Geoffray896f8f72015-03-30 15:44:25 +0100236 << ", number_of_bytes_for_inline_info=" << NumberOfBytesForInlineInfo()
237 << ", number_of_bytes_for_dex_register_map=" << NumberOfBytesForDexRegisterMap()
238 << ", number_of_bytes_for_dex_pc=" << NumberOfBytesForDexPc()
239 << ", number_of_bytes_for_native_pc=" << NumberOfBytesForNativePc()
240 << ", number_of_bytes_for_register_mask=" << NumberOfBytesForRegisterMask()
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000241 << ")\n";
242
Roland Levillaina552e1c2015-03-26 15:01:03 +0000243 // Display the Dex register location catalog.
244 size_t number_of_location_catalog_entries = GetNumberOfDexRegisterLocationCatalogEntries();
245 size_t location_catalog_size_in_bytes = GetDexRegisterLocationCatalogSize();
246 os << " DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
247 << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
248 DexRegisterLocationCatalog dex_register_location_catalog = GetDexRegisterLocationCatalog();
249 for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
250 DexRegisterLocation location = dex_register_location_catalog.GetDexRegisterLocation(i);
251 DumpRegisterMapping(os, i, location, "entry ");
252 }
253
254 // Display stack maps along with (live) Dex register maps.
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000255 for (size_t i = 0; i < number_of_stack_maps; ++i) {
256 StackMap stack_map = GetStackMapAt(i);
257 DumpStackMapHeader(os, i);
258 if (stack_map.HasDexRegisterMap(*this)) {
259 DexRegisterMap dex_register_map = GetDexRegisterMapOf(stack_map, number_of_dex_registers);
260 // TODO: Display the bit mask of live Dex registers.
261 for (size_t j = 0; j < number_of_dex_registers; ++j) {
262 if (dex_register_map.IsDexRegisterLive(j)) {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000263 size_t location_catalog_entry_index = dex_register_map.GetLocationCatalogEntryIndex(
264 j, number_of_dex_registers, number_of_location_catalog_entries);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000265 DexRegisterLocation location =
Roland Levillaina552e1c2015-03-26 15:01:03 +0000266 dex_register_map.GetDexRegisterLocation(j, number_of_dex_registers, *this);
267 DumpRegisterMapping(
268 os, j, location, "v",
269 "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000270 }
271 }
272 }
273 }
274 // TODO: Dump the stack map's inline information.
275}
276
277} // namespace art