OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/heap/spaces.h" | 5 #include "src/heap/spaces.h" |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
9 #include "src/full-codegen/full-codegen.h" | 9 #include "src/full-codegen/full-codegen.h" |
| 10 #include "src/heap/slot-set.h" |
10 #include "src/heap/slots-buffer.h" | 11 #include "src/heap/slots-buffer.h" |
11 #include "src/macro-assembler.h" | 12 #include "src/macro-assembler.h" |
12 #include "src/msan.h" | 13 #include "src/msan.h" |
13 #include "src/snapshot/snapshot.h" | 14 #include "src/snapshot/snapshot.h" |
14 | 15 |
15 namespace v8 { | 16 namespace v8 { |
16 namespace internal { | 17 namespace internal { |
17 | 18 |
18 | 19 |
19 // ---------------------------------------------------------------------------- | 20 // ---------------------------------------------------------------------------- |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 | 422 |
422 | 423 |
423 NewSpacePage* NewSpacePage::Initialize(Heap* heap, Address start, | 424 NewSpacePage* NewSpacePage::Initialize(Heap* heap, Address start, |
424 SemiSpace* semi_space) { | 425 SemiSpace* semi_space) { |
425 Address area_start = start + NewSpacePage::kObjectStartOffset; | 426 Address area_start = start + NewSpacePage::kObjectStartOffset; |
426 Address area_end = start + Page::kPageSize; | 427 Address area_end = start + Page::kPageSize; |
427 | 428 |
428 MemoryChunk* chunk = | 429 MemoryChunk* chunk = |
429 MemoryChunk::Initialize(heap, start, Page::kPageSize, area_start, | 430 MemoryChunk::Initialize(heap, start, Page::kPageSize, area_start, |
430 area_end, NOT_EXECUTABLE, semi_space); | 431 area_end, NOT_EXECUTABLE, semi_space); |
431 chunk->initialize_scan_on_scavenge(true); | |
432 bool in_to_space = (semi_space->id() != kFromSpace); | 432 bool in_to_space = (semi_space->id() != kFromSpace); |
433 chunk->SetFlag(in_to_space ? MemoryChunk::IN_TO_SPACE | 433 chunk->SetFlag(in_to_space ? MemoryChunk::IN_TO_SPACE |
434 : MemoryChunk::IN_FROM_SPACE); | 434 : MemoryChunk::IN_FROM_SPACE); |
435 DCHECK(!chunk->IsFlagSet(in_to_space ? MemoryChunk::IN_FROM_SPACE | 435 DCHECK(!chunk->IsFlagSet(in_to_space ? MemoryChunk::IN_FROM_SPACE |
436 : MemoryChunk::IN_TO_SPACE)); | 436 : MemoryChunk::IN_TO_SPACE)); |
437 NewSpacePage* page = static_cast<NewSpacePage*>(chunk); | 437 NewSpacePage* page = static_cast<NewSpacePage*>(chunk); |
438 heap->incremental_marking()->SetNewSpacePageFlags(page); | 438 heap->incremental_marking()->SetNewSpacePageFlags(page); |
439 return page; | 439 return page; |
440 } | 440 } |
441 | 441 |
(...skipping 15 matching lines...) Expand all Loading... |
457 | 457 |
458 DCHECK(base == chunk->address()); | 458 DCHECK(base == chunk->address()); |
459 | 459 |
460 chunk->heap_ = heap; | 460 chunk->heap_ = heap; |
461 chunk->size_ = size; | 461 chunk->size_ = size; |
462 chunk->area_start_ = area_start; | 462 chunk->area_start_ = area_start; |
463 chunk->area_end_ = area_end; | 463 chunk->area_end_ = area_end; |
464 chunk->flags_ = 0; | 464 chunk->flags_ = 0; |
465 chunk->set_owner(owner); | 465 chunk->set_owner(owner); |
466 chunk->InitializeReservedMemory(); | 466 chunk->InitializeReservedMemory(); |
467 chunk->slots_buffer_ = NULL; | 467 chunk->slots_buffer_ = nullptr; |
468 chunk->skip_list_ = NULL; | 468 chunk->old_to_new_slots_ = nullptr; |
| 469 chunk->skip_list_ = nullptr; |
469 chunk->write_barrier_counter_ = kWriteBarrierCounterGranularity; | 470 chunk->write_barrier_counter_ = kWriteBarrierCounterGranularity; |
470 chunk->progress_bar_ = 0; | 471 chunk->progress_bar_ = 0; |
471 chunk->high_water_mark_.SetValue(static_cast<intptr_t>(area_start - base)); | 472 chunk->high_water_mark_.SetValue(static_cast<intptr_t>(area_start - base)); |
472 chunk->parallel_sweeping_state().SetValue(kSweepingDone); | 473 chunk->parallel_sweeping_state().SetValue(kSweepingDone); |
473 chunk->parallel_compaction_state().SetValue(kCompactingDone); | 474 chunk->parallel_compaction_state().SetValue(kCompactingDone); |
474 chunk->mutex_ = NULL; | 475 chunk->mutex_ = nullptr; |
475 chunk->available_in_small_free_list_ = 0; | 476 chunk->available_in_small_free_list_ = 0; |
476 chunk->available_in_medium_free_list_ = 0; | 477 chunk->available_in_medium_free_list_ = 0; |
477 chunk->available_in_large_free_list_ = 0; | 478 chunk->available_in_large_free_list_ = 0; |
478 chunk->available_in_huge_free_list_ = 0; | 479 chunk->available_in_huge_free_list_ = 0; |
479 chunk->non_available_small_blocks_ = 0; | 480 chunk->non_available_small_blocks_ = 0; |
480 chunk->ResetLiveBytes(); | 481 chunk->ResetLiveBytes(); |
481 Bitmap::Clear(chunk); | 482 Bitmap::Clear(chunk); |
482 chunk->initialize_scan_on_scavenge(false); | |
483 chunk->SetFlag(WAS_SWEPT); | 483 chunk->SetFlag(WAS_SWEPT); |
484 chunk->set_next_chunk(nullptr); | 484 chunk->set_next_chunk(nullptr); |
485 chunk->set_prev_chunk(nullptr); | 485 chunk->set_prev_chunk(nullptr); |
486 | 486 |
487 DCHECK(OFFSET_OF(MemoryChunk, flags_) == kFlagsOffset); | 487 DCHECK(OFFSET_OF(MemoryChunk, flags_) == kFlagsOffset); |
488 DCHECK(OFFSET_OF(MemoryChunk, live_byte_count_) == kLiveBytesOffset); | 488 DCHECK(OFFSET_OF(MemoryChunk, live_byte_count_) == kLiveBytesOffset); |
489 | 489 |
490 if (executable == EXECUTABLE) { | 490 if (executable == EXECUTABLE) { |
491 chunk->SetFlag(IS_EXECUTABLE); | 491 chunk->SetFlag(IS_EXECUTABLE); |
492 } | 492 } |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
927 static_cast<PagedSpace*>(chunk->owner())->Allocate(by); | 927 static_cast<PagedSpace*>(chunk->owner())->Allocate(by); |
928 } | 928 } |
929 chunk->IncrementLiveBytes(by); | 929 chunk->IncrementLiveBytes(by); |
930 } | 930 } |
931 | 931 |
932 | 932 |
933 void MemoryChunk::ReleaseAllocatedMemory() { | 933 void MemoryChunk::ReleaseAllocatedMemory() { |
934 delete slots_buffer_; | 934 delete slots_buffer_; |
935 delete skip_list_; | 935 delete skip_list_; |
936 delete mutex_; | 936 delete mutex_; |
| 937 ReleaseOldToNewSlots(); |
937 } | 938 } |
938 | 939 |
939 | 940 |
| 941 void MemoryChunk::AllocateOldToNewSlots() { |
| 942 size_t pages = (size_ + Page::kPageSize - 1) / Page::kPageSize; |
| 943 DCHECK(owner() == heap_->lo_space() || pages == 1); |
| 944 DCHECK_GT(pages, 0); |
| 945 DCHECK(nullptr == old_to_new_slots_); |
| 946 old_to_new_slots_ = new SlotSet[pages]; |
| 947 for (int i = 0; i < pages; i++) { |
| 948 old_to_new_slots_[i].SetPageStart(address() + i * Page::kPageSize); |
| 949 } |
| 950 } |
| 951 |
| 952 |
| 953 void MemoryChunk::ReleaseOldToNewSlots() { |
| 954 delete[] old_to_new_slots_; |
| 955 old_to_new_slots_ = nullptr; |
| 956 } |
| 957 |
| 958 |
940 // ----------------------------------------------------------------------------- | 959 // ----------------------------------------------------------------------------- |
941 // PagedSpace implementation | 960 // PagedSpace implementation |
942 | 961 |
943 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::NEW_SPACE) == | 962 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::NEW_SPACE) == |
944 ObjectSpace::kObjectSpaceNewSpace); | 963 ObjectSpace::kObjectSpaceNewSpace); |
945 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::OLD_SPACE) == | 964 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::OLD_SPACE) == |
946 ObjectSpace::kObjectSpaceOldSpace); | 965 ObjectSpace::kObjectSpaceOldSpace); |
947 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::CODE_SPACE) == | 966 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::CODE_SPACE) == |
948 ObjectSpace::kObjectSpaceCodeSpace); | 967 ObjectSpace::kObjectSpaceCodeSpace); |
949 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::MAP_SPACE) == | 968 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::MAP_SPACE) == |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1232 void PagedSpace::ReleasePage(Page* page) { | 1251 void PagedSpace::ReleasePage(Page* page) { |
1233 DCHECK(page->LiveBytes() == 0); | 1252 DCHECK(page->LiveBytes() == 0); |
1234 DCHECK(AreaSize() == page->area_size()); | 1253 DCHECK(AreaSize() == page->area_size()); |
1235 | 1254 |
1236 if (page->WasSwept()) { | 1255 if (page->WasSwept()) { |
1237 intptr_t size = free_list_.EvictFreeListItems(page); | 1256 intptr_t size = free_list_.EvictFreeListItems(page); |
1238 accounting_stats_.AllocateBytes(size); | 1257 accounting_stats_.AllocateBytes(size); |
1239 DCHECK_EQ(AreaSize(), static_cast<int>(size)); | 1258 DCHECK_EQ(AreaSize(), static_cast<int>(size)); |
1240 } | 1259 } |
1241 | 1260 |
1242 if (page->IsFlagSet(MemoryChunk::SCAN_ON_SCAVENGE)) { | |
1243 heap()->decrement_scan_on_scavenge_pages(); | |
1244 page->ClearFlag(MemoryChunk::SCAN_ON_SCAVENGE); | |
1245 } | |
1246 | |
1247 DCHECK(!free_list_.ContainsPageFreeListItems(page)); | 1261 DCHECK(!free_list_.ContainsPageFreeListItems(page)); |
1248 | 1262 |
1249 if (Page::FromAllocationTop(allocation_info_.top()) == page) { | 1263 if (Page::FromAllocationTop(allocation_info_.top()) == page) { |
1250 allocation_info_.Reset(nullptr, nullptr); | 1264 allocation_info_.Reset(nullptr, nullptr); |
1251 } | 1265 } |
1252 | 1266 |
1253 // If page is still in a list, unlink it from that list. | 1267 // If page is still in a list, unlink it from that list. |
1254 if (page->next_chunk() != NULL) { | 1268 if (page->next_chunk() != NULL) { |
1255 DCHECK(page->prev_chunk() != NULL); | 1269 DCHECK(page->prev_chunk() != NULL); |
1256 page->Unlink(); | 1270 page->Unlink(); |
(...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1943 page->SetFlags(flags, mask); | 1957 page->SetFlags(flags, mask); |
1944 if (becomes_to_space) { | 1958 if (becomes_to_space) { |
1945 page->ClearFlag(MemoryChunk::IN_FROM_SPACE); | 1959 page->ClearFlag(MemoryChunk::IN_FROM_SPACE); |
1946 page->SetFlag(MemoryChunk::IN_TO_SPACE); | 1960 page->SetFlag(MemoryChunk::IN_TO_SPACE); |
1947 page->ClearFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); | 1961 page->ClearFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); |
1948 page->ResetLiveBytes(); | 1962 page->ResetLiveBytes(); |
1949 } else { | 1963 } else { |
1950 page->SetFlag(MemoryChunk::IN_FROM_SPACE); | 1964 page->SetFlag(MemoryChunk::IN_FROM_SPACE); |
1951 page->ClearFlag(MemoryChunk::IN_TO_SPACE); | 1965 page->ClearFlag(MemoryChunk::IN_TO_SPACE); |
1952 } | 1966 } |
1953 DCHECK(page->IsFlagSet(MemoryChunk::SCAN_ON_SCAVENGE)); | |
1954 DCHECK(page->IsFlagSet(MemoryChunk::IN_TO_SPACE) || | 1967 DCHECK(page->IsFlagSet(MemoryChunk::IN_TO_SPACE) || |
1955 page->IsFlagSet(MemoryChunk::IN_FROM_SPACE)); | 1968 page->IsFlagSet(MemoryChunk::IN_FROM_SPACE)); |
1956 page = page->next_page(); | 1969 page = page->next_page(); |
1957 } | 1970 } |
1958 } | 1971 } |
1959 | 1972 |
1960 | 1973 |
1961 void SemiSpace::Reset() { | 1974 void SemiSpace::Reset() { |
1962 DCHECK(anchor_.next_page() != &anchor_); | 1975 DCHECK(anchor_.next_page() != &anchor_); |
1963 current_page_ = anchor_.next_page(); | 1976 current_page_ = anchor_.next_page(); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2023 // on from-space pages, so it might be out of sync with the marking state. | 2036 // on from-space pages, so it might be out of sync with the marking state. |
2024 if (page->heap()->incremental_marking()->IsMarking()) { | 2037 if (page->heap()->incremental_marking()->IsMarking()) { |
2025 CHECK(page->IsFlagSet(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING)); | 2038 CHECK(page->IsFlagSet(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING)); |
2026 } else { | 2039 } else { |
2027 CHECK( | 2040 CHECK( |
2028 !page->IsFlagSet(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING)); | 2041 !page->IsFlagSet(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING)); |
2029 } | 2042 } |
2030 // TODO(gc): Check that the live_bytes_count_ field matches the | 2043 // TODO(gc): Check that the live_bytes_count_ field matches the |
2031 // black marking on the page (if we make it match in new-space). | 2044 // black marking on the page (if we make it match in new-space). |
2032 } | 2045 } |
2033 CHECK(page->IsFlagSet(MemoryChunk::SCAN_ON_SCAVENGE)); | |
2034 CHECK(page->prev_page()->next_page() == page); | 2046 CHECK(page->prev_page()->next_page() == page); |
2035 page = page->next_page(); | 2047 page = page->next_page(); |
2036 } | 2048 } |
2037 } | 2049 } |
2038 #endif | 2050 #endif |
2039 | 2051 |
2040 #ifdef DEBUG | 2052 #ifdef DEBUG |
2041 void SemiSpace::AssertValidRange(Address start, Address end) { | 2053 void SemiSpace::AssertValidRange(Address start, Address end) { |
2042 // Addresses belong to same semi-space | 2054 // Addresses belong to same semi-space |
2043 NewSpacePage* page = NewSpacePage::FromLimit(start); | 2055 NewSpacePage* page = NewSpacePage::FromLimit(start); |
(...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3363 object->ShortPrint(); | 3375 object->ShortPrint(); |
3364 PrintF("\n"); | 3376 PrintF("\n"); |
3365 } | 3377 } |
3366 printf(" --------------------------------------\n"); | 3378 printf(" --------------------------------------\n"); |
3367 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3379 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3368 } | 3380 } |
3369 | 3381 |
3370 #endif // DEBUG | 3382 #endif // DEBUG |
3371 } // namespace internal | 3383 } // namespace internal |
3372 } // namespace v8 | 3384 } // namespace v8 |
OLD | NEW |