V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
d8-platforms.cc
1 // Copyright 2018 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 <memory>
6 #include <unordered_map>
7 
8 #include "include/v8-platform.h"
9 #include "src/base/logging.h"
10 #include "src/base/macros.h"
11 #include "src/base/platform/mutex.h"
12 #include "src/base/platform/platform.h"
13 #include "src/base/platform/time.h"
14 #include "src/base/template-utils.h"
15 #include "src/base/utils/random-number-generator.h"
16 #include "src/d8-platforms.h"
17 
18 namespace v8 {
19 
20 class PredictablePlatform : public Platform {
21  public:
22  explicit PredictablePlatform(std::unique_ptr<Platform> platform)
23  : platform_(std::move(platform)) {
24  DCHECK_NOT_NULL(platform_);
25  }
26 
28  return platform_->GetPageAllocator();
29  }
30 
31  void OnCriticalMemoryPressure() override {
32  platform_->OnCriticalMemoryPressure();
33  }
34 
35  bool OnCriticalMemoryPressure(size_t length) override {
36  return platform_->OnCriticalMemoryPressure(length);
37  }
38 
39  std::shared_ptr<TaskRunner> GetForegroundTaskRunner(
40  v8::Isolate* isolate) override {
41  return platform_->GetForegroundTaskRunner(isolate);
42  }
43 
44  int NumberOfWorkerThreads() override { return 0; }
45 
46  void CallOnWorkerThread(std::unique_ptr<Task> task) override {
47  // It's not defined when background tasks are being executed, so we can just
48  // execute them right away.
49  task->Run();
50  }
51 
52  void CallDelayedOnWorkerThread(std::unique_ptr<Task> task,
53  double delay_in_seconds) override {
54  // Never run delayed tasks.
55  }
56 
57  void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override {
58  // This is a deprecated function and should not be called anymore.
59  UNREACHABLE();
60  }
61 
62  void CallDelayedOnForegroundThread(v8::Isolate* isolate, Task* task,
63  double delay_in_seconds) override {
64  // This is a deprecated function and should not be called anymore.
65  UNREACHABLE();
66  }
67 
68  void CallIdleOnForegroundThread(Isolate* isolate, IdleTask* task) override {
69  UNREACHABLE();
70  }
71 
72  bool IdleTasksEnabled(Isolate* isolate) override { return false; }
73 
74  double MonotonicallyIncreasingTime() override {
75  return synthetic_time_in_sec_ += 0.00001;
76  }
77 
78  double CurrentClockTimeMillis() override {
79  return MonotonicallyIncreasingTime() * base::Time::kMillisecondsPerSecond;
80  }
81 
83  return platform_->GetTracingController();
84  }
85 
86  Platform* platform() const { return platform_.get(); }
87 
88  private:
89  double synthetic_time_in_sec_ = 0.0;
90  std::unique_ptr<Platform> platform_;
91 
92  DISALLOW_COPY_AND_ASSIGN(PredictablePlatform);
93 };
94 
95 std::unique_ptr<Platform> MakePredictablePlatform(
96  std::unique_ptr<Platform> platform) {
97  return base::make_unique<PredictablePlatform>(std::move(platform));
98 }
99 
101  public:
102  explicit DelayedTasksPlatform(std::unique_ptr<Platform> platform)
103  : platform_(std::move(platform)) {
104  DCHECK_NOT_NULL(platform_);
105  }
106 
107  explicit DelayedTasksPlatform(std::unique_ptr<Platform> platform,
108  int64_t random_seed)
109  : platform_(std::move(platform)), rng_(random_seed) {
110  DCHECK_NOT_NULL(platform_);
111  }
112 
114  // When the platform shuts down, all task runners must be freed.
115  DCHECK_EQ(0, delayed_task_runners_.size());
116  }
117 
119  return platform_->GetPageAllocator();
120  }
121 
122  void OnCriticalMemoryPressure() override {
123  platform_->OnCriticalMemoryPressure();
124  }
125 
126  bool OnCriticalMemoryPressure(size_t length) override {
127  return platform_->OnCriticalMemoryPressure(length);
128  }
129 
130  std::shared_ptr<TaskRunner> GetForegroundTaskRunner(
131  v8::Isolate* isolate) override {
132  std::shared_ptr<TaskRunner> runner =
133  platform_->GetForegroundTaskRunner(isolate);
134 
135  base::MutexGuard lock_guard(&mutex_);
136  // Check if we can re-materialize the weak ptr in our map.
137  std::weak_ptr<DelayedTaskRunner>& weak_delayed_runner =
138  delayed_task_runners_[runner.get()];
139  std::shared_ptr<DelayedTaskRunner> delayed_runner =
140  weak_delayed_runner.lock();
141 
142  if (!delayed_runner) {
143  // Create a new {DelayedTaskRunner} and keep a weak reference in our map.
144  delayed_runner.reset(new DelayedTaskRunner(runner, this),
145  DelayedTaskRunnerDeleter{});
146  weak_delayed_runner = delayed_runner;
147  }
148 
149  return std::move(delayed_runner);
150  }
151 
152  int NumberOfWorkerThreads() override {
153  return platform_->NumberOfWorkerThreads();
154  }
155 
156  void CallOnWorkerThread(std::unique_ptr<Task> task) override {
157  platform_->CallOnWorkerThread(MakeDelayedTask(std::move(task)));
158  }
159 
160  void CallDelayedOnWorkerThread(std::unique_ptr<Task> task,
161  double delay_in_seconds) override {
162  platform_->CallDelayedOnWorkerThread(MakeDelayedTask(std::move(task)),
163  delay_in_seconds);
164  }
165 
166  void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override {
167  // This is a deprecated function and should not be called anymore.
168  UNREACHABLE();
169  }
170 
171  void CallDelayedOnForegroundThread(v8::Isolate* isolate, Task* task,
172  double delay_in_seconds) override {
173  // This is a deprecated function and should not be called anymore.
174  UNREACHABLE();
175  }
176 
177  void CallIdleOnForegroundThread(Isolate* isolate, IdleTask* task) override {
178  // This is a deprecated function and should not be called anymore.
179  UNREACHABLE();
180  }
181 
182  bool IdleTasksEnabled(Isolate* isolate) override {
183  return platform_->IdleTasksEnabled(isolate);
184  }
185 
186  double MonotonicallyIncreasingTime() override {
187  return platform_->MonotonicallyIncreasingTime();
188  }
189 
190  double CurrentClockTimeMillis() override {
191  return platform_->CurrentClockTimeMillis();
192  }
193 
195  return platform_->GetTracingController();
196  }
197 
198  private:
199  class DelayedTaskRunnerDeleter;
200  class DelayedTaskRunner final : public TaskRunner {
201  public:
202  DelayedTaskRunner(std::shared_ptr<TaskRunner> task_runner,
203  DelayedTasksPlatform* platform)
204  : task_runner_(task_runner), platform_(platform) {}
205 
206  void PostTask(std::unique_ptr<Task> task) final {
207  task_runner_->PostTask(platform_->MakeDelayedTask(std::move(task)));
208  }
209 
210  void PostDelayedTask(std::unique_ptr<Task> task,
211  double delay_in_seconds) final {
212  task_runner_->PostDelayedTask(platform_->MakeDelayedTask(std::move(task)),
213  delay_in_seconds);
214  }
215 
216  void PostIdleTask(std::unique_ptr<IdleTask> task) final {
217  task_runner_->PostIdleTask(
218  platform_->MakeDelayedIdleTask(std::move(task)));
219  }
220 
221  bool IdleTasksEnabled() final { return task_runner_->IdleTasksEnabled(); }
222 
223  private:
224  friend class DelayedTaskRunnerDeleter;
225  std::shared_ptr<TaskRunner> task_runner_;
226  DelayedTasksPlatform* platform_;
227  };
228 
229  class DelayedTaskRunnerDeleter {
230  public:
231  void operator()(DelayedTaskRunner* runner) const {
232  TaskRunner* original_runner = runner->task_runner_.get();
233  base::MutexGuard lock_guard(&runner->platform_->mutex_);
234  auto& delayed_task_runners = runner->platform_->delayed_task_runners_;
235  DCHECK_EQ(1, delayed_task_runners.count(original_runner));
236  delayed_task_runners.erase(original_runner);
237  }
238  };
239 
240  class DelayedTask : public Task {
241  public:
242  DelayedTask(std::unique_ptr<Task> task, int32_t delay_ms)
243  : task_(std::move(task)), delay_ms_(delay_ms) {}
244  void Run() final {
245  base::OS::Sleep(base::TimeDelta::FromMicroseconds(delay_ms_));
246  task_->Run();
247  }
248 
249  private:
250  std::unique_ptr<Task> task_;
251  int32_t delay_ms_;
252  };
253 
254  class DelayedIdleTask : public IdleTask {
255  public:
256  DelayedIdleTask(std::unique_ptr<IdleTask> task, int32_t delay_ms)
257  : task_(std::move(task)), delay_ms_(delay_ms) {}
258  void Run(double deadline_in_seconds) final {
259  base::OS::Sleep(base::TimeDelta::FromMicroseconds(delay_ms_));
260  task_->Run(deadline_in_seconds);
261  }
262 
263  private:
264  std::unique_ptr<IdleTask> task_;
265  int32_t delay_ms_;
266  };
267 
268  std::unique_ptr<Platform> platform_;
269 
270  // The Mutex protects the RNG, which is used by foreground and background
271  // threads, and the {delayed_task_runners_} map might be accessed concurrently
272  // by the shared_ptr destructor.
273  base::Mutex mutex_;
274  base::RandomNumberGenerator rng_;
275  std::unordered_map<TaskRunner*, std::weak_ptr<DelayedTaskRunner>>
276  delayed_task_runners_;
277 
278  int32_t GetRandomDelayInMilliseconds() {
279  base::MutexGuard lock_guard(&mutex_);
280  double delay_fraction = rng_.NextDouble();
281  // Sleep up to 100ms (100000us). Square {delay_fraction} to shift
282  // distribution towards shorter sleeps.
283  return 1e5 * (delay_fraction * delay_fraction);
284  }
285 
286  std::unique_ptr<Task> MakeDelayedTask(std::unique_ptr<Task> task) {
287  return base::make_unique<DelayedTask>(std::move(task),
288  GetRandomDelayInMilliseconds());
289  }
290 
291  std::unique_ptr<IdleTask> MakeDelayedIdleTask(
292  std::unique_ptr<IdleTask> task) {
293  return base::make_unique<DelayedIdleTask>(std::move(task),
294  GetRandomDelayInMilliseconds());
295  }
296 
297  DISALLOW_COPY_AND_ASSIGN(DelayedTasksPlatform);
298 };
299 
300 std::unique_ptr<Platform> MakeDelayedTasksPlatform(
301  std::unique_ptr<Platform> platform, int64_t random_seed) {
302  if (random_seed) {
303  return base::make_unique<DelayedTasksPlatform>(std::move(platform),
304  random_seed);
305  }
306  return base::make_unique<DelayedTasksPlatform>(std::move(platform));
307 }
308 
309 } // namespace v8
double MonotonicallyIncreasingTime() override
PageAllocator * GetPageAllocator() override
void OnCriticalMemoryPressure() override
void OnCriticalMemoryPressure() override
Definition: d8-platforms.cc:31
bool IdleTasksEnabled(Isolate *isolate) override
STL namespace.
double CurrentClockTimeMillis() override
Definition: d8-platforms.cc:78
double MonotonicallyIncreasingTime() override
Definition: d8-platforms.cc:74
void CallOnWorkerThread(std::unique_ptr< Task > task) override
int NumberOfWorkerThreads() override
Definition: libplatform.h:13
bool OnCriticalMemoryPressure(size_t length) override
v8::TracingController * GetTracingController() override
int NumberOfWorkerThreads() override
Definition: d8-platforms.cc:44
void CallOnWorkerThread(std::unique_ptr< Task > task) override
Definition: d8-platforms.cc:46
void CallDelayedOnWorkerThread(std::unique_ptr< Task > task, double delay_in_seconds) override
Definition: d8-platforms.cc:52
std::shared_ptr< TaskRunner > GetForegroundTaskRunner(v8::Isolate *isolate) override
Definition: d8-platforms.cc:39
bool IdleTasksEnabled(Isolate *isolate) override
Definition: d8-platforms.cc:72
PageAllocator * GetPageAllocator() override
Definition: d8-platforms.cc:27
void CallDelayedOnWorkerThread(std::unique_ptr< Task > task, double delay_in_seconds) override
std::shared_ptr< TaskRunner > GetForegroundTaskRunner(v8::Isolate *isolate) override
bool OnCriticalMemoryPressure(size_t length) override
Definition: d8-platforms.cc:35
v8::TracingController * GetTracingController() override
Definition: d8-platforms.cc:82
double CurrentClockTimeMillis() override