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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 // ConfigureHeap. | 86 // ConfigureHeap. |
87 // Will be 4 * reserved_semispace_size_ to ensure that young | 87 // Will be 4 * reserved_semispace_size_ to ensure that young |
88 // generation can be aligned to its size. | 88 // generation can be aligned to its size. |
89 maximum_committed_(0), | 89 maximum_committed_(0), |
90 survived_since_last_expansion_(0), | 90 survived_since_last_expansion_(0), |
91 survived_last_scavenge_(0), | 91 survived_last_scavenge_(0), |
92 always_allocate_scope_count_(0), | 92 always_allocate_scope_count_(0), |
93 contexts_disposed_(0), | 93 contexts_disposed_(0), |
94 number_of_disposed_maps_(0), | 94 number_of_disposed_maps_(0), |
95 global_ic_age_(0), | 95 global_ic_age_(0), |
96 scan_on_scavenge_pages_(0), | |
97 new_space_(this), | 96 new_space_(this), |
98 old_space_(NULL), | 97 old_space_(NULL), |
99 code_space_(NULL), | 98 code_space_(NULL), |
100 map_space_(NULL), | 99 map_space_(NULL), |
101 lo_space_(NULL), | 100 lo_space_(NULL), |
102 gc_state_(NOT_IN_GC), | 101 gc_state_(NOT_IN_GC), |
103 gc_post_processing_depth_(0), | 102 gc_post_processing_depth_(0), |
104 allocations_count_(0), | 103 allocations_count_(0), |
105 raw_allocations_hash_(0), | 104 raw_allocations_hash_(0), |
106 ms_count_(0), | 105 ms_count_(0), |
107 gc_count_(0), | 106 gc_count_(0), |
108 remembered_unmapped_pages_index_(0), | 107 remembered_unmapped_pages_index_(0), |
109 #ifdef DEBUG | 108 #ifdef DEBUG |
110 allocation_timeout_(0), | 109 allocation_timeout_(0), |
111 #endif // DEBUG | 110 #endif // DEBUG |
112 old_generation_allocation_limit_(initial_old_generation_size_), | 111 old_generation_allocation_limit_(initial_old_generation_size_), |
113 old_gen_exhausted_(false), | 112 old_gen_exhausted_(false), |
114 optimize_for_memory_usage_(false), | 113 optimize_for_memory_usage_(false), |
115 inline_allocation_disabled_(false), | 114 inline_allocation_disabled_(false), |
116 store_buffer_rebuilder_(store_buffer()), | |
117 total_regexp_code_generated_(0), | 115 total_regexp_code_generated_(0), |
118 tracer_(nullptr), | 116 tracer_(nullptr), |
119 high_survival_rate_period_length_(0), | 117 high_survival_rate_period_length_(0), |
120 promoted_objects_size_(0), | 118 promoted_objects_size_(0), |
121 promotion_ratio_(0), | 119 promotion_ratio_(0), |
122 semi_space_copied_object_size_(0), | 120 semi_space_copied_object_size_(0), |
123 previous_semi_space_copied_object_size_(0), | 121 previous_semi_space_copied_object_size_(0), |
124 semi_space_copied_rate_(0), | 122 semi_space_copied_rate_(0), |
125 nodes_died_in_new_space_(0), | 123 nodes_died_in_new_space_(0), |
126 nodes_copied_in_new_space_(0), | 124 nodes_copied_in_new_space_(0), |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 UpdateMaximumCommitted(); | 444 UpdateMaximumCommitted(); |
447 | 445 |
448 #ifdef DEBUG | 446 #ifdef DEBUG |
449 DCHECK(!AllowHeapAllocation::IsAllowed() && gc_state_ == NOT_IN_GC); | 447 DCHECK(!AllowHeapAllocation::IsAllowed() && gc_state_ == NOT_IN_GC); |
450 | 448 |
451 if (FLAG_gc_verbose) Print(); | 449 if (FLAG_gc_verbose) Print(); |
452 | 450 |
453 ReportStatisticsBeforeGC(); | 451 ReportStatisticsBeforeGC(); |
454 #endif // DEBUG | 452 #endif // DEBUG |
455 | 453 |
456 store_buffer()->GCPrologue(); | |
457 | |
458 if (isolate()->concurrent_osr_enabled()) { | 454 if (isolate()->concurrent_osr_enabled()) { |
459 isolate()->optimizing_compile_dispatcher()->AgeBufferedOsrJobs(); | 455 isolate()->optimizing_compile_dispatcher()->AgeBufferedOsrJobs(); |
460 } | 456 } |
461 | 457 |
462 if (new_space_.IsAtMaximumCapacity()) { | 458 if (new_space_.IsAtMaximumCapacity()) { |
463 maximum_size_scavenges_++; | 459 maximum_size_scavenges_++; |
464 } else { | 460 } else { |
465 maximum_size_scavenges_ = 0; | 461 maximum_size_scavenges_ = 0; |
466 } | 462 } |
467 CheckNewSpaceExpansionCriteria(); | 463 CheckNewSpaceExpansionCriteria(); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
635 isolate_, DependentCode::kAllocationSiteTenuringChangedGroup); | 631 isolate_, DependentCode::kAllocationSiteTenuringChangedGroup); |
636 site->set_deopt_dependent_code(false); | 632 site->set_deopt_dependent_code(false); |
637 } | 633 } |
638 list_element = site->weak_next(); | 634 list_element = site->weak_next(); |
639 } | 635 } |
640 Deoptimizer::DeoptimizeMarkedCode(isolate_); | 636 Deoptimizer::DeoptimizeMarkedCode(isolate_); |
641 } | 637 } |
642 | 638 |
643 | 639 |
644 void Heap::GarbageCollectionEpilogue() { | 640 void Heap::GarbageCollectionEpilogue() { |
645 store_buffer()->GCEpilogue(); | |
646 | |
647 // In release mode, we only zap the from space under heap verification. | 641 // In release mode, we only zap the from space under heap verification. |
648 if (Heap::ShouldZapGarbage()) { | 642 if (Heap::ShouldZapGarbage()) { |
649 ZapFromSpace(); | 643 ZapFromSpace(); |
650 } | 644 } |
651 | 645 |
652 #ifdef VERIFY_HEAP | 646 #ifdef VERIFY_HEAP |
653 if (FLAG_verify_heap) { | 647 if (FLAG_verify_heap) { |
654 Verify(); | 648 Verify(); |
655 } | 649 } |
656 #endif | 650 #endif |
(...skipping 890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1547 JSFunction* constructor = JSFunction::cast(obj_constructor); | 1541 JSFunction* constructor = JSFunction::cast(obj_constructor); |
1548 if (!constructor->shared()->IsApiFunction()) return false; | 1542 if (!constructor->shared()->IsApiFunction()) return false; |
1549 if (constructor != nullptr && | 1543 if (constructor != nullptr && |
1550 constructor->initial_map() == heap_object->map()) { | 1544 constructor->initial_map() == heap_object->map()) { |
1551 return true; | 1545 return true; |
1552 } | 1546 } |
1553 return false; | 1547 return false; |
1554 } | 1548 } |
1555 | 1549 |
1556 | 1550 |
1557 void Heap::ScavengeStoreBufferCallback(Heap* heap, MemoryChunk* page, | |
1558 StoreBufferEvent event) { | |
1559 heap->store_buffer_rebuilder_.Callback(page, event); | |
1560 } | |
1561 | |
1562 | |
1563 void PromotionQueue::Initialize() { | 1551 void PromotionQueue::Initialize() { |
1564 // The last to-space page may be used for promotion queue. On promotion | 1552 // The last to-space page may be used for promotion queue. On promotion |
1565 // conflict, we use the emergency stack. | 1553 // conflict, we use the emergency stack. |
1566 DCHECK((Page::kPageSize - MemoryChunk::kBodyOffset) % (2 * kPointerSize) == | 1554 DCHECK((Page::kPageSize - MemoryChunk::kBodyOffset) % (2 * kPointerSize) == |
1567 0); | 1555 0); |
1568 front_ = rear_ = | 1556 front_ = rear_ = |
1569 reinterpret_cast<intptr_t*>(heap_->new_space()->ToSpaceEnd()); | 1557 reinterpret_cast<intptr_t*>(heap_->new_space()->ToSpaceEnd()); |
1570 limit_ = reinterpret_cast<intptr_t*>( | 1558 limit_ = reinterpret_cast<intptr_t*>( |
1571 Page::FromAllocationTop(reinterpret_cast<Address>(rear_))->area_start()); | 1559 Page::FromAllocationTop(reinterpret_cast<Address>(rear_))->area_start()); |
1572 emergency_stack_ = NULL; | 1560 emergency_stack_ = NULL; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1685 { | 1673 { |
1686 // Copy roots. | 1674 // Copy roots. |
1687 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_ROOTS); | 1675 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_ROOTS); |
1688 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); | 1676 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); |
1689 } | 1677 } |
1690 | 1678 |
1691 { | 1679 { |
1692 // Copy objects reachable from the old generation. | 1680 // Copy objects reachable from the old generation. |
1693 GCTracer::Scope gc_scope(tracer(), | 1681 GCTracer::Scope gc_scope(tracer(), |
1694 GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS); | 1682 GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS); |
1695 StoreBufferRebuildScope scope(this, store_buffer(), | |
1696 &ScavengeStoreBufferCallback); | |
1697 store_buffer()->IteratePointersToNewSpace(&Scavenger::ScavengeObject); | 1683 store_buffer()->IteratePointersToNewSpace(&Scavenger::ScavengeObject); |
1698 } | 1684 } |
1699 | 1685 |
1700 { | 1686 { |
1701 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_WEAK); | 1687 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_WEAK); |
1702 // Copy objects reachable from the encountered weak collections list. | 1688 // Copy objects reachable from the encountered weak collections list. |
1703 scavenge_visitor.VisitPointer(&encountered_weak_collections_); | 1689 scavenge_visitor.VisitPointer(&encountered_weak_collections_); |
1704 // Copy objects reachable from the encountered weak cells. | 1690 // Copy objects reachable from the encountered weak cells. |
1705 scavenge_visitor.VisitPointer(&encountered_weak_cells_); | 1691 scavenge_visitor.VisitPointer(&encountered_weak_cells_); |
1706 } | 1692 } |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1941 new_space_front += | 1927 new_space_front += |
1942 StaticScavengeVisitor::IterateBody(object->map(), object); | 1928 StaticScavengeVisitor::IterateBody(object->map(), object); |
1943 } else { | 1929 } else { |
1944 new_space_front = | 1930 new_space_front = |
1945 NewSpacePage::FromLimit(new_space_front)->next_page()->area_start(); | 1931 NewSpacePage::FromLimit(new_space_front)->next_page()->area_start(); |
1946 } | 1932 } |
1947 } | 1933 } |
1948 | 1934 |
1949 // Promote and process all the to-be-promoted objects. | 1935 // Promote and process all the to-be-promoted objects. |
1950 { | 1936 { |
1951 StoreBufferRebuildScope scope(this, store_buffer(), | |
1952 &ScavengeStoreBufferCallback); | |
1953 while (!promotion_queue()->is_empty()) { | 1937 while (!promotion_queue()->is_empty()) { |
1954 HeapObject* target; | 1938 HeapObject* target; |
1955 int size; | 1939 int size; |
1956 promotion_queue()->remove(&target, &size); | 1940 promotion_queue()->remove(&target, &size); |
1957 | 1941 |
1958 // Promoted object might be already partially visited | 1942 // Promoted object might be already partially visited |
1959 // during old space pointer iteration. Thus we search specifically | 1943 // during old space pointer iteration. Thus we search specifically |
1960 // for pointers to from semispace instead of looking for pointers | 1944 // for pointers to from semispace instead of looking for pointers |
1961 // to new space. | 1945 // to new space. |
1962 DCHECK(!target->IsMap()); | 1946 DCHECK(!target->IsMap()); |
(...skipping 2517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4480 // to the new space. In that case we may hit newly promoted objects and | 4464 // to the new space. In that case we may hit newly promoted objects and |
4481 // fix the pointers before the promotion queue gets to them. Thus the 'if'. | 4465 // fix the pointers before the promotion queue gets to them. Thus the 'if'. |
4482 if (target->IsHeapObject()) { | 4466 if (target->IsHeapObject()) { |
4483 if (Heap::InFromSpace(target)) { | 4467 if (Heap::InFromSpace(target)) { |
4484 callback(reinterpret_cast<HeapObject**>(slot), | 4468 callback(reinterpret_cast<HeapObject**>(slot), |
4485 HeapObject::cast(target)); | 4469 HeapObject::cast(target)); |
4486 Object* new_target = *slot; | 4470 Object* new_target = *slot; |
4487 if (InNewSpace(new_target)) { | 4471 if (InNewSpace(new_target)) { |
4488 SLOW_DCHECK(Heap::InToSpace(new_target)); | 4472 SLOW_DCHECK(Heap::InToSpace(new_target)); |
4489 SLOW_DCHECK(new_target->IsHeapObject()); | 4473 SLOW_DCHECK(new_target->IsHeapObject()); |
4490 store_buffer_.EnterDirectlyIntoStoreBuffer( | 4474 store_buffer_.Mark(reinterpret_cast<Address>(slot)); |
4491 reinterpret_cast<Address>(slot)); | |
4492 } | 4475 } |
4493 SLOW_DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_target)); | 4476 SLOW_DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_target)); |
4494 } else if (record_slots && | 4477 } else if (record_slots && |
4495 MarkCompactCollector::IsOnEvacuationCandidate(target)) { | 4478 MarkCompactCollector::IsOnEvacuationCandidate(target)) { |
4496 mark_compact_collector()->RecordSlot(object, slot, target); | 4479 mark_compact_collector()->RecordSlot(object, slot, target); |
4497 } | 4480 } |
4498 } | 4481 } |
4499 slot_address += kPointerSize; | 4482 slot_address += kPointerSize; |
4500 } | 4483 } |
4501 } | 4484 } |
(...skipping 1560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6062 // PreFree logically frees the memory chunk. However, the actual freeing | 6045 // PreFree logically frees the memory chunk. However, the actual freeing |
6063 // will happen on a separate thread sometime later. | 6046 // will happen on a separate thread sometime later. |
6064 isolate_->memory_allocator()->PreFreeMemory(chunk); | 6047 isolate_->memory_allocator()->PreFreeMemory(chunk); |
6065 | 6048 |
6066 // The chunks added to this queue will be freed by a concurrent thread. | 6049 // The chunks added to this queue will be freed by a concurrent thread. |
6067 chunk->set_next_chunk(chunks_queued_for_free_); | 6050 chunk->set_next_chunk(chunks_queued_for_free_); |
6068 chunks_queued_for_free_ = chunk; | 6051 chunks_queued_for_free_ = chunk; |
6069 } | 6052 } |
6070 | 6053 |
6071 | 6054 |
6072 void Heap::FilterStoreBufferEntriesOnAboutToBeFreedPages() { | |
6073 if (chunks_queued_for_free_ == NULL) return; | |
6074 MemoryChunk* next; | |
6075 MemoryChunk* chunk; | |
6076 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { | |
6077 next = chunk->next_chunk(); | |
6078 chunk->SetFlag(MemoryChunk::ABOUT_TO_BE_FREED); | |
6079 } | |
6080 store_buffer()->Compact(); | |
6081 store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); | |
6082 } | |
6083 | |
6084 | |
6085 void Heap::FreeQueuedChunks() { | 6055 void Heap::FreeQueuedChunks() { |
6086 if (chunks_queued_for_free_ != NULL) { | 6056 if (chunks_queued_for_free_ != NULL) { |
6087 if (FLAG_concurrent_sweeping) { | 6057 if (FLAG_concurrent_sweeping) { |
6088 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 6058 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
6089 new UnmapFreeMemoryTask(this, chunks_queued_for_free_), | 6059 new UnmapFreeMemoryTask(this, chunks_queued_for_free_), |
6090 v8::Platform::kShortRunningTask); | 6060 v8::Platform::kShortRunningTask); |
6091 } else { | 6061 } else { |
6092 FreeQueuedChunks(chunks_queued_for_free_); | 6062 FreeQueuedChunks(chunks_queued_for_free_); |
6093 pending_unmapping_tasks_semaphore_.Signal(); | 6063 pending_unmapping_tasks_semaphore_.Signal(); |
6094 } | 6064 } |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6212 } | 6182 } |
6213 | 6183 |
6214 | 6184 |
6215 // static | 6185 // static |
6216 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6186 int Heap::GetStaticVisitorIdForMap(Map* map) { |
6217 return StaticVisitorBase::GetVisitorId(map); | 6187 return StaticVisitorBase::GetVisitorId(map); |
6218 } | 6188 } |
6219 | 6189 |
6220 } // namespace internal | 6190 } // namespace internal |
6221 } // namespace v8 | 6191 } // namespace v8 |
OLD | NEW |