Commit 2bb51df9 authored by mlippautz's avatar mlippautz Committed by Commit bot

Reland of "[cctest] Add tests for aborting compaction of pages"

Tests for
* aborting a full page.
* partially aborting a page.
* partially aborting a page with pointers between aborted pages.
* partially aborting a page with store buffer entries.

Also introduces force_oom() which prohibits a old space to
expand

BUG=chromium:524425
LOG=N

CQ_EXTRA_TRYBOTS=tryserver.v8:v8_linux_nosnap_rel,v8_linux_nosnap_dbg,v8_win_nosnap_shared_rel,v8_win_nosnap_shared_compile_rel

Review URL: https://codereview.chromium.org/1518803005

Cr-Commit-Position: refs/heads/master@{#32899}
parent 65d3009e
......@@ -163,7 +163,8 @@ Heap::Heap()
gc_callbacks_depth_(0),
deserialization_complete_(false),
strong_roots_list_(NULL),
array_buffer_tracker_(NULL) {
array_buffer_tracker_(NULL),
force_oom_(false) {
// Allow build-time customization of the max semispace size. Building
// V8 with snapshots and a non-default max semispace size is much
// easier if you can define it as part of the build environment.
......
......@@ -817,6 +817,7 @@ class Heap {
// TODO(hpayer): There is still a missmatch between capacity and actual
// committed memory size.
bool CanExpandOldGeneration(int size) {
if (force_oom_) return false;
return (CommittedOldGenerationMemory() + size) < MaxOldGenerationSize();
}
......@@ -2117,6 +2118,8 @@ class Heap {
MUST_USE_RESULT AllocationResult InternalizeString(String* str);
void set_force_oom(bool value) { force_oom_ = value; }
// The amount of external memory registered through the API kept alive
// by global handles
int64_t amount_of_external_allocated_memory_;
......@@ -2365,6 +2368,9 @@ class Heap {
ArrayBufferTracker* array_buffer_tracker_;
// Used for testing purposes.
bool force_oom_;
// Classes in "heap" can be friends.
friend class AlwaysAllocateScope;
friend class GCCallbacksScope;
......
......@@ -3774,6 +3774,16 @@ void MarkCompactCollector::StartSweepSpace(PagedSpace* space) {
continue;
}
if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) {
// We need to sweep the page to get it into an iterable state again. Note
// that this adds unusable memory into the free list that is later on
// (in the free list) dropped again. Since we only use the flag for
// testing this is fine.
Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST,
IGNORE_FREE_SPACE>(space, nullptr, p, nullptr);
continue;
}
// One unused page is kept, all further are released before sweeping them.
if (p->LiveBytes() == 0) {
if (unused_page_present) {
......
......@@ -2291,7 +2291,7 @@ FreeSpace* FreeListCategory::PickNodeFromList(int* node_size) {
if (node == nullptr) return nullptr;
Page* page = Page::FromAddress(node->address());
while ((node != nullptr) && page->IsEvacuationCandidate()) {
while ((node != nullptr) && !page->CanAllocate()) {
available_ -= node->size();
page->add_available_in_free_list(type_, -(node->Size()));
node = node->next();
......@@ -2333,7 +2333,7 @@ FreeSpace* FreeListCategory::SearchForNodeInList(int size_in_bytes,
int size = cur_node->size();
Page* page_for_node = Page::FromAddress(cur_node->address());
if ((size >= size_in_bytes) || page_for_node->IsEvacuationCandidate()) {
if ((size >= size_in_bytes) || !page_for_node->CanAllocate()) {
// The node is either large enough or contained in an evacuation
// candidate. In both cases we need to unlink it from the list.
available_ -= size;
......@@ -2347,7 +2347,7 @@ FreeSpace* FreeListCategory::SearchForNodeInList(int size_in_bytes,
prev_non_evac_node->set_next(cur_node->next());
}
// For evacuation candidates we continue.
if (page_for_node->IsEvacuationCandidate()) {
if (!page_for_node->CanAllocate()) {
page_for_node->add_available_in_free_list(type_, -size);
continue;
}
......@@ -2758,8 +2758,7 @@ void PagedSpace::RepairFreeListsAfterDeserialization() {
void PagedSpace::EvictEvacuationCandidatesFromLinearAllocationArea() {
if (allocation_info_.top() >= allocation_info_.limit()) return;
if (Page::FromAllocationTop(allocation_info_.top())
->IsEvacuationCandidate()) {
if (!Page::FromAllocationTop(allocation_info_.top())->CanAllocate()) {
// Create filler object to keep page iterable if it was iterable.
int remaining =
static_cast<int>(allocation_info_.limit() - allocation_info_.top());
......
......@@ -323,6 +323,9 @@ class MemoryChunk {
// candidates selection cycle.
FORCE_EVACUATION_CANDIDATE_FOR_TESTING,
// This flag is inteded to be used for testing.
NEVER_ALLOCATE_ON_PAGE,
// The memory chunk is already logically freed, however the actual freeing
// still has to be performed.
PRE_FREED,
......@@ -682,6 +685,10 @@ class MemoryChunk {
return IsFlagSet(EVACUATION_CANDIDATE);
}
bool CanAllocate() {
return !IsEvacuationCandidate() && !IsFlagSet(NEVER_ALLOCATE_ON_PAGE);
}
bool ShouldSkipEvacuationSlotRecording() {
return (flags_ & kSkipEvacuationSlotsRecordingMask) != 0;
}
......
......@@ -96,6 +96,7 @@
'gay-shortest.cc',
'heap/heap-tester.h',
'heap/test-alloc.cc',
'heap/test-compaction.cc',
'heap/test-heap.cc',
'heap/test-incremental-marking.cc',
'heap/test-mark-compact.cc',
......
......@@ -11,6 +11,10 @@
// Tests that should have access to private methods of {v8::internal::Heap}.
// Those tests need to be defined using HEAP_TEST(Name) { ... }.
#define HEAP_TEST_METHODS(V) \
V(CompactionFullAbortedPage) \
V(CompactionPartiallyAbortedPage) \
V(CompactionPartiallyAbortedPageIntraAbortedPointers) \
V(CompactionPartiallyAbortedPageWithStoreBufferEntries) \
V(CompactionSpaceDivideMultiplePages) \
V(CompactionSpaceDivideSinglePage) \
V(GCFlags) \
......
This diff is collapsed.
......@@ -16,34 +16,32 @@ namespace v8 {
namespace internal {
static int LenFromSize(int size) {
return (size - i::FixedArray::kHeaderSize) / i::kPointerSize;
return (size - FixedArray::kHeaderSize) / kPointerSize;
}
static inline void CreatePadding(i::Heap* heap, int padding_size,
i::PretenureFlag tenure) {
const int max_number_of_objects = 20;
v8::internal::Handle<v8::internal::FixedArray>
big_objects[max_number_of_objects];
i::Isolate* isolate = heap->isolate();
static inline std::vector<Handle<FixedArray>> CreatePadding(
Heap* heap, int padding_size, PretenureFlag tenure,
int object_size = Page::kMaxRegularHeapObjectSize) {
std::vector<Handle<FixedArray>> handles;
Isolate* isolate = heap->isolate();
int allocate_memory;
int length;
int free_memory = padding_size;
if (tenure == i::TENURED) {
int current_free_memory =
static_cast<int>(*heap->old_space()->allocation_limit_address() -
*heap->old_space()->allocation_top_address());
CHECK(padding_size <= current_free_memory || current_free_memory == 0);
heap->old_space()->EmptyAllocationInfo();
int overall_free_memory = static_cast<int>(heap->old_space()->Available());
CHECK(padding_size <= overall_free_memory || overall_free_memory == 0);
} else {
heap->new_space()->DisableInlineAllocationSteps();
int current_free_memory =
int overall_free_memory =
static_cast<int>(*heap->new_space()->allocation_limit_address() -
*heap->new_space()->allocation_top_address());
CHECK(padding_size <= current_free_memory || current_free_memory == 0);
CHECK(padding_size <= overall_free_memory || overall_free_memory == 0);
}
for (int i = 0; i < max_number_of_objects && free_memory > 0; i++) {
if (free_memory > i::Page::kMaxRegularHeapObjectSize) {
allocate_memory = i::Page::kMaxRegularHeapObjectSize;
while (free_memory > 0) {
if (free_memory > object_size) {
allocate_memory = object_size;
length = LenFromSize(allocate_memory);
} else {
allocate_memory = free_memory;
......@@ -55,11 +53,12 @@ static inline void CreatePadding(i::Heap* heap, int padding_size,
break;
}
}
big_objects[i] = isolate->factory()->NewFixedArray(length, tenure);
CHECK((tenure == i::NOT_TENURED && heap->InNewSpace(*big_objects[i])) ||
(tenure == i::TENURED && heap->InOldSpace(*big_objects[i])));
handles.push_back(isolate->factory()->NewFixedArray(length, tenure));
CHECK((tenure == NOT_TENURED && heap->InNewSpace(*handles.back())) ||
(tenure == TENURED && heap->InOldSpace(*handles.back())));
free_memory -= allocate_memory;
}
return handles;
}
......
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