OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2012 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can |
| 4 * be found in the LICENSE file. |
| 5 * Copyright 2012, Google Inc. |
| 6 */ |
| 7 |
| 8 #include "native_client/src/trusted/validator_mips/address_set.h" |
| 9 #include <assert.h> |
| 10 #include <stdio.h> |
| 11 #include <string.h> |
| 12 |
| 13 namespace nacl_mips_val { |
| 14 |
| 15 static const int kInstrAlignment = 4; |
| 16 static const int kInstrSize = 4; |
| 17 static const int kWordSize = 32; |
| 18 static const int kInstrPerWord = 4 * kWordSize; |
| 19 |
| 20 #define UP_ALLIGN(x) (kInstrSize * ((x + kInstrSize - 1) / kInstrSize)) |
| 21 |
| 22 AddressSet::AddressSet(uint32_t base, uint32_t size) |
| 23 : base_(base), size_(size), end_(base + UP_ALLIGN(size) - kInstrSize), |
| 24 bits_(new uint32_t[(end_ - base_) / kInstrPerWord + 1]) { |
| 25 assert(((base % kInstrAlignment) == 0) && (size > 0)); |
| 26 memset(bits_, 0, sizeof(uint32_t) * ((end_ - base_) / kInstrPerWord + 1)); |
| 27 } |
| 28 |
| 29 AddressSet::~AddressSet() { |
| 30 delete[] bits_; |
| 31 } |
| 32 |
| 33 void AddressSet::Add(uint32_t address) { |
| 34 if ((address - base_) < size_) { |
| 35 uint32_t word_address = (address - base_) / sizeof(uint32_t); |
| 36 bits_[word_address / kWordSize] |= 1 << (word_address % kWordSize); |
| 37 } |
| 38 } |
| 39 |
| 40 bool AddressSet::Contains(uint32_t address) const { |
| 41 if ((address - base_) < size_) { |
| 42 uint32_t word_address = (address - base_) / sizeof(uint32_t); |
| 43 |
| 44 return bits_[word_address / kWordSize] & (1 << (word_address % kWordSize)); |
| 45 } else { |
| 46 return false; |
| 47 } |
| 48 } |
| 49 |
| 50 AddressSet::Iterator AddressSet::Begin() const { |
| 51 return Iterator(*this, 0, 0); |
| 52 } |
| 53 |
| 54 AddressSet::Iterator AddressSet::End() const { |
| 55 uint32_t end_index = (end_ - base_) / kInstrPerWord; |
| 56 uint32_t end_shift = ((end_ - base_) / kInstrSize) % kWordSize; |
| 57 return Iterator(*this, end_index, end_shift); |
| 58 } |
| 59 |
| 60 AddressSet::Iterator::Iterator(const AddressSet &parent, |
| 61 uint32_t index, |
| 62 uint32_t shift) |
| 63 : parent_(parent), index_(index), shift_(shift) { |
| 64 Advance(); |
| 65 } |
| 66 |
| 67 AddressSet::Iterator &AddressSet::Iterator::Next() { |
| 68 shift_++; // Skip the current bit, if any, and |
| 69 Advance(); // seek to the next 1 bit. |
| 70 return *this; |
| 71 } |
| 72 |
| 73 bool AddressSet::Iterator::Equals(const AddressSet::Iterator &other) const { |
| 74 return index_ == other.index_ && shift_ == other.shift_; |
| 75 } |
| 76 |
| 77 uint32_t AddressSet::Iterator::GetAddress() const { |
| 78 return parent_.base_ + kInstrSize * ((index_ * kWordSize) + shift_); |
| 79 } |
| 80 |
| 81 void AddressSet::Iterator::Advance() { |
| 82 uint32_t max_index = (parent_.size_ / kInstrPerWord) + 1; |
| 83 |
| 84 for (; index_ < max_index; index_++) { |
| 85 uint32_t word = (shift_ > 31) ? 0 : parent_.bits_[index_] >> shift_; |
| 86 while (word) { |
| 87 if (word & 1) return; |
| 88 |
| 89 // A meager optimization for sparse words. Check if the first 16 slots are |
| 90 // empty, and if they are, skip them. Repeat the same check for 8 slots. |
| 91 // Otherwise, we will check bit by bit, to reach the next valid one. |
| 92 if (!(word & 0xFFFF)) { |
| 93 word >>= 16; |
| 94 shift_ += 16; |
| 95 } else if (!(word & 0xFF)) { |
| 96 word >>= 8; |
| 97 shift_ += 8; |
| 98 } else { |
| 99 word >>= 1; |
| 100 shift_++; |
| 101 } |
| 102 } |
| 103 shift_ = 0; |
| 104 } |
| 105 |
| 106 // If we have moved too far, we should limit the address to |
| 107 // the last valid address. |
| 108 if (index_ == max_index) { |
| 109 index_ = (parent_.end_ - parent_.base_) / kInstrPerWord; |
| 110 shift_ = ((parent_.end_ - parent_.base_) / kInstrSize) % kWordSize; |
| 111 } |
| 112 } |
| 113 |
| 114 } // namespace |
OLD | NEW |