blob: 923bb3559a215a3a886bf1249749b4600c8e3637 [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
David Srbecky71ec1cc2018-05-18 15:57:25 +010019#include <iomanip>
Nicolas Geoffray896f8f72015-03-30 15:44:25 +010020#include <stdint.h>
21
Nicolas Geoffray5d37c152017-01-12 13:25:19 +000022#include "art_method.h"
David Sehr9c4a0152018-04-05 12:23:54 -070023#include "base/indenter.h"
Nicolas Geoffray5d37c152017-01-12 13:25:19 +000024#include "scoped_thread_state_change-inl.h"
Roland Levillain0396ed72015-05-27 15:12:19 +010025
Nicolas Geoffray004c2302015-03-20 10:06:38 +000026namespace art {
27
David Srbecky71ec1cc2018-05-18 15:57:25 +010028std::ostream& operator<<(std::ostream& stream, const DexRegisterLocation& reg) {
David Srbecky7dc11782016-02-25 13:23:56 +000029 using Kind = DexRegisterLocation::Kind;
David Srbecky71ec1cc2018-05-18 15:57:25 +010030 switch (reg.GetKind()) {
David Srbecky7dc11782016-02-25 13:23:56 +000031 case Kind::kNone:
David Srbecky71ec1cc2018-05-18 15:57:25 +010032 return stream << "None";
David Srbecky7dc11782016-02-25 13:23:56 +000033 case Kind::kInStack:
David Srbecky71ec1cc2018-05-18 15:57:25 +010034 return stream << "sp+" << reg.GetValue();
David Srbecky7dc11782016-02-25 13:23:56 +000035 case Kind::kInRegister:
David Srbecky71ec1cc2018-05-18 15:57:25 +010036 return stream << "r" << reg.GetValue();
David Srbecky7dc11782016-02-25 13:23:56 +000037 case Kind::kInRegisterHigh:
David Srbecky71ec1cc2018-05-18 15:57:25 +010038 return stream << "r" << reg.GetValue() << "/hi";
David Srbecky7dc11782016-02-25 13:23:56 +000039 case Kind::kInFpuRegister:
David Srbecky71ec1cc2018-05-18 15:57:25 +010040 return stream << "f" << reg.GetValue();
David Srbecky7dc11782016-02-25 13:23:56 +000041 case Kind::kInFpuRegisterHigh:
David Srbecky71ec1cc2018-05-18 15:57:25 +010042 return stream << "f" << reg.GetValue() << "/hi";
David Srbecky7dc11782016-02-25 13:23:56 +000043 case Kind::kConstant:
David Srbecky71ec1cc2018-05-18 15:57:25 +010044 return stream << "#" << reg.GetValue();
45 default:
46 return stream << "DexRegisterLocation(" << static_cast<uint32_t>(reg.GetKind())
47 << "," << reg.GetValue() << ")";
David Srbecky7dc11782016-02-25 13:23:56 +000048 }
David Srbecky7dc11782016-02-25 13:23:56 +000049}
50
David Srbecky71ec1cc2018-05-18 15:57:25 +010051static void DumpDexRegisterMap(VariableIndentationOutputStream* vios,
52 const DexRegisterMap& map) {
53 if (map.IsValid()) {
54 ScopedIndentation indent1(vios);
55 for (size_t i = 0; i < map.size(); ++i) {
56 if (map.IsDexRegisterLive(i)) {
57 vios->Stream() << "v" << i << ":" << map.Get(i) << " ";
58 }
59 }
60 vios->Stream() << "\n";
61 }
Roland Levillaina552e1c2015-03-26 15:01:03 +000062}
63
David Srbecky71ec1cc2018-05-18 15:57:25 +010064template<uint32_t kNumColumns>
65static void DumpTable(VariableIndentationOutputStream* vios,
66 const char* table_name,
67 const BitTable<kNumColumns>& table,
68 bool verbose,
69 bool is_mask = false) {
70 if (table.NumRows() != 0) {
71 vios->Stream() << table_name << " BitSize=" << table.NumRows() * table.NumRowBits();
72 vios->Stream() << " Rows=" << table.NumRows() << " Bits={";
73 for (size_t c = 0; c < table.NumColumns(); c++) {
74 vios->Stream() << (c != 0 ? " " : "");
75 vios->Stream() << table.NumColumnBits(c);
76 }
77 vios->Stream() << "}\n";
78 if (verbose) {
79 ScopedIndentation indent1(vios);
80 for (size_t r = 0; r < table.NumRows(); r++) {
81 vios->Stream() << "[" << std::right << std::setw(3) << r << "]={";
82 for (size_t c = 0; c < table.NumColumns(); c++) {
83 vios->Stream() << (c != 0 ? " " : "");
84 if (is_mask) {
85 BitMemoryRegion bits = table.GetBitMemoryRegion(r, c);
86 for (size_t b = 0, e = bits.size_in_bits(); b < e; b++) {
87 vios->Stream() << bits.LoadBit(e - b - 1);
88 }
89 } else {
90 vios->Stream() << std::right << std::setw(8) << static_cast<int32_t>(table.Get(r, c));
91 }
92 }
93 vios->Stream() << "}\n";
94 }
95 }
96 }
David Srbecky61b28a12016-02-25 21:55:03 +000097}
98
Vladimir Marko8f1e08a2015-06-26 12:06:30 +010099void CodeInfo::Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +0100100 uint32_t code_offset,
David Srbecky71ec1cc2018-05-18 15:57:25 +0100101 uint16_t num_dex_registers,
102 bool verbose,
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700103 InstructionSet instruction_set,
104 const MethodInfo& method_info) const {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100105 vios->Stream()
David Srbecky71ec1cc2018-05-18 15:57:25 +0100106 << "CodeInfo"
107 << " BitSize=" << size_ * kBitsPerByte
108 << "\n";
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100109 ScopedIndentation indent1(vios);
David Srbecky71ec1cc2018-05-18 15:57:25 +0100110 DumpTable(vios, "StackMaps", stack_maps_, verbose);
111 DumpTable(vios, "RegisterMasks", register_masks_, verbose);
112 DumpTable(vios, "StackMasks", stack_masks_, verbose, true /* is_mask */);
113 DumpTable(vios, "InvokeInfos", invoke_infos_, verbose);
114 DumpTable(vios, "InlineInfos", inline_infos_, verbose);
115 DumpTable(vios, "DexRegisterMasks", dex_register_masks_, verbose, true /* is_mask */);
116 DumpTable(vios, "DexRegisterMaps", dex_register_maps_, verbose);
117 DumpTable(vios, "DexRegisterCatalog", dex_register_catalog_, verbose);
118
Roland Levillaina552e1c2015-03-26 15:01:03 +0000119 // Display stack maps along with (live) Dex register maps.
David Srbecky71ec1cc2018-05-18 15:57:25 +0100120 if (verbose) {
121 for (size_t i = 0; i < GetNumberOfStackMaps(); ++i) {
David Srbecky052f8ca2018-04-26 15:42:54 +0100122 StackMap stack_map = GetStackMapAt(i);
David Srbecky71ec1cc2018-05-18 15:57:25 +0100123 stack_map.Dump(vios, *this, method_info, code_offset, num_dex_registers, instruction_set);
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100124 }
125 }
126}
127
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100128void StackMap::Dump(VariableIndentationOutputStream* vios,
Roland Levillainf2650d12015-05-28 14:53:28 +0100129 const CodeInfo& code_info,
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700130 const MethodInfo& method_info,
Roland Levillainf2650d12015-05-28 14:53:28 +0100131 uint32_t code_offset,
132 uint16_t number_of_dex_registers,
David Srbecky71ec1cc2018-05-18 15:57:25 +0100133 InstructionSet instruction_set) const {
David Srbecky052f8ca2018-04-26 15:42:54 +0100134 const uint32_t pc_offset = GetNativePcOffset(instruction_set);
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100135 vios->Stream()
David Srbecky71ec1cc2018-05-18 15:57:25 +0100136 << "StackMap[" << Row() << "]"
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100137 << std::hex
David Srbecky71ec1cc2018-05-18 15:57:25 +0100138 << " (native_pc=0x" << code_offset + pc_offset
139 << ", dex_pc=0x" << GetDexPc()
David Srbecky052f8ca2018-04-26 15:42:54 +0100140 << ", register_mask=0x" << code_info.GetRegisterMaskOf(*this)
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100141 << std::dec
142 << ", stack_mask=0b";
David Srbecky052f8ca2018-04-26 15:42:54 +0100143 BitMemoryRegion stack_mask = code_info.GetStackMaskOf(*this);
David Srbecky4b59d102018-05-29 21:46:10 +0000144 for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
David Srbecky45aa5982016-03-18 02:15:09 +0000145 vios->Stream() << stack_mask.LoadBit(e - i - 1);
Roland Levillainf2650d12015-05-28 14:53:28 +0100146 }
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100147 vios->Stream() << ")\n";
David Srbecky71ec1cc2018-05-18 15:57:25 +0100148 DumpDexRegisterMap(vios, code_info.GetDexRegisterMapOf(*this, number_of_dex_registers));
David Srbecky052f8ca2018-04-26 15:42:54 +0100149 if (HasInlineInfo()) {
150 InlineInfo inline_info = code_info.GetInlineInfoOf(*this);
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100151 // We do not know the length of the dex register maps of inlined frames
152 // at this level, so we just pass null to `InlineInfo::Dump` to tell
153 // it not to look at these maps.
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700154 inline_info.Dump(vios, code_info, method_info, nullptr);
Nicolas Geoffray12bdb722015-06-17 09:44:43 +0100155 }
Roland Levillainf2650d12015-05-28 14:53:28 +0100156}
157
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100158void InlineInfo::Dump(VariableIndentationOutputStream* vios,
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100159 const CodeInfo& code_info,
Mathieu Chartiercbcedbf2017-03-12 22:24:50 -0700160 const MethodInfo& method_info,
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100161 uint16_t number_of_dex_registers[]) const {
David Srbecky052f8ca2018-04-26 15:42:54 +0100162 for (size_t i = 0; i < GetDepth(); ++i) {
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100163 vios->Stream()
David Srbecky71ec1cc2018-05-18 15:57:25 +0100164 << "InlineInfo[" << Row() + i << "]"
165 << " (depth=" << i
Vladimir Marko8f1e08a2015-06-26 12:06:30 +0100166 << std::hex
David Srbecky71ec1cc2018-05-18 15:57:25 +0100167 << ", dex_pc=0x" << GetDexPcAtDepth(i);
David Srbecky052f8ca2018-04-26 15:42:54 +0100168 if (EncodesArtMethodAtDepth(i)) {
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000169 ScopedObjectAccess soa(Thread::Current());
David Srbecky052f8ca2018-04-26 15:42:54 +0100170 vios->Stream() << ", method=" << GetArtMethodAtDepth(i)->PrettyMethod();
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000171 } else {
172 vios->Stream()
173 << std::dec
David Srbecky052f8ca2018-04-26 15:42:54 +0100174 << ", method_index=" << GetMethodIndexAtDepth(method_info, i);
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000175 }
176 vios->Stream() << ")\n";
David Srbecky71ec1cc2018-05-18 15:57:25 +0100177 if (number_of_dex_registers != nullptr) {
178 uint16_t vregs = number_of_dex_registers[i];
179 DumpDexRegisterMap(vios, code_info.GetDexRegisterMapAtDepth(i, *this, vregs));
Nicolas Geoffrayb1d0f3f2015-05-14 12:41:51 +0100180 }
181 }
Nicolas Geoffray004c2302015-03-20 10:06:38 +0000182}
183
184} // namespace art