blob: 59697a94a1fed1b2c695918ab45aaf3af1ec8c34 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <stdlib.h>
6
7#ifdef __linux__
8#include <errno.h>
9#include <fcntl.h>
10#include <sys/stat.h>
11#include <sys/types.h>
12#include <unistd.h>
13#endif
14
15#include <utility>
16
17#include "src/v8.h"
18
19#include "src/full-codegen/full-codegen.h"
20#include "src/global-handles.h"
21#include "test/cctest/cctest.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010022#include "test/cctest/heap/heap-utils.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023
24using v8::IdleTask;
25using v8::Task;
26using v8::Isolate;
27
28namespace v8 {
29namespace internal {
30
31class MockPlatform : public v8::Platform {
32 public:
33 explicit MockPlatform(v8::Platform* platform)
34 : platform_(platform), idle_task_(nullptr), delayed_task_(nullptr) {}
35 virtual ~MockPlatform() {
36 delete idle_task_;
37 delete delayed_task_;
38 }
39
40 void CallOnBackgroundThread(Task* task,
41 ExpectedRuntime expected_runtime) override {
42 platform_->CallOnBackgroundThread(task, expected_runtime);
43 }
44
45 void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override {
46 platform_->CallOnForegroundThread(isolate, task);
47 }
48
49 void CallDelayedOnForegroundThread(v8::Isolate* isolate, Task* task,
50 double delay_in_seconds) override {
51 if (delayed_task_ != nullptr) {
52 delete delayed_task_;
53 }
54 delayed_task_ = task;
55 }
56
57 double MonotonicallyIncreasingTime() override {
58 return platform_->MonotonicallyIncreasingTime();
59 }
60
61 void CallIdleOnForegroundThread(v8::Isolate* isolate,
62 IdleTask* task) override {
63 CHECK(nullptr == idle_task_);
64 idle_task_ = task;
65 }
66
67 bool IdleTasksEnabled(v8::Isolate* isolate) override { return true; }
68
69 bool PendingIdleTask() { return idle_task_ != nullptr; }
70
71 void PerformIdleTask(double idle_time_in_seconds) {
72 IdleTask* task = idle_task_;
73 idle_task_ = nullptr;
74 task->Run(MonotonicallyIncreasingTime() + idle_time_in_seconds);
75 delete task;
76 }
77
78 bool PendingDelayedTask() { return delayed_task_ != nullptr; }
79
80 void PerformDelayedTask() {
81 Task* task = delayed_task_;
82 delayed_task_ = nullptr;
83 task->Run();
84 delete task;
85 }
86
87 uint64_t AddTraceEvent(char phase, const uint8_t* categoryEnabledFlag,
Ben Murdochda12d292016-06-02 14:46:10 +010088 const char* name, const char* scope, uint64_t id,
89 uint64_t bind_id, int numArgs, const char** argNames,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090 const uint8_t* argTypes, const uint64_t* argValues,
91 unsigned int flags) override {
92 return 0;
93 }
94
95 void UpdateTraceEventDuration(const uint8_t* categoryEnabledFlag,
96 const char* name, uint64_t handle) override {}
97
98 const uint8_t* GetCategoryGroupEnabled(const char* name) override {
99 static uint8_t no = 0;
100 return &no;
101 }
102
103 const char* GetCategoryGroupName(
104 const uint8_t* categoryEnabledFlag) override {
105 static const char* dummy = "dummy";
106 return dummy;
107 }
108
109 private:
110 v8::Platform* platform_;
111 IdleTask* idle_task_;
112 Task* delayed_task_;
113};
114
115
116TEST(IncrementalMarkingUsingIdleTasks) {
117 if (!i::FLAG_incremental_marking) return;
118 CcTest::InitializeVM();
119 v8::Platform* old_platform = i::V8::GetCurrentPlatform();
120 MockPlatform platform(old_platform);
121 i::V8::SetPlatformForTesting(&platform);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100122 i::heap::SimulateFullSpace(CcTest::heap()->old_space());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123 i::IncrementalMarking* marking = CcTest::heap()->incremental_marking();
124 marking->Stop();
125 marking->Start();
126 CHECK(platform.PendingIdleTask());
127 const double kLongIdleTimeInSeconds = 1;
128 const double kShortIdleTimeInSeconds = 0.010;
129 const int kShortStepCount = 10;
130 for (int i = 0; i < kShortStepCount && platform.PendingIdleTask(); i++) {
131 platform.PerformIdleTask(kShortIdleTimeInSeconds);
132 }
133 while (platform.PendingIdleTask()) {
134 platform.PerformIdleTask(kLongIdleTimeInSeconds);
135 }
136 CHECK(marking->IsStopped());
137 i::V8::SetPlatformForTesting(old_platform);
138}
139
140
141TEST(IncrementalMarkingUsingIdleTasksAfterGC) {
142 if (!i::FLAG_incremental_marking) return;
143 CcTest::InitializeVM();
144 v8::Platform* old_platform = i::V8::GetCurrentPlatform();
145 MockPlatform platform(old_platform);
146 i::V8::SetPlatformForTesting(&platform);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100147 i::heap::SimulateFullSpace(CcTest::heap()->old_space());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000148 CcTest::heap()->CollectAllGarbage();
149 i::IncrementalMarking* marking = CcTest::heap()->incremental_marking();
150 marking->Stop();
151 marking->Start();
152 CHECK(platform.PendingIdleTask());
153 const double kLongIdleTimeInSeconds = 1;
154 const double kShortIdleTimeInSeconds = 0.010;
155 const int kShortStepCount = 10;
156 for (int i = 0; i < kShortStepCount && platform.PendingIdleTask(); i++) {
157 platform.PerformIdleTask(kShortIdleTimeInSeconds);
158 }
159 while (platform.PendingIdleTask()) {
160 platform.PerformIdleTask(kLongIdleTimeInSeconds);
161 }
162 CHECK(marking->IsStopped());
163 i::V8::SetPlatformForTesting(old_platform);
164}
165
166
167TEST(IncrementalMarkingUsingDelayedTasks) {
168 if (!i::FLAG_incremental_marking) return;
169 CcTest::InitializeVM();
170 v8::Platform* old_platform = i::V8::GetCurrentPlatform();
171 MockPlatform platform(old_platform);
172 i::V8::SetPlatformForTesting(&platform);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100173 i::heap::SimulateFullSpace(CcTest::heap()->old_space());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 i::IncrementalMarking* marking = CcTest::heap()->incremental_marking();
175 marking->Stop();
176 marking->Start();
177 CHECK(platform.PendingIdleTask());
178 // The delayed task should be a no-op if the idle task makes progress.
179 const int kIgnoredDelayedTaskStepCount = 1000;
180 for (int i = 0; i < kIgnoredDelayedTaskStepCount; i++) {
181 // Dummy idle task progress.
182 marking->incremental_marking_job()->NotifyIdleTaskProgress();
183 CHECK(platform.PendingDelayedTask());
184 platform.PerformDelayedTask();
185 }
186 // Once we stop notifying idle task progress, the delayed tasks
187 // should finish marking.
188 while (!marking->IsStopped() && platform.PendingDelayedTask()) {
189 platform.PerformDelayedTask();
190 }
191 // There could be pending delayed task from memory reducer after GC finishes.
192 CHECK(marking->IsStopped());
193 i::V8::SetPlatformForTesting(old_platform);
194}
195
196} // namespace internal
197} // namespace v8