blob: 10573e6dcde74fea002c553bbbbfff5de7fed44e [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/heap/gc_info.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
namespace blink {
// GCInfo indices start from 1 for heap objects, with 0 being treated
// specially as the index for freelist entries and large heap objects.
size_t GCInfoTable::gc_info_index_ = 0;
size_t GCInfoTable::gc_info_table_size_ = 0;
GCInfo const** g_gc_info_table = nullptr;
void GCInfoTable::EnsureGCInfoIndex(const GCInfo* gc_info,
size_t* gc_info_index_slot) {
DCHECK(gc_info);
DCHECK(gc_info_index_slot);
// Keep a global GCInfoTable lock while allocating a new slot.
DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, ());
MutexLocker locker(mutex);
// If more than one thread ends up allocating a slot for
// the same GCInfo, have later threads reuse the slot
// allocated by the first.
if (*gc_info_index_slot)
return;
int index = ++gc_info_index_;
size_t gc_info_index = static_cast<size_t>(index);
CHECK(gc_info_index < GCInfoTable::kMaxIndex);
if (gc_info_index >= gc_info_table_size_)
Resize();
g_gc_info_table[gc_info_index] = gc_info;
ReleaseStore(reinterpret_cast<int*>(gc_info_index_slot), index);
}
void GCInfoTable::Resize() {
static const int kGcInfoZapValue = 0x33;
// (Light) experimentation suggests that Blink doesn't need
// more than this while handling content on popular web properties.
const size_t kInitialSize = 512;
size_t new_size =
gc_info_table_size_ ? 2 * gc_info_table_size_ : kInitialSize;
DCHECK(new_size < GCInfoTable::kMaxIndex);
g_gc_info_table =
reinterpret_cast<GCInfo const**>(WTF::Partitions::FastRealloc(
g_gc_info_table, new_size * sizeof(GCInfo), "GCInfo"));
DCHECK(g_gc_info_table);
memset(reinterpret_cast<uint8_t*>(g_gc_info_table) +
gc_info_table_size_ * sizeof(GCInfo),
kGcInfoZapValue, (new_size - gc_info_table_size_) * sizeof(GCInfo));
gc_info_table_size_ = new_size;
}
void GCInfoTable::Init() {
CHECK(!g_gc_info_table);
Resize();
}
#if DCHECK_IS_ON()
void AssertObjectHasGCInfo(const void* payload, size_t gc_info_index) {
HeapObjectHeader::CheckFromPayload(payload);
#if !defined(COMPONENT_BUILD)
// On component builds we cannot compare the gcInfos as they are statically
// defined in each of the components and hence will not match.
DCHECK_EQ(HeapObjectHeader::FromPayload(payload)->GcInfoIndex(),
gc_info_index);
#endif
}
#endif
} // namespace blink