blob: 020a6e68acc18c2f941a1fcefe9edd553f57c3b2 [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
21constexpr uint32_t StackMap::kNoDexRegisterMapSmallEncoding;
22constexpr uint32_t StackMap::kNoInlineInfoSmallEncoding;
23constexpr uint32_t StackMap::kNoDexRegisterMap;
24constexpr uint32_t StackMap::kNoInlineInfo;
25
26uint32_t StackMap::GetDexPc(const CodeInfo& info) const {
27 return info.HasSmallDexPc()
28 ? region_.LoadUnaligned<kSmallEncoding>(info.ComputeStackMapDexPcOffset())
29 : region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapDexPcOffset());
30}
31
32void StackMap::SetDexPc(const CodeInfo& info, uint32_t dex_pc) {
33 DCHECK(!info.HasSmallDexPc() || IsUint<kBitsForSmallEncoding>(dex_pc)) << dex_pc;
34 info.HasSmallDexPc()
35 ? region_.StoreUnaligned<kSmallEncoding>(info.ComputeStackMapDexPcOffset(), dex_pc)
36 : region_.StoreUnaligned<kLargeEncoding>(info.ComputeStackMapDexPcOffset(), dex_pc);
37}
38
39uint32_t StackMap::GetNativePcOffset(const CodeInfo& info) const {
40 return info.HasSmallNativePc()
41 ? region_.LoadUnaligned<kSmallEncoding>(info.ComputeStackMapNativePcOffset())
42 : region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapNativePcOffset());
43}
44
45void StackMap::SetNativePcOffset(const CodeInfo& info, uint32_t native_pc_offset) {
46 DCHECK(!info.HasSmallNativePc()
47 || IsUint<kBitsForSmallEncoding>(native_pc_offset)) << native_pc_offset;
48 uint32_t entry = info.ComputeStackMapNativePcOffset();
49 info.HasSmallNativePc()
50 ? region_.StoreUnaligned<kSmallEncoding>(entry, native_pc_offset)
51 : region_.StoreUnaligned<kLargeEncoding>(entry, native_pc_offset);
52}
53
54uint32_t StackMap::GetDexRegisterMapOffset(const CodeInfo& info) const {
55 if (info.HasSmallDexRegisterMap()) {
56 uint8_t value = region_.LoadUnaligned<kSmallEncoding>(
57 info.ComputeStackMapDexRegisterMapOffset());
58 if (value == kNoDexRegisterMapSmallEncoding) {
59 return kNoDexRegisterMap;
60 } else {
61 return value;
62 }
63 } else {
64 return region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapDexRegisterMapOffset());
65 }
66}
67
68void StackMap::SetDexRegisterMapOffset(const CodeInfo& info, uint32_t offset) {
69 DCHECK(!info.HasSmallDexRegisterMap()
70 || (IsUint<kBitsForSmallEncoding>(offset)
71 || (offset == kNoDexRegisterMap))) << offset;
72 size_t dex_register_map_entry = info.ComputeStackMapDexRegisterMapOffset();
73 info.HasSmallDexRegisterMap()
74 ? region_.StoreUnaligned<kSmallEncoding>(dex_register_map_entry, offset)
75 : region_.StoreUnaligned<kLargeEncoding>(dex_register_map_entry, offset);
76}
77
78uint32_t StackMap::GetInlineDescriptorOffset(const CodeInfo& info) const {
79 if (!info.HasInlineInfo()) return kNoInlineInfo;
80 if (info.HasSmallInlineInfo()) {
81 uint8_t value = region_.LoadUnaligned<kSmallEncoding>(
82 info.ComputeStackMapInlineInfoOffset());
83 if (value == kNoInlineInfoSmallEncoding) {
84 return kNoInlineInfo;
85 } else {
86 return value;
87 }
88 } else {
89 return region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapInlineInfoOffset());
90 }
91}
92
93void StackMap::SetInlineDescriptorOffset(const CodeInfo& info, uint32_t offset) {
94 DCHECK(info.HasInlineInfo());
95 DCHECK(!info.HasSmallInlineInfo()
96 || (IsUint<kBitsForSmallEncoding>(offset)
97 || (offset == kNoInlineInfo))) << offset;
98 size_t inline_entry = info.ComputeStackMapInlineInfoOffset();
99 info.HasSmallInlineInfo()
100 ? region_.StoreUnaligned<kSmallEncoding>(inline_entry, offset)
101 : region_.StoreUnaligned<kLargeEncoding>(inline_entry, offset);
102}
103
104uint32_t StackMap::GetRegisterMask(const CodeInfo& info) const {
105 return region_.LoadUnaligned<kLargeEncoding>(info.ComputeStackMapRegisterMaskOffset());
106}
107
108void StackMap::SetRegisterMask(const CodeInfo& info, uint32_t mask) {
109 region_.StoreUnaligned<kLargeEncoding>(info.ComputeStackMapRegisterMaskOffset(), mask);
110}
111
112size_t StackMap::ComputeStackMapSize(size_t stack_mask_size,
113 bool has_inline_info,
114 bool is_small_inline_info,
115 bool is_small_dex_map,
116 bool is_small_dex_pc,
117 bool is_small_native_pc) {
118 return StackMap::kFixedSize
119 + stack_mask_size
120 + (has_inline_info ? NumberOfBytesForEntry(is_small_inline_info) : 0)
121 + NumberOfBytesForEntry(is_small_dex_map)
122 + NumberOfBytesForEntry(is_small_dex_pc)
123 + NumberOfBytesForEntry(is_small_native_pc);
124}
125
126size_t StackMap::ComputeStackMapSize(size_t stack_mask_size,
127 size_t inline_info_size,
128 size_t dex_register_map_size,
129 size_t dex_pc_max,
130 size_t native_pc_max) {
131 return ComputeStackMapSize(
132 stack_mask_size,
133 inline_info_size != 0,
134 // + 1 to also encode kNoInlineInfo.
135 IsUint<kBitsForSmallEncoding>(inline_info_size + dex_register_map_size + 1),
136 // + 1 to also encode kNoDexRegisterMap.
137 IsUint<kBitsForSmallEncoding>(dex_register_map_size + 1),
138 IsUint<kBitsForSmallEncoding>(dex_pc_max),
139 IsUint<kBitsForSmallEncoding>(native_pc_max));
140}
141
142MemoryRegion StackMap::GetStackMask(const CodeInfo& info) const {
143 return region_.Subregion(info.ComputeStackMapStackMaskOffset(), info.GetStackMaskSize());
144}
145
146void CodeInfo::DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const {
147 StackMap stack_map = GetStackMapAt(stack_map_num);
148 os << " StackMap " << stack_map_num
149 << std::hex
150 << " (dex_pc=0x" << stack_map.GetDexPc(*this)
151 << ", native_pc_offset=0x" << stack_map.GetNativePcOffset(*this)
152 << ", dex_register_map_offset=0x" << stack_map.GetDexRegisterMapOffset(*this)
153 << ", inline_info_offset=0x" << stack_map.GetInlineDescriptorOffset(*this)
154 << ", register_mask=0x" << stack_map.GetRegisterMask(*this)
155 << std::dec
156 << ", stack_mask=0b";
157 MemoryRegion stack_mask = stack_map.GetStackMask(*this);
158 for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
159 os << stack_mask.LoadBit(e - i - 1);
160 }
161 os << ")\n";
162};
163
164void CodeInfo::Dump(std::ostream& os, uint16_t number_of_dex_registers) const {
165 uint32_t code_info_size = GetOverallSize();
166 size_t number_of_stack_maps = GetNumberOfStackMaps();
167 os << " Optimized CodeInfo (size=" << code_info_size
168 << ", number_of_dex_registers=" << number_of_dex_registers
169 << ", number_of_stack_maps=" << number_of_stack_maps
170 << ", has_inline_info=" << HasInlineInfo()
171 << ", has_small_inline_info=" << HasSmallInlineInfo()
172 << ", has_small_dex_register_map=" << HasSmallDexRegisterMap()
173 << ", has_small_dex_pc=" << HasSmallDexPc()
174 << ", has_small_native_pc=" << HasSmallNativePc()
175 << ")\n";
176
177 // Display stack maps along with Dex register maps.
178 for (size_t i = 0; i < number_of_stack_maps; ++i) {
179 StackMap stack_map = GetStackMapAt(i);
180 DumpStackMapHeader(os, i);
181 if (stack_map.HasDexRegisterMap(*this)) {
182 DexRegisterMap dex_register_map = GetDexRegisterMapOf(stack_map, number_of_dex_registers);
183 // TODO: Display the bit mask of live Dex registers.
184 for (size_t j = 0; j < number_of_dex_registers; ++j) {
185 if (dex_register_map.IsDexRegisterLive(j)) {
186 DexRegisterLocation location =
187 dex_register_map.GetLocationKindAndValue(j, number_of_dex_registers);
188 os << " " << "v" << j << ": "
189 << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
190 << " (" << location.GetValue() << ")" << '\n';
191 }
192 }
193 }
194 }
195 // TODO: Dump the stack map's inline information.
196}
197
198} // namespace art