blob: 1a4f5c372b39014c42d268024551c642a75886d0 [file] [log] [blame]
[email protected]b64e5212014-04-04 21:09:161// Copyright 2014 The Chromium 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 "gin/public/v8_platform.h"
6
fdorayb87bcfb82017-05-24 17:49:407#include <algorithm>
8
[email protected]b64e5212014-04-04 21:09:169#include "base/bind.h"
jochen4844f72e2017-03-20 09:07:0310#include "base/debug/stack_trace.h"
[email protected]b64e5212014-04-04 21:09:1611#include "base/location.h"
mlippautz40dfecc92016-03-07 21:06:5012#include "base/sys_info.h"
fdorayb87bcfb82017-05-24 17:49:4013#include "base/task_scheduler/post_task.h"
14#include "base/task_scheduler/task_scheduler.h"
tmoniuszko36416932016-01-27 16:28:4515#include "base/trace_event/trace_event.h"
[email protected]b64e5212014-04-04 21:09:1616#include "gin/per_isolate_data.h"
17
18namespace gin {
19
20namespace {
21
fdorayb87bcfb82017-05-24 17:49:4022constexpr base::TaskTraits kBackgroundThreadTaskTraits = {
fdoray6eb5c1e2017-05-25 19:51:1323 base::TaskPriority::USER_VISIBLE};
fdorayb87bcfb82017-05-24 17:49:4024
[email protected]b64e5212014-04-04 21:09:1625base::LazyInstance<V8Platform>::Leaky g_v8_platform = LAZY_INSTANCE_INITIALIZER;
26
jochen76acff102016-11-08 08:20:3727void RunWithLocker(v8::Isolate* isolate, v8::Task* task) {
28 v8::Locker lock(isolate);
29 task->Run();
30}
31
32class IdleTaskWithLocker : public v8::IdleTask {
33 public:
34 IdleTaskWithLocker(v8::Isolate* isolate, v8::IdleTask* task)
35 : isolate_(isolate), task_(task) {}
36
37 ~IdleTaskWithLocker() override = default;
38
39 // v8::IdleTask implementation.
40 void Run(double deadline_in_seconds) override {
41 v8::Locker lock(isolate_);
42 task_->Run(deadline_in_seconds);
43 }
44
45 private:
46 v8::Isolate* isolate_;
47 std::unique_ptr<v8::IdleTask> task_;
48
49 DISALLOW_COPY_AND_ASSIGN(IdleTaskWithLocker);
50};
51
jochen4844f72e2017-03-20 09:07:0352void PrintStackTrace() {
53 base::debug::StackTrace trace;
54 trace.Print();
55}
56
Jochen Eisinger7845aae22017-06-26 15:05:4557class ConvertableToTraceFormatWrapper final
58 : public base::trace_event::ConvertableToTraceFormat {
59 public:
60 explicit ConvertableToTraceFormatWrapper(
61 std::unique_ptr<v8::ConvertableToTraceFormat>& inner)
62 : inner_(std::move(inner)) {}
63 ~ConvertableToTraceFormatWrapper() override = default;
64 void AppendAsTraceFormat(std::string* out) const final {
65 inner_->AppendAsTraceFormat(out);
66 }
67
68 private:
69 std::unique_ptr<v8::ConvertableToTraceFormat> inner_;
70
71 DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormatWrapper);
72};
73
74class EnabledStateObserverImpl final
75 : public base::trace_event::TraceLog::EnabledStateObserver {
76 public:
77 EnabledStateObserverImpl() = default;
78
79 void OnTraceLogEnabled() final {
80 base::AutoLock lock(mutex_);
81 for (auto* o : observers_) {
82 o->OnTraceEnabled();
83 }
84 }
85
86 void OnTraceLogDisabled() final {
87 base::AutoLock lock(mutex_);
88 for (auto* o : observers_) {
89 o->OnTraceDisabled();
90 }
91 }
92
93 void AddObserver(v8::TracingController::TraceStateObserver* observer) {
94 {
95 base::AutoLock lock(mutex_);
96 DCHECK(!observers_.count(observer));
97 if (observers_.empty()) {
98 base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(
99 this);
100 }
101 observers_.insert(observer);
102 }
103 // Fire the observer if recording is already in progress.
104 if (base::trace_event::TraceLog::GetInstance()->IsEnabled())
105 observer->OnTraceEnabled();
106 }
107
108 void RemoveObserver(v8::TracingController::TraceStateObserver* observer) {
109 base::AutoLock lock(mutex_);
110 DCHECK(observers_.count(observer) == 1);
111 observers_.erase(observer);
112 if (observers_.empty()) {
113 base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(
114 this);
115 }
116 }
117
118 private:
119 base::Lock mutex_;
120 std::unordered_set<v8::TracingController::TraceStateObserver*> observers_;
121
122 DISALLOW_COPY_AND_ASSIGN(EnabledStateObserverImpl);
123};
124
125base::LazyInstance<EnabledStateObserverImpl>::Leaky g_trace_state_dispatcher =
126 LAZY_INSTANCE_INITIALIZER;
127
[email protected]b64e5212014-04-04 21:09:16128} // namespace
129
Jochen Eisinger7845aae22017-06-26 15:05:45130class V8Platform::TracingControllerImpl : public v8::TracingController {
131 public:
132 TracingControllerImpl() = default;
133 ~TracingControllerImpl() override = default;
134
135 // TracingController implementation.
136 const uint8_t* GetCategoryGroupEnabled(const char* name) override {
137 return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(name);
138 }
139 uint64_t AddTraceEvent(
140 char phase,
141 const uint8_t* category_enabled_flag,
142 const char* name,
143 const char* scope,
144 uint64_t id,
145 uint64_t bind_id,
146 int32_t num_args,
147 const char** arg_names,
148 const uint8_t* arg_types,
149 const uint64_t* arg_values,
150 std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
151 unsigned int flags) override {
152 std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
153 convertables[2];
154 if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
155 convertables[0].reset(
156 new ConvertableToTraceFormatWrapper(arg_convertables[0]));
157 }
158 if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) {
159 convertables[1].reset(
160 new ConvertableToTraceFormatWrapper(arg_convertables[1]));
161 }
162 DCHECK_LE(num_args, 2);
163 base::trace_event::TraceEventHandle handle =
164 TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID(
165 phase, category_enabled_flag, name, scope, id, bind_id, num_args,
166 arg_names, arg_types, (const long long unsigned int*)arg_values,
167 convertables, flags);
168 uint64_t result;
169 memcpy(&result, &handle, sizeof(result));
170 return result;
171 }
172 void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
173 const char* name,
174 uint64_t handle) override {
175 base::trace_event::TraceEventHandle traceEventHandle;
176 memcpy(&traceEventHandle, &handle, sizeof(handle));
177 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_enabled_flag, name,
178 traceEventHandle);
179 }
180 void AddTraceStateObserver(TraceStateObserver* observer) override {
181 g_trace_state_dispatcher.Get().AddObserver(observer);
182 }
183 void RemoveTraceStateObserver(TraceStateObserver* observer) override {
184 g_trace_state_dispatcher.Get().RemoveObserver(observer);
185 }
186
187 private:
188 DISALLOW_COPY_AND_ASSIGN(TracingControllerImpl);
189};
190
[email protected]b64e5212014-04-04 21:09:16191// static
192V8Platform* V8Platform::Get() { return g_v8_platform.Pointer(); }
193
Jochen Eisinger7845aae22017-06-26 15:05:45194V8Platform::V8Platform() : tracing_controller_(new TracingControllerImpl) {}
[email protected]b64e5212014-04-04 21:09:16195
196V8Platform::~V8Platform() {}
197
mlippautz40dfecc92016-03-07 21:06:50198size_t V8Platform::NumberOfAvailableBackgroundThreads() {
fdorayb87bcfb82017-05-24 17:49:40199 return std::max(1, base::TaskScheduler::GetInstance()
Jeffrey Hed628419b2017-08-23 18:51:51200 ->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
fdorayb87bcfb82017-05-24 17:49:40201 kBackgroundThreadTaskTraits));
mlippautz40dfecc92016-03-07 21:06:50202}
203
[email protected]b64e5212014-04-04 21:09:16204void V8Platform::CallOnBackgroundThread(
205 v8::Task* task,
206 v8::Platform::ExpectedRuntime expected_runtime) {
fdorayb87bcfb82017-05-24 17:49:40207 base::PostTaskWithTraits(FROM_HERE, kBackgroundThreadTaskTraits,
208 base::Bind(&v8::Task::Run, base::Owned(task)));
[email protected]b64e5212014-04-04 21:09:16209}
210
211void V8Platform::CallOnForegroundThread(v8::Isolate* isolate, v8::Task* task) {
jochen76acff102016-11-08 08:20:37212 PerIsolateData* data = PerIsolateData::From(isolate);
213 if (data->access_mode() == IsolateHolder::kUseLocker) {
214 data->task_runner()->PostTask(
215 FROM_HERE, base::Bind(RunWithLocker, base::Unretained(isolate),
216 base::Owned(task)));
217 } else {
218 data->task_runner()->PostTask(
219 FROM_HERE, base::Bind(&v8::Task::Run, base::Owned(task)));
220 }
[email protected]b64e5212014-04-04 21:09:16221}
222
ulan49cd773c2015-06-24 16:38:08223void V8Platform::CallDelayedOnForegroundThread(v8::Isolate* isolate,
224 v8::Task* task,
225 double delay_in_seconds) {
jochen76acff102016-11-08 08:20:37226 PerIsolateData* data = PerIsolateData::From(isolate);
227 if (data->access_mode() == IsolateHolder::kUseLocker) {
228 data->task_runner()->PostDelayedTask(
229 FROM_HERE,
230 base::Bind(RunWithLocker, base::Unretained(isolate), base::Owned(task)),
231 base::TimeDelta::FromSecondsD(delay_in_seconds));
232 } else {
233 data->task_runner()->PostDelayedTask(
234 FROM_HERE, base::Bind(&v8::Task::Run, base::Owned(task)),
235 base::TimeDelta::FromSecondsD(delay_in_seconds));
236 }
ulan49cd773c2015-06-24 16:38:08237}
238
ulan3cbdcd02015-07-20 11:32:58239void V8Platform::CallIdleOnForegroundThread(v8::Isolate* isolate,
240 v8::IdleTask* task) {
jochen76acff102016-11-08 08:20:37241 PerIsolateData* data = PerIsolateData::From(isolate);
242 DCHECK(data->idle_task_runner());
243 if (data->access_mode() == IsolateHolder::kUseLocker) {
244 data->idle_task_runner()->PostIdleTask(
245 new IdleTaskWithLocker(isolate, task));
246 } else {
247 data->idle_task_runner()->PostIdleTask(task);
248 }
ulan3cbdcd02015-07-20 11:32:58249}
250
251bool V8Platform::IdleTasksEnabled(v8::Isolate* isolate) {
252 return PerIsolateData::From(isolate)->idle_task_runner() != nullptr;
253}
254
rmcilroy05d26622014-10-08 11:28:05255double V8Platform::MonotonicallyIncreasingTime() {
256 return base::TimeTicks::Now().ToInternalValue() /
257 static_cast<double>(base::Time::kMicrosecondsPerSecond);
258}
259
Sergei Dcdd78f72017-08-22 01:45:25260double V8Platform::CurrentClockTimeMillis() {
261 return base::Time::Now().ToJsTime();
262}
263
Jochen Eisinger7845aae22017-06-26 15:05:45264v8::TracingController* V8Platform::GetTracingController() {
265 return tracing_controller_.get();
266}
267
jochen4844f72e2017-03-20 09:07:03268v8::Platform::StackTracePrinter V8Platform::GetStackTracePrinter() {
269 return PrintStackTrace;
270}
271
[email protected]b64e5212014-04-04 21:09:16272} // namespace gin