Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | Friends | List of all members
dart::Scavenger Class Reference

#include <scavenger.h>

Public Member Functions

 Scavenger (Heap *heap, intptr_t max_semi_capacity_in_words)
 
 ~Scavenger ()
 
bool Contains (uword addr) const
 
uword TryAllocate (Thread *thread, intptr_t size)
 
uword TryAllocateNoSafepoint (Thread *thread, intptr_t size)
 
intptr_t AbandonRemainingTLAB (Thread *thread)
 
void AbandonRemainingTLABForDebugging (Thread *thread)
 
void Scavenge (Thread *thread, GCType type, GCReason reason)
 
intptr_t UsedInWords () const
 
intptr_t CapacityInWords () const
 
intptr_t ExternalInWords () const
 
SpaceUsage GetCurrentUsage () const
 
intptr_t ThresholdInWords () const
 
void VisitObjects (ObjectVisitor *visitor) const
 
void VisitObjectPointers (ObjectPointerVisitor *visitor) const
 
void AddRegionsToObjectSet (ObjectSet *set) const
 
void WriteProtect (bool read_only)
 
bool ShouldPerformIdleScavenge (int64_t deadline)
 
void AddGCTime (int64_t micros)
 
int64_t gc_time_micros () const
 
void IncrementCollections ()
 
intptr_t collections () const
 
void PrintToJSONObject (JSONObject *object) const
 
bool AllocatedExternal (intptr_t size)
 
void FreedExternal (intptr_t size)
 
void set_freed_in_words (intptr_t value)
 
Pagehead () const
 
void PruneNew ()
 
void PruneDeferred ()
 
void Forward (MarkingStackBlock *blocks)
 
void ForwardDeferred ()
 
void PruneWeak (GCLinkedLists *delayed)
 
template<typename Type , typename PtrType >
void PruneWeak (GCLinkedList< Type, PtrType > *list)
 

Static Public Member Functions

static intptr_t MaxMutatorThreadCount ()
 

Friends

template<bool >
class ScavengerVisitorBase
 

Detailed Description

Definition at line 124 of file scavenger.h.

Constructor & Destructor Documentation

◆ Scavenger()

dart::Scavenger::Scavenger ( Heap heap,
intptr_t  max_semi_capacity_in_words 
)

Definition at line 824 of file scavenger.cc.

825 : heap_(heap),
826 max_semi_capacity_in_words_(max_semi_capacity_in_words),
827 scavenge_words_per_micro_(kConservativeInitialScavengeSpeed) {
828 ASSERT(heap != nullptr);
829
830 // Verify assumptions about the first word in objects which the scavenger is
831 // going to use for forwarding pointers.
833
834 // Set initial semi space size in words.
835 const intptr_t initial_semi_capacity_in_words = Utils::Minimum(
836 max_semi_capacity_in_words, FLAG_new_gen_semi_initial_size * MBInWords);
837
838 to_ = new SemiSpace(initial_semi_capacity_in_words);
839 idle_scavenge_threshold_in_words_ = initial_semi_capacity_in_words;
840
841 UpdateMaxHeapCapacity();
842 UpdateMaxHeapUsage();
843}
static intptr_t tags_offset()
Definition: object.h:346
static T Minimum(T x, T y)
Definition: utils.h:36
#define ASSERT(E)
static constexpr intptr_t kConservativeInitialScavengeSpeed
Definition: scavenger.cc:822
constexpr intptr_t MBInWords
Definition: globals.h:537

◆ ~Scavenger()

dart::Scavenger::~Scavenger ( )

Definition at line 845 of file scavenger.cc.

845 {
846 ASSERT(!scavenging_);
847 delete to_;
848 ASSERT(blocks_ == nullptr);
849}

Member Function Documentation

◆ AbandonRemainingTLAB()

intptr_t dart::Scavenger::AbandonRemainingTLAB ( Thread thread)

Definition at line 1863 of file scavenger.cc.

