Add a test for OptimizingCompileDispatcher::Flush's non-blocking behavior

R=mtrofin@chromium.org,verwaest@chromium.org
BUG=

Review-Url: https://codereview.chromium.org/2662883003
Cr-Commit-Position: refs/heads/master@{#42787}
This commit is contained in:
jochen 2017-01-30 11:27:00 -08:00 committed by Commit bot
parent c0f255f075
commit d651ce314c
8 changed files with 123 additions and 20 deletions

View File

@ -31,7 +31,9 @@ class AtomicNumber {
&value_, -static_cast<base::AtomicWord>(decrement))); &value_, -static_cast<base::AtomicWord>(decrement)));
} }
V8_INLINE T Value() { return static_cast<T>(base::Acquire_Load(&value_)); } V8_INLINE T Value() const {
return static_cast<T>(base::Acquire_Load(&value_));
}
V8_INLINE void SetValue(T new_value) { V8_INLINE void SetValue(T new_value) {
base::Release_Store(&value_, static_cast<base::AtomicWord>(new_value)); base::Release_Store(&value_, static_cast<base::AtomicWord>(new_value));

View File

@ -9,6 +9,7 @@
#include "src/compilation-dependencies.h" #include "src/compilation-dependencies.h"
#include "src/frames.h" #include "src/frames.h"
#include "src/globals.h"
#include "src/handles.h" #include "src/handles.h"
#include "src/objects.h" #include "src/objects.h"
#include "src/source-position-table.h" #include "src/source-position-table.h"
@ -28,7 +29,7 @@ class Zone;
// CompilationInfo encapsulates some information known at compile time. It // CompilationInfo encapsulates some information known at compile time. It
// is constructed based on the resources available at compile-time. // is constructed based on the resources available at compile-time.
class CompilationInfo final { class V8_EXPORT_PRIVATE CompilationInfo final {
public: public:
// Various configuration flags for a compilation, as well as some properties // Various configuration flags for a compilation, as well as some properties
// of the compiled code produced by a compilation. // of the compiled code produced by a compilation.

View File

@ -33,11 +33,11 @@ void DisposeCompilationJob(CompilationJob* job, bool restore_function_code) {
class OptimizingCompileDispatcher::CompileTask : public v8::Task { class OptimizingCompileDispatcher::CompileTask : public v8::Task {
public: public:
explicit CompileTask(Isolate* isolate) : isolate_(isolate) { explicit CompileTask(Isolate* isolate,
OptimizingCompileDispatcher* dispatcher = OptimizingCompileDispatcher* dispatcher)
isolate_->optimizing_compile_dispatcher(); : isolate_(isolate), dispatcher_(dispatcher) {
base::LockGuard<base::Mutex> lock_guard(&dispatcher->ref_count_mutex_); base::LockGuard<base::Mutex> lock_guard(&dispatcher_->ref_count_mutex_);
++dispatcher->ref_count_; ++dispatcher_->ref_count_;
} }
virtual ~CompileTask() {} virtual ~CompileTask() {}
@ -49,30 +49,29 @@ class OptimizingCompileDispatcher::CompileTask : public v8::Task {
DisallowHandleAllocation no_handles; DisallowHandleAllocation no_handles;
DisallowHandleDereference no_deref; DisallowHandleDereference no_deref;
OptimizingCompileDispatcher* dispatcher =
isolate_->optimizing_compile_dispatcher();
{ {
TimerEventScope<TimerEventRecompileConcurrent> timer(isolate_); TimerEventScope<TimerEventRecompileConcurrent> timer(isolate_);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.RecompileConcurrent"); "V8.RecompileConcurrent");
if (dispatcher->recompilation_delay_ != 0) { if (dispatcher_->recompilation_delay_ != 0) {
base::OS::Sleep(base::TimeDelta::FromMilliseconds( base::OS::Sleep(base::TimeDelta::FromMilliseconds(
dispatcher->recompilation_delay_)); dispatcher_->recompilation_delay_));
} }
dispatcher->CompileNext(dispatcher->NextInput(true)); dispatcher_->CompileNext(dispatcher_->NextInput(true));
} }
{ {
base::LockGuard<base::Mutex> lock_guard(&dispatcher->ref_count_mutex_); base::LockGuard<base::Mutex> lock_guard(&dispatcher_->ref_count_mutex_);
if (--dispatcher->ref_count_ == 0) { if (--dispatcher_->ref_count_ == 0) {
dispatcher->ref_count_zero_.NotifyOne(); dispatcher_->ref_count_zero_.NotifyOne();
} }
} }
} }
Isolate* isolate_; Isolate* isolate_;
OptimizingCompileDispatcher* dispatcher_;
DISALLOW_COPY_AND_ASSIGN(CompileTask); DISALLOW_COPY_AND_ASSIGN(CompileTask);
}; };
@ -222,14 +221,14 @@ void OptimizingCompileDispatcher::QueueForOptimization(CompilationJob* job) {
blocked_jobs_++; blocked_jobs_++;
} else { } else {
V8::GetCurrentPlatform()->CallOnBackgroundThread( V8::GetCurrentPlatform()->CallOnBackgroundThread(
new CompileTask(isolate_), v8::Platform::kShortRunningTask); new CompileTask(isolate_, this), v8::Platform::kShortRunningTask);
} }
} }
void OptimizingCompileDispatcher::Unblock() { void OptimizingCompileDispatcher::Unblock() {
while (blocked_jobs_ > 0) { while (blocked_jobs_ > 0) {
V8::GetCurrentPlatform()->CallOnBackgroundThread( V8::GetCurrentPlatform()->CallOnBackgroundThread(
new CompileTask(isolate_), v8::Platform::kShortRunningTask); new CompileTask(isolate_, this), v8::Platform::kShortRunningTask);
blocked_jobs_--; blocked_jobs_--;
} }
} }

View File

@ -12,6 +12,7 @@
#include "src/base/platform/mutex.h" #include "src/base/platform/mutex.h"
#include "src/base/platform/platform.h" #include "src/base/platform/platform.h"
#include "src/flags.h" #include "src/flags.h"
#include "src/globals.h"
#include "src/list.h" #include "src/list.h"
namespace v8 { namespace v8 {
@ -20,7 +21,7 @@ namespace internal {
class CompilationJob; class CompilationJob;
class SharedFunctionInfo; class SharedFunctionInfo;
class OptimizingCompileDispatcher { class V8_EXPORT_PRIVATE OptimizingCompileDispatcher {
public: public:
enum class BlockingBehavior { kBlock, kDontBlock }; enum class BlockingBehavior { kBlock, kDontBlock };
@ -38,9 +39,9 @@ class OptimizingCompileDispatcher {
~OptimizingCompileDispatcher(); ~OptimizingCompileDispatcher();
void Run();
void Stop(); void Stop();
void Flush(BlockingBehavior blocking_behavior); void Flush(BlockingBehavior blocking_behavior);
// Takes ownership of |job|.
void QueueForOptimization(CompilationJob* job); void QueueForOptimization(CompilationJob* job);
void Unblock(); void Unblock();
void InstallOptimizedFunctions(); void InstallOptimizedFunctions();

View File

@ -154,7 +154,7 @@ class V8_EXPORT_PRIVATE Compiler : public AllStatic {
// //
// Each of the three phases can either fail or succeed. The current state of // Each of the three phases can either fail or succeed. The current state of
// the job can be checked using {state()}. // the job can be checked using {state()}.
class CompilationJob { class V8_EXPORT_PRIVATE CompilationJob {
public: public:
enum Status { SUCCEEDED, FAILED }; enum Status { SUCCEEDED, FAILED };
enum class State { enum class State {

View File

@ -33,6 +33,7 @@ v8_executable("unittests") {
"compiler-dispatcher/compiler-dispatcher-job-unittest.cc", "compiler-dispatcher/compiler-dispatcher-job-unittest.cc",
"compiler-dispatcher/compiler-dispatcher-tracer-unittest.cc", "compiler-dispatcher/compiler-dispatcher-tracer-unittest.cc",
"compiler-dispatcher/compiler-dispatcher-unittest.cc", "compiler-dispatcher/compiler-dispatcher-unittest.cc",
"compiler-dispatcher/optimizing-compile-dispatcher-unittest.cc",
"compiler/branch-elimination-unittest.cc", "compiler/branch-elimination-unittest.cc",
"compiler/bytecode-analysis-unittest.cc", "compiler/bytecode-analysis-unittest.cc",
"compiler/checkpoint-elimination-unittest.cc", "compiler/checkpoint-elimination-unittest.cc",

View File

@ -0,0 +1,98 @@
// 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 "src/zone/zone.h"
#include "test/unittests/compiler-dispatcher/compiler-dispatcher-helper.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
typedef TestWithContext OptimizingCompileDispatcherTest;
namespace {
class BlockingCompilationJob : public CompilationJob {
public:
BlockingCompilationJob(Isolate* isolate, Handle<JSFunction> function)
: CompilationJob(isolate, &info_, "BlockingCompilationJob",
State::kReadyToExecute),
zone_(isolate->allocator(), ZONE_NAME),
parse_info_(&zone_, handle(function->shared())),
info_(&parse_info_, function),
blocking_(false),
semaphore_(0) {}
~BlockingCompilationJob() override = default;
bool IsBlocking() const { return blocking_.Value(); }
void Signal() { semaphore_.Signal(); }
// CompilationJob implementation.
Status PrepareJobImpl() override {
UNREACHABLE();
return FAILED;
}
Status ExecuteJobImpl() override {
blocking_.SetValue(true);
semaphore_.Wait();
blocking_.SetValue(false);
return SUCCEEDED;
}
Status FinalizeJobImpl() override { return SUCCEEDED; }
private:
Zone zone_;
ParseInfo parse_info_;
CompilationInfo info_;
base::AtomicValue<bool> 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<JSFunction> fun = Handle<JSFunction>::cast(
RunJS(isolate(), "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

View File

@ -87,6 +87,7 @@
'compiler-dispatcher/compiler-dispatcher-job-unittest.cc', 'compiler-dispatcher/compiler-dispatcher-job-unittest.cc',
'compiler-dispatcher/compiler-dispatcher-tracer-unittest.cc', 'compiler-dispatcher/compiler-dispatcher-tracer-unittest.cc',
'compiler-dispatcher/compiler-dispatcher-unittest.cc', 'compiler-dispatcher/compiler-dispatcher-unittest.cc',
'compiler-dispatcher/optimizing-compile-dispatcher-unittest.cc',
'counters-unittest.cc', 'counters-unittest.cc',
'eh-frame-iterator-unittest.cc', 'eh-frame-iterator-unittest.cc',
'eh-frame-writer-unittest.cc', 'eh-frame-writer-unittest.cc',