OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/heap.h" | 5 #include "src/heap/heap.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/ast/scopeinfo.h" | 9 #include "src/ast/scopeinfo.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
87 // ConfigureHeap. | 87 // ConfigureHeap. |
88 // Will be 4 * reserved_semispace_size_ to ensure that young | 88 // Will be 4 * reserved_semispace_size_ to ensure that young |
89 // generation can be aligned to its size. | 89 // generation can be aligned to its size. |
90 maximum_committed_(0), | 90 maximum_committed_(0), |
91 survived_since_last_expansion_(0), | 91 survived_since_last_expansion_(0), |
92 survived_last_scavenge_(0), | 92 survived_last_scavenge_(0), |
93 always_allocate_scope_count_(0), | 93 always_allocate_scope_count_(0), |
94 contexts_disposed_(0), | 94 contexts_disposed_(0), |
95 number_of_disposed_maps_(0), | 95 number_of_disposed_maps_(0), |
96 global_ic_age_(0), | 96 global_ic_age_(0), |
97 scan_on_scavenge_pages_(0), | |
98 new_space_(this), | 97 new_space_(this), |
99 old_space_(NULL), | 98 old_space_(NULL), |
100 code_space_(NULL), | 99 code_space_(NULL), |
101 map_space_(NULL), | 100 map_space_(NULL), |
102 lo_space_(NULL), | 101 lo_space_(NULL), |
103 gc_state_(NOT_IN_GC), | 102 gc_state_(NOT_IN_GC), |
104 gc_post_processing_depth_(0), | 103 gc_post_processing_depth_(0), |
105 allocations_count_(0), | 104 allocations_count_(0), |
106 raw_allocations_hash_(0), | 105 raw_allocations_hash_(0), |
107 ms_count_(0), | 106 ms_count_(0), |
108 gc_count_(0), | 107 gc_count_(0), |
109 remembered_unmapped_pages_index_(0), | 108 remembered_unmapped_pages_index_(0), |
110 #ifdef DEBUG | 109 #ifdef DEBUG |
111 allocation_timeout_(0), | 110 allocation_timeout_(0), |
112 #endif // DEBUG | 111 #endif // DEBUG |
113 old_generation_allocation_limit_(initial_old_generation_size_), | 112 old_generation_allocation_limit_(initial_old_generation_size_), |
114 old_gen_exhausted_(false), | 113 old_gen_exhausted_(false), |
115 optimize_for_memory_usage_(false), | 114 optimize_for_memory_usage_(false), |
116 inline_allocation_disabled_(false), | 115 inline_allocation_disabled_(false), |
117 store_buffer_rebuilder_(store_buffer()), | |
118 total_regexp_code_generated_(0), | 116 total_regexp_code_generated_(0), |
119 tracer_(nullptr), | 117 tracer_(nullptr), |
120 high_survival_rate_period_length_(0), | 118 high_survival_rate_period_length_(0), |
121 promoted_objects_size_(0), | 119 promoted_objects_size_(0), |
122 promotion_ratio_(0), | 120 promotion_ratio_(0), |
123 semi_space_copied_object_size_(0), | 121 semi_space_copied_object_size_(0), |
124 previous_semi_space_copied_object_size_(0), | 122 previous_semi_space_copied_object_size_(0), |
125 semi_space_copied_rate_(0), | 123 semi_space_copied_rate_(0), |
126 nodes_died_in_new_space_(0), | 124 nodes_died_in_new_space_(0), |
127 nodes_copied_in_new_space_(0), | 125 nodes_copied_in_new_space_(0), |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 UpdateMaximumCommitted(); | 445 UpdateMaximumCommitted(); |
448 | 446 |
449 #ifdef DEBUG | 447 #ifdef DEBUG |
450 DCHECK(!AllowHeapAllocation::IsAllowed() && gc_state_ == NOT_IN_GC); | 448 DCHECK(!AllowHeapAllocation::IsAllowed() && gc_state_ == NOT_IN_GC); |
451 | 449 |
452 if (FLAG_gc_verbose) Print(); | 450 if (FLAG_gc_verbose) Print(); |
453 | 451 |
454 ReportStatisticsBeforeGC(); | 452 ReportStatisticsBeforeGC(); |
455 #endif // DEBUG | 453 #endif // DEBUG |
456 | 454 |
457 store_buffer()->GCPrologue(); | |
458 | |
459 if (isolate()->concurrent_osr_enabled()) { | 455 if (isolate()->concurrent_osr_enabled()) { |
460 isolate()->optimizing_compile_dispatcher()->AgeBufferedOsrJobs(); | 456 isolate()->optimizing_compile_dispatcher()->AgeBufferedOsrJobs(); |
461 } | 457 } |
462 | 458 |
463 if (new_space_.IsAtMaximumCapacity()) { | 459 if (new_space_.IsAtMaximumCapacity()) { |
464 maximum_size_scavenges_++; | 460 maximum_size_scavenges_++; |
465 } else { | 461 } else { |
466 maximum_size_scavenges_ = 0; | 462 maximum_size_scavenges_ = 0; |
467 } | 463 } |
468 CheckNewSpaceExpansionCriteria(); | 464 CheckNewSpaceExpansionCriteria(); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
632 isolate_, DependentCode::kAllocationSiteTenuringChangedGroup); | 628 isolate_, DependentCode::kAllocationSiteTenuringChangedGroup); |
633 site->set_deopt_dependent_code(false); | 629 site->set_deopt_dependent_code(false); |
634 } | 630 } |
635 list_element = site->weak_next(); | 631 list_element = site->weak_next(); |
636 } | 632 } |
637 Deoptimizer::DeoptimizeMarkedCode(isolate_); | 633 Deoptimizer::DeoptimizeMarkedCode(isolate_); |
638 } | 634 } |
639 | 635 |
640 | 636 |
641 void Heap::GarbageCollectionEpilogue() { | 637 void Heap::GarbageCollectionEpilogue() { |
642 store_buffer()->GCEpilogue(); | |
643 | |
644 // In release mode, we only zap the from space under heap verification. | 638 // In release mode, we only zap the from space under heap verification. |
645 if (Heap::ShouldZapGarbage()) { | 639 if (Heap::ShouldZapGarbage()) { |
646 ZapFromSpace(); | 640 ZapFromSpace(); |
647 } | 641 } |
648 | 642 |
649 #ifdef VERIFY_HEAP | 643 #ifdef VERIFY_HEAP |
650 if (FLAG_verify_heap) { | 644 if (FLAG_verify_heap) { |
651 Verify(); | 645 Verify(); |
652 } | 646 } |
653 #endif | 647 #endif |
(...skipping 891 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1545 JSFunction* constructor = JSFunction::cast(obj_constructor); | 1539 JSFunction* constructor = JSFunction::cast(obj_constructor); |
1546 if (!constructor->shared()->IsApiFunction()) return false; | 1540 if (!constructor->shared()->IsApiFunction()) return false; |
1547 if (constructor != nullptr && | 1541 if (constructor != nullptr && |
1548 constructor->initial_map() == heap_object->map()) { | 1542 constructor->initial_map() == heap_object->map()) { |
1549 return true; | 1543 return true; |
1550 } | 1544 } |
1551 return false; | 1545 return false; |
1552 } | 1546 } |
1553 | 1547 |
1554 | 1548 |
1555 void Heap::ScavengeStoreBufferCallback(Heap* heap, MemoryChunk* page, | |
1556 StoreBufferEvent event) { | |
1557 heap->store_buffer_rebuilder_.Callback(page, event); | |
1558 } | |
1559 | |
1560 | |
1561 void PromotionQueue::Initialize() { | 1549 void PromotionQueue::Initialize() { |
1562 // The last to-space page may be used for promotion queue. On promotion | 1550 // The last to-space page may be used for promotion queue. On promotion |
1563 // conflict, we use the emergency stack. | 1551 // conflict, we use the emergency stack. |
1564 DCHECK((Page::kPageSize - MemoryChunk::kBodyOffset) % (2 * kPointerSize) == | 1552 DCHECK((Page::kPageSize - MemoryChunk::kBodyOffset) % (2 * kPointerSize) == |
1565 0); | 1553 0); |
1566 front_ = rear_ = | 1554 front_ = rear_ = |
1567 reinterpret_cast<intptr_t*>(heap_->new_space()->ToSpaceEnd()); | 1555 reinterpret_cast<intptr_t*>(heap_->new_space()->ToSpaceEnd()); |
1568 limit_ = reinterpret_cast<intptr_t*>( | 1556 limit_ = reinterpret_cast<intptr_t*>( |
1569 Page::FromAllocationTop(reinterpret_cast<Address>(rear_))->area_start()); | 1557 Page::FromAllocationTop(reinterpret_cast<Address>(rear_))->area_start()); |
1570 emergency_stack_ = NULL; | 1558 emergency_stack_ = NULL; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1683 { | 1671 { |
1684 // Copy roots. | 1672 // Copy roots. |
1685 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_ROOTS); | 1673 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_ROOTS); |
1686 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); | 1674 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); |
1687 } | 1675 } |
1688 | 1676 |
1689 { | 1677 { |
1690 // Copy objects reachable from the old generation. | 1678 // Copy objects reachable from the old generation. |
1691 GCTracer::Scope gc_scope(tracer(), | 1679 GCTracer::Scope gc_scope(tracer(), |
1692 GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS); | 1680 GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS); |
1693 StoreBufferRebuildScope scope(this, store_buffer(), | |
1694 &ScavengeStoreBufferCallback); | |
1695 store_buffer()->IteratePointersToNewSpace(&Scavenger::ScavengeObject); | 1681 store_buffer()->IteratePointersToNewSpace(&Scavenger::ScavengeObject); |
1696 } | 1682 } |
1697 | 1683 |
1698 { | 1684 { |
1699 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_WEAK); | 1685 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_WEAK); |
1700 // Copy objects reachable from the encountered weak collections list. | 1686 // Copy objects reachable from the encountered weak collections list. |
1701 scavenge_visitor.VisitPointer(&encountered_weak_collections_); | 1687 scavenge_visitor.VisitPointer(&encountered_weak_collections_); |
1702 // Copy objects reachable from the encountered weak cells. | 1688 // Copy objects reachable from the encountered weak cells. |
1703 scavenge_visitor.VisitPointer(&encountered_weak_cells_); | 1689 scavenge_visitor.VisitPointer(&encountered_weak_cells_); |
1704 } | 1690 } |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1939 new_space_front += | 1925 new_space_front += |
1940 StaticScavengeVisitor::IterateBody(object->map(), object); | 1926 StaticScavengeVisitor::IterateBody(object->map(), object); |
1941 } else { | 1927 } else { |
1942 new_space_front = | 1928 new_space_front = |
1943 NewSpacePage::FromLimit(new_space_front)->next_page()->area_start(); | 1929 NewSpacePage::FromLimit(new_space_front)->next_page()->area_start(); |
1944 } | 1930 } |
1945 } | 1931 } |
1946 | 1932 |
1947 // Promote and process all the to-be-promoted objects. | 1933 // Promote and process all the to-be-promoted objects. |
1948 { | 1934 { |
1949 StoreBufferRebuildScope scope(this, store_buffer(), | |
1950 &ScavengeStoreBufferCallback); | |
1951 while (!promotion_queue()->is_empty()) { | 1935 while (!promotion_queue()->is_empty()) { |
1952 HeapObject* target; | 1936 HeapObject* target; |
1953 int size; | 1937 int size; |
1954 promotion_queue()->remove(&target, &size); | 1938 promotion_queue()->remove(&target, &size); |
1955 | 1939 |
1956 // Promoted object might be already partially visited | 1940 // Promoted object might be already partially visited |
1957 // during old space pointer iteration. Thus we search specifically | 1941 // during old space pointer iteration. Thus we search specifically |
1958 // for pointers to from semispace instead of looking for pointers | 1942 // for pointers to from semispace instead of looking for pointers |
1959 // to new space. | 1943 // to new space. |
1960 DCHECK(!target->IsMap()); | 1944 DCHECK(!target->IsMap()); |
(...skipping 2527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4488 // to the new space. In that case we may hit newly promoted objects and | 4472 // to the new space. In that case we may hit newly promoted objects and |
4489 // fix the pointers before the promotion queue gets to them. Thus the 'if'. | 4473 // fix the pointers before the promotion queue gets to them. Thus the 'if'. |
4490 if (target->IsHeapObject()) { | 4474 if (target->IsHeapObject()) { |
4491 if (Heap::InFromSpace(target)) { | 4475 if (Heap::InFromSpace(target)) { |
4492 callback(reinterpret_cast<HeapObject**>(slot), | 4476 callback(reinterpret_cast<HeapObject**>(slot), |
4493 HeapObject::cast(target)); | 4477 HeapObject::cast(target)); |
4494 Object* new_target = *slot; | 4478 Object* new_target = *slot; |
4495 if (InNewSpace(new_target)) { | 4479 if (InNewSpace(new_target)) { |
4496 SLOW_DCHECK(Heap::InToSpace(new_target)); | 4480 SLOW_DCHECK(Heap::InToSpace(new_target)); |
4497 SLOW_DCHECK(new_target->IsHeapObject()); | 4481 SLOW_DCHECK(new_target->IsHeapObject()); |
4498 store_buffer_.EnterDirectlyIntoStoreBuffer( | 4482 store_buffer_.Mark(reinterpret_cast<Address>(slot)); |
4499 reinterpret_cast<Address>(slot)); | |
4500 } | 4483 } |
4501 SLOW_DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_target)); | 4484 SLOW_DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_target)); |
4502 } else if (record_slots && | 4485 } else if (record_slots && |
4503 MarkCompactCollector::IsOnEvacuationCandidate(target)) { | 4486 MarkCompactCollector::IsOnEvacuationCandidate(target)) { |
4504 mark_compact_collector()->RecordSlot(object, slot, target); | 4487 mark_compact_collector()->RecordSlot(object, slot, target); |
4505 } | 4488 } |
4506 } | 4489 } |
4507 slot_address += kPointerSize; | 4490 slot_address += kPointerSize; |
4508 } | 4491 } |
4509 } | 4492 } |
(...skipping 1583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6093 // PreFree logically frees the memory chunk. However, the actual freeing | 6076 // PreFree logically frees the memory chunk. However, the actual freeing |
6094 // will happen on a separate thread sometime later. | 6077 // will happen on a separate thread sometime later. |
6095 isolate_->memory_allocator()->PreFreeMemory(chunk); | 6078 isolate_->memory_allocator()->PreFreeMemory(chunk); |
6096 | 6079 |
6097 // The chunks added to this queue will be freed by a concurrent thread. | 6080 // The chunks added to this queue will be freed by a concurrent thread. |
6098 chunk->set_next_chunk(chunks_queued_for_free_); | 6081 chunk->set_next_chunk(chunks_queued_for_free_); |
6099 chunks_queued_for_free_ = chunk; | 6082 chunks_queued_for_free_ = chunk; |
6100 } | 6083 } |
6101 | 6084 |
6102 | 6085 |
6103 void Heap::FilterStoreBufferEntriesOnAboutToBeFreedPages() { | 6086 void Heap::FilterStoreBufferEntriesOnAboutToBeFreedPages() { |
Hannes Payer (out of office)
2016/01/20 19:43:00
This method should not be needed anymore because:
ulan
2016/01/28 19:07:21
Done.
| |
6104 if (chunks_queued_for_free_ == NULL) return; | 6087 if (chunks_queued_for_free_ == NULL) return; |
6105 MemoryChunk* next; | 6088 MemoryChunk* next; |
6106 MemoryChunk* chunk; | 6089 MemoryChunk* chunk; |
6107 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { | 6090 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { |
6108 next = chunk->next_chunk(); | 6091 next = chunk->next_chunk(); |
6092 chunk->ReleaseOldToNewSlots(); | |
Hannes Payer (out of office)
2016/01/20 19:43:00
They should be released in MemoryChunk::ReleaseAll
ulan
2016/01/28 19:07:22
Done.
| |
6109 chunk->SetFlag(MemoryChunk::ABOUT_TO_BE_FREED); | 6093 chunk->SetFlag(MemoryChunk::ABOUT_TO_BE_FREED); |
Hannes Payer (out of office)
2016/01/20 19:43:00
ABOUT_TO_BE_FREED should not be needed anymore.
ulan
2016/01/28 19:07:21
Done.
| |
6110 } | 6094 } |
6111 store_buffer()->Compact(); | |
6112 store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); | |
6113 } | 6095 } |
6114 | 6096 |
6115 | 6097 |
6116 void Heap::FreeQueuedChunks() { | 6098 void Heap::FreeQueuedChunks() { |
6117 if (chunks_queued_for_free_ != NULL) { | 6099 if (chunks_queued_for_free_ != NULL) { |
6118 if (FLAG_concurrent_sweeping) { | 6100 if (FLAG_concurrent_sweeping) { |
6119 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 6101 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
6120 new UnmapFreeMemoryTask(this, chunks_queued_for_free_), | 6102 new UnmapFreeMemoryTask(this, chunks_queued_for_free_), |
6121 v8::Platform::kShortRunningTask); | 6103 v8::Platform::kShortRunningTask); |
6122 } else { | 6104 } else { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6243 } | 6225 } |
6244 | 6226 |
6245 | 6227 |
6246 // static | 6228 // static |
6247 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6229 int Heap::GetStaticVisitorIdForMap(Map* map) { |
6248 return StaticVisitorBase::GetVisitorId(map); | 6230 return StaticVisitorBase::GetVisitorId(map); |
6249 } | 6231 } |
6250 | 6232 |
6251 } // namespace internal | 6233 } // namespace internal |
6252 } // namespace v8 | 6234 } // namespace v8 |
OLD | NEW |