1863 {
1864 if (thread->top() == 0) return 0;
1865
1866 Page* page = Page::Of(thread->top() - 1);
1867 intptr_t allocated;
1868 {
1869 if (thread->is_marking()) {
1870 thread->DeferredMarkLiveTemporaries();
1871 }
1872 MutexLocker ml(&space_lock_);
1873 allocated = page->Release(thread);
1874 }
1875 ASSERT(thread->top() == 0);
1876 return allocated;
1877}
static Page * Of(ObjectPtr obj)
Definition: page.h:162

◆ AbandonRemainingTLABForDebugging()

void dart::Scavenger::AbandonRemainingTLABForDebugging ( Thread thread)

Definition at line 1850 of file scavenger.cc.

1850 {
1851 // Allocate any remaining space so the TLAB won't be reused. Write a filler
1852 // object so it remains iterable.
1853 uword top = thread->top();
1854 intptr_t size = thread->end() - thread->top();
1855 if (size > 0) {
1856 thread->set_top(top + size);
1858 }
1859
1860 AbandonRemainingTLAB(thread);
1861}
static ForwardingCorpse * AsForwarder(uword addr, intptr_t size)
Definition: become.cc:20
intptr_t AbandonRemainingTLAB(Thread *thread)
Definition: scavenger.cc:1863
uintptr_t uword
Definition: globals.h:501
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259

◆ AddGCTime()

void dart::Scavenger::AddGCTime ( int64_t  micros)
inline

Definition at line 187 of file scavenger.h.

187{ gc_time_micros_ += micros; }

◆ AddRegionsToObjectSet()

void dart::Scavenger::AddRegionsToObjectSet ( ObjectSet set) const

Definition at line 1793 of file scavenger.cc.

1793 {
1794 for (Page* page = to_->head(); page != nullptr; page = page->next()) {
1795 set->AddRegion(page->start(), page->end());
1796 }
1797}
Page * head() const
Definition: scavenger.h:57
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
Definition: switches.h:76

◆ AllocatedExternal()

bool dart::Scavenger::AllocatedExternal ( intptr_t  size)
inline

Definition at line 202 of file scavenger.h.

202 {
203 ASSERT(size >= 0);
204 intptr_t expected = external_size_.load();
205 intptr_t desired;
206 do {
207 intptr_t next_external_size_in_words =
208 (external_size_ >> kWordSizeLog2) + (size >> kWordSizeLog2);
209 if (next_external_size_in_words < 0 ||
210 next_external_size_in_words > kMaxAddrSpaceInWords) {
211 return false;
212 }
213 desired = expected + size;
214 ASSERT(desired >= 0);
215 } while (!external_size_.compare_exchange_weak(expected, desired));
216 return true;
217 }
T load(std::memory_order order=std::memory_order_relaxed) const
Definition: atomic.h:21
bool compare_exchange_weak(T &expected, T desired, std::memory_order order=std::memory_order_relaxed)
Definition: atomic.h:52
constexpr intptr_t kWordSizeLog2
Definition: globals.h:507
const intptr_t kMaxAddrSpaceInWords
Definition: globals.h:50

◆ CapacityInWords()

intptr_t dart::Scavenger::CapacityInWords ( ) const
inline

Definition at line 164 of file scavenger.h.

164 {
165 MutexLocker ml(&space_lock_);
166 return to_->capacity_in_words();
167 }
intptr_t capacity_in_words() const
Definition: scavenger.h:54

◆ collections()

intptr_t dart::Scavenger::collections ( ) const
inline

Definition at line 193 of file scavenger.h.

193{ return collections_; }

◆ Contains()

bool dart::Scavenger::Contains ( uword  addr) const
inline

Definition at line 136 of file scavenger.h.

136{ return to_->Contains(addr); }
bool Contains(uword addr) const
Definition: scavenger.cc:792

◆ ExternalInWords()

intptr_t dart::Scavenger::ExternalInWords ( ) const
inline

Definition at line 168 of file scavenger.h.

