Commit 14083b7e authored by Jeremy Roman's avatar Jeremy Roman Committed by Commit Bot

Use std::atomic for the GCInfo table index.

Bug: 736037
Change-Id: I4c0bf2d3d374fbd659c7c70383e68c8102ef80f3
Reviewed-on: https://chromium-review.googlesource.com/c/1349494Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#610620}
parent f8d66686
...@@ -42,14 +42,16 @@ constexpr size_t MaxTableSize() { ...@@ -42,14 +42,16 @@ constexpr size_t MaxTableSize() {
} // namespace } // namespace
GCInfoTable* GCInfoTable::global_table_ = nullptr; GCInfoTable* GCInfoTable::global_table_ = nullptr;
constexpr uint32_t GCInfoTable::kMaxIndex;
void GCInfoTable::CreateGlobalTable() { void GCInfoTable::CreateGlobalTable() {
DEFINE_STATIC_LOCAL(GCInfoTable, table, ()); DEFINE_STATIC_LOCAL(GCInfoTable, table, ());
global_table_ = &table; global_table_ = &table;
} }
void GCInfoTable::EnsureGCInfoIndex(const GCInfo* gc_info, uint32_t GCInfoTable::EnsureGCInfoIndex(
uint32_t* gc_info_index_slot) { const GCInfo* gc_info,
std::atomic_uint32_t* gc_info_index_slot) {
DCHECK(gc_info); DCHECK(gc_info);
DCHECK(gc_info_index_slot); DCHECK(gc_info_index_slot);
...@@ -61,16 +63,18 @@ void GCInfoTable::EnsureGCInfoIndex(const GCInfo* gc_info, ...@@ -61,16 +63,18 @@ void GCInfoTable::EnsureGCInfoIndex(const GCInfo* gc_info,
// If more than one thread ends up allocating a slot for // If more than one thread ends up allocating a slot for
// the same GCInfo, have later threads reuse the slot // the same GCInfo, have later threads reuse the slot
// allocated by the first. // allocated by the first.
if (*gc_info_index_slot) uint32_t gc_info_index = gc_info_index_slot->load(std::memory_order_acquire);
return; if (gc_info_index)
return gc_info_index;
uint32_t gc_info_index = ++current_index_; gc_info_index = ++current_index_;
CHECK(gc_info_index < GCInfoTable::kMaxIndex); CHECK(gc_info_index < GCInfoTable::kMaxIndex);
if (current_index_ >= limit_) if (current_index_ >= limit_)
Resize(); Resize();
table_[gc_info_index] = gc_info; table_[gc_info_index] = gc_info;
ReleaseStore(gc_info_index_slot, gc_info_index); gc_info_index_slot->store(gc_info_index, std::memory_order_release);
return gc_info_index;
} }
void GCInfoTable::Resize() { void GCInfoTable::Resize() {
......
...@@ -5,13 +5,13 @@ ...@@ -5,13 +5,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_GC_INFO_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_GC_INFO_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_GC_INFO_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_GC_INFO_H_
#include <atomic>
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "third_party/blink/renderer/platform/heap/finalizer_traits.h" #include "third_party/blink/renderer/platform/heap/finalizer_traits.h"
#include "third_party/blink/renderer/platform/heap/name_traits.h" #include "third_party/blink/renderer/platform/heap/name_traits.h"
#include "third_party/blink/renderer/platform/heap/visitor.h" #include "third_party/blink/renderer/platform/heap/visitor.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h" #include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/atomics.h"
#include "third_party/blink/renderer/platform/wtf/deque.h" #include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/hash_counted_set.h" #include "third_party/blink/renderer/platform/wtf/hash_counted_set.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h"
...@@ -72,7 +72,7 @@ class PLATFORM_EXPORT GCInfoTable { ...@@ -72,7 +72,7 @@ class PLATFORM_EXPORT GCInfoTable {
return info; return info;
} }
void EnsureGCInfoIndex(const GCInfo*, uint32_t*); uint32_t EnsureGCInfoIndex(const GCInfo*, std::atomic_uint32_t*);
uint32_t GcInfoIndex() { return current_index_; } uint32_t GcInfoIndex() { return current_index_; }
...@@ -115,12 +115,15 @@ struct GCInfoAtBaseType { ...@@ -115,12 +115,15 @@ struct GCInfoAtBaseType {
NameTrait<T>::GetName, FinalizerTrait<T>::kNonTrivialFinalizer, NameTrait<T>::GetName, FinalizerTrait<T>::kNonTrivialFinalizer,
std::is_polymorphic<T>::value, std::is_polymorphic<T>::value,
}; };
static uint32_t gc_info_index = 0; // This is more complicated than using threadsafe initialization, but this
if (!AcquireLoad(&gc_info_index)) // is instantiated many times (once for every GC type).
GCInfoTable::Get().EnsureGCInfoIndex(&kGcInfo, &gc_info_index); static std::atomic_uint32_t gc_info_index{0};
DCHECK_GE(gc_info_index, 1u); uint32_t index = gc_info_index.load(std::memory_order_acquire);
DCHECK(gc_info_index < GCInfoTable::kMaxIndex); if (!index)
return gc_info_index; index = GCInfoTable::Get().EnsureGCInfoIndex(&kGcInfo, &gc_info_index);
DCHECK_GE(index, 1u);
DCHECK_LT(index, GCInfoTable::kMaxIndex);
return index;
} }
}; };
......
...@@ -16,10 +16,11 @@ TEST(GCInfoTest, InitialEmpty) { ...@@ -16,10 +16,11 @@ TEST(GCInfoTest, InitialEmpty) {
TEST(GCInfoTest, ResizeToMaxIndex) { TEST(GCInfoTest, ResizeToMaxIndex) {
GCInfoTable table; GCInfoTable table;
GCInfo info = {nullptr, nullptr, nullptr, false, false}; GCInfo info = {nullptr, nullptr, nullptr, false, false};
uint32_t slot = 0; std::atomic_uint32_t slot{0};
for (uint32_t i = 0; i < (GCInfoTable::kMaxIndex - 1); i++) { for (uint32_t i = 0; i < (GCInfoTable::kMaxIndex - 1); i++) {
slot = 0; slot = 0;
table.EnsureGCInfoIndex(&info, &slot); uint32_t index = table.EnsureGCInfoIndex(&info, &slot);
EXPECT_EQ(index, slot);
EXPECT_LT(0u, slot); EXPECT_LT(0u, slot);
EXPECT_EQ(&info, table.GCInfoFromIndex(slot)); EXPECT_EQ(&info, table.GCInfoFromIndex(slot));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment