Chromium Code Reviews| Index: test/cctest/test-heap.cc |
| diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc |
| index f0682b297c2ac4eb4c5910cb62f8fea8d865c7a4..5d61524d23655b762c78d83ab750cd84ad7fb24a 100644 |
| --- a/test/cctest/test-heap.cc |
| +++ b/test/cctest/test-heap.cc |
| @@ -4329,6 +4329,81 @@ TEST(ArrayShiftSweeping) { |
| } |
| +TEST(PromotionQueue) { |
| + i::FLAG_expose_gc = true; |
| + i::FLAG_max_semi_space_size = 2; |
| + CcTest::InitializeVM(); |
| + v8::HandleScope scope(CcTest::isolate()); |
| + Isolate* isolate = CcTest::i_isolate(); |
| + Heap* heap = isolate->heap(); |
| + NewSpace* new_space = heap->new_space(); |
| + |
| + // In this test we will try to overwrite the promotion queue which is at the |
| + // end of to-space. To actually make that possible, we need at least two |
| + // semi-space pages and take advantage of fragementation. |
|
titzer
2014/07/01 11:58:20
I like these comments
Hannes Payer (out of office)
2014/07/01 16:08:12
I know.
|
| + // (1) Grow semi-space to two pages. |
| + // (2) Create a few small long living objects and call the scavenger to |
| + // move them to the other semi-space. |
| + // (3) Create a huge object, i.e., remainder of first semi-space page and |
| + // create another huge object which should be of maximum allocatable memory |
| + // size of the second semi-space page. |
| + // (4) Call the scavenger again. |
| + // What will happen is: the scavenger will promote the objects created in (2) |
| + // and will create promotion queue entries at the end of the second |
| + // semi-space page during the next scavenge when it promotes the objects to |
| + // the old generation. The first allocation of (3) will fill up the first |
| + // semi-space page. The second allocation in (3) will not fit into the first |
| + // semi-space page, but it will overwrite the promotion queue which are in |
| + // the second semi-space page. If the right guards are in place, the promotion |
| + // queue will be evacuated in that case. |
| + |
| + // Grow the semi-space to two pages to make semi-space copy overwrite the |
| + // promotion queue, which will be at the end of the second page. |
| + intptr_t old_capacity = new_space->Capacity(); |
| + new_space->Grow(); |
| + CHECK(new_space->IsAtMaximumCapacity()); |
| + CHECK(2 * old_capacity == new_space->Capacity()); |
| + |
| + // Call the scavenger two times to get an empty new space |
| + heap->CollectGarbage(NEW_SPACE); |
| + heap->CollectGarbage(NEW_SPACE); |
| + |
| + // First create a few objects which will survive a scavenge, and will get |
| + // promoted to the old generation later on. These objects will create |
| + // promotion queue entries at the end of the second semi-space page. |
| + const int number_handles = 12; |
| + Handle<FixedArray> handles[number_handles]; |
| + for (int i = 0; i < number_handles; i++) { |
| + handles[i] = isolate->factory()->NewFixedArray(1, NOT_TENURED); |
| + } |
| + heap->CollectGarbage(NEW_SPACE); |
| + |
| + // Create the first huge object which will exactly fit the first semi-space |
| + // page. |
| + int new_linear_size = static_cast<int>( |
| + *heap->new_space()->allocation_limit_address() - |
| + *heap->new_space()->allocation_top_address()); |
| + int length = new_linear_size / kPointerSize - FixedArray::kHeaderSize; |
| + Handle<FixedArray> first = |
| + isolate->factory()->NewFixedArray(length, NOT_TENURED); |
| + CHECK(heap->InNewSpace(*first)); |
| + |
| + // Create the second huge object of maximum allocatable second semi-space |
| + // page size. |
| + new_linear_size = static_cast<int>( |
| + *heap->new_space()->allocation_limit_address() - |
| + *heap->new_space()->allocation_top_address()); |
| + length = Page::kMaxRegularHeapObjectSize / kPointerSize - |
| + FixedArray::kHeaderSize; |
| + Handle<FixedArray> second = |
| + isolate->factory()->NewFixedArray(length, NOT_TENURED); |
| + CHECK(heap->InNewSpace(*second)); |
| + |
| + // This scavenge will corrupt memory if the promotion queue is not evacuated. |
| + heap->CollectGarbage(NEW_SPACE); |
| +} |
| + |
| + |
| #ifdef DEBUG |
| TEST(PathTracer) { |
| CcTest::InitializeVM(); |