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(
V8_PLATFORM_EXPORT bool PumpMessageLoop(v8::Platform* platform,
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.
*
......
......@@ -27,6 +27,7 @@
#include "src/base/debug/stack_trace.h"
#include "src/base/logging.h"
#include "src/base/platform/platform.h"
#include "src/base/platform/time.h"
#include "src/base/sys-info.h"
#include "src/basic-block-profiler.h"
#include "src/interpreter/interpreter.h"
......@@ -2595,6 +2596,8 @@ void Shell::CollectGarbage(Isolate* isolate) {
void Shell::EmptyMessageQueues(Isolate* isolate) {
if (!i::FLAG_verify_predictable) {
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) {
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(
v8::Platform* platform,
v8::platform::tracing::TracingController* tracing_controller) {
......@@ -69,6 +75,12 @@ DefaultPlatform::~DefaultPlatform() {
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) {
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) {
Task* task = NULL;
......@@ -142,8 +163,25 @@ bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate) {
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) {
EnsureInitialized();
queue_.Append(task);
......@@ -164,15 +202,13 @@ void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate,
main_thread_delayed_queue_[isolate].push(std::make_pair(deadline, task));
}
void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate,
IdleTask* task) {
UNREACHABLE();
base::LockGuard<base::Mutex> guard(&lock_);
main_thread_idle_queue_[isolate].push(task);
}
bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) { return false; }
bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) { return true; }
double DefaultPlatform::MonotonicallyIncreasingTime() {
return base::TimeTicks::HighResolutionNow().ToInternalValue() /
......
......@@ -41,6 +41,8 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) {
bool PumpMessageLoop(v8::Isolate* isolate);
void RunIdleTasks(v8::Isolate* isolate, double idle_time_in_seconds);
// v8::Platform implementation.
size_t NumberOfAvailableBackgroundThreads() override;
void CallOnBackgroundThread(Task* task,
......@@ -74,13 +76,15 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) {
Task* PopTaskInMainThreadQueue(v8::Isolate* isolate);
Task* PopTaskInMainThreadDelayedQueue(v8::Isolate* isolate);
IdleTask* PopTaskInMainThreadIdleQueue(v8::Isolate* isolate);
base::Mutex lock_;
bool initialized_;
int thread_pool_size_;
std::vector<WorkerThread*> thread_pool_;
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;
std::map<v8::Isolate*,
......
......@@ -19,6 +19,11 @@ struct MockTask : public Task {
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 {
public:
......@@ -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 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