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:
parent
c0f255f075
commit
d651ce314c
@ -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));
|
||||
|
@ -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.
|
||||
|
@ -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_--;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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",
|
||||
|
@ -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
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user