Commit 1795343f authored by jochen's avatar jochen Committed by Commit bot

Add support for idle tasks to the default platform

BUG=

Review-Url: https://codereview.chromium.org/2609833003
Cr-Commit-Position: refs/heads/master@{#42022}
parent d3ed71ed
...@@ -34,6 +34,17 @@ V8_PLATFORM_EXPORT v8::Platform* CreateDefaultPlatform( ...@@ -34,6 +34,17 @@ V8_PLATFORM_EXPORT v8::Platform* CreateDefaultPlatform(
V8_PLATFORM_EXPORT bool PumpMessageLoop(v8::Platform* platform, V8_PLATFORM_EXPORT bool PumpMessageLoop(v8::Platform* platform,
v8::Isolate* isolate); v8::Isolate* isolate);
/**
* Runs pending idle tasks for at most |idle_time_in_seconds| seconds.
*
* The caller has to make sure that this is called from the right thread.
* This call does not block if no task is pending. The |platform| has to be
* created using |CreateDefaultPlatform|.
*/
V8_PLATFORM_EXPORT void RunIdleTasks(v8::Platform* platform,
v8::Isolate* isolate,
double idle_time_in_seconds);
/** /**
* Attempts to set the tracing controller for the given platform. * Attempts to set the tracing controller for the given platform.
* *
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "src/base/debug/stack_trace.h" #include "src/base/debug/stack_trace.h"
#include "src/base/logging.h" #include "src/base/logging.h"
#include "src/base/platform/platform.h" #include "src/base/platform/platform.h"
#include "src/base/platform/time.h"
#include "src/base/sys-info.h" #include "src/base/sys-info.h"
#include "src/basic-block-profiler.h" #include "src/basic-block-profiler.h"
#include "src/interpreter/interpreter.h" #include "src/interpreter/interpreter.h"
...@@ -2595,6 +2596,8 @@ void Shell::CollectGarbage(Isolate* isolate) { ...@@ -2595,6 +2596,8 @@ void Shell::CollectGarbage(Isolate* isolate) {
void Shell::EmptyMessageQueues(Isolate* isolate) { void Shell::EmptyMessageQueues(Isolate* isolate) {
if (!i::FLAG_verify_predictable) { if (!i::FLAG_verify_predictable) {
while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue; while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue;
v8::platform::RunIdleTasks(g_platform, isolate,
50.0 / base::Time::kMillisecondsPerSecond);
} }
} }
......
...@@ -30,6 +30,12 @@ bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate) { ...@@ -30,6 +30,12 @@ bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate) {
return reinterpret_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate); return reinterpret_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate);
} }
void RunIdleTasks(v8::Platform* platform, v8::Isolate* isolate,
double idle_time_in_seconds) {
reinterpret_cast<DefaultPlatform*>(platform)->RunIdleTasks(
isolate, idle_time_in_seconds);
}
void SetTracingController( void SetTracingController(
v8::Platform* platform, v8::Platform* platform,
v8::platform::tracing::TracingController* tracing_controller) { v8::platform::tracing::TracingController* tracing_controller) {
...@@ -69,6 +75,12 @@ DefaultPlatform::~DefaultPlatform() { ...@@ -69,6 +75,12 @@ DefaultPlatform::~DefaultPlatform() {
i->second.pop(); i->second.pop();
} }
} }
for (auto& i : main_thread_idle_queue_) {
while (!i.second.empty()) {
delete i.second.front();
i.second.pop();
}
}
} }
...@@ -118,6 +130,15 @@ Task* DefaultPlatform::PopTaskInMainThreadDelayedQueue(v8::Isolate* isolate) { ...@@ -118,6 +130,15 @@ Task* DefaultPlatform::PopTaskInMainThreadDelayedQueue(v8::Isolate* isolate) {
return deadline_and_task.second; return deadline_and_task.second;
} }
IdleTask* DefaultPlatform::PopTaskInMainThreadIdleQueue(v8::Isolate* isolate) {
auto it = main_thread_idle_queue_.find(isolate);
if (it == main_thread_idle_queue_.end() || it->second.empty()) {
return nullptr;
}
IdleTask* task = it->second.front();
it->second.pop();
return task;
}
bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate) { bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate) {
Task* task = NULL; Task* task = NULL;
...@@ -142,8 +163,25 @@ bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate) { ...@@ -142,8 +163,25 @@ bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate) {
return true; return true;
} }
void DefaultPlatform::RunIdleTasks(v8::Isolate* isolate,
double idle_time_in_seconds) {
double deadline_in_seconds =
MonotonicallyIncreasingTime() + idle_time_in_seconds;
while (deadline_in_seconds > MonotonicallyIncreasingTime()) {
{
IdleTask* task;
{
base::LockGuard<base::Mutex> guard(&lock_);
task = PopTaskInMainThreadIdleQueue(isolate);
}
if (task == nullptr) return;
task->Run(deadline_in_seconds);
delete task;
}
}
}
void DefaultPlatform::CallOnBackgroundThread(Task *task, void DefaultPlatform::CallOnBackgroundThread(Task* task,
ExpectedRuntime expected_runtime) { ExpectedRuntime expected_runtime) {
EnsureInitialized(); EnsureInitialized();
queue_.Append(task); queue_.Append(task);
...@@ -164,15 +202,13 @@ void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate, ...@@ -164,15 +202,13 @@ void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate,
main_thread_delayed_queue_[isolate].push(std::make_pair(deadline, task)); main_thread_delayed_queue_[isolate].push(std::make_pair(deadline, task));
} }
void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate, void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate,
IdleTask* task) { IdleTask* task) {
UNREACHABLE(); base::LockGuard<base::Mutex> guard(&lock_);
main_thread_idle_queue_[isolate].push(task);
} }
bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) { return true; }
bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) { return false; }
double DefaultPlatform::MonotonicallyIncreasingTime() { double DefaultPlatform::MonotonicallyIncreasingTime() {
return base::TimeTicks::HighResolutionNow().ToInternalValue() / return base::TimeTicks::HighResolutionNow().ToInternalValue() /
......
...@@ -41,6 +41,8 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) { ...@@ -41,6 +41,8 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) {
bool PumpMessageLoop(v8::Isolate* isolate); bool PumpMessageLoop(v8::Isolate* isolate);
void RunIdleTasks(v8::Isolate* isolate, double idle_time_in_seconds);
// v8::Platform implementation. // v8::Platform implementation.
size_t NumberOfAvailableBackgroundThreads() override; size_t NumberOfAvailableBackgroundThreads() override;
void CallOnBackgroundThread(Task* task, void CallOnBackgroundThread(Task* task,
...@@ -74,13 +76,15 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) { ...@@ -74,13 +76,15 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) {
Task* PopTaskInMainThreadQueue(v8::Isolate* isolate); Task* PopTaskInMainThreadQueue(v8::Isolate* isolate);
Task* PopTaskInMainThreadDelayedQueue(v8::Isolate* isolate); Task* PopTaskInMainThreadDelayedQueue(v8::Isolate* isolate);
IdleTask* PopTaskInMainThreadIdleQueue(v8::Isolate* isolate);
base::Mutex lock_; base::Mutex lock_;
bool initialized_; bool initialized_;
int thread_pool_size_; int thread_pool_size_;
std::vector<WorkerThread*> thread_pool_; std::vector<WorkerThread*> thread_pool_;
TaskQueue queue_; TaskQueue queue_;
std::map<v8::Isolate*, std::queue<Task*> > main_thread_queue_; std::map<v8::Isolate*, std::queue<Task*>> main_thread_queue_;
std::map<v8::Isolate*, std::queue<IdleTask*>> main_thread_idle_queue_;
typedef std::pair<double, Task*> DelayedEntry; typedef std::pair<double, Task*> DelayedEntry;
std::map<v8::Isolate*, std::map<v8::Isolate*,
......
...@@ -19,6 +19,11 @@ struct MockTask : public Task { ...@@ -19,6 +19,11 @@ struct MockTask : public Task {
MOCK_METHOD0(Die, void()); MOCK_METHOD0(Die, void());
}; };
struct MockIdleTask : public IdleTask {
virtual ~MockIdleTask() { Die(); }
MOCK_METHOD1(Run, void(double deadline_in_seconds));
MOCK_METHOD0(Die, void());
};
class DefaultPlatformWithMockTime : public DefaultPlatform { class DefaultPlatformWithMockTime : public DefaultPlatform {
public: public:
...@@ -126,6 +131,35 @@ TEST(DefaultPlatformTest, PendingDelayedTasksAreDestroyedOnShutdown) { ...@@ -126,6 +131,35 @@ TEST(DefaultPlatformTest, PendingDelayedTasksAreDestroyedOnShutdown) {
} }
} }
TEST(DefaultPlatformTest, RunIdleTasks) {
InSequence s;
int dummy;
Isolate* isolate = reinterpret_cast<Isolate*>(&dummy);
DefaultPlatformWithMockTime platform;
StrictMock<MockIdleTask>* task = new StrictMock<MockIdleTask>;
platform.CallIdleOnForegroundThread(isolate, task);
EXPECT_CALL(*task, Run(42.0 + 23.0));
EXPECT_CALL(*task, Die());
platform.IncreaseTime(23.0);
platform.RunIdleTasks(isolate, 42.0);
}
TEST(DefaultPlatformTest, PendingIdleTasksAreDestroyedOnShutdown) {
InSequence s;
int dummy;
Isolate* isolate = reinterpret_cast<Isolate*>(&dummy);
{
DefaultPlatformWithMockTime platform;
StrictMock<MockIdleTask>* task = new StrictMock<MockIdleTask>;
platform.CallIdleOnForegroundThread(isolate, task);
EXPECT_CALL(*task, Die());
}
}
} // namespace platform } // namespace platform
} // namespace v8 } // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment