Avi Drissman | 468e51b6 | 2022-09-13 20:47:01 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors |
[email protected] | b64e521 | 2014-04-04 21:09:16 | [diff] [blame] | 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 | |
fdoray | b87bcfb8 | 2017-05-24 17:49:40 | [diff] [blame] | 7 | #include <algorithm> |
| 8 | |
[email protected] | b64e521 | 2014-04-04 21:09:16 | [diff] [blame] | 9 | #include "base/bind.h" |
Sami Kyostila | 2613496a | 2018-01-04 10:32:57 | [diff] [blame] | 10 | #include "base/bit_cast.h" |
Hans Wennborg | dcc5ada | 2020-04-27 13:27:23 | [diff] [blame] | 11 | #include "base/check_op.h" |
jochen | 4844f72e | 2017-03-20 09:07:03 | [diff] [blame] | 12 | #include "base/debug/stack_trace.h" |
[email protected] | b64e521 | 2014-04-04 21:09:16 | [diff] [blame] | 13 | #include "base/location.h" |
Anton Bikineev | 8d95441b | 2021-10-03 12:26:27 | [diff] [blame] | 14 | #include "base/memory/nonscannable_memory.h" |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 15 | #include "base/memory/raw_ptr.h" |
Sami Kyostila | 2613496a | 2018-01-04 10:32:57 | [diff] [blame] | 16 | #include "base/rand_util.h" |
Sebastien Marchand | 75a7cdf | 2018-11-13 23:47:03 | [diff] [blame] | 17 | #include "base/system/sys_info.h" |
Etienne Pierre-doray | 9caa721e | 2020-05-19 15:22:22 | [diff] [blame] | 18 | #include "base/task/post_job.h" |
Gabriel Charette | 44db142 | 2018-08-06 11:19:33 | [diff] [blame] | 19 | #include "base/task/task_traits.h" |
Gabriel Charette | 99f5df3 | 2021-03-19 19:55:55 | [diff] [blame] | 20 | #include "base/task/thread_pool.h" |
Gabriel Charette | eadf5886 | 2019-08-29 05:20:27 | [diff] [blame] | 21 | #include "base/task/thread_pool/thread_pool_instance.h" |
tmoniuszko | 3641693 | 2016-01-27 16:28:45 | [diff] [blame] | 22 | #include "base/trace_event/trace_event.h" |
Sami Kyostila | 88a4d55 | 2021-01-06 10:15:19 | [diff] [blame] | 23 | #include "base/tracing_buildflags.h" |
Bill Budge | d1b87f0 | 2017-08-30 06:44:08 | [diff] [blame] | 24 | #include "build/build_config.h" |
[email protected] | b64e521 | 2014-04-04 21:09:16 | [diff] [blame] | 25 | #include "gin/per_isolate_data.h" |
André Kempe | 6026911 | 2021-09-17 13:14:11 | [diff] [blame] | 26 | #include "v8_platform_page_allocator.h" |
[email protected] | b64e521 | 2014-04-04 21:09:16 | [diff] [blame] | 27 | |
| 28 | namespace gin { |
| 29 | |
| 30 | namespace { |
| 31 | |
| 32 | base::LazyInstance<V8Platform>::Leaky g_v8_platform = LAZY_INSTANCE_INITIALIZER; |
| 33 | |
Andreas Haas | 6d4023c | 2019-01-18 13:16:00 | [diff] [blame] | 34 | constexpr base::TaskTraits kLowPriorityTaskTraits = { |
Gabriel Charette | 8209d844 | 2020-02-28 17:52:35 | [diff] [blame] | 35 | base::TaskPriority::BEST_EFFORT}; |
Andreas Haas | 6d4023c | 2019-01-18 13:16:00 | [diff] [blame] | 36 | |
Gabriel Charette | ca4884b | 2018-05-04 17:35:06 | [diff] [blame] | 37 | constexpr base::TaskTraits kDefaultTaskTraits = { |
Gabriel Charette | 8209d844 | 2020-02-28 17:52:35 | [diff] [blame] | 38 | base::TaskPriority::USER_VISIBLE}; |
Gabriel Charette | ca4884b | 2018-05-04 17:35:06 | [diff] [blame] | 39 | |
| 40 | constexpr base::TaskTraits kBlockingTaskTraits = { |
Gabriel Charette | 8209d844 | 2020-02-28 17:52:35 | [diff] [blame] | 41 | base::TaskPriority::USER_BLOCKING}; |
Gabriel Charette | ca4884b | 2018-05-04 17:35:06 | [diff] [blame] | 42 | |
jochen | 4844f72e | 2017-03-20 09:07:03 | [diff] [blame] | 43 | void PrintStackTrace() { |
| 44 | base::debug::StackTrace trace; |
| 45 | trace.Print(); |
| 46 | } |
| 47 | |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 48 | class ConvertableToTraceFormatWrapper final |
| 49 | : public base::trace_event::ConvertableToTraceFormat { |
| 50 | public: |
| 51 | explicit ConvertableToTraceFormatWrapper( |
David 'Digit' Turner | c1b9c28 | 2019-01-08 15:13:11 | [diff] [blame] | 52 | std::unique_ptr<v8::ConvertableToTraceFormat> inner) |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 53 | : inner_(std::move(inner)) {} |
Daniel Hosseinian | 68c0798d | 2021-04-16 08:16:07 | [diff] [blame] | 54 | ConvertableToTraceFormatWrapper(const ConvertableToTraceFormatWrapper&) = |
| 55 | delete; |
| 56 | ConvertableToTraceFormatWrapper& operator=( |
| 57 | const ConvertableToTraceFormatWrapper&) = delete; |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 58 | ~ConvertableToTraceFormatWrapper() override = default; |
| 59 | void AppendAsTraceFormat(std::string* out) const final { |
| 60 | inner_->AppendAsTraceFormat(out); |
| 61 | } |
| 62 | |
| 63 | private: |
| 64 | std::unique_ptr<v8::ConvertableToTraceFormat> inner_; |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 65 | }; |
| 66 | |
| 67 | class EnabledStateObserverImpl final |
| 68 | : public base::trace_event::TraceLog::EnabledStateObserver { |
| 69 | public: |
Alexei Filippov | 05cd86c3c | 2018-09-26 02:12:12 | [diff] [blame] | 70 | EnabledStateObserverImpl() { |
| 71 | base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this); |
| 72 | } |
| 73 | |
Daniel Hosseinian | 68c0798d | 2021-04-16 08:16:07 | [diff] [blame] | 74 | EnabledStateObserverImpl(const EnabledStateObserverImpl&) = delete; |
| 75 | |
| 76 | EnabledStateObserverImpl& operator=(const EnabledStateObserverImpl&) = delete; |
| 77 | |
Alexei Filippov | 05cd86c3c | 2018-09-26 02:12:12 | [diff] [blame] | 78 | ~EnabledStateObserverImpl() override { |
| 79 | base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver( |
| 80 | this); |
| 81 | } |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 82 | |
| 83 | void OnTraceLogEnabled() final { |
| 84 | base::AutoLock lock(mutex_); |
| 85 | for (auto* o : observers_) { |
| 86 | o->OnTraceEnabled(); |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | void OnTraceLogDisabled() final { |
| 91 | base::AutoLock lock(mutex_); |
| 92 | for (auto* o : observers_) { |
| 93 | o->OnTraceDisabled(); |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | void AddObserver(v8::TracingController::TraceStateObserver* observer) { |
| 98 | { |
| 99 | base::AutoLock lock(mutex_); |
| 100 | DCHECK(!observers_.count(observer)); |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 101 | observers_.insert(observer); |
| 102 | } |
Alexei Filippov | 05cd86c3c | 2018-09-26 02:12:12 | [diff] [blame] | 103 | |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 104 | // Fire the observer if recording is already in progress. |
| 105 | if (base::trace_event::TraceLog::GetInstance()->IsEnabled()) |
| 106 | observer->OnTraceEnabled(); |
| 107 | } |
| 108 | |
| 109 | void RemoveObserver(v8::TracingController::TraceStateObserver* observer) { |
| 110 | base::AutoLock lock(mutex_); |
| 111 | DCHECK(observers_.count(observer) == 1); |
| 112 | observers_.erase(observer); |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 113 | } |
| 114 | |
| 115 | private: |
| 116 | base::Lock mutex_; |
| 117 | std::unordered_set<v8::TracingController::TraceStateObserver*> observers_; |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 118 | }; |
| 119 | |
| 120 | base::LazyInstance<EnabledStateObserverImpl>::Leaky g_trace_state_dispatcher = |
| 121 | LAZY_INSTANCE_INITIALIZER; |
| 122 | |
Sami Kyostila | 2613496a | 2018-01-04 10:32:57 | [diff] [blame] | 123 | // TODO(skyostil): Deduplicate this with the clamper in Blink. |
| 124 | class TimeClamper { |
| 125 | public: |
Sami Kyostila | 1cf0735 | 2018-10-22 12:16:25 | [diff] [blame] | 126 | // As site isolation is enabled on desktop platforms, we can safely provide |
| 127 | // more timing resolution. Jittering is still enabled everywhere. |
Xiaohan Wang | c696a474 | 2022-01-08 01:20:46 | [diff] [blame] | 128 | #if BUILDFLAG(IS_ANDROID) |
Sami Kyostila | 1cf0735 | 2018-10-22 12:16:25 | [diff] [blame] | 129 | static constexpr double kResolutionSeconds = 100e-6; |
| 130 | #else |
| 131 | static constexpr double kResolutionSeconds = 5e-6; |
| 132 | #endif |
Sami Kyostila | 2613496a | 2018-01-04 10:32:57 | [diff] [blame] | 133 | |
| 134 | TimeClamper() : secret_(base::RandUint64()) {} |
Daniel Hosseinian | 68c0798d | 2021-04-16 08:16:07 | [diff] [blame] | 135 | TimeClamper(const TimeClamper&) = delete; |
| 136 | TimeClamper& operator=(const TimeClamper&) = delete; |
Sami Kyostila | 2613496a | 2018-01-04 10:32:57 | [diff] [blame] | 137 | |
| 138 | double ClampTimeResolution(double time_seconds) const { |
Kenneth Russell | 0ebb714c | 2018-07-20 22:03:35 | [diff] [blame] | 139 | bool was_negative = false; |
| 140 | if (time_seconds < 0) { |
| 141 | was_negative = true; |
| 142 | time_seconds = -time_seconds; |
| 143 | } |
Sami Kyostila | 2613496a | 2018-01-04 10:32:57 | [diff] [blame] | 144 | // For each clamped time interval, compute a pseudorandom transition |
| 145 | // threshold. The reported time will either be the start of that interval or |
| 146 | // the next one depending on which side of the threshold |time_seconds| is. |
Sami Kyostila | 874bac6e | 2018-01-16 12:23:57 | [diff] [blame] | 147 | double interval = floor(time_seconds / kResolutionSeconds); |
| 148 | double clamped_time = interval * kResolutionSeconds; |
Sami Kyostila | 2613496a | 2018-01-04 10:32:57 | [diff] [blame] | 149 | double tick_threshold = ThresholdFor(clamped_time); |
| 150 | |
| 151 | if (time_seconds >= tick_threshold) |
Kenneth Russell | 0ebb714c | 2018-07-20 22:03:35 | [diff] [blame] | 152 | clamped_time = (interval + 1) * kResolutionSeconds; |
| 153 | if (was_negative) |
| 154 | clamped_time = -clamped_time; |
Sami Kyostila | 2613496a | 2018-01-04 10:32:57 | [diff] [blame] | 155 | return clamped_time; |
| 156 | } |
| 157 | |
| 158 | private: |
| 159 | inline double ThresholdFor(double clamped_time) const { |
Peter Kasting | cc88ac05 | 2022-05-03 09:58:01 | [diff] [blame] | 160 | uint64_t time_hash = |
| 161 | MurmurHash3(base::bit_cast<int64_t>(clamped_time) ^ secret_); |
Sami Kyostila | 2613496a | 2018-01-04 10:32:57 | [diff] [blame] | 162 | return clamped_time + kResolutionSeconds * ToDouble(time_hash); |
| 163 | } |
| 164 | |
| 165 | static inline double ToDouble(uint64_t value) { |
| 166 | // Exponent for double values for [1.0 .. 2.0] |
| 167 | static const uint64_t kExponentBits = uint64_t{0x3FF0000000000000}; |
| 168 | static const uint64_t kMantissaMask = uint64_t{0x000FFFFFFFFFFFFF}; |
| 169 | uint64_t random = (value & kMantissaMask) | kExponentBits; |
Peter Kasting | cc88ac05 | 2022-05-03 09:58:01 | [diff] [blame] | 170 | return base::bit_cast<double>(random) - 1; |
Sami Kyostila | 2613496a | 2018-01-04 10:32:57 | [diff] [blame] | 171 | } |
| 172 | |
| 173 | static inline uint64_t MurmurHash3(uint64_t value) { |
| 174 | value ^= value >> 33; |
| 175 | value *= uint64_t{0xFF51AFD7ED558CCD}; |
| 176 | value ^= value >> 33; |
| 177 | value *= uint64_t{0xC4CEB9FE1A85EC53}; |
| 178 | value ^= value >> 33; |
| 179 | return value; |
| 180 | } |
| 181 | |
| 182 | const uint64_t secret_; |
Sami Kyostila | 2613496a | 2018-01-04 10:32:57 | [diff] [blame] | 183 | }; |
| 184 | |
| 185 | base::LazyInstance<TimeClamper>::Leaky g_time_clamper = |
| 186 | LAZY_INSTANCE_INITIALIZER; |
| 187 | |
Bill Budge | 24b75fd | 2018-02-02 01:45:20 | [diff] [blame] | 188 | #if BUILDFLAG(USE_PARTITION_ALLOC) |
Bill Budge | 24b75fd | 2018-02-02 01:45:20 | [diff] [blame] | 189 | |
André Kempe | 6026911 | 2021-09-17 13:14:11 | [diff] [blame] | 190 | base::LazyInstance<gin::PageAllocator>::Leaky g_page_allocator = |
Bill Budge | 24b75fd | 2018-02-02 01:45:20 | [diff] [blame] | 191 | LAZY_INSTANCE_INITIALIZER; |
| 192 | |
| 193 | #endif // BUILDFLAG(USE_PARTITION_ALLOC) |
| 194 | |
Etienne Pierre-doray | 9caa721e | 2020-05-19 15:22:22 | [diff] [blame] | 195 | class JobDelegateImpl : public v8::JobDelegate { |
| 196 | public: |
| 197 | explicit JobDelegateImpl(base::JobDelegate* delegate) : delegate_(delegate) {} |
| 198 | JobDelegateImpl() = default; |
| 199 | |
| 200 | JobDelegateImpl(const JobDelegateImpl&) = delete; |
| 201 | JobDelegateImpl& operator=(const JobDelegateImpl&) = delete; |
| 202 | |
| 203 | // v8::JobDelegate: |
| 204 | bool ShouldYield() override { return delegate_->ShouldYield(); } |
| 205 | void NotifyConcurrencyIncrease() override { |
| 206 | delegate_->NotifyConcurrencyIncrease(); |
| 207 | } |
Etienne Pierre-doray | df06735 | 2020-08-17 15:50:26 | [diff] [blame] | 208 | uint8_t GetTaskId() override { return delegate_->GetTaskId(); } |
Etienne Pierre-doray | bcff179ae | 2020-09-22 14:53:53 | [diff] [blame] | 209 | bool IsJoiningThread() const override { return delegate_->IsJoiningThread(); } |
Etienne Pierre-doray | 9caa721e | 2020-05-19 15:22:22 | [diff] [blame] | 210 | |
| 211 | private: |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 212 | raw_ptr<base::JobDelegate> delegate_; |
Etienne Pierre-doray | 9caa721e | 2020-05-19 15:22:22 | [diff] [blame] | 213 | }; |
| 214 | |
| 215 | class JobHandleImpl : public v8::JobHandle { |
| 216 | public: |
Etienne Pierre-doray | 2e0c74cf | 2020-12-03 15:17:18 | [diff] [blame] | 217 | explicit JobHandleImpl(base::JobHandle handle) : handle_(std::move(handle)) {} |
Etienne Pierre-doray | 9caa721e | 2020-05-19 15:22:22 | [diff] [blame] | 218 | ~JobHandleImpl() override = default; |
| 219 | |
| 220 | JobHandleImpl(const JobHandleImpl&) = delete; |
| 221 | JobHandleImpl& operator=(const JobHandleImpl&) = delete; |
| 222 | |
| 223 | // v8::JobHandle: |
| 224 | void NotifyConcurrencyIncrease() override { |
| 225 | handle_.NotifyConcurrencyIncrease(); |
| 226 | } |
Etienne Pierre-doray | 1307346 | 2020-11-03 18:51:11 | [diff] [blame] | 227 | bool UpdatePriorityEnabled() const override { return true; } |
| 228 | void UpdatePriority(v8::TaskPriority new_priority) override { |
| 229 | handle_.UpdatePriority(ToBaseTaskPriority(new_priority)); |
| 230 | } |
Etienne Pierre-doray | 9caa721e | 2020-05-19 15:22:22 | [diff] [blame] | 231 | void Join() override { handle_.Join(); } |
| 232 | void Cancel() override { handle_.Cancel(); } |
Etienne Pierre-doray | c72968a0 | 2020-10-08 13:28:02 | [diff] [blame] | 233 | void CancelAndDetach() override { handle_.CancelAndDetach(); } |
Etienne Pierre-doray | 4fea66bd | 2020-11-30 23:20:12 | [diff] [blame] | 234 | bool IsActive() override { return handle_.IsActive(); } |
| 235 | bool IsValid() override { return !!handle_; } |
| 236 | |
Etienne Pierre-doray | 9caa721e | 2020-05-19 15:22:22 | [diff] [blame] | 237 | private: |
Etienne Pierre-doray | 1307346 | 2020-11-03 18:51:11 | [diff] [blame] | 238 | static base::TaskPriority ToBaseTaskPriority(v8::TaskPriority priority) { |
| 239 | switch (priority) { |
| 240 | case v8::TaskPriority::kBestEffort: |
| 241 | return base::TaskPriority::BEST_EFFORT; |
| 242 | case v8::TaskPriority::kUserVisible: |
| 243 | return base::TaskPriority::USER_VISIBLE; |
| 244 | case v8::TaskPriority::kUserBlocking: |
| 245 | return base::TaskPriority::USER_BLOCKING; |
| 246 | } |
| 247 | } |
| 248 | |
Etienne Pierre-doray | 9caa721e | 2020-05-19 15:22:22 | [diff] [blame] | 249 | base::JobHandle handle_; |
Etienne Pierre-doray | 9caa721e | 2020-05-19 15:22:22 | [diff] [blame] | 250 | }; |
| 251 | |
[email protected] | b64e521 | 2014-04-04 21:09:16 | [diff] [blame] | 252 | } // namespace |
| 253 | |
David 'Digit' Turner | c1b9c28 | 2019-01-08 15:13:11 | [diff] [blame] | 254 | } // namespace gin |
| 255 | |
| 256 | // Allow std::unique_ptr<v8::ConvertableToTraceFormat> to be a valid |
| 257 | // initialization value for trace macros. |
| 258 | template <> |
| 259 | struct base::trace_event::TraceValue::Helper< |
| 260 | std::unique_ptr<v8::ConvertableToTraceFormat>> { |
| 261 | static constexpr unsigned char kType = TRACE_VALUE_TYPE_CONVERTABLE; |
| 262 | static inline void SetValue( |
| 263 | TraceValue* v, |
| 264 | std::unique_ptr<v8::ConvertableToTraceFormat> value) { |
| 265 | // NOTE: |as_convertable| is an owning pointer, so using new here |
| 266 | // is acceptable. |
| 267 | v->as_convertable = |
| 268 | new gin::ConvertableToTraceFormatWrapper(std::move(value)); |
| 269 | } |
| 270 | }; |
| 271 | |
| 272 | namespace gin { |
| 273 | |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 274 | class V8Platform::TracingControllerImpl : public v8::TracingController { |
| 275 | public: |
| 276 | TracingControllerImpl() = default; |
Daniel Hosseinian | 68c0798d | 2021-04-16 08:16:07 | [diff] [blame] | 277 | TracingControllerImpl(const TracingControllerImpl&) = delete; |
| 278 | TracingControllerImpl& operator=(const TracingControllerImpl&) = delete; |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 279 | ~TracingControllerImpl() override = default; |
| 280 | |
| 281 | // TracingController implementation. |
Sami Kyostila | 88a4d55 | 2021-01-06 10:15:19 | [diff] [blame] | 282 | #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 283 | const uint8_t* GetCategoryGroupEnabled(const char* name) override { |
| 284 | return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(name); |
| 285 | } |
| 286 | uint64_t AddTraceEvent( |
| 287 | char phase, |
| 288 | const uint8_t* category_enabled_flag, |
| 289 | const char* name, |
| 290 | const char* scope, |
| 291 | uint64_t id, |
| 292 | uint64_t bind_id, |
| 293 | int32_t num_args, |
| 294 | const char** arg_names, |
| 295 | const uint8_t* arg_types, |
| 296 | const uint64_t* arg_values, |
| 297 | std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, |
| 298 | unsigned int flags) override { |
David 'Digit' Turner | c1b9c28 | 2019-01-08 15:13:11 | [diff] [blame] | 299 | base::trace_event::TraceArguments args( |
| 300 | num_args, arg_names, arg_types, |
| 301 | reinterpret_cast<const unsigned long long*>(arg_values), |
| 302 | arg_convertables); |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 303 | DCHECK_LE(num_args, 2); |
| 304 | base::trace_event::TraceEventHandle handle = |
| 305 | TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID( |
David 'Digit' Turner | c1b9c28 | 2019-01-08 15:13:11 | [diff] [blame] | 306 | phase, category_enabled_flag, name, scope, id, bind_id, &args, |
| 307 | flags); |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 308 | uint64_t result; |
| 309 | memcpy(&result, &handle, sizeof(result)); |
| 310 | return result; |
| 311 | } |
Sajal Khandelwal | 56c2931 | 2019-04-24 21:40:33 | [diff] [blame] | 312 | uint64_t AddTraceEventWithTimestamp( |
| 313 | char phase, |
| 314 | const uint8_t* category_enabled_flag, |
| 315 | const char* name, |
| 316 | const char* scope, |
| 317 | uint64_t id, |
| 318 | uint64_t bind_id, |
| 319 | int32_t num_args, |
| 320 | const char** arg_names, |
| 321 | const uint8_t* arg_types, |
| 322 | const uint64_t* arg_values, |
| 323 | std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, |
| 324 | unsigned int flags, |
| 325 | int64_t timestampMicroseconds) override { |
| 326 | base::trace_event::TraceArguments args( |
| 327 | num_args, arg_names, arg_types, |
| 328 | reinterpret_cast<const unsigned long long*>(arg_values), |
| 329 | arg_convertables); |
| 330 | DCHECK_LE(num_args, 2); |
| 331 | base::TimeTicks timestamp = |
Peter Kasting | e5a38ed | 2021-10-02 03:06:35 | [diff] [blame] | 332 | base::TimeTicks() + base::Microseconds(timestampMicroseconds); |
Sajal Khandelwal | 56c2931 | 2019-04-24 21:40:33 | [diff] [blame] | 333 | base::trace_event::TraceEventHandle handle = |
| 334 | TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( |
| 335 | phase, category_enabled_flag, name, scope, id, bind_id, |
| 336 | TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, &args, flags); |
| 337 | uint64_t result; |
| 338 | memcpy(&result, &handle, sizeof(result)); |
| 339 | return result; |
| 340 | } |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 341 | void UpdateTraceEventDuration(const uint8_t* category_enabled_flag, |
| 342 | const char* name, |
| 343 | uint64_t handle) override { |
| 344 | base::trace_event::TraceEventHandle traceEventHandle; |
| 345 | memcpy(&traceEventHandle, &handle, sizeof(handle)); |
| 346 | TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_enabled_flag, name, |
| 347 | traceEventHandle); |
| 348 | } |
Sami Kyostila | 88a4d55 | 2021-01-06 10:15:19 | [diff] [blame] | 349 | #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 350 | void AddTraceStateObserver(TraceStateObserver* observer) override { |
| 351 | g_trace_state_dispatcher.Get().AddObserver(observer); |
| 352 | } |
| 353 | void RemoveTraceStateObserver(TraceStateObserver* observer) override { |
| 354 | g_trace_state_dispatcher.Get().RemoveObserver(observer); |
| 355 | } |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 356 | }; |
| 357 | |
[email protected] | b64e521 | 2014-04-04 21:09:16 | [diff] [blame] | 358 | // static |
| 359 | V8Platform* V8Platform::Get() { return g_v8_platform.Pointer(); } |
| 360 | |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 361 | V8Platform::V8Platform() : tracing_controller_(new TracingControllerImpl) {} |
[email protected] | b64e521 | 2014-04-04 21:09:16 | [diff] [blame] | 362 | |
Chris Watkins | 756035a | 2017-12-01 03:03:27 | [diff] [blame] | 363 | V8Platform::~V8Platform() = default; |
[email protected] | b64e521 | 2014-04-04 21:09:16 | [diff] [blame] | 364 | |
Bill Budge | 24b75fd | 2018-02-02 01:45:20 | [diff] [blame] | 365 | #if BUILDFLAG(USE_PARTITION_ALLOC) |
André Kempe | 6026911 | 2021-09-17 13:14:11 | [diff] [blame] | 366 | PageAllocator* V8Platform::GetPageAllocator() { |
Bill Budge | 24b75fd | 2018-02-02 01:45:20 | [diff] [blame] | 367 | return g_page_allocator.Pointer(); |
| 368 | } |
| 369 | |
Bill Budge | d1b87f0 | 2017-08-30 06:44:08 | [diff] [blame] | 370 | void V8Platform::OnCriticalMemoryPressure() { |
Bill Budge | 24b75fd | 2018-02-02 01:45:20 | [diff] [blame] | 371 | // We only have a reservation on 32-bit Windows systems. |
| 372 | // TODO(bbudge) Make the #if's in BlinkInitializer match. |
Xiaohan Wang | c696a474 | 2022-01-08 01:20:46 | [diff] [blame] | 373 | #if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_32_BITS) |
Kalvin Lee | cb9c00c2 | 2022-07-12 05:18:35 | [diff] [blame] | 374 | partition_alloc::ReleaseReservation(); |
Bill Budge | d1b87f0 | 2017-08-30 06:44:08 | [diff] [blame] | 375 | #endif |
| 376 | } |
Anton Bikineev | 8d95441b | 2021-10-03 12:26:27 | [diff] [blame] | 377 | |
| 378 | v8::ZoneBackingAllocator* V8Platform::GetZoneBackingAllocator() { |
| 379 | static struct Allocator final : v8::ZoneBackingAllocator { |
| 380 | MallocFn GetMallocFn() const override { |
| 381 | return &base::AllocNonQuarantinable; |
| 382 | } |
| 383 | FreeFn GetFreeFn() const override { return &base::FreeNonQuarantinable; } |
| 384 | } allocator; |
| 385 | return &allocator; |
| 386 | } |
Bill Budge | 24b75fd | 2018-02-02 01:45:20 | [diff] [blame] | 387 | #endif // BUILDFLAG(USE_PARTITION_ALLOC) |
Bill Budge | d1b87f0 | 2017-08-30 06:44:08 | [diff] [blame] | 388 | |
Andreas Haas | c13cae8 | 2017-11-16 12:54:38 | [diff] [blame] | 389 | std::shared_ptr<v8::TaskRunner> V8Platform::GetForegroundTaskRunner( |
| 390 | v8::Isolate* isolate) { |
| 391 | PerIsolateData* data = PerIsolateData::From(isolate); |
| 392 | return data->task_runner(); |
| 393 | } |
| 394 | |
Gabriel Charette | ca4884b | 2018-05-04 17:35:06 | [diff] [blame] | 395 | int V8Platform::NumberOfWorkerThreads() { |
| 396 | // V8Platform assumes the scheduler uses the same set of workers for default |
| 397 | // and user blocking tasks. |
Peter Kasting | 12bf330 | 2022-06-07 19:52:07 | [diff] [blame] | 398 | const size_t num_foreground_workers = |
Gabriel Charette | 43fd370 | 2019-05-29 16:36:51 | [diff] [blame] | 399 | base::ThreadPoolInstance::Get() |
Gabriel Charette | ca4884b | 2018-05-04 17:35:06 | [diff] [blame] | 400 | ->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated( |
| 401 | kDefaultTaskTraits); |
| 402 | DCHECK_EQ(num_foreground_workers, |
Gabriel Charette | 43fd370 | 2019-05-29 16:36:51 | [diff] [blame] | 403 | base::ThreadPoolInstance::Get() |
Gabriel Charette | ca4884b | 2018-05-04 17:35:06 | [diff] [blame] | 404 | ->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated( |
| 405 | kBlockingTaskTraits)); |
Peter Kasting | 12bf330 | 2022-06-07 19:52:07 | [diff] [blame] | 406 | return std::max(1, static_cast<int>(num_foreground_workers)); |
Andreas Haas | c13cae8 | 2017-11-16 12:54:38 | [diff] [blame] | 407 | } |
| 408 | |
Gabriel Charette | ca4884b | 2018-05-04 17:35:06 | [diff] [blame] | 409 | void V8Platform::CallOnWorkerThread(std::unique_ptr<v8::Task> task) { |
Gabriel Charette | 8209d844 | 2020-02-28 17:52:35 | [diff] [blame] | 410 | base::ThreadPool::PostTask(FROM_HERE, kDefaultTaskTraits, |
| 411 | base::BindOnce(&v8::Task::Run, std::move(task))); |
mlippautz | 40dfecc9 | 2016-03-07 21:06:50 | [diff] [blame] | 412 | } |
| 413 | |
Gabriel Charette | ca4884b | 2018-05-04 17:35:06 | [diff] [blame] | 414 | void V8Platform::CallBlockingTaskOnWorkerThread( |
| 415 | std::unique_ptr<v8::Task> task) { |
Gabriel Charette | 8209d844 | 2020-02-28 17:52:35 | [diff] [blame] | 416 | base::ThreadPool::PostTask(FROM_HERE, kBlockingTaskTraits, |
| 417 | base::BindOnce(&v8::Task::Run, std::move(task))); |
Gabriel Charette | ca4884b | 2018-05-04 17:35:06 | [diff] [blame] | 418 | } |
| 419 | |
Andreas Haas | 6d4023c | 2019-01-18 13:16:00 | [diff] [blame] | 420 | void V8Platform::CallLowPriorityTaskOnWorkerThread( |
| 421 | std::unique_ptr<v8::Task> task) { |
Gabriel Charette | 8209d844 | 2020-02-28 17:52:35 | [diff] [blame] | 422 | base::ThreadPool::PostTask(FROM_HERE, kLowPriorityTaskTraits, |
| 423 | base::BindOnce(&v8::Task::Run, std::move(task))); |
Andreas Haas | 6d4023c | 2019-01-18 13:16:00 | [diff] [blame] | 424 | } |
| 425 | |
Gabriel Charette | ca4884b | 2018-05-04 17:35:06 | [diff] [blame] | 426 | void V8Platform::CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task, |
| 427 | double delay_in_seconds) { |
Gabriel Charette | 8209d844 | 2020-02-28 17:52:35 | [diff] [blame] | 428 | base::ThreadPool::PostDelayedTask( |
| 429 | FROM_HERE, kDefaultTaskTraits, |
| 430 | base::BindOnce(&v8::Task::Run, std::move(task)), |
Peter Kasting | e5a38ed | 2021-10-02 03:06:35 | [diff] [blame] | 431 | base::Seconds(delay_in_seconds)); |
[email protected] | b64e521 | 2014-04-04 21:09:16 | [diff] [blame] | 432 | } |
| 433 | |
Etienne Pierre-doray | 3a94d64 | 2022-06-21 17:35:53 | [diff] [blame] | 434 | std::unique_ptr<v8::JobHandle> V8Platform::CreateJob( |
Etienne Pierre-doray | 9caa721e | 2020-05-19 15:22:22 | [diff] [blame] | 435 | v8::TaskPriority priority, |
| 436 | std::unique_ptr<v8::JobTask> job_task) { |
| 437 | base::TaskTraits task_traits; |
| 438 | switch (priority) { |
| 439 | case v8::TaskPriority::kBestEffort: |
| 440 | task_traits = kLowPriorityTaskTraits; |
| 441 | break; |
| 442 | case v8::TaskPriority::kUserVisible: |
| 443 | task_traits = kDefaultTaskTraits; |
| 444 | break; |
| 445 | case v8::TaskPriority::kUserBlocking: |
| 446 | task_traits = kBlockingTaskTraits; |
| 447 | break; |
| 448 | } |
Etienne Pierre-doray | 2e0c74cf | 2020-12-03 15:17:18 | [diff] [blame] | 449 | // Ownership of |job_task| is assumed by |worker_task|, while |
| 450 | // |max_concurrency_callback| uses an unretained pointer. |
| 451 | auto* job_task_ptr = job_task.get(); |
Etienne Pierre-doray | 2f52b351 | 2020-08-12 19:04:29 | [diff] [blame] | 452 | auto handle = |
Etienne Pierre-doray | 3a94d64 | 2022-06-21 17:35:53 | [diff] [blame] | 453 | base::CreateJob(FROM_HERE, task_traits, |
| 454 | base::BindRepeating( |
| 455 | [](const std::unique_ptr<v8::JobTask>& job_task, |
| 456 | base::JobDelegate* delegate) { |
| 457 | JobDelegateImpl delegate_impl(delegate); |
| 458 | job_task->Run(&delegate_impl); |
| 459 | }, |
| 460 | std::move(job_task)), |
| 461 | base::BindRepeating( |
| 462 | [](v8::JobTask* job_task, size_t worker_count) { |
| 463 | return job_task->GetMaxConcurrency(worker_count); |
| 464 | }, |
| 465 | base::Unretained(job_task_ptr))); |
Etienne Pierre-doray | 9caa721e | 2020-05-19 15:22:22 | [diff] [blame] | 466 | |
Etienne Pierre-doray | 2e0c74cf | 2020-12-03 15:17:18 | [diff] [blame] | 467 | return std::make_unique<JobHandleImpl>(std::move(handle)); |
Etienne Pierre-doray | 9caa721e | 2020-05-19 15:22:22 | [diff] [blame] | 468 | } |
| 469 | |
ulan | 3cbdcd0 | 2015-07-20 11:32:58 | [diff] [blame] | 470 | bool V8Platform::IdleTasksEnabled(v8::Isolate* isolate) { |
Andreas Haas | c13cae8 | 2017-11-16 12:54:38 | [diff] [blame] | 471 | return PerIsolateData::From(isolate)->task_runner()->IdleTasksEnabled(); |
ulan | 3cbdcd0 | 2015-07-20 11:32:58 | [diff] [blame] | 472 | } |
| 473 | |
rmcilroy | 05d2662 | 2014-10-08 11:28:05 | [diff] [blame] | 474 | double V8Platform::MonotonicallyIncreasingTime() { |
| 475 | return base::TimeTicks::Now().ToInternalValue() / |
| 476 | static_cast<double>(base::Time::kMicrosecondsPerSecond); |
| 477 | } |
| 478 | |
Sergei D | cdd78f7 | 2017-08-22 01:45:25 | [diff] [blame] | 479 | double V8Platform::CurrentClockTimeMillis() { |
Sami Kyostila | 2613496a | 2018-01-04 10:32:57 | [diff] [blame] | 480 | double now_seconds = base::Time::Now().ToJsTime() / 1000; |
| 481 | return g_time_clamper.Get().ClampTimeResolution(now_seconds) * 1000; |
Sergei D | cdd78f7 | 2017-08-22 01:45:25 | [diff] [blame] | 482 | } |
| 483 | |
Jochen Eisinger | 7845aae2 | 2017-06-26 15:05:45 | [diff] [blame] | 484 | v8::TracingController* V8Platform::GetTracingController() { |
| 485 | return tracing_controller_.get(); |
| 486 | } |
| 487 | |
jochen | 4844f72e | 2017-03-20 09:07:03 | [diff] [blame] | 488 | v8::Platform::StackTracePrinter V8Platform::GetStackTracePrinter() { |
| 489 | return PrintStackTrace; |
| 490 | } |
| 491 | |
[email protected] | b64e521 | 2014-04-04 21:09:16 | [diff] [blame] | 492 | } // namespace gin |