168{ return external_size_ >> kWordSizeLog2; }

◆ Forward()

void dart::Scavenger::Forward ( MarkingStackBlock blocks)

Definition at line 1524 of file scavenger.cc.

1524 {
1525 ASSERT(abort_);
1526
1527 GCMarker* marker = heap_->old_space()->marker();
1528 MarkingStack* old_marking_stack = &marker->old_marking_stack_;
1529 MarkingStack* new_marking_stack = &marker->new_marking_stack_;
1530 MarkingStackBlock* old_writing = old_marking_stack->PopNonFullBlock();
1531 MarkingStackBlock* new_writing = new_marking_stack->PopNonFullBlock();
1532 while (reading != nullptr) {
1533 // Generated code appends to marking stacks; tell MemorySanitizer.
1534 MSAN_UNPOISON(reading, sizeof(*reading));
1535 while (!reading->IsEmpty()) {
1536 ObjectPtr obj = reading->Pop();
1537 ASSERT(obj->IsHeapObject());
1538#if defined(DEBUG)
1539 if (obj->IsNewObject()) {
1542 }
1543#endif
1544 if (obj->IsForwardingCorpse()) {
1545 // Promoted object was pushed to mark list but reversed.
1546 obj = reinterpret_cast<ForwardingCorpse*>(UntaggedObject::ToAddr(obj))
1547 ->target();
1548 }
1549 ASSERT(!obj->IsForwardingCorpse());
1550 ASSERT(!obj->IsFreeListElement());
1551 if (obj->IsNewObject()) {
1552 new_writing->Push(obj);
1553 if (new_writing->IsFull()) {
1554 new_marking_stack->PushBlock(new_writing);
1555 new_writing = new_marking_stack->PopNonFullBlock();
1556 }
1557 } else {
1558 old_writing->Push(obj);
1559 if (old_writing->IsFull()) {
1560 old_marking_stack->PushBlock(old_writing);
1561 old_writing = old_marking_stack->PopNonFullBlock();
1562 }
1563 }
1564 }
1565
1566 MarkingStackBlock* next = reading->next();
1567 reading->Reset();
1568 old_marking_stack->PushBlock(reading);
1569 reading = next;
1570 }
1571 old_marking_stack->PushBlock(old_writing);
1572 new_marking_stack->PushBlock(new_writing);
1573}
static float next(float f)
static const char marker[]
PageSpace * old_space()
Definition: heap.h:63
GCMarker * marker() const
Definition: pages.h:358
static uword ToAddr(const UntaggedObject *raw_obj)
Definition: raw_object.h:522
uint32_t * target
#define MSAN_UNPOISON(ptr, len)
static DART_FORCE_INLINE uword ReadHeaderRelaxed(ObjectPtr obj)
Definition: scavenger.cc:118
MarkingStack::Block MarkingStackBlock
static DART_FORCE_INLINE bool IsForwarding(uword header)
Definition: scavenger.cc:66
static const char header[]
Definition: skpbench.cpp:88

◆ ForwardDeferred()

void dart::Scavenger::ForwardDeferred ( )

Definition at line 1575 of file scavenger.cc.

1575 {
1576 ASSERT(abort_);
1577
1578 class ReverseMarkStack : public ObjectPointerVisitor {
1579 public:
1580 explicit ReverseMarkStack(IsolateGroup* group)
1581 : ObjectPointerVisitor(group) {}
1582
1583 void VisitPointers(ObjectPtr* first, ObjectPtr* last) override {
1584 for (ObjectPtr* p = first; p <= last; p++) {
1585 ObjectPtr obj = *p;
1586#if defined(DEBUG)
1587 if (obj->IsNewObject()) {
1590 }
1591#endif
1592 if (obj->IsForwardingCorpse()) {
1593 // Promoted object was pushed to mark list but reversed.
1594 *p = reinterpret_cast<ForwardingCorpse*>(UntaggedObject::ToAddr(obj))
1595 ->target();
1596 }
1597 }
1598 }
1599#if defined(DART_COMPRESSED_POINTERS)
1600 void VisitCompressedPointers(uword heap_base,
1601 CompressedObjectPtr* first,
1602 CompressedObjectPtr* last) override {
1603 UNREACHABLE();
1604 }
1605#endif
1606 };
1607
1608 ReverseMarkStack visitor(heap_->isolate_group());
1609 heap_->old_space()->marker()->deferred_marking_stack_.VisitObjectPointers(
1610 &visitor);
1611}
#define UNREACHABLE()
Definition: assert.h:248
void VisitObjectPointers(ObjectPointerVisitor *visitor)
IsolateGroup * isolate_group() const
Definition: heap.h:273
ObjectPtr CompressedObjectPtr

