blob: c468c1efb4c434c4f2c6ad508b7d4a80bd885180 [file] [log] [blame]
Ian Rogers96faf5b2013-08-09 22:05:32 -07001/*
2 * Copyright (C) 2013 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#ifndef ART_RUNTIME_MAPPING_TABLE_H_
18#define ART_RUNTIME_MAPPING_TABLE_H_
19
20#include "base/logging.h"
21#include "leb128.h"
22
23namespace art {
24
25// A utility for processing the raw uleb128 encoded mapping table created by the quick compiler.
26class MappingTable {
27 public:
28 explicit MappingTable(const uint8_t* encoded_map) : encoded_table_(encoded_map) {
29 }
30
31 uint32_t TotalSize() const PURE {
32 const uint8_t* table = encoded_table_;
Ian Rogers159aa952013-11-14 14:51:11 -080033 if (table == nullptr) {
Ian Rogers96faf5b2013-08-09 22:05:32 -070034 return 0;
35 } else {
36 return DecodeUnsignedLeb128(&table);
37 }
38 }
39
40 uint32_t DexToPcSize() const PURE {
41 const uint8_t* table = encoded_table_;
Ian Rogers159aa952013-11-14 14:51:11 -080042 if (table == nullptr) {
Ian Rogers96faf5b2013-08-09 22:05:32 -070043 return 0;
44 } else {
45 uint32_t total_size = DecodeUnsignedLeb128(&table);
46 uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table);
47 return total_size - pc_to_dex_size;
48 }
49 }
50
51 const uint8_t* FirstDexToPcPtr() const {
52 const uint8_t* table = encoded_table_;
Ian Rogers159aa952013-11-14 14:51:11 -080053 if (table != nullptr) {
54 uint32_t total_size = DecodeUnsignedLeb128(&table);
Ian Rogers96faf5b2013-08-09 22:05:32 -070055 uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table);
Ian Rogers159aa952013-11-14 14:51:11 -080056 // We must have dex to pc entries or else the loop will go beyond the end of the table.
57 DCHECK_GT(total_size, pc_to_dex_size);
Ian Rogers96faf5b2013-08-09 22:05:32 -070058 for (uint32_t i = 0; i < pc_to_dex_size; ++i) {
59 DecodeUnsignedLeb128(&table); // Move ptr past native PC.
60 DecodeUnsignedLeb128(&table); // Move ptr past dex PC.
61 }
62 }
63 return table;
64 }
65
66 class DexToPcIterator {
67 public:
68 DexToPcIterator(const MappingTable* table, uint32_t element) :
Ian Rogers159aa952013-11-14 14:51:11 -080069 table_(table), element_(element), end_(table_->DexToPcSize()), encoded_table_ptr_(nullptr),
Ian Rogers96faf5b2013-08-09 22:05:32 -070070 native_pc_offset_(0), dex_pc_(0) {
Ian Rogers159aa952013-11-14 14:51:11 -080071 if (element == 0) { // An iterator wanted from the start.
Ian Rogers20ab6c82013-11-13 23:31:08 -080072 if (end_ > 0) {
Ian Rogers159aa952013-11-14 14:51:11 -080073 encoded_table_ptr_ = table_->FirstDexToPcPtr();
Ian Rogers20ab6c82013-11-13 23:31:08 -080074 native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
75 dex_pc_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
76 }
Ian Rogers159aa952013-11-14 14:51:11 -080077 } else { // An iterator wanted from the end.
Ian Rogers96faf5b2013-08-09 22:05:32 -070078 DCHECK_EQ(table_->DexToPcSize(), element);
79 }
80 }
81 uint32_t NativePcOffset() const {
82 return native_pc_offset_;
83 }
84 uint32_t DexPc() const {
85 return dex_pc_;
86 }
87 void operator++() {
88 ++element_;
89 if (element_ != end_) { // Avoid reading beyond the end of the table.
90 native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
91 dex_pc_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
92 }
93 }
94 bool operator==(const DexToPcIterator& rhs) const {
95 CHECK(table_ == rhs.table_);
96 return element_ == rhs.element_;
97 }
98 bool operator!=(const DexToPcIterator& rhs) const {
99 CHECK(table_ == rhs.table_);
100 return element_ != rhs.element_;
101 }
102
103 private:
104 const MappingTable* const table_; // The original table.
105 uint32_t element_; // A value in the range 0 to end_.
106 const uint32_t end_; // Equal to table_->DexToPcSize().
Ian Rogers159aa952013-11-14 14:51:11 -0800107 const uint8_t* encoded_table_ptr_; // Either nullptr or points to encoded data after this entry.
Ian Rogers96faf5b2013-08-09 22:05:32 -0700108 uint32_t native_pc_offset_; // The current value of native pc offset.
109 uint32_t dex_pc_; // The current value of dex pc.
110 };
111
112 DexToPcIterator DexToPcBegin() const {
113 return DexToPcIterator(this, 0);
114 }
115
116 DexToPcIterator DexToPcEnd() const {
117 uint32_t size = DexToPcSize();
118 return DexToPcIterator(this, size);
119 }
120
121 uint32_t PcToDexSize() const PURE {
122 const uint8_t* table = encoded_table_;
Ian Rogers159aa952013-11-14 14:51:11 -0800123 if (table == nullptr) {
Ian Rogers96faf5b2013-08-09 22:05:32 -0700124 return 0;
125 } else {
126 DecodeUnsignedLeb128(&table); // Total_size, unused.
127 uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table);
128 return pc_to_dex_size;
129 }
130 }
131
132 const uint8_t* FirstPcToDexPtr() const {
133 const uint8_t* table = encoded_table_;
Ian Rogers159aa952013-11-14 14:51:11 -0800134 if (table != nullptr) {
Ian Rogers96faf5b2013-08-09 22:05:32 -0700135 DecodeUnsignedLeb128(&table); // Total_size, unused.
136 DecodeUnsignedLeb128(&table); // PC to Dex size, unused.
137 }
138 return table;
139 }
140
141 class PcToDexIterator {
142 public:
143 PcToDexIterator(const MappingTable* table, uint32_t element) :
Ian Rogers159aa952013-11-14 14:51:11 -0800144 table_(table), element_(element), end_(table_->PcToDexSize()), encoded_table_ptr_(nullptr),
Ian Rogers96faf5b2013-08-09 22:05:32 -0700145 native_pc_offset_(0), dex_pc_(0) {
Ian Rogers159aa952013-11-14 14:51:11 -0800146 if (element == 0) { // An iterator wanted from the start.
Ian Rogers20ab6c82013-11-13 23:31:08 -0800147 if (end_ > 0) {
Ian Rogers159aa952013-11-14 14:51:11 -0800148 encoded_table_ptr_ = table_->FirstPcToDexPtr();
Ian Rogers20ab6c82013-11-13 23:31:08 -0800149 native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
150 dex_pc_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
151 }
Ian Rogers159aa952013-11-14 14:51:11 -0800152 } else { // An iterator wanted from the end.
Ian Rogers96faf5b2013-08-09 22:05:32 -0700153 DCHECK_EQ(table_->PcToDexSize(), element);
154 }
155 }
156 uint32_t NativePcOffset() const {
157 return native_pc_offset_;
158 }
159 uint32_t DexPc() const {
160 return dex_pc_;
161 }
162 void operator++() {
163 ++element_;
164 if (element_ != end_) { // Avoid reading beyond the end of the table.
165 native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
166 dex_pc_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
167 }
168 }
169 bool operator==(const PcToDexIterator& rhs) const {
170 CHECK(table_ == rhs.table_);
171 return element_ == rhs.element_;
172 }
173 bool operator!=(const PcToDexIterator& rhs) const {
174 CHECK(table_ == rhs.table_);
175 return element_ != rhs.element_;
176 }
177
178 private:
179 const MappingTable* const table_; // The original table.
180 uint32_t element_; // A value in the range 0 to PcToDexSize.
181 const uint32_t end_; // Equal to table_->PcToDexSize().
Ian Rogers159aa952013-11-14 14:51:11 -0800182 const uint8_t* encoded_table_ptr_; // Either null or points to encoded data after this entry.
Ian Rogers96faf5b2013-08-09 22:05:32 -0700183 uint32_t native_pc_offset_; // The current value of native pc offset.
184 uint32_t dex_pc_; // The current value of dex pc.
185 };
186
187 PcToDexIterator PcToDexBegin() const {
188 return PcToDexIterator(this, 0);
189 }
190
191 PcToDexIterator PcToDexEnd() const {
192 uint32_t size = PcToDexSize();
193 return PcToDexIterator(this, size);
194 }
195
196 private:
197 const uint8_t* const encoded_table_;
198};
199
200} // namespace art
201
202#endif // ART_RUNTIME_MAPPING_TABLE_H_