tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 6502ca57a26a7e0694f4b413453c595de54c03f5
parent 3f4b804de8bf477fafe37f115c041978dfa16f7b
Author: Jon Coppeard <jcoppeard@mozilla.com>
Date:   Sat,  1 Nov 2025 11:58:10 +0000

Bug 1994871 - Part 1: Simplify error handling for SparseBitmap by handling OOM in the caller r=sfink

This removes the infallible versions of SparseBitmap methods.

Differential Revision: https://phabricator.services.mozilla.com/D269954

Diffstat:
Mjs/src/ds/Bitmap.cpp | 20++++++++------------
Mjs/src/ds/Bitmap.h | 29++++-------------------------
Mjs/src/gc/AtomMarking-inl.h | 20+++++++++++++++-----
Mjs/src/jsapi-tests/testSparseBitmap.cpp | 14+++++++-------
4 files changed, 34 insertions(+), 49 deletions(-)

diff --git a/js/src/ds/Bitmap.cpp b/js/src/ds/Bitmap.cpp @@ -37,15 +37,6 @@ SparseBitmap::BitBlock* SparseBitmap::createBlock(Data::AddPtr p, return block.release(); } -SparseBitmap::BitBlock& SparseBitmap::createBlock( - Data::AddPtr p, size_t blockId, AutoEnterOOMUnsafeRegion& oomUnsafe) { - BitBlock* block = createBlock(p, blockId); - if (!block) { - oomUnsafe.crash("Bitmap OOM"); - } - return *block; -} - bool SparseBitmap::getBit(size_t bit) const { size_t word = bit / JS_BITS_PER_WORD; size_t blockWord = blockStartWord(word); @@ -85,14 +76,19 @@ void SparseBitmap::bitwiseAndWith(const DenseBitmap& other) { } } -void SparseBitmap::bitwiseOrWith(const SparseBitmap& other) { +bool SparseBitmap::bitwiseOrWith(const SparseBitmap& other) { for (Data::Range r(other.data.all()); !r.empty(); r.popFront()) { const BitBlock& otherBlock = *r.front().value(); - BitBlock& block = getOrCreateBlock(r.front().key()); + BitBlock* block = getOrCreateBlock(r.front().key()); + if (!block) { + return false; + } for (size_t i = 0; i < WordsInBlock; i++) { - block[i] |= otherBlock[i]; + (*block)[i] |= otherBlock[i]; } } + + return true; } void SparseBitmap::bitwiseOrInto(DenseBitmap& other) const { diff --git a/js/src/ds/Bitmap.h b/js/src/ds/Bitmap.h @@ -110,9 +110,6 @@ class SparseBitmap { return static_cast<size_t>(std::clamp(count, 0l, (long)WordsInBlock)); } - BitBlock& createBlock(Data::AddPtr p, size_t blockId, - AutoEnterOOMUnsafeRegion& oomUnsafe); - BitBlock* createBlock(Data::AddPtr p, size_t blockId); MOZ_ALWAYS_INLINE BitBlock* getBlock(size_t blockId) const { @@ -126,18 +123,7 @@ class SparseBitmap { return p ? p->value() : nullptr; } - MOZ_ALWAYS_INLINE BitBlock& getOrCreateBlock(size_t blockId) { - // The lookupForAdd() needs protection against injected OOMs, as does - // the add() within createBlock(). - AutoEnterOOMUnsafeRegion oomUnsafe; - Data::AddPtr p = data.lookupForAdd(blockId); - if (p) { - return *p->value(); - } - return createBlock(p, blockId, oomUnsafe); - } - - MOZ_ALWAYS_INLINE BitBlock* getOrCreateBlockFallible(size_t blockId) { + MOZ_ALWAYS_INLINE BitBlock* getOrCreateBlock(size_t blockId) { Data::AddPtr p = data.lookupForAdd(blockId); if (p) { return p->value(); @@ -150,17 +136,10 @@ class SparseBitmap { size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf); - MOZ_ALWAYS_INLINE void setBit(size_t bit) { - size_t word = bit / JS_BITS_PER_WORD; - size_t blockWord = blockStartWord(word); - BitBlock& block = getOrCreateBlock(blockWord / WordsInBlock); - block[word - blockWord] |= bitMask(bit); - } - - MOZ_ALWAYS_INLINE bool setBitFallible(size_t bit) { + [[nodiscard]] MOZ_ALWAYS_INLINE bool setBit(size_t bit) { size_t word = bit / JS_BITS_PER_WORD; size_t blockWord = blockStartWord(word); - BitBlock* block = getOrCreateBlockFallible(blockWord / WordsInBlock); + BitBlock* block = getOrCreateBlock(blockWord / WordsInBlock); if (!block) { return false; } @@ -172,7 +151,7 @@ class SparseBitmap { bool readonlyThreadsafeGetBit(size_t bit) const; void bitwiseAndWith(const DenseBitmap& other); - void bitwiseOrWith(const SparseBitmap& other); + [[nodiscard]] bool bitwiseOrWith(const SparseBitmap& other); void bitwiseOrInto(DenseBitmap& other) const; // Currently, the following APIs only supports a range of words that is in a diff --git a/js/src/gc/AtomMarking-inl.h b/js/src/gc/AtomMarking-inl.h @@ -10,6 +10,7 @@ #include "gc/AtomMarking.h" #include "mozilla/Assertions.h" +#include "mozilla/Maybe.h" #include <type_traits> @@ -56,12 +57,21 @@ MOZ_ALWAYS_INLINE bool AtomMarkingRuntime::inlinedMarkAtomInternal( size_t bit = GetAtomBit(cell); MOZ_ASSERT(bit / JS_BITS_PER_WORD < allocatedWords); - if (Fallible) { - if (!cx->zone()->markedAtoms().setBitFallible(bit)) { - return false; + { + mozilla::Maybe<AutoEnterOOMUnsafeRegion> oomUnsafe; + if constexpr (!Fallible) { + oomUnsafe.emplace(); + } + + bool ok = cx->zone()->markedAtoms().setBit(bit); + + if (!ok) { + if constexpr (!Fallible) { + oomUnsafe->crash("AtomMarkingRuntime::inlinedMarkAtomInternal"); + } else { + return false; + } } - } else { - cx->zone()->markedAtoms().setBit(bit); } // Trigger a read barrier on the atom, in case there is an incremental diff --git a/js/src/jsapi-tests/testSparseBitmap.cpp b/js/src/jsapi-tests/testSparseBitmap.cpp @@ -28,7 +28,7 @@ BEGIN_TEST(testSparseBitmapBasics) { // Set some bits in the first block and check they are set. for (size_t i = 0; i < 100; i += 2) { - bitmap.setBit(i); + CHECK(bitmap.setBit(i)); } for (size_t i = 0; i < 100; i++) { CHECK(bitmap.getBit(i) == ((i % 2) == 0)); @@ -36,7 +36,7 @@ BEGIN_TEST(testSparseBitmapBasics) { // Set some bits in different blocks and check they are set. for (size_t i = 0; i < 100; i += 2) { - bitmap.setBit(i * 1000); + CHECK(bitmap.setBit(i * 1000)); } for (size_t i = 0; i < 100; i++) { CHECK(bitmap.getBit(i * 1000) == ((i % 2) == 0)); @@ -45,14 +45,14 @@ BEGIN_TEST(testSparseBitmapBasics) { // Create another bitmap with different bits set. SparseBitmap other; for (size_t i = 1; i < 100; i += 2) { - other.setBit(i * 1000); + CHECK(other.setBit(i * 1000)); } for (size_t i = 0; i < 100; i++) { CHECK(other.getBit(i * 1000) == ((i % 2) != 0)); } // OR some bits into this bitmap and check the result. - bitmap.bitwiseOrWith(other); + CHECK(bitmap.bitwiseOrWith(other)); for (size_t i = 0; i < 100; i++) { CHECK(bitmap.getBit(i * 1000)); } @@ -79,7 +79,7 @@ BEGIN_TEST(testSparseBitmapExternalOR) { // Create a bitmap with one bit set per word so we can tell them apart. SparseBitmap bitmap; for (size_t i = 0; i < wordCount; i++) { - bitmap.setBit(i * JS_BITS_PER_WORD + i); + CHECK(bitmap.setBit(i * JS_BITS_PER_WORD + i)); } // Copy a single word. @@ -121,8 +121,8 @@ BEGIN_TEST(testSparseBitmapExternalAND) { // Create a bitmap with two bits set per word based on the word index. SparseBitmap bitmap; for (size_t i = 0; i < wordCount; i++) { - bitmap.setBit(i * JS_BITS_PER_WORD + i); - bitmap.setBit(i * JS_BITS_PER_WORD + i + 1); + CHECK(bitmap.setBit(i * JS_BITS_PER_WORD + i)); + CHECK(bitmap.setBit(i * JS_BITS_PER_WORD + i + 1)); } // Update a single word, clearing one of the bits.