[vm] Establish ordering between publish a new field table background store and concurrently accessing it.

TSAN doesn't understand std::atomic_thread_fence.

TEST=iso-stress, tsan
Change-Id: Icb873af1f58f111c4e69666f33a27f5a6cdf724c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/233445
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2022-02-17 18:10:31 +00:00 committed by Commit Bot
parent 7386ea6326
commit 4577d4e013
2 changed files with 5 additions and 5 deletions

View file

@ -117,8 +117,7 @@ void FieldTable::Grow(intptr_t new_capacity) {
old_tables_->Add(old_table);
// Ensure that new_table_ is populated before it is published
// via store to table_.
std::atomic_thread_fence(std::memory_order_release);
table_ = new_table;
reinterpret_cast<AcqRelAtomic<ObjectPtr*>*>(&table_)->store(new_table);
if (isolate_ != nullptr) {
isolate_->mutator_thread()->field_table_values_ = table_;
}

View file

@ -60,14 +60,15 @@ class FieldTable {
ObjectPtr At(intptr_t index, bool concurrent_use = false) const {
ASSERT(IsValidIndex(index));
ObjectPtr* slot = &table_[index];
if (concurrent_use) {
return reinterpret_cast<AcqRelAtomic<ObjectPtr>*>(slot)->load();
ObjectPtr* table =
reinterpret_cast<const AcqRelAtomic<ObjectPtr*>*>(&table_)->load();
return reinterpret_cast<AcqRelAtomic<ObjectPtr>*>(&table[index])->load();
} else {
// There is no concurrent access expected for this field, so we avoid
// using atomics. This will allow us to detect via TSAN if there are
// racy uses.
return *slot;
return table_[index];
}
}