summaryrefslogtreecommitdiffstats
path: root/js/src/ds
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
commitd8bbc7858622b6d9c278469aab701ca0b609cddf (patch)
treeeff41dc61d9f714852212739e6b3738b82a2af87 /js/src/ds
parentReleasing progress-linux version 125.0.3-1~progress7.99u1. (diff)
downloadfirefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz
firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/ds')
-rw-r--r--js/src/ds/BitArray.h6
-rw-r--r--js/src/ds/Bitmap.h22
-rw-r--r--js/src/ds/OrderedHashTable.h71
3 files changed, 80 insertions, 19 deletions
diff --git a/js/src/ds/BitArray.h b/js/src/ds/BitArray.h
index bdd78873fd..f8a6aad455 100644
--- a/js/src/ds/BitArray.h
+++ b/js/src/ds/BitArray.h
@@ -99,6 +99,12 @@ class BitArray {
return map[elementIndex];
}
+ // Update a word at a time.
+ void setWord(size_t elementIndex, WordT value) {
+ MOZ_ASSERT(elementIndex < nbits);
+ map[elementIndex] = value;
+ }
+
static void getIndexAndMask(size_t offset, size_t* indexp, WordT* maskp) {
MOZ_ASSERT(offset < nbits);
static_assert(bitsPerElement == 32, "unexpected bitsPerElement value");
diff --git a/js/src/ds/Bitmap.h b/js/src/ds/Bitmap.h
index 6770585a61..f564e2a328 100644
--- a/js/src/ds/Bitmap.h
+++ b/js/src/ds/Bitmap.h
@@ -162,8 +162,26 @@ class SparseBitmap {
void bitwiseOrWith(const SparseBitmap& other);
void bitwiseOrInto(DenseBitmap& other) const;
- // Currently, this API only supports a range of words that is in a single bit
- // block.
+ // Currently, the following APIs only supports a range of words that is in a
+ // single bit block.
+
+ template <typename T>
+ typename std::enable_if_t<std::is_convertible_v<T, uintptr_t>, void>
+ bitwiseAndRangeWith(size_t wordStart, size_t numWords, T* source) {
+ size_t blockWord = blockStartWord(wordStart);
+
+ // We only support using a single bit block in this API.
+ MOZ_ASSERT(numWords &&
+ (blockWord == blockStartWord(wordStart + numWords - 1)));
+
+ BitBlock* block = getBlock(blockWord / WordsInBlock);
+ if (block) {
+ for (size_t i = 0; i < numWords; i++) {
+ (*block)[wordStart - blockWord + i] &= source[i];
+ }
+ }
+ }
+
template <typename T>
typename std::enable_if_t<std::is_convertible_v<T, uintptr_t>, void>
bitwiseOrRangeInto(size_t wordStart, size_t numWords, T* target) const {
diff --git a/js/src/ds/OrderedHashTable.h b/js/src/ds/OrderedHashTable.h
index 3ef366abc3..75c22bd123 100644
--- a/js/src/ds/OrderedHashTable.h
+++ b/js/src/ds/OrderedHashTable.h
@@ -39,6 +39,7 @@
#include "mozilla/HashFunctions.h"
#include "mozilla/Likely.h"
+#include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/TemplateLib.h"
@@ -85,9 +86,16 @@ class OrderedHashTable {
uint32_t dataCapacity; // size of data, in elements
uint32_t liveCount; // dataLength less empty (removed) entries
uint32_t hashShift; // multiplicative hash shift
- Range* ranges; // list of all live Ranges on this table in malloc memory
- Range*
- nurseryRanges; // list of all live Ranges on this table in the GC nursery
+
+ // List of all live Ranges on this table in malloc memory. Populated when
+ // ranges are created.
+ Range* ranges;
+
+ // List of all live Ranges on this table in the GC nursery. Populated when
+ // ranges are created. This is cleared at the start of minor GC and rebuilt
+ // when ranges are moved.
+ Range* nurseryRanges;
+
AllocPolicy alloc;
mozilla::HashCodeScrambler hcs; // don't reveal pointer hash codes
@@ -382,22 +390,28 @@ class OrderedHashTable {
next->prevp = &next;
}
seek();
+ MOZ_ASSERT(valid());
}
public:
- Range(const Range& other)
+ Range(const Range& other, bool inNursery)
: ht(other.ht),
i(other.i),
count(other.count),
- prevp(&ht->ranges),
- next(ht->ranges) {
+ prevp(inNursery ? &ht->nurseryRanges : &ht->ranges),
+ next(*prevp) {
*prevp = this;
if (next) {
next->prevp = &next;
}
+ MOZ_ASSERT(valid());
}
~Range() {
+ if (!prevp) {
+ // Head of removed nursery ranges.
+ return;
+ }
*prevp = next;
if (next) {
next->prevp = prevp;
@@ -446,12 +460,15 @@ class OrderedHashTable {
i = count = 0;
}
- bool valid() const { return next != this; }
+#ifdef DEBUG
+ bool valid() const { return /* *prevp == this && */ next != this; }
+#endif
void onTableDestroyed() {
MOZ_ASSERT(valid());
prevp = &next;
next = this;
+ MOZ_ASSERT(!valid());
}
public:
@@ -559,9 +576,6 @@ class OrderedHashTable {
/*
* Allocate a new Range, possibly in nursery memory. The buffer must be
* large enough to hold a Range object.
- *
- * All nursery-allocated ranges can be freed in one go by calling
- * destroyNurseryRanges().
*/
Range* createRange(void* buffer, bool inNursery) const {
auto* self = const_cast<OrderedHashTable*>(this);
@@ -570,7 +584,16 @@ class OrderedHashTable {
return static_cast<Range*>(buffer);
}
- void destroyNurseryRanges() { nurseryRanges = nullptr; }
+ void destroyNurseryRanges() {
+ if (nurseryRanges) {
+ nurseryRanges->prevp = nullptr;
+ }
+ nurseryRanges = nullptr;
+ }
+
+#ifdef DEBUG
+ bool hasNurseryRanges() const { return nurseryRanges; }
+#endif
/*
* Change the value of the given key.
@@ -959,13 +982,17 @@ class OrderedHashMap {
HashNumber hash(const Lookup& key) const { return impl.prepareHash(key); }
template <typename GetNewKey>
- void rekeyOneEntry(const Lookup& current, const GetNewKey& getNewKey) {
+ mozilla::Maybe<Key> rekeyOneEntry(Lookup& current, GetNewKey&& getNewKey) {
+ // TODO: This is inefficient because we also look up the entry in
+ // impl.rekeyOneEntry below.
const Entry* e = get(current);
if (!e) {
- return;
+ return mozilla::Nothing();
}
+
Key newKey = getNewKey(current);
- return impl.rekeyOneEntry(current, newKey, Entry(newKey, e->value));
+ impl.rekeyOneEntry(current, newKey, Entry(newKey, e->value));
+ return mozilla::Some(newKey);
}
Range* createRange(void* buffer, bool inNursery) const {
@@ -973,6 +1000,9 @@ class OrderedHashMap {
}
void destroyNurseryRanges() { impl.destroyNurseryRanges(); }
+#ifdef DEBUG
+ bool hasNurseryRanges() const { return impl.hasNurseryRanges(); }
+#endif
void trace(JSTracer* trc) { impl.trace(trc); }
@@ -1048,12 +1078,16 @@ class OrderedHashSet {
HashNumber hash(const Lookup& value) const { return impl.prepareHash(value); }
template <typename GetNewKey>
- void rekeyOneEntry(const Lookup& current, const GetNewKey& getNewKey) {
+ mozilla::Maybe<T> rekeyOneEntry(Lookup& current, GetNewKey&& getNewKey) {
+ // TODO: This is inefficient because we also look up the entry in
+ // impl.rekeyOneEntry below.
if (!has(current)) {
- return;
+ return mozilla::Nothing();
}
+
T newKey = getNewKey(current);
- return impl.rekeyOneEntry(current, newKey, newKey);
+ impl.rekeyOneEntry(current, newKey, newKey);
+ return mozilla::Some(newKey);
}
Range* createRange(void* buffer, bool inNursery) const {
@@ -1061,6 +1095,9 @@ class OrderedHashSet {
}
void destroyNurseryRanges() { impl.destroyNurseryRanges(); }
+#ifdef DEBUG
+ bool hasNurseryRanges() const { return impl.hasNurseryRanges(); }
+#endif
void trace(JSTracer* trc) { impl.trace(trc); }