From 96faf5b363d922ae91cf25404dee0e87c740c7c5 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 9 Aug 2013 22:05:32 -0700 Subject: Uleb128 compression of vmap and mapping table. Bug 9437697. Change-Id: I30bcb97d12cd8b46d3b2cdcbdd358f08fbb9947a (cherry picked from commit 1809a72a66d245ae598582d658b93a24ac3bf01e) --- runtime/mapping_table.h | 196 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 runtime/mapping_table.h (limited to 'runtime/mapping_table.h') diff --git a/runtime/mapping_table.h b/runtime/mapping_table.h new file mode 100644 index 0000000..2162008 --- /dev/null +++ b/runtime/mapping_table.h @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_MAPPING_TABLE_H_ +#define ART_RUNTIME_MAPPING_TABLE_H_ + +#include "base/logging.h" +#include "leb128.h" + +namespace art { + +// A utility for processing the raw uleb128 encoded mapping table created by the quick compiler. +class MappingTable { + public: + explicit MappingTable(const uint8_t* encoded_map) : encoded_table_(encoded_map) { + } + + uint32_t TotalSize() const PURE { + const uint8_t* table = encoded_table_; + if (table == NULL) { + return 0; + } else { + return DecodeUnsignedLeb128(&table); + } + } + + uint32_t DexToPcSize() const PURE { + const uint8_t* table = encoded_table_; + if (table == NULL) { + return 0; + } else { + uint32_t total_size = DecodeUnsignedLeb128(&table); + uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table); + return total_size - pc_to_dex_size; + } + } + + const uint8_t* FirstDexToPcPtr() const { + const uint8_t* table = encoded_table_; + if (table != NULL) { + DecodeUnsignedLeb128(&table); // Total_size, unused. + uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table); + for (uint32_t i = 0; i < pc_to_dex_size; ++i) { + DecodeUnsignedLeb128(&table); // Move ptr past native PC. + DecodeUnsignedLeb128(&table); // Move ptr past dex PC. + } + } + return table; + } + + class DexToPcIterator { + public: + DexToPcIterator(const MappingTable* table, uint32_t element) : + table_(table), element_(element), end_(table_->DexToPcSize()), encoded_table_ptr_(NULL), + native_pc_offset_(0), dex_pc_(0) { + if (element == 0) { + encoded_table_ptr_ = table_->FirstDexToPcPtr(); + native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_); + dex_pc_ = DecodeUnsignedLeb128(&encoded_table_ptr_); + } else { + DCHECK_EQ(table_->DexToPcSize(), element); + } + } + uint32_t NativePcOffset() const { + return native_pc_offset_; + } + uint32_t DexPc() const { + return dex_pc_; + } + void operator++() { + ++element_; + if (element_ != end_) { // Avoid reading beyond the end of the table. + native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_); + dex_pc_ = DecodeUnsignedLeb128(&encoded_table_ptr_); + } + } + bool operator==(const DexToPcIterator& rhs) const { + CHECK(table_ == rhs.table_); + return element_ == rhs.element_; + } + bool operator!=(const DexToPcIterator& rhs) const { + CHECK(table_ == rhs.table_); + return element_ != rhs.element_; + } + + private: + const MappingTable* const table_; // The original table. + uint32_t element_; // A value in the range 0 to end_. + const uint32_t end_; // Equal to table_->DexToPcSize(). + const uint8_t* encoded_table_ptr_; // Either NULL or points to encoded data after this entry. + uint32_t native_pc_offset_; // The current value of native pc offset. + uint32_t dex_pc_; // The current value of dex pc. + }; + + DexToPcIterator DexToPcBegin() const { + return DexToPcIterator(this, 0); + } + + DexToPcIterator DexToPcEnd() const { + uint32_t size = DexToPcSize(); + return DexToPcIterator(this, size); + } + + uint32_t PcToDexSize() const PURE { + const uint8_t* table = encoded_table_; + if (table == NULL) { + return 0; + } else { + DecodeUnsignedLeb128(&table); // Total_size, unused. + uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table); + return pc_to_dex_size; + } + } + + const uint8_t* FirstPcToDexPtr() const { + const uint8_t* table = encoded_table_; + if (table != NULL) { + DecodeUnsignedLeb128(&table); // Total_size, unused. + DecodeUnsignedLeb128(&table); // PC to Dex size, unused. + } + return table; + } + + class PcToDexIterator { + public: + PcToDexIterator(const MappingTable* table, uint32_t element) : + table_(table), element_(element), end_(table_->PcToDexSize()), encoded_table_ptr_(NULL), + native_pc_offset_(0), dex_pc_(0) { + if (element == 0) { + encoded_table_ptr_ = table_->FirstPcToDexPtr(); + native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_); + dex_pc_ = DecodeUnsignedLeb128(&encoded_table_ptr_); + } else { + DCHECK_EQ(table_->PcToDexSize(), element); + } + } + uint32_t NativePcOffset() const { + return native_pc_offset_; + } + uint32_t DexPc() const { + return dex_pc_; + } + void operator++() { + ++element_; + if (element_ != end_) { // Avoid reading beyond the end of the table. + native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_); + dex_pc_ = DecodeUnsignedLeb128(&encoded_table_ptr_); + } + } + bool operator==(const PcToDexIterator& rhs) const { + CHECK(table_ == rhs.table_); + return element_ == rhs.element_; + } + bool operator!=(const PcToDexIterator& rhs) const { + CHECK(table_ == rhs.table_); + return element_ != rhs.element_; + } + + private: + const MappingTable* const table_; // The original table. + uint32_t element_; // A value in the range 0 to PcToDexSize. + const uint32_t end_; // Equal to table_->PcToDexSize(). + const uint8_t* encoded_table_ptr_; // Either NULL or points to encoded data after this entry. + uint32_t native_pc_offset_; // The current value of native pc offset. + uint32_t dex_pc_; // The current value of dex pc. + }; + + PcToDexIterator PcToDexBegin() const { + return PcToDexIterator(this, 0); + } + + PcToDexIterator PcToDexEnd() const { + uint32_t size = PcToDexSize(); + return PcToDexIterator(this, size); + } + + private: + const uint8_t* const encoded_table_; +}; + +} // namespace art + +#endif // ART_RUNTIME_MAPPING_TABLE_H_ -- cgit v1.1