Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/heap/embedder-tracing.h"
6 : #include "src/heap/heap.h"
7 : #include "test/unittests/test-utils.h"
8 : #include "testing/gmock/include/gmock/gmock.h"
9 : #include "testing/gtest/include/gtest/gtest.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 :
14 : using LocalEmbedderHeapTracerWithIsolate = TestWithIsolate;
15 :
16 : namespace heap {
17 :
18 : using testing::StrictMock;
19 : using testing::_;
20 : using testing::Return;
21 : using v8::EmbedderHeapTracer;
22 : using v8::internal::LocalEmbedderHeapTracer;
23 :
24 : namespace {
25 :
26 : LocalEmbedderHeapTracer::WrapperInfo CreateWrapperInfo() {
27 : return LocalEmbedderHeapTracer::WrapperInfo(nullptr, nullptr);
28 : }
29 :
30 : } // namespace
31 :
32 70 : class MockEmbedderHeapTracer : public EmbedderHeapTracer {
33 : public:
34 2 : MOCK_METHOD0(TracePrologue, void());
35 2 : MOCK_METHOD0(TraceEpilogue, void());
36 32 : MOCK_METHOD1(EnterFinalPause, void(EmbedderHeapTracer::EmbedderStackState));
37 6 : MOCK_METHOD0(IsTracingDone, bool());
38 4 : MOCK_METHOD1(RegisterV8References,
39 : void(const std::vector<std::pair<void*, void*> >&));
40 0 : MOCK_METHOD1(AdvanceTracing, bool(double deadline_in_ms));
41 : };
42 :
43 15443 : TEST(LocalEmbedderHeapTracer, InUse) {
44 2 : MockEmbedderHeapTracer mock_remote_tracer;
45 : LocalEmbedderHeapTracer local_tracer(nullptr);
46 1 : local_tracer.SetRemoteTracer(&mock_remote_tracer);
47 1 : EXPECT_TRUE(local_tracer.InUse());
48 1 : }
49 :
50 15443 : TEST(LocalEmbedderHeapTracer, NoRemoteTracer) {
51 : LocalEmbedderHeapTracer local_tracer(nullptr);
52 : // We should be able to call all functions without a remote tracer being
53 : // attached.
54 : EXPECT_FALSE(local_tracer.InUse());
55 1 : local_tracer.TracePrologue();
56 1 : local_tracer.EnterFinalPause();
57 1 : bool done = local_tracer.Trace(std::numeric_limits<double>::infinity());
58 1 : EXPECT_TRUE(done);
59 1 : local_tracer.TraceEpilogue();
60 1 : }
61 :
62 15443 : TEST(LocalEmbedderHeapTracer, TracePrologueForwards) {
63 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
64 : LocalEmbedderHeapTracer local_tracer(nullptr);
65 1 : local_tracer.SetRemoteTracer(&remote_tracer);
66 2 : EXPECT_CALL(remote_tracer, TracePrologue());
67 1 : local_tracer.TracePrologue();
68 1 : }
69 :
70 15443 : TEST(LocalEmbedderHeapTracer, TraceEpilogueForwards) {
71 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
72 : LocalEmbedderHeapTracer local_tracer(nullptr);
73 1 : local_tracer.SetRemoteTracer(&remote_tracer);
74 2 : EXPECT_CALL(remote_tracer, TraceEpilogue());
75 1 : local_tracer.TraceEpilogue();
76 1 : }
77 :
78 15443 : TEST(LocalEmbedderHeapTracer, EnterFinalPauseForwards) {
79 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
80 : LocalEmbedderHeapTracer local_tracer(nullptr);
81 1 : local_tracer.SetRemoteTracer(&remote_tracer);
82 4 : EXPECT_CALL(remote_tracer, EnterFinalPause(_));
83 1 : local_tracer.EnterFinalPause();
84 1 : }
85 :
86 15443 : TEST(LocalEmbedderHeapTracer, IsRemoteTracingDoneForwards) {
87 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
88 : LocalEmbedderHeapTracer local_tracer(nullptr);
89 1 : local_tracer.SetRemoteTracer(&remote_tracer);
90 2 : EXPECT_CALL(remote_tracer, IsTracingDone());
91 1 : local_tracer.IsRemoteTracingDone();
92 1 : }
93 :
94 15443 : TEST(LocalEmbedderHeapTracer, EnterFinalPauseDefaultStackStateUnkown) {
95 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
96 : LocalEmbedderHeapTracer local_tracer(nullptr);
97 1 : local_tracer.SetRemoteTracer(&remote_tracer);
98 : // The default stack state is expected to be unkown.
99 3 : EXPECT_CALL(remote_tracer, EnterFinalPause(EmbedderHeapTracer::kUnknown));
100 1 : local_tracer.EnterFinalPause();
101 1 : }
102 :
103 15443 : TEST(LocalEmbedderHeapTracer, EnterFinalPauseStackStateIsForwarded) {
104 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
105 : LocalEmbedderHeapTracer local_tracer(nullptr);
106 1 : local_tracer.SetRemoteTracer(&remote_tracer);
107 : local_tracer.SetEmbedderStackStateForNextFinalization(
108 1 : EmbedderHeapTracer::kEmpty);
109 3 : EXPECT_CALL(remote_tracer, EnterFinalPause(EmbedderHeapTracer::kEmpty));
110 1 : local_tracer.EnterFinalPause();
111 1 : }
112 :
113 15443 : TEST(LocalEmbedderHeapTracer, TemporaryEmbedderStackState) {
114 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
115 : LocalEmbedderHeapTracer local_tracer(nullptr);
116 1 : local_tracer.SetRemoteTracer(&remote_tracer);
117 : // Default is unknown, see above.
118 : {
119 : EmbedderStackStateScope scope(&local_tracer, EmbedderHeapTracer::kEmpty);
120 3 : EXPECT_CALL(remote_tracer, EnterFinalPause(EmbedderHeapTracer::kEmpty));
121 1 : local_tracer.EnterFinalPause();
122 : }
123 1 : }
124 :
125 15443 : TEST(LocalEmbedderHeapTracer, TemporaryEmbedderStackStateRestores) {
126 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
127 : LocalEmbedderHeapTracer local_tracer(nullptr);
128 1 : local_tracer.SetRemoteTracer(&remote_tracer);
129 : // Default is unknown, see above.
130 : {
131 : EmbedderStackStateScope scope(&local_tracer, EmbedderHeapTracer::kEmpty);
132 : {
133 : EmbedderStackStateScope scope(&local_tracer,
134 : EmbedderHeapTracer::kUnknown);
135 3 : EXPECT_CALL(remote_tracer, EnterFinalPause(EmbedderHeapTracer::kUnknown));
136 1 : local_tracer.EnterFinalPause();
137 : }
138 3 : EXPECT_CALL(remote_tracer, EnterFinalPause(EmbedderHeapTracer::kEmpty));
139 1 : local_tracer.EnterFinalPause();
140 : }
141 1 : }
142 :
143 15443 : TEST(LocalEmbedderHeapTracer, EnterFinalPauseStackStateResets) {
144 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
145 : LocalEmbedderHeapTracer local_tracer(nullptr);
146 1 : local_tracer.SetRemoteTracer(&remote_tracer);
147 : local_tracer.SetEmbedderStackStateForNextFinalization(
148 1 : EmbedderHeapTracer::kEmpty);
149 3 : EXPECT_CALL(remote_tracer, EnterFinalPause(EmbedderHeapTracer::kEmpty));
150 1 : local_tracer.EnterFinalPause();
151 3 : EXPECT_CALL(remote_tracer, EnterFinalPause(EmbedderHeapTracer::kUnknown));
152 1 : local_tracer.EnterFinalPause();
153 1 : }
154 :
155 15443 : TEST(LocalEmbedderHeapTracer, IsRemoteTracingDoneIncludesRemote) {
156 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
157 : LocalEmbedderHeapTracer local_tracer(nullptr);
158 1 : local_tracer.SetRemoteTracer(&remote_tracer);
159 2 : EXPECT_CALL(remote_tracer, IsTracingDone());
160 1 : local_tracer.IsRemoteTracingDone();
161 1 : }
162 :
163 15443 : TEST(LocalEmbedderHeapTracer, RegisterV8ReferencesWithRemoteTracer) {
164 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
165 : LocalEmbedderHeapTracer local_tracer(nullptr);
166 1 : local_tracer.SetRemoteTracer(&remote_tracer);
167 : {
168 2 : LocalEmbedderHeapTracer::ProcessingScope scope(&local_tracer);
169 1 : scope.AddWrapperInfoForTesting(CreateWrapperInfo());
170 4 : EXPECT_CALL(remote_tracer, RegisterV8References(_));
171 : }
172 4 : EXPECT_CALL(remote_tracer, IsTracingDone()).WillOnce(Return(false));
173 2 : EXPECT_FALSE(local_tracer.IsRemoteTracingDone());
174 1 : }
175 :
176 15444 : TEST_F(LocalEmbedderHeapTracerWithIsolate, SetRemoteTracerSetsIsolate) {
177 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
178 : LocalEmbedderHeapTracer local_tracer(isolate());
179 1 : local_tracer.SetRemoteTracer(&remote_tracer);
180 3 : EXPECT_EQ(isolate(), reinterpret_cast<Isolate*>(remote_tracer.isolate()));
181 1 : }
182 :
183 15444 : TEST_F(LocalEmbedderHeapTracerWithIsolate, DestructorClearsIsolate) {
184 1 : StrictMock<MockEmbedderHeapTracer> remote_tracer;
185 : {
186 : LocalEmbedderHeapTracer local_tracer(isolate());
187 1 : local_tracer.SetRemoteTracer(&remote_tracer);
188 3 : EXPECT_EQ(isolate(), reinterpret_cast<Isolate*>(remote_tracer.isolate()));
189 : }
190 1 : EXPECT_EQ(nullptr, remote_tracer.isolate());
191 1 : }
192 :
193 : } // namespace heap
194 : } // namespace internal
195 9264 : } // namespace v8
|