blob: 79e6e94daa3f57a7757dd53e35ca8c1fd3930597 [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) {
Vladimir Marko12d16ad2014-02-27 13:42:09 +000059 DecodeUnsignedLeb128(&table); // Move ptr past native PC delta.
60 DecodeSignedLeb128(&table); // Move ptr past dex PC delta.
Ian Rogers96faf5b2013-08-09 22:05:32 -070061 }
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_);
Vladimir Marko1e6cb632013-11-28 16:27:29 +000075 // First delta is always positive.
76 dex_pc_ = static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_));
Ian Rogers20ab6c82013-11-13 23:31:08 -080077 }
Ian Rogers159aa952013-11-14 14:51:11 -080078 } else { // An iterator wanted from the end.
Ian Rogers96faf5b2013-08-09 22:05:32 -070079 DCHECK_EQ(table_->DexToPcSize(), element);
80 }
81 }
82 uint32_t NativePcOffset() const {
83 return native_pc_offset_;
84 }
85 uint32_t DexPc() const {
86 return dex_pc_;
87 }
88 void operator++() {
89 ++element_;
90 if (element_ != end_) { // Avoid reading beyond the end of the table.
Vladimir Marko1e6cb632013-11-28 16:27:29 +000091 native_pc_offset_ += DecodeUnsignedLeb128(&encoded_table_ptr_);
92 // For negative delta, unsigned overflow after static_cast does exactly what we need.
93 dex_pc_ += static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_));
Ian Rogers96faf5b2013-08-09 22:05:32 -070094 }
95 }
96 bool operator==(const DexToPcIterator& rhs) const {
97 CHECK(table_ == rhs.table_);
98 return element_ == rhs.element_;
99 }
100 bool operator!=(const DexToPcIterator& rhs) const {
101 CHECK(table_ == rhs.table_);
102 return element_ != rhs.element_;
103 }
104
105 private:
106 const MappingTable* const table_; // The original table.
107 uint32_t element_; // A value in the range 0 to end_.
108 const uint32_t end_; // Equal to table_->DexToPcSize().
Ian Rogers159aa952013-11-14 14:51:11 -0800109 const uint8_t* encoded_table_ptr_; // Either nullptr or points to encoded data after this entry.
Ian Rogers96faf5b2013-08-09 22:05:32 -0700110 uint32_t native_pc_offset_; // The current value of native pc offset.
111 uint32_t dex_pc_; // The current value of dex pc.
112 };
113
114 DexToPcIterator DexToPcBegin() const {
115 return DexToPcIterator(this, 0);
116 }
117
118 DexToPcIterator DexToPcEnd() const {
119 uint32_t size = DexToPcSize();
120 return DexToPcIterator(this, size);
121 }
122
123 uint32_t PcToDexSize() const PURE {
124 const uint8_t* table = encoded_table_;
Ian Rogers159aa952013-11-14 14:51:11 -0800125 if (table == nullptr) {
Ian Rogers96faf5b2013-08-09 22:05:32 -0700126 return 0;
127 } else {
128 DecodeUnsignedLeb128(&table); // Total_size, unused.
129 uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table);
130 return pc_to_dex_size;
131 }
132 }
133
134 const uint8_t* FirstPcToDexPtr() const {
135 const uint8_t* table = encoded_table_;
Ian Rogers159aa952013-11-14 14:51:11 -0800136 if (table != nullptr) {
Ian Rogers96faf5b2013-08-09 22:05:32 -0700137 DecodeUnsignedLeb128(&table); // Total_size, unused.
138 DecodeUnsignedLeb128(&table); // PC to Dex size, unused.
139 }
140 return table;
141 }
142
143 class PcToDexIterator {
144 public:
145 PcToDexIterator(const MappingTable* table, uint32_t element) :
Ian Rogers159aa952013-11-14 14:51:11 -0800146 table_(table), element_(element), end_(table_->PcToDexSize()), encoded_table_ptr_(nullptr),
Ian Rogers96faf5b2013-08-09 22:05:32 -0700147 native_pc_offset_(0), dex_pc_(0) {
Ian Rogers159aa952013-11-14 14:51:11 -0800148 if (element == 0) { // An iterator wanted from the start.
Ian Rogers20ab6c82013-11-13 23:31:08 -0800149 if (end_ > 0) {
Ian Rogers159aa952013-11-14 14:51:11 -0800150 encoded_table_ptr_ = table_->FirstPcToDexPtr();
Ian Rogers20ab6c82013-11-13 23:31:08 -0800151 native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
Vladimir Marko1e6cb632013-11-28 16:27:29 +0000152 // First delta is always positive.
153 dex_pc_ = static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_));
Ian Rogers20ab6c82013-11-13 23:31:08 -0800154 }
Ian Rogers159aa952013-11-14 14:51:11 -0800155 } else { // An iterator wanted from the end.
Ian Rogers96faf5b2013-08-09 22:05:32 -0700156 DCHECK_EQ(table_->PcToDexSize(), element);
157 }
158 }
159 uint32_t NativePcOffset() const {
160 return native_pc_offset_;
161 }
162 uint32_t DexPc() const {
163 return dex_pc_;
164 }
165 void operator++() {
166 ++element_;
167 if (element_ != end_) { // Avoid reading beyond the end of the table.
Vladimir Marko1e6cb632013-11-28 16:27:29 +0000168 native_pc_offset_ += DecodeUnsignedLeb128(&encoded_table_ptr_);
169 // For negative delta, unsigned overflow after static_cast does exactly what we need.
170 dex_pc_ += static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_));
Ian Rogers96faf5b2013-08-09 22:05:32 -0700171 }
172 }
173 bool operator==(const PcToDexIterator& rhs) const {
174 CHECK(table_ == rhs.table_);
175 return element_ == rhs.element_;
176 }
177 bool operator!=(const PcToDexIterator& rhs) const {
178 CHECK(table_ == rhs.table_);
179 return element_ != rhs.element_;
180 }
181
182 private:
183 const MappingTable* const table_; // The original table.
184 uint32_t element_; // A value in the range 0 to PcToDexSize.
185 const uint32_t end_; // Equal to table_->PcToDexSize().
Ian Rogers159aa952013-11-14 14:51:11 -0800186 const uint8_t* encoded_table_ptr_; // Either null or points to encoded data after this entry.
Ian Rogers96faf5b2013-08-09 22:05:32 -0700187 uint32_t native_pc_offset_; // The current value of native pc offset.
188 uint32_t dex_pc_; // The current value of dex pc.
189 };
190
191 PcToDexIterator PcToDexBegin() const {
192 return PcToDexIterator(this, 0);
193 }
194
195 PcToDexIterator PcToDexEnd() const {
196 uint32_t size = PcToDexSize();
197 return PcToDexIterator(this, size);
198 }
199
200 private:
201 const uint8_t* const encoded_table_;
202};
203
204} // namespace art
205
206#endif // ART_RUNTIME_MAPPING_TABLE_H_