◆ FreedExternal()

void dart::Scavenger::FreedExternal ( intptr_t  size)
inline

Definition at line 218 of file scavenger.h.

218 {
219 ASSERT(size >= 0);
220 external_size_ -= size;
221 ASSERT(external_size_ >= 0);
222 }

◆ gc_time_micros()

int64_t dart::Scavenger::gc_time_micros ( ) const
inline

Definition at line 189 of file scavenger.h.

189{ return gc_time_micros_; }

◆ GetCurrentUsage()

SpaceUsage dart::Scavenger::GetCurrentUsage ( ) const
inline

Definition at line 169 of file scavenger.h.

169 {
170 SpaceUsage usage;
171 usage.used_in_words = UsedInWords();
172 usage.capacity_in_words = CapacityInWords();
173 usage.external_in_words = ExternalInWords();
174 return usage;
175 }
intptr_t ExternalInWords() const
Definition: scavenger.h:168
intptr_t CapacityInWords() const
Definition: scavenger.h:164
intptr_t UsedInWords() const
Definition: scavenger.h:160
static void usage(char *argv0)

◆ head()

Page * dart::Scavenger::head ( ) const
inline

Definition at line 237 of file scavenger.h.

237{ return to_->head(); }

◆ IncrementCollections()

void dart::Scavenger::IncrementCollections ( )
inline

Definition at line 191 of file scavenger.h.

191{ collections_++; }

◆ MaxMutatorThreadCount()

static intptr_t dart::Scavenger::MaxMutatorThreadCount ( )
inlinestatic

Definition at line 228 of file scavenger.h.

228 {
229 // With a max new-space of 16 MB and 512kb TLABs we would allow up to 8
230 // mutator threads to run at the same time.
231 const intptr_t max_parallel_tlab_usage =
232 (FLAG_new_gen_semi_max_size * MB) / Scavenger::kTLABSize;
233 const intptr_t max_pool_size = max_parallel_tlab_usage / 4;
234 return max_pool_size > 0 ? max_pool_size : 1;
235 }
constexpr intptr_t MB
Definition: globals.h:530

◆ PrintToJSONObject()

void dart::Scavenger::PrintToJSONObject ( JSONObject object) const

Definition at line 2132 of file scavenger.cc.

2132 {
2133 auto isolate_group = IsolateGroup::Current();
2134 ASSERT(isolate_group != nullptr);
2135 JSONObject space(object, "new");
2136 space.AddProperty("type", "HeapSpace");
2137 space.AddProperty("name", "new");
2138 space.AddProperty("vmName", "Scavenger");
2139 space.AddProperty("collections", collections());
2140 if (collections() > 0) {
2141 int64_t run_time = isolate_group->UptimeMicros();
2142 run_time = Utils::Maximum(run_time, static_cast<int64_t>(0));
2143 double run_time_millis = MicrosecondsToMilliseconds(run_time);
2144 double avg_time_between_collections =
2145 run_time_millis / static_cast<double>(collections());
2146 space.AddProperty("avgCollectionPeriodMillis",
2147 avg_time_between_collections);
2148 } else {
2149 space.AddProperty("avgCollectionPeriodMillis", 0.0);
2150 }
2151 space.AddProperty64("used", UsedInWords() * kWordSize);
2152 space.AddProperty64("capacity", CapacityInWords() * kWordSize);
2153 space.AddProperty64("external", ExternalInWords() * kWordSize);
2154 space.AddProperty("time", MicrosecondsToSeconds(gc_time_micros()));
2155}
static IsolateGroup * Current()
Definition: isolate.h:539
int64_t gc_time_micros() const
Definition: scavenger.h:189
intptr_t collections() const
Definition: scavenger.h:193
static constexpr T Maximum(T x, T y)
Definition: utils.h:41
constexpr double MicrosecondsToSeconds(int64_t micros)
Definition: globals.h:571
constexpr intptr_t kWordSize
Definition: globals.h:509
constexpr double MicrosecondsToMilliseconds(int64_t micros)
Definition: globals.h:574

