blob: e9b7b026aa9290974cae85041ffc7d3949ac453d [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
Bill Budged1b87f02017-08-30 06:44:089#include "base/allocator/partition_allocator/page_allocator.h"
[email protected]b64e5212014-04-04 21:09:1610#include "base/bind.h"
jochen4844f72e2017-03-20 09:07:0311#include "base/debug/stack_trace.h"
[email protected]b64e5212014-04-04 21:09:1612#include "base/location.h"
mlippautz40dfecc92016-03-07 21:06:5013#include "base/sys_info.h"
fdorayb87bcfb82017-05-24 17:49:4014#include "base/task_scheduler/post_task.h"
15#include "base/task_scheduler/task_scheduler.h"
tmoniuszko36416932016-01-27 16:28:4516#include "base/trace_event/trace_event.h"
Bill Budged1b87f02017-08-30 06:44:0817#include "build/build_config.h"
[email protected]b64e5212014-04-04 21:09:1618#include "gin/per_isolate_data.h"
19
20namespace gin {
21
22namespace {
23
fdorayb87bcfb82017-05-24 17:49:4024constexpr base::TaskTraits kBackgroundThreadTaskTraits = {
fdoray6eb5c1e2017-05-25 19:51:1325 base::TaskPriority::USER_VISIBLE};
fdorayb87bcfb82017-05-24 17:49:4026
[email protected]b64e5212014-04-04 21:09:1627base::LazyInstance<V8Platform>::Leaky g_v8_platform = LAZY_INSTANCE_INITIALIZER;
28
jochen76acff102016-11-08 08:20:3729void RunWithLocker(v8::Isolate* isolate, v8::Task* task) {
30 v8::Locker lock(isolate);
31 task->Run();
32}
33
34class IdleTaskWithLocker : public v8::IdleTask {
35 public:
36 IdleTaskWithLocker(v8::Isolate* isolate, v8::IdleTask* task)
37 : isolate_(isolate), task_(task) {}
38
39 ~IdleTaskWithLocker() override = default;
40
41 // v8::IdleTask implementation.
42 void Run(double deadline_in_seconds) override {
43 v8::Locker lock(isolate_);
44 task_->Run(deadline_in_seconds);
45 }
46
47 private:
48 v8::Isolate* isolate_;
49 std::unique_ptr<v8::IdleTask> task_;
50
51 DISALLOW_COPY_AND_ASSIGN(IdleTaskWithLocker);
52};
53
jochen4844f72e2017-03-20 09:07:0354void PrintStackTrace() {
55 base::debug::StackTrace trace;
56 trace.Print();
57}
58
Jochen Eisinger7845aae22017-06-26 15:05:4559class ConvertableToTraceFormatWrapper final
60 : public base::trace_event::ConvertableToTraceFormat {
61 public:
62 explicit ConvertableToTraceFormatWrapper(
63 std::unique_ptr<v8::ConvertableToTraceFormat>& inner)
64 : inner_(std::move(inner)) {}
65 ~ConvertableToTraceFormatWrapper() override = default;
66 void AppendAsTraceFormat(std::string* out) const final {
67 inner_->AppendAsTraceFormat(out);
68 }
69
70 private:
71 std::unique_ptr<v8::ConvertableToTraceFormat> inner_;
72
73 DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormatWrapper);
74};
75
76class EnabledStateObserverImpl final
77 : public base::trace_event::TraceLog::EnabledStateObserver {
78 public:
79 EnabledStateObserverImpl() = default;
80
81 void OnTraceLogEnabled() final {
82 base::AutoLock lock(mutex_);
83 for (auto* o : observers_) {
84 o->OnTraceEnabled();
85 }
86 }
87
88 void OnTraceLogDisabled() final {
89 base::AutoLock lock(mutex_);
90 for (auto* o : observers_) {
91 o->OnTraceDisabled();
92 }
93 }
94
95 void AddObserver(v8::TracingController::TraceStateObserver* observer) {
96 {
97 base::AutoLock lock(mutex_);
98 DCHECK(!observers_.count(observer));
99 if (observers_.empty()) {
100 base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(
101 this);
102 }
103 observers_.insert(observer);
104 }
105 // Fire the observer if recording is already in progress.
106 if (base::trace_event::TraceLog::GetInstance()->IsEnabled())
107 observer->OnTraceEnabled();
108 }
109
110 void RemoveObserver(v8::TracingController::TraceStateObserver* observer) {
111 base::AutoLock lock(mutex_);
112 DCHECK(observers_.count(observer) == 1);
113 observers_.erase(observer);
114 if (observers_.empty()) {
115 base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(
116 this);
117 }
118 }
119
120 private:
121 base::Lock mutex_;
122 std::unordered_set<v8::TracingController::TraceStateObserver*> observers_;
123
124 DISALLOW_COPY_AND_ASSIGN(EnabledStateObserverImpl);
125};
126
127base::LazyInstance<EnabledStateObserverImpl>::Leaky g_trace_state_dispatcher =
128 LAZY_INSTANCE_INITIALIZER;
129
[email protected]b64e5212014-04-04 21:09:16130} // namespace
131
Jochen Eisinger7845aae22017-06-26 15:05:45132class V8Platform::TracingControllerImpl : public v8::TracingController {
133 public:
134 TracingControllerImpl() = default;
135 ~TracingControllerImpl() override = default;
136
137 // TracingController implementation.
138 const uint8_t* GetCategoryGroupEnabled(const char* name) override {
139 return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(name);
140 }
141 uint64_t AddTraceEvent(
142 char phase,
143 const uint8_t* category_enabled_flag,
144 const char* name,
145 const char* scope,
146 uint64_t id,
147 uint64_t bind_id,
148 int32_t num_args,
149 const char** arg_names,
150 const uint8_t* arg_types,
151 const uint64_t* arg_values,
152 std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
153 unsigned int flags) override {
154 std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
155 convertables[2];
156 if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
157 convertables[0].reset(
158 new ConvertableToTraceFormatWrapper(arg_convertables[0]));
159 }
160 if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) {
161 convertables[1].reset(
162 new ConvertableToTraceFormatWrapper(arg_convertables[1]));
163 }
164 DCHECK_LE(num_args, 2);
165 base::trace_event::TraceEventHandle handle =
166 TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID(
167 phase, category_enabled_flag, name, scope, id, bind_id, num_args,
168 arg_names, arg_types, (const long long unsigned int*)arg_values,
169 convertables, flags);
170 uint64_t result;
171 memcpy(&result, &handle, sizeof(result));
172 return result;
173 }
174 void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
175 const char* name,
176 uint64_t handle) override {
177 base::trace_event::TraceEventHandle traceEventHandle;
178 memcpy(&traceEventHandle, &handle, sizeof(handle));
179 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_enabled_flag, name,
180 traceEventHandle);
181 }
182 void AddTraceStateObserver(TraceStateObserver* observer) override {
183 g_trace_state_dispatcher.Get().AddObserver(observer);
184 }
185 void RemoveTraceStateObserver(TraceStateObserver* observer) override {
186 g_trace_state_dispatcher.Get().RemoveObserver(observer);
187 }
188
189 private:
190 DISALLOW_COPY_AND_ASSIGN(TracingControllerImpl);
191};
192
[email protected]b64e5212014-04-04 21:09:16193// static
194V8Platform* V8Platform::Get() { return g_v8_platform.Pointer(); }
195
Jochen Eisinger7845aae22017-06-26 15:05:45196V8Platform::V8Platform() : tracing_controller_(new TracingControllerImpl) {}
[email protected]b64e5212014-04-04 21:09:16197
198V8Platform::~V8Platform() {}
199
Bill Budged1b87f02017-08-30 06:44:08200void V8Platform::OnCriticalMemoryPressure() {
201#if defined(OS_WIN)
202 // Some configurations do not use page_allocator. Only 32 bit Windows systems
203 // reserve memory currently.
204 base::ReleaseReservation();
205#endif
206}
207
mlippautz40dfecc92016-03-07 21:06:50208size_t V8Platform::NumberOfAvailableBackgroundThreads() {
fdorayb87bcfb82017-05-24 17:49:40209 return std::max(1, base::TaskScheduler::GetInstance()
Jeffrey Hed628419b2017-08-23 18:51:51210 ->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
fdorayb87bcfb82017-05-24 17:49:40211 kBackgroundThreadTaskTraits));
mlippautz40dfecc92016-03-07 21:06:50212}
213
[email protected]b64e5212014-04-04 21:09:16214void V8Platform::CallOnBackgroundThread(
215 v8::Task* task,
216 v8::Platform::ExpectedRuntime expected_runtime) {
fdorayb87bcfb82017-05-24 17:49:40217 base::PostTaskWithTraits(FROM_HERE, kBackgroundThreadTaskTraits,
218 base::Bind(&v8::Task::Run, base::Owned(task)));
[email protected]b64e5212014-04-04 21:09:16219}
220
221void V8Platform::CallOnForegroundThread(v8::Isolate* isolate, v8::Task* task) {
jochen76acff102016-11-08 08:20:37222 PerIsolateData* data = PerIsolateData::From(isolate);
223 if (data->access_mode() == IsolateHolder::kUseLocker) {
224 data->task_runner()->PostTask(
225 FROM_HERE, base::Bind(RunWithLocker, base::Unretained(isolate),
226 base::Owned(task)));
227 } else {
228 data->task_runner()->PostTask(
229 FROM_HERE, base::Bind(&v8::Task::Run, base::Owned(task)));
230 }
[email protected]b64e5212014-04-04 21:09:16231}
232
ulan49cd773c2015-06-24 16:38:08233void V8Platform::CallDelayedOnForegroundThread(v8::Isolate* isolate,
234 v8::Task* task,
235 double delay_in_seconds) {
jochen76acff102016-11-08 08:20:37236 PerIsolateData* data = PerIsolateData::From(isolate);
237 if (data->access_mode() == IsolateHolder::kUseLocker) {
238 data->task_runner()->PostDelayedTask(
239 FROM_HERE,
240 base::Bind(RunWithLocker, base::Unretained(isolate), base::Owned(task)),
241 base::TimeDelta::FromSecondsD(delay_in_seconds));
242 } else {
243 data->task_runner()->PostDelayedTask(
244 FROM_HERE, base::Bind(&v8::Task::Run, base::Owned(task)),
245 base::TimeDelta::FromSecondsD(delay_in_seconds));
246 }
ulan49cd773c2015-06-24 16:38:08247}
248
ulan3cbdcd02015-07-20 11:32:58249void V8Platform::CallIdleOnForegroundThread(v8::Isolate* isolate,
250 v8::IdleTask* task) {
jochen76acff102016-11-08 08:20:37251 PerIsolateData* data = PerIsolateData::From(isolate);
252 DCHECK(data->idle_task_runner());
253 if (data->access_mode() == IsolateHolder::kUseLocker) {
254 data->idle_task_runner()->PostIdleTask(
255 new IdleTaskWithLocker(isolate, task));
256 } else {
257 data->idle_task_runner()->PostIdleTask(task);
258 }
ulan3cbdcd02015-07-20 11:32:58259}
260
261bool V8Platform::IdleTasksEnabled(v8::Isolate* isolate) {
262 return PerIsolateData::From(isolate)->idle_task_runner() != nullptr;
263}
264
rmcilroy05d26622014-10-08 11:28:05265double V8Platform::MonotonicallyIncreasingTime() {
266 return base::TimeTicks::Now().ToInternalValue() /
267 static_cast<double>(base::Time::kMicrosecondsPerSecond);
268}
269
Sergei Dcdd78f72017-08-22 01:45:25270double V8Platform::CurrentClockTimeMillis() {
271 return base::Time::Now().ToJsTime();
272}
273
Jochen Eisinger7845aae22017-06-26 15:05:45274v8::TracingController* V8Platform::GetTracingController() {
275 return tracing_controller_.get();
276}
277
jochen4844f72e2017-03-20 09:07:03278v8::Platform::StackTracePrinter V8Platform::GetStackTracePrinter() {
279 return PrintStackTrace;
280}
281
[email protected]b64e5212014-04-04 21:09:16282} // namespace gin