11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_LOGGING_METRICS_H_
61cb0ef41Sopenharmony_ci#define V8_LOGGING_METRICS_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <memory>
91cb0ef41Sopenharmony_ci#include <queue>
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci#include "include/v8-metrics.h"
121cb0ef41Sopenharmony_ci#include "src/base/platform/mutex.h"
131cb0ef41Sopenharmony_ci#include "src/base/platform/time.h"
141cb0ef41Sopenharmony_ci#include "src/init/v8.h"
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_cinamespace v8 {
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ciclass TaskRunner;
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_cinamespace internal {
211cb0ef41Sopenharmony_cinamespace metrics {
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ciclass Recorder : public std::enable_shared_from_this<Recorder> {
241cb0ef41Sopenharmony_ci public:
251cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE void SetEmbedderRecorder(
261cb0ef41Sopenharmony_ci      Isolate* isolate,
271cb0ef41Sopenharmony_ci      const std::shared_ptr<v8::metrics::Recorder>& embedder_recorder);
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE bool HasEmbedderRecorder() const;
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE void NotifyIsolateDisposal();
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci  template <class T>
341cb0ef41Sopenharmony_ci  void AddMainThreadEvent(const T& event,
351cb0ef41Sopenharmony_ci                          v8::metrics::Recorder::ContextId id) {
361cb0ef41Sopenharmony_ci    if (embedder_recorder_)
371cb0ef41Sopenharmony_ci      embedder_recorder_->AddMainThreadEvent(event, id);
381cb0ef41Sopenharmony_ci  }
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  template <class T>
411cb0ef41Sopenharmony_ci  void DelayMainThreadEvent(const T& event,
421cb0ef41Sopenharmony_ci                            v8::metrics::Recorder::ContextId id) {
431cb0ef41Sopenharmony_ci    if (!embedder_recorder_) return;
441cb0ef41Sopenharmony_ci    Delay(std::make_unique<DelayedEvent<T>>(event, id));
451cb0ef41Sopenharmony_ci  }
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  template <class T>
481cb0ef41Sopenharmony_ci  void AddThreadSafeEvent(const T& event) {
491cb0ef41Sopenharmony_ci    if (embedder_recorder_) embedder_recorder_->AddThreadSafeEvent(event);
501cb0ef41Sopenharmony_ci  }
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci private:
531cb0ef41Sopenharmony_ci  class DelayedEventBase {
541cb0ef41Sopenharmony_ci   public:
551cb0ef41Sopenharmony_ci    virtual ~DelayedEventBase() = default;
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci    virtual void Run(const std::shared_ptr<Recorder>& recorder) = 0;
581cb0ef41Sopenharmony_ci  };
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  template <class T>
611cb0ef41Sopenharmony_ci  class DelayedEvent : public DelayedEventBase {
621cb0ef41Sopenharmony_ci   public:
631cb0ef41Sopenharmony_ci    DelayedEvent(const T& event, v8::metrics::Recorder::ContextId id)
641cb0ef41Sopenharmony_ci        : event_(event), id_(id) {}
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci    void Run(const std::shared_ptr<Recorder>& recorder) override {
671cb0ef41Sopenharmony_ci      recorder->AddMainThreadEvent(event_, id_);
681cb0ef41Sopenharmony_ci    }
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci   protected:
711cb0ef41Sopenharmony_ci    T event_;
721cb0ef41Sopenharmony_ci    v8::metrics::Recorder::ContextId id_;
731cb0ef41Sopenharmony_ci  };
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  class Task;
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE void Delay(
781cb0ef41Sopenharmony_ci      std::unique_ptr<Recorder::DelayedEventBase>&& event);
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  base::Mutex lock_;
811cb0ef41Sopenharmony_ci  std::shared_ptr<v8::TaskRunner> foreground_task_runner_;
821cb0ef41Sopenharmony_ci  std::shared_ptr<v8::metrics::Recorder> embedder_recorder_;
831cb0ef41Sopenharmony_ci  std::queue<std::unique_ptr<DelayedEventBase>> delayed_events_;
841cb0ef41Sopenharmony_ci};
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_citemplate <class T, int64_t (base::TimeDelta::*precision)() const =
871cb0ef41Sopenharmony_ci                       &base::TimeDelta::InMicroseconds>
881cb0ef41Sopenharmony_ciclass V8_NODISCARD TimedScope {
891cb0ef41Sopenharmony_ci public:
901cb0ef41Sopenharmony_ci  explicit TimedScope(T* event) : event_(event) { Start(); }
911cb0ef41Sopenharmony_ci  ~TimedScope() { Stop(); }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  void Start() { start_time_ = base::TimeTicks::Now(); }
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  void Stop() {
961cb0ef41Sopenharmony_ci    if (start_time_.IsMin()) return;
971cb0ef41Sopenharmony_ci    base::TimeDelta duration = base::TimeTicks::Now() - start_time_;
981cb0ef41Sopenharmony_ci    event_->wall_clock_duration_in_us = (duration.*precision)();
991cb0ef41Sopenharmony_ci    start_time_ = base::TimeTicks::Min();
1001cb0ef41Sopenharmony_ci  }
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci private:
1031cb0ef41Sopenharmony_ci  T* event_;
1041cb0ef41Sopenharmony_ci  base::TimeTicks start_time_;
1051cb0ef41Sopenharmony_ci};
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci}  // namespace metrics
1081cb0ef41Sopenharmony_ci}  // namespace internal
1091cb0ef41Sopenharmony_ci}  // namespace v8
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci#endif  // V8_LOGGING_METRICS_H_
112