Home | History | Annotate | Download | only in runtime
      1 /*
      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 
     23 namespace art {
     24 
     25 // A utility for processing the raw uleb128 encoded mapping table created by the quick compiler.
     26 class 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_;
     33     if (table == NULL) {
     34       return 0;
     35     } else {
     36       return DecodeUnsignedLeb128(&table);
     37     }
     38   }
     39 
     40   uint32_t DexToPcSize() const PURE {
     41     const uint8_t* table = encoded_table_;
     42     if (table == NULL) {
     43       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_;
     53     if (table != NULL) {
     54       DecodeUnsignedLeb128(&table);  // Total_size, unused.
     55       uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table);
     56       for (uint32_t i = 0; i < pc_to_dex_size; ++i) {
     57         DecodeUnsignedLeb128(&table);  // Move ptr past native PC.
     58         DecodeUnsignedLeb128(&table);  // Move ptr past dex PC.
     59       }
     60     }
     61     return table;
     62   }
     63 
     64   class DexToPcIterator {
     65    public:
     66     DexToPcIterator(const MappingTable* table, uint32_t element) :
     67         table_(table), element_(element), end_(table_->DexToPcSize()), encoded_table_ptr_(NULL),
     68         native_pc_offset_(0), dex_pc_(0) {
     69       if (element == 0) {
     70         encoded_table_ptr_ = table_->FirstDexToPcPtr();
     71         native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
     72         dex_pc_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
     73       } else {
     74         DCHECK_EQ(table_->DexToPcSize(), element);
     75       }
     76     }
     77     uint32_t NativePcOffset() const {
     78       return native_pc_offset_;
     79     }
     80     uint32_t DexPc() const {
     81       return dex_pc_;
     82     }
     83     void operator++() {
     84       ++element_;
     85       if (element_ != end_) {  // Avoid reading beyond the end of the table.
     86         native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
     87         dex_pc_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
     88       }
     89     }
     90     bool operator==(const DexToPcIterator& rhs) const {
     91       CHECK(table_ == rhs.table_);
     92       return element_ == rhs.element_;
     93     }
     94     bool operator!=(const DexToPcIterator& rhs) const {
     95       CHECK(table_ == rhs.table_);
     96       return element_ != rhs.element_;
     97     }
     98 
     99    private:
    100     const MappingTable* const table_;  // The original table.
    101     uint32_t element_;  // A value in the range 0 to end_.
    102     const uint32_t end_;  // Equal to table_->DexToPcSize().
    103     const uint8_t* encoded_table_ptr_;  // Either NULL or points to encoded data after this entry.
    104     uint32_t native_pc_offset_;  // The current value of native pc offset.
    105     uint32_t dex_pc_;  // The current value of dex pc.
    106   };
    107 
    108   DexToPcIterator DexToPcBegin() const {
    109     return DexToPcIterator(this, 0);
    110   }
    111 
    112   DexToPcIterator DexToPcEnd() const {
    113     uint32_t size = DexToPcSize();
    114     return DexToPcIterator(this, size);
    115   }
    116 
    117   uint32_t PcToDexSize() const PURE {
    118     const uint8_t* table = encoded_table_;
    119     if (table == NULL) {
    120       return 0;
    121     } else {
    122       DecodeUnsignedLeb128(&table);  // Total_size, unused.
    123       uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table);
    124       return pc_to_dex_size;
    125     }
    126   }
    127 
    128   const uint8_t* FirstPcToDexPtr() const {
    129     const uint8_t* table = encoded_table_;
    130     if (table != NULL) {
    131       DecodeUnsignedLeb128(&table);  // Total_size, unused.
    132       DecodeUnsignedLeb128(&table);  // PC to Dex size, unused.
    133     }
    134     return table;
    135   }
    136 
    137   class PcToDexIterator {
    138    public:
    139     PcToDexIterator(const MappingTable* table, uint32_t element) :
    140         table_(table), element_(element), end_(table_->PcToDexSize()), encoded_table_ptr_(NULL),
    141         native_pc_offset_(0), dex_pc_(0) {
    142       if (element == 0) {
    143         encoded_table_ptr_ = table_->FirstPcToDexPtr();
    144         native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
    145         dex_pc_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
    146       } else {
    147         DCHECK_EQ(table_->PcToDexSize(), element);
    148       }
    149     }
    150     uint32_t NativePcOffset() const {
    151       return native_pc_offset_;
    152     }
    153     uint32_t DexPc() const {
    154       return dex_pc_;
    155     }
    156     void operator++() {
    157       ++element_;
    158       if (element_ != end_) {  // Avoid reading beyond the end of the table.
    159         native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
    160         dex_pc_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
    161       }
    162     }
    163     bool operator==(const PcToDexIterator& rhs) const {
    164       CHECK(table_ == rhs.table_);
    165       return element_ == rhs.element_;
    166     }
    167     bool operator!=(const PcToDexIterator& rhs) const {
    168       CHECK(table_ == rhs.table_);
    169       return element_ != rhs.element_;
    170     }
    171 
    172    private:
    173     const MappingTable* const table_;  // The original table.
    174     uint32_t element_;  // A value in the range 0 to PcToDexSize.
    175     const uint32_t end_;  // Equal to table_->PcToDexSize().
    176     const uint8_t* encoded_table_ptr_;  // Either NULL or points to encoded data after this entry.
    177     uint32_t native_pc_offset_;  // The current value of native pc offset.
    178     uint32_t dex_pc_;  // The current value of dex pc.
    179   };
    180 
    181   PcToDexIterator PcToDexBegin() const {
    182     return PcToDexIterator(this, 0);
    183   }
    184 
    185   PcToDexIterator PcToDexEnd() const {
    186     uint32_t size = PcToDexSize();
    187     return PcToDexIterator(this, size);
    188   }
    189 
    190  private:
    191   const uint8_t* const encoded_table_;
    192 };
    193 
    194 }  // namespace art
    195 
    196 #endif  // ART_RUNTIME_MAPPING_TABLE_H_
    197