summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2023-01-23 17:54:23 +0000
committerHenning Baldersheim <balder@yahoo-inc.com>2023-01-23 17:54:23 +0000
commit78e994df4130ab8a3eb07135f17e306695947207 (patch)
tree258159c756b5a32e6b295703964bb7a8090a147a
parent6d55ba7e9bdfd6248d5a83786c9dd1e5ee63e9b9 (diff)
Add rangecheck to BitVector::store(Word & word).
Handle nonoverlapping vectors in orWith, andWith and andNotWith.
-rw-r--r--searchlib/src/vespa/searchlib/common/bitvector.cpp15
-rw-r--r--searchlib/src/vespa/searchlib/common/bitvector.h27
2 files changed, 25 insertions, 17 deletions
diff --git a/searchlib/src/vespa/searchlib/common/bitvector.cpp b/searchlib/src/vespa/searchlib/common/bitvector.cpp
index 47ca590c9bc..1e403702fad 100644
--- a/searchlib/src/vespa/searchlib/common/bitvector.cpp
+++ b/searchlib/src/vespa/searchlib/common/bitvector.cpp
@@ -90,11 +90,16 @@ void
BitVector::clearInterval(Index start, Index end)
{
clearIntervalNoInvalidation(Range(start, end));
-
invalidateCachedCount();
}
void
+BitVector::store(Word &word, Word value) {
+ assert(!_enable_range_check && (&word >= getActiveStart()));
+ return store_unchecked(word, value);
+}
+
+void
BitVector::clearIntervalNoInvalidation(Range range_in)
{
Range range = sanitize(range_in);
@@ -107,7 +112,7 @@ BitVector::clearIntervalNoInvalidation(Range range_in)
if (endw > startw) {
store(_words[startw], _words[startw] & startBits(range.start()));
for (Index i = startw + 1; i < endw; ++i) {
- store(_words[i], 0);
+ store_unchecked(_words[i], 0);
}
store(_words[endw], _words[endw] & endBits(last));
} else {
@@ -128,7 +133,7 @@ BitVector::setInterval(Index start_in, Index end_in)
if (endw > startw) {
store(_words[startw], _words[startw] | checkTab(range.start()));
for (Index i = startw + 1; i < endw; ++i) {
- store(_words[i], allBits());
+ store_unchecked(_words[i], allBits());
}
store(_words[endw], _words[endw] | ~endBits(last));
} else {
@@ -190,7 +195,7 @@ BitVector::orWith(const BitVector & right)
verifyInclusiveStart(*this, right);
if (right.size() < size()) {
- if (right.size() > 0) {
+ if (right.size() > getStartIndex()) {
ssize_t commonBytes = numActiveBytes(getStartIndex(), right.size()) - sizeof(Word);
if (commonBytes > 0) {
IAccelrated::getAccelerator().orBit(getActiveStart(), right.getWordIndex(getStartIndex()), commonBytes);
@@ -240,7 +245,7 @@ BitVector::andNotWith(const BitVector& right)
verifyInclusiveStart(*this, right);
if (right.size() < size()) {
- if (right.size() > 0) {
+ if (right.size() > getStartIndex()) {
ssize_t commonBytes = numActiveBytes(getStartIndex(), right.size()) - sizeof(Word);
if (commonBytes > 0) {
IAccelrated::getAccelerator().andNotBit(getActiveStart(), right.getWordIndex(getStartIndex()), commonBytes);
diff --git a/searchlib/src/vespa/searchlib/common/bitvector.h b/searchlib/src/vespa/searchlib/common/bitvector.h
index 1d289435f6d..973d1a8704b 100644
--- a/searchlib/src/vespa/searchlib/common/bitvector.h
+++ b/searchlib/src/vespa/searchlib/common/bitvector.h
@@ -28,10 +28,10 @@ public:
using UP = std::unique_ptr<BitVector>;
class Range {
public:
- Range(Index start_in, Index end_in) : _start(start_in), _end(end_in) {}
- Index start() const { return _start; }
- Index end() const { return _end; }
- bool validNonZero() const { return _end > _start; }
+ Range(Index start_in, Index end_in) noexcept : _start(start_in), _end(end_in) {}
+ [[nodiscard]] Index start() const noexcept { return _start; }
+ [[nodiscard]] Index end() const noexcept { return _end; }
+ [[nodiscard]] bool validNonZero() const noexcept { return _end > _start; }
private:
Index _start;
Index _end;
@@ -144,15 +144,15 @@ public:
vespalib::atomic::store_ref_release(_sz, sz);
}
void set_bit_no_range_check(Index idx) {
- store(_words[wordNum(idx)], _words[wordNum(idx)] | mask(idx));
+ store_unchecked(_words[wordNum(idx)], _words[wordNum(idx)] | mask(idx));
}
void clear_bit_no_range_check(Index idx) {
- store(_words[wordNum(idx)], _words[wordNum(idx)] & ~ mask(idx));
+ store_unchecked(_words[wordNum(idx)], _words[wordNum(idx)] & ~ mask(idx));
}
void flip_bit_no_range_check(Index idx) {
- store(_words[wordNum(idx)], _words[wordNum(idx)] ^ mask(idx));
+ store_unchecked(_words[wordNum(idx)], _words[wordNum(idx)] ^ mask(idx));
}
- void range_check(Index idx) {
+ void range_check(Index idx) const {
assert(!_enable_range_check || (idx >= _startOffset && idx < _sz));
}
void setBit(Index idx) {
@@ -301,8 +301,11 @@ protected:
static Alloc allocatePaddedAndAligned(Index start, Index end, Index capacity, const Alloc* init_alloc = nullptr);
private:
- Word load(const Word &word) const { return vespalib::atomic::load_ref_relaxed(word); }
- void store(Word &word, Word value) { return vespalib::atomic::store_ref_relaxed(word, value); }
+ static Word load(const Word &word) { return vespalib::atomic::load_ref_relaxed(word); }
+ VESPA_DLL_LOCAL void store(Word &word, Word value);
+ static void store_unchecked(Word &word, Word value) {
+ return vespalib::atomic::store_ref_relaxed(word, value);
+ }
friend PartialBitVector;
const Word * getWordIndex(Index index) const { return static_cast<const Word *>(getStart()) + wordNum(index); }
Word * getWordIndex(Index index) { return static_cast<Word *>(getStart()) + wordNum(index); }
@@ -330,8 +333,8 @@ private:
}
VESPA_DLL_LOCAL void repairEnds();
Range sanitize(Range range) const {
- return Range(std::max(range.start(), getStartIndex()),
- std::min(range.end(), size()));
+ return {std::max(range.start(), getStartIndex()),
+ std::min(range.end(), size())};
}
Index count() const;
bool hasTrueBitsInternal() const;