◆ PruneDeferred()

void dart::Scavenger::PruneDeferred ( )

Definition at line 1662 of file scavenger.cc.

1662 {
1663 ASSERT(!abort_);
1664 TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "PruneDeferredMarkingStack");
1665 MarkingStackBlock* reading;
1666 GCMarker* marker = heap_->old_space()->marker();
1667 MarkingStack* marking_stack = &marker->deferred_marking_stack_;
1668 MarkingStackBlock* writing = marking_stack->PopNonFullBlock();
1669 for (;;) {
1670 {
1671 MutexLocker ml(&space_lock_);
1672 reading = deferred_blocks_;
1673 if (reading == nullptr) break;
1674 deferred_blocks_ = reading->next();
1675 }
1676 // Generated code appends to marking stacks; tell MemorySanitizer.
1677 MSAN_UNPOISON(reading, sizeof(*reading));
1678 while (!reading->IsEmpty()) {
1679 ObjectPtr obj = reading->Pop();
1680 ASSERT(obj->IsHeapObject());
1681 if (obj->IsNewObject()) {
1683 if (!IsForwarding(header)) continue;
1684 obj = ForwardedObj(header);
1685 }
1686 ASSERT(!obj->IsForwardingCorpse());
1687 ASSERT(!obj->IsFreeListElement());
1688 writing->Push(obj);
1689 if (writing->IsFull()) {
1690 marking_stack->PushBlock(writing);
1691 writing = marking_stack->PopNonFullBlock();
1692 }
1693 }
1694 reading->Reset();
1695 marking_stack->PushBlock(reading);
1696 }
1697 marking_stack->PushBlock(writing);
1698}
PointerBlock< Size > * next() const
Definition: pointer_block.h:30
static Thread * Current()
Definition: thread.h:362
static DART_FORCE_INLINE ObjectPtr ForwardedObj(uword header)
Definition: scavenger.cc:73
#define TIMELINE_FUNCTION_GC_DURATION(thread, name)
Definition: timeline.h:41

◆ PruneNew()

void dart::Scavenger::PruneNew ( )

Definition at line 1613 of file scavenger.cc.

