Commit 43886bc3 authored by Hannes Payer's avatar Hannes Payer Committed by Commit Bot

[heap] Cleanup heap creation a bit.

Change-Id: I7f2d0ba0e544267a9f97838e2904d8dfeecd9a99
Reviewed-on: https://chromium-review.googlesource.com/1095615Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Commit-Queue: Hannes Payer <hpayer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53647}
parent 1dacb786
......@@ -4091,11 +4091,9 @@ void Heap::IterateBuiltins(RootVisitor* v) {
// TODO(1236194): Since the heap size is configurable on the command line
// and through the API, we should gracefully handle the case that the heap
// size is not big enough to fit all the initial objects.
bool Heap::ConfigureHeap(size_t max_semi_space_size_in_kb,
void Heap::ConfigureHeap(size_t max_semi_space_size_in_kb,
size_t max_old_generation_size_in_mb,
size_t code_range_size_in_mb) {
if (HasBeenSetUp()) return false;
// Overwrite default configuration.
if (max_semi_space_size_in_kb != 0) {
max_semi_space_size_ =
......@@ -4183,7 +4181,6 @@ bool Heap::ConfigureHeap(size_t max_semi_space_size_in_kb,
code_range_size_ = code_range_size_in_mb * MB;
configured_ = true;
return true;
}
......@@ -4210,7 +4207,7 @@ void Heap::GetFromRingBuffer(char* buffer) {
memcpy(buffer + copied, trace_ring_buffer_, ring_buffer_end_);
}
bool Heap::ConfigureHeapDefault() { return ConfigureHeap(0, 0, 0); }
void Heap::ConfigureHeapDefault() { ConfigureHeap(0, 0, 0); }
void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
*stats->start_marker = HeapStats::kStartMarker;
......@@ -4517,30 +4514,26 @@ HeapObject* Heap::AllocateRawCodeInLargeObjectSpace(int size) {
return nullptr;
}
bool Heap::SetUp() {
void Heap::SetUp() {
#ifdef V8_ENABLE_ALLOCATION_TIMEOUT
allocation_timeout_ = NextAllocationTimeout();
#endif
// Initialize heap spaces and initial maps and objects. Whenever something
// goes wrong, just return false. The caller should check the results and
// call Heap::TearDown() to release allocated memory.
// Initialize heap spaces and initial maps and objects.
//
// If the heap is not yet configured (e.g. through the API), configure it.
// Configuration is based on the flags new-space-size (really the semispace
// size) and old-space-size if set or the initial values of semispace_size_
// and old_generation_size_ otherwise.
if (!configured_) {
if (!ConfigureHeapDefault()) return false;
}
if (!configured_) ConfigureHeapDefault();
mmap_region_base_ =
reinterpret_cast<uintptr_t>(v8::internal::GetRandomMmapAddr()) &
~kMmapRegionMask;
// Set up memory allocator.
memory_allocator_ = new MemoryAllocator(isolate_);
if (!memory_allocator_->SetUp(MaxReserved(), code_range_size_)) return false;
memory_allocator_ =
new MemoryAllocator(isolate_, MaxReserved(), code_range_size_);
store_buffer_ = new StoreBuffer(this);
......@@ -4562,26 +4555,17 @@ bool Heap::SetUp() {
new ConcurrentMarking(this, nullptr, nullptr, nullptr, nullptr);
}
for (int i = 0; i <= LAST_SPACE; i++) {
for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
space_[i] = nullptr;
}
space_[NEW_SPACE] = new_space_ = new NewSpace(this);
if (!new_space_->SetUp(initial_semispace_size_, max_semi_space_size_)) {
return false;
}
space_[RO_SPACE] = read_only_space_ = new ReadOnlySpace(this);
space_[NEW_SPACE] = new_space_ =
new NewSpace(this, initial_semispace_size_, max_semi_space_size_);
space_[OLD_SPACE] = old_space_ = new OldSpace(this);
space_[CODE_SPACE] = code_space_ = new CodeSpace(this);
space_[MAP_SPACE] = map_space_ = new MapSpace(this, MAP_SPACE);
// The large object space may contain code or data. We set the memory
// to be non-executable here for safety, but this means we need to enable it
// explicitly when allocating large code objects.
space_[LO_SPACE] = lo_space_ = new LargeObjectSpace(this, LO_SPACE);
space_[RO_SPACE] = read_only_space_ =
new ReadOnlySpace(this, RO_SPACE, NOT_EXECUTABLE);
space_[MAP_SPACE] = map_space_ = new MapSpace(this);
space_[LO_SPACE] = lo_space_ = new LargeObjectSpace(this);
// Set up the seed that is used to randomize the string hash function.
DCHECK_EQ(Smi::kZero, hash_seed());
......@@ -4641,8 +4625,6 @@ bool Heap::SetUp() {
write_protect_code_memory_ = FLAG_write_protect_code_memory;
external_reference_table_.Init(isolate_);
return true;
}
void Heap::InitializeHashSeed() {
......
......@@ -964,15 +964,14 @@ class Heap {
// max_semi_space_size_in_kb: maximum semi-space size in KB
// max_old_generation_size_in_mb: maximum old generation size in MB
// code_range_size_in_mb: code range size in MB
// Return false if the heap has been set up already.
bool ConfigureHeap(size_t max_semi_space_size_in_kb,
void ConfigureHeap(size_t max_semi_space_size_in_kb,
size_t max_old_generation_size_in_mb,
size_t code_range_size_in_mb);
bool ConfigureHeapDefault();
void ConfigureHeapDefault();
// Prepares the heap, setting up memory areas that are needed in the isolate
// without actually creating any objects.
bool SetUp();
void SetUp();
// (Re-)Initialize hash seed from flag or RNG.
void InitializeHashSeed();
......
......@@ -94,13 +94,11 @@ PauseAllocationObserversScope::~PauseAllocationObserversScope() {
// -----------------------------------------------------------------------------
// CodeRange
CodeRange::CodeRange(Isolate* isolate)
CodeRange::CodeRange(Isolate* isolate, size_t requested)
: isolate_(isolate),
free_list_(0),
allocation_list_(0),
current_allocation_block_index_(0) {}
bool CodeRange::SetUp(size_t requested) {
current_allocation_block_index_(0) {
DCHECK(!virtual_memory_.IsReserved());
if (requested == 0) {
......@@ -110,7 +108,7 @@ bool CodeRange::SetUp(size_t requested) {
if (kRequiresCodeRange) {
requested = kMaximalCodeRangeSize;
} else {
return true;
return;
}
}
......@@ -129,7 +127,8 @@ bool CodeRange::SetUp(size_t requested) {
if (!AlignedAllocVirtualMemory(
requested, Max(kCodeRangeAreaAlignment, AllocatePageSize()),
GetRandomMmapAddr(), &reservation)) {
return false;
V8::FatalProcessOutOfMemory(isolate,
"CodeRange setup: allocate virtual memory");
}
// We are sure that we have mapped a block of requested addresses.
......@@ -141,7 +140,7 @@ bool CodeRange::SetUp(size_t requested) {
if (reserved_area > 0) {
if (!reservation.SetPermissions(base, reserved_area,
PageAllocator::kReadWrite))
return false;
V8::FatalProcessOutOfMemory(isolate, "CodeRange setup: set permissions");
base += reserved_area;
}
......@@ -154,7 +153,6 @@ bool CodeRange::SetUp(size_t requested) {
NewEvent("CodeRange", reinterpret_cast<void*>(reservation.address()),
requested));
virtual_memory_.TakeControl(&reservation);
return true;
}
bool CodeRange::CompareFreeBlockAddress(const FreeBlock& left,
......@@ -268,26 +266,17 @@ void CodeRange::ReleaseBlock(const FreeBlock* block) {
// MemoryAllocator
//
MemoryAllocator::MemoryAllocator(Isolate* isolate)
MemoryAllocator::MemoryAllocator(Isolate* isolate, size_t capacity,
size_t code_range_size)
: isolate_(isolate),
code_range_(nullptr),
capacity_(0),
capacity_(RoundUp(capacity, Page::kPageSize)),
size_(0),
size_executable_(0),
lowest_ever_allocated_(static_cast<Address>(-1ll)),
highest_ever_allocated_(kNullAddress),
unmapper_(isolate->heap(), this) {}
bool MemoryAllocator::SetUp(size_t capacity, size_t code_range_size) {
capacity_ = ::RoundUp(capacity, Page::kPageSize);
size_ = 0;
size_executable_ = 0;
code_range_ = new CodeRange(isolate_);
if (!code_range_->SetUp(code_range_size)) return false;
return true;
unmapper_(isolate->heap(), this) {
code_range_ = new CodeRange(isolate_, code_range_size);
}
......@@ -1982,24 +1971,25 @@ void PagedSpace::VerifyCountersBeforeConcurrentSweeping() {
// -----------------------------------------------------------------------------
// NewSpace implementation
bool NewSpace::SetUp(size_t initial_semispace_capacity,
size_t maximum_semispace_capacity) {
DCHECK(initial_semispace_capacity <= maximum_semispace_capacity);
DCHECK(base::bits::IsPowerOfTwo(
static_cast<uint32_t>(maximum_semispace_capacity)));
to_space_.SetUp(initial_semispace_capacity, maximum_semispace_capacity);
from_space_.SetUp(initial_semispace_capacity, maximum_semispace_capacity);
NewSpace::NewSpace(Heap* heap, size_t initial_semispace_capacity,
size_t max_semispace_capacity)
: SpaceWithLinearArea(heap, NEW_SPACE),
to_space_(heap, kToSpace),
from_space_(heap, kFromSpace),
reservation_() {
DCHECK(initial_semispace_capacity <= max_semispace_capacity);
DCHECK(
base::bits::IsPowerOfTwo(static_cast<uint32_t>(max_semispace_capacity)));
to_space_.SetUp(initial_semispace_capacity, max_semispace_capacity);
from_space_.SetUp(initial_semispace_capacity, max_semispace_capacity);
if (!to_space_.Commit()) {
return false;
V8::FatalProcessOutOfMemory(heap->isolate(), "New space setup");
}
DCHECK(!from_space_.is_committed()); // No need to use memory yet.
ResetLinearAllocationArea();
return true;
}
void NewSpace::TearDown() {
allocation_info_.Reset(kNullAddress, kNullAddress);
......@@ -3134,9 +3124,8 @@ bool PagedSpace::RawSlowRefillLinearAllocationArea(int size_in_bytes) {
void MapSpace::VerifyObject(HeapObject* object) { CHECK(object->IsMap()); }
#endif
ReadOnlySpace::ReadOnlySpace(Heap* heap, AllocationSpace id,
Executability executable)
: PagedSpace(heap, id, executable),
ReadOnlySpace::ReadOnlySpace(Heap* heap)
: PagedSpace(heap, RO_SPACE, NOT_EXECUTABLE),
is_string_padding_cleared_(heap->isolate()->initialized_from_snapshot()) {
}
......@@ -3235,8 +3224,8 @@ HeapObject* LargeObjectIterator::Next() {
// -----------------------------------------------------------------------------
// LargeObjectSpace
LargeObjectSpace::LargeObjectSpace(Heap* heap, AllocationSpace id)
: Space(heap, id), // Managed on a per-allocation basis
LargeObjectSpace::LargeObjectSpace(Heap* heap)
: Space(heap, LO_SPACE), // Managed on a per-allocation basis
size_(0),
page_count_(0),
objects_size_(0),
......
......@@ -1023,16 +1023,11 @@ class MemoryChunkValidator {
// manages a range of virtual memory.
class CodeRange {
public:
explicit CodeRange(Isolate* isolate);
CodeRange(Isolate* isolate, size_t requested_size);
~CodeRange() {
if (virtual_memory_.IsReserved()) virtual_memory_.Free();
}
// Reserves a range of virtual memory, but does not commit any of it.
// Can only be called once, at heap initialization time.
// Returns false on failure.
bool SetUp(size_t requested_size);
bool valid() { return virtual_memory_.IsReserved(); }
Address start() {
DCHECK(valid());
......@@ -1299,11 +1294,8 @@ class V8_EXPORT_PRIVATE MemoryAllocator {
static intptr_t GetCommitPageSize();
explicit MemoryAllocator(Isolate* isolate);
// Initializes its internal bookkeeping structures.
// Max capacity of the total space and executable memory limit.
bool SetUp(size_t max_capacity, size_t code_range_size);
MemoryAllocator(Isolate* isolate, size_t max_capacity,
size_t code_range_size);
void TearDown();
......@@ -2531,11 +2523,8 @@ class NewSpace : public SpaceWithLinearArea {
public:
typedef PageIterator iterator;
explicit NewSpace(Heap* heap)
: SpaceWithLinearArea(heap, NEW_SPACE),
to_space_(heap, kToSpace),
from_space_(heap, kFromSpace),
reservation_() {}
NewSpace(Heap* heap, size_t initial_semispace_capacity,
size_t max_semispace_capacity);
~NewSpace() override { TearDown(); }
......@@ -2543,8 +2532,6 @@ class NewSpace : public SpaceWithLinearArea {
inline bool ContainsSlow(Address a);
inline bool Contains(Object* o);
bool SetUp(size_t initial_semispace_capacity, size_t max_semispace_capacity);
// Tears down the space. Heap memory was not allocated by the space, so it
// is not deallocated here.
void TearDown();
......@@ -2858,8 +2845,7 @@ class CodeSpace : public PagedSpace {
class MapSpace : public PagedSpace {
public:
// Creates a map space object.
MapSpace(Heap* heap, AllocationSpace id)
: PagedSpace(heap, id, NOT_EXECUTABLE) {}
explicit MapSpace(Heap* heap) : PagedSpace(heap, MAP_SPACE, NOT_EXECUTABLE) {}
int RoundSizeDownToObjectAlignment(int size) override {
if (base::bits::IsPowerOfTwo(Map::kSize)) {
......@@ -2891,7 +2877,7 @@ class ReadOnlySpace : public PagedSpace {
ReadOnlySpace* space_;
};
ReadOnlySpace(Heap* heap, AllocationSpace id, Executability executable);
explicit ReadOnlySpace(Heap* heap);
void ClearStringPaddingIfNeeded();
void MarkAsReadOnly();
......@@ -2919,7 +2905,7 @@ class LargeObjectSpace : public Space {
public:
typedef LargePageIterator iterator;
LargeObjectSpace(Heap* heap, AllocationSpace id);
explicit LargeObjectSpace(Heap* heap);
~LargeObjectSpace() override { TearDown(); }
// Releases internal resources, frees objects in this space.
......
......@@ -2991,10 +2991,7 @@ bool Isolate::Init(StartupDeserializer* des) {
// SetUp the object heap.
DCHECK(!heap_.HasBeenSetUp());
if (!heap_.SetUp()) {
V8::FatalProcessOutOfMemory(this, "heap setup");
return false;
}
heap_.SetUp();
// Setup the wasm engine. Currently, there's one per Isolate.
wasm_engine_.reset(new wasm::WasmEngine(
......
......@@ -204,8 +204,8 @@ class Block {
TEST(CodeRange) {
const size_t code_range_size = 32*MB;
CcTest::InitializeVM();
CodeRange code_range(reinterpret_cast<Isolate*>(CcTest::isolate()));
code_range.SetUp(code_range_size);
CodeRange code_range(reinterpret_cast<Isolate*>(CcTest::isolate()),
code_range_size);
size_t current_allocated = 0;
size_t total_allocated = 0;
std::vector<Block> blocks;
......
......@@ -84,8 +84,8 @@ static void VerifyMemoryChunk(Isolate* isolate, Heap* heap,
CodeRange* code_range, size_t reserve_area_size,
size_t commit_area_size, Executability executable,
Space* space) {
MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
CHECK(memory_allocator->SetUp(heap->MaxReserved(), 0));
MemoryAllocator* memory_allocator =
new MemoryAllocator(isolate, heap->MaxReserved(), 0);
{
TestMemoryAllocatorScope test_allocator_scope(isolate, memory_allocator);
TestCodeRangeScope test_code_range_scope(isolate, code_range);
......@@ -122,15 +122,12 @@ static void VerifyMemoryChunk(Isolate* isolate, Heap* heap,
TEST(Regress3540) {
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
CHECK(memory_allocator->SetUp(heap->MaxReserved(), 0));
MemoryAllocator* memory_allocator =
new MemoryAllocator(isolate, heap->MaxReserved(), 0);
TestMemoryAllocatorScope test_allocator_scope(isolate, memory_allocator);
CodeRange* code_range = new CodeRange(isolate);
size_t code_range_size =
kMinimumCodeRangeSize > 0 ? kMinimumCodeRangeSize : 3 * Page::kPageSize;
if (!code_range->SetUp(code_range_size)) {
return;
}
CodeRange* code_range = new CodeRange(isolate, code_range_size);
Address address;
size_t size;
......@@ -172,9 +169,8 @@ TEST(MemoryChunk) {
initial_commit_area_size = PseudorandomAreaSize();
// With CodeRange.
CodeRange* code_range = new CodeRange(isolate);
const size_t code_range_size = 32 * MB;
if (!code_range->SetUp(code_range_size)) return;
CodeRange* code_range = new CodeRange(isolate, code_range_size);
VerifyMemoryChunk(isolate, heap, code_range, reserve_area_size,
initial_commit_area_size, EXECUTABLE, heap->code_space());
......@@ -183,16 +179,6 @@ TEST(MemoryChunk) {
initial_commit_area_size, NOT_EXECUTABLE,
heap->old_space());
delete code_range;
// Without a valid CodeRange, i.e., omitting SetUp.
code_range = new CodeRange(isolate);
VerifyMemoryChunk(isolate, heap, code_range, reserve_area_size,
initial_commit_area_size, EXECUTABLE, heap->code_space());
VerifyMemoryChunk(isolate, heap, code_range, reserve_area_size,
initial_commit_area_size, NOT_EXECUTABLE,
heap->old_space());
delete code_range;
}
}
......@@ -201,9 +187,9 @@ TEST(MemoryAllocator) {
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
MemoryAllocator* memory_allocator =
new MemoryAllocator(isolate, heap->MaxReserved(), 0);
CHECK_NOT_NULL(memory_allocator);
CHECK(memory_allocator->SetUp(heap->MaxReserved(), 0));
TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
{
......@@ -249,14 +235,12 @@ TEST(MemoryAllocator) {
TEST(NewSpace) {
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
CHECK(memory_allocator->SetUp(heap->MaxReserved(), 0));
MemoryAllocator* memory_allocator =
new MemoryAllocator(isolate, heap->MaxReserved(), 0);
TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
NewSpace new_space(heap);
CHECK(new_space.SetUp(CcTest::heap()->InitialSemiSpaceSize(),
CcTest::heap()->InitialSemiSpaceSize()));
NewSpace new_space(heap, CcTest::heap()->InitialSemiSpaceSize(),
CcTest::heap()->InitialSemiSpaceSize());
CHECK(new_space.MaximumCapacity());
while (new_space.Available() >= kMaxRegularHeapObjectSize) {
......@@ -275,8 +259,8 @@ TEST(NewSpace) {
TEST(OldSpace) {
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
CHECK(memory_allocator->SetUp(heap->MaxReserved(), 0));
MemoryAllocator* memory_allocator =
new MemoryAllocator(isolate, heap->MaxReserved(), 0);
TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
OldSpace* s = new OldSpace(heap);
......
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