blob: 82975fa339d6b85959236bf3de4101663e347222 [file] [log] [blame]
// Copyright 2020 the V8 project 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 "src/heap/concurrent-allocator.h"
#include "src/common/globals.h"
#include "src/execution/isolate.h"
#include "src/handles/persistent-handles.h"
#include "src/heap/concurrent-allocator-inl.h"
#include "src/heap/local-heap-inl.h"
#include "src/heap/local-heap.h"
#include "src/heap/marking.h"
#include "src/heap/memory-chunk.h"
namespace v8 {
namespace internal {
void StressConcurrentAllocatorTask::RunInternal() {
Heap* heap = isolate_->heap();
LocalHeap local_heap(heap, ThreadKind::kBackground);
UnparkedScope unparked_scope(&local_heap);
const int kNumIterations = 2000;
const int kSmallObjectSize = 10 * kTaggedSize;
const int kMediumObjectSize = 8 * KB;
const int kLargeObjectSize =
static_cast<int>(MemoryChunk::kPageSize -
MemoryChunkLayout::ObjectStartOffsetInDataPage());
for (int i = 0; i < kNumIterations; i++) {
// Isolate tear down started, stop allocation...
if (heap->gc_state() == Heap::TEAR_DOWN) return;
Address address = local_heap.AllocateRawOrFail(
kSmallObjectSize, AllocationType::kOld, AllocationOrigin::kRuntime,
AllocationAlignment::kWordAligned);
heap->CreateFillerObjectAtBackground(
address, kSmallObjectSize, ClearFreedMemoryMode::kDontClearFreedMemory);
local_heap.Safepoint();
address = local_heap.AllocateRawOrFail(
kMediumObjectSize, AllocationType::kOld, AllocationOrigin::kRuntime,
AllocationAlignment::kWordAligned);
heap->CreateFillerObjectAtBackground(
address, kMediumObjectSize,
ClearFreedMemoryMode::kDontClearFreedMemory);
local_heap.Safepoint();
address = local_heap.AllocateRawOrFail(
kLargeObjectSize, AllocationType::kOld, AllocationOrigin::kRuntime,
AllocationAlignment::kWordAligned);
heap->CreateFillerObjectAtBackground(
address, kLargeObjectSize, ClearFreedMemoryMode::kDontClearFreedMemory);
local_heap.Safepoint();
}
Schedule(isolate_);
}
// static
void StressConcurrentAllocatorTask::Schedule(Isolate* isolate) {
CHECK(FLAG_local_heaps && FLAG_concurrent_allocation);
auto task = std::make_unique<StressConcurrentAllocatorTask>(isolate);
const double kDelayInSeconds = 0.1;
V8::GetCurrentPlatform()->CallDelayedOnWorkerThread(std::move(task),
kDelayInSeconds);
}
void ConcurrentAllocator::FreeLinearAllocationArea() {
lab_.CloseAndMakeIterable();
}
void ConcurrentAllocator::MakeLinearAllocationAreaIterable() {
lab_.MakeIterable();
}
void ConcurrentAllocator::MarkLinearAllocationAreaBlack() {
Address top = lab_.top();
Address limit = lab_.limit();
if (top != kNullAddress && top != limit) {
Page::FromAllocationAreaAddress(top)->CreateBlackAreaBackground(top, limit);
}
}
void ConcurrentAllocator::UnmarkLinearAllocationArea() {
Address top = lab_.top();
Address limit = lab_.limit();
if (top != kNullAddress && top != limit) {
Page::FromAllocationAreaAddress(top)->DestroyBlackAreaBackground(top,
limit);
}
}
AllocationResult ConcurrentAllocator::AllocateInLabSlow(
int object_size, AllocationAlignment alignment, AllocationOrigin origin) {
if (!EnsureLab(origin)) {
return AllocationResult::Retry(OLD_SPACE);
}
AllocationResult allocation = lab_.AllocateRawAligned(object_size, alignment);
DCHECK(!allocation.IsRetry());
return allocation;
}
bool ConcurrentAllocator::EnsureLab(AllocationOrigin origin) {
auto result = space_->RawRefillLabBackground(
local_heap_, kLabSize, kMaxLabSize, kWordAligned, origin);
if (!result) return false;
if (local_heap_->heap()->incremental_marking()->black_allocation()) {
Address top = result->first;
Address limit = top + result->second;
Page::FromAllocationAreaAddress(top)->CreateBlackAreaBackground(top, limit);
}
HeapObject object = HeapObject::FromAddress(result->first);
LocalAllocationBuffer saved_lab = std::move(lab_);
lab_ = LocalAllocationBuffer::FromResult(
local_heap_->heap(), AllocationResult(object), result->second);
DCHECK(lab_.IsValid());
if (!lab_.TryMerge(&saved_lab)) {
saved_lab.CloseAndMakeIterable();
}
return true;
}
AllocationResult ConcurrentAllocator::AllocateOutsideLab(
int object_size, AllocationAlignment alignment, AllocationOrigin origin) {
auto result = space_->RawRefillLabBackground(local_heap_, object_size,
object_size, alignment, origin);
if (!result) return AllocationResult::Retry(OLD_SPACE);
HeapObject object = HeapObject::FromAddress(result->first);
if (local_heap_->heap()->incremental_marking()->black_allocation()) {
local_heap_->heap()->incremental_marking()->MarkBlackBackground(
object, object_size);
}
return AllocationResult(object);
}
} // namespace internal
} // namespace v8