Commit 0f934866 authored by hlopko's avatar hlopko Committed by Commit bot

Introduce api for incremental wrapper tracing

This cl sketches an api for incremental wrapper tracing, but still uses the api
in the stop-the-world fashion. Responsibility to maintain a marking deque is
transfered to the embedder. V8 will still collect wrapper internal fields, but
will send them to the embedder after each incremental gc task. Wrappers must be
sent at latest by the time next oilpan gc runs - so blink can keep all
discovered wrappables alive.

The old api will be cleared after this cl and corresponding blink cl land.

Comments are very welcomed :)

LOG=no
BUG=468240

Review-Url: https://codereview.chromium.org/2032213003
Cr-Commit-Position: refs/heads/master@{#36761}
parent 46a9322e
......@@ -5468,18 +5468,44 @@ enum class MemoryPressureLevel { kNone, kModerate, kCritical };
*/
class V8_EXPORT EmbedderHeapTracer {
public:
enum ForceCompletionAction { FORCE_COMPLETION, DO_NOT_FORCE_COMPLETION };
struct AdvanceTracingActions {
explicit AdvanceTracingActions(ForceCompletionAction force_completion_)
: force_completion(force_completion_) {}
ForceCompletionAction force_completion;
};
/**
* V8 will call this method with internal fields of found wrappers.
* Embedder is expected to store them in it's marking deque and trace
* reachable wrappers from them when asked by AdvanceTracing method.
*/
// TODO(hlopko): Make pure virtual after migration
virtual void RegisterV8References(
const std::vector<std::pair<void*, void*> >& internal_fields) {}
/**
* **Deprecated**
*/
// TODO(hlopko): Remove after migration
virtual void TraceWrappersFrom(
const std::vector<std::pair<void*, void*> >& internal_fields) {}
/**
* V8 will call this method at the beginning of the gc cycle.
*/
virtual void TracePrologue() = 0;
/**
* V8 will call this method with internal fields of a potential wrappers.
* Embedder is expected to trace its heap (synchronously) and call
* PersistentBase::RegisterExternalReference() on all wrappers reachable from
* any of the given wrappers.
* Embedder is expected to trace its heap starting from wrappers reported by
* RegisterV8References method, and call
* PersistentBase::RegisterExternalReference() on all reachable wrappers.
* Embedder is expected to stop tracing by the given deadline.
*
* Returns true if there is still work to do.
*/
virtual void TraceWrappersFrom(
const std::vector<std::pair<void*, void*> >& internal_fields) = 0;
// TODO(hlopko): Make pure virtual after migration
virtual bool AdvanceTracing(double deadline_in_ms,
AdvanceTracingActions actions) {
return false;
}
/**
* V8 will call this method at the end of the gc cycle. Allocation is *not*
* allowed in the TraceEpilogue.
......
......@@ -1628,6 +1628,13 @@ void Heap::Scavenge() {
scavenge_collector_->SelectScavengingVisitorsTable();
if (UsingEmbedderHeapTracer()) {
// Register found wrappers with embedder so he can add them to his marking
// deque and correctly manage the case when v8 scavenger collects the
// wrappers by either keeping wrappables alive, or cleaning marking deque.
mark_compact_collector()->RegisterWrappersWithEmbedderHeapTracer();
}
array_buffer_tracker()->PrepareDiscoveryInNewSpace();
// Flip the semispaces. After flipping, to space is empty, from space has
......
......@@ -2123,8 +2123,10 @@ void MarkCompactCollector::ProcessEphemeralMarking(
bool work_to_do = true;
while (work_to_do) {
if (UsingEmbedderHeapTracer()) {
embedder_heap_tracer()->TraceWrappersFrom(wrappers_to_trace_);
wrappers_to_trace_.clear();
RegisterWrappersWithEmbedderHeapTracer();
embedder_heap_tracer()->AdvanceTracing(
0, EmbedderHeapTracer::AdvanceTracingActions(
EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
}
if (!only_process_harmony_weak_collections) {
isolate()->global_handles()->IterateObjectGroups(
......@@ -2241,6 +2243,15 @@ void MarkCompactCollector::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) {
embedder_heap_tracer_ = tracer;
}
void MarkCompactCollector::RegisterWrappersWithEmbedderHeapTracer() {
DCHECK(UsingEmbedderHeapTracer());
if (wrappers_to_trace_.empty()) {
return;
}
embedder_heap_tracer()->RegisterV8References(wrappers_to_trace_);
wrappers_to_trace_.clear();
}
void MarkCompactCollector::TracePossibleWrapper(JSObject* js_object) {
DCHECK(js_object->WasConstructedFromApiFunction());
if (js_object->GetInternalFieldCount() >= 2 &&
......@@ -2248,7 +2259,7 @@ void MarkCompactCollector::TracePossibleWrapper(JSObject* js_object) {
js_object->GetInternalField(0) != heap_->undefined_value() &&
js_object->GetInternalField(1) != heap_->undefined_value()) {
DCHECK(reinterpret_cast<intptr_t>(js_object->GetInternalField(0)) % 2 == 0);
wrappers_to_trace().push_back(std::pair<void*, void*>(
wrappers_to_trace_.push_back(std::pair<void*, void*>(
reinterpret_cast<void*>(js_object->GetInternalField(0)),
reinterpret_cast<void*>(js_object->GetInternalField(1))));
}
......
......@@ -613,9 +613,7 @@ class MarkCompactCollector {
Sweeper& sweeper() { return sweeper_; }
std::vector<std::pair<void*, void*>>& wrappers_to_trace() {
return wrappers_to_trace_;
}
void RegisterWrappersWithEmbedderHeapTracer();
void SetEmbedderHeapTracer(EmbedderHeapTracer* tracer);
......
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