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 compiler {
60 :
61 : class JSHeapBroker;
62 :
63 : } // namespace compiler
64 :
65 : } // namespace internal
66 :
67 : } // namespace v8
68 :
69 : #ifndef TEST
70 : #define TEST(Name) \
71 : static void Test##Name(); \
72 : CcTest register_test_##Name(Test##Name, __FILE__, #Name, true, true); \
73 : static void Test##Name()
74 : #endif
75 :
76 : #ifndef UNINITIALIZED_TEST
77 : #define UNINITIALIZED_TEST(Name) \
78 : static void Test##Name(); \
79 : CcTest register_test_##Name(Test##Name, __FILE__, #Name, true, false); \
80 : static void Test##Name()
81 : #endif
82 :
83 : #ifndef DISABLED_TEST
84 : #define DISABLED_TEST(Name) \
85 : static void Test##Name(); \
86 : CcTest register_test_##Name(Test##Name, __FILE__, #Name, false, true); \
87 : static void Test##Name()
88 : #endif
89 :
90 : #define EXTENSION_LIST(V) \
91 : V(GC_EXTENSION, "v8/gc") \
92 : V(PRINT_EXTENSION, "v8/print") \
93 : V(PROFILER_EXTENSION, "v8/profiler") \
94 : V(TRACE_EXTENSION, "v8/trace")
95 :
96 : #define DEFINE_EXTENSION_ID(Name, Ident) Name##_ID,
97 : enum CcTestExtensionId { EXTENSION_LIST(DEFINE_EXTENSION_ID) kMaxExtensions };
98 : #undef DEFINE_EXTENSION_ID
99 :
100 : using CcTestExtensionFlags = v8::base::EnumSet<CcTestExtensionId>;
101 :
102 : #define DEFINE_EXTENSION_NAME(Name, Ident) Ident,
103 : static constexpr const char* kExtensionName[kMaxExtensions] = {
104 : EXTENSION_LIST(DEFINE_EXTENSION_NAME)};
105 : #undef DEFINE_EXTENSION_NAME
106 :
107 : class CcTest {
108 : public:
109 : typedef void (TestFunction)();
110 : CcTest(TestFunction* callback, const char* file, const char* name,
111 : bool enabled, bool initialize);
112 320999950 : ~CcTest() { i::DeleteArray(file_); }
113 : void Run();
114 38566 : static CcTest* last() { return last_; }
115 : CcTest* prev() { return prev_; }
116 : const char* file() { return file_; }
117 : const char* name() { return name_; }
118 : bool enabled() { return enabled_; }
119 :
120 16042708 : static v8::Isolate* isolate() {
121 16042708 : CHECK_NOT_NULL(isolate_);
122 : v8::base::Relaxed_Store(&isolate_used_, 1);
123 16042708 : return isolate_;
124 : }
125 :
126 : static i::Isolate* InitIsolateOnce() {
127 12916513 : if (!initialize_called_) InitializeVM();
128 : return i_isolate();
129 : }
130 :
131 : static i::Isolate* i_isolate() {
132 15786421 : return reinterpret_cast<i::Isolate*>(isolate());
133 : }
134 :
135 : static i::Heap* heap();
136 :
137 : static void CollectGarbage(i::AllocationSpace space);
138 : static void CollectAllGarbage(i::Isolate* isolate = nullptr);
139 : static void CollectAllAvailableGarbage(i::Isolate* isolate = nullptr);
140 : static void PreciseCollectAllGarbage(i::Isolate* isolate = nullptr);
141 :
142 : static v8::base::RandomNumberGenerator* random_number_generator();
143 :
144 : static v8::Local<v8::Object> global();
145 :
146 : static v8::ArrayBuffer::Allocator* array_buffer_allocator() {
147 1536 : return allocator_;
148 : }
149 :
150 : static void set_array_buffer_allocator(
151 : v8::ArrayBuffer::Allocator* allocator) {
152 26639 : allocator_ = allocator;
153 : }
154 :
155 : // TODO(dcarney): Remove.
156 : // This must be called first in a test.
157 : static void InitializeVM();
158 :
159 : // Only for UNINITIALIZED_TESTs
160 : static void DisableAutomaticDispose();
161 :
162 : // Helper function to configure a context.
163 : // Must be in a HandleScope.
164 : static v8::Local<v8::Context> NewContext(
165 : v8::Isolate* isolate = CcTest::isolate()) {
166 : return NewContext({}, isolate);
167 : }
168 : static v8::Local<v8::Context> NewContext(
169 : CcTestExtensionFlags extension_flags,
170 : v8::Isolate* isolate = CcTest::isolate());
171 :
172 : static void TearDown();
173 :
174 : private:
175 : friend int main(int argc, char** argv);
176 : TestFunction* callback_;
177 : const char* file_;
178 : const char* name_;
179 : bool enabled_;
180 : bool initialize_;
181 : CcTest* prev_;
182 : static CcTest* last_;
183 : static v8::ArrayBuffer::Allocator* allocator_;
184 : static v8::Isolate* isolate_;
185 : static bool initialize_called_;
186 : static v8::base::Atomic32 isolate_used_;
187 : };
188 :
189 : // Switches between all the Api tests using the threading support.
190 : // In order to get a surprising but repeatable pattern of thread
191 : // switching it has extra semaphores to control the order in which
192 : // the tests alternate, not relying solely on the big V8 lock.
193 : //
194 : // A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
195 : // callbacks. This will have no effect when we are not running the
196 : // thread fuzzing test. In the thread fuzzing test it will
197 : // pseudorandomly select a successor thread and switch execution
198 : // to that thread, suspending the current test.
199 : class ApiTestFuzzer: public v8::base::Thread {
200 : public:
201 : void CallTest();
202 :
203 : // The ApiTestFuzzer is also a Thread, so it has a Run method.
204 : void Run() override;
205 :
206 : enum PartOfTest {
207 : FIRST_PART,
208 : SECOND_PART,
209 : THIRD_PART,
210 : FOURTH_PART,
211 : FIFTH_PART,
212 : SIXTH_PART,
213 : SEVENTH_PART,
214 : EIGHTH_PART,
215 : LAST_PART = EIGHTH_PART
216 : };
217 :
218 : static void SetUp(PartOfTest part);
219 : static void RunAllTests();
220 : static void TearDown();
221 : // This method switches threads if we are running the Threading test.
222 : // Otherwise it does nothing.
223 : static void Fuzz();
224 :
225 : private:
226 480 : explicit ApiTestFuzzer(int num)
227 : : Thread(Options("ApiTestFuzzer")),
228 : test_number_(num),
229 : gate_(0),
230 480 : active_(true) {}
231 0 : ~ApiTestFuzzer() override = default;
232 :
233 : static bool fuzzing_;
234 : static int tests_being_run_;
235 : static int current_;
236 : static int active_tests_;
237 : static bool NextThread();
238 : int test_number_;
239 : v8::base::Semaphore gate_;
240 : bool active_;
241 : void ContextSwitch();
242 : static int GetNextTestNumber();
243 : static v8::base::Semaphore all_tests_done_;
244 : };
245 :
246 :
247 : #define THREADED_TEST(Name) \
248 : static void Test##Name(); \
249 : RegisterThreadedTest register_##Name(Test##Name, #Name); \
250 : /* */ TEST(Name)
251 :
252 : class RegisterThreadedTest {
253 : public:
254 : explicit RegisterThreadedTest(CcTest::TestFunction* callback,
255 : const char* name)
256 12786720 : : fuzzer_(nullptr), callback_(callback), name_(name) {
257 12786720 : prev_ = first_;
258 12786720 : first_ = this;
259 12786720 : count_++;
260 : }
261 3461289 : static int count() { return count_; }
262 3457433 : static RegisterThreadedTest* nth(int i) {
263 3457433 : CHECK(i < count());
264 3457433 : RegisterThreadedTest* current = first_;
265 208328149 : while (i > 0) {
266 102435358 : i--;
267 102435358 : current = current->prev_;
268 : }
269 3457433 : return current;
270 : }
271 : CcTest::TestFunction* callback() { return callback_; }
272 : ApiTestFuzzer* fuzzer_;
273 : const char* name() { return name_; }
274 :
275 : private:
276 : static RegisterThreadedTest* first_;
277 : static int count_;
278 : CcTest::TestFunction* callback_;
279 : RegisterThreadedTest* prev_;
280 : const char* name_;
281 : };
282 :
283 : // A LocalContext holds a reference to a v8::Context.
284 : class LocalContext {
285 : public:
286 : LocalContext(v8::Isolate* isolate,
287 : v8::ExtensionConfiguration* extensions = nullptr,
288 : v8::Local<v8::ObjectTemplate> global_template =
289 : v8::Local<v8::ObjectTemplate>(),
290 2461 : v8::Local<v8::Value> global_object = v8::Local<v8::Value>()) {
291 2461 : Initialize(isolate, extensions, global_template, global_object);
292 : }
293 :
294 : LocalContext(v8::ExtensionConfiguration* extensions = nullptr,
295 : v8::Local<v8::ObjectTemplate> global_template =
296 : v8::Local<v8::ObjectTemplate>(),
297 9441 : v8::Local<v8::Value> global_object = v8::Local<v8::Value>()) {
298 9441 : Initialize(CcTest::isolate(), extensions, global_template, global_object);
299 : }
300 :
301 : virtual ~LocalContext();
302 :
303 : v8::Context* operator->() {
304 112796 : return *reinterpret_cast<v8::Context**>(&context_);
305 : }
306 : v8::Context* operator*() { return operator->(); }
307 : bool IsReady() { return !context_.IsEmpty(); }
308 :
309 : v8::Local<v8::Context> local() {
310 188204 : return v8::Local<v8::Context>::New(isolate_, context_);
311 : }
312 :
313 : private:
314 : void Initialize(v8::Isolate* isolate, v8::ExtensionConfiguration* extensions,
315 : v8::Local<v8::ObjectTemplate> global_template,
316 : v8::Local<v8::Value> global_object);
317 :
318 : v8::Persistent<v8::Context> context_;
319 : v8::Isolate* isolate_;
320 : };
321 :
322 :
323 26762 : static inline uint16_t* AsciiToTwoByteString(const char* source) {
324 26762 : int array_length = i::StrLength(source) + 1;
325 26762 : uint16_t* converted = i::NewArray<uint16_t>(array_length);
326 269362 : for (int i = 0; i < array_length; i++) converted[i] = source[i];
327 26762 : return converted;
328 : }
329 :
330 : template <typename T>
331 134 : static inline i::Handle<T> GetGlobal(const char* name) {
332 : i::Isolate* isolate = CcTest::i_isolate();
333 : i::Handle<i::String> str_name =
334 134 : isolate->factory()->InternalizeUtf8String(name);
335 :
336 : i::Handle<i::Object> value =
337 268 : i::Object::GetProperty(isolate, isolate->global_object(), str_name)
338 268 : .ToHandleChecked();
339 134 : return i::Handle<T>::cast(value);
340 : }
341 :
342 : static inline v8::Local<v8::Boolean> v8_bool(bool val) {
343 60 : return v8::Boolean::New(v8::Isolate::GetCurrent(), val);
344 : }
345 :
346 77377 : static inline v8::Local<v8::Value> v8_num(double x) {
347 77377 : return v8::Number::New(v8::Isolate::GetCurrent(), x);
348 : }
349 :
350 : static inline v8::Local<v8::Integer> v8_int(int32_t x) {
351 40 : return v8::Integer::New(v8::Isolate::GetCurrent(), x);
352 : }
353 :
354 516671 : static inline v8::Local<v8::String> v8_str(const char* x) {
355 516672 : return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), x,
356 516671 : v8::NewStringType::kNormal)
357 516671 : .ToLocalChecked();
358 : }
359 :
360 :
361 1024 : static inline v8::Local<v8::String> v8_str(v8::Isolate* isolate,
362 : const char* x) {
363 1024 : return v8::String::NewFromUtf8(isolate, x, v8::NewStringType::kNormal)
364 1024 : .ToLocalChecked();
365 : }
366 :
367 :
368 5 : static inline v8::Local<v8::Symbol> v8_symbol(const char* name) {
369 5 : return v8::Symbol::New(v8::Isolate::GetCurrent(), v8_str(name));
370 : }
371 :
372 :
373 116858 : static inline v8::Local<v8::Script> v8_compile(v8::Local<v8::String> x) {
374 : v8::Local<v8::Script> result;
375 233716 : if (v8::Script::Compile(v8::Isolate::GetCurrent()->GetCurrentContext(), x)
376 : .ToLocal(&result)) {
377 116848 : return result;
378 : }
379 10 : return v8::Local<v8::Script>();
380 : }
381 :
382 :
383 : static inline v8::Local<v8::Script> v8_compile(const char* x) {
384 2232 : return v8_compile(v8_str(x));
385 : }
386 :
387 :
388 2054 : static inline int32_t v8_run_int32value(v8::Local<v8::Script> script) {
389 2054 : v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
390 6162 : return script->Run(context).ToLocalChecked()->Int32Value(context).FromJust();
391 : }
392 :
393 60 : static inline v8::Local<v8::Script> CompileWithOrigin(
394 : v8::Local<v8::String> source, v8::Local<v8::String> origin_url,
395 : v8::Local<v8::Boolean> is_shared_cross_origin) {
396 : v8::ScriptOrigin origin(origin_url, v8::Local<v8::Integer>(),
397 : v8::Local<v8::Integer>(), is_shared_cross_origin);
398 : v8::ScriptCompiler::Source script_source(source, origin);
399 60 : return v8::ScriptCompiler::Compile(
400 60 : v8::Isolate::GetCurrent()->GetCurrentContext(), &script_source)
401 60 : .ToLocalChecked();
402 : }
403 :
404 23 : static inline v8::Local<v8::Script> CompileWithOrigin(
405 : v8::Local<v8::String> source, const char* origin_url,
406 : bool is_shared_cross_origin) {
407 : return CompileWithOrigin(source, v8_str(origin_url),
408 23 : v8_bool(is_shared_cross_origin));
409 : }
410 :
411 27 : static inline v8::Local<v8::Script> CompileWithOrigin(
412 : const char* source, const char* origin_url, bool is_shared_cross_origin) {
413 : return CompileWithOrigin(v8_str(source), v8_str(origin_url),
414 27 : v8_bool(is_shared_cross_origin));
415 : }
416 :
417 : // Helper functions that compile and run the source.
418 273 : static inline v8::MaybeLocal<v8::Value> CompileRun(
419 : v8::Local<v8::Context> context, const char* source) {
420 273 : return v8::Script::Compile(context, v8_str(source))
421 : .ToLocalChecked()
422 273 : ->Run(context);
423 : }
424 :
425 :
426 543 : static inline v8::Local<v8::Value> CompileRunChecked(v8::Isolate* isolate,
427 : const char* source) {
428 : v8::Local<v8::String> source_string =
429 543 : v8::String::NewFromUtf8(isolate, source, v8::NewStringType::kNormal)
430 543 : .ToLocalChecked();
431 543 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
432 : v8::Local<v8::Script> script =
433 543 : v8::Script::Compile(context, source_string).ToLocalChecked();
434 1086 : return script->Run(context).ToLocalChecked();
435 : }
436 :
437 :
438 114488 : static inline v8::Local<v8::Value> CompileRun(v8::Local<v8::String> source) {
439 : v8::Local<v8::Value> result;
440 228978 : if (v8_compile(source)
441 228977 : ->Run(v8::Isolate::GetCurrent()->GetCurrentContext())
442 : .ToLocal(&result)) {
443 111876 : return result;
444 : }
445 2613 : return v8::Local<v8::Value>();
446 : }
447 :
448 :
449 : // Helper functions that compile and run the source.
450 : static inline v8::Local<v8::Value> CompileRun(const char* source) {
451 112625 : return CompileRun(v8_str(source));
452 : }
453 :
454 :
455 80 : static inline v8::Local<v8::Value> CompileRun(
456 : v8::Local<v8::Context> context, v8::ScriptCompiler::Source* script_source,
457 : v8::ScriptCompiler::CompileOptions options) {
458 : v8::Local<v8::Value> result;
459 160 : if (v8::ScriptCompiler::Compile(context, script_source, options)
460 : .ToLocalChecked()
461 80 : ->Run(context)
462 : .ToLocal(&result)) {
463 60 : return result;
464 : }
465 20 : return v8::Local<v8::Value>();
466 : }
467 :
468 :
469 : // Helper functions that compile and run the source with given origin.
470 60 : static inline v8::Local<v8::Value> CompileRunWithOrigin(const char* source,
471 : const char* origin_url,
472 : int line_number,
473 : int column_number) {
474 60 : v8::Isolate* isolate = v8::Isolate::GetCurrent();
475 60 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
476 : v8::ScriptOrigin origin(v8_str(origin_url),
477 : v8::Integer::New(isolate, line_number),
478 60 : v8::Integer::New(isolate, column_number));
479 60 : v8::ScriptCompiler::Source script_source(v8_str(source), origin);
480 : return CompileRun(context, &script_source,
481 120 : v8::ScriptCompiler::CompileOptions());
482 : }
483 :
484 :
485 20 : static inline v8::Local<v8::Value> CompileRunWithOrigin(
486 : v8::Local<v8::String> source, const char* origin_url) {
487 20 : v8::Isolate* isolate = v8::Isolate::GetCurrent();
488 20 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
489 : v8::ScriptCompiler::Source script_source(
490 20 : source, v8::ScriptOrigin(v8_str(origin_url)));
491 : return CompileRun(context, &script_source,
492 40 : v8::ScriptCompiler::CompileOptions());
493 : }
494 :
495 :
496 : static inline v8::Local<v8::Value> CompileRunWithOrigin(
497 : const char* source, const char* origin_url) {
498 20 : return CompileRunWithOrigin(v8_str(source), origin_url);
499 : }
500 :
501 : // Takes a JSFunction and runs it through the test version of the optimizing
502 : // pipeline, allocating the temporary compilation artifacts in a given Zone.
503 : // For possible {flags} values, look at OptimizedCompilationInfo::Flag.
504 : // If passed a non-null pointer for {broker}, outputs the JSHeapBroker to it.
505 : i::Handle<i::JSFunction> Optimize(
506 : i::Handle<i::JSFunction> function, i::Zone* zone, i::Isolate* isolate,
507 : uint32_t flags, i::compiler::JSHeapBroker** out_broker = nullptr);
508 :
509 872 : static inline void ExpectString(const char* code, const char* expected) {
510 : v8::Local<v8::Value> result = CompileRun(code);
511 872 : CHECK(result->IsString());
512 1744 : v8::String::Utf8Value utf8(v8::Isolate::GetCurrent(), result);
513 872 : CHECK_EQ(0, strcmp(expected, *utf8));
514 872 : }
515 :
516 :
517 1238 : static inline void ExpectInt32(const char* code, int expected) {
518 : v8::Local<v8::Value> result = CompileRun(code);
519 1238 : CHECK(result->IsInt32());
520 2476 : CHECK_EQ(expected,
521 : result->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext())
522 : .FromJust());
523 1238 : }
524 :
525 :
526 882 : static inline void ExpectBoolean(const char* code, bool expected) {
527 : v8::Local<v8::Value> result = CompileRun(code);
528 882 : CHECK(result->IsBoolean());
529 882 : CHECK_EQ(expected, result->BooleanValue(v8::Isolate::GetCurrent()));
530 882 : }
531 :
532 :
533 : static inline void ExpectTrue(const char* code) {
534 254 : ExpectBoolean(code, true);
535 : }
536 :
537 :
538 : static inline void ExpectFalse(const char* code) {
539 89 : ExpectBoolean(code, false);
540 : }
541 :
542 :
543 92 : static inline void ExpectObject(const char* code,
544 : v8::Local<v8::Value> expected) {
545 : v8::Local<v8::Value> result = CompileRun(code);
546 92 : CHECK(result->SameValue(expected));
547 92 : }
548 :
549 :
550 42 : static inline void ExpectUndefined(const char* code) {
551 : v8::Local<v8::Value> result = CompileRun(code);
552 42 : CHECK(result->IsUndefined());
553 42 : }
554 :
555 :
556 : static inline void ExpectNull(const char* code) {
557 : v8::Local<v8::Value> result = CompileRun(code);
558 : CHECK(result->IsNull());
559 : }
560 :
561 :
562 5 : static inline void CheckDoubleEquals(double expected, double actual) {
563 : const double kEpsilon = 1e-10;
564 10 : CHECK_LE(expected, actual + kEpsilon);
565 10 : CHECK_GE(expected, actual - kEpsilon);
566 5 : }
567 :
568 4848298 : static v8::debug::DebugDelegate dummy_delegate;
569 :
570 : static inline void EnableDebugger(v8::Isolate* isolate) {
571 30 : v8::debug::SetDebugDelegate(isolate, &dummy_delegate);
572 : }
573 :
574 :
575 : static inline void DisableDebugger(v8::Isolate* isolate) {
576 25 : v8::debug::SetDebugDelegate(isolate, nullptr);
577 : }
578 :
579 :
580 26183 : static inline void EmptyMessageQueues(v8::Isolate* isolate) {
581 45340 : while (v8::platform::PumpMessageLoop(v8::internal::V8::GetCurrentPlatform(),
582 : isolate)) {
583 : }
584 26183 : }
585 :
586 : class InitializedHandleScopeImpl;
587 :
588 1446740 : class InitializedHandleScope {
589 : public:
590 : InitializedHandleScope();
591 : ~InitializedHandleScope();
592 :
593 : // Prefixing the below with main_ reduces a lot of naming clashes.
594 : i::Isolate* main_isolate() { return main_isolate_; }
595 :
596 : private:
597 : i::Isolate* main_isolate_;
598 : std::unique_ptr<InitializedHandleScopeImpl> initialized_handle_scope_impl_;
599 : };
600 :
601 2885760 : class HandleAndZoneScope : public InitializedHandleScope {
602 : public:
603 : HandleAndZoneScope();
604 : ~HandleAndZoneScope();
605 :
606 : // Prefixing the below with main_ reduces a lot of naming clashes.
607 : i::Zone* main_zone() { return main_zone_.get(); }
608 :
609 : private:
610 : v8::internal::AccountingAllocator allocator_;
611 : std::unique_ptr<i::Zone> main_zone_;
612 : };
613 :
614 : class StaticOneByteResource : public v8::String::ExternalOneByteStringResource {
615 : public:
616 5 : explicit StaticOneByteResource(const char* data) : data_(data) {}
617 :
618 10 : ~StaticOneByteResource() override = default;
619 :
620 10 : const char* data() const override { return data_; }
621 :
622 20 : size_t length() const override { return strlen(data_); }
623 :
624 : private:
625 : const char* data_;
626 : };
627 :
628 : class ManualGCScope {
629 : public:
630 : ManualGCScope()
631 : : flag_concurrent_marking_(i::FLAG_concurrent_marking),
632 : flag_concurrent_sweeping_(i::FLAG_concurrent_sweeping),
633 : flag_stress_incremental_marking_(i::FLAG_stress_incremental_marking),
634 : flag_parallel_marking_(i::FLAG_parallel_marking),
635 : flag_detect_ineffective_gcs_near_heap_limit_(
636 502 : i::FLAG_detect_ineffective_gcs_near_heap_limit) {
637 507 : i::FLAG_concurrent_marking = false;
638 507 : i::FLAG_concurrent_sweeping = false;
639 507 : i::FLAG_stress_incremental_marking = false;
640 : // Parallel marking has a dependency on concurrent marking.
641 507 : i::FLAG_parallel_marking = false;
642 507 : i::FLAG_detect_ineffective_gcs_near_heap_limit = false;
643 : }
644 : ~ManualGCScope() {
645 507 : i::FLAG_concurrent_marking = flag_concurrent_marking_;
646 507 : i::FLAG_concurrent_sweeping = flag_concurrent_sweeping_;
647 507 : i::FLAG_stress_incremental_marking = flag_stress_incremental_marking_;
648 507 : i::FLAG_parallel_marking = flag_parallel_marking_;
649 : i::FLAG_detect_ineffective_gcs_near_heap_limit =
650 507 : flag_detect_ineffective_gcs_near_heap_limit_;
651 : }
652 :
653 : private:
654 : bool flag_concurrent_marking_;
655 : bool flag_concurrent_sweeping_;
656 : bool flag_stress_incremental_marking_;
657 : bool flag_parallel_marking_;
658 : bool flag_detect_ineffective_gcs_near_heap_limit_;
659 : };
660 :
661 : // This is an abstract base class that can be overridden to implement a test
662 : // platform. It delegates all operations to a given platform at the time
663 : // of construction.
664 : class TestPlatform : public v8::Platform {
665 : public:
666 : // v8::Platform implementation.
667 0 : v8::PageAllocator* GetPageAllocator() override {
668 0 : return old_platform_->GetPageAllocator();
669 : }
670 :
671 0 : void OnCriticalMemoryPressure() override {
672 0 : old_platform_->OnCriticalMemoryPressure();
673 0 : }
674 :
675 0 : bool OnCriticalMemoryPressure(size_t length) override {
676 0 : return old_platform_->OnCriticalMemoryPressure(length);
677 : }
678 :
679 191 : int NumberOfWorkerThreads() override {
680 191 : return old_platform_->NumberOfWorkerThreads();
681 : }
682 :
683 6 : std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner(
684 : v8::Isolate* isolate) override {
685 6 : return old_platform_->GetForegroundTaskRunner(isolate);
686 : }
687 :
688 7 : void CallOnWorkerThread(std::unique_ptr<v8::Task> task) override {
689 21 : old_platform_->CallOnWorkerThread(std::move(task));
690 7 : }
691 :
692 0 : void CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task,
693 : double delay_in_seconds) override {
694 0 : old_platform_->CallDelayedOnWorkerThread(std::move(task), delay_in_seconds);
695 0 : }
696 :
697 0 : void CallOnForegroundThread(v8::Isolate* isolate, v8::Task* task) override {
698 : // This is a deprecated function and should not be called anymore.
699 0 : UNREACHABLE();
700 : }
701 :
702 0 : void CallDelayedOnForegroundThread(v8::Isolate* isolate, v8::Task* task,
703 : double delay_in_seconds) override {
704 : // This is a deprecated function and should not be called anymore.
705 0 : UNREACHABLE();
706 : }
707 :
708 18848 : double MonotonicallyIncreasingTime() override {
709 18848 : return old_platform_->MonotonicallyIncreasingTime();
710 : }
711 :
712 0 : double CurrentClockTimeMillis() override {
713 0 : return old_platform_->CurrentClockTimeMillis();
714 : }
715 :
716 0 : void CallIdleOnForegroundThread(v8::Isolate* isolate,
717 : v8::IdleTask* task) override {
718 : // This is a deprecated function and should not be called anymore.
719 0 : UNREACHABLE();
720 : }
721 :
722 0 : bool IdleTasksEnabled(v8::Isolate* isolate) override {
723 0 : return old_platform_->IdleTasksEnabled(isolate);
724 : }
725 :
726 3810 : v8::TracingController* GetTracingController() override {
727 3810 : return old_platform_->GetTracingController();
728 : }
729 :
730 : protected:
731 244 : TestPlatform() : old_platform_(i::V8::GetCurrentPlatform()) {}
732 458 : ~TestPlatform() override { i::V8::SetPlatformForTesting(old_platform_); }
733 :
734 : v8::Platform* old_platform() const { return old_platform_; }
735 :
736 : private:
737 : v8::Platform* old_platform_;
738 :
739 : DISALLOW_COPY_AND_ASSIGN(TestPlatform);
740 : };
741 :
742 : #endif // ifndef CCTEST_H_
|