Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(355)

Side by Side Diff: test/cctest/heap/test-array-buffer-tracker.cc

Issue 2026633003: Reland "[heap] Fine-grained JSArrayBuffer tracking" (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Tests should not assert for promotion decisions but only for tracking Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/heap/heap-utils.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/array-buffer-tracker.h"
6 #include "test/cctest/cctest.h"
7 #include "test/cctest/heap/heap-utils.h"
8
9 namespace {
10
11 typedef i::LocalArrayBufferTracker LocalTracker;
12
13 bool IsTracked(i::JSArrayBuffer* buf) {
14 return i::ArrayBufferTracker::IsTracked(buf);
15 }
16
17 } // namespace
18
19 namespace v8 {
20 namespace internal {
21
22 // The following tests make sure that JSArrayBuffer tracking works expected when
23 // moving the objects through various spaces during GC phases.
24
25 TEST(ArrayBuffer_OnlyMC) {
26 CcTest::InitializeVM();
27 LocalContext env;
28 v8::Isolate* isolate = env->GetIsolate();
29 Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
30
31 JSArrayBuffer* raw_ab = nullptr;
32 {
33 v8::HandleScope handle_scope(isolate);
34 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
35 Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
36 CHECK(IsTracked(*buf));
37 heap::GcAndSweep(heap, OLD_SPACE);
38 CHECK(IsTracked(*buf));
39 heap::GcAndSweep(heap, OLD_SPACE);
40 CHECK(IsTracked(*buf));
41 raw_ab = *buf;
42 // Prohibit page from being released.
43 Page::FromAddress(buf->address())->MarkNeverEvacuate();
44 }
45 // 2 GCs are needed because we promote to old space as live, meaning that
46 // we will survive one GC.
47 heap::GcAndSweep(heap, OLD_SPACE);
48 heap::GcAndSweep(heap, OLD_SPACE);
49 CHECK(!IsTracked(raw_ab));
50 }
51
52 TEST(ArrayBuffer_OnlyScavenge) {
53 CcTest::InitializeVM();
54 LocalContext env;
55 v8::Isolate* isolate = env->GetIsolate();
56 Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
57
58 JSArrayBuffer* raw_ab = nullptr;
59 {
60 v8::HandleScope handle_scope(isolate);
61 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
62 Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
63 CHECK(IsTracked(*buf));
64 heap::GcAndSweep(heap, NEW_SPACE);
65 CHECK(IsTracked(*buf));
66 heap::GcAndSweep(heap, NEW_SPACE);
67 CHECK(IsTracked(*buf));
68 heap::GcAndSweep(heap, NEW_SPACE);
69 CHECK(IsTracked(*buf));
70 raw_ab = *buf;
71 // Prohibit page from being released.
72 Page::FromAddress(buf->address())->MarkNeverEvacuate();
73 }
74 // 2 GCs are needed because we promote to old space as live, meaning that
75 // we will survive one GC.
76 heap::GcAndSweep(heap, OLD_SPACE);
77 heap::GcAndSweep(heap, OLD_SPACE);
78 CHECK(!IsTracked(raw_ab));
79 }
80
81 TEST(ArrayBuffer_ScavengeAndMC) {
82 CcTest::InitializeVM();
83 LocalContext env;
84 v8::Isolate* isolate = env->GetIsolate();
85 Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
86
87 JSArrayBuffer* raw_ab = nullptr;
88 {
89 v8::HandleScope handle_scope(isolate);
90 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
91 Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
92 CHECK(IsTracked(*buf));
93 heap::GcAndSweep(heap, NEW_SPACE);
94 CHECK(IsTracked(*buf));
95 heap::GcAndSweep(heap, NEW_SPACE);
96 CHECK(IsTracked(*buf));
97 heap::GcAndSweep(heap, OLD_SPACE);
98 CHECK(IsTracked(*buf));
99 heap::GcAndSweep(heap, NEW_SPACE);
100 CHECK(IsTracked(*buf));
101 raw_ab = *buf;
102 // Prohibit page from being released.
103 Page::FromAddress(buf->address())->MarkNeverEvacuate();
104 }
105 // 2 GCs are needed because we promote to old space as live, meaning that
106 // we will survive one GC.
107 heap::GcAndSweep(heap, OLD_SPACE);
108 heap::GcAndSweep(heap, OLD_SPACE);
109 CHECK(!IsTracked(raw_ab));
110 }
111
112 TEST(ArrayBuffer_Compaction) {
113 FLAG_manual_evacuation_candidates_selection = true;
114 CcTest::InitializeVM();
115 LocalContext env;
116 v8::Isolate* isolate = env->GetIsolate();
117 Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
118 heap::AbandonCurrentlyFreeMemory(heap->old_space());
119
120 v8::HandleScope handle_scope(isolate);
121 Local<v8::ArrayBuffer> ab1 = v8::ArrayBuffer::New(isolate, 100);
122 Handle<JSArrayBuffer> buf1 = v8::Utils::OpenHandle(*ab1);
123 CHECK(IsTracked(*buf1));
124 heap::GcAndSweep(heap, NEW_SPACE);
125 heap::GcAndSweep(heap, NEW_SPACE);
126
127 Page* page_before_gc = Page::FromAddress(buf1->address());
128 page_before_gc->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
129 CHECK(IsTracked(*buf1));
130
131 heap->CollectAllGarbage();
132
133 Page* page_after_gc = Page::FromAddress(buf1->address());
134 CHECK(IsTracked(*buf1));
135
136 CHECK_NE(page_before_gc, page_after_gc);
137 }
138
139 TEST(ArrayBuffer_UnregisterDuringSweep) {
140 // Regular pages in old space (without compaction) are processed concurrently
141 // in the sweeper. If we happen to unregister a buffer (either explicitly, or
142 // implicitly through e.g. |Externalize|) we need to sync with the sweeper
143 // task.
144 //
145 // Note: This test will will only fail on TSAN configurations.
146
147 // Disable verify-heap since it forces sweeping to be completed in the
148 // epilogue of the GC.
149 #ifdef VERIFY_HEAP
150 i::FLAG_verify_heap = false;
151 #endif // VERIFY_HEAP
152
153 CcTest::InitializeVM();
154 LocalContext env;
155 v8::Isolate* isolate = env->GetIsolate();
156 Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
157 {
158 v8::HandleScope handle_scope(isolate);
159 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
160 Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
161
162 {
163 v8::HandleScope handle_scope(isolate);
164 // Allocate another buffer on the same page to force processing a
165 // non-empty set of buffers in the last GC.
166 Local<v8::ArrayBuffer> ab2 = v8::ArrayBuffer::New(isolate, 100);
167 Handle<JSArrayBuffer> buf2 = v8::Utils::OpenHandle(*ab2);
168 CHECK(IsTracked(*buf));
169 CHECK(IsTracked(*buf));
170 heap::GcAndSweep(heap, NEW_SPACE);
171 CHECK(IsTracked(*buf));
172 CHECK(IsTracked(*buf));
173 heap::GcAndSweep(heap, NEW_SPACE);
174 CHECK(IsTracked(*buf));
175 CHECK(IsTracked(*buf2));
176 }
177
178 heap->CollectGarbage(OLD_SPACE);
179 // |Externalize| will cause the buffer to be |Unregister|ed. Without
180 // barriers and proper synchronization this will trigger a data race on
181 // TSAN.
182 v8::ArrayBuffer::Contents contents = ab->Externalize();
183 heap->isolate()->array_buffer_allocator()->Free(contents.Data(),
184 contents.ByteLength());
185 }
186 }
187
188 TEST(ArrayBuffer_NonLivePromotion) {
189 // The test verifies that the marking state is preserved when promoting
190 // a buffer to old space.
191 CcTest::InitializeVM();
192 LocalContext env;
193 v8::Isolate* isolate = env->GetIsolate();
194 Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
195
196 JSArrayBuffer* raw_ab = nullptr;
197 {
198 v8::HandleScope handle_scope(isolate);
199 Handle<FixedArray> root =
200 heap->isolate()->factory()->NewFixedArray(1, TENURED);
201 {
202 v8::HandleScope handle_scope(isolate);
203 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
204 Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
205 root->set(0, *buf); // Buffer that should not be promoted as live.
206 }
207 heap::SimulateIncrementalMarking(heap, false);
208 CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
209 heap::GcAndSweep(heap, NEW_SPACE);
210 CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
211 heap::GcAndSweep(heap, NEW_SPACE);
212 CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
213 raw_ab = JSArrayBuffer::cast(root->get(0));
214 root->set(0, heap->undefined_value());
215 heap::SimulateIncrementalMarking(heap, true);
216 // Prohibit page from being released.
217 Page::FromAddress(raw_ab->address())->MarkNeverEvacuate();
218 heap::GcAndSweep(heap, OLD_SPACE);
219 CHECK(!IsTracked(raw_ab));
220 }
221 }
222
223 TEST(ArrayBuffer_LivePromotion) {
224 // The test verifies that the marking state is preserved when promoting
225 // a buffer to old space.
226 CcTest::InitializeVM();
227 LocalContext env;
228 v8::Isolate* isolate = env->GetIsolate();
229 Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
230
231 JSArrayBuffer* raw_ab = nullptr;
232 {
233 v8::HandleScope handle_scope(isolate);
234 Handle<FixedArray> root =
235 heap->isolate()->factory()->NewFixedArray(1, TENURED);
236 {
237 v8::HandleScope handle_scope(isolate);
238 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
239 Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
240 root->set(0, *buf); // Buffer that should be promoted as live.
241 }
242 heap::SimulateIncrementalMarking(heap, true);
243 CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
244 heap::GcAndSweep(heap, NEW_SPACE);
245 CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
246 heap::GcAndSweep(heap, NEW_SPACE);
247 CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
248 raw_ab = JSArrayBuffer::cast(root->get(0));
249 root->set(0, heap->undefined_value());
250 // Prohibit page from being released.
251 Page::FromAddress(raw_ab->address())->MarkNeverEvacuate();
252 heap::GcAndSweep(heap, OLD_SPACE);
253 CHECK(IsTracked(raw_ab));
254 }
255 }
256
257 TEST(ArrayBuffer_SemiSpaceCopyThenPagePromotion) {
258 // The test verifies that the marking state is preserved across semispace
259 // copy.
260 CcTest::InitializeVM();
261 LocalContext env;
262 v8::Isolate* isolate = env->GetIsolate();
263 Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
264
265 heap::SealCurrentObjects(heap);
266 {
267 v8::HandleScope handle_scope(isolate);
268 Handle<FixedArray> root =
269 heap->isolate()->factory()->NewFixedArray(1, TENURED);
270 {
271 v8::HandleScope handle_scope(isolate);
272 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
273 Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
274 root->set(0, *buf); // Buffer that should be promoted as live.
275 Page::FromAddress(buf->address())->MarkNeverEvacuate();
276 }
277 std::vector<Handle<FixedArray>> handles;
278 // Make the whole page transition from new->old, getting the buffers
279 // processed in the sweeper (relying on marking information) instead of
280 // processing during newspace evacuation.
281 heap::FillCurrentPage(heap->new_space(), &handles);
282 CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
283 heap::GcAndSweep(heap, NEW_SPACE);
284 heap::SimulateIncrementalMarking(heap, true);
285 heap::GcAndSweep(heap, OLD_SPACE);
286 CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
287 }
288 }
289
290 } // namespace internal
291 } // namespace v8
OLDNEW
« no previous file with comments | « test/cctest/heap/heap-utils.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698