1613 {
1614 ASSERT(!abort_);
1615 TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "PruneNewMarkingStack");
1616 MarkingStackBlock* reading;
1617 GCMarker* marker = heap_->old_space()->marker();
1618 MarkingStack* old_marking_stack = &marker->old_marking_stack_;
1619 MarkingStack* new_marking_stack = &marker->new_marking_stack_;
1620 MarkingStackBlock* old_writing = old_marking_stack->PopNonFullBlock();
1621 MarkingStackBlock* new_writing = new_marking_stack->PopNonFullBlock();
1622 for (;;) {
1623 {
1624 MutexLocker ml(&space_lock_);
1625 reading = new_blocks_;
1626 if (reading == nullptr) break;
1627 new_blocks_ = reading->next();
1628 }
1629 // Generated code appends to marking stacks; tell MemorySanitizer.
1630 MSAN_UNPOISON(reading, sizeof(*reading));
1631 while (!reading->IsEmpty()) {
1632 ObjectPtr obj = reading->Pop();
1633 ASSERT(obj->IsHeapObject());
1634 if (obj->IsNewObject()) {
1636 if (!IsForwarding(header)) continue;
1637 obj = ForwardedObj(header);
1638 }
1639 ASSERT(!obj->IsForwardingCorpse());
1640 ASSERT(!obj->IsFreeListElement());
1641 if (obj->IsNewObject()) {
1642 new_writing->Push(obj);
1643 if (new_writing->IsFull()) {
1644 new_marking_stack->PushBlock(new_writing);
1645 new_writing = new_marking_stack->PopNonFullBlock();
1646 }
1647 } else {
1648 old_writing->Push(obj);
1649 if (old_writing->IsFull()) {
1650 old_marking_stack->PushBlock(old_writing);
1651 old_writing = old_marking_stack->PopNonFullBlock();
1652 }
1653 }
1654 }
1655 reading->Reset();
1656 new_marking_stack->PushBlock(reading);
1657 }
1658 old_marking_stack->PushBlock(old_writing);
1659 new_marking_stack->PushBlock(new_writing);
1660}

◆ PruneWeak() [1/2]

template<typename Type , typename PtrType >
void dart::Scavenger::PruneWeak ( GCLinkedList< Type, PtrType > *  list)

Definition at line 1710 of file scavenger.cc.

1710 {
1711 PtrType weak = list->Release();
1712 while (weak != Object::null()) {
1713 PtrType next;
1714 if (weak->IsOldObject()) {
1715 ASSERT(weak->GetClassId() == Type::kClassId);
1716 next = weak->untag()->next_seen_by_gc_.Decompress(weak->heap_base());
1717 weak->untag()->next_seen_by_gc_ = Type::null();
1718 list->Enqueue(weak);
1719 } else {
1721 if (IsForwarding(header)) {
1722 weak = static_cast<PtrType>(ForwardedObj(header));
1723 ASSERT(weak->GetClassId() == Type::kClassId);
1724 next = weak->untag()->next_seen_by_gc_.Decompress(weak->heap_base());
1725 weak->untag()->next_seen_by_gc_ = Type::null();
1726 list->Enqueue(weak);
1727 } else {
1728 // Collected in this scavenge.
1729 ASSERT(weak->GetClassId() == Type::kClassId);
1730 next = weak->untag()->next_seen_by_gc_.Decompress(weak->heap_base());
1731 }
1732 }
1733
1734 weak = next;
1735 }
1736}
static const ClassId kClassId
Definition: object.h:606
static ObjectPtr null()
Definition: object.h:433

◆ PruneWeak() [2/2]

void dart::Scavenger::PruneWeak ( GCLinkedLists delayed)

Definition at line 1700 of file scavenger.cc.

1700 {
1701 ASSERT(!abort_);
1703 PruneWeak(&deferred->weak_properties);
1704 PruneWeak(&deferred->weak_references);
1705 PruneWeak(&deferred->weak_arrays);
1706 PruneWeak(&deferred->finalizer_entries);
1707}
void PruneWeak(GCLinkedLists *delayed)
Definition: scavenger.cc:1700

◆ Scavenge()

void dart::Scavenger::Scavenge ( Thread thread,
GCType  type,
GCReason  reason 
)

Definition at line 1901 of file scavenger.cc.

