196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers/*
296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers * Copyright (C) 2013 The Android Open Source Project
396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers *
496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers * Licensed under the Apache License, Version 2.0 (the "License");
596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers * you may not use this file except in compliance with the License.
696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers * You may obtain a copy of the License at
796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers *
896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers *      http://www.apache.org/licenses/LICENSE-2.0
996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers *
1096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers * Unless required by applicable law or agreed to in writing, software
1196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers * distributed under the License is distributed on an "AS IS" BASIS,
1296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers * See the License for the specific language governing permissions and
1496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers * limitations under the License.
1596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers */
1696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
1796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers#ifndef ART_RUNTIME_MAPPING_TABLE_H_
1896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers#define ART_RUNTIME_MAPPING_TABLE_H_
1996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
2096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers#include "base/logging.h"
2196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers#include "leb128.h"
2296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
2396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogersnamespace art {
2496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
2596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers// A utility for processing the raw uleb128 encoded mapping table created by the quick compiler.
2696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogersclass MappingTable {
2796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers public:
2896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  explicit MappingTable(const uint8_t* encoded_map) : encoded_table_(encoded_map) {
2996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  }
3096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
3196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  uint32_t TotalSize() const PURE {
3296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    const uint8_t* table = encoded_table_;
33159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers    if (table == nullptr) {
3496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return 0;
3596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    } else {
3696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return DecodeUnsignedLeb128(&table);
3796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
3896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  }
3996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
4096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  uint32_t DexToPcSize() const PURE {
4196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    const uint8_t* table = encoded_table_;
42159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers    if (table == nullptr) {
4396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return 0;
4496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    } else {
4596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      uint32_t total_size = DecodeUnsignedLeb128(&table);
4696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table);
4796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return total_size - pc_to_dex_size;
4896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
4996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  }
5096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
5196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  const uint8_t* FirstDexToPcPtr() const {
5296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    const uint8_t* table = encoded_table_;
53159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers    if (table != nullptr) {
54159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers      uint32_t total_size = DecodeUnsignedLeb128(&table);
5596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table);
56159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers      // We must have dex to pc entries or else the loop will go beyond the end of the table.
57159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers      DCHECK_GT(total_size, pc_to_dex_size);
5896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      for (uint32_t i = 0; i < pc_to_dex_size; ++i) {
5912d16ad924836cad46419a0f7eb57e13363139efVladimir Marko        DecodeUnsignedLeb128(&table);  // Move ptr past native PC delta.
6012d16ad924836cad46419a0f7eb57e13363139efVladimir Marko        DecodeSignedLeb128(&table);  // Move ptr past dex PC delta.
6196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      }
6296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
6396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    return table;
6496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  }
6596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
6696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  class DexToPcIterator {
6796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers   public:
6896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    DexToPcIterator(const MappingTable* table, uint32_t element) :
69159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers        table_(table), element_(element), end_(table_->DexToPcSize()), encoded_table_ptr_(nullptr),
7096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers        native_pc_offset_(0), dex_pc_(0) {
71159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers      if (element == 0) {  // An iterator wanted from the start.
7220ab6c861d248ae2822b5f38d5c09dff7506fc3aIan Rogers        if (end_ > 0) {
73159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers          encoded_table_ptr_ = table_->FirstDexToPcPtr();
7420ab6c861d248ae2822b5f38d5c09dff7506fc3aIan Rogers          native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
751e6cb63d77090ddc6aa19c755d7066f66e9ff87eVladimir Marko          // First delta is always positive.
761e6cb63d77090ddc6aa19c755d7066f66e9ff87eVladimir Marko          dex_pc_ = static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_));
7720ab6c861d248ae2822b5f38d5c09dff7506fc3aIan Rogers        }
78159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers      } else {  // An iterator wanted from the end.
7996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers        DCHECK_EQ(table_->DexToPcSize(), element);
8096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      }
8196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
8296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    uint32_t NativePcOffset() const {
8396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return native_pc_offset_;
8496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
8596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    uint32_t DexPc() const {
8696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return dex_pc_;
8796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
8896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    void operator++() {
8996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      ++element_;
9096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      if (element_ != end_) {  // Avoid reading beyond the end of the table.
911e6cb63d77090ddc6aa19c755d7066f66e9ff87eVladimir Marko        native_pc_offset_ += DecodeUnsignedLeb128(&encoded_table_ptr_);
921e6cb63d77090ddc6aa19c755d7066f66e9ff87eVladimir Marko        // For negative delta, unsigned overflow after static_cast does exactly what we need.
931e6cb63d77090ddc6aa19c755d7066f66e9ff87eVladimir Marko        dex_pc_ += static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_));
9496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      }
9596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
9696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    bool operator==(const DexToPcIterator& rhs) const {
9796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      CHECK(table_ == rhs.table_);
9896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return element_ == rhs.element_;
9996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
10096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    bool operator!=(const DexToPcIterator& rhs) const {
10196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      CHECK(table_ == rhs.table_);
10296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return element_ != rhs.element_;
10396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
10496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
10596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers   private:
10696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    const MappingTable* const table_;  // The original table.
10796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    uint32_t element_;  // A value in the range 0 to end_.
10896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    const uint32_t end_;  // Equal to table_->DexToPcSize().
1092cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    const uint8_t* encoded_table_ptr_;  // Either null or points to encoded data after this entry.
11096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    uint32_t native_pc_offset_;  // The current value of native pc offset.
11196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    uint32_t dex_pc_;  // The current value of dex pc.
11296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  };
11396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
11496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  DexToPcIterator DexToPcBegin() const {
11596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    return DexToPcIterator(this, 0);
11696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  }
11796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
11896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  DexToPcIterator DexToPcEnd() const {
11996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    uint32_t size = DexToPcSize();
12096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    return DexToPcIterator(this, size);
12196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  }
12296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
12396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  uint32_t PcToDexSize() const PURE {
12496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    const uint8_t* table = encoded_table_;
125159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers    if (table == nullptr) {
12696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return 0;
12796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    } else {
12896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      DecodeUnsignedLeb128(&table);  // Total_size, unused.
12996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      uint32_t pc_to_dex_size = DecodeUnsignedLeb128(&table);
13096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return pc_to_dex_size;
13196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
13296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  }
13396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
13496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  const uint8_t* FirstPcToDexPtr() const {
13596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    const uint8_t* table = encoded_table_;
136159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers    if (table != nullptr) {
13796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      DecodeUnsignedLeb128(&table);  // Total_size, unused.
13896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      DecodeUnsignedLeb128(&table);  // PC to Dex size, unused.
13996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
14096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    return table;
14196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  }
14296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
14396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  class PcToDexIterator {
14496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers   public:
14596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    PcToDexIterator(const MappingTable* table, uint32_t element) :
146159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers        table_(table), element_(element), end_(table_->PcToDexSize()), encoded_table_ptr_(nullptr),
14796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers        native_pc_offset_(0), dex_pc_(0) {
148159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers      if (element == 0) {  // An iterator wanted from the start.
14920ab6c861d248ae2822b5f38d5c09dff7506fc3aIan Rogers        if (end_ > 0) {
150159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers          encoded_table_ptr_ = table_->FirstPcToDexPtr();
15120ab6c861d248ae2822b5f38d5c09dff7506fc3aIan Rogers          native_pc_offset_ = DecodeUnsignedLeb128(&encoded_table_ptr_);
1521e6cb63d77090ddc6aa19c755d7066f66e9ff87eVladimir Marko          // First delta is always positive.
1531e6cb63d77090ddc6aa19c755d7066f66e9ff87eVladimir Marko          dex_pc_ = static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_));
15420ab6c861d248ae2822b5f38d5c09dff7506fc3aIan Rogers        }
155159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers      } else {  // An iterator wanted from the end.
15696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers        DCHECK_EQ(table_->PcToDexSize(), element);
15796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      }
15896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
15996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    uint32_t NativePcOffset() const {
16096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return native_pc_offset_;
16196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
16296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    uint32_t DexPc() const {
16396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return dex_pc_;
16496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
16596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    void operator++() {
16696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      ++element_;
16796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      if (element_ != end_) {  // Avoid reading beyond the end of the table.
1681e6cb63d77090ddc6aa19c755d7066f66e9ff87eVladimir Marko        native_pc_offset_ += DecodeUnsignedLeb128(&encoded_table_ptr_);
1691e6cb63d77090ddc6aa19c755d7066f66e9ff87eVladimir Marko        // For negative delta, unsigned overflow after static_cast does exactly what we need.
1701e6cb63d77090ddc6aa19c755d7066f66e9ff87eVladimir Marko        dex_pc_ += static_cast<uint32_t>(DecodeSignedLeb128(&encoded_table_ptr_));
17196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      }
17296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
17396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    bool operator==(const PcToDexIterator& rhs) const {
17496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      CHECK(table_ == rhs.table_);
17596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return element_ == rhs.element_;
17696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
17796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    bool operator!=(const PcToDexIterator& rhs) const {
17896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      CHECK(table_ == rhs.table_);
17996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers      return element_ != rhs.element_;
18096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    }
18196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
18296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers   private:
18396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    const MappingTable* const table_;  // The original table.
18496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    uint32_t element_;  // A value in the range 0 to PcToDexSize.
18596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    const uint32_t end_;  // Equal to table_->PcToDexSize().
186159aa95e1e23cd585ac305b44b4cd65ae72048a4Ian Rogers    const uint8_t* encoded_table_ptr_;  // Either null or points to encoded data after this entry.
18796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    uint32_t native_pc_offset_;  // The current value of native pc offset.
18896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    uint32_t dex_pc_;  // The current value of dex pc.
18996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  };
19096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
19196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  PcToDexIterator PcToDexBegin() const {
19296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    return PcToDexIterator(this, 0);
19396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  }
19496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
19596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  PcToDexIterator PcToDexEnd() const {
19696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    uint32_t size = PcToDexSize();
19796faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers    return PcToDexIterator(this, size);
19896faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  }
19996faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
20096faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers private:
20196faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers  const uint8_t* const encoded_table_;
20296faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers};
20396faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
20496faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers}  // namespace art
20596faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers
20696faf5b363d922ae91cf25404dee0e87c740c7c5Ian Rogers#endif  // ART_RUNTIME_MAPPING_TABLE_H_
207