forked from facebook/hermes
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhermes.cpp
More file actions
230 lines (204 loc) · 8.02 KB
/
hermes.cpp
File metadata and controls
230 lines (204 loc) · 8.02 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
/*
* 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.
*/
#include "hermes/CompilerDriver/CompilerDriver.h"
#include "hermes/ConsoleHost/ConsoleHost.h"
#include "hermes/ConsoleHost/RuntimeFlags.h"
#include "hermes/Support/OSCompat.h"
#include "hermes/Support/PageAccessTracker.h"
#include "llvh/ADT/SmallString.h"
#include "llvh/ADT/SmallVector.h"
#include "llvh/Support/Allocator.h"
#include "llvh/Support/CommandLine.h"
#include "llvh/Support/FileSystem.h"
#include "llvh/Support/InitLLVM.h"
#include "llvh/Support/PrettyStackTrace.h"
#include "llvh/Support/Program.h"
#include "llvh/Support/SHA1.h"
#include "llvh/Support/Signals.h"
#include "repl.h"
using namespace hermes;
namespace cl {
using llvh::cl::opt;
static opt<bool> EnableJIT(
"jit",
llvh::cl::desc("enable JIT compilation"),
llvh::cl::init(false));
static opt<bool> DumpJITCode(
"dump-jitcode",
llvh::cl::desc("dump JIT'ed code"),
llvh::cl::init(false));
static opt<bool> JITCrashOnError(
"jit-crash-on-error",
llvh::cl::desc("crash on any JIT compilation error"),
llvh::cl::init(false));
static opt<unsigned> Repeat(
"Xrepeat",
llvh::cl::desc("Repeat execution N number of times"),
llvh::cl::init(1),
llvh::cl::Hidden);
static opt<bool> RandomizeMemoryLayout(
"Xrandomize-memory-layout",
llvh::cl::desc("Randomize stack placement etc."),
llvh::cl::init(false),
llvh::cl::Hidden);
static opt<bool> GCAllocYoung(
"gc-alloc-young",
desc("Determines whether to (initially) allocate in the young generation"),
cat(GCCategory),
init(true));
static opt<bool> GCRevertToYGAtTTI(
"gc-revert-to-yg-at-tti",
desc("Determines whether to revert to young generation, if necessary, at "
"TTI notification"),
cat(GCCategory),
init(false));
static opt<bool> GCBeforeStats(
"gc-before-stats",
desc("Perform a full GC just before printing statistics at exit"),
cat(GCCategory),
init(false));
static opt<bool> GCPrintStats(
"gc-print-stats",
desc("Output summary garbage collection statistics at exit"),
cat(GCCategory),
init(false));
static opt<unsigned> ExecutionTimeLimit(
"time-limit",
llvh::cl::desc("Number of milliseconds after which to abort JS exeuction"),
llvh::cl::init(0));
} // namespace cl
/// Execute Hermes bytecode \p bytecode, respecting command line arguments.
/// \return an exit status.
static int executeHBCBytecodeFromCL(
std::unique_ptr<hbc::BCProvider> bytecode,
const driver::BytecodeBufferInfo &info) {
auto recStats =
(cl::GCPrintStats || cl::GCBeforeStats) && !cl::StableInstructionCount;
ExecuteOptions options;
options.runtimeConfig =
vm::RuntimeConfig::Builder()
.withGCConfig(
vm::GCConfig::Builder()
.withMinHeapSize(cl::MinHeapSize.bytes)
.withInitHeapSize(cl::InitHeapSize.bytes)
.withMaxHeapSize(cl::MaxHeapSize.bytes)
.withOccupancyTarget(cl::OccupancyTarget)
.withSanitizeConfig(
vm::GCSanitizeConfig::Builder()
.withSanitizeRate(cl::GCSanitizeRate)
.withRandomSeed(cl::GCSanitizeRandomSeed)
.build())
.withShouldRandomizeAllocSpace(cl::GCRandomizeAllocSpace)
.withShouldRecordStats(recStats)
.withShouldReleaseUnused(vm::kReleaseUnusedNone)
.withAllocInYoung(cl::GCAllocYoung)
.withRevertToYGAtTTI(cl::GCRevertToYGAtTTI)
.build())
.withEnableJIT(cl::DumpJITCode || cl::EnableJIT)
.withEnableEval(cl::EnableEval)
.withVerifyEvalIR(cl::VerifyIR)
.withOptimizedEval(cl::OptimizedEval)
.withVMExperimentFlags(cl::VMExperimentFlags)
.withES6Proxy(cl::ES6Proxy)
.withES6Symbol(cl::ES6Symbol)
.withEnableSampleProfiling(cl::SampleProfiling)
.withRandomizeMemoryLayout(cl::RandomizeMemoryLayout)
.withTrackIO(cl::TrackBytecodeIO)
.withEnableHermesInternal(cl::EnableHermesInternal)
.withEnableHermesInternalTestMethods(
cl::EnableHermesInternalTestMethods)
.withAllowFunctionToStringWithRuntimeSource(cl::AllowFunctionToString)
.build();
options.basicBlockProfiling = cl::BasicBlockProfiling;
options.stopAfterInit = false;
#ifdef HERMESVM_PROFILER_EXTERN
options.patchProfilerSymbols = cl::PatchProfilerSymbols;
options.profilerSymbolsFile = cl::ProfilerSymbolsFile;
#endif
options.timeLimit = cl::ExecutionTimeLimit;
options.dumpJITCode = cl::DumpJITCode;
options.jitCrashOnError = cl::JITCrashOnError;
options.stopAfterInit = cl::StopAfterInit;
options.forceGCBeforeStats = cl::GCBeforeStats;
options.stabilizeInstructionCount = cl::StableInstructionCount;
#ifdef HERMESVM_SERIALIZE
options.SerializeAfterInitFile = cl::SerializeAfterInitFile;
options.DeserializeFile = cl::DeserializeFile;
options.SerializeVMPath = cl::SerializeVMPath;
#endif
bool success;
if (cl::Repeat <= 1) {
success = executeHBCBytecode(std::move(bytecode), options, &info.filename);
} else {
// The runtime is supposed to own the bytecode exclusively, but we
// want to keep it around in this special case, so we can reuse it
// between iterations.
std::shared_ptr<hbc::BCProvider> sharedBytecode = std::move(bytecode);
success = true;
for (unsigned i = 0; i < cl::Repeat; ++i) {
success &= executeHBCBytecode(
std::shared_ptr<hbc::BCProvider>{sharedBytecode},
options,
&info.filename);
}
}
return success ? EXIT_SUCCESS : EXIT_FAILURE;
}
static vm::RuntimeConfig getReplRuntimeConfig() {
return vm::RuntimeConfig::Builder()
.withGCConfig(
vm::GCConfig::Builder()
.withInitHeapSize(cl::InitHeapSize.bytes)
.withMaxHeapSize(cl::MaxHeapSize.bytes)
.withSanitizeConfig(vm::GCSanitizeConfig::Builder()
.withSanitizeRate(cl::GCSanitizeRate)
.withRandomSeed(cl::GCSanitizeRandomSeed)
.build())
.withShouldRecordStats(cl::GCPrintStats)
.build())
.withES6Proxy(cl::ES6Proxy)
.withES6Symbol(cl::ES6Symbol)
.withEnableHermesInternal(true)
.withEnableHermesInternalTestMethods(true)
.withAllowFunctionToStringWithRuntimeSource(cl::AllowFunctionToString)
.build();
}
int main(int argc, char **argv) {
#ifndef HERMES_FBCODE_BUILD
// Normalize the arg vector.
llvh::InitLLVM initLLVM(argc, argv);
#else
// When both HERMES_FBCODE_BUILD and sanitizers are enabled, InitLLVM may have
// been already created and destroyed before main() is invoked. This presents
// a problem because InitLLVM can't be instantiated more than once in the same
// process. The most important functionality InitLLVM provides is shutting
// down LLVM in its destructor. We can use "llvm_shutdown_obj" to do the same.
llvh::llvm_shutdown_obj Y;
#endif
llvh::cl::AddExtraVersionPrinter(driver::printHermesCompilerVMVersion);
llvh::cl::ParseCommandLineOptions(argc, argv, "Hermes driver\n");
if (cl::InputFilenames.size() == 0) {
return repl(getReplRuntimeConfig());
}
// Tell compiler to emit async break check if time-limit feature is enabled
// so that user can turn on this feature with single ExecutionTimeLimit
// option.
if (cl::ExecutionTimeLimit > 0) {
cl::EmitAsyncBreakCheck = true;
}
// Make sure any allocated alt signal stack is not considered a leak
// by ASAN.
oscompat::SigAltStackLeakSuppressor sigAltLeakSuppressor;
driver::CompileResult res = driver::compileFromCommandLineOptions();
if (res.bytecodeProvider) {
auto ret = executeHBCBytecodeFromCL(
std::move(res.bytecodeProvider), res.bytecodeBufferInfo);
return ret;
} else {
return res.status;
}
}