TracingRuntime.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #ifndef HERMES_TRACINGRUNTIME_H
  8. #define HERMES_TRACINGRUNTIME_H
  9. #ifdef HERMESVM_API_TRACE
  10. #include "SynthTrace.h"
  11. #include <hermes/hermes.h>
  12. #include <jsi/decorator.h>
  13. #include "llvm/Support/raw_ostream.h"
  14. namespace facebook {
  15. namespace hermes {
  16. namespace tracing {
  17. class TracingRuntime : public jsi::RuntimeDecorator<jsi::Runtime> {
  18. public:
  19. using RD = RuntimeDecorator<jsi::Runtime>;
  20. TracingRuntime(
  21. std::unique_ptr<jsi::Runtime> runtime,
  22. uint64_t globalID,
  23. const ::hermes::vm::RuntimeConfig &conf,
  24. std::unique_ptr<llvm::raw_ostream> traceStream);
  25. virtual SynthTrace::ObjectID getUniqueID(const jsi::Object &o) = 0;
  26. virtual void flushAndDisableTrace() = 0;
  27. /// @name jsi::Runtime methods.
  28. /// @{
  29. jsi::Value evaluateJavaScript(
  30. const std::shared_ptr<const jsi::Buffer> &buffer,
  31. const std::string &sourceURL) override;
  32. jsi::Object createObject() override;
  33. jsi::Object createObject(std::shared_ptr<jsi::HostObject> ho) override;
  34. jsi::Value getProperty(const jsi::Object &obj, const jsi::String &name)
  35. override;
  36. jsi::Value getProperty(const jsi::Object &obj, const jsi::PropNameID &name)
  37. override;
  38. bool hasProperty(const jsi::Object &obj, const jsi::String &name) override;
  39. bool hasProperty(const jsi::Object &obj, const jsi::PropNameID &name)
  40. override;
  41. void setPropertyValue(
  42. jsi::Object &obj,
  43. const jsi::String &name,
  44. const jsi::Value &value) override;
  45. void setPropertyValue(
  46. jsi::Object &obj,
  47. const jsi::PropNameID &name,
  48. const jsi::Value &value) override;
  49. jsi::Array getPropertyNames(const jsi::Object &o) override;
  50. jsi::WeakObject createWeakObject(const jsi::Object &o) override;
  51. jsi::Value lockWeakObject(const jsi::WeakObject &wo) override;
  52. jsi::Array createArray(size_t length) override;
  53. size_t size(const jsi::Array &arr) override;
  54. size_t size(const jsi::ArrayBuffer &buf) override;
  55. uint8_t *data(const jsi::ArrayBuffer &buf) override;
  56. jsi::Value getValueAtIndex(const jsi::Array &arr, size_t i) override;
  57. void setValueAtIndexImpl(jsi::Array &arr, size_t i, const jsi::Value &value)
  58. override;
  59. jsi::Function createFunctionFromHostFunction(
  60. const jsi::PropNameID &name,
  61. unsigned int paramCount,
  62. jsi::HostFunctionType func) override;
  63. jsi::Value call(
  64. const jsi::Function &func,
  65. const jsi::Value &jsThis,
  66. const jsi::Value *args,
  67. size_t count) override;
  68. jsi::Value callAsConstructor(
  69. const jsi::Function &func,
  70. const jsi::Value *args,
  71. size_t count) override;
  72. /// @}
  73. void addMarker(const std::string &marker);
  74. SynthTrace &trace() {
  75. return trace_;
  76. }
  77. const SynthTrace &trace() const {
  78. return trace_;
  79. }
  80. private:
  81. SynthTrace::TraceValue toTraceValue(const jsi::Value &value);
  82. std::vector<SynthTrace::TraceValue> argStringifyer(
  83. const jsi::Value *args,
  84. size_t count);
  85. SynthTrace::TimeSinceStart getTimeSinceStart() const;
  86. std::unique_ptr<jsi::Runtime> runtime_;
  87. SynthTrace trace_;
  88. const SynthTrace::TimePoint startTime_{std::chrono::steady_clock::now()};
  89. };
  90. // TracingRuntime is *almost* vm independent. This provides the
  91. // vm-specific bits. And, it's not a HermesRuntime, but it holds one.
  92. class TracingHermesRuntime final : public TracingRuntime {
  93. public:
  94. TracingHermesRuntime(
  95. std::unique_ptr<HermesRuntime> runtime,
  96. const ::hermes::vm::RuntimeConfig &runtimeConfig,
  97. std::unique_ptr<llvm::raw_ostream> traceStream,
  98. const std::string &traceFilename);
  99. ~TracingHermesRuntime();
  100. SynthTrace::ObjectID getUniqueID(const jsi::Object &o) override {
  101. return static_cast<SynthTrace::ObjectID>(hermesRuntime().getUniqueID(o));
  102. }
  103. void flushAndDisableTrace() override;
  104. std::string flushAndDisableBridgeTrafficTrace() override;
  105. jsi::Value evaluateJavaScript(
  106. const std::shared_ptr<const jsi::Buffer> &buffer,
  107. const std::string &sourceURL) override;
  108. HermesRuntime &hermesRuntime() {
  109. return static_cast<HermesRuntime &>(plain());
  110. }
  111. const HermesRuntime &hermesRuntime() const {
  112. return static_cast<const HermesRuntime &>(plain());
  113. }
  114. private:
  115. // Why do we have a private ctor executed from the public one,
  116. // instead of just having a single public ctor which calls
  117. // getUniqueID() to initialize the base class? This one weird trick
  118. // is needed to avoid undefined behavior in that case. Otherwise,
  119. // when calling the base class ctor, the order of evaluating the
  120. // globalID value and the side effect of moving the runtime would be
  121. // unspecified.
  122. TracingHermesRuntime(
  123. std::unique_ptr<HermesRuntime> &runtime,
  124. uint64_t globalID,
  125. const ::hermes::vm::RuntimeConfig &runtimeConfig,
  126. std::unique_ptr<llvm::raw_ostream> traceStream,
  127. const std::string &traceFilename);
  128. void crashCallback(int fd);
  129. const ::hermes::vm::RuntimeConfig conf_;
  130. const std::string traceFilename_;
  131. const llvm::Optional<::hermes::vm::CrashManager::CallbackKey>
  132. crashCallbackKey_;
  133. };
  134. /// Creates and returns a HermesRuntime that traces JSI interactions.
  135. /// If \p traceStream is non-null, writes the trace to \p traceStream.
  136. /// If non-empty, \p traceFilename is the file to which \p traceStream writes.
  137. /// The \p forReplay parameter indicates whether the runtime is being used
  138. /// in trace replay. (Its behavior can differ slightly in that case.)
  139. std::unique_ptr<TracingHermesRuntime> makeTracingHermesRuntime(
  140. std::unique_ptr<HermesRuntime> hermesRuntime,
  141. const ::hermes::vm::RuntimeConfig &runtimeConfig,
  142. std::unique_ptr<llvm::raw_ostream> traceStream = nullptr,
  143. const std::string &traceFilename = "",
  144. bool forReplay = false);
  145. } // namespace tracing
  146. } // namespace hermes
  147. } // namespace facebook
  148. #endif // HERMESVM_API_TRACE
  149. #endif // HERMES_TRACINGRUNTIME_H