Commit 17318bbd authored by mlippautz's avatar mlippautz Committed by Commit bot

[heap] Create a thin wrapper around wrapper tracing in V8 to avoid misuse

BUG=chromium:468240

Review-Url: https://codereview.chromium.org/2576453002
Cr-Commit-Position: refs/heads/master@{#41837}
parent 7e8bd39a
......@@ -1374,6 +1374,8 @@ v8_source_set("v8_base") {
"src/heap/array-buffer-tracker.h",
"src/heap/code-stats.cc",
"src/heap/code-stats.h",
"src/heap/embedder-tracing.cc",
"src/heap/embedder-tracing.h",
"src/heap/gc-idle-time-handler.cc",
"src/heap/gc-idle-time-handler.h",
"src/heap/gc-tracer.cc",
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/heap/embedder-tracing.h"
#include "src/base/logging.h"
namespace v8 {
namespace internal {
void LocalEmbedderHeapTracer::TracePrologue() {
if (!InUse()) return;
CHECK(cached_wrappers_to_trace_.empty());
remote_tracer_->TracePrologue();
}
void LocalEmbedderHeapTracer::TraceEpilogue() {
if (!InUse()) return;
CHECK(cached_wrappers_to_trace_.empty());
remote_tracer_->TraceEpilogue();
}
void LocalEmbedderHeapTracer::AbortTracing() {
if (!InUse()) return;
cached_wrappers_to_trace_.clear();
remote_tracer_->AbortTracing();
}
void LocalEmbedderHeapTracer::EnterFinalPause() {
if (!InUse()) return;
remote_tracer_->EnterFinalPause();
}
bool LocalEmbedderHeapTracer::Trace(
double deadline, EmbedderHeapTracer::AdvanceTracingActions actions) {
if (!InUse()) return false;
RegisterWrappersWithRemoteTracer();
return remote_tracer_->AdvanceTracing(deadline, actions);
}
size_t LocalEmbedderHeapTracer::NumberOfWrappersToTrace() {
return (InUse())
? cached_wrappers_to_trace_.size() +
remote_tracer_->NumberOfWrappersToTrace()
: 0;
}
void LocalEmbedderHeapTracer::RegisterWrappersWithRemoteTracer() {
if (!InUse()) return;
if (cached_wrappers_to_trace_.empty()) {
return;
}
remote_tracer_->RegisterV8References(cached_wrappers_to_trace_);
cached_wrappers_to_trace_.clear();
}
bool LocalEmbedderHeapTracer::RequiresImmediateWrapperProcessing() {
const size_t kTooManyWrappers = 16000;
return cached_wrappers_to_trace_.size() > kTooManyWrappers;
}
} // namespace internal
} // namespace v8
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HEAP_EMBEDDER_TRACING_H_
#define V8_HEAP_EMBEDDER_TRACING_H_
#include "include/v8.h"
#include "src/globals.h"
namespace v8 {
namespace internal {
class Heap;
class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final {
public:
typedef std::pair<void*, void*> WrapperInfo;
LocalEmbedderHeapTracer() : remote_tracer_(nullptr) {}
void SetRemoteTracer(EmbedderHeapTracer* tracer) { remote_tracer_ = tracer; }
bool InUse() { return remote_tracer_ != nullptr; }
void TracePrologue();
void TraceEpilogue();
void AbortTracing();
void EnterFinalPause();
bool Trace(double deadline,
EmbedderHeapTracer::AdvanceTracingActions actions);
size_t NumberOfWrappersToTrace();
size_t NumberOfCachedWrappersToTrace() {
return cached_wrappers_to_trace_.size();
}
void AddWrapperToTrace(WrapperInfo entry) {
cached_wrappers_to_trace_.push_back(entry);
}
void ClearCachedWrappersToTrace() { cached_wrappers_to_trace_.clear(); }
void RegisterWrappersWithRemoteTracer();
// In order to avoid running out of memory we force tracing wrappers if there
// are too many of them.
bool RequiresImmediateWrapperProcessing();
private:
typedef std::vector<WrapperInfo> WrapperCache;
EmbedderHeapTracer* remote_tracer_;
WrapperCache cached_wrappers_to_trace_;
};
} // namespace internal
} // namespace v8
#endif // V8_HEAP_EMBEDDER_TRACING_H_
......@@ -20,6 +20,7 @@
#include "src/global-handles.h"
#include "src/heap/array-buffer-tracker-inl.h"
#include "src/heap/code-stats.h"
#include "src/heap/embedder-tracing.h"
#include "src/heap/gc-idle-time-handler.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/incremental-marking.h"
......@@ -155,7 +156,7 @@ Heap::Heap()
deserialization_complete_(false),
strong_roots_list_(NULL),
heap_iterator_depth_(0),
embedder_heap_tracer_(nullptr),
local_embedder_heap_tracer_(nullptr),
force_oom_(false),
delay_sweeper_tasks_for_testing_(false) {
// Allow build-time customization of the max semispace size. Building
......@@ -1608,12 +1609,7 @@ void Heap::Scavenge() {
scavenge_collector_->SelectScavengingVisitorsTable();
if (UsingEmbedderHeapTracer()) {
// Register found wrappers with embedder so it can add them to its marking
// deque and correctly manage the case when v8 scavenger collects the
// wrappers by either keeping wrappables alive, or cleaning marking deque.
RegisterWrappersWithEmbedderHeapTracer();
}
local_embedder_heap_tracer()->RegisterWrappersWithRemoteTracer();
// Flip the semispaces. After flipping, to space is empty, from space has
// live objects.
......@@ -4182,9 +4178,7 @@ void Heap::ReduceNewSpaceSize() {
bool Heap::MarkingDequesAreEmpty() {
return mark_compact_collector()->marking_deque()->IsEmpty() &&
(!UsingEmbedderHeapTracer() ||
(wrappers_to_trace() == 0 &&
embedder_heap_tracer()->NumberOfWrappersToTrace() == 0));
local_embedder_heap_tracer()->NumberOfWrappersToTrace() == 0;
}
void Heap::FinalizeIncrementalMarkingIfComplete(
......@@ -5499,6 +5493,7 @@ bool Heap::SetUp() {
dead_object_stats_ = new ObjectStats(this);
}
scavenge_job_ = new ScavengeJob();
local_embedder_heap_tracer_ = new LocalEmbedderHeapTracer();
LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity()));
LOG(isolate_, IntPtrTEvent("heap-available", Available()));
......@@ -5574,16 +5569,7 @@ void Heap::NotifyDeserializationComplete() {
void Heap::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) {
DCHECK_EQ(gc_state_, HeapState::NOT_IN_GC);
embedder_heap_tracer_ = tracer;
}
void Heap::RegisterWrappersWithEmbedderHeapTracer() {
DCHECK(UsingEmbedderHeapTracer());
if (wrappers_to_trace_.empty()) {
return;
}
embedder_heap_tracer()->RegisterV8References(wrappers_to_trace_);
wrappers_to_trace_.clear();
local_embedder_heap_tracer()->SetRemoteTracer(tracer);
}
void Heap::TracePossibleWrapper(JSObject* js_object) {
......@@ -5593,17 +5579,12 @@ void Heap::TracePossibleWrapper(JSObject* js_object) {
js_object->GetInternalField(0) != undefined_value() &&
js_object->GetInternalField(1) != undefined_value()) {
DCHECK(reinterpret_cast<intptr_t>(js_object->GetInternalField(0)) % 2 == 0);
wrappers_to_trace_.push_back(std::pair<void*, void*>(
local_embedder_heap_tracer()->AddWrapperToTrace(std::pair<void*, void*>(
reinterpret_cast<void*>(js_object->GetInternalField(0)),
reinterpret_cast<void*>(js_object->GetInternalField(1))));
}
}
bool Heap::RequiresImmediateWrapperProcessing() {
const size_t kTooManyWrappers = 16000;
return wrappers_to_trace_.size() > kTooManyWrappers;
}
void Heap::RegisterExternallyReferencedObject(Object** object) {
HeapObject* heap_object = HeapObject::cast(*object);
DCHECK(Contains(heap_object));
......@@ -5680,6 +5661,9 @@ void Heap::TearDown() {
dead_object_stats_ = nullptr;
}
delete local_embedder_heap_tracer_;
local_embedder_heap_tracer_ = nullptr;
delete scavenge_job_;
scavenge_job_ = nullptr;
......
......@@ -330,6 +330,7 @@ class HeapObjectsFilter;
class HeapStats;
class HistogramTimer;
class Isolate;
class LocalEmbedderHeapTracer;
class MemoryAllocator;
class MemoryReducer;
class ObjectIterator;
......@@ -1204,25 +1205,13 @@ class Heap {
// Embedder heap tracer support. =============================================
// ===========================================================================
LocalEmbedderHeapTracer* local_embedder_heap_tracer() {
return local_embedder_heap_tracer_;
}
void SetEmbedderHeapTracer(EmbedderHeapTracer* tracer);
bool UsingEmbedderHeapTracer() { return embedder_heap_tracer() != nullptr; }
void TracePossibleWrapper(JSObject* js_object);
void RegisterExternallyReferencedObject(Object** object);
void RegisterWrappersWithEmbedderHeapTracer();
// In order to avoid running out of memory we force tracing wrappers if there
// are too many of them.
bool RequiresImmediateWrapperProcessing();
EmbedderHeapTracer* embedder_heap_tracer() { return embedder_heap_tracer_; }
size_t wrappers_to_trace() { return wrappers_to_trace_.size(); }
void clear_wrappers_to_trace() { wrappers_to_trace_.clear(); }
// ===========================================================================
// External string table API. ================================================
// ===========================================================================
......@@ -2350,8 +2339,7 @@ class Heap {
// The depth of HeapIterator nestings.
int heap_iterator_depth_;
EmbedderHeapTracer* embedder_heap_tracer_;
std::vector<std::pair<void*, void*>> wrappers_to_trace_;
LocalEmbedderHeapTracer* local_embedder_heap_tracer_;
// Used for testing purposes.
bool force_oom_;
......
......@@ -524,10 +524,10 @@ void IncrementalMarking::StartMarking() {
state_ = MARKING;
if (heap_->UsingEmbedderHeapTracer()) {
{
TRACE_GC(heap()->tracer(),
GCTracer::Scope::MC_INCREMENTAL_WRAPPER_PROLOGUE);
heap_->embedder_heap_tracer()->TracePrologue();
heap_->local_embedder_heap_tracer()->TracePrologue();
}
RecordWriteStub::Mode mode = is_compacting_
......@@ -603,7 +603,7 @@ void IncrementalMarking::MarkObjectGroups() {
TRACE_GC(heap_->tracer(),
GCTracer::Scope::MC_INCREMENTAL_FINALIZE_OBJECT_GROUPING);
DCHECK(!heap_->UsingEmbedderHeapTracer());
DCHECK(!heap_->local_embedder_heap_tracer()->InUse());
DCHECK(!finalize_marking_completed_);
DCHECK(IsMarking());
......@@ -736,7 +736,7 @@ void IncrementalMarking::FinalizeIncrementally() {
// 4) Remove weak cell with live values from the list of weak cells, they
// do not need processing during GC.
MarkRoots();
if (!heap_->UsingEmbedderHeapTracer()) {
if (!heap_->local_embedder_heap_tracer()->InUse()) {
MarkObjectGroups();
}
if (incremental_marking_finalization_rounds_ == 0) {
......@@ -750,7 +750,8 @@ void IncrementalMarking::FinalizeIncrementally() {
abs(old_marking_deque_top -
heap_->mark_compact_collector()->marking_deque()->top());
marking_progress += static_cast<int>(heap_->wrappers_to_trace());
marking_progress += static_cast<int>(
heap_->local_embedder_heap_tracer()->NumberOfCachedWrappersToTrace());
double end = heap_->MonotonicallyIncreasingTimeInMs();
double delta = end - start;
......@@ -1134,10 +1135,12 @@ 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_->UsingEmbedderHeapTracer();
FLAG_incremental_marking_wrappers &&
heap_->local_embedder_heap_tracer()->InUse();
const bool process_wrappers =
incremental_wrapper_tracing &&
(heap_->RequiresImmediateWrapperProcessing() ||
(heap_->local_embedder_heap_tracer()
->RequiresImmediateWrapperProcessing() ||
heap_->mark_compact_collector()->marking_deque()->IsEmpty());
bool wrapper_work_left = incremental_wrapper_tracing;
if (!process_wrappers) {
......@@ -1150,8 +1153,7 @@ size_t IncrementalMarking::Step(size_t bytes_to_process,
heap_->MonotonicallyIncreasingTimeInMs() + kStepSizeInMs;
TRACE_GC(heap()->tracer(),
GCTracer::Scope::MC_INCREMENTAL_WRAPPER_TRACING);
heap_->RegisterWrappersWithEmbedderHeapTracer();
wrapper_work_left = heap_->embedder_heap_tracer()->AdvanceTracing(
wrapper_work_left = heap_->local_embedder_heap_tracer()->Trace(
wrapper_deadline, EmbedderHeapTracer::AdvanceTracingActions(
EmbedderHeapTracer::ForceCompletionAction::
DO_NOT_FORCE_COMPLETION));
......
......@@ -796,24 +796,17 @@ void MarkCompactCollector::Prepare() {
AbortWeakCells();
AbortTransitionArrays();
AbortCompaction();
if (heap_->UsingEmbedderHeapTracer()) {
heap_->embedder_heap_tracer()->AbortTracing();
heap_->clear_wrappers_to_trace();
}
heap_->local_embedder_heap_tracer()->AbortTracing();
marking_deque()->Clear();
was_marked_incrementally_ = false;
}
if (!was_marked_incrementally_) {
if (heap_->UsingEmbedderHeapTracer()) {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_PROLOGUE);
heap_->embedder_heap_tracer()->TracePrologue();
}
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_PROLOGUE);
heap_->local_embedder_heap_tracer()->TracePrologue();
}
if (heap_->UsingEmbedderHeapTracer()) {
heap_->embedder_heap_tracer()->EnterFinalPause();
}
heap_->local_embedder_heap_tracer()->EnterFinalPause();
// Don't start compaction if we are in the middle of incremental
// marking cycle. We did not collect any slots.
......@@ -2141,10 +2134,9 @@ void MarkCompactCollector::ProcessEphemeralMarking(
bool work_to_do = true;
while (work_to_do) {
if (!only_process_harmony_weak_collections) {
if (heap_->UsingEmbedderHeapTracer()) {
if (heap_->local_embedder_heap_tracer()->InUse()) {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_TRACING);
heap_->RegisterWrappersWithEmbedderHeapTracer();
heap_->embedder_heap_tracer()->AdvanceTracing(
heap_->local_embedder_heap_tracer()->Trace(
0,
EmbedderHeapTracer::AdvanceTracingActions(
EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
......@@ -2159,7 +2151,7 @@ void MarkCompactCollector::ProcessEphemeralMarking(
// discovering new objects reachable from weak roots (that have been made
// strong). This is a limitation of not having a separate handle type
// that doesn't require zapping before this phase. See crbug.com/668060.
heap_->clear_wrappers_to_trace();
heap_->local_embedder_heap_tracer()->ClearCachedWrappersToTrace();
}
ProcessWeakCollections();
work_to_do = !marking_deque()->IsEmpty();
......@@ -2502,9 +2494,9 @@ void MarkCompactCollector::MarkLiveObjects() {
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_HARMONY);
ProcessEphemeralMarking(&root_visitor, true);
if (heap_->UsingEmbedderHeapTracer()) {
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_EPILOGUE);
heap()->embedder_heap_tracer()->TraceEpilogue();
heap()->local_embedder_heap_tracer()->TraceEpilogue();
}
}
}
......
......@@ -6,6 +6,7 @@
#define V8_OBJECTS_VISITING_H_
#include "src/allocation.h"
#include "src/heap/embedder-tracing.h"
#include "src/heap/heap.h"
#include "src/heap/spaces.h"
#include "src/layout-descriptor.h"
......@@ -424,7 +425,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
private:
INLINE(static void TracePossibleWrapper(HeapObject* object)) {
if (object->GetHeap()->UsingEmbedderHeapTracer()) {
if (object->GetHeap()->local_embedder_heap_tracer()->InUse()) {
DCHECK(object->IsJSObject());
object->GetHeap()->TracePossibleWrapper(JSObject::cast(object));
}
......
......@@ -913,6 +913,8 @@
'heap/array-buffer-tracker.h',
'heap/code-stats.cc',
'heap/code-stats.h',
'heap/embedder-tracing.cc',
'heap/embedder-tracing.h',
'heap/memory-reducer.cc',
'heap/memory-reducer.h',
'heap/gc-idle-time-handler.cc',
......
......@@ -93,6 +93,7 @@ v8_executable("unittests") {
"eh-frame-iterator-unittest.cc",
"eh-frame-writer-unittest.cc",
"heap/bitmap-unittest.cc",
"heap/embedder-tracing-unittest.cc",
"heap/gc-idle-time-handler-unittest.cc",
"heap/gc-tracer-unittest.cc",
"heap/heap-unittest.cc",
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/heap/embedder-tracing.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
namespace heap {
using testing::StrictMock;
using testing::_;
using testing::Return;
using v8::EmbedderHeapTracer;
using v8::internal::LocalEmbedderHeapTracer;
namespace {
LocalEmbedderHeapTracer::WrapperInfo CreateWrapperInfo() {
return LocalEmbedderHeapTracer::WrapperInfo(nullptr, nullptr);
}
} // namespace
class MockEmbedderHeapTracer : public EmbedderHeapTracer {
public:
MOCK_METHOD0(TracePrologue, void());
MOCK_METHOD0(TraceEpilogue, void());
MOCK_METHOD0(AbortTracing, void());
MOCK_METHOD0(EnterFinalPause, void());
MOCK_METHOD0(NumberOfWrappersToTrace, size_t());
MOCK_METHOD1(RegisterV8References,
void(const std::vector<std::pair<void*, void*> >&));
MOCK_METHOD2(AdvanceTracing,
bool(double deadline_in_ms, AdvanceTracingActions actions));
};
TEST(LocalEmbedderHeapTracer, InUse) {
LocalEmbedderHeapTracer local_tracer;
MockEmbedderHeapTracer mock_remote_tracer;
local_tracer.SetRemoteTracer(&mock_remote_tracer);
EXPECT_TRUE(local_tracer.InUse());
}
TEST(LocalEmbedderHeapTracer, NoRemoteTracer) {
LocalEmbedderHeapTracer local_tracer;
// We should be able to call all functions without a remote tracer being
// attached.
EXPECT_FALSE(local_tracer.InUse());
local_tracer.TracePrologue();
local_tracer.EnterFinalPause();
bool more_work = local_tracer.Trace(
0, EmbedderHeapTracer::AdvanceTracingActions(
EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
EXPECT_FALSE(more_work);
local_tracer.TraceEpilogue();
}
TEST(LocalEmbedderHeapTracer, TracePrologueForwards) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer;
local_tracer.SetRemoteTracer(&remote_tracer);
EXPECT_CALL(remote_tracer, TracePrologue());
local_tracer.TracePrologue();
}
TEST(LocalEmbedderHeapTracer, TraceEpilogueForwards) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer;
local_tracer.SetRemoteTracer(&remote_tracer);
EXPECT_CALL(remote_tracer, TraceEpilogue());
local_tracer.TraceEpilogue();
}
TEST(LocalEmbedderHeapTracer, AbortTracingForwards) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer;
local_tracer.SetRemoteTracer(&remote_tracer);
EXPECT_CALL(remote_tracer, AbortTracing());
local_tracer.AbortTracing();
}
TEST(LocalEmbedderHeapTracer, AbortTracingClearsCachedWrappers) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer;
local_tracer.SetRemoteTracer(&remote_tracer);
local_tracer.AddWrapperToTrace(CreateWrapperInfo());
EXPECT_CALL(remote_tracer, AbortTracing());
local_tracer.AbortTracing();
EXPECT_EQ(0u, local_tracer.NumberOfCachedWrappersToTrace());
}
TEST(LocalEmbedderHeapTracer, EnterFinalPauseForwards) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer;
local_tracer.SetRemoteTracer(&remote_tracer);
EXPECT_CALL(remote_tracer, EnterFinalPause());
local_tracer.EnterFinalPause();
}
TEST(LocalEmbedderHeapTracer, NumberOfWrappersToTraceIncludesRemote) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer;
local_tracer.SetRemoteTracer(&remote_tracer);
EXPECT_CALL(remote_tracer, NumberOfWrappersToTrace());
local_tracer.NumberOfWrappersToTrace();
}
TEST(LocalEmbedderHeapTracer, NumberOfCachedWrappersToTraceExcludesRemote) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer;
local_tracer.SetRemoteTracer(&remote_tracer);
local_tracer.NumberOfCachedWrappersToTrace();
}
TEST(LocalEmbedderHeapTracer, RegisterWrappersWithRemoteTracer) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer;
local_tracer.SetRemoteTracer(&remote_tracer);
local_tracer.AddWrapperToTrace(CreateWrapperInfo());
EXPECT_EQ(1u, local_tracer.NumberOfCachedWrappersToTrace());
EXPECT_CALL(remote_tracer, RegisterV8References(_));
local_tracer.RegisterWrappersWithRemoteTracer();
EXPECT_EQ(0u, local_tracer.NumberOfCachedWrappersToTrace());
EXPECT_CALL(remote_tracer, NumberOfWrappersToTrace()).WillOnce(Return(1));
EXPECT_EQ(1u, local_tracer.NumberOfWrappersToTrace());
}
TEST(LocalEmbedderHeapTracer, TraceFinishes) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer;
local_tracer.SetRemoteTracer(&remote_tracer);
local_tracer.AddWrapperToTrace(CreateWrapperInfo());
EXPECT_EQ(1u, local_tracer.NumberOfCachedWrappersToTrace());
EXPECT_CALL(remote_tracer, RegisterV8References(_));
EXPECT_CALL(remote_tracer, AdvanceTracing(0, _)).WillOnce(Return(false));
EXPECT_EQ(
false,
local_tracer.Trace(
0, EmbedderHeapTracer::AdvanceTracingActions(
EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION)));
EXPECT_EQ(0u, local_tracer.NumberOfCachedWrappersToTrace());
}
TEST(LocalEmbedderHeapTracer, TraceDoesNotFinish) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer;
local_tracer.SetRemoteTracer(&remote_tracer);
local_tracer.AddWrapperToTrace(CreateWrapperInfo());
EXPECT_EQ(1u, local_tracer.NumberOfCachedWrappersToTrace());
EXPECT_CALL(remote_tracer, RegisterV8References(_));
EXPECT_CALL(remote_tracer, AdvanceTracing(0, _)).WillOnce(Return(true));
EXPECT_EQ(
true,
local_tracer.Trace(
0, EmbedderHeapTracer::AdvanceTracingActions(
EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION)));
EXPECT_EQ(0u, local_tracer.NumberOfCachedWrappersToTrace());
}
} // namespace heap
} // namespace internal
} // namespace v8
......@@ -110,6 +110,7 @@
'libplatform/task-queue-unittest.cc',
'libplatform/worker-thread-unittest.cc',
'heap/bitmap-unittest.cc',
'heap/embedder-tracing-unittest.cc',
'heap/gc-idle-time-handler-unittest.cc',
'heap/gc-tracer-unittest.cc',
'heap/marking-unittest.cc',
......
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