}
+void Heap::FinalizeIncrementalMarkingIfComplete(const char* comment) {
+ if (FLAG_overapproximate_weak_closure && incremental_marking()->IsMarking() &&
+ (incremental_marking()->IsReadyToOverApproximateWeakClosure() ||
+ (!incremental_marking()->weak_closure_was_overapproximated() &&
+ mark_compact_collector_.marking_deque()->IsEmpty()))) {
+ OverApproximateWeakClosure(comment);
+ } else if (incremental_marking()->IsComplete() ||
+ (mark_compact_collector_.marking_deque()->IsEmpty())) {
+ CollectAllGarbage(current_gc_flags_, comment);
+ }
+}
+
+
bool Heap::TryFinalizeIdleIncrementalMarking(
double idle_time_in_ms, size_t size_of_objects,
size_t final_incremental_mark_compact_speed_in_bytes_per_ms) {
- if (FLAG_overapproximate_weak_closure &&
+ if (FLAG_overapproximate_weak_closure && incremental_marking()->IsMarking() &&
(incremental_marking()->IsReadyToOverApproximateWeakClosure() ||
(!incremental_marking()->weak_closure_was_overapproximated() &&
mark_compact_collector_.marking_deque()->IsEmpty() &&
bool HasHighFragmentation();
bool HasHighFragmentation(intptr_t used, intptr_t committed);
+ bool ShouldOptimizeForMemoryUsage() { return optimize_for_memory_usage_; }
+
// ===========================================================================
// Initialization. ===========================================================
// ===========================================================================
intptr_t step_size_in_bytes, double deadline_in_ms,
IncrementalMarking::StepActions step_actions);
+ void FinalizeIncrementalMarkingIfComplete(const char* comment);
+
IncrementalMarking* incremental_marking() { return &incremental_marking_; }
// ===========================================================================
void IncrementalMarking::MarkObjectGroups() {
DCHECK(FLAG_overapproximate_weak_closure);
DCHECK(!weak_closure_was_overapproximated_);
+ DCHECK(IsMarking());
int old_marking_deque_top =
heap_->mark_compact_collector()->marking_deque()->top();
if (state_.action == kRun) {
DCHECK(heap()->incremental_marking()->IsStopped());
DCHECK(FLAG_incremental_marking);
- heap()->StartIdleIncrementalMarking();
if (FLAG_trace_gc_verbose) {
PrintIsolate(heap()->isolate(), "Memory reducer: started GC #%d\n",
state_.started_gcs);
}
+ if (heap()->ShouldOptimizeForMemoryUsage()) {
+ // Do full GC if memory usage has higher priority than latency. This is
+ // important for background tabs that do not send idle notifications.
+ heap()->CollectAllGarbage(Heap::kReduceMemoryFootprintMask,
+ "memory reducer");
+ } else {
+ heap()->StartIdleIncrementalMarking();
+ }
} else if (state_.action == kWait) {
+ if (!heap()->incremental_marking()->IsStopped() &&
+ heap()->ShouldOptimizeForMemoryUsage()) {
+ // Make progress with pending incremental marking if memory usage has
+ // higher priority than latency. This is important for background tabs
+ // that do not send idle notifications.
+ const int kIncrementalMarkingDelayMs = 500;
+ double deadline = heap()->MonotonicallyIncreasingTimeInMs() +
+ kIncrementalMarkingDelayMs;
+ heap()->AdvanceIncrementalMarking(
+ 0, deadline, i::IncrementalMarking::StepActions(
+ i::IncrementalMarking::NO_GC_VIA_STACK_GUARD,
+ i::IncrementalMarking::FORCE_MARKING,
+ i::IncrementalMarking::FORCE_COMPLETION));
+ heap()->FinalizeIncrementalMarkingIfComplete(
+ "Memory reducer: finalize incremental marking");
+ }
// Re-schedule the timer.
ScheduleTimer(state_.next_gc_start_ms - event.time_ms);
if (FLAG_trace_gc_verbose) {
CHECK_EQ(0, sfi_count);
}
+
+template <typename T>
+static UniqueId MakeUniqueId(const Persistent<T>& p) {
+ return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
+}
+
+
+TEST(Regress519319) {
+ CcTest::InitializeVM();
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ Heap* heap = CcTest::heap();
+ LocalContext context;
+
+ v8::Persistent<Value> parent;
+ v8::Persistent<Value> child;
+
+ parent.Reset(isolate, v8::Object::New(isolate));
+ child.Reset(isolate, v8::Object::New(isolate));
+
+ SimulateFullSpace(heap->old_space());
+ heap->CollectGarbage(OLD_SPACE);
+ {
+ UniqueId id = MakeUniqueId(parent);
+ isolate->SetObjectGroupId(parent, id);
+ isolate->SetReferenceFromGroup(id, child);
+ }
+ // The CollectGarbage call above starts sweeper threads.
+ // The crash will happen if the following two functions
+ // are called before sweeping finishes.
+ heap->StartIncrementalMarking();
+ heap->FinalizeIncrementalMarkingIfComplete("test");
+}
+
+
} // namespace internal
} // namespace v8