Line data Source code
1 : // Copyright 2008 the V8 project authors. All rights reserved.
2 : // Redistribution and use in source and binary forms, with or without
3 : // modification, are permitted provided that the following conditions are
4 : // met:
5 : //
6 : // * Redistributions of source code must retain the above copyright
7 : // notice, this list of conditions and the following disclaimer.
8 : // * Redistributions in binary form must reproduce the above
9 : // copyright notice, this list of conditions and the following
10 : // disclaimer in the documentation and/or other materials provided
11 : // with the distribution.
12 : // * Neither the name of Google Inc. nor the names of its
13 : // contributors may be used to endorse or promote products derived
14 : // from this software without specific prior written permission.
15 : //
16 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 :
28 : #ifndef CCTEST_H_
29 : #define CCTEST_H_
30 :
31 : #include <memory>
32 :
33 : #include "include/libplatform/libplatform.h"
34 : #include "include/v8-platform.h"
35 : #include "src/base/enum-set.h"
36 : #include "src/debug/debug-interface.h"
37 : #include "src/flags.h"
38 : #include "src/heap/factory.h"
39 : #include "src/isolate.h"
40 : #include "src/objects.h"
41 : #include "src/register-configuration.h"
42 : #include "src/v8.h"
43 : #include "src/zone/accounting-allocator.h"
44 :
45 : namespace v8 {
46 : namespace base {
47 :
48 : class RandomNumberGenerator;
49 :
50 : } // namespace base
51 :
52 : namespace internal {
53 :
54 : const auto GetRegConfig = RegisterConfiguration::Default;
55 :
56 : class HandleScope;
57 : class Zone;
58 :
59 : } // namespace internal
60 :
61 : } // namespace v8
62 :
63 : #ifndef TEST
64 : #define TEST(Name) \
65 : static void Test##Name(); \
66 : CcTest register_test_##Name(Test##Name, __FILE__, #Name, true, true); \
67 : static void Test##Name()
68 : #endif
69 :
70 : #ifndef UNINITIALIZED_TEST
71 : #define UNINITIALIZED_TEST(Name) \
72 : static void Test##Name(); \
73 : CcTest register_test_##Name(Test##Name, __FILE__, #Name, true, false); \
74 : static void Test##Name()
75 : #endif
76 :
77 : #ifndef DISABLED_TEST
78 : #define DISABLED_TEST(Name) \
79 : static void Test##Name(); \
80 : CcTest register_test_##Name(Test##Name, __FILE__, #Name, false, true); \
81 : static void Test##Name()
82 : #endif
83 :
84 : #define EXTENSION_LIST(V) \
85 : V(GC_EXTENSION, "v8/gc") \
86 : V(PRINT_EXTENSION, "v8/print") \
87 : V(PROFILER_EXTENSION, "v8/profiler") \
88 : V(TRACE_EXTENSION, "v8/trace")
89 :
90 : #define DEFINE_EXTENSION_ID(Name, Ident) Name##_ID,
91 : enum CcTestExtensionId { EXTENSION_LIST(DEFINE_EXTENSION_ID) kMaxExtensions };
92 : #undef DEFINE_EXTENSION_ID
93 :
94 : using CcTestExtensionFlags = v8::base::EnumSet<CcTestExtensionId>;
95 :
96 : #define DEFINE_EXTENSION_NAME(Name, Ident) Ident,
97 : static constexpr const char* kExtensionName[kMaxExtensions] = {
98 : EXTENSION_LIST(DEFINE_EXTENSION_NAME)};
99 : #undef DEFINE_EXTENSION_NAME
100 :
101 : class CcTest {
102 : public:
103 : typedef void (TestFunction)();
104 : CcTest(TestFunction* callback, const char* file, const char* name,
105 : bool enabled, bool initialize);
106 324515324 : ~CcTest() { i::DeleteArray(file_); }
107 : void Run();
108 39654 : static CcTest* last() { return last_; }
109 : CcTest* prev() { return prev_; }
110 : const char* file() { return file_; }
111 : const char* name() { return name_; }
112 : bool enabled() { return enabled_; }
113 :
114 20447093 : static v8::Isolate* isolate() {
115 20447093 : CHECK_NOT_NULL(isolate_);
116 : v8::base::Relaxed_Store(&isolate_used_, 1);
117 20447093 : return isolate_;
118 : }
119 :
120 15618292 : static i::Isolate* InitIsolateOnce() {
121 15618292 : if (!initialize_called_) InitializeVM();
122 15618292 : return i_isolate();
123 : }
124 :
125 : static i::Isolate* i_isolate() {
126 20231902 : return reinterpret_cast<i::Isolate*>(isolate());
127 : }
128 :
129 : static i::Heap* heap();
130 :
131 : static void CollectGarbage(i::AllocationSpace space);
132 : static void CollectAllGarbage(i::Isolate* isolate = nullptr);
133 : static void CollectAllAvailableGarbage(i::Isolate* isolate = nullptr);
134 : static void PreciseCollectAllGarbage(i::Isolate* isolate = nullptr);
135 :
136 : static v8::base::RandomNumberGenerator* random_number_generator();
137 :
138 : static v8::Local<v8::Object> global();
139 :
140 : static v8::ArrayBuffer::Allocator* array_buffer_allocator() {
141 1548 : return allocator_;
142 : }
143 :
144 : static void set_array_buffer_allocator(
145 : v8::ArrayBuffer::Allocator* allocator) {
146 28337 : allocator_ = allocator;
147 : }
148 :
149 : // TODO(dcarney): Remove.
150 : // This must be called first in a test.
151 : static void InitializeVM();
152 :
153 : // Only for UNINITIALIZED_TESTs
154 : static void DisableAutomaticDispose();
155 :
156 : // Helper function to configure a context.
157 : // Must be in a HandleScope.
158 : static v8::Local<v8::Context> NewContext(
159 : v8::Isolate* isolate = CcTest::isolate()) {
160 : return NewContext({}, isolate);
161 : }
162 : static v8::Local<v8::Context> NewContext(
163 : CcTestExtensionFlags extension_flags,
164 : v8::Isolate* isolate = CcTest::isolate());
165 :
166 : static void TearDown();
167 :
168 : private:
169 : friend int main(int argc, char** argv);
170 : TestFunction* callback_;
171 : const char* file_;
172 : const char* name_;
173 : bool enabled_;
174 : bool initialize_;
175 : CcTest* prev_;
176 : static CcTest* last_;
177 : static v8::ArrayBuffer::Allocator* allocator_;
178 : static v8::Isolate* isolate_;
179 : static bool initialize_called_;
180 : static v8::base::Atomic32 isolate_used_;
181 : };
182 :
183 : // Switches between all the Api tests using the threading support.
184 : // In order to get a surprising but repeatable pattern of thread
185 : // switching it has extra semaphores to control the order in which
186 : // the tests alternate, not relying solely on the big V8 lock.
187 : //
188 : // A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
189 : // callbacks. This will have no effect when we are not running the
190 : // thread fuzzing test. In the thread fuzzing test it will
191 : // pseudorandomly select a successor thread and switch execution
192 : // to that thread, suspending the current test.
193 : class ApiTestFuzzer: public v8::base::Thread {
194 : public:
195 : void CallTest();
196 :
197 : // The ApiTestFuzzer is also a Thread, so it has a Run method.
198 : void Run() override;
199 :
200 : enum PartOfTest {
201 : FIRST_PART,
202 : SECOND_PART,
203 : THIRD_PART,
204 : FOURTH_PART,
205 : FIFTH_PART,
206 : SIXTH_PART,
207 : SEVENTH_PART,
208 : EIGHTH_PART,
209 : LAST_PART = EIGHTH_PART
210 : };
211 :
212 : static void SetUp(PartOfTest part);
213 : static void RunAllTests();
214 : static void TearDown();
215 : // This method switches threads if we are running the Threading test.
216 : // Otherwise it does nothing.
217 : static void Fuzz();
218 :
219 : private:
220 480 : explicit ApiTestFuzzer(int num)
221 : : Thread(Options("ApiTestFuzzer")),
222 : test_number_(num),
223 : gate_(0),
224 480 : active_(true) {}
225 0 : ~ApiTestFuzzer() override = default;
226 :
227 : static bool fuzzing_;
228 : static int tests_being_run_;
229 : static int current_;
230 : static int active_tests_;
231 : static bool NextThread();
232 : int test_number_;
233 : v8::base::Semaphore gate_;
234 : bool active_;
235 : void ContextSwitch();
236 : static int GetNextTestNumber();
237 : static v8::base::Semaphore all_tests_done_;
238 : };
239 :
240 :
241 : #define THREADED_TEST(Name) \
242 : static void Test##Name(); \
243 : RegisterThreadedTest register_##Name(Test##Name, #Name); \
244 : /* */ TEST(Name)
245 :
246 : class RegisterThreadedTest {
247 : public:
248 : explicit RegisterThreadedTest(CcTest::TestFunction* callback,
249 : const char* name)
250 13601760 : : fuzzer_(nullptr), callback_(callback), name_(name) {
251 13601760 : prev_ = first_;
252 13601760 : first_ = this;
253 13601760 : count_++;
254 : }
255 3439247 : static int count() { return count_; }
256 3435391 : static RegisterThreadedTest* nth(int i) {
257 3435391 : CHECK(i < count());
258 3435391 : RegisterThreadedTest* current = first_;
259 109900210 : while (i > 0) {
260 103029428 : i--;
261 103029428 : current = current->prev_;
262 : }
263 3435391 : return current;
264 : }
265 : CcTest::TestFunction* callback() { return callback_; }
266 : ApiTestFuzzer* fuzzer_;
267 : const char* name() { return name_; }
268 :
269 : private:
270 : static RegisterThreadedTest* first_;
271 : static int count_;
272 : CcTest::TestFunction* callback_;
273 : RegisterThreadedTest* prev_;
274 : const char* name_;
275 : };
276 :
277 : // A LocalContext holds a reference to a v8::Context.
278 : class LocalContext {
279 : public:
280 : LocalContext(v8::Isolate* isolate,
281 : v8::ExtensionConfiguration* extensions = nullptr,
282 : v8::Local<v8::ObjectTemplate> global_template =
283 : v8::Local<v8::ObjectTemplate>(),
284 2466 : v8::Local<v8::Value> global_object = v8::Local<v8::Value>()) {
285 2466 : Initialize(isolate, extensions, global_template, global_object);
286 : }
287 :
288 9819 : LocalContext(v8::ExtensionConfiguration* extensions = nullptr,
289 : v8::Local<v8::ObjectTemplate> global_template =
290 : v8::Local<v8::ObjectTemplate>(),
291 9819 : v8::Local<v8::Value> global_object = v8::Local<v8::Value>()) {
292 9819 : Initialize(CcTest::isolate(), extensions, global_template, global_object);
293 9819 : }
294 :
295 : virtual ~LocalContext();
296 :
297 : v8::Context* operator->() {
298 112875 : return *reinterpret_cast<v8::Context**>(&context_);
299 : }
300 : v8::Context* operator*() { return operator->(); }
301 : bool IsReady() { return !context_.IsEmpty(); }
302 :
303 188988 : v8::Local<v8::Context> local() {
304 377976 : return v8::Local<v8::Context>::New(isolate_, context_);
305 : }
306 :
307 : private:
308 : void Initialize(v8::Isolate* isolate, v8::ExtensionConfiguration* extensions,
309 : v8::Local<v8::ObjectTemplate> global_template,
310 : v8::Local<v8::Value> global_object);
311 :
312 : v8::Persistent<v8::Context> context_;
313 : v8::Isolate* isolate_;
314 : };
315 :
316 :
317 28460 : static inline uint16_t* AsciiToTwoByteString(const char* source) {
318 28460 : int array_length = i::StrLength(source) + 1;
319 28460 : uint16_t* converted = i::NewArray<uint16_t>(array_length);
320 28460 : for (int i = 0; i < array_length; i++) converted[i] = source[i];
321 28460 : return converted;
322 : }
323 :
324 : template <typename T>
325 65 : static inline i::Handle<T> GetGlobal(const char* name) {
326 : i::Isolate* isolate = CcTest::i_isolate();
327 : i::Handle<i::String> str_name =
328 65 : isolate->factory()->InternalizeUtf8String(name);
329 :
330 : i::Handle<i::Object> value =
331 130 : i::Object::GetProperty(isolate, isolate->global_object(), str_name)
332 130 : .ToHandleChecked();
333 65 : return i::Handle<T>::cast(value);
334 : }
335 :
336 77456 : static inline v8::Local<v8::Value> v8_num(double x) {
337 77456 : return v8::Number::New(v8::Isolate::GetCurrent(), x);
338 : }
339 :
340 : static inline v8::Local<v8::Integer> v8_int(int32_t x) {
341 40 : return v8::Integer::New(v8::Isolate::GetCurrent(), x);
342 : }
343 :
344 517790 : static inline v8::Local<v8::String> v8_str(const char* x) {
345 : return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), x,
346 517790 : v8::NewStringType::kNormal)
347 1035580 : .ToLocalChecked();
348 : }
349 :
350 :
351 913 : static inline v8::Local<v8::String> v8_str(v8::Isolate* isolate,
352 : const char* x) {
353 : return v8::String::NewFromUtf8(isolate, x, v8::NewStringType::kNormal)
354 1826 : .ToLocalChecked();
355 : }
356 :
357 :
358 5 : static inline v8::Local<v8::Symbol> v8_symbol(const char* name) {
359 5 : return v8::Symbol::New(v8::Isolate::GetCurrent(), v8_str(name));
360 : }
361 :
362 :
363 118046 : static inline v8::Local<v8::Script> v8_compile(v8::Local<v8::String> x) {
364 : v8::Local<v8::Script> result;
365 236092 : if (v8::Script::Compile(v8::Isolate::GetCurrent()->GetCurrentContext(), x)
366 118046 : .ToLocal(&result)) {
367 118036 : return result;
368 : }
369 10 : return v8::Local<v8::Script>();
370 : }
371 :
372 :
373 : static inline v8::Local<v8::Script> v8_compile(const char* x) {
374 2219 : return v8_compile(v8_str(x));
375 : }
376 :
377 :
378 2054 : static inline int32_t v8_run_int32value(v8::Local<v8::Script> script) {
379 2054 : v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
380 6162 : return script->Run(context).ToLocalChecked()->Int32Value(context).FromJust();
381 : }
382 :
383 :
384 60 : static inline v8::Local<v8::Script> CompileWithOrigin(
385 : v8::Local<v8::String> source, v8::Local<v8::String> origin_url) {
386 : v8::ScriptOrigin origin(origin_url);
387 : v8::ScriptCompiler::Source script_source(source, origin);
388 : return v8::ScriptCompiler::Compile(
389 60 : v8::Isolate::GetCurrent()->GetCurrentContext(), &script_source)
390 120 : .ToLocalChecked();
391 : }
392 :
393 :
394 : static inline v8::Local<v8::Script> CompileWithOrigin(
395 : v8::Local<v8::String> source, const char* origin_url) {
396 17 : return CompileWithOrigin(source, v8_str(origin_url));
397 : }
398 :
399 :
400 27 : static inline v8::Local<v8::Script> CompileWithOrigin(const char* source,
401 : const char* origin_url) {
402 27 : return CompileWithOrigin(v8_str(source), v8_str(origin_url));
403 : }
404 :
405 :
406 : // Helper functions that compile and run the source.
407 258 : static inline v8::MaybeLocal<v8::Value> CompileRun(
408 : v8::Local<v8::Context> context, const char* source) {
409 258 : return v8::Script::Compile(context, v8_str(source))
410 258 : .ToLocalChecked()
411 258 : ->Run(context);
412 : }
413 :
414 :
415 538 : static inline v8::Local<v8::Value> CompileRunChecked(v8::Isolate* isolate,
416 : const char* source) {
417 : v8::Local<v8::String> source_string =
418 : v8::String::NewFromUtf8(isolate, source, v8::NewStringType::kNormal)
419 1076 : .ToLocalChecked();
420 538 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
421 : v8::Local<v8::Script> script =
422 538 : v8::Script::Compile(context, source_string).ToLocalChecked();
423 1076 : return script->Run(context).ToLocalChecked();
424 : }
425 :
426 :
427 115700 : static inline v8::Local<v8::Value> CompileRun(v8::Local<v8::String> source) {
428 : v8::Local<v8::Value> result;
429 115700 : if (v8_compile(source)
430 231400 : ->Run(v8::Isolate::GetCurrent()->GetCurrentContext())
431 115700 : .ToLocal(&result)) {
432 113079 : return result;
433 : }
434 2621 : return v8::Local<v8::Value>();
435 : }
436 :
437 :
438 : // Helper functions that compile and run the source.
439 : static inline v8::Local<v8::Value> CompileRun(const char* source) {
440 113858 : return CompileRun(v8_str(source));
441 : }
442 :
443 :
444 80 : static inline v8::Local<v8::Value> CompileRun(
445 : v8::Local<v8::Context> context, v8::ScriptCompiler::Source* script_source,
446 : v8::ScriptCompiler::CompileOptions options) {
447 : v8::Local<v8::Value> result;
448 80 : if (v8::ScriptCompiler::Compile(context, script_source, options)
449 80 : .ToLocalChecked()
450 : ->Run(context)
451 80 : .ToLocal(&result)) {
452 60 : return result;
453 : }
454 20 : return v8::Local<v8::Value>();
455 : }
456 :
457 :
458 : // Helper functions that compile and run the source with given origin.
459 60 : static inline v8::Local<v8::Value> CompileRunWithOrigin(const char* source,
460 : const char* origin_url,
461 : int line_number,
462 : int column_number) {
463 60 : v8::Isolate* isolate = v8::Isolate::GetCurrent();
464 60 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
465 : v8::ScriptOrigin origin(v8_str(origin_url),
466 : v8::Integer::New(isolate, line_number),
467 60 : v8::Integer::New(isolate, column_number));
468 60 : v8::ScriptCompiler::Source script_source(v8_str(source), origin);
469 : return CompileRun(context, &script_source,
470 120 : v8::ScriptCompiler::CompileOptions());
471 : }
472 :
473 :
474 20 : static inline v8::Local<v8::Value> CompileRunWithOrigin(
475 : v8::Local<v8::String> source, const char* origin_url) {
476 20 : v8::Isolate* isolate = v8::Isolate::GetCurrent();
477 20 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
478 : v8::ScriptCompiler::Source script_source(
479 20 : source, v8::ScriptOrigin(v8_str(origin_url)));
480 : return CompileRun(context, &script_source,
481 40 : v8::ScriptCompiler::CompileOptions());
482 : }
483 :
484 :
485 : static inline v8::Local<v8::Value> CompileRunWithOrigin(
486 : const char* source, const char* origin_url) {
487 20 : return CompileRunWithOrigin(v8_str(source), origin_url);
488 : }
489 :
490 :
491 :
492 872 : static inline void ExpectString(const char* code, const char* expected) {
493 : v8::Local<v8::Value> result = CompileRun(code);
494 872 : CHECK(result->IsString());
495 872 : v8::String::Utf8Value utf8(v8::Isolate::GetCurrent(), result);
496 872 : CHECK_EQ(0, strcmp(expected, *utf8));
497 872 : }
498 :
499 :
500 1244 : static inline void ExpectInt32(const char* code, int expected) {
501 : v8::Local<v8::Value> result = CompileRun(code);
502 1244 : CHECK(result->IsInt32());
503 2488 : CHECK_EQ(expected,
504 : result->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext())
505 : .FromJust());
506 1244 : }
507 :
508 :
509 924 : static inline void ExpectBoolean(const char* code, bool expected) {
510 : v8::Local<v8::Value> result = CompileRun(code);
511 924 : CHECK(result->IsBoolean());
512 924 : CHECK_EQ(expected, result->BooleanValue(v8::Isolate::GetCurrent()));
513 924 : }
514 :
515 :
516 : static inline void ExpectTrue(const char* code) {
517 254 : ExpectBoolean(code, true);
518 : }
519 :
520 :
521 : static inline void ExpectFalse(const char* code) {
522 89 : ExpectBoolean(code, false);
523 : }
524 :
525 :
526 92 : static inline void ExpectObject(const char* code,
527 : v8::Local<v8::Value> expected) {
528 : v8::Local<v8::Value> result = CompileRun(code);
529 92 : CHECK(result->SameValue(expected));
530 92 : }
531 :
532 :
533 42 : static inline void ExpectUndefined(const char* code) {
534 : v8::Local<v8::Value> result = CompileRun(code);
535 42 : CHECK(result->IsUndefined());
536 42 : }
537 :
538 :
539 : static inline void ExpectNull(const char* code) {
540 : v8::Local<v8::Value> result = CompileRun(code);
541 : CHECK(result->IsNull());
542 : }
543 :
544 :
545 5 : static inline void CheckDoubleEquals(double expected, double actual) {
546 : const double kEpsilon = 1e-10;
547 10 : CHECK_LE(expected, actual + kEpsilon);
548 10 : CHECK_GE(expected, actual - kEpsilon);
549 5 : }
550 :
551 5100660 : static v8::debug::DebugDelegate dummy_delegate;
552 :
553 : static inline void EnableDebugger(v8::Isolate* isolate) {
554 30 : v8::debug::SetDebugDelegate(isolate, &dummy_delegate);
555 : }
556 :
557 :
558 : static inline void DisableDebugger(v8::Isolate* isolate) {
559 25 : v8::debug::SetDebugDelegate(isolate, nullptr);
560 : }
561 :
562 :
563 28039 : static inline void EmptyMessageQueues(v8::Isolate* isolate) {
564 79245 : while (v8::platform::PumpMessageLoop(v8::internal::V8::GetCurrentPlatform(),
565 51206 : isolate)) {
566 : }
567 28039 : }
568 :
569 : class InitializedHandleScopeImpl;
570 :
571 4570 : class InitializedHandleScope {
572 : public:
573 : InitializedHandleScope();
574 : ~InitializedHandleScope();
575 :
576 : // Prefixing the below with main_ reduces a lot of naming clashes.
577 : i::Isolate* main_isolate() { return main_isolate_; }
578 :
579 : private:
580 : i::Isolate* main_isolate_;
581 : std::unique_ptr<InitializedHandleScopeImpl> initialized_handle_scope_impl_;
582 : };
583 :
584 5270250 : class HandleAndZoneScope : public InitializedHandleScope {
585 : public:
586 : HandleAndZoneScope();
587 : ~HandleAndZoneScope();
588 :
589 : // Prefixing the below with main_ reduces a lot of naming clashes.
590 : i::Zone* main_zone() { return main_zone_.get(); }
591 :
592 : private:
593 : v8::internal::AccountingAllocator allocator_;
594 : std::unique_ptr<i::Zone> main_zone_;
595 : };
596 :
597 : class StaticOneByteResource : public v8::String::ExternalOneByteStringResource {
598 : public:
599 5 : explicit StaticOneByteResource(const char* data) : data_(data) {}
600 :
601 10 : ~StaticOneByteResource() override = default;
602 :
603 40 : const char* data() const override { return data_; }
604 :
605 20 : size_t length() const override { return strlen(data_); }
606 :
607 : private:
608 : const char* data_;
609 : };
610 :
611 : class ManualGCScope {
612 : public:
613 : ManualGCScope()
614 : : flag_concurrent_marking_(i::FLAG_concurrent_marking),
615 : flag_concurrent_sweeping_(i::FLAG_concurrent_sweeping),
616 : flag_stress_incremental_marking_(i::FLAG_stress_incremental_marking),
617 : flag_parallel_marking_(i::FLAG_parallel_marking),
618 : flag_detect_ineffective_gcs_near_heap_limit_(
619 443 : i::FLAG_detect_ineffective_gcs_near_heap_limit) {
620 443 : i::FLAG_concurrent_marking = false;
621 443 : i::FLAG_concurrent_sweeping = false;
622 443 : i::FLAG_stress_incremental_marking = false;
623 : // Parallel marking has a dependency on concurrent marking.
624 443 : i::FLAG_parallel_marking = false;
625 443 : i::FLAG_detect_ineffective_gcs_near_heap_limit = false;
626 : }
627 : ~ManualGCScope() {
628 443 : i::FLAG_concurrent_marking = flag_concurrent_marking_;
629 443 : i::FLAG_concurrent_sweeping = flag_concurrent_sweeping_;
630 443 : i::FLAG_stress_incremental_marking = flag_stress_incremental_marking_;
631 443 : i::FLAG_parallel_marking = flag_parallel_marking_;
632 : i::FLAG_detect_ineffective_gcs_near_heap_limit =
633 443 : flag_detect_ineffective_gcs_near_heap_limit_;
634 : }
635 :
636 : private:
637 : bool flag_concurrent_marking_;
638 : bool flag_concurrent_sweeping_;
639 : bool flag_stress_incremental_marking_;
640 : bool flag_parallel_marking_;
641 : bool flag_detect_ineffective_gcs_near_heap_limit_;
642 : };
643 :
644 : // This is an abstract base class that can be overridden to implement a test
645 : // platform. It delegates all operations to a given platform at the time
646 : // of construction.
647 : class TestPlatform : public v8::Platform {
648 : public:
649 : // v8::Platform implementation.
650 0 : v8::PageAllocator* GetPageAllocator() override {
651 0 : return old_platform_->GetPageAllocator();
652 : }
653 :
654 0 : void OnCriticalMemoryPressure() override {
655 0 : old_platform_->OnCriticalMemoryPressure();
656 0 : }
657 :
658 0 : bool OnCriticalMemoryPressure(size_t length) override {
659 0 : return old_platform_->OnCriticalMemoryPressure(length);
660 : }
661 :
662 206 : int NumberOfWorkerThreads() override {
663 206 : return old_platform_->NumberOfWorkerThreads();
664 : }
665 :
666 6 : std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner(
667 : v8::Isolate* isolate) override {
668 6 : return old_platform_->GetForegroundTaskRunner(isolate);
669 : }
670 :
671 7 : void CallOnWorkerThread(std::unique_ptr<v8::Task> task) override {
672 21 : old_platform_->CallOnWorkerThread(std::move(task));
673 7 : }
674 :
675 0 : void CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task,
676 : double delay_in_seconds) override {
677 0 : old_platform_->CallDelayedOnWorkerThread(std::move(task), delay_in_seconds);
678 0 : }
679 :
680 0 : void CallOnForegroundThread(v8::Isolate* isolate, v8::Task* task) override {
681 : // This is a deprecated function and should not be called anymore.
682 0 : UNREACHABLE();
683 : }
684 :
685 0 : void CallDelayedOnForegroundThread(v8::Isolate* isolate, v8::Task* task,
686 : double delay_in_seconds) override {
687 : // This is a deprecated function and should not be called anymore.
688 0 : UNREACHABLE();
689 : }
690 :
691 14025 : double MonotonicallyIncreasingTime() override {
692 14025 : return old_platform_->MonotonicallyIncreasingTime();
693 : }
694 :
695 0 : double CurrentClockTimeMillis() override {
696 0 : return old_platform_->CurrentClockTimeMillis();
697 : }
698 :
699 0 : void CallIdleOnForegroundThread(v8::Isolate* isolate,
700 : v8::IdleTask* task) override {
701 : // This is a deprecated function and should not be called anymore.
702 0 : UNREACHABLE();
703 : }
704 :
705 0 : bool IdleTasksEnabled(v8::Isolate* isolate) override {
706 0 : return old_platform_->IdleTasksEnabled(isolate);
707 : }
708 :
709 3584 : v8::TracingController* GetTracingController() override {
710 3584 : return old_platform_->GetTracingController();
711 : }
712 :
713 : protected:
714 275 : TestPlatform() : old_platform_(i::V8::GetCurrentPlatform()) {}
715 260 : ~TestPlatform() override { i::V8::SetPlatformForTesting(old_platform_); }
716 :
717 : v8::Platform* old_platform() const { return old_platform_; }
718 :
719 : private:
720 : v8::Platform* old_platform_;
721 :
722 : DISALLOW_COPY_AND_ASSIGN(TestPlatform);
723 : };
724 :
725 : #endif // ifndef CCTEST_H_
|