Commit 8de19ddb authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

[unified-heap] Add finalization trigger

Allows embedders using the EmbedderHeapTracer to synchronously finalize
an already running garbage collection

Bug: chromium:843903
Tbr: ulan@chromium.org
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Change-Id: Iea01451ea2c1204c34dc7904732abae6b63e1704
Reviewed-on: https://chromium-review.googlesource.com/1128971
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarHannes Payer <hpayer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54378}
parent 0454f94b
...@@ -145,6 +145,7 @@ class DeferredHandles; ...@@ -145,6 +145,7 @@ class DeferredHandles;
class Heap; class Heap;
class HeapObject; class HeapObject;
class Isolate; class Isolate;
class LocalEmbedderHeapTracer;
class Object; class Object;
struct ScriptStreamingData; struct ScriptStreamingData;
template<typename T> class CustomArguments; template<typename T> class CustomArguments;
...@@ -7065,6 +7066,23 @@ class V8_EXPORT EmbedderHeapTracer { ...@@ -7065,6 +7066,23 @@ class V8_EXPORT EmbedderHeapTracer {
*/ */
virtual void AbortTracing() = 0; virtual void AbortTracing() = 0;
/*
* Called by the embedder to request immediaet finalization of the currently
* running tracing phase that has been started with TracePrologue and not
* yet finished with TraceEpilogue.
*
* Will be a noop when currently not in tracing.
*
* This is an experimental feature.
*/
void FinalizeTracing();
/*
* Returns the v8::Isolate this tracer is attached too and |nullptr| if it
* is not attached to any v8::Isolate.
*/
v8::Isolate* isolate() const { return isolate_; }
/** /**
* Returns the number of wrappers that are still to be traced by the embedder. * Returns the number of wrappers that are still to be traced by the embedder.
*/ */
...@@ -7073,6 +7091,10 @@ class V8_EXPORT EmbedderHeapTracer { ...@@ -7073,6 +7091,10 @@ class V8_EXPORT EmbedderHeapTracer {
protected: protected:
virtual ~EmbedderHeapTracer() = default; virtual ~EmbedderHeapTracer() = default;
v8::Isolate* isolate_ = nullptr;
friend class internal::LocalEmbedderHeapTracer;
}; };
/** /**
......
...@@ -10636,6 +10636,16 @@ void Testing::DeoptimizeAll(Isolate* isolate) { ...@@ -10636,6 +10636,16 @@ void Testing::DeoptimizeAll(Isolate* isolate) {
i::Deoptimizer::DeoptimizeAll(i_isolate); i::Deoptimizer::DeoptimizeAll(i_isolate);
} }
void EmbedderHeapTracer::FinalizeTracing() {
if (isolate_) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(isolate_);
if (isolate->heap()->incremental_marking()->IsMarking()) {
isolate->heap()->CollectAllGarbage(
i::Heap::kNoGCFlags, i::GarbageCollectionReason::kExternalFinalize,
kNoGCCallbackFlags);
}
}
}
namespace internal { namespace internal {
......
...@@ -18,10 +18,23 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final { ...@@ -18,10 +18,23 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final {
public: public:
typedef std::pair<void*, void*> WrapperInfo; typedef std::pair<void*, void*> WrapperInfo;
LocalEmbedderHeapTracer() explicit LocalEmbedderHeapTracer(Isolate* isolate)
: remote_tracer_(nullptr), num_v8_marking_worklist_was_empty_(0) {} : isolate_(isolate),
remote_tracer_(nullptr),
num_v8_marking_worklist_was_empty_(0) {}
~LocalEmbedderHeapTracer() {
if (remote_tracer_) remote_tracer_->isolate_ = nullptr;
}
void SetRemoteTracer(EmbedderHeapTracer* tracer) {
if (remote_tracer_) remote_tracer_->isolate_ = nullptr;
remote_tracer_ = tracer;
if (remote_tracer_)
remote_tracer_->isolate_ = reinterpret_cast<v8::Isolate*>(isolate_);
}
void SetRemoteTracer(EmbedderHeapTracer* tracer) { remote_tracer_ = tracer; }
bool InUse() { return remote_tracer_ != nullptr; } bool InUse() { return remote_tracer_ != nullptr; }
void TracePrologue(); void TracePrologue();
...@@ -58,6 +71,7 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final { ...@@ -58,6 +71,7 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final {
private: private:
typedef std::vector<WrapperInfo> WrapperCache; typedef std::vector<WrapperInfo> WrapperCache;
Isolate* const isolate_;
EmbedderHeapTracer* remote_tracer_; EmbedderHeapTracer* remote_tracer_;
WrapperCache cached_wrappers_to_trace_; WrapperCache cached_wrappers_to_trace_;
size_t num_v8_marking_worklist_was_empty_; size_t num_v8_marking_worklist_was_empty_;
......
...@@ -3664,6 +3664,8 @@ const char* Heap::GarbageCollectionReasonToString( ...@@ -3664,6 +3664,8 @@ const char* Heap::GarbageCollectionReasonToString(
return "snapshot creator"; return "snapshot creator";
case GarbageCollectionReason::kTesting: case GarbageCollectionReason::kTesting:
return "testing"; return "testing";
case GarbageCollectionReason::kExternalFinalize:
return "external finalize";
case GarbageCollectionReason::kUnknown: case GarbageCollectionReason::kUnknown:
return "unknown"; return "unknown";
} }
...@@ -4680,7 +4682,7 @@ void Heap::SetUp() { ...@@ -4680,7 +4682,7 @@ void Heap::SetUp() {
dead_object_stats_ = new ObjectStats(this); dead_object_stats_ = new ObjectStats(this);
} }
scavenge_job_ = new ScavengeJob(); scavenge_job_ = new ScavengeJob();
local_embedder_heap_tracer_ = new LocalEmbedderHeapTracer(); local_embedder_heap_tracer_ = new LocalEmbedderHeapTracer(isolate());
LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity())); LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity()));
LOG(isolate_, IntPtrTEvent("heap-available", Available())); LOG(isolate_, IntPtrTEvent("heap-available", Available()));
......
...@@ -242,7 +242,8 @@ enum class GarbageCollectionReason { ...@@ -242,7 +242,8 @@ enum class GarbageCollectionReason {
kRuntime = 18, kRuntime = 18,
kSamplingProfiler = 19, kSamplingProfiler = 19,
kSnapshotCreator = 20, kSnapshotCreator = 20,
kTesting = 21 kTesting = 21,
kExternalFinalize = 22
// If you add new items here, then update the incremental_marking_reason, // If you add new items here, then update the incremental_marking_reason,
// mark_compact_reason, and scavenge_reason counters in counters.h. // mark_compact_reason, and scavenge_reason counters in counters.h.
// Also update src/tools/metrics/histograms/histograms.xml in chromium. // Also update src/tools/metrics/histograms/histograms.xml in chromium.
...@@ -913,14 +914,14 @@ class Heap { ...@@ -913,14 +914,14 @@ class Heap {
// Performs garbage collection operation. // Performs garbage collection operation.
// Returns whether there is a chance that another major GC could // Returns whether there is a chance that another major GC could
// collect more garbage. // collect more garbage.
bool CollectGarbage( V8_EXPORT_PRIVATE bool CollectGarbage(
AllocationSpace space, GarbageCollectionReason gc_reason, AllocationSpace space, GarbageCollectionReason gc_reason,
const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags); const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
// Performs a full garbage collection. If (flags & kMakeHeapIterableMask) is // Performs a full garbage collection. If (flags & kMakeHeapIterableMask) is
// non-zero, then the slower precise sweeper is used, which leaves the heap // non-zero, then the slower precise sweeper is used, which leaves the heap
// in a state where we can iterate over the heap visiting all objects. // in a state where we can iterate over the heap visiting all objects.
void CollectAllGarbage( V8_EXPORT_PRIVATE void CollectAllGarbage(
int flags, GarbageCollectionReason gc_reason, int flags, GarbageCollectionReason gc_reason,
const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags); const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
......
...@@ -76,6 +76,22 @@ class TestEmbedderHeapTracer final : public v8::EmbedderHeapTracer { ...@@ -76,6 +76,22 @@ class TestEmbedderHeapTracer final : public v8::EmbedderHeapTracer {
std::vector<v8::Persistent<v8::Object>*> to_register_with_v8_; std::vector<v8::Persistent<v8::Object>*> to_register_with_v8_;
}; };
class TemporaryEmbedderHeapTracerScope {
public:
TemporaryEmbedderHeapTracerScope(v8::Isolate* isolate,
EmbedderHeapTracer* tracer)
: isolate_(isolate) {
isolate_->SetEmbedderHeapTracer(tracer);
}
~TemporaryEmbedderHeapTracerScope() {
isolate_->SetEmbedderHeapTracer(nullptr);
}
private:
v8::Isolate* const isolate_;
};
} // namespace } // namespace
TEST(V8RegisteringEmbedderReference) { TEST(V8RegisteringEmbedderReference) {
...@@ -85,7 +101,7 @@ TEST(V8RegisteringEmbedderReference) { ...@@ -85,7 +101,7 @@ TEST(V8RegisteringEmbedderReference) {
CcTest::InitializeVM(); CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate(); v8::Isolate* isolate = CcTest::isolate();
TestEmbedderHeapTracer tracer(isolate); TestEmbedderHeapTracer tracer(isolate);
isolate->SetEmbedderHeapTracer(&tracer); TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
...@@ -105,7 +121,7 @@ TEST(EmbedderRegisteringV8Reference) { ...@@ -105,7 +121,7 @@ TEST(EmbedderRegisteringV8Reference) {
CcTest::InitializeVM(); CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate(); v8::Isolate* isolate = CcTest::isolate();
TestEmbedderHeapTracer tracer(isolate); TestEmbedderHeapTracer tracer(isolate);
isolate->SetEmbedderHeapTracer(&tracer); TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
...@@ -139,7 +155,7 @@ TEST(TracingInRevivedSubgraph) { ...@@ -139,7 +155,7 @@ TEST(TracingInRevivedSubgraph) {
CcTest::InitializeVM(); CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate(); v8::Isolate* isolate = CcTest::isolate();
TestEmbedderHeapTracer tracer(isolate); TestEmbedderHeapTracer tracer(isolate);
isolate->SetEmbedderHeapTracer(&tracer); TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
...@@ -167,7 +183,7 @@ TEST(TracingInEphemerons) { ...@@ -167,7 +183,7 @@ TEST(TracingInEphemerons) {
CcTest::InitializeVM(); CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate(); v8::Isolate* isolate = CcTest::isolate();
TestEmbedderHeapTracer tracer(isolate); TestEmbedderHeapTracer tracer(isolate);
isolate->SetEmbedderHeapTracer(&tracer); TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
...@@ -192,6 +208,49 @@ TEST(TracingInEphemerons) { ...@@ -192,6 +208,49 @@ TEST(TracingInEphemerons) {
CHECK(tracer.IsRegisteredFromV8(first_field)); CHECK(tracer.IsRegisteredFromV8(first_field));
} }
TEST(FinalizeTracingIsNoopWhenNotMarking) {
ManualGCScope manual_gc;
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
Isolate* i_isolate = CcTest::i_isolate();
TestEmbedderHeapTracer tracer(isolate);
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
// Finalize a potentially running garbage collection.
i_isolate->heap()->CollectGarbage(OLD_SPACE,
GarbageCollectionReason::kTesting);
CHECK(i_isolate->heap()->incremental_marking()->IsStopped());
int gc_counter = i_isolate->heap()->gc_count();
tracer.FinalizeTracing();
CHECK(i_isolate->heap()->incremental_marking()->IsStopped());
CHECK_EQ(gc_counter, i_isolate->heap()->gc_count());
}
TEST(FinalizeTracingWhenMarking) {
ManualGCScope manual_gc;
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
Isolate* i_isolate = CcTest::i_isolate();
TestEmbedderHeapTracer tracer(isolate);
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
// Finalize a potentially running garbage collection.
i_isolate->heap()->CollectGarbage(OLD_SPACE,
GarbageCollectionReason::kTesting);
if (i_isolate->heap()->mark_compact_collector()->sweeping_in_progress()) {
i_isolate->heap()->mark_compact_collector()->EnsureSweepingCompleted();
}
CHECK(i_isolate->heap()->incremental_marking()->IsStopped());
i::IncrementalMarking* marking = i_isolate->heap()->incremental_marking();
marking->Start(i::GarbageCollectionReason::kTesting);
// Sweeping is not runing so we should immediately start marking.
CHECK(marking->IsMarking());
tracer.FinalizeTracing();
CHECK(marking->IsStopped());
}
} // namespace heap } // namespace heap
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -3,11 +3,15 @@ ...@@ -3,11 +3,15 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "src/heap/embedder-tracing.h" #include "src/heap/embedder-tracing.h"
#include "test/unittests/test-utils.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
using LocalEmbedderHeapTracerWithIsolate = TestWithIsolate;
namespace heap { namespace heap {
using testing::StrictMock; using testing::StrictMock;
...@@ -38,14 +42,14 @@ class MockEmbedderHeapTracer : public EmbedderHeapTracer { ...@@ -38,14 +42,14 @@ class MockEmbedderHeapTracer : public EmbedderHeapTracer {
}; };
TEST(LocalEmbedderHeapTracer, InUse) { TEST(LocalEmbedderHeapTracer, InUse) {
LocalEmbedderHeapTracer local_tracer;
MockEmbedderHeapTracer mock_remote_tracer; MockEmbedderHeapTracer mock_remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
local_tracer.SetRemoteTracer(&mock_remote_tracer); local_tracer.SetRemoteTracer(&mock_remote_tracer);
EXPECT_TRUE(local_tracer.InUse()); EXPECT_TRUE(local_tracer.InUse());
} }
TEST(LocalEmbedderHeapTracer, NoRemoteTracer) { TEST(LocalEmbedderHeapTracer, NoRemoteTracer) {
LocalEmbedderHeapTracer local_tracer; LocalEmbedderHeapTracer local_tracer(nullptr);
// We should be able to call all functions without a remote tracer being // We should be able to call all functions without a remote tracer being
// attached. // attached.
EXPECT_FALSE(local_tracer.InUse()); EXPECT_FALSE(local_tracer.InUse());
...@@ -59,32 +63,32 @@ TEST(LocalEmbedderHeapTracer, NoRemoteTracer) { ...@@ -59,32 +63,32 @@ TEST(LocalEmbedderHeapTracer, NoRemoteTracer) {
} }
TEST(LocalEmbedderHeapTracer, TracePrologueForwards) { TEST(LocalEmbedderHeapTracer, TracePrologueForwards) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer; StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
local_tracer.SetRemoteTracer(&remote_tracer); local_tracer.SetRemoteTracer(&remote_tracer);
EXPECT_CALL(remote_tracer, TracePrologue()); EXPECT_CALL(remote_tracer, TracePrologue());
local_tracer.TracePrologue(); local_tracer.TracePrologue();
} }
TEST(LocalEmbedderHeapTracer, TraceEpilogueForwards) { TEST(LocalEmbedderHeapTracer, TraceEpilogueForwards) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer; StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
local_tracer.SetRemoteTracer(&remote_tracer); local_tracer.SetRemoteTracer(&remote_tracer);
EXPECT_CALL(remote_tracer, TraceEpilogue()); EXPECT_CALL(remote_tracer, TraceEpilogue());
local_tracer.TraceEpilogue(); local_tracer.TraceEpilogue();
} }
TEST(LocalEmbedderHeapTracer, AbortTracingForwards) { TEST(LocalEmbedderHeapTracer, AbortTracingForwards) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer; StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
local_tracer.SetRemoteTracer(&remote_tracer); local_tracer.SetRemoteTracer(&remote_tracer);
EXPECT_CALL(remote_tracer, AbortTracing()); EXPECT_CALL(remote_tracer, AbortTracing());
local_tracer.AbortTracing(); local_tracer.AbortTracing();
} }
TEST(LocalEmbedderHeapTracer, AbortTracingClearsCachedWrappers) { TEST(LocalEmbedderHeapTracer, AbortTracingClearsCachedWrappers) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer; StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
local_tracer.SetRemoteTracer(&remote_tracer); local_tracer.SetRemoteTracer(&remote_tracer);
local_tracer.AddWrapperToTrace(CreateWrapperInfo()); local_tracer.AddWrapperToTrace(CreateWrapperInfo());
EXPECT_CALL(remote_tracer, AbortTracing()); EXPECT_CALL(remote_tracer, AbortTracing());
...@@ -93,31 +97,31 @@ TEST(LocalEmbedderHeapTracer, AbortTracingClearsCachedWrappers) { ...@@ -93,31 +97,31 @@ TEST(LocalEmbedderHeapTracer, AbortTracingClearsCachedWrappers) {
} }
TEST(LocalEmbedderHeapTracer, EnterFinalPauseForwards) { TEST(LocalEmbedderHeapTracer, EnterFinalPauseForwards) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer; StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
local_tracer.SetRemoteTracer(&remote_tracer); local_tracer.SetRemoteTracer(&remote_tracer);
EXPECT_CALL(remote_tracer, EnterFinalPause()); EXPECT_CALL(remote_tracer, EnterFinalPause());
local_tracer.EnterFinalPause(); local_tracer.EnterFinalPause();
} }
TEST(LocalEmbedderHeapTracer, IsRemoteTracingDoneIncludesRemote) { TEST(LocalEmbedderHeapTracer, IsRemoteTracingDoneIncludesRemote) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer; StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
local_tracer.SetRemoteTracer(&remote_tracer); local_tracer.SetRemoteTracer(&remote_tracer);
EXPECT_CALL(remote_tracer, IsTracingDone()); EXPECT_CALL(remote_tracer, IsTracingDone());
local_tracer.IsRemoteTracingDone(); local_tracer.IsRemoteTracingDone();
} }
TEST(LocalEmbedderHeapTracer, NumberOfCachedWrappersToTraceExcludesRemote) { TEST(LocalEmbedderHeapTracer, NumberOfCachedWrappersToTraceExcludesRemote) {
LocalEmbedderHeapTracer local_tracer; LocalEmbedderHeapTracer local_tracer(nullptr);
StrictMock<MockEmbedderHeapTracer> remote_tracer; StrictMock<MockEmbedderHeapTracer> remote_tracer;
local_tracer.SetRemoteTracer(&remote_tracer); local_tracer.SetRemoteTracer(&remote_tracer);
local_tracer.NumberOfCachedWrappersToTrace(); local_tracer.NumberOfCachedWrappersToTrace();
} }
TEST(LocalEmbedderHeapTracer, RegisterWrappersWithRemoteTracer) { TEST(LocalEmbedderHeapTracer, RegisterWrappersWithRemoteTracer) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer; StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
local_tracer.SetRemoteTracer(&remote_tracer); local_tracer.SetRemoteTracer(&remote_tracer);
local_tracer.AddWrapperToTrace(CreateWrapperInfo()); local_tracer.AddWrapperToTrace(CreateWrapperInfo());
EXPECT_EQ(1u, local_tracer.NumberOfCachedWrappersToTrace()); EXPECT_EQ(1u, local_tracer.NumberOfCachedWrappersToTrace());
...@@ -129,8 +133,8 @@ TEST(LocalEmbedderHeapTracer, RegisterWrappersWithRemoteTracer) { ...@@ -129,8 +133,8 @@ TEST(LocalEmbedderHeapTracer, RegisterWrappersWithRemoteTracer) {
} }
TEST(LocalEmbedderHeapTracer, TraceFinishes) { TEST(LocalEmbedderHeapTracer, TraceFinishes) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer; StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
local_tracer.SetRemoteTracer(&remote_tracer); local_tracer.SetRemoteTracer(&remote_tracer);
local_tracer.AddWrapperToTrace(CreateWrapperInfo()); local_tracer.AddWrapperToTrace(CreateWrapperInfo());
EXPECT_EQ(1u, local_tracer.NumberOfCachedWrappersToTrace()); EXPECT_EQ(1u, local_tracer.NumberOfCachedWrappersToTrace());
...@@ -144,8 +148,8 @@ TEST(LocalEmbedderHeapTracer, TraceFinishes) { ...@@ -144,8 +148,8 @@ TEST(LocalEmbedderHeapTracer, TraceFinishes) {
} }
TEST(LocalEmbedderHeapTracer, TraceDoesNotFinish) { TEST(LocalEmbedderHeapTracer, TraceDoesNotFinish) {
LocalEmbedderHeapTracer local_tracer;
StrictMock<MockEmbedderHeapTracer> remote_tracer; StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
local_tracer.SetRemoteTracer(&remote_tracer); local_tracer.SetRemoteTracer(&remote_tracer);
local_tracer.AddWrapperToTrace(CreateWrapperInfo()); local_tracer.AddWrapperToTrace(CreateWrapperInfo());
EXPECT_EQ(1u, local_tracer.NumberOfCachedWrappersToTrace()); EXPECT_EQ(1u, local_tracer.NumberOfCachedWrappersToTrace());
...@@ -158,6 +162,23 @@ TEST(LocalEmbedderHeapTracer, TraceDoesNotFinish) { ...@@ -158,6 +162,23 @@ TEST(LocalEmbedderHeapTracer, TraceDoesNotFinish) {
EXPECT_EQ(0u, local_tracer.NumberOfCachedWrappersToTrace()); EXPECT_EQ(0u, local_tracer.NumberOfCachedWrappersToTrace());
} }
TEST_F(LocalEmbedderHeapTracerWithIsolate, SetRemoteTracerSetsIsolate) {
StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(isolate());
local_tracer.SetRemoteTracer(&remote_tracer);
EXPECT_EQ(isolate(), reinterpret_cast<Isolate*>(remote_tracer.isolate()));
}
TEST_F(LocalEmbedderHeapTracerWithIsolate, DestructorClearsIsolate) {
StrictMock<MockEmbedderHeapTracer> remote_tracer;
{
LocalEmbedderHeapTracer local_tracer(isolate());
local_tracer.SetRemoteTracer(&remote_tracer);
EXPECT_EQ(isolate(), reinterpret_cast<Isolate*>(remote_tracer.isolate()));
}
EXPECT_EQ(nullptr, remote_tracer.isolate());
}
} // namespace heap } // namespace heap
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
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