blob: 2b7e8dd748f89902409cd88577f78546ad27c8e8 [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 Geoffray5d37c152017-01-12 13:25:19 +000021#include "art_method.h"
David Sehr9c4a0152018-04-05 12:23:54 -070022#include "base/indenter.h"
Nicolas Geoffray5d37c152017-01-12 13:25:19 +000023#include "scoped_thread_state_change-inl.h"
Roland Levillain0396ed72015-05-27 15:12:19 +010024
Nicolas Geoffray004c2302015-03-20 10:06:38 +000025namespace art {
26
Roland Levillaina552e1c2015-03-26 15:01:03 +000027constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
Nicolas Geoffray004c2302015-03-20 10:06:38 +000028
David Srbecky7dc11782016-02-25 13:23:56 +000029std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation::Kind& kind) {
30 using Kind = DexRegisterLocation::Kind;
31 switch (kind) {
32 case Kind::kNone:
33 return stream << "none";
34 case Kind::kInStack:
35 return stream << "in stack";
36 case Kind::kInRegister:
37 return stream << "in register";
38 case Kind::kInRegisterHigh:
39 return stream << "in register high";
40 case Kind::kInFpuRegister:
41 return stream << "in fpu register";
42 case Kind::kInFpuRegisterHigh:
43 return stream << "in fpu register high";
44 case Kind::kConstant:
45 return stream << "as constant";
46 case Kind::kInStackLargeOffset:
47 return stream << "in stack (large offset)";
48 case Kind::kConstantLargeValue:
49 return stream << "as constant (large value)";
50 }
51 return stream << "Kind<" << static_cast<uint32_t>(kind) << ">";
52}
53
Roland Levillain1c1da432015-07-16 11:54:44 +010054DexRegisterLocation::Kind DexRegisterMap::GetLocationInternalKind(
55 uint16_t dex_register_number,
56 uint16_t number_of_dex_registers,
David Srbecky052f8ca2018-04-26 15:42:54 +010057 const CodeInfo& code_info) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +000058 DexRegisterLocationCatalog dex_register_location_catalog =
David Srbecky052f8ca2018-04-26 15:42:54 +010059 code_info.GetDexRegisterLocationCatalog();
Roland Levillaina552e1c2015-03-26 15:01:03 +000060 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
61 dex_register_number,
62 number_of_dex_registers,
David Srbecky052f8ca2018-04-26 15:42:54 +010063 code_info.GetNumberOfLocationCatalogEntries());
Roland Levillaina552e1c2015-03-26 15:01:03 +000064 return dex_register_location_catalog.GetLocationInternalKind(location_catalog_entry_index);
65}
66
67DexRegisterLocation DexRegisterMap::GetDexRegisterLocation(uint16_t dex_register_number,
68 uint16_t number_of_dex_registers,
David Srbecky052f8ca2018-04-26 15:42:54 +010069 const CodeInfo& code_info) const {
Roland Levillaina552e1c2015-03-26 15:01:03 +000070 DexRegisterLocationCatalog dex_register_location_catalog =
David Srbecky052f8ca2018-04-26 15:42:54 +010071 code_info.GetDexRegisterLocationCatalog();
Roland Levillaina552e1c2015-03-26 15:01:03 +000072 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
73 dex_register_number,
74 number_of_dex_registers,
David Srbecky052f8ca2018-04-26 15:42:54 +010075 code_info.GetNumberOfLocationCatalogEntries());
Roland Levillaina552e1c2015-03-26 15:01:03 +000076 return dex_register_location_catalog.GetDexRegisterLocation(location_catalog_entry_index);
77}
78
Roland Levillaina552e1c2015-03-26 15:01:03 +000079static void DumpRegisterMapping(std::ostream& os,
80 size_t dex_register_num,
81 DexRegisterLocation location,
82 const std::string& prefix = "v",
83 const std::string& suffix = "") {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +010084 os << prefix << dex_register_num << ": "
David Srbecky7dc11782016-02-25 13:23:56 +000085 << location.GetInternalKind()
Vladimir Marko8f1e08a2015-06-26 12:06:30 +010086 << " (" << location.GetValue() << ")" << suffix << '\n';
Roland Levillain0396ed72015-05-27 15:12:19 +010087}
88
David Srbecky052f8ca2018-04-26 15:42:54 +010089void StackMap::DumpEncoding(const BitTable<6>& table,
90 VariableIndentationOutputStream* vios) {
David Srbecky09ed0982016-02-12 21:58:43 +000091 vios->Stream()
92 << "StackMapEncoding"
David Srbecky052f8ca2018-04-26 15:42:54 +010093 << " (NativePcOffsetBits=" << table.NumColumnBits(kNativePcOffset)
94 << ", DexPcBits=" << table.NumColumnBits(kDexPc)
95 << ", DexRegisterMapOffsetBits=" << table.NumColumnBits(kDexRegisterMapOffset)
96 << ", InlineInfoIndexBits=" << table.NumColumnBits(kInlineInfoIndex)
97 << ", RegisterMaskIndexBits=" << table.NumColumnBits(kRegisterMaskIndex)
98 << ", StackMaskIndexBits=" << table.NumColumnBits(kStackMaskIndex)
David Srbecky09ed0982016-02-12 21:58:43 +000099 << ")\n";
100}
101
David Srbecky052f8ca2018-04-26 15:42:54 +0100102void InlineInfo::DumpEncoding(const BitTable<5>& table,
103 VariableIndentationOutputStream* vios) {
David Srbecky61b28a12016-02-25 21:55:03 +0000104 vios->Stream()
105 << "InlineInfoEncoding"
David Srbecky052f8ca2018-04-26 15:42:54 +0100106 << " (IsLastBits=" << table.NumColumnBits(kIsLast)
107 << ", MethodIndexIdxBits=" << table.NumColumnBits(kMethodIndexIdx)
108 << ", DexPcBits=" << table.NumColumnBits(kDexPc)
109 << ", ExtraDataBits=" << table.NumColumnBits(kExtraData)
110 << ", DexRegisterMapOffsetBits=" << table.NumColumnBits(kDexRegisterMapOffset)
David Srbecky61b28a12016-02-25 21:55:03 +0000111 << ")\n";
112}
113
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100114void CodeInfo::Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +0100115 uint32_t code_offset,
Roland Levillain0396ed72015-05-27 15:12:19 +0100116 uint16_t number_of_dex_registers,
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800117 bool dump_stack_maps,
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700118 InstructionSet instruction_set,
119 const MethodInfo& method_info) const {
David Srbecky052f8ca2018-04-26 15:42:54 +0100120 size_t number_of_stack_maps = GetNumberOfStackMaps();
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100121 vios->Stream()
David Srbecky09ed0982016-02-12 21:58:43 +0000122 << "Optimized CodeInfo (number_of_dex_registers=" << number_of_dex_registers
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100123 << ", number_of_stack_maps=" << number_of_stack_maps
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100124 << ")\n";
125 ScopedIndentation indent1(vios);
David Srbecky052f8ca2018-04-26 15:42:54 +0100126 StackMap::DumpEncoding(stack_maps_, vios);
127 if (HasInlineInfo()) {
128 InlineInfo::DumpEncoding(inline_infos_, vios);
David Srbecky61b28a12016-02-25 21:55:03 +0000129 }
Roland Levillaina552e1c2015-03-26 15:01:03 +0000130 // Display the Dex register location catalog.
David Srbecky052f8ca2018-04-26 15:42:54 +0100131 GetDexRegisterLocationCatalog().Dump(vios, *this);
Roland Levillaina552e1c2015-03-26 15:01:03 +0000132 // Display stack maps along with (live) Dex register maps.
Roland Levillain0396ed72015-05-27 15:12:19 +0100133 if (dump_stack_maps) {
134 for (size_t i = 0; i < number_of_stack_maps; ++i) {
David Srbecky052f8ca2018-04-26 15:42:54 +0100135 StackMap stack_map = GetStackMapAt(i);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100136 stack_map.Dump(vios,
David Brazdilf677ebf2015-05-29 16:29:43 +0100137 *this,
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700138 method_info,
David Brazdilf677ebf2015-05-29 16:29:43 +0100139 code_offset,
140 number_of_dex_registers,
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800141 instruction_set,
David Brazdilf677ebf2015-05-29 16:29:43 +0100142 " " + std::to_string(i));
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000143 }
144 }
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100145 // TODO: Dump the stack map's inline information? We need to know more from the caller:
146 // we need to know the number of dex registers for each inlined method.
147}
148
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100149void DexRegisterLocationCatalog::Dump(VariableIndentationOutputStream* vios,
150 const CodeInfo& code_info) {
David Srbecky052f8ca2018-04-26 15:42:54 +0100151 size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
152 size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize();
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100153 vios->Stream()
Roland Levillain0396ed72015-05-27 15:12:19 +0100154 << "DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
155 << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
156 for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
157 DexRegisterLocation location = GetDexRegisterLocation(i);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100158 ScopedIndentation indent1(vios);
159 DumpRegisterMapping(vios->Stream(), i, location, "entry ");
Roland Levillain0396ed72015-05-27 15:12:19 +0100160 }
161}
162
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100163void DexRegisterMap::Dump(VariableIndentationOutputStream* vios,
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100164 const CodeInfo& code_info,
165 uint16_t number_of_dex_registers) const {
David Srbecky052f8ca2018-04-26 15:42:54 +0100166 size_t number_of_location_catalog_entries = code_info.GetNumberOfLocationCatalogEntries();
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100167 // TODO: Display the bit mask of live Dex registers.
168 for (size_t j = 0; j < number_of_dex_registers; ++j) {
169 if (IsDexRegisterLive(j)) {
170 size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
171 j, number_of_dex_registers, number_of_location_catalog_entries);
David Brazdilf677ebf2015-05-29 16:29:43 +0100172 DexRegisterLocation location = GetDexRegisterLocation(j,
173 number_of_dex_registers,
David Srbecky052f8ca2018-04-26 15:42:54 +0100174 code_info);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100175 ScopedIndentation indent1(vios);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100176 DumpRegisterMapping(
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100177 vios->Stream(), j, location, "v",
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100178 "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
179 }
180 }
181}
182
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100183void StackMap::Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +0100184 const CodeInfo& code_info,
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700185 const MethodInfo& method_info,
Roland Levillainf2650d12015-05-28 14:53:28 +0100186 uint32_t code_offset,
187 uint16_t number_of_dex_registers,
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800188 InstructionSet instruction_set,
Roland Levillainf2650d12015-05-28 14:53:28 +0100189 const std::string& header_suffix) const {
David Srbecky052f8ca2018-04-26 15:42:54 +0100190 const uint32_t pc_offset = GetNativePcOffset(instruction_set);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100191 vios->Stream()
192 << "StackMap" << header_suffix
193 << std::hex
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800194 << " [native_pc=0x" << code_offset + pc_offset << "]"
David Srbecky052f8ca2018-04-26 15:42:54 +0100195 << " (dex_pc=0x" << GetDexPc()
Mathieu Chartiera2f526f2017-01-19 14:48:48 -0800196 << ", native_pc_offset=0x" << pc_offset
David Srbecky052f8ca2018-04-26 15:42:54 +0100197 << ", dex_register_map_offset=0x" << GetDexRegisterMapOffset()
198 << ", inline_info_offset=0x" << GetInlineInfoIndex()
199 << ", register_mask=0x" << code_info.GetRegisterMaskOf(*this)
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100200 << std::dec
201 << ", stack_mask=0b";
David Srbecky052f8ca2018-04-26 15:42:54 +0100202 BitMemoryRegion stack_mask = code_info.GetStackMaskOf(*this);
Vladimir Marko8b20b5c2018-05-29 15:32:55 +0000203 for (size_t i = 0, e = code_info.GetNumberOfStackMaskBits(); i < e; ++i) {
David Srbecky45aa5982016-03-18 02:15:09 +0000204 vios->Stream() << stack_mask.LoadBit(e - i - 1);
Roland Levillainf2650d12015-05-28 14:53:28 +0100205 }
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100206 vios->Stream() << ")\n";
David Srbecky052f8ca2018-04-26 15:42:54 +0100207 if (HasDexRegisterMap()) {
David Brazdilf677ebf2015-05-29 16:29:43 +0100208 DexRegisterMap dex_register_map = code_info.GetDexRegisterMapOf(
David Srbecky052f8ca2018-04-26 15:42:54 +0100209 *this, number_of_dex_registers);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100210 dex_register_map.Dump(vios, code_info, number_of_dex_registers);
Roland Levillainf2650d12015-05-28 14:53:28 +0100211 }
David Srbecky052f8ca2018-04-26 15:42:54 +0100212 if (HasInlineInfo()) {
213 InlineInfo inline_info = code_info.GetInlineInfoOf(*this);
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100214 // We do not know the length of the dex register maps of inlined frames
215 // at this level, so we just pass null to `InlineInfo::Dump` to tell
216 // it not to look at these maps.
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700217 inline_info.Dump(vios, code_info, method_info, nullptr);
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100218 }
Roland Levillainf2650d12015-05-28 14:53:28 +0100219}
220
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100221void InlineInfo::Dump(VariableIndentationOutputStream* vios,
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100222 const CodeInfo& code_info,
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700223 const MethodInfo& method_info,
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100224 uint16_t number_of_dex_registers[]) const {
David Srbecky61b28a12016-02-25 21:55:03 +0000225 vios->Stream() << "InlineInfo with depth "
David Srbecky052f8ca2018-04-26 15:42:54 +0100226 << static_cast<uint32_t>(GetDepth())
David Srbecky61b28a12016-02-25 21:55:03 +0000227 << "\n";
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100228
David Srbecky052f8ca2018-04-26 15:42:54 +0100229 for (size_t i = 0; i < GetDepth(); ++i) {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100230 vios->Stream()
231 << " At depth " << i
232 << std::hex
David Srbecky052f8ca2018-04-26 15:42:54 +0100233 << " (dex_pc=0x" << GetDexPcAtDepth(i);
234 if (EncodesArtMethodAtDepth(i)) {
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000235 ScopedObjectAccess soa(Thread::Current());
David Srbecky052f8ca2018-04-26 15:42:54 +0100236 vios->Stream() << ", method=" << GetArtMethodAtDepth(i)->PrettyMethod();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000237 } else {
238 vios->Stream()
239 << std::dec
David Srbecky052f8ca2018-04-26 15:42:54 +0100240 << ", method_index=" << GetMethodIndexAtDepth(method_info, i);
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000241 }
242 vios->Stream() << ")\n";
David Srbecky052f8ca2018-04-26 15:42:54 +0100243 if (HasDexRegisterMapAtDepth(i) && (number_of_dex_registers != nullptr)) {
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100244 DexRegisterMap dex_register_map =
David Srbecky052f8ca2018-04-26 15:42:54 +0100245 code_info.GetDexRegisterMapAtDepth(i, *this, number_of_dex_registers[i]);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100246 ScopedIndentation indent1(vios);
247 dex_register_map.Dump(vios, code_info, number_of_dex_registers[i]);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100248 }
249 }
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000250}
251
252} // namespace art