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() { ...@@ -13,6 +13,7 @@ void LocalEmbedderHeapTracer::TracePrologue() {
if (!InUse()) return; if (!InUse()) return;
CHECK(cached_wrappers_to_trace_.empty()); CHECK(cached_wrappers_to_trace_.empty());
num_v8_marking_deque_was_empty_ = 0;
remote_tracer_->TracePrologue(); remote_tracer_->TracePrologue();
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define V8_HEAP_EMBEDDER_TRACING_H_ #define V8_HEAP_EMBEDDER_TRACING_H_
#include "include/v8.h" #include "include/v8.h"
#include "src/flags.h"
#include "src/globals.h" #include "src/globals.h"
namespace v8 { namespace v8 {
...@@ -17,7 +18,8 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final { ...@@ -17,7 +18,8 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final {
public: public:
typedef std::pair<void*, void*> WrapperInfo; 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; } void SetRemoteTracer(EmbedderHeapTracer* tracer) { remote_tracer_ = tracer; }
bool InUse() { return remote_tracer_ != nullptr; } bool InUse() { return remote_tracer_ != nullptr; }
...@@ -43,11 +45,20 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final { ...@@ -43,11 +45,20 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final {
// are too many of them. // are too many of them.
bool RequiresImmediateWrapperProcessing(); 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: private:
typedef std::vector<WrapperInfo> WrapperCache; typedef std::vector<WrapperInfo> WrapperCache;
EmbedderHeapTracer* remote_tracer_; EmbedderHeapTracer* remote_tracer_;
WrapperCache cached_wrappers_to_trace_; WrapperCache cached_wrappers_to_trace_;
size_t num_v8_marking_deque_was_empty_;
}; };
} // namespace internal } // namespace internal
......
...@@ -4176,19 +4176,18 @@ void Heap::ReduceNewSpaceSize() { ...@@ -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( void Heap::FinalizeIncrementalMarkingIfComplete(
GarbageCollectionReason gc_reason) { GarbageCollectionReason gc_reason) {
if (incremental_marking()->IsMarking() && if (incremental_marking()->IsMarking() &&
(incremental_marking()->IsReadyToOverApproximateWeakClosure() || (incremental_marking()->IsReadyToOverApproximateWeakClosure() ||
(!incremental_marking()->finalize_marking_completed() && (!incremental_marking()->finalize_marking_completed() &&
MarkingDequesAreEmpty()))) { mark_compact_collector()->marking_deque()->IsEmpty() &&
local_embedder_heap_tracer()->ShouldFinalizeIncrementalMarking()))) {
FinalizeIncrementalMarking(gc_reason); 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); CollectAllGarbage(current_gc_flags_, gc_reason);
} }
} }
...@@ -4200,13 +4199,16 @@ bool Heap::TryFinalizeIdleIncrementalMarking( ...@@ -4200,13 +4199,16 @@ bool Heap::TryFinalizeIdleIncrementalMarking(
tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond(); tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond();
if (incremental_marking()->IsReadyToOverApproximateWeakClosure() || if (incremental_marking()->IsReadyToOverApproximateWeakClosure() ||
(!incremental_marking()->finalize_marking_completed() && (!incremental_marking()->finalize_marking_completed() &&
MarkingDequesAreEmpty() && mark_compact_collector()->marking_deque()->IsEmpty() &&
local_embedder_heap_tracer()->ShouldFinalizeIncrementalMarking() &&
gc_idle_time_handler_->ShouldDoOverApproximateWeakClosure( gc_idle_time_handler_->ShouldDoOverApproximateWeakClosure(
idle_time_in_ms))) { idle_time_in_ms))) {
FinalizeIncrementalMarking(gc_reason); FinalizeIncrementalMarking(gc_reason);
return true; return true;
} else if (incremental_marking()->IsComplete() || } else if (incremental_marking()->IsComplete() ||
(MarkingDequesAreEmpty() && (mark_compact_collector()->marking_deque()->IsEmpty() &&
local_embedder_heap_tracer()
->ShouldFinalizeIncrementalMarking() &&
gc_idle_time_handler_->ShouldDoFinalIncrementalMarkCompact( gc_idle_time_handler_->ShouldDoFinalIncrementalMarkCompact(
idle_time_in_ms, size_of_objects, idle_time_in_ms, size_of_objects,
final_incremental_mark_compact_speed_in_bytes_per_ms))) { final_incremental_mark_compact_speed_in_bytes_per_ms))) {
......
...@@ -1627,10 +1627,6 @@ class Heap { ...@@ -1627,10 +1627,6 @@ class Heap {
return current_gc_flags_ & kFinalizeIncrementalMarkingMask; 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(); void PreprocessStackTraces();
// Checks whether a global GC is necessary // Checks whether a global GC is necessary
......
...@@ -32,6 +32,7 @@ IncrementalMarking::IncrementalMarking(Heap* heap) ...@@ -32,6 +32,7 @@ IncrementalMarking::IncrementalMarking(Heap* heap)
was_activated_(false), was_activated_(false),
black_allocation_(false), black_allocation_(false),
finalize_marking_completed_(false), finalize_marking_completed_(false),
trace_wrappers_toggle_(false),
request_type_(NONE), request_type_(NONE),
new_generation_observer_(*this, kAllocatedThreshold), new_generation_observer_(*this, kAllocatedThreshold),
old_generation_observer_(*this, kAllocatedThreshold) {} old_generation_observer_(*this, kAllocatedThreshold) {}
...@@ -1038,8 +1039,27 @@ double IncrementalMarking::AdvanceIncrementalMarking( ...@@ -1038,8 +1039,27 @@ double IncrementalMarking::AdvanceIncrementalMarking(
kStepSizeInMs, kStepSizeInMs,
heap()->tracer()->IncrementalMarkingSpeedInBytesPerMillisecond()); heap()->tracer()->IncrementalMarkingSpeedInBytesPerMillisecond());
const bool incremental_wrapper_tracing =
state_ == MARKING && FLAG_incremental_marking_wrappers &&
heap_->local_embedder_heap_tracer()->InUse();
do { 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 = remaining_time_in_ms =
deadline_in_ms - heap()->MonotonicallyIncreasingTimeInMs(); deadline_in_ms - heap()->MonotonicallyIncreasingTimeInMs();
} while (remaining_time_in_ms >= kStepSizeInMs && !IsComplete() && } while (remaining_time_in_ms >= kStepSizeInMs && !IsComplete() &&
...@@ -1138,42 +1158,26 @@ size_t IncrementalMarking::Step(size_t bytes_to_process, ...@@ -1138,42 +1158,26 @@ size_t IncrementalMarking::Step(size_t bytes_to_process,
size_t bytes_processed = 0; size_t bytes_processed = 0;
if (state_ == MARKING) { if (state_ == MARKING) {
const bool incremental_wrapper_tracing = bytes_processed = ProcessMarkingDeque(bytes_to_process);
FLAG_incremental_marking_wrappers && if (step_origin == StepOrigin::kTask) {
heap_->local_embedder_heap_tracer()->InUse(); bytes_marked_ahead_of_schedule_ += bytes_processed;
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));
} }
if (heap_->mark_compact_collector()->marking_deque()->IsEmpty() && if (heap_->mark_compact_collector()->marking_deque()->IsEmpty()) {
!wrapper_work_left) { if (heap_->local_embedder_heap_tracer()
if (completion == FORCE_COMPLETION || ->ShouldFinalizeIncrementalMarking()) {
IsIdleMarkingDelayCounterLimitReached()) { if (completion == FORCE_COMPLETION ||
if (!finalize_marking_completed_) { IsIdleMarkingDelayCounterLimitReached()) {
FinalizeMarking(action); if (!finalize_marking_completed_) {
FinalizeMarking(action);
} else {
MarkingComplete(action);
}
} else { } else {
MarkingComplete(action); IncrementIdleMarkingDelayCounter();
} }
} else { } else {
IncrementIdleMarkingDelayCounter(); heap_->local_embedder_heap_tracer()->NotifyV8MarkingDequeWasEmpty();
} }
} }
} }
......
...@@ -298,6 +298,7 @@ class IncrementalMarking { ...@@ -298,6 +298,7 @@ class IncrementalMarking {
bool was_activated_; bool was_activated_;
bool black_allocation_; bool black_allocation_;
bool finalize_marking_completed_; bool finalize_marking_completed_;
bool trace_wrappers_toggle_;
GCRequestType request_type_; GCRequestType request_type_;
......
...@@ -2157,7 +2157,8 @@ void MarkCompactCollector::ProcessEphemeralMarking( ...@@ -2157,7 +2157,8 @@ void MarkCompactCollector::ProcessEphemeralMarking(
work_to_do = !marking_deque()->IsEmpty(); work_to_do = !marking_deque()->IsEmpty();
ProcessMarkingDeque<MarkCompactMode::FULL>(); ProcessMarkingDeque<MarkCompactMode::FULL>();
} }
CHECK(heap_->MarkingDequesAreEmpty()); CHECK(marking_deque()->IsEmpty());
CHECK_EQ(0, heap()->local_embedder_heap_tracer()->NumberOfWrappersToTrace());
} }
void MarkCompactCollector::ProcessTopOptimizedFrame(ObjectVisitor* visitor) { 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