1901 {
1903
1904 ASSERT(thread->OwnsGCSafepoint());
1905
1906 // Scavenging is not reentrant. Make sure that is the case.
1907 ASSERT(!scavenging_);
1908 scavenging_ = true;
1909
1910 if (type == GCType::kEvacuate) {
1911 // Forces the next scavenge to promote all the objects in the new space.
1912 early_tenure_ = true;
1913 }
1914
1915 if (FLAG_verify_before_gc) {
1916 heap_->WaitForSweeperTasksAtSafepoint(thread);
1917 heap_->VerifyGC("Verifying before Scavenge",
1918 thread->is_marking() ? kAllowMarked : kForbidMarked);
1919 }
1920
1921 // Prepare for a scavenge.
1922 failed_to_promote_ = false;
1923 abort_ = false;
1924 root_slices_started_ = 0;
1925 weak_slices_started_ = 0;
1926 freed_in_words_ = 0;
1927 intptr_t abandoned_bytes = 0; // TODO(rmacnak): Count fragmentation?
1928 SpaceUsage usage_before = GetCurrentUsage();
1929 intptr_t promo_candidate_words = 0;
1930 for (Page* page = to_->head(); page != nullptr; page = page->next()) {
1931 page->Release();
1932 if (early_tenure_) {
1933 page->EarlyTenure();
1934 }
1935 promo_candidate_words += page->promo_candidate_words();
1936 }
1938 SemiSpace* from = Prologue(reason);
1939
1940 intptr_t bytes_promoted;
1941 if (FLAG_scavenger_tasks == 0) {
1942 bytes_promoted = SerialScavenge(from);
1943 } else {
1944 bytes_promoted = ParallelScavenge(from);
1945 }
1946 if (abort_) {
1947 ReverseScavenge(&from);
1948 bytes_promoted = 0;
1949 } else {
1950 if ((ThresholdInWords() - UsedInWords()) < KBInWords) {
1951 // Don't scavenge again until the next old-space GC has occurred. Prevents
1952 // performing one scavenge per allocation as the heap limit is approached.
1953 heap_->assume_scavenge_will_fail_ = true;
1954 }
1955 }
1956 ASSERT(promotion_stack_.IsEmpty());
1957
1958 // Scavenge finished. Run accounting.
1960 stats_history_.Add(ScavengeStats(
1961 start, end, usage_before, GetCurrentUsage(), promo_candidate_words,
1962 bytes_promoted >> kWordSizeLog2, abandoned_bytes >> kWordSizeLog2));
1963 Epilogue(from);
1965
1966 if (FLAG_verify_after_gc) {
1967 heap_->WaitForSweeperTasksAtSafepoint(thread);
1968 heap_->VerifyGC("Verifying after Scavenge...",
1969 thread->is_marking() ? kAllowMarked : kForbidMarked);
1970 }
1971
1972 // Done scavenging. Reset the marker.
1973 ASSERT(scavenging_);
1974 scavenging_ = false;
1975
1976 // It is possible for objects to stay in the new space
1977 // if the VM cannot create more pages for these objects.
1978 ASSERT((type != GCType::kEvacuate) || (UsedInWords() == 0) ||
1979 failed_to_promote_);
1980}
GLenum type
void WaitForSweeperTasksAtSafepoint(Thread *thread)
Definition: heap.cc:680
static int64_t GetCurrentMonotonicMicros()
void ResumeConcurrentMarking()
Definition: pages.cc:452
void PauseConcurrentMarking()
Definition: pages.cc:443
SpaceUsage GetCurrentUsage() const
Definition: scavenger.h:169
intptr_t ThresholdInWords() const
Definition: scavenger.h:176
glong glong end
@ kAllowMarked
Definition: verifier.h:21
@ kForbidMarked
Definition: verifier.h:21
constexpr intptr_t KBInWords
Definition: globals.h:535

◆ set_freed_in_words()

void dart::Scavenger::set_freed_in_words ( intptr_t  value)
inline

Definition at line 224 of file scavenger.h.

224{ freed_in_words_ = value; }
uint8_t value

◆ ShouldPerformIdleScavenge()

bool dart::Scavenger::ShouldPerformIdleScavenge ( int64_t  deadline)

Definition at line 1170 of file scavenger.cc.

