blob: 6e5491bff11801397e353cb371b1a9762fffb970 [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
7#include "base/bind.h"
8#include "base/location.h"
mlippautz40dfecc92016-03-07 21:06:509#include "base/sys_info.h"
[email protected]b64e5212014-04-04 21:09:1610#include "base/threading/worker_pool.h"
tmoniuszko36416932016-01-27 16:28:4511#include "base/trace_event/trace_event.h"
[email protected]b64e5212014-04-04 21:09:1612#include "gin/per_isolate_data.h"
13
14namespace gin {
15
16namespace {
17
18base::LazyInstance<V8Platform>::Leaky g_v8_platform = LAZY_INSTANCE_INITIALIZER;
19
jochen76acff102016-11-08 08:20:3720void RunWithLocker(v8::Isolate* isolate, v8::Task* task) {
21 v8::Locker lock(isolate);
22 task->Run();
23}
24
25class IdleTaskWithLocker : public v8::IdleTask {
26 public:
27 IdleTaskWithLocker(v8::Isolate* isolate, v8::IdleTask* task)
28 : isolate_(isolate), task_(task) {}
29
30 ~IdleTaskWithLocker() override = default;
31
32 // v8::IdleTask implementation.
33 void Run(double deadline_in_seconds) override {
34 v8::Locker lock(isolate_);
35 task_->Run(deadline_in_seconds);
36 }
37
38 private:
39 v8::Isolate* isolate_;
40 std::unique_ptr<v8::IdleTask> task_;
41
42 DISALLOW_COPY_AND_ASSIGN(IdleTaskWithLocker);
43};
44
[email protected]b64e5212014-04-04 21:09:1645} // namespace
46
47// static
48V8Platform* V8Platform::Get() { return g_v8_platform.Pointer(); }
49
50V8Platform::V8Platform() {}
51
52V8Platform::~V8Platform() {}
53
mlippautz40dfecc92016-03-07 21:06:5054size_t V8Platform::NumberOfAvailableBackgroundThreads() {
55 // WorkerPool will currently always create additional threads for posted
56 // background tasks, unless there are threads sitting idle (on posix).
57 // Indicate that V8 should create no more than the number of cores available,
58 // reserving one core for the main thread.
59 const size_t available_cores =
60 static_cast<size_t>(base::SysInfo::NumberOfProcessors());
61 if (available_cores > 1) {
62 return available_cores - 1;
63 }
64 return 1;
65}
66
[email protected]b64e5212014-04-04 21:09:1667void V8Platform::CallOnBackgroundThread(
68 v8::Task* task,
69 v8::Platform::ExpectedRuntime expected_runtime) {
70 base::WorkerPool::PostTask(
71 FROM_HERE,
72 base::Bind(&v8::Task::Run, base::Owned(task)),
73 expected_runtime == v8::Platform::kLongRunningTask);
74}
75
76void V8Platform::CallOnForegroundThread(v8::Isolate* isolate, v8::Task* task) {
jochen76acff102016-11-08 08:20:3777 PerIsolateData* data = PerIsolateData::From(isolate);
78 if (data->access_mode() == IsolateHolder::kUseLocker) {
79 data->task_runner()->PostTask(
80 FROM_HERE, base::Bind(RunWithLocker, base::Unretained(isolate),
81 base::Owned(task)));
82 } else {
83 data->task_runner()->PostTask(
84 FROM_HERE, base::Bind(&v8::Task::Run, base::Owned(task)));
85 }
[email protected]b64e5212014-04-04 21:09:1686}
87
ulan49cd773c2015-06-24 16:38:0888void V8Platform::CallDelayedOnForegroundThread(v8::Isolate* isolate,
89 v8::Task* task,
90 double delay_in_seconds) {
jochen76acff102016-11-08 08:20:3791 PerIsolateData* data = PerIsolateData::From(isolate);
92 if (data->access_mode() == IsolateHolder::kUseLocker) {
93 data->task_runner()->PostDelayedTask(
94 FROM_HERE,
95 base::Bind(RunWithLocker, base::Unretained(isolate), base::Owned(task)),
96 base::TimeDelta::FromSecondsD(delay_in_seconds));
97 } else {
98 data->task_runner()->PostDelayedTask(
99 FROM_HERE, base::Bind(&v8::Task::Run, base::Owned(task)),
100 base::TimeDelta::FromSecondsD(delay_in_seconds));
101 }
ulan49cd773c2015-06-24 16:38:08102}
103
ulan3cbdcd02015-07-20 11:32:58104void V8Platform::CallIdleOnForegroundThread(v8::Isolate* isolate,
105 v8::IdleTask* task) {
jochen76acff102016-11-08 08:20:37106 PerIsolateData* data = PerIsolateData::From(isolate);
107 DCHECK(data->idle_task_runner());
108 if (data->access_mode() == IsolateHolder::kUseLocker) {
109 data->idle_task_runner()->PostIdleTask(
110 new IdleTaskWithLocker(isolate, task));
111 } else {
112 data->idle_task_runner()->PostIdleTask(task);
113 }
ulan3cbdcd02015-07-20 11:32:58114}
115
116bool V8Platform::IdleTasksEnabled(v8::Isolate* isolate) {
117 return PerIsolateData::From(isolate)->idle_task_runner() != nullptr;
118}
119
rmcilroy05d26622014-10-08 11:28:05120double V8Platform::MonotonicallyIncreasingTime() {
121 return base::TimeTicks::Now().ToInternalValue() /
122 static_cast<double>(base::Time::kMicrosecondsPerSecond);
123}
124
fmeawad471a2202015-12-21 17:00:24125const uint8_t* V8Platform::GetCategoryGroupEnabled(const char* name) {
126 return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(name);
127}
128
129const char* V8Platform::GetCategoryGroupName(
130 const uint8_t* category_enabled_flag) {
131 return base::trace_event::TraceLog::GetCategoryGroupName(
132 category_enabled_flag);
133}
134
alph92d855a42016-09-28 09:34:52135namespace {
136
137class ConvertableToTraceFormatWrapper
138 : public base::trace_event::ConvertableToTraceFormat {
139 public:
140 explicit ConvertableToTraceFormatWrapper(
141 std::unique_ptr<v8::ConvertableToTraceFormat>& inner)
142 : inner_(std::move(inner)) {}
143 ~ConvertableToTraceFormatWrapper() override = default;
144 void AppendAsTraceFormat(std::string* out) const final {
145 inner_->AppendAsTraceFormat(out);
146 }
147
148 private:
149 std::unique_ptr<v8::ConvertableToTraceFormat> inner_;
150
151 DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormatWrapper);
152};
153
154} // namespace
155
156uint64_t V8Platform::AddTraceEvent(
157 char phase,
158 const uint8_t* category_enabled_flag,
159 const char* name,
160 const char* scope,
161 uint64_t id,
162 uint64_t bind_id,
163 int32_t num_args,
164 const char** arg_names,
165 const uint8_t* arg_types,
166 const uint64_t* arg_values,
167 std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
168 unsigned int flags) {
alph7722c1c2016-09-23 01:47:21169 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> convertables[2];
170 if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
171 convertables[0].reset(
alph92d855a42016-09-28 09:34:52172 new ConvertableToTraceFormatWrapper(arg_convertables[0]));
alph7722c1c2016-09-23 01:47:21173 }
174 if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) {
175 convertables[1].reset(
alph92d855a42016-09-28 09:34:52176 new ConvertableToTraceFormatWrapper(arg_convertables[1]));
alph7722c1c2016-09-23 01:47:21177 }
alph92d855a42016-09-28 09:34:52178 DCHECK_LE(num_args, 2);
fmeawad471a2202015-12-21 17:00:24179 base::trace_event::TraceEventHandle handle =
180 TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID(
fmeawadab615cf2016-03-01 18:03:31181 phase, category_enabled_flag, name, scope, id, bind_id, num_args,
alph7722c1c2016-09-23 01:47:21182 arg_names, arg_types, (const long long unsigned int*)arg_values,
183 convertables, flags);
fmeawad471a2202015-12-21 17:00:24184 uint64_t result;
185 memcpy(&result, &handle, sizeof(result));
186 return result;
187}
188
189void V8Platform::UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
190 const char* name,
191 uint64_t handle) {
192 base::trace_event::TraceEventHandle traceEventHandle;
193 memcpy(&traceEventHandle, &handle, sizeof(handle));
194 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_enabled_flag, name,
195 traceEventHandle);
196}
197
alph290f6302016-09-21 00:00:39198namespace {
199
200class EnabledStateObserverImpl final
201 : public base::trace_event::TraceLog::EnabledStateObserver {
202 public:
lpy241ab2f2016-11-02 00:27:42203 EnabledStateObserverImpl() = default;
alph290f6302016-09-21 00:00:39204
205 void OnTraceLogEnabled() final {
206 base::AutoLock lock(mutex_);
207 for (auto o : observers_) {
208 o->OnTraceEnabled();
209 }
210 }
211
212 void OnTraceLogDisabled() final {
213 base::AutoLock lock(mutex_);
214 for (auto o : observers_) {
215 o->OnTraceDisabled();
216 }
217 }
218
219 void AddObserver(v8::Platform::TraceStateObserver* observer) {
220 base::AutoLock lock(mutex_);
221 DCHECK(!observers_.count(observer));
222 observers_.insert(observer);
223 if (observers_.size() == 1) {
224 base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
225 }
226 }
227
228 void RemoveObserver(v8::Platform::TraceStateObserver* observer) {
229 base::AutoLock lock(mutex_);
230 DCHECK(observers_.count(observer) == 1);
231 observers_.erase(observer);
232 if (observers_.empty()) {
233 base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(
234 this);
235 }
236 }
237
238 private:
239 base::Lock mutex_;
240 std::unordered_set<v8::Platform::TraceStateObserver*> observers_;
241
242 DISALLOW_COPY_AND_ASSIGN(EnabledStateObserverImpl);
243};
244
245base::LazyInstance<EnabledStateObserverImpl>::Leaky g_trace_state_dispatcher =
246 LAZY_INSTANCE_INITIALIZER;
247
248} // namespace
249
250void V8Platform::AddTraceStateObserver(
251 v8::Platform::TraceStateObserver* observer) {
252 g_trace_state_dispatcher.Get().AddObserver(observer);
253}
254
255void V8Platform::RemoveTraceStateObserver(
256 v8::Platform::TraceStateObserver* observer) {
257 g_trace_state_dispatcher.Get().RemoveObserver(observer);
258}
259
[email protected]b64e5212014-04-04 21:09:16260} // namespace gin