OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 5537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5548 Page* page = Page::FromAddress(o->elements()->address()); | 5548 Page* page = Page::FromAddress(o->elements()->address()); |
5549 CHECK(page->parallel_sweeping_state().Value() <= | 5549 CHECK(page->parallel_sweeping_state().Value() <= |
5550 MemoryChunk::kSweepingFinalize || | 5550 MemoryChunk::kSweepingFinalize || |
5551 Marking::IsBlack(Marking::MarkBitFrom(o->elements()))); | 5551 Marking::IsBlack(Marking::MarkBitFrom(o->elements()))); |
5552 } | 5552 } |
5553 | 5553 |
5554 | 5554 |
5555 UNINITIALIZED_TEST(PromotionQueue) { | 5555 UNINITIALIZED_TEST(PromotionQueue) { |
5556 i::FLAG_expose_gc = true; | 5556 i::FLAG_expose_gc = true; |
5557 i::FLAG_max_semi_space_size = 2 * (Page::kPageSize / MB); | 5557 i::FLAG_max_semi_space_size = 2 * (Page::kPageSize / MB); |
| 5558 i::FLAG_min_semi_space_size = i::FLAG_max_semi_space_size; |
5558 v8::Isolate::CreateParams create_params; | 5559 v8::Isolate::CreateParams create_params; |
5559 create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); | 5560 create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); |
5560 v8::Isolate* isolate = v8::Isolate::New(create_params); | 5561 v8::Isolate* isolate = v8::Isolate::New(create_params); |
5561 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 5562 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
5562 { | 5563 { |
5563 v8::Isolate::Scope isolate_scope(isolate); | 5564 v8::Isolate::Scope isolate_scope(isolate); |
5564 v8::HandleScope handle_scope(isolate); | 5565 v8::HandleScope handle_scope(isolate); |
5565 v8::Context::New(isolate)->Enter(); | 5566 v8::Context::New(isolate)->Enter(); |
5566 Heap* heap = i_isolate->heap(); | 5567 Heap* heap = i_isolate->heap(); |
5567 NewSpace* new_space = heap->new_space(); | 5568 NewSpace* new_space = heap->new_space(); |
5568 DisableInlineAllocationSteps(new_space); | |
5569 | 5569 |
5570 // In this test we will try to overwrite the promotion queue which is at the | 5570 // In this test we will try to overwrite the promotion queue which is at the |
5571 // end of to-space. To actually make that possible, we need at least two | 5571 // end of to-space. To actually make that possible, we need at least two |
5572 // semi-space pages and take advantage of fragmentation. | 5572 // semi-space pages and take advantage of fragmentation. |
5573 // (1) Grow semi-space to two pages. | 5573 // (1) Use a semi-space consisting of two pages. |
5574 // (2) Create a few small long living objects and call the scavenger to | 5574 // (2) Create a few small long living objects and call the scavenger to |
5575 // move them to the other semi-space. | 5575 // move them to the other semi-space. |
5576 // (3) Create a huge object, i.e., remainder of first semi-space page and | 5576 // (3) Create a huge object, i.e., remainder of first semi-space page and |
5577 // create another huge object which should be of maximum allocatable memory | 5577 // create another huge object which should be of maximum allocatable memory |
5578 // size of the second semi-space page. | 5578 // size of the second semi-space page. |
5579 // (4) Call the scavenger again. | 5579 // (4) Call the scavenger again. |
5580 // What will happen is: the scavenger will promote the objects created in | 5580 // What will happen is: the scavenger will promote the objects created in |
5581 // (2) and will create promotion queue entries at the end of the second | 5581 // (2) and will create promotion queue entries at the end of the second |
5582 // semi-space page during the next scavenge when it promotes the objects to | 5582 // semi-space page during the next scavenge when it promotes the objects to |
5583 // the old generation. The first allocation of (3) will fill up the first | 5583 // the old generation. The first allocation of (3) will fill up the first |
5584 // semi-space page. The second allocation in (3) will not fit into the | 5584 // semi-space page. The second allocation in (3) will not fit into the |
5585 // first semi-space page, but it will overwrite the promotion queue which | 5585 // first semi-space page, but it will overwrite the promotion queue which |
5586 // are in the second semi-space page. If the right guards are in place, the | 5586 // are in the second semi-space page. If the right guards are in place, the |
5587 // promotion queue will be evacuated in that case. | 5587 // promotion queue will be evacuated in that case. |
5588 | 5588 |
5589 // Grow the semi-space to two pages to make semi-space copy overwrite the | |
5590 // promotion queue, which will be at the end of the second page. | |
5591 intptr_t old_capacity = new_space->TotalCapacity(); | |
5592 | 5589 |
5593 // If we are in a low memory config, we can't grow to two pages and we can't | |
5594 // run this test. This also means the issue we are testing cannot arise, as | |
5595 // there is no fragmentation. | |
5596 if (new_space->IsAtMaximumCapacity()) return; | |
5597 | |
5598 new_space->Grow(); | |
5599 CHECK(new_space->IsAtMaximumCapacity()); | 5590 CHECK(new_space->IsAtMaximumCapacity()); |
5600 CHECK(2 * old_capacity == new_space->TotalCapacity()); | 5591 CHECK(i::FLAG_min_semi_space_size * MB == new_space->TotalCapacity()); |
5601 | 5592 |
5602 // Call the scavenger two times to get an empty new space | 5593 // Call the scavenger two times to get an empty new space |
5603 heap->CollectGarbage(NEW_SPACE); | 5594 heap->CollectGarbage(NEW_SPACE); |
5604 heap->CollectGarbage(NEW_SPACE); | 5595 heap->CollectGarbage(NEW_SPACE); |
5605 | 5596 |
5606 // First create a few objects which will survive a scavenge, and will get | 5597 // First create a few objects which will survive a scavenge, and will get |
5607 // promoted to the old generation later on. These objects will create | 5598 // promoted to the old generation later on. These objects will create |
5608 // promotion queue entries at the end of the second semi-space page. | 5599 // promotion queue entries at the end of the second semi-space page. |
5609 const int number_handles = 12; | 5600 const int number_handles = 12; |
5610 Handle<FixedArray> handles[number_handles]; | 5601 Handle<FixedArray> handles[number_handles]; |
5611 for (int i = 0; i < number_handles; i++) { | 5602 for (int i = 0; i < number_handles; i++) { |
5612 handles[i] = i_isolate->factory()->NewFixedArray(1, NOT_TENURED); | 5603 handles[i] = i_isolate->factory()->NewFixedArray(1, NOT_TENURED); |
5613 } | 5604 } |
| 5605 |
5614 heap->CollectGarbage(NEW_SPACE); | 5606 heap->CollectGarbage(NEW_SPACE); |
| 5607 CHECK(i::FLAG_min_semi_space_size * MB == new_space->TotalCapacity()); |
5615 | 5608 |
5616 // Create the first huge object which will exactly fit the first semi-space | 5609 // Create the first huge object which will exactly fit the first semi-space |
5617 // page. | 5610 // page. |
| 5611 DisableInlineAllocationSteps(new_space); |
5618 int new_linear_size = | 5612 int new_linear_size = |
5619 static_cast<int>(*heap->new_space()->allocation_limit_address() - | 5613 static_cast<int>(*heap->new_space()->allocation_limit_address() - |
5620 *heap->new_space()->allocation_top_address()); | 5614 *heap->new_space()->allocation_top_address()); |
5621 int length = new_linear_size / kPointerSize - FixedArray::kHeaderSize; | 5615 int length = (new_linear_size - FixedArray::kHeaderSize) / kPointerSize; |
5622 Handle<FixedArray> first = | 5616 Handle<FixedArray> first = |
5623 i_isolate->factory()->NewFixedArray(length, NOT_TENURED); | 5617 i_isolate->factory()->NewFixedArray(length, NOT_TENURED); |
5624 CHECK(heap->InNewSpace(*first)); | 5618 CHECK(heap->InNewSpace(*first)); |
5625 | 5619 |
| 5620 // Create a small object to initialize the bump pointer on the second |
| 5621 // semi-space page. |
| 5622 Handle<FixedArray> small = |
| 5623 i_isolate->factory()->NewFixedArray(1, NOT_TENURED); |
| 5624 CHECK(heap->InNewSpace(*small)); |
| 5625 |
| 5626 |
5626 // Create the second huge object of maximum allocatable second semi-space | 5627 // Create the second huge object of maximum allocatable second semi-space |
5627 // page size. | 5628 // page size. |
| 5629 DisableInlineAllocationSteps(new_space); |
5628 new_linear_size = | 5630 new_linear_size = |
5629 static_cast<int>(*heap->new_space()->allocation_limit_address() - | 5631 static_cast<int>(*heap->new_space()->allocation_limit_address() - |
5630 *heap->new_space()->allocation_top_address()); | 5632 *heap->new_space()->allocation_top_address()); |
5631 length = Page::kMaxRegularHeapObjectSize / kPointerSize - | 5633 length = (new_linear_size - FixedArray::kHeaderSize) / kPointerSize; |
5632 FixedArray::kHeaderSize; | |
5633 Handle<FixedArray> second = | 5634 Handle<FixedArray> second = |
5634 i_isolate->factory()->NewFixedArray(length, NOT_TENURED); | 5635 i_isolate->factory()->NewFixedArray(length, NOT_TENURED); |
5635 CHECK(heap->InNewSpace(*second)); | 5636 CHECK(heap->InNewSpace(*second)); |
5636 | 5637 |
5637 // This scavenge will corrupt memory if the promotion queue is not | 5638 // This scavenge will corrupt memory if the promotion queue is not |
5638 // evacuated. | 5639 // evacuated. |
5639 heap->CollectGarbage(NEW_SPACE); | 5640 heap->CollectGarbage(NEW_SPACE); |
5640 } | 5641 } |
5641 isolate->Dispose(); | 5642 isolate->Dispose(); |
5642 } | 5643 } |
(...skipping 773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6416 // The CollectGarbage call above starts sweeper threads. | 6417 // The CollectGarbage call above starts sweeper threads. |
6417 // The crash will happen if the following two functions | 6418 // The crash will happen if the following two functions |
6418 // are called before sweeping finishes. | 6419 // are called before sweeping finishes. |
6419 heap->StartIncrementalMarking(); | 6420 heap->StartIncrementalMarking(); |
6420 heap->FinalizeIncrementalMarkingIfComplete("test"); | 6421 heap->FinalizeIncrementalMarkingIfComplete("test"); |
6421 } | 6422 } |
6422 | 6423 |
6423 | 6424 |
6424 } // namespace internal | 6425 } // namespace internal |
6425 } // namespace v8 | 6426 } // namespace v8 |
OLD | NEW |