1170 {
1171 // To make a consistent decision, we should not yield for a safepoint in the
1172 // middle of deciding whether to perform an idle GC.
1173 NoSafepointScope no_safepoint;
1174
1175 // TODO(rmacnak): Investigate collecting a history of idle period durations.
1176 intptr_t used_in_words = UsedInWords() + freed_in_words_;
1177 intptr_t external_in_words = ExternalInWords();
1178 // Normal reason: new space is getting full.
1179 bool for_new_space = (used_in_words >= idle_scavenge_threshold_in_words_) ||
1180 (external_in_words >= idle_scavenge_threshold_in_words_);
1181 if (!for_new_space) {
1182 return false;
1183 }
1184
1185 int64_t estimated_scavenge_completion =
1187 used_in_words / scavenge_words_per_micro_;
1188 return estimated_scavenge_completion <= deadline;
1189}

◆ ThresholdInWords()

intptr_t dart::Scavenger::ThresholdInWords ( ) const
inline

Definition at line 176 of file scavenger.h.

176{ return to_->gc_threshold_in_words(); }
intptr_t gc_threshold_in_words() const
Definition: scavenger.h:55

◆ TryAllocate()

uword dart::Scavenger::TryAllocate ( Thread thread,
intptr_t  size 
)
inline

Definition at line 138 of file scavenger.h.

138 {
139 uword addr = TryAllocateFromTLAB(thread, size);
140 if (LIKELY(addr != 0)) {
141 return addr;
142 }
143 TryAllocateNewTLAB(thread, size, true);
144 return TryAllocateFromTLAB(thread, size);
145 }
#define LIKELY(cond)
Definition: globals.h:260

◆ TryAllocateNoSafepoint()

uword dart::Scavenger::TryAllocateNoSafepoint ( Thread thread,
intptr_t  size 
)
inline

Definition at line 146 of file scavenger.h.

146 {
147 uword addr = TryAllocateFromTLAB(thread, size);
148 if (LIKELY(addr != 0)) {
149 return addr;
150 }
151 TryAllocateNewTLAB(thread, size, false);
152 return TryAllocateFromTLAB(thread, size);
153 }

◆ UsedInWords()

intptr_t dart::Scavenger::UsedInWords ( ) const
inline

Definition at line 160 of file scavenger.h.

160 {
161 MutexLocker ml(&space_lock_);
162 return to_->used_in_words() - freed_in_words_;
163 }
intptr_t used_in_words() const
Definition: scavenger.h:47

◆ VisitObjectPointers()

void dart::Scavenger::VisitObjectPointers ( ObjectPointerVisitor visitor) const

Definition at line 1775 of file scavenger.cc.

1775 {
1776 ASSERT(Thread::Current()->OwnsGCSafepoint() ||
1777 (Thread::Current()->task_kind() == Thread::kMarkerTask) ||
1778 (Thread::Current()->task_kind() == Thread::kCompactorTask));
1779 for (Page* page = to_->head(); page != nullptr; page = page->next()) {
1780 page->VisitObjectPointers(visitor);
1781 }
1782}
@ kMarkerTask
Definition: thread.h:349
@ kCompactorTask
Definition: thread.h:351

◆ VisitObjects()

void dart::Scavenger::VisitObjects ( ObjectVisitor visitor) const

Definition at line 1784 of file scavenger.cc.

1784 {
1785 ASSERT(Thread::Current()->OwnsGCSafepoint() ||
1786 (Thread::Current()->task_kind() == Thread::kMarkerTask) ||
1788 for (Page* page = to_->head(); page != nullptr; page = page->next()) {
1789 page->VisitObjects(visitor);
1790 }
1791}
@ kIncrementalCompactorTask
Definition: thread.h:354

◆ WriteProtect()

void dart::Scavenger::WriteProtect ( bool  read_only)

Definition at line 2126 of file scavenger.cc.

2126 {
2127 ASSERT(!scavenging_);
2128 to_->WriteProtect(read_only);
2129}
void WriteProtect(bool read_only)
Definition: scavenger.cc:799

Friends And Related Function Documentation

◆ ScavengerVisitorBase

template<bool >
friend class ScavengerVisitorBase
friend

Definition at line 336 of file scavenger.h.


The documentation for this class was generated from the following files: