Commit fb8b3bcc authored by mlippautz's avatar mlippautz Committed by Commit bot

Reland "[heap] Ensure progress when incrementally marking wrappers"

1) Alternate between processing v8 and wrappers
2) Once v8 is empty, try 3 rounds of finding the fixpoint between v8 and wrappers
3) After that, finalize once v8 marking deque is empty again

Reland fixed: Toggle needs to be IncrementalMarking global as we need to properly
alternate tracing v8 and wrappers.

BUG=chromium:468240, chromium:668164

Review-Url: https://codereview.chromium.org/2599283002
Cr-Commit-Position: refs/heads/master@{#41940}
parent 6236060c
......@@ -13,6 +13,7 @@ void LocalEmbedderHeapTracer::TracePrologue() {
if (!InUse()) return;
CHECK(cached_wrappers_to_trace_.empty());
num_v8_marking_deque_was_empty_ = 0;
remote_tracer_->TracePrologue();
}
......
......@@ -6,6 +6,7 @@
#define V8_HEAP_EMBEDDER_TRACING_H_
#include "include/v8.h"
#include "src/flags.h"
#include "src/globals.h"
namespace v8 {
......@@ -17,7 +18,8 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final {
public:
typedef std::pair<void*, void*> WrapperInfo;
LocalEmbedderHeapTracer() : remote_tracer_(nullptr) {}
LocalEmbedderHeapTracer()
: remote_tracer_(nullptr), num_v8_marking_deque_was_empty_(0) {}
void SetRemoteTracer(EmbedderHeapTracer* tracer) { remote_tracer_ = tracer; }
bool InUse() { return remote_tracer_ != nullptr; }
......@@ -43,11 +45,20 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final {
// are too many of them.
bool RequiresImmediateWrapperProcessing();
void NotifyV8MarkingDequeWasEmpty() { num_v8_marking_deque_was_empty_++; }
bool ShouldFinalizeIncrementalMarking() {
static const size_t kMaxIncrementalFixpointRounds = 3;
return !FLAG_incremental_marking_wrappers || !InUse() ||
NumberOfWrappersToTrace() == 0 ||
num_v8_marking_deque_was_empty_ > kMaxIncrementalFixpointRounds;
}
private:
typedef std::vector<WrapperInfo> WrapperCache;
EmbedderHeapTracer* remote_tracer_;
WrapperCache cached_wrappers_to_trace_;
size_t num_v8_marking_deque_was_empty_;
};
} // namespace internal
......
......@@ -4176,19 +4176,18 @@ void Heap::ReduceNewSpaceSize() {
}
}
bool Heap::MarkingDequesAreEmpty() {
return mark_compact_collector()->marking_deque()->IsEmpty() &&
local_embedder_heap_tracer()->NumberOfWrappersToTrace() == 0;
}
void Heap::FinalizeIncrementalMarkingIfComplete(
GarbageCollectionReason gc_reason) {
if (incremental_marking()->IsMarking() &&
(incremental_marking()->IsReadyToOverApproximateWeakClosure() ||
(!incremental_marking()->finalize_marking_completed() &&
MarkingDequesAreEmpty()))) {
mark_compact_collector()->marking_deque()->IsEmpty() &&
local_embedder_heap_tracer()->ShouldFinalizeIncrementalMarking()))) {
FinalizeIncrementalMarking(gc_reason);
} else if (incremental_marking()->IsComplete() || MarkingDequesAreEmpty()) {
} else if (incremental_marking()->IsComplete() ||
(mark_compact_collector()->marking_deque()->IsEmpty() &&
local_embedder_heap_tracer()
->ShouldFinalizeIncrementalMarking())) {
CollectAllGarbage(current_gc_flags_, gc_reason);
}
}
......@@ -4200,13 +4199,16 @@ bool Heap::TryFinalizeIdleIncrementalMarking(
tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond();
if (incremental_marking()->IsReadyToOverApproximateWeakClosure() ||
(!incremental_marking()->finalize_marking_completed() &&
MarkingDequesAreEmpty() &&
mark_compact_collector()->marking_deque()->IsEmpty() &&
local_embedder_heap_tracer()->ShouldFinalizeIncrementalMarking() &&
gc_idle_time_handler_->ShouldDoOverApproximateWeakClosure(
idle_time_in_ms))) {
FinalizeIncrementalMarking(gc_reason);
return true;
} else if (incremental_marking()->IsComplete() ||
(MarkingDequesAreEmpty() &&
(mark_compact_collector()->marking_deque()->IsEmpty() &&
local_embedder_heap_tracer()
->ShouldFinalizeIncrementalMarking() &&
gc_idle_time_handler_->ShouldDoFinalIncrementalMarkCompact(
idle_time_in_ms, size_of_objects,
final_incremental_mark_compact_speed_in_bytes_per_ms))) {
......
......@@ -1627,10 +1627,6 @@ class Heap {
return current_gc_flags_ & kFinalizeIncrementalMarkingMask;
}
// Checks whether both, the internal marking deque, and the embedder provided
// one are empty. Avoid in fast path as it potentially calls through the API.
bool MarkingDequesAreEmpty();
void PreprocessStackTraces();
// Checks whether a global GC is necessary
......
......@@ -32,6 +32,7 @@ IncrementalMarking::IncrementalMarking(Heap* heap)
was_activated_(false),
black_allocation_(false),
finalize_marking_completed_(false),
trace_wrappers_toggle_(false),
request_type_(NONE),
new_generation_observer_(*this, kAllocatedThreshold),
old_generation_observer_(*this, kAllocatedThreshold) {}
......@@ -1038,8 +1039,27 @@ double IncrementalMarking::AdvanceIncrementalMarking(
kStepSizeInMs,
heap()->tracer()->IncrementalMarkingSpeedInBytesPerMillisecond());
const bool incremental_wrapper_tracing =
state_ == MARKING && FLAG_incremental_marking_wrappers &&
heap_->local_embedder_heap_tracer()->InUse();
do {
Step(step_size_in_bytes, completion_action, force_completion, step_origin);
if (incremental_wrapper_tracing && trace_wrappers_toggle_) {
TRACE_GC(heap()->tracer(),
GCTracer::Scope::MC_INCREMENTAL_WRAPPER_TRACING);
const double wrapper_deadline =
heap_->MonotonicallyIncreasingTimeInMs() + kStepSizeInMs;
if (!heap_->local_embedder_heap_tracer()
->ShouldFinalizeIncrementalMarking()) {
heap_->local_embedder_heap_tracer()->Trace(
wrapper_deadline, EmbedderHeapTracer::AdvanceTracingActions(
EmbedderHeapTracer::ForceCompletionAction::
DO_NOT_FORCE_COMPLETION));
}
} else {
Step(step_size_in_bytes, completion_action, force_completion,
step_origin);
}
trace_wrappers_toggle_ = !trace_wrappers_toggle_;
remaining_time_in_ms =
deadline_in_ms - heap()->MonotonicallyIncreasingTimeInMs();
} while (remaining_time_in_ms >= kStepSizeInMs && !IsComplete() &&
......@@ -1138,42 +1158,26 @@ size_t IncrementalMarking::Step(size_t bytes_to_process,
size_t bytes_processed = 0;
if (state_ == MARKING) {
const bool incremental_wrapper_tracing =
FLAG_incremental_marking_wrappers &&
heap_->local_embedder_heap_tracer()->InUse();
const bool process_wrappers =
incremental_wrapper_tracing &&
(heap_->local_embedder_heap_tracer()
->RequiresImmediateWrapperProcessing() ||
heap_->mark_compact_collector()->marking_deque()->IsEmpty());
bool wrapper_work_left = incremental_wrapper_tracing;
if (!process_wrappers) {
bytes_processed = ProcessMarkingDeque(bytes_to_process);
if (step_origin == StepOrigin::kTask) {
bytes_marked_ahead_of_schedule_ += bytes_processed;
}
} else {
const double wrapper_deadline =
heap_->MonotonicallyIncreasingTimeInMs() + kStepSizeInMs;
TRACE_GC(heap()->tracer(),
GCTracer::Scope::MC_INCREMENTAL_WRAPPER_TRACING);
wrapper_work_left = heap_->local_embedder_heap_tracer()->Trace(
wrapper_deadline, EmbedderHeapTracer::AdvanceTracingActions(
EmbedderHeapTracer::ForceCompletionAction::
DO_NOT_FORCE_COMPLETION));
bytes_processed = ProcessMarkingDeque(bytes_to_process);
if (step_origin == StepOrigin::kTask) {
bytes_marked_ahead_of_schedule_ += bytes_processed;
}
if (heap_->mark_compact_collector()->marking_deque()->IsEmpty() &&
!wrapper_work_left) {
if (completion == FORCE_COMPLETION ||
IsIdleMarkingDelayCounterLimitReached()) {
if (!finalize_marking_completed_) {
FinalizeMarking(action);
if (heap_->mark_compact_collector()->marking_deque()->IsEmpty()) {
if (heap_->local_embedder_heap_tracer()
->ShouldFinalizeIncrementalMarking()) {
if (completion == FORCE_COMPLETION ||
IsIdleMarkingDelayCounterLimitReached()) {
if (!finalize_marking_completed_) {
FinalizeMarking(action);
} else {
MarkingComplete(action);
}
} else {
MarkingComplete(action);
IncrementIdleMarkingDelayCounter();
}
} else {
IncrementIdleMarkingDelayCounter();
heap_->local_embedder_heap_tracer()->NotifyV8MarkingDequeWasEmpty();
}
}
}
......
......@@ -298,6 +298,7 @@ class IncrementalMarking {
bool was_activated_;
bool black_allocation_;
bool finalize_marking_completed_;
bool trace_wrappers_toggle_;
GCRequestType request_type_;
......
......@@ -2157,7 +2157,8 @@ void MarkCompactCollector::ProcessEphemeralMarking(
work_to_do = !marking_deque()->IsEmpty();
ProcessMarkingDeque<MarkCompactMode::FULL>();
}
CHECK(heap_->MarkingDequesAreEmpty());
CHECK(marking_deque()->IsEmpty());
CHECK_EQ(0, heap()->local_embedder_heap_tracer()->NumberOfWrappersToTrace());
}
void MarkCompactCollector::ProcessTopOptimizedFrame(ObjectVisitor* visitor) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment