blob: 28f42c1fbd185b0a789656b77deb0f1ce0b1fdb2 [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
19namespace art {
20
Roland Levillaina552e1c2015-03-26 15:01:03 +000021constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
22
Nicolas Geoffray004c2302015-03-20 10:06:38 +000023constexpr uint32_t StackMap::kNoDexRegisterMapSmallEncoding;
24constexpr uint32_t StackMap::kNoInlineInfoSmallEncoding;
25constexpr uint32_t StackMap::kNoDexRegisterMap;
26constexpr uint32_t StackMap::kNoInlineInfo;
27
Roland Levillaina552e1c2015-03-26 15:01:03 +000028DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(uint16_t dex_register_number,
29 uint16_t number_of_dex_registers,
30 const CodeInfo& code_info) const {
31 DexRegisterLocationCatalog dex_register_location_catalog =
32 code_info.GetDexRegisterLocationCatalog();
33 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
34 dex_register_number,
35 number_of_dex_registers,
36 code_info.GetNumberOfDexRegisterLocationCatalogEntries());
37 return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index);
38}
39
40DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number,
41 uint16_t number_of_dex_registers,
42 const CodeInfo& code_info) const {
43 DexRegisterLocationCatalog dex_register_location_catalog =
44 code_info.GetDexRegisterLocationCatalog();
45 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
46 dex_register_number,
47 number_of_dex_registers,
48 code_info.GetNumberOfDexRegisterLocationCatalogEntries());
49 return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index);
50}
51
Nicolas Geoffray004c2302015-03-20 10:06:38 +000052uint32_t StackMap::GetDexPc(const CodeInfo& info) const {
53 return info.HasSmallDexPc()
54 ? region_.LoadUnaligned<kSmallEncoding>(info.ComputeStackMapDexPcOffset())
55 : region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapDexPcOffset());
56}
57
58void StackMap::SetDexPc(const CodeInfo& info, uint32_t dex_pc) {
59 DCHECK(!info.HasSmallDexPc() || IsUint<kBitsForSmallEncoding>(dex_pc)) << dex_pc;
60 info.HasSmallDexPc()
61 ? region_.StoreUnaligned<kSmallEncoding>(info.ComputeStackMapDexPcOffset(), dex_pc)
62 : region_.StoreUnaligned<kLargeEncoding>(info.ComputeStackMapDexPcOffset(), dex_pc);
63}
64
65uint32_t StackMap::GetNativePcOffset(const CodeInfo& info) const {
66 return info.HasSmallNativePc()
67 ? region_.LoadUnaligned<kSmallEncoding>(info.ComputeStackMapNativePcOffset())
68 : region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapNativePcOffset());
69}
70
71void StackMap::SetNativePcOffset(const CodeInfo& info, uint32_t native_pc_offset) {
72 DCHECK(!info.HasSmallNativePc()
73 || IsUint<kBitsForSmallEncoding>(native_pc_offset)) << native_pc_offset;
74 uint32_t entry = info.ComputeStackMapNativePcOffset();
75 info.HasSmallNativePc()
76 ? region_.StoreUnaligned<kSmallEncoding>(entry, native_pc_offset)
77 : region_.StoreUnaligned<kLargeEncoding>(entry, native_pc_offset);
78}
79
80uint32_t StackMap::GetDexRegisterMapOffset(const CodeInfo& info) const {
81 if (info.HasSmallDexRegisterMap()) {
82 uint8_t value = region_.LoadUnaligned<kSmallEncoding>(
83 info.ComputeStackMapDexRegisterMapOffset());
84 if (value == kNoDexRegisterMapSmallEncoding) {
85 return kNoDexRegisterMap;
86 } else {
87 return value;
88 }
89 } else {
90 return region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapDexRegisterMapOffset());
91 }
92}
93
94void StackMap::SetDexRegisterMapOffset(const CodeInfo& info, uint32_t offset) {
95 DCHECK(!info.HasSmallDexRegisterMap()
96 || (IsUint<kBitsForSmallEncoding>(offset)
97 || (offset == kNoDexRegisterMap))) << offset;
98 size_t dex_register_map_entry = info.ComputeStackMapDexRegisterMapOffset();
99 info.HasSmallDexRegisterMap()
100 ? region_.StoreUnaligned<kSmallEncoding>(dex_register_map_entry, offset)
101 : region_.StoreUnaligned<kLargeEncoding>(dex_register_map_entry, offset);
102}
103
104uint32_t StackMap::GetInlineDescriptorOffset(const CodeInfo& info) const {
105 if (!info.HasInlineInfo()) return kNoInlineInfo;
106 if (info.HasSmallInlineInfo()) {
107 uint8_t value = region_.LoadUnaligned<kSmallEncoding>(
108 info.ComputeStackMapInlineInfoOffset());
109 if (value == kNoInlineInfoSmallEncoding) {
110 return kNoInlineInfo;
111 } else {
112 return value;
113 }
114 } else {
115 return region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapInlineInfoOffset());
116 }
117}
118
119void StackMap::SetInlineDescriptorOffset(const CodeInfo& info, uint32_t offset) {
120 DCHECK(info.HasInlineInfo());
121 DCHECK(!info.HasSmallInlineInfo()
122 || (IsUint<kBitsForSmallEncoding>(offset)
123 || (offset == kNoInlineInfo))) << offset;
124 size_t inline_entry = info.ComputeStackMapInlineInfoOffset();
125 info.HasSmallInlineInfo()
126 ? region_.StoreUnaligned<kSmallEncoding>(inline_entry, offset)
127 : region_.StoreUnaligned<kLargeEncoding>(inline_entry, offset);
128}
129
130uint32_t StackMap::GetRegisterMask(const CodeInfo& info) const {
131 return region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapRegisterMaskOffset());
132}
133
134void StackMap::SetRegisterMask(const CodeInfo& info, uint32_t mask) {
135 region_.StoreUnaligned<kLargeEncoding>(info.ComputeStackMapRegisterMaskOffset(), mask);
136}
137
138size_t StackMap::ComputeStackMapSize(size_t stack_mask_size,
139 bool has_inline_info,
140 bool is_small_inline_info,
141 bool is_small_dex_map,
142 bool is_small_dex_pc,
143 bool is_small_native_pc) {
144 return StackMap::kFixedSize
145 + stack_mask_size
146 + (has_inline_info ? NumberOfBytesForEntry(is_small_inline_info) : 0)
147 + NumberOfBytesForEntry(is_small_dex_map)
148 + NumberOfBytesForEntry(is_small_dex_pc)
149 + NumberOfBytesForEntry(is_small_native_pc);
150}
151
152size_t StackMap::ComputeStackMapSize(size_t stack_mask_size,
153 size_t inline_info_size,
154 size_t dex_register_map_size,
155 size_t dex_pc_max,
156 size_t native_pc_max) {
157 return ComputeStackMapSize(
158 stack_mask_size,
159 inline_info_size != 0,
160 // + 1 to also encode kNoInlineInfo.
161 IsUint<kBitsForSmallEncoding>(inline_info_size + dex_register_map_size + 1),
162 // + 1 to also encode kNoDexRegisterMap.
163 IsUint<kBitsForSmallEncoding>(dex_register_map_size + 1),
164 IsUint<kBitsForSmallEncoding>(dex_pc_max),
165 IsUint<kBitsForSmallEncoding>(native_pc_max));
166}
167
168MemoryRegion StackMap::GetStackMask(const CodeInfo& info) const {
169 return region_.Subregion(info.ComputeStackMapStackMaskOffset(), info.GetStackMaskSize());
170}
171
Roland Levillaina552e1c2015-03-26 15:01:03 +0000172static void DumpRegisterMapping(std::ostream& os,
173 size_t dex_register_num,
174 DexRegisterLocation location,
175 const std::string& prefix = "v",
176 const std::string& suffix = "") {
177 os << " " << prefix << dex_register_num << ": "
178 << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
179 << " (" << location.GetValue() << ")" << suffix << '\n';
180}
181
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000182void CodeInfo::DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const {
183 StackMap stack_map = GetStackMapAt(stack_map_num);
184 os << " StackMap " << stack_map_num
185 << std::hex
186 << " (dex_pc=0x" << stack_map.GetDexPc(*this)
187 << ", native_pc_offset=0x" << stack_map.GetNativePcOffset(*this)
188 << ", dex_register_map_offset=0x" << stack_map.GetDexRegisterMapOffset(*this)
189 << ", inline_info_offset=0x" << stack_map.GetInlineDescriptorOffset(*this)
190 << ", register_mask=0x" << stack_map.GetRegisterMask(*this)
191 << std::dec
192 << ", stack_mask=0b";
193 MemoryRegion stack_mask = stack_map.GetStackMask(*this);
194 for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
195 os << stack_mask.LoadBit(e - i - 1);
196 }
197 os << ")\n";
198};
199
200void CodeInfo::Dump(std::ostream& os, uint16_t number_of_dex_registers) const {
201 uint32_t code_info_size = GetOverallSize();
202 size_t number_of_stack_maps = GetNumberOfStackMaps();
203 os << " Optimized CodeInfo (size=" << code_info_size
204 << ", number_of_dex_registers=" << number_of_dex_registers
205 << ", number_of_stack_maps=" << number_of_stack_maps
206 << ", has_inline_info=" << HasInlineInfo()
207 << ", has_small_inline_info=" << HasSmallInlineInfo()
208 << ", has_small_dex_register_map=" << HasSmallDexRegisterMap()
209 << ", has_small_dex_pc=" << HasSmallDexPc()
210 << ", has_small_native_pc=" << HasSmallNativePc()
211 << ")\n";
212
Roland Levillaina552e1c2015-03-26 15:01:03 +0000213 // Display the Dex register location catalog.
214 size_t number_of_location_catalog_entries = GetNumberOfDexRegisterLocationCatalogEntries();
215 size_t location_catalog_size_in_bytes = GetDexRegisterLocationCatalogSize();
216 os << " DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
217 << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
218 DexRegisterLocationCatalog dex_register_location_catalog = GetDexRegisterLocationCatalog();
219 for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
220 DexRegisterLocation location = dex_register_location_catalog.GetDexRegisterLocation(i);
221 DumpRegisterMapping(os, i, location, "entry ");
222 }
223
224 // Display stack maps along with (live) Dex register maps.
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000225 for (size_t i = 0; i < number_of_stack_maps; ++i) {
226 StackMap stack_map = GetStackMapAt(i);
227 DumpStackMapHeader(os, i);
228 if (stack_map.HasDexRegisterMap(*this)) {
229 DexRegisterMap dex_register_map = GetDexRegisterMapOf(stack_map, number_of_dex_registers);
230 // TODO: Display the bit mask of live Dex registers.
231 for (size_t j = 0; j < number_of_dex_registers; ++j) {
232 if (dex_register_map.IsDexRegisterLive(j)) {
Roland Levillaina552e1c2015-03-26 15:01:03 +0000233 size_t location_catalog_entry_index = dex_register_map.GetLocationCatalogEntryIndex(
234 j, number_of_dex_registers, number_of_location_catalog_entries);
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000235 DexRegisterLocation location =
Roland Levillaina552e1c2015-03-26 15:01:03 +0000236 dex_register_map.GetDexRegisterLocation(j, number_of_dex_registers, *this);
237 DumpRegisterMapping(
238 os, j, location, "v",
239 "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000240 }
241 }
242 }
243 }
244 // TODO: Dump the stack map's inline information.
245}
246
247} // namespace art