Bug 1665338 - Make GC cell header word atomic to avoid race in compacting GC r=sfink,decoder

Differential Revision: https://phabricator.services.mozilla.com/D90389
This commit is contained in:
Jon Coppeard 2020-09-22 12:49:40 +00:00
Родитель 8804eb9be3
Коммит 6bb01d4a27
5 изменённых файлов: 16 добавлений и 13 удалений

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

@ -7,6 +7,8 @@
#ifndef gc_Cell_h
#define gc_Cell_h
#include "mozilla/Atomics.h"
#include <type_traits>
#include "gc/GCEnum.h"
@ -115,7 +117,13 @@ class CellColor {
struct Cell {
protected:
// Cell header word. Stores GC flags and derived class data.
uintptr_t header_;
//
// This is atomic since it can be read from and written to by different
// threads during compacting GC, in a limited way. Specifically, writes that
// update the derived class data can race with reads that check the forwarded
// flag. The writes do not change the forwarded flag (which is always false in
// this situation).
mozilla::Atomic<uintptr_t, mozilla::MemoryOrdering::Relaxed> header_;
public:
static_assert(gc::CellFlagBitsReservedForGC >= 3,
@ -681,7 +689,7 @@ class alignas(gc::CellAlignBytes) TenuredCellWithNonGCPointer
// flags are also always clear). This means we don't need to use masking to
// get and set the pointer.
MOZ_ASSERT(flags() == 0);
return reinterpret_cast<PtrT*>(header_);
return reinterpret_cast<PtrT*>(uintptr_t(header_));
}
void setHeaderPtr(PtrT* newValue) {
@ -747,7 +755,7 @@ class alignas(gc::CellAlignBytes) CellWithTenuredGCPointer : public BaseCell {
// masking to get and set the pointer.
staticAsserts();
MOZ_ASSERT(this->flags() == 0);
return reinterpret_cast<PtrT*>(this->header_);
return reinterpret_cast<PtrT*>(uintptr_t(this->header_));
}
void unbarrieredSetHeaderPtr(PtrT* newValue) {

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

@ -8,13 +8,13 @@ import gdb
def get_header_ptr(value, ptr_t):
# Return the pointer stored in Cell::header_ for subclasses of
# TenuredCellWithNonGCPointer and CellWithTenuredGCPointer.
return value['header_'].cast(ptr_t)
return value['header_']['mValue'].cast(ptr_t)
def get_header_length_and_flags(value):
def get_header_length_and_flags(value, cache):
# Return the length and flags values for subclasses of
# CellWithLengthAndFlags.
flags = value['header_']
flags = value['header_']['mValue'].cast(cache.uintptr_t)
try:
length = value['length_']
except gdb.error:

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

@ -44,7 +44,7 @@ class JSStringPtr(Common):
def chars(self):
d = self.value['d']
length, flags = get_header_length_and_flags(self.value)
length, flags = get_header_length_and_flags(self.value, self.cache)
corrupt = {
0x2f2f2f2f: 'JS_FRESH_NURSERY_PATTERN',

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

@ -204,6 +204,7 @@ class TypeCache(object):
# enough.
self.void_t = gdb.lookup_type('void')
self.void_ptr_t = self.void_t.pointer()
self.uintptr_t = gdb.lookup_type('uintptr_t')
try:
self.JSString_ptr_t = gdb.lookup_type('JSString').pointer()
self.JSSymbol_ptr_t = gdb.lookup_type('JS::Symbol').pointer()

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

@ -126,12 +126,6 @@ extern "C" const char* __tsan_default_suppressions() {
// Bug 1600594
"race:nsThread::SizeOfEventQueues\n"
// Bug 1600895, bug 1647702
"race:UpdateArenaPointersTyped<js::ObjectGroup>\n"
"race:UpdateArenaPointersTyped<js::Shape>\n"
"race:UpdateArenaPointersTyped<JSObject>\n"
"race:JSObject::fixupAfterMovingGC\n"
// Bug 1601286
"race:setFlagBit\n"
"race:isFatInline\n"