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)));
}
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) {
base::Release_Store(&value_, static_cast<base::AtomicWord>(new_value));

View File

@ -9,6 +9,7 @@
#include "src/compilation-dependencies.h"
#include "src/frames.h"
#include "src/globals.h"
#include "src/handles.h"
#include "src/objects.h"
#include "src/source-position-table.h"
@ -28,7 +29,7 @@ class Zone;
// CompilationInfo encapsulates some information known at compile time. It
// is constructed based on the resources available at compile-time.
class CompilationInfo final {
class V8_EXPORT_PRIVATE CompilationInfo final {
public:
// Various configuration flags for a compilation, as well as some properties
// 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 {
public:
explicit CompileTask(Isolate* isolate) : isolate_(isolate) {
OptimizingCompileDispatcher* dispatcher =
isolate_->optimizing_compile_dispatcher();
base::LockGuard<base::Mutex> lock_guard(&dispatcher->ref_count_mutex_);
++dispatcher->ref_count_;
explicit CompileTask(Isolate* isolate,
OptimizingCompileDispatcher* dispatcher)
: isolate_(isolate), dispatcher_(dispatcher) {
base::LockGuard<base::Mutex> lock_guard(&dispatcher_->ref_count_mutex_);
++dispatcher_->ref_count_;
}
virtual ~CompileTask() {}
@ -49,30 +49,29 @@ class OptimizingCompileDispatcher::CompileTask : public v8::Task {
DisallowHandleAllocation no_handles;
DisallowHandleDereference no_deref;
OptimizingCompileDispatcher* dispatcher =
isolate_->optimizing_compile_dispatcher();
{
TimerEventScope<TimerEventRecompileConcurrent> timer(isolate_);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.RecompileConcurrent");
if (dispatcher->recompilation_delay_ != 0) {
if (dispatcher_->recompilation_delay_ != 0) {
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_);
if (--dispatcher->ref_count_ == 0) {
dispatcher->ref_count_zero_.NotifyOne();
base::LockGuard<base::Mutex> lock_guard(&dispatcher_->ref_count_mutex_);
if (--dispatcher_->ref_count_ == 0) {
dispatcher_->ref_count_zero_.NotifyOne();
}
}
}
Isolate* isolate_;
OptimizingCompileDispatcher* dispatcher_;
DISALLOW_COPY_AND_ASSIGN(CompileTask);
};
@ -222,14 +221,14 @@ void OptimizingCompileDispatcher::QueueForOptimization(CompilationJob* job) {
blocked_jobs_++;
} else {
V8::GetCurrentPlatform()->CallOnBackgroundThread(
new CompileTask(isolate_), v8::Platform::kShortRunningTask);
new CompileTask(isolate_, this), v8::Platform::kShortRunningTask);
}
}
void OptimizingCompileDispatcher::Unblock() {
while (blocked_jobs_ > 0) {
V8::GetCurrentPlatform()->CallOnBackgroundThread(
new CompileTask(isolate_), v8::Platform::kShortRunningTask);
new CompileTask(isolate_, this), v8::Platform::kShortRunningTask);
blocked_jobs_--;
}
}

View File

@ -12,6 +12,7 @@
#include "src/base/platform/mutex.h"
#include "src/base/platform/platform.h"
#include "src/flags.h"
#include "src/globals.h"
#include "src/list.h"
namespace v8 {
@ -20,7 +21,7 @@ namespace internal {
class CompilationJob;
class SharedFunctionInfo;
class OptimizingCompileDispatcher {
class V8_EXPORT_PRIVATE OptimizingCompileDispatcher {
public:
enum class BlockingBehavior { kBlock, kDontBlock };
@ -38,9 +39,9 @@ class OptimizingCompileDispatcher {
~OptimizingCompileDispatcher();
void Run();
void Stop();
void Flush(BlockingBehavior blocking_behavior);
// Takes ownership of |job|.
void QueueForOptimization(CompilationJob* job);
void Unblock();
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
// the job can be checked using {state()}.
class CompilationJob {
class V8_EXPORT_PRIVATE CompilationJob {
public:
enum Status { SUCCEEDED, FAILED };
enum class State {

View File

@ -33,6 +33,7 @@ v8_executable("unittests") {
"compiler-dispatcher/compiler-dispatcher-job-unittest.cc",
"compiler-dispatcher/compiler-dispatcher-tracer-unittest.cc",
"compiler-dispatcher/compiler-dispatcher-unittest.cc",
"compiler-dispatcher/optimizing-compile-dispatcher-unittest.cc",
"compiler/branch-elimination-unittest.cc",
"compiler/bytecode-analysis-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-tracer-unittest.cc',
'compiler-dispatcher/compiler-dispatcher-unittest.cc',
'compiler-dispatcher/optimizing-compile-dispatcher-unittest.cc',
'counters-unittest.cc',
'eh-frame-iterator-unittest.cc',
'eh-frame-writer-unittest.cc',