// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" #include "src/base/atomic-utils.h" #include "src/base/platform/semaphore.h" #include "src/compilation-info.h" #include "src/compiler.h" #include "src/handles.h" #include "src/isolate.h" #include "src/objects-inl.h" #include "src/parsing/parse-info.h" #include "test/unittests/test-helpers.h" #include "test/unittests/test-utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace v8 { namespace internal { typedef TestWithNativeContext OptimizingCompileDispatcherTest; namespace { class BlockingCompilationJob : public CompilationJob { public: BlockingCompilationJob(Isolate* isolate, Handle function) : CompilationJob(isolate->stack_guard()->real_climit(), &parse_info_, &info_, "BlockingCompilationJob", State::kReadyToExecute), shared_(function->shared()), parse_info_(shared_), info_(parse_info_.zone(), function->GetIsolate(), shared_, function), blocking_(false), semaphore_(0) {} ~BlockingCompilationJob() override = default; bool IsBlocking() const { return blocking_.Value(); } void Signal() { semaphore_.Signal(); } // CompilationJob implementation. Status PrepareJobImpl(Isolate* isolate) override { UNREACHABLE(); } Status ExecuteJobImpl() override { blocking_.SetValue(true); semaphore_.Wait(); blocking_.SetValue(false); return SUCCEEDED; } Status FinalizeJobImpl(Isolate* isolate) override { return SUCCEEDED; } private: Handle shared_; ParseInfo parse_info_; CompilationInfo info_; base::AtomicValue blocking_; base::Semaphore semaphore_; DISALLOW_COPY_AND_ASSIGN(BlockingCompilationJob); }; } // namespace TEST_F(OptimizingCompileDispatcherTest, Construct) { OptimizingCompileDispatcher dispatcher(i_isolate()); ASSERT_TRUE(OptimizingCompileDispatcher::Enabled()); ASSERT_TRUE(dispatcher.IsQueueAvailable()); } TEST_F(OptimizingCompileDispatcherTest, NonBlockingFlush) { Handle fun = RunJS("function f() { function g() {}; return g;}; f();"); BlockingCompilationJob* job = new BlockingCompilationJob(i_isolate(), fun); OptimizingCompileDispatcher dispatcher(i_isolate()); ASSERT_TRUE(OptimizingCompileDispatcher::Enabled()); ASSERT_TRUE(dispatcher.IsQueueAvailable()); dispatcher.QueueForOptimization(job); // Busy-wait for the job to run on a background thread. while (!job->IsBlocking()) { } // Should not block. dispatcher.Flush(OptimizingCompileDispatcher::BlockingBehavior::kDontBlock); // Unblock the job & finish. job->Signal(); dispatcher.Stop(); } } // namespace internal } // namespace v8