Commit 6cbf881d authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

heap: Add deadline to processing ephemeron callbacks

Incremental steps may process ephemerons. When we are at a very deep
stack there's a chance that the hang monitor interrupts us because
InvokeEphemeronCallbacks is taking too long.

Add deadline logic to InvokeEphemeronCallbacks to make the situation
even more unlikely.

Bug: 1058151
Change-Id: Ic0d455097284be83314c1e4dce6e29803bc33d93
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2087391Reviewed-by: default avatarOmer Katz <omerkatz@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#746730}
parent 4aeffa3b
......@@ -261,39 +261,6 @@ void ThreadHeap::MarkNotFullyConstructedObjects(MarkingVisitor* visitor) {
}
}
void ThreadHeap::InvokeEphemeronCallbacks(MarkingVisitor* visitor) {
// Mark any strong pointers that have now become reachable in ephemeron maps.
ThreadHeapStatsCollector::Scope stats_scope(
stats_collector(),
ThreadHeapStatsCollector::kMarkInvokeEphemeronCallbacks);
// We first reiterate over known callbacks from previous iterations.
for (auto& tuple : ephemeron_callbacks_)
tuple.value(visitor, tuple.key);
DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id());
// Then we iterate over the new callbacks found by the marking visitor.
// Callbacks found by the concurrent marking will be flushed eventually
// and then invoked by the mutator thread (in the atomic pause at latest).
while (
!weak_table_worklist_->IsLocalViewEmpty(WorklistTaskId::MutatorThread)) {
// Read ephemeron callbacks from worklist to ephemeron_callbacks_ hashmap.
WeakTableWorklist::View ephemerons_worklist(weak_table_worklist_.get(),
WorklistTaskId::MutatorThread);
WeakTableItem item;
while (ephemerons_worklist.Pop(&item)) {
auto result =
ephemeron_callbacks_.insert(item.base_object_payload, item.callback);
DCHECK(result.is_new_entry ||
result.stored_value->value == item.callback);
if (result.is_new_entry) {
item.callback(visitor, item.base_object_payload);
}
}
}
}
namespace {
template <typename Worklist, typename Callback>
......@@ -319,6 +286,45 @@ bool DrainWorklistWithDeadline(base::TimeTicks deadline,
} // namespace
bool ThreadHeap::InvokeEphemeronCallbacks(MarkingVisitor* visitor,
base::TimeTicks deadline) {
// Mark any strong pointers that have now become reachable in ephemeron maps.
ThreadHeapStatsCollector::Scope stats_scope(
stats_collector(),
ThreadHeapStatsCollector::kMarkInvokeEphemeronCallbacks);
// We first reiterate over known callbacks from previous iterations.
constexpr size_t kDeadlineCheckInterval = 250;
size_t processed_callback_count = 0;
for (auto& tuple : ephemeron_callbacks_) {
tuple.value(visitor, tuple.key);
if (++processed_callback_count == kDeadlineCheckInterval) {
if (deadline <= base::TimeTicks::Now()) {
return false;
}
processed_callback_count = 0;
}
}
DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id());
// Then we iterate over the new callbacks found by the marking visitor.
// Callbacks found by the concurrent marking will be flushed eventually
// and then invoked by the mutator thread (in the atomic pause at latest).
return DrainWorklistWithDeadline(
deadline, weak_table_worklist_.get(),
[this, visitor](const WeakTableItem& item) {
auto result = ephemeron_callbacks_.insert(item.base_object_payload,
item.callback);
DCHECK(result.is_new_entry ||
result.stored_value->value == item.callback);
if (result.is_new_entry) {
item.callback(visitor, item.base_object_payload);
}
},
WorklistTaskId::MutatorThread);
}
bool ThreadHeap::AdvanceMarking(MarkingVisitor* visitor,
base::TimeTicks deadline) {
DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id());
......@@ -390,7 +396,9 @@ bool ThreadHeap::AdvanceMarking(MarkingVisitor* visitor,
break;
}
InvokeEphemeronCallbacks(visitor);
finished = InvokeEphemeronCallbacks(visitor, deadline);
if (!finished)
break;
// Rerun loop if ephemeron processing queued more objects for tracing.
} while (!marking_worklist_->IsLocalViewEmpty(WorklistTaskId::MutatorThread));
......
......@@ -404,7 +404,7 @@ class PLATFORM_EXPORT ThreadHeap {
void DestroyMarkingWorklists(BlinkGC::StackState);
void DestroyCompactionWorklists();
void InvokeEphemeronCallbacks(MarkingVisitor*);
bool InvokeEphemeronCallbacks(MarkingVisitor*, base::TimeTicks);
bool FlushV8References(base::TimeTicks);
......
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