forked from facebook/hermes
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTracingRuntime.h
More file actions
243 lines (192 loc) · 8.37 KB
/
TracingRuntime.h
File metadata and controls
243 lines (192 loc) · 8.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#ifndef HERMES_TRACINGRUNTIME_H
#define HERMES_TRACINGRUNTIME_H
#include "SynthTrace.h"
#include <hermes/hermes.h>
#include <jsi/decorator.h>
#include "llvh/Support/raw_ostream.h"
namespace facebook {
namespace hermes {
namespace tracing {
class TracingRuntime : public jsi::RuntimeDecorator<jsi::Runtime> {
public:
using RD = RuntimeDecorator<jsi::Runtime>;
TracingRuntime(
std::unique_ptr<jsi::Runtime> runtime,
uint64_t globalID,
const ::hermes::vm::RuntimeConfig &conf,
std::unique_ptr<llvh::raw_ostream> traceStream);
virtual SynthTrace::ObjectID getUniqueID(const jsi::Object &o) = 0;
virtual SynthTrace::ObjectID getUniqueID(const jsi::String &s) = 0;
virtual SynthTrace::ObjectID getUniqueID(const jsi::PropNameID &pni) = 0;
virtual void flushAndDisableTrace() = 0;
/// @name jsi::Runtime methods.
/// @{
jsi::Value evaluateJavaScript(
const std::shared_ptr<const jsi::Buffer> &buffer,
const std::string &sourceURL) override;
jsi::Object createObject() override;
jsi::Object createObject(std::shared_ptr<jsi::HostObject> ho) override;
jsi::String createStringFromAscii(const char *str, size_t length) override;
jsi::String createStringFromUtf8(const uint8_t *utf8, size_t length) override;
jsi::PropNameID createPropNameIDFromAscii(const char *str, size_t length)
override;
jsi::PropNameID createPropNameIDFromUtf8(const uint8_t *utf8, size_t length)
override;
jsi::PropNameID createPropNameIDFromString(const jsi::String &str) override;
jsi::Value getProperty(const jsi::Object &obj, const jsi::String &name)
override;
jsi::Value getProperty(const jsi::Object &obj, const jsi::PropNameID &name)
override;
bool hasProperty(const jsi::Object &obj, const jsi::String &name) override;
bool hasProperty(const jsi::Object &obj, const jsi::PropNameID &name)
override;
void setPropertyValue(
jsi::Object &obj,
const jsi::String &name,
const jsi::Value &value) override;
void setPropertyValue(
jsi::Object &obj,
const jsi::PropNameID &name,
const jsi::Value &value) override;
jsi::Array getPropertyNames(const jsi::Object &o) override;
jsi::WeakObject createWeakObject(const jsi::Object &o) override;
jsi::Value lockWeakObject(jsi::WeakObject &wo) override;
jsi::Array createArray(size_t length) override;
size_t size(const jsi::Array &arr) override;
size_t size(const jsi::ArrayBuffer &buf) override;
uint8_t *data(const jsi::ArrayBuffer &buf) override;
jsi::Value getValueAtIndex(const jsi::Array &arr, size_t i) override;
void setValueAtIndexImpl(jsi::Array &arr, size_t i, const jsi::Value &value)
override;
jsi::Function createFunctionFromHostFunction(
const jsi::PropNameID &name,
unsigned int paramCount,
jsi::HostFunctionType func) override;
jsi::Value call(
const jsi::Function &func,
const jsi::Value &jsThis,
const jsi::Value *args,
size_t count) override;
jsi::Value callAsConstructor(
const jsi::Function &func,
const jsi::Value *args,
size_t count) override;
/// @}
void addMarker(const std::string &marker);
SynthTrace &trace() {
return trace_;
}
const SynthTrace &trace() const {
return trace_;
}
private:
SynthTrace::TraceValue toTraceValue(const jsi::Value &value);
std::vector<SynthTrace::TraceValue> argStringifyer(
const jsi::Value *args,
size_t count);
SynthTrace::TimeSinceStart getTimeSinceStart() const;
std::unique_ptr<jsi::Runtime> runtime_;
SynthTrace trace_;
const SynthTrace::TimePoint startTime_{std::chrono::steady_clock::now()};
};
// TracingRuntime is *almost* vm independent. This provides the
// vm-specific bits. And, it's not a HermesRuntime, but it holds one.
class TracingHermesRuntime final : public TracingRuntime {
public:
/// This constructor is not intended to be invoked directly.
/// Use makeTracingHermesRuntime instead.
///
/// \p traceStream the stream to write trace to.
/// \p commitAction is invoked on completion of tracing.
/// Completion can be triggered implicitly by crash (if crash manager is
/// provided) or explicitly by invocation of flush. If the committed trace
/// can be found in a file, the callback returns the file name. Otherwise,
/// the callback returns empty.
/// \p rollbackAction is invoked if the runtime is destructed prior to
/// completion of tracing. It may or may not invoked if completion failed.
TracingHermesRuntime(
std::unique_ptr<HermesRuntime> runtime,
const ::hermes::vm::RuntimeConfig &runtimeConfig,
std::unique_ptr<llvh::raw_ostream> traceStream,
std::function<std::string()> commitAction,
std::function<void()> rollbackAction);
~TracingHermesRuntime();
SynthTrace::ObjectID getUniqueID(const jsi::Object &o) override {
return static_cast<SynthTrace::ObjectID>(hermesRuntime().getUniqueID(o));
}
SynthTrace::ObjectID getUniqueID(const jsi::String &s) override {
return static_cast<SynthTrace::ObjectID>(hermesRuntime().getUniqueID(s));
}
SynthTrace::ObjectID getUniqueID(const jsi::PropNameID &pni) override {
return static_cast<SynthTrace::ObjectID>(hermesRuntime().getUniqueID(pni));
}
void flushAndDisableTrace() override;
std::string flushAndDisableBridgeTrafficTrace() override;
jsi::Value evaluateJavaScript(
const std::shared_ptr<const jsi::Buffer> &buffer,
const std::string &sourceURL) override;
HermesRuntime &hermesRuntime() {
return static_cast<HermesRuntime &>(plain());
}
const HermesRuntime &hermesRuntime() const {
return static_cast<const HermesRuntime &>(plain());
}
private:
// Why do we have a private ctor executed from the public one,
// instead of just having a single public ctor which calls
// getUniqueID() to initialize the base class? This one weird trick
// is needed to avoid undefined behavior in that case. Otherwise,
// when calling the base class ctor, the order of evaluating the
// globalID value and the side effect of moving the runtime would be
// unspecified.
TracingHermesRuntime(
std::unique_ptr<HermesRuntime> &runtime,
uint64_t globalID,
const ::hermes::vm::RuntimeConfig &runtimeConfig,
std::unique_ptr<llvh::raw_ostream> traceStream,
std::function<std::string()> commitAction,
std::function<void()> rollbackAction);
void crashCallback(int fd);
const ::hermes::vm::RuntimeConfig conf_;
const std::function<std::string()> commitAction_;
const std::function<void()> rollbackAction_;
const llvh::Optional<::hermes::vm::CrashManager::CallbackKey>
crashCallbackKey_;
bool flushedAndDisabled_{false};
std::string committedTraceFilename_;
};
/// Creates and returns a HermesRuntime that traces JSI interactions.
/// The trace will be written to \p traceScratchPath incrementally.
/// On completion, the file will be renamed to \p traceResultPath, and
/// \p traceCompletionCallback (for post-processing) will be invoked.
/// Completion can be triggered implicitly by crash (if crash manager is
/// provided) or explicitly by invocation of flush.
/// If the runtime is destructed without triggering trace completion,
/// the file at \p traceScratchPath will be deleted.
/// The return value of \p traceCompletionCallback indicates whether the
/// invocation completed successfully.
std::unique_ptr<TracingHermesRuntime> makeTracingHermesRuntime(
std::unique_ptr<HermesRuntime> hermesRuntime,
const ::hermes::vm::RuntimeConfig &runtimeConfig,
const std::string &traceScratchPath,
const std::string &traceResultPath,
std::function<bool()> traceCompletionCallback);
/// Creates and returns a HermesRuntime that traces JSI interactions.
/// If \p traceStream is non-null, writes the trace to \p traceStream.
/// The \p forReplay parameter indicates whether the runtime is being used
/// in trace replay. (Its behavior can differ slightly in that case.)
std::unique_ptr<TracingHermesRuntime> makeTracingHermesRuntime(
std::unique_ptr<HermesRuntime> hermesRuntime,
const ::hermes::vm::RuntimeConfig &runtimeConfig,
std::unique_ptr<llvh::raw_ostream> traceStream,
bool forReplay = false);
} // namespace tracing
} // namespace hermes
} // namespace facebook
#endif // HERMES_TRACINGRUNTIME_H