Bug 1799446 - Don't use atomic update operations when updating the mark bitmap r=jandem

The Atomic class supports operations such as |&=| that perform atomic updates
on shared memory that are correct when performed concurrently with other such
updates. This is unnecessary for the mark bitmap and results in sub-optimal
code generation.

Instead, updates can be done with separate read and write operations.

Differential Revision: https://phabricator.services.mozilla.com/D161473
This commit is contained in:
Jon Coppeard 2022-11-07 16:17:49 +00:00
Родитель d84a6fb3b9
Коммит f15a4185f4
1 изменённых файлов: 27 добавлений и 11 удалений

Просмотреть файл

@ -513,6 +513,16 @@ MOZ_ALWAYS_INLINE bool MarkBitmap::isMarkedGray(const TenuredCell* cell) {
markBit(cell, ColorBit::GrayOrBlackBit);
}
// The following methods that update the mark bits are not thread safe and must
// not be called in parallel with each other.
//
// They use separate read and write operations to avoid an unnecessarily strict
// atomic update on the marking bitmap.
//
// They may be called in parallel with read operations on the mark bitmap where
// there is no required ordering between the operations. This happens when gray
// unmarking occurs in parallel with background sweeping.
// The return value indicates if the cell went from unmarked to marked.
MOZ_ALWAYS_INLINE bool MarkBitmap::markIfUnmarked(const TenuredCell* cell,
MarkColor color) {
@ -523,17 +533,17 @@ MOZ_ALWAYS_INLINE bool MarkBitmap::markIfUnmarked(const TenuredCell* cell,
return false;
}
if (color == MarkColor::Black) {
*word |= mask;
uintptr_t bits = *word;
*word = bits | mask;
} else {
/*
* We use getMarkWordAndMask to recalculate both mask and word as
* doing just mask << color may overflow the mask.
*/
// We use getMarkWordAndMask to recalculate both mask and word as doing just
// mask << color may overflow the mask.
getMarkWordAndMask(cell, ColorBit::GrayOrBlackBit, &word, &mask);
if (*word & mask) {
return false;
}
*word |= mask;
uintptr_t bits = *word;
*word = bits | mask;
}
return true;
}
@ -542,7 +552,8 @@ MOZ_ALWAYS_INLINE void MarkBitmap::markBlack(const TenuredCell* cell) {
MarkBitmapWord* word;
uintptr_t mask;
getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask);
*word |= mask;
uintptr_t bits = *word;
*word = bits | mask;
}
MOZ_ALWAYS_INLINE void MarkBitmap::copyMarkBit(TenuredCell* dst,
@ -557,19 +568,24 @@ MOZ_ALWAYS_INLINE void MarkBitmap::copyMarkBit(TenuredCell* dst,
uintptr_t dstMask;
getMarkWordAndMask(dst, colorBit, &dstWord, &dstMask);
*dstWord &= ~dstMask;
uintptr_t bits = *dstWord;
bits &= ~dstMask;
if (*srcWord & srcMask) {
*dstWord |= dstMask;
bits |= dstMask;
}
*dstWord = bits;
}
MOZ_ALWAYS_INLINE void MarkBitmap::unmark(const TenuredCell* cell) {
MarkBitmapWord* word;
uintptr_t mask;
uintptr_t bits;
getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask);
*word &= ~mask;
bits = *word;
*word = bits & ~mask;
getMarkWordAndMask(cell, ColorBit::GrayOrBlackBit, &word, &mask);
*word &= ~mask;
bits = *word;
*word = bits & ~mask;
}
inline MarkBitmapWord* MarkBitmap::arenaBits(Arena* arena) {