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/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
11 #include "src/base/utils/random-number-generator.h" | 11 #include "src/base/utils/random-number-generator.h" |
12 #include "src/bootstrapper.h" | 12 #include "src/bootstrapper.h" |
13 #include "src/codegen.h" | 13 #include "src/codegen.h" |
14 #include "src/compilation-cache.h" | 14 #include "src/compilation-cache.h" |
15 #include "src/conversions.h" | 15 #include "src/conversions.h" |
16 #include "src/cpu-profiler.h" | 16 #include "src/cpu-profiler.h" |
17 #include "src/debug/debug.h" | 17 #include "src/debug/debug.h" |
18 #include "src/deoptimizer.h" | 18 #include "src/deoptimizer.h" |
19 #include "src/global-handles.h" | 19 #include "src/global-handles.h" |
20 #include "src/heap/array-buffer-tracker.h" | 20 #include "src/heap/array-buffer-tracker.h" |
21 #include "src/heap/gc-idle-time-handler.h" | 21 #include "src/heap/gc-idle-time-handler.h" |
22 #include "src/heap/gc-tracer.h" | 22 #include "src/heap/gc-tracer.h" |
23 #include "src/heap/incremental-marking.h" | 23 #include "src/heap/incremental-marking.h" |
24 #include "src/heap/mark-compact-inl.h" | 24 #include "src/heap/mark-compact-inl.h" |
25 #include "src/heap/mark-compact.h" | 25 #include "src/heap/mark-compact.h" |
26 #include "src/heap/memory-reducer.h" | 26 #include "src/heap/memory-reducer.h" |
27 #include "src/heap/object-stats.h" | 27 #include "src/heap/object-stats.h" |
28 #include "src/heap/objects-visiting-inl.h" | 28 #include "src/heap/objects-visiting-inl.h" |
29 #include "src/heap/objects-visiting.h" | 29 #include "src/heap/objects-visiting.h" |
| 30 #include "src/heap/scavenger-inl.h" |
30 #include "src/heap/store-buffer.h" | 31 #include "src/heap/store-buffer.h" |
31 #include "src/heap-profiler.h" | 32 #include "src/heap-profiler.h" |
32 #include "src/interpreter/interpreter.h" | 33 #include "src/interpreter/interpreter.h" |
33 #include "src/runtime-profiler.h" | 34 #include "src/runtime-profiler.h" |
34 #include "src/scopeinfo.h" | 35 #include "src/scopeinfo.h" |
35 #include "src/snapshot/natives.h" | 36 #include "src/snapshot/natives.h" |
36 #include "src/snapshot/serialize.h" | 37 #include "src/snapshot/serialize.h" |
37 #include "src/snapshot/snapshot.h" | 38 #include "src/snapshot/snapshot.h" |
38 #include "src/type-feedback-vector.h" | 39 #include "src/type-feedback-vector.h" |
39 #include "src/utils.h" | 40 #include "src/utils.h" |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 nodes_promoted_(0), | 114 nodes_promoted_(0), |
114 maximum_size_scavenges_(0), | 115 maximum_size_scavenges_(0), |
115 max_gc_pause_(0.0), | 116 max_gc_pause_(0.0), |
116 total_gc_time_ms_(0.0), | 117 total_gc_time_ms_(0.0), |
117 max_alive_after_gc_(0), | 118 max_alive_after_gc_(0), |
118 min_in_mutator_(kMaxInt), | 119 min_in_mutator_(kMaxInt), |
119 marking_time_(0.0), | 120 marking_time_(0.0), |
120 sweeping_time_(0.0), | 121 sweeping_time_(0.0), |
121 last_idle_notification_time_(0.0), | 122 last_idle_notification_time_(0.0), |
122 last_gc_time_(0.0), | 123 last_gc_time_(0.0), |
| 124 scavenge_collector_(nullptr), |
123 mark_compact_collector_(this), | 125 mark_compact_collector_(this), |
124 store_buffer_(this), | 126 store_buffer_(this), |
125 incremental_marking_(this), | 127 incremental_marking_(this), |
126 memory_reducer_(nullptr), | 128 memory_reducer_(nullptr), |
127 object_stats_(nullptr), | 129 object_stats_(nullptr), |
128 full_codegen_bytes_generated_(0), | 130 full_codegen_bytes_generated_(0), |
129 crankshaft_codegen_bytes_generated_(0), | 131 crankshaft_codegen_bytes_generated_(0), |
130 new_space_allocation_counter_(0), | 132 new_space_allocation_counter_(0), |
131 old_generation_allocation_counter_(0), | 133 old_generation_allocation_counter_(0), |
132 old_generation_size_at_last_gc_(0), | 134 old_generation_size_at_last_gc_(0), |
(...skipping 1253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1386 | 1388 |
1387 FlushNumberStringCache(); | 1389 FlushNumberStringCache(); |
1388 if (FLAG_cleanup_code_caches_at_gc) { | 1390 if (FLAG_cleanup_code_caches_at_gc) { |
1389 polymorphic_code_cache()->set_cache(undefined_value()); | 1391 polymorphic_code_cache()->set_cache(undefined_value()); |
1390 } | 1392 } |
1391 | 1393 |
1392 ClearNormalizedMapCaches(); | 1394 ClearNormalizedMapCaches(); |
1393 } | 1395 } |
1394 | 1396 |
1395 | 1397 |
1396 // Helper class for copying HeapObjects | |
1397 class ScavengeVisitor : public ObjectVisitor { | |
1398 public: | |
1399 explicit ScavengeVisitor(Heap* heap) : heap_(heap) {} | |
1400 | |
1401 void VisitPointer(Object** p) { ScavengePointer(p); } | |
1402 | |
1403 void VisitPointers(Object** start, Object** end) { | |
1404 // Copy all HeapObject pointers in [start, end) | |
1405 for (Object** p = start; p < end; p++) ScavengePointer(p); | |
1406 } | |
1407 | |
1408 private: | |
1409 void ScavengePointer(Object** p) { | |
1410 Object* object = *p; | |
1411 if (!heap_->InNewSpace(object)) return; | |
1412 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), | |
1413 reinterpret_cast<HeapObject*>(object)); | |
1414 } | |
1415 | |
1416 Heap* heap_; | |
1417 }; | |
1418 | |
1419 | |
1420 #ifdef VERIFY_HEAP | 1398 #ifdef VERIFY_HEAP |
1421 // Visitor class to verify pointers in code or data space do not point into | 1399 // Visitor class to verify pointers in code or data space do not point into |
1422 // new space. | 1400 // new space. |
1423 class VerifyNonPointerSpacePointersVisitor : public ObjectVisitor { | 1401 class VerifyNonPointerSpacePointersVisitor : public ObjectVisitor { |
1424 public: | 1402 public: |
1425 explicit VerifyNonPointerSpacePointersVisitor(Heap* heap) : heap_(heap) {} | 1403 explicit VerifyNonPointerSpacePointersVisitor(Heap* heap) : heap_(heap) {} |
1426 void VisitPointers(Object** start, Object** end) { | 1404 void VisitPointers(Object** start, Object** end) { |
1427 for (Object** current = start; current < end; current++) { | 1405 for (Object** current = start; current < end; current++) { |
1428 if ((*current)->IsHeapObject()) { | 1406 if ((*current)->IsHeapObject()) { |
1429 CHECK(!heap_->InNewSpace(HeapObject::cast(*current))); | 1407 CHECK(!heap_->InNewSpace(HeapObject::cast(*current))); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1554 | 1532 |
1555 // Implements Cheney's copying algorithm | 1533 // Implements Cheney's copying algorithm |
1556 LOG(isolate_, ResourceEvent("scavenge", "begin")); | 1534 LOG(isolate_, ResourceEvent("scavenge", "begin")); |
1557 | 1535 |
1558 // Clear descriptor cache. | 1536 // Clear descriptor cache. |
1559 isolate_->descriptor_lookup_cache()->Clear(); | 1537 isolate_->descriptor_lookup_cache()->Clear(); |
1560 | 1538 |
1561 // Used for updating survived_since_last_expansion_ at function end. | 1539 // Used for updating survived_since_last_expansion_ at function end. |
1562 intptr_t survived_watermark = PromotedSpaceSizeOfObjects(); | 1540 intptr_t survived_watermark = PromotedSpaceSizeOfObjects(); |
1563 | 1541 |
1564 SelectScavengingVisitorsTable(); | 1542 scavenge_collector_->SelectScavengingVisitorsTable(); |
1565 | 1543 |
1566 array_buffer_tracker()->PrepareDiscoveryInNewSpace(); | 1544 array_buffer_tracker()->PrepareDiscoveryInNewSpace(); |
1567 | 1545 |
1568 // Flip the semispaces. After flipping, to space is empty, from space has | 1546 // Flip the semispaces. After flipping, to space is empty, from space has |
1569 // live objects. | 1547 // live objects. |
1570 new_space_.Flip(); | 1548 new_space_.Flip(); |
1571 new_space_.ResetAllocationInfo(); | 1549 new_space_.ResetAllocationInfo(); |
1572 | 1550 |
1573 // We need to sweep newly copied objects which can be either in the | 1551 // We need to sweep newly copied objects which can be either in the |
1574 // to space or promoted to the old generation. For to-space | 1552 // to space or promoted to the old generation. For to-space |
(...skipping 21 matching lines...) Expand all Loading... |
1596 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_ROOTS); | 1574 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_ROOTS); |
1597 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); | 1575 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); |
1598 } | 1576 } |
1599 | 1577 |
1600 { | 1578 { |
1601 // Copy objects reachable from the old generation. | 1579 // Copy objects reachable from the old generation. |
1602 GCTracer::Scope gc_scope(tracer(), | 1580 GCTracer::Scope gc_scope(tracer(), |
1603 GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS); | 1581 GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS); |
1604 StoreBufferRebuildScope scope(this, store_buffer(), | 1582 StoreBufferRebuildScope scope(this, store_buffer(), |
1605 &ScavengeStoreBufferCallback); | 1583 &ScavengeStoreBufferCallback); |
1606 store_buffer()->IteratePointersToNewSpace(&ScavengeObject); | 1584 store_buffer()->IteratePointersToNewSpace(&Scavenger::ScavengeObject); |
1607 } | 1585 } |
1608 | 1586 |
1609 { | 1587 { |
1610 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_WEAK); | 1588 GCTracer::Scope gc_scope(tracer(), GCTracer::Scope::SCAVENGER_WEAK); |
1611 // Copy objects reachable from the encountered weak collections list. | 1589 // Copy objects reachable from the encountered weak collections list. |
1612 scavenge_visitor.VisitPointer(&encountered_weak_collections_); | 1590 scavenge_visitor.VisitPointer(&encountered_weak_collections_); |
1613 // Copy objects reachable from the encountered weak cells. | 1591 // Copy objects reachable from the encountered weak cells. |
1614 scavenge_visitor.VisitPointer(&encountered_weak_cells_); | 1592 scavenge_visitor.VisitPointer(&encountered_weak_cells_); |
1615 } | 1593 } |
1616 | 1594 |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1825 } | 1803 } |
1826 | 1804 |
1827 private: | 1805 private: |
1828 v8::ExternalResourceVisitor* visitor_; | 1806 v8::ExternalResourceVisitor* visitor_; |
1829 } external_string_table_visitor(visitor); | 1807 } external_string_table_visitor(visitor); |
1830 | 1808 |
1831 external_string_table_.Iterate(&external_string_table_visitor); | 1809 external_string_table_.Iterate(&external_string_table_visitor); |
1832 } | 1810 } |
1833 | 1811 |
1834 | 1812 |
1835 class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> { | |
1836 public: | |
1837 static inline void VisitPointer(Heap* heap, Object** p) { | |
1838 Object* object = *p; | |
1839 if (!heap->InNewSpace(object)) return; | |
1840 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), | |
1841 reinterpret_cast<HeapObject*>(object)); | |
1842 } | |
1843 }; | |
1844 | |
1845 | |
1846 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, | 1813 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, |
1847 Address new_space_front) { | 1814 Address new_space_front) { |
1848 do { | 1815 do { |
1849 SemiSpace::AssertValidRange(new_space_front, new_space_.top()); | 1816 SemiSpace::AssertValidRange(new_space_front, new_space_.top()); |
1850 // The addresses new_space_front and new_space_.top() define a | 1817 // The addresses new_space_front and new_space_.top() define a |
1851 // queue of unprocessed copied objects. Process them until the | 1818 // queue of unprocessed copied objects. Process them until the |
1852 // queue is empty. | 1819 // queue is empty. |
1853 while (new_space_front != new_space_.top()) { | 1820 while (new_space_front != new_space_.top()) { |
1854 if (!NewSpacePage::IsAtEnd(new_space_front)) { | 1821 if (!NewSpacePage::IsAtEnd(new_space_front)) { |
1855 HeapObject* object = HeapObject::FromAddress(new_space_front); | 1822 HeapObject* object = HeapObject::FromAddress(new_space_front); |
1856 new_space_front += | 1823 new_space_front += |
1857 NewSpaceScavenger::IterateBody(object->map(), object); | 1824 StaticScavengeVisitor::IterateBody(object->map(), object); |
1858 } else { | 1825 } else { |
1859 new_space_front = | 1826 new_space_front = |
1860 NewSpacePage::FromLimit(new_space_front)->next_page()->area_start(); | 1827 NewSpacePage::FromLimit(new_space_front)->next_page()->area_start(); |
1861 } | 1828 } |
1862 } | 1829 } |
1863 | 1830 |
1864 // Promote and process all the to-be-promoted objects. | 1831 // Promote and process all the to-be-promoted objects. |
1865 { | 1832 { |
1866 StoreBufferRebuildScope scope(this, store_buffer(), | 1833 StoreBufferRebuildScope scope(this, store_buffer(), |
1867 &ScavengeStoreBufferCallback); | 1834 &ScavengeStoreBufferCallback); |
(...skipping 24 matching lines...) Expand all Loading... |
1892 LayoutDescriptorHelper helper(target->map()); | 1859 LayoutDescriptorHelper helper(target->map()); |
1893 bool has_only_tagged_fields = helper.all_fields_tagged(); | 1860 bool has_only_tagged_fields = helper.all_fields_tagged(); |
1894 | 1861 |
1895 if (!has_only_tagged_fields) { | 1862 if (!has_only_tagged_fields) { |
1896 for (int offset = 0; offset < size;) { | 1863 for (int offset = 0; offset < size;) { |
1897 int end_of_region_offset; | 1864 int end_of_region_offset; |
1898 if (helper.IsTagged(offset, size, &end_of_region_offset)) { | 1865 if (helper.IsTagged(offset, size, &end_of_region_offset)) { |
1899 IterateAndMarkPointersToFromSpace( | 1866 IterateAndMarkPointersToFromSpace( |
1900 target, obj_address + offset, | 1867 target, obj_address + offset, |
1901 obj_address + end_of_region_offset, record_slots, | 1868 obj_address + end_of_region_offset, record_slots, |
1902 &ScavengeObject); | 1869 &Scavenger::ScavengeObject); |
1903 } | 1870 } |
1904 offset = end_of_region_offset; | 1871 offset = end_of_region_offset; |
1905 } | 1872 } |
1906 } else { | 1873 } else { |
1907 #endif | 1874 #endif |
1908 IterateAndMarkPointersToFromSpace(target, obj_address, | 1875 IterateAndMarkPointersToFromSpace(target, obj_address, |
1909 obj_address + size, record_slots, | 1876 obj_address + size, record_slots, |
1910 &ScavengeObject); | 1877 &Scavenger::ScavengeObject); |
1911 #if V8_DOUBLE_FIELDS_UNBOXING | 1878 #if V8_DOUBLE_FIELDS_UNBOXING |
1912 } | 1879 } |
1913 #endif | 1880 #endif |
1914 } | 1881 } |
1915 } | 1882 } |
1916 | 1883 |
1917 // Take another spin if there are now unswept objects in new space | 1884 // Take another spin if there are now unswept objects in new space |
1918 // (there are currently no more unswept promoted objects). | 1885 // (there are currently no more unswept promoted objects). |
1919 } while (new_space_front != new_space_.top()); | 1886 } while (new_space_front != new_space_.top()); |
1920 | 1887 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1992 void Heap::RegisterNewArrayBuffer(JSArrayBuffer* buffer) { | 1959 void Heap::RegisterNewArrayBuffer(JSArrayBuffer* buffer) { |
1993 return array_buffer_tracker()->RegisterNew(buffer); | 1960 return array_buffer_tracker()->RegisterNew(buffer); |
1994 } | 1961 } |
1995 | 1962 |
1996 | 1963 |
1997 void Heap::UnregisterArrayBuffer(JSArrayBuffer* buffer) { | 1964 void Heap::UnregisterArrayBuffer(JSArrayBuffer* buffer) { |
1998 return array_buffer_tracker()->Unregister(buffer); | 1965 return array_buffer_tracker()->Unregister(buffer); |
1999 } | 1966 } |
2000 | 1967 |
2001 | 1968 |
2002 enum LoggingAndProfiling { | |
2003 LOGGING_AND_PROFILING_ENABLED, | |
2004 LOGGING_AND_PROFILING_DISABLED | |
2005 }; | |
2006 | |
2007 | |
2008 enum MarksHandling { TRANSFER_MARKS, IGNORE_MARKS }; | |
2009 | |
2010 | |
2011 template <MarksHandling marks_handling, | |
2012 LoggingAndProfiling logging_and_profiling_mode> | |
2013 class ScavengingVisitor : public StaticVisitorBase { | |
2014 public: | |
2015 static void Initialize() { | |
2016 table_.Register(kVisitSeqOneByteString, &EvacuateSeqOneByteString); | |
2017 table_.Register(kVisitSeqTwoByteString, &EvacuateSeqTwoByteString); | |
2018 table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate); | |
2019 table_.Register(kVisitByteArray, &EvacuateByteArray); | |
2020 table_.Register(kVisitFixedArray, &EvacuateFixedArray); | |
2021 table_.Register(kVisitFixedDoubleArray, &EvacuateFixedDoubleArray); | |
2022 table_.Register(kVisitFixedTypedArray, &EvacuateFixedTypedArray); | |
2023 table_.Register(kVisitFixedFloat64Array, &EvacuateFixedFloat64Array); | |
2024 table_.Register(kVisitJSArrayBuffer, &EvacuateJSArrayBuffer); | |
2025 | |
2026 table_.Register( | |
2027 kVisitNativeContext, | |
2028 &ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized< | |
2029 Context::kSize>); | |
2030 | |
2031 table_.Register( | |
2032 kVisitConsString, | |
2033 &ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized< | |
2034 ConsString::kSize>); | |
2035 | |
2036 table_.Register( | |
2037 kVisitSlicedString, | |
2038 &ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized< | |
2039 SlicedString::kSize>); | |
2040 | |
2041 table_.Register( | |
2042 kVisitSymbol, | |
2043 &ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized< | |
2044 Symbol::kSize>); | |
2045 | |
2046 table_.Register( | |
2047 kVisitSharedFunctionInfo, | |
2048 &ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized< | |
2049 SharedFunctionInfo::kSize>); | |
2050 | |
2051 table_.Register(kVisitJSWeakCollection, | |
2052 &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit); | |
2053 | |
2054 table_.Register(kVisitJSTypedArray, | |
2055 &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit); | |
2056 | |
2057 table_.Register(kVisitJSDataView, | |
2058 &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit); | |
2059 | |
2060 table_.Register(kVisitJSRegExp, | |
2061 &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit); | |
2062 | |
2063 if (marks_handling == IGNORE_MARKS) { | |
2064 table_.Register( | |
2065 kVisitJSFunction, | |
2066 &ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized< | |
2067 JSFunction::kSize>); | |
2068 } else { | |
2069 table_.Register(kVisitJSFunction, &EvacuateJSFunction); | |
2070 } | |
2071 | |
2072 table_.RegisterSpecializations<ObjectEvacuationStrategy<DATA_OBJECT>, | |
2073 kVisitDataObject, kVisitDataObjectGeneric>(); | |
2074 | |
2075 table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>, | |
2076 kVisitJSObject, kVisitJSObjectGeneric>(); | |
2077 | |
2078 table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>, | |
2079 kVisitStruct, kVisitStructGeneric>(); | |
2080 } | |
2081 | |
2082 static VisitorDispatchTable<ScavengingCallback>* GetTable() { | |
2083 return &table_; | |
2084 } | |
2085 | |
2086 private: | |
2087 enum ObjectContents { DATA_OBJECT, POINTER_OBJECT }; | |
2088 | |
2089 static void RecordCopiedObject(Heap* heap, HeapObject* obj) { | |
2090 bool should_record = false; | |
2091 #ifdef DEBUG | |
2092 should_record = FLAG_heap_stats; | |
2093 #endif | |
2094 should_record = should_record || FLAG_log_gc; | |
2095 if (should_record) { | |
2096 if (heap->new_space()->Contains(obj)) { | |
2097 heap->new_space()->RecordAllocation(obj); | |
2098 } else { | |
2099 heap->new_space()->RecordPromotion(obj); | |
2100 } | |
2101 } | |
2102 } | |
2103 | |
2104 // Helper function used by CopyObject to copy a source object to an | |
2105 // allocated target object and update the forwarding pointer in the source | |
2106 // object. Returns the target object. | |
2107 INLINE(static void MigrateObject(Heap* heap, HeapObject* source, | |
2108 HeapObject* target, int size)) { | |
2109 // If we migrate into to-space, then the to-space top pointer should be | |
2110 // right after the target object. Incorporate double alignment | |
2111 // over-allocation. | |
2112 DCHECK(!heap->InToSpace(target) || | |
2113 target->address() + size == heap->new_space()->top() || | |
2114 target->address() + size + kPointerSize == heap->new_space()->top()); | |
2115 | |
2116 // Make sure that we do not overwrite the promotion queue which is at | |
2117 // the end of to-space. | |
2118 DCHECK(!heap->InToSpace(target) || | |
2119 heap->promotion_queue()->IsBelowPromotionQueue( | |
2120 heap->new_space()->top())); | |
2121 | |
2122 // Copy the content of source to target. | |
2123 heap->CopyBlock(target->address(), source->address(), size); | |
2124 | |
2125 // Set the forwarding address. | |
2126 source->set_map_word(MapWord::FromForwardingAddress(target)); | |
2127 | |
2128 if (logging_and_profiling_mode == LOGGING_AND_PROFILING_ENABLED) { | |
2129 // Update NewSpace stats if necessary. | |
2130 RecordCopiedObject(heap, target); | |
2131 heap->OnMoveEvent(target, source, size); | |
2132 } | |
2133 | |
2134 if (marks_handling == TRANSFER_MARKS) { | |
2135 if (Marking::TransferColor(source, target)) { | |
2136 MemoryChunk::IncrementLiveBytesFromGC(target, size); | |
2137 } | |
2138 } | |
2139 } | |
2140 | |
2141 template <AllocationAlignment alignment> | |
2142 static inline bool SemiSpaceCopyObject(Map* map, HeapObject** slot, | |
2143 HeapObject* object, int object_size) { | |
2144 Heap* heap = map->GetHeap(); | |
2145 | |
2146 DCHECK(heap->AllowedToBeMigrated(object, NEW_SPACE)); | |
2147 AllocationResult allocation = | |
2148 heap->new_space()->AllocateRaw(object_size, alignment); | |
2149 | |
2150 HeapObject* target = NULL; // Initialization to please compiler. | |
2151 if (allocation.To(&target)) { | |
2152 // Order is important here: Set the promotion limit before storing a | |
2153 // filler for double alignment or migrating the object. Otherwise we | |
2154 // may end up overwriting promotion queue entries when we migrate the | |
2155 // object. | |
2156 heap->promotion_queue()->SetNewLimit(heap->new_space()->top()); | |
2157 | |
2158 MigrateObject(heap, object, target, object_size); | |
2159 | |
2160 // Update slot to new target. | |
2161 *slot = target; | |
2162 | |
2163 heap->IncrementSemiSpaceCopiedObjectSize(object_size); | |
2164 return true; | |
2165 } | |
2166 return false; | |
2167 } | |
2168 | |
2169 | |
2170 template <ObjectContents object_contents, AllocationAlignment alignment> | |
2171 static inline bool PromoteObject(Map* map, HeapObject** slot, | |
2172 HeapObject* object, int object_size) { | |
2173 Heap* heap = map->GetHeap(); | |
2174 | |
2175 AllocationResult allocation = | |
2176 heap->old_space()->AllocateRaw(object_size, alignment); | |
2177 | |
2178 HeapObject* target = NULL; // Initialization to please compiler. | |
2179 if (allocation.To(&target)) { | |
2180 MigrateObject(heap, object, target, object_size); | |
2181 | |
2182 // Update slot to new target. | |
2183 *slot = target; | |
2184 | |
2185 if (object_contents == POINTER_OBJECT) { | |
2186 if (map->instance_type() == JS_FUNCTION_TYPE) { | |
2187 heap->promotion_queue()->insert(target, | |
2188 JSFunction::kNonWeakFieldsEndOffset); | |
2189 } else { | |
2190 heap->promotion_queue()->insert(target, object_size); | |
2191 } | |
2192 } | |
2193 heap->IncrementPromotedObjectsSize(object_size); | |
2194 return true; | |
2195 } | |
2196 return false; | |
2197 } | |
2198 | |
2199 | |
2200 template <ObjectContents object_contents, AllocationAlignment alignment> | |
2201 static inline void EvacuateObject(Map* map, HeapObject** slot, | |
2202 HeapObject* object, int object_size) { | |
2203 SLOW_DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); | |
2204 SLOW_DCHECK(object->Size() == object_size); | |
2205 Heap* heap = map->GetHeap(); | |
2206 | |
2207 if (!heap->ShouldBePromoted(object->address(), object_size)) { | |
2208 // A semi-space copy may fail due to fragmentation. In that case, we | |
2209 // try to promote the object. | |
2210 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) { | |
2211 return; | |
2212 } | |
2213 } | |
2214 | |
2215 if (PromoteObject<object_contents, alignment>(map, slot, object, | |
2216 object_size)) { | |
2217 return; | |
2218 } | |
2219 | |
2220 // If promotion failed, we try to copy the object to the other semi-space | |
2221 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) return; | |
2222 | |
2223 UNREACHABLE(); | |
2224 } | |
2225 | |
2226 | |
2227 static inline void EvacuateJSFunction(Map* map, HeapObject** slot, | |
2228 HeapObject* object) { | |
2229 ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized< | |
2230 JSFunction::kSize>(map, slot, object); | |
2231 | |
2232 MapWord map_word = object->map_word(); | |
2233 DCHECK(map_word.IsForwardingAddress()); | |
2234 HeapObject* target = map_word.ToForwardingAddress(); | |
2235 | |
2236 MarkBit mark_bit = Marking::MarkBitFrom(target); | |
2237 if (Marking::IsBlack(mark_bit)) { | |
2238 // This object is black and it might not be rescanned by marker. | |
2239 // We should explicitly record code entry slot for compaction because | |
2240 // promotion queue processing (IterateAndMarkPointersToFromSpace) will | |
2241 // miss it as it is not HeapObject-tagged. | |
2242 Address code_entry_slot = | |
2243 target->address() + JSFunction::kCodeEntryOffset; | |
2244 Code* code = Code::cast(Code::GetObjectFromEntryAddress(code_entry_slot)); | |
2245 map->GetHeap()->mark_compact_collector()->RecordCodeEntrySlot( | |
2246 target, code_entry_slot, code); | |
2247 } | |
2248 } | |
2249 | |
2250 | |
2251 static inline void EvacuateFixedArray(Map* map, HeapObject** slot, | |
2252 HeapObject* object) { | |
2253 int object_size = FixedArray::BodyDescriptor::SizeOf(map, object); | |
2254 EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, | |
2255 object_size); | |
2256 } | |
2257 | |
2258 | |
2259 static inline void EvacuateFixedDoubleArray(Map* map, HeapObject** slot, | |
2260 HeapObject* object) { | |
2261 int length = reinterpret_cast<FixedDoubleArray*>(object)->length(); | |
2262 int object_size = FixedDoubleArray::SizeFor(length); | |
2263 EvacuateObject<DATA_OBJECT, kDoubleAligned>(map, slot, object, object_size); | |
2264 } | |
2265 | |
2266 | |
2267 static inline void EvacuateFixedTypedArray(Map* map, HeapObject** slot, | |
2268 HeapObject* object) { | |
2269 int object_size = reinterpret_cast<FixedTypedArrayBase*>(object)->size(); | |
2270 EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size); | |
2271 | |
2272 MapWord map_word = object->map_word(); | |
2273 DCHECK(map_word.IsForwardingAddress()); | |
2274 FixedTypedArrayBase* target = | |
2275 reinterpret_cast<FixedTypedArrayBase*>(map_word.ToForwardingAddress()); | |
2276 if (target->base_pointer() != Smi::FromInt(0)) | |
2277 target->set_base_pointer(target, SKIP_WRITE_BARRIER); | |
2278 } | |
2279 | |
2280 | |
2281 static inline void EvacuateFixedFloat64Array(Map* map, HeapObject** slot, | |
2282 HeapObject* object) { | |
2283 int object_size = reinterpret_cast<FixedFloat64Array*>(object)->size(); | |
2284 EvacuateObject<DATA_OBJECT, kDoubleAligned>(map, slot, object, object_size); | |
2285 | |
2286 MapWord map_word = object->map_word(); | |
2287 DCHECK(map_word.IsForwardingAddress()); | |
2288 FixedTypedArrayBase* target = | |
2289 reinterpret_cast<FixedTypedArrayBase*>(map_word.ToForwardingAddress()); | |
2290 if (target->base_pointer() != Smi::FromInt(0)) | |
2291 target->set_base_pointer(target, SKIP_WRITE_BARRIER); | |
2292 } | |
2293 | |
2294 | |
2295 static inline void EvacuateJSArrayBuffer(Map* map, HeapObject** slot, | |
2296 HeapObject* object) { | |
2297 ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object); | |
2298 | |
2299 Heap* heap = map->GetHeap(); | |
2300 MapWord map_word = object->map_word(); | |
2301 DCHECK(map_word.IsForwardingAddress()); | |
2302 HeapObject* target = map_word.ToForwardingAddress(); | |
2303 if (!heap->InNewSpace(target)) { | |
2304 heap->array_buffer_tracker()->Promote(JSArrayBuffer::cast(target)); | |
2305 } | |
2306 } | |
2307 | |
2308 | |
2309 static inline void EvacuateByteArray(Map* map, HeapObject** slot, | |
2310 HeapObject* object) { | |
2311 int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize(); | |
2312 EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size); | |
2313 } | |
2314 | |
2315 | |
2316 static inline void EvacuateSeqOneByteString(Map* map, HeapObject** slot, | |
2317 HeapObject* object) { | |
2318 int object_size = SeqOneByteString::cast(object) | |
2319 ->SeqOneByteStringSize(map->instance_type()); | |
2320 EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size); | |
2321 } | |
2322 | |
2323 | |
2324 static inline void EvacuateSeqTwoByteString(Map* map, HeapObject** slot, | |
2325 HeapObject* object) { | |
2326 int object_size = SeqTwoByteString::cast(object) | |
2327 ->SeqTwoByteStringSize(map->instance_type()); | |
2328 EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size); | |
2329 } | |
2330 | |
2331 | |
2332 static inline void EvacuateShortcutCandidate(Map* map, HeapObject** slot, | |
2333 HeapObject* object) { | |
2334 DCHECK(IsShortcutCandidate(map->instance_type())); | |
2335 | |
2336 Heap* heap = map->GetHeap(); | |
2337 | |
2338 if (marks_handling == IGNORE_MARKS && | |
2339 ConsString::cast(object)->unchecked_second() == heap->empty_string()) { | |
2340 HeapObject* first = | |
2341 HeapObject::cast(ConsString::cast(object)->unchecked_first()); | |
2342 | |
2343 *slot = first; | |
2344 | |
2345 if (!heap->InNewSpace(first)) { | |
2346 object->set_map_word(MapWord::FromForwardingAddress(first)); | |
2347 return; | |
2348 } | |
2349 | |
2350 MapWord first_word = first->map_word(); | |
2351 if (first_word.IsForwardingAddress()) { | |
2352 HeapObject* target = first_word.ToForwardingAddress(); | |
2353 | |
2354 *slot = target; | |
2355 object->set_map_word(MapWord::FromForwardingAddress(target)); | |
2356 return; | |
2357 } | |
2358 | |
2359 Heap::ScavengeObjectSlow(slot, first); | |
2360 object->set_map_word(MapWord::FromForwardingAddress(*slot)); | |
2361 return; | |
2362 } | |
2363 | |
2364 int object_size = ConsString::kSize; | |
2365 EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, | |
2366 object_size); | |
2367 } | |
2368 | |
2369 template <ObjectContents object_contents> | |
2370 class ObjectEvacuationStrategy { | |
2371 public: | |
2372 template <int object_size> | |
2373 static inline void VisitSpecialized(Map* map, HeapObject** slot, | |
2374 HeapObject* object) { | |
2375 EvacuateObject<object_contents, kWordAligned>(map, slot, object, | |
2376 object_size); | |
2377 } | |
2378 | |
2379 static inline void Visit(Map* map, HeapObject** slot, HeapObject* object) { | |
2380 int object_size = map->instance_size(); | |
2381 EvacuateObject<object_contents, kWordAligned>(map, slot, object, | |
2382 object_size); | |
2383 } | |
2384 }; | |
2385 | |
2386 static VisitorDispatchTable<ScavengingCallback> table_; | |
2387 }; | |
2388 | |
2389 | |
2390 template <MarksHandling marks_handling, | |
2391 LoggingAndProfiling logging_and_profiling_mode> | |
2392 VisitorDispatchTable<ScavengingCallback> | |
2393 ScavengingVisitor<marks_handling, logging_and_profiling_mode>::table_; | |
2394 | |
2395 | |
2396 static void InitializeScavengingVisitorsTables() { | |
2397 ScavengingVisitor<TRANSFER_MARKS, | |
2398 LOGGING_AND_PROFILING_DISABLED>::Initialize(); | |
2399 ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_DISABLED>::Initialize(); | |
2400 ScavengingVisitor<TRANSFER_MARKS, | |
2401 LOGGING_AND_PROFILING_ENABLED>::Initialize(); | |
2402 ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_ENABLED>::Initialize(); | |
2403 } | |
2404 | |
2405 | |
2406 void Heap::SelectScavengingVisitorsTable() { | |
2407 bool logging_and_profiling = | |
2408 FLAG_verify_predictable || isolate()->logger()->is_logging() || | |
2409 isolate()->cpu_profiler()->is_profiling() || | |
2410 (isolate()->heap_profiler() != NULL && | |
2411 isolate()->heap_profiler()->is_tracking_object_moves()); | |
2412 | |
2413 if (!incremental_marking()->IsMarking()) { | |
2414 if (!logging_and_profiling) { | |
2415 scavenging_visitors_table_.CopyFrom(ScavengingVisitor< | |
2416 IGNORE_MARKS, LOGGING_AND_PROFILING_DISABLED>::GetTable()); | |
2417 } else { | |
2418 scavenging_visitors_table_.CopyFrom(ScavengingVisitor< | |
2419 IGNORE_MARKS, LOGGING_AND_PROFILING_ENABLED>::GetTable()); | |
2420 } | |
2421 } else { | |
2422 if (!logging_and_profiling) { | |
2423 scavenging_visitors_table_.CopyFrom(ScavengingVisitor< | |
2424 TRANSFER_MARKS, LOGGING_AND_PROFILING_DISABLED>::GetTable()); | |
2425 } else { | |
2426 scavenging_visitors_table_.CopyFrom(ScavengingVisitor< | |
2427 TRANSFER_MARKS, LOGGING_AND_PROFILING_ENABLED>::GetTable()); | |
2428 } | |
2429 | |
2430 if (incremental_marking()->IsCompacting()) { | |
2431 // When compacting forbid short-circuiting of cons-strings. | |
2432 // Scavenging code relies on the fact that new space object | |
2433 // can't be evacuated into evacuation candidate but | |
2434 // short-circuiting violates this assumption. | |
2435 scavenging_visitors_table_.Register( | |
2436 StaticVisitorBase::kVisitShortcutCandidate, | |
2437 scavenging_visitors_table_.GetVisitorById( | |
2438 StaticVisitorBase::kVisitConsString)); | |
2439 } | |
2440 } | |
2441 } | |
2442 | |
2443 | |
2444 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { | |
2445 SLOW_DCHECK(object->GetIsolate()->heap()->InFromSpace(object)); | |
2446 MapWord first_word = object->map_word(); | |
2447 SLOW_DCHECK(!first_word.IsForwardingAddress()); | |
2448 Map* map = first_word.ToMap(); | |
2449 map->GetHeap()->scavenging_visitors_table_.GetVisitor(map)(map, p, object); | |
2450 } | |
2451 | |
2452 | |
2453 void Heap::ConfigureInitialOldGenerationSize() { | 1969 void Heap::ConfigureInitialOldGenerationSize() { |
2454 if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) { | 1970 if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) { |
2455 old_generation_allocation_limit_ = | 1971 old_generation_allocation_limit_ = |
2456 Max(kMinimumOldGenerationAllocationLimit, | 1972 Max(kMinimumOldGenerationAllocationLimit, |
2457 static_cast<intptr_t>( | 1973 static_cast<intptr_t>( |
2458 static_cast<double>(old_generation_allocation_limit_) * | 1974 static_cast<double>(old_generation_allocation_limit_) * |
2459 (tracer()->AverageSurvivalRatio() / 100))); | 1975 (tracer()->AverageSurvivalRatio() / 100))); |
2460 } | 1976 } |
2461 } | 1977 } |
2462 | 1978 |
(...skipping 3008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5471 for (PagedSpace* space = spaces.next(); space != NULL; | 4987 for (PagedSpace* space = spaces.next(); space != NULL; |
5472 space = spaces.next()) { | 4988 space = spaces.next()) { |
5473 space->EmptyAllocationInfo(); | 4989 space->EmptyAllocationInfo(); |
5474 } | 4990 } |
5475 } | 4991 } |
5476 | 4992 |
5477 | 4993 |
5478 V8_DECLARE_ONCE(initialize_gc_once); | 4994 V8_DECLARE_ONCE(initialize_gc_once); |
5479 | 4995 |
5480 static void InitializeGCOnce() { | 4996 static void InitializeGCOnce() { |
5481 InitializeScavengingVisitorsTables(); | 4997 Scavenger::Initialize(); |
5482 NewSpaceScavenger::Initialize(); | 4998 StaticScavengeVisitor::Initialize(); |
5483 MarkCompactCollector::Initialize(); | 4999 MarkCompactCollector::Initialize(); |
5484 } | 5000 } |
5485 | 5001 |
5486 | 5002 |
5487 bool Heap::SetUp() { | 5003 bool Heap::SetUp() { |
5488 #ifdef DEBUG | 5004 #ifdef DEBUG |
5489 allocation_timeout_ = FLAG_gc_interval; | 5005 allocation_timeout_ = FLAG_gc_interval; |
5490 #endif | 5006 #endif |
5491 | 5007 |
5492 // Initialize heap spaces and initial maps and objects. Whenever something | 5008 // Initialize heap spaces and initial maps and objects. Whenever something |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5551 } | 5067 } |
5552 } | 5068 } |
5553 | 5069 |
5554 for (int i = 0; i < static_cast<int>(v8::Isolate::kUseCounterFeatureCount); | 5070 for (int i = 0; i < static_cast<int>(v8::Isolate::kUseCounterFeatureCount); |
5555 i++) { | 5071 i++) { |
5556 deferred_counters_[i] = 0; | 5072 deferred_counters_[i] = 0; |
5557 } | 5073 } |
5558 | 5074 |
5559 tracer_ = new GCTracer(this); | 5075 tracer_ = new GCTracer(this); |
5560 | 5076 |
| 5077 scavenge_collector_ = new Scavenger(this); |
| 5078 |
5561 memory_reducer_ = new MemoryReducer(this); | 5079 memory_reducer_ = new MemoryReducer(this); |
5562 | 5080 |
5563 object_stats_ = new ObjectStats(this); | 5081 object_stats_ = new ObjectStats(this); |
5564 object_stats_->ClearObjectStats(true); | 5082 object_stats_->ClearObjectStats(true); |
5565 | 5083 |
5566 array_buffer_tracker_ = new ArrayBufferTracker(this); | 5084 array_buffer_tracker_ = new ArrayBufferTracker(this); |
5567 | 5085 |
5568 LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity())); | 5086 LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity())); |
5569 LOG(isolate_, IntPtrTEvent("heap-available", Available())); | 5087 LOG(isolate_, IntPtrTEvent("heap-available", Available())); |
5570 | 5088 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5662 map_space_->MaximumCommittedMemory()); | 5180 map_space_->MaximumCommittedMemory()); |
5663 PrintF("maximum_committed_by_lo_space=%" V8_PTR_PREFIX "d ", | 5181 PrintF("maximum_committed_by_lo_space=%" V8_PTR_PREFIX "d ", |
5664 lo_space_->MaximumCommittedMemory()); | 5182 lo_space_->MaximumCommittedMemory()); |
5665 PrintF("\n\n"); | 5183 PrintF("\n\n"); |
5666 } | 5184 } |
5667 | 5185 |
5668 if (FLAG_verify_predictable) { | 5186 if (FLAG_verify_predictable) { |
5669 PrintAlloctionsHash(); | 5187 PrintAlloctionsHash(); |
5670 } | 5188 } |
5671 | 5189 |
| 5190 delete scavenge_collector_; |
| 5191 scavenge_collector_ = nullptr; |
| 5192 |
5672 if (memory_reducer_ != nullptr) { | 5193 if (memory_reducer_ != nullptr) { |
5673 memory_reducer_->TearDown(); | 5194 memory_reducer_->TearDown(); |
5674 delete memory_reducer_; | 5195 delete memory_reducer_; |
5675 memory_reducer_ = nullptr; | 5196 memory_reducer_ = nullptr; |
5676 } | 5197 } |
5677 | 5198 |
5678 delete object_stats_; | 5199 delete object_stats_; |
5679 object_stats_ = nullptr; | 5200 object_stats_ = nullptr; |
5680 | 5201 |
5681 WaitUntilUnmappingOfFreeChunksCompleted(); | 5202 WaitUntilUnmappingOfFreeChunksCompleted(); |
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6578 *object_sub_type = "CODE_AGE/" #name; \ | 6099 *object_sub_type = "CODE_AGE/" #name; \ |
6579 return true; | 6100 return true; |
6580 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) | 6101 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) |
6581 #undef COMPARE_AND_RETURN_NAME | 6102 #undef COMPARE_AND_RETURN_NAME |
6582 } | 6103 } |
6583 return false; | 6104 return false; |
6584 } | 6105 } |
6585 | 6106 |
6586 } // namespace internal | 6107 } // namespace internal |
6587 } // namespace v8 | 6108 } // namespace v8 |
OLD | NEW |