blob: 1ee4c3a27536b057bde7c09166d8ae9ba6c5e3d7 [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 = {
23 base::MayBlock(), base::TaskPriority::USER_VISIBLE,
24 base::TaskShutdownBehavior::BLOCK_SHUTDOWN};
25
[email protected]b64e5212014-04-04 21:09:1626base::LazyInstance<V8Platform>::Leaky g_v8_platform = LAZY_INSTANCE_INITIALIZER;
27
jochen76acff102016-11-08 08:20:3728void RunWithLocker(v8::Isolate* isolate, v8::Task* task) {
29 v8::Locker lock(isolate);
30 task->Run();
31}
32
33class IdleTaskWithLocker : public v8::IdleTask {
34 public:
35 IdleTaskWithLocker(v8::Isolate* isolate, v8::IdleTask* task)
36 : isolate_(isolate), task_(task) {}
37
38 ~IdleTaskWithLocker() override = default;
39
40 // v8::IdleTask implementation.
41 void Run(double deadline_in_seconds) override {
42 v8::Locker lock(isolate_);
43 task_->Run(deadline_in_seconds);
44 }
45
46 private:
47 v8::Isolate* isolate_;
48 std::unique_ptr<v8::IdleTask> task_;
49
50 DISALLOW_COPY_AND_ASSIGN(IdleTaskWithLocker);
51};
52
jochen4844f72e2017-03-20 09:07:0353void PrintStackTrace() {
54 base::debug::StackTrace trace;
55 trace.Print();
56}
57
[email protected]b64e5212014-04-04 21:09:1658} // namespace
59
60// static
61V8Platform* V8Platform::Get() { return g_v8_platform.Pointer(); }
62
63V8Platform::V8Platform() {}
64
65V8Platform::~V8Platform() {}
66
mlippautz40dfecc92016-03-07 21:06:5067size_t V8Platform::NumberOfAvailableBackgroundThreads() {
fdorayb87bcfb82017-05-24 17:49:4068 return std::max(1, base::TaskScheduler::GetInstance()
69 ->GetMaxConcurrentTasksWithTraitsDeprecated(
70 kBackgroundThreadTaskTraits));
mlippautz40dfecc92016-03-07 21:06:5071}
72
[email protected]b64e5212014-04-04 21:09:1673void V8Platform::CallOnBackgroundThread(
74 v8::Task* task,
75 v8::Platform::ExpectedRuntime expected_runtime) {
fdorayb87bcfb82017-05-24 17:49:4076 base::PostTaskWithTraits(FROM_HERE, kBackgroundThreadTaskTraits,
77 base::Bind(&v8::Task::Run, base::Owned(task)));
[email protected]b64e5212014-04-04 21:09:1678}
79
80void V8Platform::CallOnForegroundThread(v8::Isolate* isolate, v8::Task* task) {
jochen76acff102016-11-08 08:20:3781 PerIsolateData* data = PerIsolateData::From(isolate);
82 if (data->access_mode() == IsolateHolder::kUseLocker) {
83 data->task_runner()->PostTask(
84 FROM_HERE, base::Bind(RunWithLocker, base::Unretained(isolate),
85 base::Owned(task)));
86 } else {
87 data->task_runner()->PostTask(
88 FROM_HERE, base::Bind(&v8::Task::Run, base::Owned(task)));
89 }
[email protected]b64e5212014-04-04 21:09:1690}
91
ulan49cd773c2015-06-24 16:38:0892void V8Platform::CallDelayedOnForegroundThread(v8::Isolate* isolate,
93 v8::Task* task,
94 double delay_in_seconds) {
jochen76acff102016-11-08 08:20:3795 PerIsolateData* data = PerIsolateData::From(isolate);
96 if (data->access_mode() == IsolateHolder::kUseLocker) {
97 data->task_runner()->PostDelayedTask(
98 FROM_HERE,
99 base::Bind(RunWithLocker, base::Unretained(isolate), base::Owned(task)),
100 base::TimeDelta::FromSecondsD(delay_in_seconds));
101 } else {
102 data->task_runner()->PostDelayedTask(
103 FROM_HERE, base::Bind(&v8::Task::Run, base::Owned(task)),
104 base::TimeDelta::FromSecondsD(delay_in_seconds));
105 }
ulan49cd773c2015-06-24 16:38:08106}
107
ulan3cbdcd02015-07-20 11:32:58108void V8Platform::CallIdleOnForegroundThread(v8::Isolate* isolate,
109 v8::IdleTask* task) {
jochen76acff102016-11-08 08:20:37110 PerIsolateData* data = PerIsolateData::From(isolate);
111 DCHECK(data->idle_task_runner());
112 if (data->access_mode() == IsolateHolder::kUseLocker) {
113 data->idle_task_runner()->PostIdleTask(
114 new IdleTaskWithLocker(isolate, task));
115 } else {
116 data->idle_task_runner()->PostIdleTask(task);
117 }
ulan3cbdcd02015-07-20 11:32:58118}
119
120bool V8Platform::IdleTasksEnabled(v8::Isolate* isolate) {
121 return PerIsolateData::From(isolate)->idle_task_runner() != nullptr;
122}
123
rmcilroy05d26622014-10-08 11:28:05124double V8Platform::MonotonicallyIncreasingTime() {
125 return base::TimeTicks::Now().ToInternalValue() /
126 static_cast<double>(base::Time::kMicrosecondsPerSecond);
127}
128
fmeawad471a2202015-12-21 17:00:24129const uint8_t* V8Platform::GetCategoryGroupEnabled(const char* name) {
130 return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(name);
131}
132
133const char* V8Platform::GetCategoryGroupName(
134 const uint8_t* category_enabled_flag) {
135 return base::trace_event::TraceLog::GetCategoryGroupName(
136 category_enabled_flag);
137}
138
alph92d855a42016-09-28 09:34:52139namespace {
140
141class ConvertableToTraceFormatWrapper
142 : public base::trace_event::ConvertableToTraceFormat {
143 public:
144 explicit ConvertableToTraceFormatWrapper(
145 std::unique_ptr<v8::ConvertableToTraceFormat>& inner)
146 : inner_(std::move(inner)) {}
147 ~ConvertableToTraceFormatWrapper() override = default;
148 void AppendAsTraceFormat(std::string* out) const final {
149 inner_->AppendAsTraceFormat(out);
150 }
151
152 private:
153 std::unique_ptr<v8::ConvertableToTraceFormat> inner_;
154
155 DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormatWrapper);
156};
157
158} // namespace
159
160uint64_t V8Platform::AddTraceEvent(
161 char phase,
162 const uint8_t* category_enabled_flag,
163 const char* name,
164 const char* scope,
165 uint64_t id,
166 uint64_t bind_id,
167 int32_t num_args,
168 const char** arg_names,
169 const uint8_t* arg_types,
170 const uint64_t* arg_values,
171 std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
172 unsigned int flags) {
alph7722c1c2016-09-23 01:47:21173 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> convertables[2];
174 if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
175 convertables[0].reset(
alph92d855a42016-09-28 09:34:52176 new ConvertableToTraceFormatWrapper(arg_convertables[0]));
alph7722c1c2016-09-23 01:47:21177 }
178 if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) {
179 convertables[1].reset(
alph92d855a42016-09-28 09:34:52180 new ConvertableToTraceFormatWrapper(arg_convertables[1]));
alph7722c1c2016-09-23 01:47:21181 }
alph92d855a42016-09-28 09:34:52182 DCHECK_LE(num_args, 2);
fmeawad471a2202015-12-21 17:00:24183 base::trace_event::TraceEventHandle handle =
184 TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID(
fmeawadab615cf2016-03-01 18:03:31185 phase, category_enabled_flag, name, scope, id, bind_id, num_args,
alph7722c1c2016-09-23 01:47:21186 arg_names, arg_types, (const long long unsigned int*)arg_values,
187 convertables, flags);
fmeawad471a2202015-12-21 17:00:24188 uint64_t result;
189 memcpy(&result, &handle, sizeof(result));
190 return result;
191}
192
193void V8Platform::UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
194 const char* name,
195 uint64_t handle) {
196 base::trace_event::TraceEventHandle traceEventHandle;
197 memcpy(&traceEventHandle, &handle, sizeof(handle));
198 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_enabled_flag, name,
199 traceEventHandle);
200}
201
alph290f6302016-09-21 00:00:39202namespace {
203
204class EnabledStateObserverImpl final
205 : public base::trace_event::TraceLog::EnabledStateObserver {
206 public:
lpy241ab2f2016-11-02 00:27:42207 EnabledStateObserverImpl() = default;
alph290f6302016-09-21 00:00:39208
209 void OnTraceLogEnabled() final {
210 base::AutoLock lock(mutex_);
vmpstr6d9996c82017-02-23 00:43:25211 for (auto* o : observers_) {
alph290f6302016-09-21 00:00:39212 o->OnTraceEnabled();
213 }
214 }
215
216 void OnTraceLogDisabled() final {
217 base::AutoLock lock(mutex_);
vmpstr6d9996c82017-02-23 00:43:25218 for (auto* o : observers_) {
alph290f6302016-09-21 00:00:39219 o->OnTraceDisabled();
220 }
221 }
222
223 void AddObserver(v8::Platform::TraceStateObserver* observer) {
lpy48e4c322017-01-27 18:22:34224 {
225 base::AutoLock lock(mutex_);
226 DCHECK(!observers_.count(observer));
227 if (observers_.empty()) {
228 base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(
229 this);
230 }
231 observers_.insert(observer);
alph290f6302016-09-21 00:00:39232 }
lpy48e4c322017-01-27 18:22:34233 // Fire the observer if recording is already in progress.
234 if (base::trace_event::TraceLog::GetInstance()->IsEnabled())
235 observer->OnTraceEnabled();
alph290f6302016-09-21 00:00:39236 }
237
238 void RemoveObserver(v8::Platform::TraceStateObserver* observer) {
239 base::AutoLock lock(mutex_);
240 DCHECK(observers_.count(observer) == 1);
241 observers_.erase(observer);
242 if (observers_.empty()) {
243 base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(
244 this);
245 }
246 }
247
248 private:
249 base::Lock mutex_;
250 std::unordered_set<v8::Platform::TraceStateObserver*> observers_;
251
252 DISALLOW_COPY_AND_ASSIGN(EnabledStateObserverImpl);
253};
254
255base::LazyInstance<EnabledStateObserverImpl>::Leaky g_trace_state_dispatcher =
256 LAZY_INSTANCE_INITIALIZER;
257
258} // namespace
259
260void V8Platform::AddTraceStateObserver(
261 v8::Platform::TraceStateObserver* observer) {
262 g_trace_state_dispatcher.Get().AddObserver(observer);
263}
264
265void V8Platform::RemoveTraceStateObserver(
266 v8::Platform::TraceStateObserver* observer) {
267 g_trace_state_dispatcher.Get().RemoveObserver(observer);
268}
269
jochen4844f72e2017-03-20 09:07:03270v8::Platform::StackTracePrinter V8Platform::GetStackTracePrinter() {
271 return PrintStackTrace;
272}
273
[email protected]b64e5212014-04-04 21:09:16274} // namespace gin