Try ripping out inferred types because it might be a performance improvement
[WebKit-https.git] / Source / JavaScriptCore / jsc.cpp
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2004-2018 Apple Inc. All rights reserved.
4  *  Copyright (C) 2006 Bjoern Graf (bjoern.graf@gmail.com)
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Library General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Library General Public License
17  *  along with this library; see the file COPYING.LIB.  If not, write to
18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #include "config.h"
24
25 #include "ArrayBuffer.h"
26 #include "ArrayPrototype.h"
27 #include "BuiltinNames.h"
28 #include "ButterflyInlines.h"
29 #include "CatchScope.h"
30 #include "CodeBlock.h"
31 #include "Completion.h"
32 #include "ConfigFile.h"
33 #include "Disassembler.h"
34 #include "Exception.h"
35 #include "ExceptionHelpers.h"
36 #include "HeapProfiler.h"
37 #include "HeapSnapshotBuilder.h"
38 #include "InitializeThreading.h"
39 #include "Interpreter.h"
40 #include "JIT.h"
41 #include "JSArray.h"
42 #include "JSArrayBuffer.h"
43 #include "JSBigInt.h"
44 #include "JSCInlines.h"
45 #include "JSFunction.h"
46 #include "JSInternalPromise.h"
47 #include "JSInternalPromiseDeferred.h"
48 #include "JSLock.h"
49 #include "JSModuleLoader.h"
50 #include "JSNativeStdFunction.h"
51 #include "JSONObject.h"
52 #include "JSSourceCode.h"
53 #include "JSString.h"
54 #include "JSTypedArrays.h"
55 #include "JSWebAssemblyInstance.h"
56 #include "JSWebAssemblyMemory.h"
57 #include "LLIntThunks.h"
58 #include "ObjectConstructor.h"
59 #include "ParserError.h"
60 #include "ProfilerDatabase.h"
61 #include "PromiseDeferredTimer.h"
62 #include "ProtoCallFrame.h"
63 #include "ReleaseHeapAccessScope.h"
64 #include "SamplingProfiler.h"
65 #include "StackVisitor.h"
66 #include "StructureInlines.h"
67 #include "StructureRareDataInlines.h"
68 #include "SuperSampler.h"
69 #include "TestRunnerUtils.h"
70 #include "TypedArrayInlines.h"
71 #include "WasmContext.h"
72 #include "WasmFaultSignalHandler.h"
73 #include "WasmMemory.h"
74 #include <locale.h>
75 #include <math.h>
76 #include <stdio.h>
77 #include <stdlib.h>
78 #include <string.h>
79 #include <sys/stat.h>
80 #include <sys/types.h>
81 #include <thread>
82 #include <type_traits>
83 #include <wtf/Box.h>
84 #include <wtf/CommaPrinter.h>
85 #include <wtf/MainThread.h>
86 #include <wtf/MemoryPressureHandler.h>
87 #include <wtf/MonotonicTime.h>
88 #include <wtf/NeverDestroyed.h>
89 #include <wtf/StringPrintStream.h>
90 #include <wtf/URL.h>
91 #include <wtf/WallTime.h>
92 #include <wtf/text/StringBuilder.h>
93
94 #if OS(WINDOWS)
95 #include <direct.h>
96 #include <fcntl.h>
97 #include <io.h>
98 #include <wtf/text/win/WCharStringExtras.h>
99 #else
100 #include <unistd.h>
101 #endif
102
103 #if PLATFORM(COCOA)
104 #include <crt_externs.h>
105 #endif
106
107 #if HAVE(READLINE)
108 // readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
109 // We #define it to something else to avoid this conflict.
110 #define Function ReadlineFunction
111 #include <readline/history.h>
112 #include <readline/readline.h>
113 #undef Function
114 #endif
115
116 #if HAVE(SYS_TIME_H)
117 #include <sys/time.h>
118 #endif
119
120 #if HAVE(SIGNAL_H)
121 #include <signal.h>
122 #endif
123
124 #if COMPILER(MSVC)
125 #include <crtdbg.h>
126 #include <mmsystem.h>
127 #include <windows.h>
128 #endif
129
130 #if PLATFORM(IOS_FAMILY) && CPU(ARM_THUMB2)
131 #include <fenv.h>
132 #include <arm/arch.h>
133 #endif
134
135 #if __has_include(<WebKitAdditions/MemoryFootprint.h>)
136 #include <WebKitAdditions/MemoryFootprint.h>
137 #else
138 struct MemoryFootprint {
139     uint64_t current;
140     uint64_t peak;
141     
142     static MemoryFootprint now()
143     {
144         return { 0L, 0L };
145     }
146     
147     static void resetPeak()
148     {
149     }
150 };
151 #endif
152
153 #if !defined(PATH_MAX)
154 #define PATH_MAX 4096
155 #endif
156
157 using namespace JSC;
158 using namespace WTF;
159
160 namespace {
161
162 NO_RETURN_WITH_VALUE static void jscExit(int status)
163 {
164     waitForAsynchronousDisassembly();
165     
166 #if ENABLE(DFG_JIT)
167     if (DFG::isCrashing()) {
168         for (;;) {
169 #if OS(WINDOWS)
170             Sleep(1000);
171 #else
172             pause();
173 #endif
174         }
175     }
176 #endif // ENABLE(DFG_JIT)
177     exit(status);
178 }
179
180 class Masquerader : public JSNonFinalObject {
181 public:
182     Masquerader(VM& vm, Structure* structure)
183         : Base(vm, structure)
184     {
185     }
186
187     typedef JSNonFinalObject Base;
188     static const unsigned StructureFlags = Base::StructureFlags | JSC::MasqueradesAsUndefined;
189
190     static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
191     {
192         globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(vm, "Masquerading object allocated");
193         Structure* structure = createStructure(vm, globalObject, jsNull());
194         Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
195         result->finishCreation(vm);
196         return result;
197     }
198
199     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
200     {
201         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
202     }
203
204     DECLARE_INFO;
205 };
206
207 const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(Masquerader) };
208 static unsigned asyncTestPasses { 0 };
209 static unsigned asyncTestExpectedPasses { 0 };
210
211 }
212
213 template<typename Vector>
214 static bool fillBufferWithContentsOfFile(const String& fileName, Vector& buffer);
215 static RefPtr<Uint8Array> fillBufferWithContentsOfFile(const String& fileName);
216
217 class CommandLine;
218 class GlobalObject;
219 class Workers;
220
221 template<typename Func>
222 int runJSC(const CommandLine&, bool isWorker, const Func&);
223 static void checkException(ExecState*, GlobalObject*, bool isLastFile, bool hasException, JSValue, CommandLine&, bool& success);
224
225 class Message : public ThreadSafeRefCounted<Message> {
226 public:
227     Message(ArrayBufferContents&&, int32_t);
228     ~Message();
229     
230     ArrayBufferContents&& releaseContents() { return WTFMove(m_contents); }
231     int32_t index() const { return m_index; }
232
233 private:
234     ArrayBufferContents m_contents;
235     int32_t m_index { 0 };
236 };
237
238 class Worker : public BasicRawSentinelNode<Worker> {
239 public:
240     Worker(Workers&);
241     ~Worker();
242     
243     void enqueue(const AbstractLocker&, RefPtr<Message>);
244     RefPtr<Message> dequeue();
245     
246     static Worker& current();
247
248 private:
249     static ThreadSpecific<Worker*>& currentWorker();
250
251     Workers& m_workers;
252     Deque<RefPtr<Message>> m_messages;
253 };
254
255 class Workers {
256 public:
257     Workers();
258     ~Workers();
259     
260     template<typename Func>
261     void broadcast(const Func&);
262     
263     void report(const String&);
264     String tryGetReport();
265     String getReport();
266     
267     static Workers& singleton();
268     
269 private:
270     friend class Worker;
271     
272     Lock m_lock;
273     Condition m_condition;
274     SentinelLinkedList<Worker, BasicRawSentinelNode<Worker>> m_workers;
275     Deque<String> m_reports;
276 };
277
278
279 static EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState*);
280
281 static EncodedJSValue JSC_HOST_CALL functionPrintStdOut(ExecState*);
282 static EncodedJSValue JSC_HOST_CALL functionPrintStdErr(ExecState*);
283 static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
284 static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
285 static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
286 static EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState*);
287 static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
288 static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
289 static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
290 static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
291 static EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*);
292 static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
293 static EncodedJSValue JSC_HOST_CALL functionCreateMemoryFootprint(ExecState*);
294 static EncodedJSValue JSC_HOST_CALL functionResetMemoryPeak(ExecState*);
295 static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
296 static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
297 static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
298 static EncodedJSValue JSC_HOST_CALL functionRunString(ExecState*);
299 static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
300 static EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState*);
301 static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*);
302 static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
303 static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
304 static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
305 static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*);
306 static EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState*);
307 static EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState*);
308 static EncodedJSValue JSC_HOST_CALL functionNoOSRExitFuzzing(ExecState*);
309 static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
310 static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
311 static EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState*);
312 static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
313 static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
314 static EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState*);
315 static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
316 static EncodedJSValue JSC_HOST_CALL functionFalse(ExecState*);
317 static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
318 static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
319 static EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState*);
320 static EncodedJSValue JSC_HOST_CALL functionIsPureNaN(ExecState*);
321 static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
322 static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
323 static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
324 static EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState*);
325 static EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState*);
326 static EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState*);
327 static EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*);
328 static EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState*);
329 static EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*);
330 static EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState*);
331 static EncodedJSValue JSC_HOST_CALL functionResetSuperSamplerState(ExecState*);
332 static EncodedJSValue JSC_HOST_CALL functionEnsureArrayStorage(ExecState*);
333 #if ENABLE(SAMPLING_PROFILER)
334 static EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState*);
335 static EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState*);
336 #endif
337
338 static EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*);
339 static EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState*);
340 static EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*);
341
342 #if ENABLE(WEBASSEMBLY)
343 static EncodedJSValue JSC_HOST_CALL functionWebAssemblyMemoryMode(ExecState*);
344 #endif
345
346 #if ENABLE(SAMPLING_FLAGS)
347 static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
348 static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
349 #endif
350
351 static EncodedJSValue JSC_HOST_CALL functionGetRandomSeed(ExecState*);
352 static EncodedJSValue JSC_HOST_CALL functionSetRandomSeed(ExecState*);
353 static EncodedJSValue JSC_HOST_CALL functionIsRope(ExecState*);
354 static EncodedJSValue JSC_HOST_CALL functionCallerSourceOrigin(ExecState*);
355 static EncodedJSValue JSC_HOST_CALL functionDollarCreateRealm(ExecState*);
356 static EncodedJSValue JSC_HOST_CALL functionDollarDetachArrayBuffer(ExecState*);
357 static EncodedJSValue JSC_HOST_CALL functionDollarEvalScript(ExecState*);
358 static EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState*);
359 static EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState*);
360 static EncodedJSValue JSC_HOST_CALL functionDollarAgentReport(ExecState*);
361 static EncodedJSValue JSC_HOST_CALL functionDollarAgentSleep(ExecState*);
362 static EncodedJSValue JSC_HOST_CALL functionDollarAgentBroadcast(ExecState*);
363 static EncodedJSValue JSC_HOST_CALL functionDollarAgentGetReport(ExecState*);
364 static EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*);
365 static EncodedJSValue JSC_HOST_CALL functionDollarAgentMonotonicNow(ExecState*);
366 static EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState*);
367 static EncodedJSValue JSC_HOST_CALL functionHeapCapacity(ExecState*);
368 static EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState*);
369 static EncodedJSValue JSC_HOST_CALL functionDisableRichSourceInfo(ExecState*);
370 static EncodedJSValue JSC_HOST_CALL functionMallocInALoop(ExecState*);
371 static EncodedJSValue JSC_HOST_CALL functionTotalCompileTime(ExecState*);
372
373 struct Script {
374     enum class StrictMode {
375         Strict,
376         Sloppy
377     };
378
379     enum class ScriptType {
380         Script,
381         Module
382     };
383
384     enum class CodeSource {
385         File,
386         CommandLine
387     };
388
389     StrictMode strictMode;
390     CodeSource codeSource;
391     ScriptType scriptType;
392     char* argument;
393
394     Script(StrictMode strictMode, CodeSource codeSource, ScriptType scriptType, char *argument)
395         : strictMode(strictMode)
396         , codeSource(codeSource)
397         , scriptType(scriptType)
398         , argument(argument)
399     {
400         if (strictMode == StrictMode::Strict)
401             ASSERT(codeSource == CodeSource::File);
402     }
403 };
404
405 class CommandLine {
406 public:
407     CommandLine(int argc, char** argv)
408     {
409         parseArguments(argc, argv);
410     }
411
412     bool m_interactive { false };
413     bool m_dump { false };
414     bool m_module { false };
415     bool m_exitCode { false };
416     Vector<Script> m_scripts;
417     Vector<String> m_arguments;
418     bool m_profile { false };
419     String m_profilerOutput;
420     String m_uncaughtExceptionName;
421     bool m_treatWatchdogExceptionAsSuccess { false };
422     bool m_alwaysDumpUncaughtException { false };
423     bool m_dumpMemoryFootprint { false };
424     bool m_dumpSamplingProfilerData { false };
425     bool m_enableRemoteDebugging { false };
426
427     void parseArguments(int, char**);
428 };
429
430 static const char interactivePrompt[] = ">>> ";
431
432 class StopWatch {
433 public:
434     void start();
435     void stop();
436     long getElapsedMS(); // call stop() first
437
438 private:
439     MonotonicTime m_startTime;
440     MonotonicTime m_stopTime;
441 };
442
443 void StopWatch::start()
444 {
445     m_startTime = MonotonicTime::now();
446 }
447
448 void StopWatch::stop()
449 {
450     m_stopTime = MonotonicTime::now();
451 }
452
453 long StopWatch::getElapsedMS()
454 {
455     return (m_stopTime - m_startTime).millisecondsAs<long>();
456 }
457
458 template<typename Vector>
459 static inline String stringFromUTF(const Vector& utf8)
460 {
461     return String::fromUTF8WithLatin1Fallback(utf8.data(), utf8.size());
462 }
463
464 class GlobalObject : public JSGlobalObject {
465 private:
466     GlobalObject(VM&, Structure*);
467
468 public:
469     typedef JSGlobalObject Base;
470
471     static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
472     {
473         GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
474         object->finishCreation(vm, arguments);
475         return object;
476     }
477
478     static const bool needsDestruction = false;
479
480     DECLARE_INFO;
481     static const GlobalObjectMethodTable s_globalObjectMethodTable;
482
483     static Structure* createStructure(VM& vm, JSValue prototype)
484     {
485         return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
486     }
487
488     static RuntimeFlags javaScriptRuntimeFlags(const JSGlobalObject*) { return RuntimeFlags::createAllEnabled(); }
489
490 protected:
491     void finishCreation(VM& vm, const Vector<String>& arguments)
492     {
493         Base::finishCreation(vm);
494
495         addFunction(vm, "debug", functionDebug, 1);
496         addFunction(vm, "describe", functionDescribe, 1);
497         addFunction(vm, "describeArray", functionDescribeArray, 1);
498         addFunction(vm, "print", functionPrintStdOut, 1);
499         addFunction(vm, "printErr", functionPrintStdErr, 1);
500         addFunction(vm, "quit", functionQuit, 0);
501         addFunction(vm, "gc", functionGCAndSweep, 0);
502         addFunction(vm, "fullGC", functionFullGC, 0);
503         addFunction(vm, "edenGC", functionEdenGC, 0);
504         addFunction(vm, "forceGCSlowPaths", functionForceGCSlowPaths, 0);
505         addFunction(vm, "gcHeapSize", functionHeapSize, 0);
506         addFunction(vm, "MemoryFootprint", functionCreateMemoryFootprint, 0);
507         addFunction(vm, "resetMemoryPeak", functionResetMemoryPeak, 0);
508         addFunction(vm, "addressOf", functionAddressOf, 1);
509         addFunction(vm, "version", functionVersion, 1);
510         addFunction(vm, "run", functionRun, 1);
511         addFunction(vm, "runString", functionRunString, 1);
512         addFunction(vm, "load", functionLoad, 1);
513         addFunction(vm, "loadString", functionLoadString, 1);
514         addFunction(vm, "readFile", functionReadFile, 2);
515         addFunction(vm, "read", functionReadFile, 2);
516         addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
517         addFunction(vm, "sleepSeconds", functionSleepSeconds, 1);
518         addFunction(vm, "jscStack", functionJSCStack, 1);
519         addFunction(vm, "readline", functionReadline, 0);
520         addFunction(vm, "preciseTime", functionPreciseTime, 0);
521         addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
522         addFunction(vm, "noInline", functionNeverInlineFunction, 1);
523         addFunction(vm, "noDFG", functionNoDFG, 1);
524         addFunction(vm, "noFTL", functionNoFTL, 1);
525         addFunction(vm, "noOSRExitFuzzing", functionNoOSRExitFuzzing, 1);
526         addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
527         addFunction(vm, "jscOptions", functionJSCOptions, 0);
528         addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
529         addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
530         addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
531         addFunction(vm, "failNextNewCodeBlock", functionFailNextNewCodeBlock, 1);
532 #if ENABLE(SAMPLING_FLAGS)
533         addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
534         addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
535 #endif
536
537         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
538         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isFinalTier"), 0, functionFalse, IsFinalTierIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
539         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
540         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isInt32"), 0, functionIsInt32, CheckInt32Intrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
541         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isPureNaN"), 0, functionIsPureNaN, CheckInt32Intrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
542         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
543         
544         addFunction(vm, "effectful42", functionEffectful42, 0);
545         addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
546         addFunction(vm, "hasCustomProperties", functionHasCustomProperties, 0);
547
548         addFunction(vm, "createGlobalObject", functionCreateGlobalObject, 0);
549
550         addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 0);
551
552         addFunction(vm, "drainMicrotasks", functionDrainMicrotasks, 0);
553
554         addFunction(vm, "getRandomSeed", functionGetRandomSeed, 0);
555         addFunction(vm, "setRandomSeed", functionSetRandomSeed, 1);
556         addFunction(vm, "isRope", functionIsRope, 1);
557         addFunction(vm, "callerSourceOrigin", functionCallerSourceOrigin, 0);
558
559         addFunction(vm, "is32BitPlatform", functionIs32BitPlatform, 0);
560
561         addFunction(vm, "checkModuleSyntax", functionCheckModuleSyntax, 1);
562
563         addFunction(vm, "platformSupportsSamplingProfiler", functionPlatformSupportsSamplingProfiler, 0);
564         addFunction(vm, "generateHeapSnapshot", functionGenerateHeapSnapshot, 0);
565         addFunction(vm, "resetSuperSamplerState", functionResetSuperSamplerState, 0);
566         addFunction(vm, "ensureArrayStorage", functionEnsureArrayStorage, 0);
567 #if ENABLE(SAMPLING_PROFILER)
568         addFunction(vm, "startSamplingProfiler", functionStartSamplingProfiler, 0);
569         addFunction(vm, "samplingProfilerStackTraces", functionSamplingProfilerStackTraces, 0);
570 #endif
571
572         addFunction(vm, "maxArguments", functionMaxArguments, 0);
573
574         addFunction(vm, "asyncTestStart", functionAsyncTestStart, 1);
575         addFunction(vm, "asyncTestPassed", functionAsyncTestPassed, 1);
576
577 #if ENABLE(WEBASSEMBLY)
578         addFunction(vm, "WebAssemblyMemoryMode", functionWebAssemblyMemoryMode, 1);
579 #endif
580
581         if (!arguments.isEmpty()) {
582             JSArray* array = constructEmptyArray(globalExec(), 0);
583             for (size_t i = 0; i < arguments.size(); ++i)
584                 array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
585             putDirect(vm, Identifier::fromString(globalExec(), "arguments"), array);
586         }
587
588         putDirect(vm, Identifier::fromString(globalExec(), "console"), jsUndefined());
589         
590         Structure* plainObjectStructure = JSFinalObject::createStructure(vm, this, objectPrototype(), 0);
591         
592         JSObject* dollar = JSFinalObject::create(vm, plainObjectStructure);
593         putDirect(vm, Identifier::fromString(globalExec(), "$"), dollar);
594         putDirect(vm, Identifier::fromString(globalExec(), "$262"), dollar);
595         
596         addFunction(vm, dollar, "createRealm", functionDollarCreateRealm, 0);
597         addFunction(vm, dollar, "detachArrayBuffer", functionDollarDetachArrayBuffer, 1);
598         addFunction(vm, dollar, "evalScript", functionDollarEvalScript, 1);
599         
600         dollar->putDirect(vm, Identifier::fromString(globalExec(), "global"), this);
601         
602         JSObject* agent = JSFinalObject::create(vm, plainObjectStructure);
603         dollar->putDirect(vm, Identifier::fromString(globalExec(), "agent"), agent);
604         
605         // The test262 INTERPRETING.md document says that some of these functions are just in the main
606         // thread and some are in the other threads. We just put them in all threads.
607         addFunction(vm, agent, "start", functionDollarAgentStart, 1);
608         addFunction(vm, agent, "receiveBroadcast", functionDollarAgentReceiveBroadcast, 1);
609         addFunction(vm, agent, "report", functionDollarAgentReport, 1);
610         addFunction(vm, agent, "sleep", functionDollarAgentSleep, 1);
611         addFunction(vm, agent, "broadcast", functionDollarAgentBroadcast, 1);
612         addFunction(vm, agent, "getReport", functionDollarAgentGetReport, 0);
613         addFunction(vm, agent, "leaving", functionDollarAgentLeaving, 0);
614         addFunction(vm, agent, "monotonicNow", functionDollarAgentMonotonicNow, 0);
615
616         addFunction(vm, "waitForReport", functionWaitForReport, 0);
617
618         addFunction(vm, "heapCapacity", functionHeapCapacity, 0);
619         addFunction(vm, "flashHeapAccess", functionFlashHeapAccess, 0);
620
621         addFunction(vm, "disableRichSourceInfo", functionDisableRichSourceInfo, 0);
622         addFunction(vm, "mallocInALoop", functionMallocInALoop, 0);
623         addFunction(vm, "totalCompileTime", functionTotalCompileTime, 0);
624     }
625     
626     void addFunction(VM& vm, JSObject* object, const char* name, NativeFunction function, unsigned arguments)
627     {
628         Identifier identifier = Identifier::fromString(&vm, name);
629         object->putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
630     }
631
632     void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
633     {
634         addFunction(vm, this, name, function, arguments);
635     }
636     
637     static JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, ExecState*, JSModuleLoader*, JSString*, JSValue, const SourceOrigin&);
638     static Identifier moduleLoaderResolve(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
639     static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
640     static JSObject* moduleLoaderCreateImportMetaProperties(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSModuleRecord*, JSValue);
641 };
642
643 static bool supportsRichSourceInfo = true;
644 static bool shellSupportsRichSourceInfo(const JSGlobalObject*)
645 {
646     return supportsRichSourceInfo;
647 }
648
649 const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
650 const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = {
651     &shellSupportsRichSourceInfo,
652     &shouldInterruptScript,
653     &javaScriptRuntimeFlags,
654     nullptr, // queueTaskToEventLoop
655     &shouldInterruptScriptBeforeTimeout,
656     &moduleLoaderImportModule,
657     &moduleLoaderResolve,
658     &moduleLoaderFetch,
659     &moduleLoaderCreateImportMetaProperties,
660     nullptr, // moduleLoaderEvaluate
661     nullptr, // promiseRejectionTracker
662     nullptr, // defaultLanguage
663     nullptr, // compileStreaming
664     nullptr, // instantinateStreaming
665 };
666
667 GlobalObject::GlobalObject(VM& vm, Structure* structure)
668     : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
669 {
670 }
671
672 static UChar pathSeparator()
673 {
674 #if OS(WINDOWS)
675     return '\\';
676 #else
677     return '/';
678 #endif
679 }
680
681 struct DirectoryName {
682     // In unix, it is "/". In Windows, it becomes a drive letter like "C:\"
683     String rootName;
684
685     // If the directory name is "/home/WebKit", this becomes "home/WebKit". If the directory name is "/", this becomes "".
686     String queryName;
687 };
688
689 struct ModuleName {
690     ModuleName(const String& moduleName);
691
692     bool startsWithRoot() const
693     {
694         return !queries.isEmpty() && queries[0].isEmpty();
695     }
696
697     Vector<String> queries;
698 };
699
700 ModuleName::ModuleName(const String& moduleName)
701 {
702     // A module name given from code is represented as the UNIX style path. Like, `./A/B.js`.
703     queries = moduleName.splitAllowingEmptyEntries('/');
704 }
705
706 static Optional<DirectoryName> extractDirectoryName(const String& absolutePathToFile)
707 {
708     size_t firstSeparatorPosition = absolutePathToFile.find(pathSeparator());
709     if (firstSeparatorPosition == notFound)
710         return WTF::nullopt;
711     DirectoryName directoryName;
712     directoryName.rootName = absolutePathToFile.substring(0, firstSeparatorPosition + 1); // Include the separator.
713     size_t lastSeparatorPosition = absolutePathToFile.reverseFind(pathSeparator());
714     ASSERT_WITH_MESSAGE(lastSeparatorPosition != notFound, "If the separator is not found, this function already returns when performing the forward search.");
715     if (firstSeparatorPosition == lastSeparatorPosition)
716         directoryName.queryName = StringImpl::empty();
717     else {
718         size_t queryStartPosition = firstSeparatorPosition + 1;
719         size_t queryLength = lastSeparatorPosition - queryStartPosition; // Not include the last separator.
720         directoryName.queryName = absolutePathToFile.substring(queryStartPosition, queryLength);
721     }
722     return directoryName;
723 }
724
725 static Optional<DirectoryName> currentWorkingDirectory()
726 {
727 #if OS(WINDOWS)
728     // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364934.aspx
729     // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
730     // The _MAX_PATH in Windows is 260. If the path of the current working directory is longer than that, _getcwd truncates the result.
731     // And other I/O functions taking a path name also truncate it. To avoid this situation,
732     //
733     // (1). When opening the file in Windows for modules, we always use the abosolute path and add "\\?\" prefix to the path name.
734     // (2). When retrieving the current working directory, use GetCurrentDirectory instead of _getcwd.
735     //
736     // In the path utility functions inside the JSC shell, we does not handle the UNC and UNCW including the network host name.
737     DWORD bufferLength = ::GetCurrentDirectoryW(0, nullptr);
738     if (!bufferLength)
739         return WTF::nullopt;
740     // In Windows, wchar_t is the UTF-16LE.
741     // https://msdn.microsoft.com/en-us/library/dd374081.aspx
742     // https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407.aspx
743     Vector<wchar_t> buffer(bufferLength);
744     DWORD lengthNotIncludingNull = ::GetCurrentDirectoryW(bufferLength, buffer.data());
745     String directoryString = wcharToString(buffer.data(), lengthNotIncludingNull);
746     // We don't support network path like \\host\share\<path name>.
747     if (directoryString.startsWith("\\\\"))
748         return WTF::nullopt;
749 #else
750     Vector<char> buffer(PATH_MAX);
751     if (!getcwd(buffer.data(), PATH_MAX))
752         return WTF::nullopt;
753     String directoryString = String::fromUTF8(buffer.data());
754 #endif
755     if (directoryString.isEmpty())
756         return WTF::nullopt;
757
758     if (directoryString[directoryString.length() - 1] == pathSeparator())
759         return extractDirectoryName(directoryString);
760     // Append the seperator to represents the file name. extractDirectoryName only accepts the absolute file name.
761     return extractDirectoryName(makeString(directoryString, pathSeparator()));
762 }
763
764 static String resolvePath(const DirectoryName& directoryName, const ModuleName& moduleName)
765 {
766     Vector<String> directoryPieces = directoryName.queryName.split(pathSeparator());
767
768     // Only first '/' is recognized as the path from the root.
769     if (moduleName.startsWithRoot())
770         directoryPieces.clear();
771
772     for (const auto& query : moduleName.queries) {
773         if (query == String(".."_s)) {
774             if (!directoryPieces.isEmpty())
775                 directoryPieces.removeLast();
776         } else if (!query.isEmpty() && query != String("."_s))
777             directoryPieces.append(query);
778     }
779
780     StringBuilder builder;
781     builder.append(directoryName.rootName);
782     for (size_t i = 0; i < directoryPieces.size(); ++i) {
783         builder.append(directoryPieces[i]);
784         if (i + 1 != directoryPieces.size())
785             builder.append(pathSeparator());
786     }
787     return builder.toString();
788 }
789
790 static String absolutePath(const String& fileName)
791 {
792     auto directoryName = currentWorkingDirectory();
793     if (!directoryName)
794         return fileName;
795     return resolvePath(directoryName.value(), ModuleName(fileName.impl()));
796 }
797
798 JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSString* moduleNameValue, JSValue parameters, const SourceOrigin& sourceOrigin)
799 {
800     VM& vm = globalObject->vm();
801     auto throwScope = DECLARE_THROW_SCOPE(vm);
802
803     auto* deferred = JSInternalPromiseDeferred::tryCreate(exec, globalObject);
804     RETURN_IF_EXCEPTION(throwScope, nullptr);
805
806     auto catchScope = DECLARE_CATCH_SCOPE(vm);
807     auto reject = [&] (JSValue rejectionReason) {
808         catchScope.clearException();
809         auto result = deferred->reject(exec, rejectionReason);
810         catchScope.clearException();
811         return result;
812     };
813
814     if (sourceOrigin.isNull())
815         return reject(createError(exec, "Could not resolve the module specifier."_s));
816
817     const auto& referrer = sourceOrigin.string();
818     const auto& moduleName = moduleNameValue->value(exec);
819     if (UNLIKELY(catchScope.exception()))
820         return reject(catchScope.exception());
821
822     auto directoryName = extractDirectoryName(referrer.impl());
823     if (!directoryName)
824         return reject(createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
825
826     auto result = JSC::importModule(exec, Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(moduleName))), parameters, jsUndefined());
827     if (UNLIKELY(catchScope.exception()))
828         return reject(catchScope.exception());
829     return result;
830 }
831
832 Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue)
833 {
834     VM& vm = globalObject->vm();
835     auto scope = DECLARE_THROW_SCOPE(vm);
836
837     scope.releaseAssertNoException();
838     const Identifier key = keyValue.toPropertyKey(exec);
839     RETURN_IF_EXCEPTION(scope, { });
840
841     if (key.isSymbol())
842         return key;
843
844     if (referrerValue.isUndefined()) {
845         auto directoryName = currentWorkingDirectory();
846         if (!directoryName) {
847             throwException(exec, scope, createError(exec, "Could not resolve the current working directory."_s));
848             return { };
849         }
850         return Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(key.impl())));
851     }
852
853     const Identifier referrer = referrerValue.toPropertyKey(exec);
854     RETURN_IF_EXCEPTION(scope, { });
855
856     if (referrer.isSymbol()) {
857         auto directoryName = currentWorkingDirectory();
858         if (!directoryName) {
859             throwException(exec, scope, createError(exec, "Could not resolve the current working directory."_s));
860             return { };
861         }
862         return Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(key.impl())));
863     }
864
865     // If the referrer exists, we assume that the referrer is the correct absolute path.
866     auto directoryName = extractDirectoryName(referrer.impl());
867     if (!directoryName) {
868         throwException(exec, scope, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
869         return { };
870     }
871     return Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(key.impl())));
872 }
873
874 template<typename Vector>
875 static void convertShebangToJSComment(Vector& buffer)
876 {
877     if (buffer.size() >= 2) {
878         if (buffer[0] == '#' && buffer[1] == '!')
879             buffer[0] = buffer[1] = '/';
880     }
881 }
882
883 static RefPtr<Uint8Array> fillBufferWithContentsOfFile(FILE* file)
884 {
885     if (fseek(file, 0, SEEK_END) == -1)
886         return nullptr;
887     long bufferCapacity = ftell(file);
888     if (bufferCapacity == -1)
889         return nullptr;
890     if (fseek(file, 0, SEEK_SET) == -1)
891         return nullptr;
892     auto result = Uint8Array::tryCreate(bufferCapacity);
893     if (!result)
894         return nullptr;
895     size_t readSize = fread(result->data(), 1, bufferCapacity, file);
896     if (readSize != static_cast<size_t>(bufferCapacity))
897         return nullptr;
898     return result;
899 }
900
901 static RefPtr<Uint8Array> fillBufferWithContentsOfFile(const String& fileName)
902 {
903     FILE* f = fopen(fileName.utf8().data(), "rb");
904     if (!f) {
905         fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
906         return nullptr;
907     }
908
909     RefPtr<Uint8Array> result = fillBufferWithContentsOfFile(f);
910     fclose(f);
911
912     return result;
913 }
914
915 template<typename Vector>
916 static bool fillBufferWithContentsOfFile(FILE* file, Vector& buffer)
917 {
918     // We might have injected "use strict"; at the top.
919     size_t initialSize = buffer.size();
920     if (fseek(file, 0, SEEK_END) == -1)
921         return false;
922     long bufferCapacity = ftell(file);
923     if (bufferCapacity == -1)
924         return false;
925     if (fseek(file, 0, SEEK_SET) == -1)
926         return false;
927     buffer.resize(bufferCapacity + initialSize);
928     size_t readSize = fread(buffer.data() + initialSize, 1, buffer.size(), file);
929     return readSize == buffer.size() - initialSize;
930 }
931
932 static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
933 {
934     FILE* f = fopen(fileName.utf8().data(), "rb");
935     if (!f) {
936         fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
937         return false;
938     }
939
940     bool result = fillBufferWithContentsOfFile(f, buffer);
941     fclose(f);
942
943     return result;
944 }
945
946 static bool fetchScriptFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
947 {
948     if (!fillBufferWithContentsOfFile(fileName, buffer))
949         return false;
950     convertShebangToJSComment(buffer);
951     return true;
952 }
953
954 template<typename Vector>
955 static inline SourceCode jscSource(const Vector& utf8, const SourceOrigin& sourceOrigin, const String& filename)
956 {
957     // FIXME: This should use an absolute file URL https://bugs.webkit.org/show_bug.cgi?id=193077
958     String str = stringFromUTF(utf8);
959     return makeSource(str, sourceOrigin, URL({ }, filename));
960 }
961
962 template<typename Vector>
963 static bool fetchModuleFromLocalFileSystem(const String& fileName, Vector& buffer)
964 {
965     // We assume that fileName is always an absolute path.
966 #if OS(WINDOWS)
967     // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
968     // Use long UNC to pass the long path name to the Windows APIs.
969     String longUNCPathName = WTF::makeString("\\\\?\\", fileName);
970     auto pathName = stringToNullTerminatedWChar(longUNCPathName);
971     struct _stat status { };
972     if (_wstat(pathName.data(), &status))
973         return false;
974     if ((status.st_mode & S_IFMT) != S_IFREG)
975         return false;
976
977     FILE* f = _wfopen(pathName.data(), L"rb");
978 #else
979     auto pathName = fileName.utf8();
980     struct stat status { };
981     if (stat(pathName.data(), &status))
982         return false;
983     if ((status.st_mode & S_IFMT) != S_IFREG)
984         return false;
985
986     FILE* f = fopen(pathName.data(), "r");
987 #endif
988     if (!f) {
989         fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
990         return false;
991     }
992
993     bool result = fillBufferWithContentsOfFile(f, buffer);
994     if (result)
995         convertShebangToJSComment(buffer);
996     fclose(f);
997
998     return result;
999 }
1000
1001 JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSValue, JSValue)
1002 {
1003     VM& vm = globalObject->vm();
1004     auto throwScope = DECLARE_THROW_SCOPE(vm);
1005     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::tryCreate(exec, globalObject);
1006     RETURN_IF_EXCEPTION(throwScope, nullptr);
1007
1008     auto catchScope = DECLARE_CATCH_SCOPE(vm);
1009     auto reject = [&] (JSValue rejectionReason) {
1010         catchScope.clearException();
1011         auto result = deferred->reject(exec, rejectionReason);
1012         catchScope.clearException();
1013         return result;
1014     };
1015
1016     String moduleKey = key.toWTFString(exec);
1017     if (UNLIKELY(catchScope.exception()))
1018         return reject(catchScope.exception());
1019
1020     // Here, now we consider moduleKey as the fileName.
1021     Vector<uint8_t> buffer;
1022     if (!fetchModuleFromLocalFileSystem(moduleKey, buffer))
1023         return reject(createError(exec, makeString("Could not open file '", moduleKey, "'.")));
1024
1025
1026     URL moduleURL = URL({ }, moduleKey);
1027 #if ENABLE(WEBASSEMBLY)
1028     // FileSystem does not have mime-type header. The JSC shell recognizes WebAssembly's magic header.
1029     if (buffer.size() >= 4) {
1030         if (buffer[0] == '\0' && buffer[1] == 'a' && buffer[2] == 's' && buffer[3] == 'm') {
1031             auto source = SourceCode(WebAssemblySourceProvider::create(WTFMove(buffer), SourceOrigin { moduleKey }, WTFMove(moduleURL)));
1032             catchScope.releaseAssertNoException();
1033             auto sourceCode = JSSourceCode::create(vm, WTFMove(source));
1034             catchScope.releaseAssertNoException();
1035             auto result = deferred->resolve(exec, sourceCode);
1036             catchScope.clearException();
1037             return result;
1038         }
1039     }
1040 #endif
1041
1042     auto sourceCode = JSSourceCode::create(vm, makeSource(stringFromUTF(buffer), SourceOrigin { moduleKey }, WTFMove(moduleURL), TextPosition(), SourceProviderSourceType::Module));
1043     catchScope.releaseAssertNoException();
1044     auto result = deferred->resolve(exec, sourceCode);
1045     catchScope.clearException();
1046     return result;
1047 }
1048
1049 JSObject* GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSModuleRecord*, JSValue)
1050 {
1051     VM& vm = exec->vm();
1052     auto scope = DECLARE_THROW_SCOPE(vm);
1053
1054     JSObject* metaProperties = constructEmptyObject(exec, globalObject->nullPrototypeObjectStructure());
1055     RETURN_IF_EXCEPTION(scope, nullptr);
1056
1057     metaProperties->putDirect(vm, Identifier::fromString(&vm, "filename"), key);
1058     RETURN_IF_EXCEPTION(scope, nullptr);
1059
1060     return metaProperties;
1061 }
1062
1063 static CString cStringFromViewWithString(ExecState* exec, ThrowScope& scope, StringViewWithUnderlyingString& viewWithString)
1064 {
1065     Expected<CString, UTF8ConversionError> expectedString = viewWithString.view.tryGetUtf8();
1066     if (expectedString)
1067         return expectedString.value();
1068     switch (expectedString.error()) {
1069     case UTF8ConversionError::OutOfMemory:
1070         throwOutOfMemoryError(exec, scope);
1071         break;
1072     case UTF8ConversionError::IllegalSource:
1073         scope.throwException(exec, createError(exec, "Illegal source encountered during UTF8 conversion"));
1074         break;
1075     case UTF8ConversionError::SourceExhausted:
1076         scope.throwException(exec, createError(exec, "Source exhausted during UTF8 conversion"));
1077         break;
1078     default:
1079         RELEASE_ASSERT_NOT_REACHED();
1080     }
1081     return { };
1082 }
1083
1084 static EncodedJSValue printInternal(ExecState* exec, FILE* out)
1085 {
1086     VM& vm = exec->vm();
1087     auto scope = DECLARE_THROW_SCOPE(vm);
1088
1089     if (asyncTestExpectedPasses) {
1090         JSValue value = exec->argument(0);
1091         if (value.isString() && WTF::equal(asString(value)->value(exec).impl(), "Test262:AsyncTestComplete")) {
1092             asyncTestPasses++;
1093             return JSValue::encode(jsUndefined());
1094         }
1095     }
1096
1097     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1098         if (i)
1099             if (EOF == fputc(' ', out))
1100                 goto fail;
1101
1102         auto viewWithString = exec->uncheckedArgument(i).toString(exec)->viewWithUnderlyingString(exec);
1103         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1104         auto string = cStringFromViewWithString(exec, scope, viewWithString);
1105         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1106         if (fprintf(out, "%s", string.data()) < 0)
1107             goto fail;
1108     }
1109
1110     fputc('\n', out);
1111 fail:
1112     fflush(out);
1113     return JSValue::encode(jsUndefined());
1114 }
1115
1116 EncodedJSValue JSC_HOST_CALL functionPrintStdOut(ExecState* exec) { return printInternal(exec, stdout); }
1117 EncodedJSValue JSC_HOST_CALL functionPrintStdErr(ExecState* exec) { return printInternal(exec, stderr); }
1118
1119 EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
1120 {
1121     VM& vm = exec->vm();
1122     auto scope = DECLARE_THROW_SCOPE(vm);
1123     auto viewWithString = exec->argument(0).toString(exec)->viewWithUnderlyingString(exec);
1124     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1125     auto string = cStringFromViewWithString(exec, scope, viewWithString);
1126     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1127     fprintf(stderr, "--> %s\n", string.data());
1128     return JSValue::encode(jsUndefined());
1129 }
1130
1131 EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
1132 {
1133     if (exec->argumentCount() < 1)
1134         return JSValue::encode(jsUndefined());
1135     return JSValue::encode(jsString(exec, toString(exec->argument(0))));
1136 }
1137
1138 EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
1139 {
1140     if (exec->argumentCount() < 1)
1141         return JSValue::encode(jsUndefined());
1142     VM& vm = exec->vm();
1143     JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(0));
1144     if (!object)
1145         return JSValue::encode(jsNontrivialString(exec, "<not object>"_s));
1146     return JSValue::encode(jsNontrivialString(exec, toString("<Butterfly: ", RawPointer(object->butterfly()), "; public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
1147 }
1148
1149 EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState* exec)
1150 {
1151     VM& vm = exec->vm();
1152     auto scope = DECLARE_THROW_SCOPE(vm);
1153
1154     if (exec->argumentCount() >= 1) {
1155         Seconds seconds = Seconds(exec->argument(0).toNumber(exec));
1156         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1157         sleep(seconds);
1158     }
1159     
1160     return JSValue::encode(jsUndefined());
1161 }
1162
1163 class FunctionJSCStackFunctor {
1164 public:
1165     FunctionJSCStackFunctor(StringBuilder& trace)
1166         : m_trace(trace)
1167     {
1168     }
1169
1170     StackVisitor::Status operator()(StackVisitor& visitor) const
1171     {
1172         m_trace.append(String::format("    %zu   %s\n", visitor->index(), visitor->toString().utf8().data()));
1173         return StackVisitor::Continue;
1174     }
1175
1176 private:
1177     StringBuilder& m_trace;
1178 };
1179
1180 EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
1181 {
1182     StringBuilder trace;
1183     trace.appendLiteral("--> Stack trace:\n");
1184
1185     FunctionJSCStackFunctor functor(trace);
1186     exec->iterate(functor);
1187     fprintf(stderr, "%s", trace.toString().utf8().data());
1188     return JSValue::encode(jsUndefined());
1189 }
1190
1191 EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
1192 {
1193     VM& vm = exec->vm();
1194     JSLockHolder lock(vm);
1195     vm.heap.collectNow(Sync, CollectionScope::Full);
1196     return JSValue::encode(jsNumber(vm.heap.sizeAfterLastFullCollection()));
1197 }
1198
1199 EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
1200 {
1201     VM& vm = exec->vm();
1202     JSLockHolder lock(vm);
1203     vm.heap.collectSync(CollectionScope::Full);
1204     return JSValue::encode(jsNumber(vm.heap.sizeAfterLastFullCollection()));
1205 }
1206
1207 EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
1208 {
1209     VM& vm = exec->vm();
1210     JSLockHolder lock(vm);
1211     vm.heap.collectSync(CollectionScope::Eden);
1212     return JSValue::encode(jsNumber(vm.heap.sizeAfterLastEdenCollection()));
1213 }
1214
1215 EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*)
1216 {
1217     // It's best for this to be the first thing called in the 
1218     // JS program so the option is set to true before we JIT.
1219     Options::forceGCSlowPaths() = true;
1220     return JSValue::encode(jsUndefined());
1221 }
1222
1223 EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState* exec)
1224 {
1225     VM& vm = exec->vm();
1226     JSLockHolder lock(vm);
1227     return JSValue::encode(jsNumber(vm.heap.size()));
1228 }
1229
1230 class JSCMemoryFootprint : public JSDestructibleObject {
1231     using Base = JSDestructibleObject;
1232 public:
1233     JSCMemoryFootprint(VM& vm, Structure* structure)
1234         : Base(vm, structure)
1235     { }
1236
1237     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
1238     {
1239         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
1240     }
1241
1242     static JSCMemoryFootprint* create(VM& vm, JSGlobalObject* globalObject)
1243     {
1244         Structure* structure = createStructure(vm, globalObject, jsNull());
1245         JSCMemoryFootprint* footprint = new (NotNull, allocateCell<JSCMemoryFootprint>(vm.heap, sizeof(JSCMemoryFootprint))) JSCMemoryFootprint(vm, structure);
1246         footprint->finishCreation(vm);
1247         return footprint;
1248     }
1249
1250     void finishCreation(VM& vm)
1251     {
1252         Base::finishCreation(vm);
1253
1254         auto addProperty = [&] (VM& vm, const char* name, JSValue value) {
1255             JSCMemoryFootprint::addProperty(vm, name, value);
1256         };
1257
1258         MemoryFootprint footprint = MemoryFootprint::now();
1259
1260         addProperty(vm, "current", jsNumber(footprint.current));
1261         addProperty(vm, "peak", jsNumber(footprint.peak));
1262     }
1263
1264     DECLARE_INFO;
1265
1266 private:
1267     void addProperty(VM& vm, const char* name, JSValue value)
1268     {
1269         Identifier identifier = Identifier::fromString(&vm, name);
1270         putDirect(vm, identifier, value);
1271     }
1272 };
1273
1274 const ClassInfo JSCMemoryFootprint::s_info = { "MemoryFootprint", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCMemoryFootprint) };
1275
1276 EncodedJSValue JSC_HOST_CALL functionCreateMemoryFootprint(ExecState* exec)
1277 {
1278     VM& vm = exec->vm();
1279     JSLockHolder lock(vm);
1280     return JSValue::encode(JSCMemoryFootprint::create(vm, exec->lexicalGlobalObject()));
1281 }
1282
1283 EncodedJSValue JSC_HOST_CALL functionResetMemoryPeak(ExecState*)
1284 {
1285     MemoryFootprint::resetPeak();
1286     return JSValue::encode(jsUndefined());
1287 }
1288
1289 // This function is not generally very helpful in 64-bit code as the tag and payload
1290 // share a register. But in 32-bit JITed code the tag may not be checked if an
1291 // optimization removes type checking requirements, such as in ===.
1292 EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState* exec)
1293 {
1294     JSValue value = exec->argument(0);
1295     if (!value.isCell())
1296         return JSValue::encode(jsUndefined());
1297     // Need to cast to uint64_t so bitwise_cast will play along.
1298     uint64_t asNumber = reinterpret_cast<uint64_t>(value.asCell());
1299     EncodedJSValue returnValue = JSValue::encode(jsNumber(bitwise_cast<double>(asNumber)));
1300     return returnValue;
1301 }
1302
1303 EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
1304 {
1305     // We need this function for compatibility with the Mozilla JS tests but for now
1306     // we don't actually do any version-specific handling
1307     return JSValue::encode(jsUndefined());
1308 }
1309
1310 EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
1311 {
1312     VM& vm = exec->vm();
1313     auto scope = DECLARE_THROW_SCOPE(vm);
1314
1315     String fileName = exec->argument(0).toWTFString(exec);
1316     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1317     Vector<char> script;
1318     if (!fetchScriptFromLocalFileSystem(fileName, script))
1319         return JSValue::encode(throwException(exec, scope, createError(exec, "Could not open file."_s)));
1320
1321     GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
1322
1323     JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
1324     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1325     for (unsigned i = 1; i < exec->argumentCount(); ++i) {
1326         array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
1327         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1328     }
1329     globalObject->putDirect(
1330         vm, Identifier::fromString(globalObject->globalExec(), "arguments"), array);
1331
1332     NakedPtr<Exception> exception;
1333     StopWatch stopWatch;
1334     stopWatch.start();
1335     evaluate(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), exception);
1336     stopWatch.stop();
1337
1338     if (exception) {
1339         throwException(globalObject->globalExec(), scope, exception);
1340         return JSValue::encode(jsUndefined());
1341     }
1342     
1343     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1344 }
1345
1346 EncodedJSValue JSC_HOST_CALL functionRunString(ExecState* exec)
1347 {
1348     VM& vm = exec->vm();
1349     auto scope = DECLARE_THROW_SCOPE(vm);
1350
1351     String source = exec->argument(0).toWTFString(exec);
1352     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1353
1354     GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
1355
1356     JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
1357     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1358     for (unsigned i = 1; i < exec->argumentCount(); ++i) {
1359         array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
1360         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1361     }
1362     globalObject->putDirect(
1363         vm, Identifier::fromString(globalObject->globalExec(), "arguments"), array);
1364
1365     NakedPtr<Exception> exception;
1366     evaluate(globalObject->globalExec(), makeSource(source, exec->callerSourceOrigin()), JSValue(), exception);
1367
1368     if (exception) {
1369         scope.throwException(globalObject->globalExec(), exception);
1370         return JSValue::encode(jsUndefined());
1371     }
1372     
1373     return JSValue::encode(globalObject);
1374 }
1375
1376 EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
1377 {
1378     VM& vm = exec->vm();
1379     auto scope = DECLARE_THROW_SCOPE(vm);
1380
1381     String fileName = exec->argument(0).toWTFString(exec);
1382     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1383     Vector<char> script;
1384     if (!fetchScriptFromLocalFileSystem(fileName, script))
1385         return JSValue::encode(throwException(exec, scope, createError(exec, "Could not open file."_s)));
1386
1387     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1388     
1389     NakedPtr<Exception> evaluationException;
1390     JSValue result = evaluate(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
1391     if (evaluationException)
1392         throwException(exec, scope, evaluationException);
1393     return JSValue::encode(result);
1394 }
1395
1396 EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState* exec)
1397 {
1398     VM& vm = exec->vm();
1399     auto scope = DECLARE_THROW_SCOPE(vm);
1400
1401     String sourceCode = exec->argument(0).toWTFString(exec);
1402     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1403     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1404
1405     NakedPtr<Exception> evaluationException;
1406     JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode, exec->callerSourceOrigin()), JSValue(), evaluationException);
1407     if (evaluationException)
1408         throwException(exec, scope, evaluationException);
1409     return JSValue::encode(result);
1410 }
1411
1412 EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
1413 {
1414     VM& vm = exec->vm();
1415     auto scope = DECLARE_THROW_SCOPE(vm);
1416
1417     String fileName = exec->argument(0).toWTFString(exec);
1418     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1419
1420     bool isBinary = false;
1421     if (exec->argumentCount() > 1) {
1422         String type = exec->argument(1).toWTFString(exec);
1423         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1424         if (type != "binary")
1425             return throwVMError(exec, scope, "Expected 'binary' as second argument.");
1426         isBinary = true;
1427     }
1428
1429     RefPtr<Uint8Array> content = fillBufferWithContentsOfFile(fileName);
1430     if (!content)
1431         return throwVMError(exec, scope, "Could not open file.");
1432
1433     if (!isBinary)
1434         return JSValue::encode(jsString(exec, String::fromUTF8WithLatin1Fallback(content->data(), content->length())));
1435
1436     Structure* structure = exec->lexicalGlobalObject()->typedArrayStructure(TypeUint8);
1437     JSObject* result = JSUint8Array::create(vm, structure, WTFMove(content));
1438     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1439
1440     return JSValue::encode(result);
1441 }
1442
1443 EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
1444 {
1445     VM& vm = exec->vm();
1446     auto scope = DECLARE_THROW_SCOPE(vm);
1447
1448     String fileName = exec->argument(0).toWTFString(exec);
1449     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1450     Vector<char> script;
1451     if (!fetchScriptFromLocalFileSystem(fileName, script))
1452         return JSValue::encode(throwException(exec, scope, createError(exec, "Could not open file."_s)));
1453
1454     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1455
1456     StopWatch stopWatch;
1457     stopWatch.start();
1458
1459     JSValue syntaxException;
1460     bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), &syntaxException);
1461     stopWatch.stop();
1462
1463     if (!validSyntax)
1464         throwException(exec, scope, syntaxException);
1465     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1466 }
1467
1468 #if ENABLE(SAMPLING_FLAGS)
1469 EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
1470 {
1471     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1472         unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1473         if ((flag >= 1) && (flag <= 32))
1474             SamplingFlags::setFlag(flag);
1475     }
1476     return JSValue::encode(jsNull());
1477 }
1478
1479 EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
1480 {
1481     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1482         unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1483         if ((flag >= 1) && (flag <= 32))
1484             SamplingFlags::clearFlag(flag);
1485     }
1486     return JSValue::encode(jsNull());
1487 }
1488 #endif
1489
1490 EncodedJSValue JSC_HOST_CALL functionGetRandomSeed(ExecState* exec)
1491 {
1492     return JSValue::encode(jsNumber(exec->lexicalGlobalObject()->weakRandom().seed()));
1493 }
1494
1495 EncodedJSValue JSC_HOST_CALL functionSetRandomSeed(ExecState* exec)
1496 {
1497     VM& vm = exec->vm();
1498     auto scope = DECLARE_THROW_SCOPE(vm);
1499
1500     unsigned seed = exec->argument(0).toUInt32(exec);
1501     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1502     exec->lexicalGlobalObject()->weakRandom().setSeed(seed);
1503     return JSValue::encode(jsUndefined());
1504 }
1505
1506 EncodedJSValue JSC_HOST_CALL functionIsRope(ExecState* exec)
1507 {
1508     JSValue argument = exec->argument(0);
1509     if (!argument.isString())
1510         return JSValue::encode(jsBoolean(false));
1511     const StringImpl* impl = asString(argument)->tryGetValueImpl();
1512     return JSValue::encode(jsBoolean(!impl));
1513 }
1514
1515 EncodedJSValue JSC_HOST_CALL functionCallerSourceOrigin(ExecState* state)
1516 {
1517     SourceOrigin sourceOrigin = state->callerSourceOrigin();
1518     if (sourceOrigin.isNull())
1519         return JSValue::encode(jsNull());
1520     return JSValue::encode(jsString(state, sourceOrigin.string()));
1521 }
1522
1523 EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
1524 {
1525     Vector<char, 256> line;
1526     int c;
1527     while ((c = getchar()) != EOF) {
1528         // FIXME: Should we also break on \r? 
1529         if (c == '\n')
1530             break;
1531         line.append(c);
1532     }
1533     line.append('\0');
1534     return JSValue::encode(jsString(exec, line.data()));
1535 }
1536
1537 EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
1538 {
1539     return JSValue::encode(jsNumber(WallTime::now().secondsSinceEpoch().value()));
1540 }
1541
1542 EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState* exec)
1543 {
1544     return JSValue::encode(setNeverInline(exec));
1545 }
1546
1547 EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState* exec)
1548 {
1549     return JSValue::encode(setNeverOptimize(exec));
1550 }
1551
1552 EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState* exec)
1553 {
1554     if (exec->argumentCount()) {
1555         FunctionExecutable* executable = getExecutableForFunction(exec->argument(0));
1556         if (executable)
1557             executable->setNeverFTLOptimize(true);
1558     }
1559     return JSValue::encode(jsUndefined());
1560 }
1561
1562 EncodedJSValue JSC_HOST_CALL functionNoOSRExitFuzzing(ExecState* exec)
1563 {
1564     return JSValue::encode(setCannotUseOSRExitFuzzing(exec));
1565 }
1566
1567 EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
1568 {
1569     return JSValue::encode(optimizeNextInvocation(exec));
1570 }
1571
1572 EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
1573 {
1574     return JSValue::encode(numberOfDFGCompiles(exec));
1575 }
1576
1577 Message::Message(ArrayBufferContents&& contents, int32_t index)
1578     : m_contents(WTFMove(contents))
1579     , m_index(index)
1580 {
1581 }
1582
1583 Message::~Message()
1584 {
1585 }
1586
1587 Worker::Worker(Workers& workers)
1588     : m_workers(workers)
1589 {
1590     auto locker = holdLock(m_workers.m_lock);
1591     m_workers.m_workers.append(this);
1592     
1593     *currentWorker() = this;
1594 }
1595
1596 Worker::~Worker()
1597 {
1598     auto locker = holdLock(m_workers.m_lock);
1599     RELEASE_ASSERT(isOnList());
1600     remove();
1601 }
1602
1603 void Worker::enqueue(const AbstractLocker&, RefPtr<Message> message)
1604 {
1605     m_messages.append(message);
1606 }
1607
1608 RefPtr<Message> Worker::dequeue()
1609 {
1610     auto locker = holdLock(m_workers.m_lock);
1611     while (m_messages.isEmpty())
1612         m_workers.m_condition.wait(m_workers.m_lock);
1613     return m_messages.takeFirst();
1614 }
1615
1616 Worker& Worker::current()
1617 {
1618     return **currentWorker();
1619 }
1620
1621 ThreadSpecific<Worker*>& Worker::currentWorker()
1622 {
1623     static ThreadSpecific<Worker*>* result;
1624     static std::once_flag flag;
1625     std::call_once(
1626         flag,
1627         [] () {
1628             result = new ThreadSpecific<Worker*>();
1629         });
1630     return *result;
1631 }
1632
1633 Workers::Workers()
1634 {
1635 }
1636
1637 Workers::~Workers()
1638 {
1639     UNREACHABLE_FOR_PLATFORM();
1640 }
1641
1642 template<typename Func>
1643 void Workers::broadcast(const Func& func)
1644 {
1645     auto locker = holdLock(m_lock);
1646     for (Worker* worker = m_workers.begin(); worker != m_workers.end(); worker = worker->next()) {
1647         if (worker != &Worker::current())
1648             func(locker, *worker);
1649     }
1650     m_condition.notifyAll();
1651 }
1652
1653 void Workers::report(const String& string)
1654 {
1655     auto locker = holdLock(m_lock);
1656     m_reports.append(string.isolatedCopy());
1657     m_condition.notifyAll();
1658 }
1659
1660 String Workers::tryGetReport()
1661 {
1662     auto locker = holdLock(m_lock);
1663     if (m_reports.isEmpty())
1664         return String();
1665     return m_reports.takeFirst();
1666 }
1667
1668 String Workers::getReport()
1669 {
1670     auto locker = holdLock(m_lock);
1671     while (m_reports.isEmpty())
1672         m_condition.wait(m_lock);
1673     return m_reports.takeFirst();
1674 }
1675
1676 Workers& Workers::singleton()
1677 {
1678     static Workers* result;
1679     static std::once_flag flag;
1680     std::call_once(
1681         flag,
1682         [] {
1683             result = new Workers();
1684         });
1685     return *result;
1686 }
1687
1688 EncodedJSValue JSC_HOST_CALL functionDollarCreateRealm(ExecState* exec)
1689 {
1690     VM& vm = exec->vm();
1691     GlobalObject* result = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
1692     return JSValue::encode(result->getDirect(vm, Identifier::fromString(exec, "$")));
1693 }
1694
1695 EncodedJSValue JSC_HOST_CALL functionDollarDetachArrayBuffer(ExecState* exec)
1696 {
1697     return functionTransferArrayBuffer(exec);
1698 }
1699
1700 EncodedJSValue JSC_HOST_CALL functionDollarEvalScript(ExecState* exec)
1701 {
1702     VM& vm = exec->vm();
1703     auto scope = DECLARE_THROW_SCOPE(vm);
1704
1705     String sourceCode = exec->argument(0).toWTFString(exec);
1706     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1707     
1708     GlobalObject* globalObject = jsDynamicCast<GlobalObject*>(vm,
1709         exec->thisValue().get(exec, Identifier::fromString(exec, "global")));
1710     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1711     if (!globalObject)
1712         return JSValue::encode(throwException(exec, scope, createError(exec, "Expected global to point to a global object"_s)));
1713     
1714     NakedPtr<Exception> evaluationException;
1715     JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode, exec->callerSourceOrigin()), JSValue(), evaluationException);
1716     if (evaluationException)
1717         throwException(exec, scope, evaluationException);
1718     return JSValue::encode(result);
1719 }
1720
1721 EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState* exec)
1722 {
1723     VM& vm = exec->vm();
1724     auto scope = DECLARE_THROW_SCOPE(vm);
1725
1726     String sourceCode = exec->argument(0).toWTFString(exec).isolatedCopy();
1727     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1728     
1729     Lock didStartLock;
1730     Condition didStartCondition;
1731     bool didStart = false;
1732     
1733     Thread::create(
1734         "JSC Agent",
1735         [sourceCode, &didStartLock, &didStartCondition, &didStart] () {
1736             CommandLine commandLine(0, nullptr);
1737             commandLine.m_interactive = false;
1738             runJSC(
1739                 commandLine, true,
1740                 [&] (VM&, GlobalObject* globalObject, bool& success) {
1741                     // Notify the thread that started us that we have registered a worker.
1742                     {
1743                         auto locker = holdLock(didStartLock);
1744                         didStart = true;
1745                         didStartCondition.notifyOne();
1746                     }
1747                     
1748                     NakedPtr<Exception> evaluationException;
1749                     JSValue result;
1750                     result = evaluate(globalObject->globalExec(), makeSource(sourceCode, SourceOrigin("worker"_s)), JSValue(), evaluationException);
1751                     if (evaluationException)
1752                         result = evaluationException->value();
1753                     checkException(globalObject->globalExec(), globalObject, true, evaluationException, result, commandLine, success);
1754                     if (!success)
1755                         exit(1);
1756                 });
1757         })->detach();
1758     
1759     {
1760         auto locker = holdLock(didStartLock);
1761         while (!didStart)
1762             didStartCondition.wait(didStartLock);
1763     }
1764     
1765     return JSValue::encode(jsUndefined());
1766 }
1767
1768 EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState* exec)
1769 {
1770     VM& vm = exec->vm();
1771     auto scope = DECLARE_THROW_SCOPE(vm);
1772
1773     JSValue callback = exec->argument(0);
1774     CallData callData;
1775     CallType callType = getCallData(vm, callback, callData);
1776     if (callType == CallType::None)
1777         return JSValue::encode(throwException(exec, scope, createError(exec, "Expected callback"_s)));
1778     
1779     RefPtr<Message> message;
1780     {
1781         ReleaseHeapAccessScope releaseAccess(vm.heap);
1782         message = Worker::current().dequeue();
1783     }
1784     
1785     auto nativeBuffer = ArrayBuffer::create(message->releaseContents());
1786     ArrayBufferSharingMode sharingMode = nativeBuffer->sharingMode();
1787     JSArrayBuffer* jsBuffer = JSArrayBuffer::create(vm, exec->lexicalGlobalObject()->arrayBufferStructure(sharingMode), WTFMove(nativeBuffer));
1788     
1789     MarkedArgumentBuffer args;
1790     args.append(jsBuffer);
1791     args.append(jsNumber(message->index()));
1792     if (UNLIKELY(args.hasOverflowed()))
1793         return JSValue::encode(throwOutOfMemoryError(exec, scope));
1794     RELEASE_AND_RETURN(scope, JSValue::encode(call(exec, callback, callType, callData, jsNull(), args)));
1795 }
1796
1797 EncodedJSValue JSC_HOST_CALL functionDollarAgentReport(ExecState* exec)
1798 {
1799     VM& vm = exec->vm();
1800     auto scope = DECLARE_THROW_SCOPE(vm);
1801
1802     String report = exec->argument(0).toWTFString(exec);
1803     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1804     
1805     Workers::singleton().report(report);
1806     
1807     return JSValue::encode(jsUndefined());
1808 }
1809
1810 EncodedJSValue JSC_HOST_CALL functionDollarAgentSleep(ExecState* exec)
1811 {
1812     VM& vm = exec->vm();
1813     auto scope = DECLARE_THROW_SCOPE(vm);
1814
1815     if (exec->argumentCount() >= 1) {
1816         Seconds seconds = Seconds::fromMilliseconds(exec->argument(0).toNumber(exec));
1817         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1818         sleep(seconds);
1819     }
1820     return JSValue::encode(jsUndefined());
1821 }
1822
1823 EncodedJSValue JSC_HOST_CALL functionDollarAgentBroadcast(ExecState* exec)
1824 {
1825     VM& vm = exec->vm();
1826     auto scope = DECLARE_THROW_SCOPE(vm);
1827
1828     JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(vm, exec->argument(0));
1829     if (!jsBuffer || !jsBuffer->isShared())
1830         return JSValue::encode(throwException(exec, scope, createError(exec, "Expected SharedArrayBuffer"_s)));
1831     
1832     int32_t index = exec->argument(1).toInt32(exec);
1833     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1834     
1835     Workers::singleton().broadcast(
1836         [&] (const AbstractLocker& locker, Worker& worker) {
1837             ArrayBuffer* nativeBuffer = jsBuffer->impl();
1838             ArrayBufferContents contents;
1839             nativeBuffer->transferTo(vm, contents); // "transferTo" means "share" if the buffer is shared.
1840             RefPtr<Message> message = adoptRef(new Message(WTFMove(contents), index));
1841             worker.enqueue(locker, message);
1842         });
1843     
1844     return JSValue::encode(jsUndefined());
1845 }
1846
1847 EncodedJSValue JSC_HOST_CALL functionDollarAgentGetReport(ExecState* exec)
1848 {
1849     VM& vm = exec->vm();
1850
1851     String string = Workers::singleton().tryGetReport();
1852     if (!string)
1853         return JSValue::encode(jsNull());
1854     
1855     return JSValue::encode(jsString(&vm, string));
1856 }
1857
1858 EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*)
1859 {
1860     return JSValue::encode(jsUndefined());
1861 }
1862
1863 EncodedJSValue JSC_HOST_CALL functionDollarAgentMonotonicNow(ExecState*)
1864 {
1865     return JSValue::encode(jsNumber(MonotonicTime::now().secondsSinceEpoch().milliseconds()));
1866 }
1867
1868 EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState* exec)
1869 {
1870     VM& vm = exec->vm();
1871
1872     String string;
1873     {
1874         ReleaseHeapAccessScope releaseAccess(vm.heap);
1875         string = Workers::singleton().getReport();
1876     }
1877     if (!string)
1878         return JSValue::encode(jsNull());
1879     
1880     return JSValue::encode(jsString(&vm, string));
1881 }
1882
1883 EncodedJSValue JSC_HOST_CALL functionHeapCapacity(ExecState* exec)
1884 {
1885     VM& vm = exec->vm();
1886     return JSValue::encode(jsNumber(vm.heap.capacity()));
1887 }
1888
1889 EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState* exec)
1890 {
1891     VM& vm = exec->vm();
1892     auto scope = DECLARE_THROW_SCOPE(vm);
1893     
1894     double sleepTimeMs = 0;
1895     if (exec->argumentCount() >= 1) {
1896         sleepTimeMs = exec->argument(0).toNumber(exec);
1897         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1898     }
1899
1900     vm.heap.releaseAccess();
1901     if (sleepTimeMs)
1902         sleep(Seconds::fromMilliseconds(sleepTimeMs));
1903     vm.heap.acquireAccess();
1904     return JSValue::encode(jsUndefined());
1905 }
1906
1907 EncodedJSValue JSC_HOST_CALL functionDisableRichSourceInfo(ExecState*)
1908 {
1909     supportsRichSourceInfo = false;
1910     return JSValue::encode(jsUndefined());
1911 }
1912
1913 EncodedJSValue JSC_HOST_CALL functionMallocInALoop(ExecState*)
1914 {
1915     Vector<void*> ptrs;
1916     for (unsigned i = 0; i < 5000; ++i)
1917         ptrs.append(fastMalloc(1024 * 2));
1918     for (void* ptr : ptrs)
1919         fastFree(ptr);
1920     return JSValue::encode(jsUndefined());
1921 }
1922
1923 EncodedJSValue JSC_HOST_CALL functionTotalCompileTime(ExecState*)
1924 {
1925 #if ENABLE(JIT)
1926     return JSValue::encode(jsNumber(JIT::totalCompileTime().milliseconds()));
1927 #else
1928     return JSValue::encode(jsNumber(0));
1929 #endif
1930 }
1931
1932 template<typename ValueType>
1933 typename std::enable_if<!std::is_fundamental<ValueType>::value>::type addOption(VM&, JSObject*, const Identifier&, ValueType) { }
1934
1935 template<typename ValueType>
1936 typename std::enable_if<std::is_fundamental<ValueType>::value>::type addOption(VM& vm, JSObject* optionsObject, const Identifier& identifier, ValueType value)
1937 {
1938     optionsObject->putDirect(vm, identifier, JSValue(value));
1939 }
1940
1941 EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState* exec)
1942 {
1943     VM& vm = exec->vm();
1944     JSObject* optionsObject = constructEmptyObject(exec);
1945 #define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
1946     addOption(vm, optionsObject, Identifier::fromString(exec, #name_), Options::name_());
1947     JSC_OPTIONS(FOR_EACH_OPTION)
1948 #undef FOR_EACH_OPTION
1949     return JSValue::encode(optionsObject);
1950 }
1951
1952 EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
1953 {
1954     if (exec->argumentCount() < 1)
1955         return JSValue::encode(jsUndefined());
1956     
1957     CodeBlock* block = getSomeBaselineCodeBlockForFunction(exec->argument(0));
1958     if (!block)
1959         return JSValue::encode(jsNumber(0));
1960     
1961     return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
1962 }
1963
1964 EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
1965 {
1966     VM& vm = exec->vm();
1967     auto scope = DECLARE_THROW_SCOPE(vm);
1968
1969     if (exec->argumentCount() < 1)
1970         return JSValue::encode(throwException(exec, scope, createError(exec, "Not enough arguments"_s)));
1971     
1972     JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(vm, exec->argument(0));
1973     if (!buffer)
1974         return JSValue::encode(throwException(exec, scope, createError(exec, "Expected an array buffer"_s)));
1975     
1976     ArrayBufferContents dummyContents;
1977     buffer->impl()->transferTo(vm, dummyContents);
1978     
1979     return JSValue::encode(jsUndefined());
1980 }
1981
1982 EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState* exec)
1983 {
1984     VM& vm = exec->vm();
1985     vm.setFailNextNewCodeBlock();
1986     return JSValue::encode(jsUndefined());
1987 }
1988
1989 EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
1990 {
1991     jscExit(EXIT_SUCCESS);
1992
1993 #if COMPILER(MSVC)
1994     // Without this, Visual Studio will complain that this method does not return a value.
1995     return JSValue::encode(jsUndefined());
1996 #endif
1997 }
1998
1999 EncodedJSValue JSC_HOST_CALL functionFalse(ExecState*) { return JSValue::encode(jsBoolean(false)); }
2000
2001 EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
2002 EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
2003 EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState* exec)
2004 {
2005     for (size_t i = 0; i < exec->argumentCount(); ++i) {
2006         if (!exec->argument(i).isInt32())
2007             return JSValue::encode(jsBoolean(false));
2008     }
2009     return JSValue::encode(jsBoolean(true));
2010 }
2011
2012 EncodedJSValue JSC_HOST_CALL functionIsPureNaN(ExecState* exec)
2013 {
2014     for (size_t i = 0; i < exec->argumentCount(); ++i) {
2015         JSValue value = exec->argument(i);
2016         if (!value.isNumber())
2017             return JSValue::encode(jsBoolean(false));
2018         double number = value.asNumber();
2019         if (!std::isnan(number))
2020             return JSValue::encode(jsBoolean(false));
2021         if (isImpureNaN(number))
2022             return JSValue::encode(jsBoolean(false));
2023     }
2024     return JSValue::encode(jsBoolean(true));
2025 }
2026
2027 EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
2028
2029 EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
2030 {
2031     return JSValue::encode(jsNumber(42));
2032 }
2033
2034 EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
2035 {
2036     VM& vm = exec->vm();
2037     return JSValue::encode(Masquerader::create(vm, exec->lexicalGlobalObject()));
2038 }
2039
2040 EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState* exec)
2041 {
2042     JSValue value = exec->argument(0);
2043     if (value.isObject())
2044         return JSValue::encode(jsBoolean(asObject(value)->hasCustomProperties(exec->vm())));
2045     return JSValue::encode(jsBoolean(false));
2046 }
2047
2048 EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
2049 {
2050     VM& vm = exec->vm();
2051     vm.dumpTypeProfilerData();
2052     return JSValue::encode(jsUndefined());
2053 }
2054
2055 EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState* exec)
2056 {
2057     VM& vm = exec->vm();
2058     vm.drainMicrotasks();
2059     return JSValue::encode(jsUndefined());
2060 }
2061
2062 EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*)
2063 {
2064 #if USE(JSVALUE64)
2065     return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
2066 #else
2067     return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
2068 #endif
2069 }
2070
2071 EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState* exec)
2072 {
2073     VM& vm = exec->vm();
2074     return JSValue::encode(GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>()));
2075 }
2076
2077 EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState* exec)
2078 {
2079     VM& vm = exec->vm();
2080     auto scope = DECLARE_THROW_SCOPE(vm);
2081
2082     String source = exec->argument(0).toWTFString(exec);
2083     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2084
2085     StopWatch stopWatch;
2086     stopWatch.start();
2087
2088     ParserError error;
2089     bool validSyntax = checkModuleSyntax(exec, makeSource(source, { }, URL(), TextPosition(), SourceProviderSourceType::Module), error);
2090     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2091     stopWatch.stop();
2092
2093     if (!validSyntax)
2094         throwException(exec, scope, jsNontrivialString(exec, toString("SyntaxError: ", error.message(), ":", error.line())));
2095     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
2096 }
2097
2098 EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*)
2099 {
2100 #if ENABLE(SAMPLING_PROFILER)
2101     return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
2102 #else
2103     return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
2104 #endif
2105 }
2106
2107 EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState* exec)
2108 {
2109     VM& vm = exec->vm();
2110     JSLockHolder lock(vm);
2111     auto scope = DECLARE_THROW_SCOPE(vm);
2112
2113     HeapSnapshotBuilder snapshotBuilder(vm.ensureHeapProfiler());
2114     snapshotBuilder.buildSnapshot();
2115
2116     String jsonString = snapshotBuilder.json();
2117     EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
2118     scope.releaseAssertNoException();
2119     return result;
2120 }
2121
2122 EncodedJSValue JSC_HOST_CALL functionResetSuperSamplerState(ExecState*)
2123 {
2124     resetSuperSamplerState();
2125     return JSValue::encode(jsUndefined());
2126 }
2127
2128 EncodedJSValue JSC_HOST_CALL functionEnsureArrayStorage(ExecState* exec)
2129 {
2130     VM& vm = exec->vm();
2131     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
2132         if (JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(i)))
2133             object->ensureArrayStorage(vm);
2134     }
2135     return JSValue::encode(jsUndefined());
2136 }
2137
2138 #if ENABLE(SAMPLING_PROFILER)
2139 EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState* exec)
2140 {
2141     VM& vm = exec->vm();
2142     SamplingProfiler& samplingProfiler = vm.ensureSamplingProfiler(WTF::Stopwatch::create());
2143     samplingProfiler.noticeCurrentThreadAsJSCExecutionThread();
2144     samplingProfiler.start();
2145     return JSValue::encode(jsUndefined());
2146 }
2147
2148 EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState* exec)
2149 {
2150     VM& vm = exec->vm();
2151     auto scope = DECLARE_THROW_SCOPE(vm);
2152
2153     if (!vm.samplingProfiler())
2154         return JSValue::encode(throwException(exec, scope, createError(exec, "Sampling profiler was never started"_s)));
2155
2156     String jsonString = vm.samplingProfiler()->stackTracesAsJSON();
2157     EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
2158     scope.releaseAssertNoException();
2159     return result;
2160 }
2161 #endif // ENABLE(SAMPLING_PROFILER)
2162
2163 EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*)
2164 {
2165     return JSValue::encode(jsNumber(JSC::maxArguments));
2166 }
2167
2168 EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState* exec)
2169 {
2170     VM& vm = exec->vm();
2171     auto scope = DECLARE_THROW_SCOPE(vm);
2172
2173     JSValue numberOfAsyncPasses = exec->argument(0);
2174     if (!numberOfAsyncPasses.isUInt32())
2175         return throwVMError(exec, scope, "Expected first argument to a uint32"_s);
2176
2177     asyncTestExpectedPasses += numberOfAsyncPasses.asUInt32();
2178     return encodedJSUndefined();
2179 }
2180
2181 EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*)
2182 {
2183     asyncTestPasses++;
2184     return encodedJSUndefined();
2185 }
2186
2187 #if ENABLE(WEBASSEMBLY)
2188
2189 static EncodedJSValue JSC_HOST_CALL functionWebAssemblyMemoryMode(ExecState* exec)
2190 {
2191     VM& vm = exec->vm();
2192     auto scope = DECLARE_THROW_SCOPE(vm);
2193     
2194     if (!Options::useWebAssembly())
2195         return throwVMTypeError(exec, scope, "WebAssemblyMemoryMode should only be called if the useWebAssembly option is set"_s);
2196
2197     if (JSObject* object = exec->argument(0).getObject()) {
2198         if (auto* memory = jsDynamicCast<JSWebAssemblyMemory*>(vm, object))
2199             return JSValue::encode(jsString(&vm, makeString(memory->memory().mode())));
2200         if (auto* instance = jsDynamicCast<JSWebAssemblyInstance*>(vm, object))
2201             return JSValue::encode(jsString(&vm, makeString(instance->memoryMode())));
2202     }
2203
2204     return throwVMTypeError(exec, scope, "WebAssemblyMemoryMode expects either a WebAssembly.Memory or WebAssembly.Instance"_s);
2205 }
2206
2207 #endif // ENABLE(WEBASSEMBLY)
2208
2209 // Use SEH for Release builds only to get rid of the crash report dialog
2210 // (luckily the same tests fail in Release and Debug builds so far). Need to
2211 // be in a separate main function because the jscmain function requires object
2212 // unwinding.
2213
2214 #if COMPILER(MSVC) && !defined(_DEBUG)
2215 #define TRY       __try {
2216 #define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
2217 #else
2218 #define TRY
2219 #define EXCEPT(x)
2220 #endif
2221
2222 int jscmain(int argc, char** argv);
2223
2224 static double s_desiredTimeout;
2225 static double s_timeoutMultiplier = 1.0;
2226
2227 static void startTimeoutThreadIfNeeded()
2228 {
2229     if (char* timeoutString = getenv("JSCTEST_timeout")) {
2230         if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
2231             dataLog("WARNING: timeout string is malformed, got ", timeoutString,
2232                 " but expected a number. Not using a timeout.\n");
2233         } else {
2234             Thread::create("jsc Timeout Thread", [] () {
2235                 Seconds timeoutDuration(s_desiredTimeout * s_timeoutMultiplier);
2236                 sleep(timeoutDuration);
2237                 dataLog("Timed out after ", timeoutDuration, " seconds!\n");
2238                 CRASH();
2239             });
2240         }
2241     }
2242 }
2243
2244 int main(int argc, char** argv)
2245 {
2246 #if PLATFORM(IOS_FAMILY) && CPU(ARM_THUMB2)
2247     // Enabled IEEE754 denormal support.
2248     fenv_t env;
2249     fegetenv( &env );
2250     env.__fpscr &= ~0x01000000u;
2251     fesetenv( &env );
2252 #endif
2253
2254 #if OS(WINDOWS)
2255     // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
2256     // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
2257     // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
2258     ::SetErrorMode(0);
2259
2260     _setmode(_fileno(stdout), _O_BINARY);
2261     _setmode(_fileno(stderr), _O_BINARY);
2262
2263 #if defined(_DEBUG)
2264     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
2265     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2266     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
2267     _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
2268     _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
2269     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
2270 #endif
2271
2272     timeBeginPeriod(1);
2273 #endif
2274
2275 #if PLATFORM(GTK)
2276     if (!setlocale(LC_ALL, ""))
2277         WTFLogAlways("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
2278 #endif
2279
2280     // Need to initialize WTF threading before we start any threads. Cannot initialize JSC
2281     // threading yet, since that would do somethings that we'd like to defer until after we
2282     // have a chance to parse options.
2283     WTF::initializeThreading();
2284
2285 #if PLATFORM(IOS_FAMILY)
2286     Options::crashIfCantAllocateJITMemory() = true;
2287 #endif
2288
2289     // We can't use destructors in the following code because it uses Windows
2290     // Structured Exception Handling
2291     int res = 0;
2292     TRY
2293         res = jscmain(argc, argv);
2294     EXCEPT(res = 3)
2295     finalizeStatsAtEndOfTesting();
2296
2297     jscExit(res);
2298 }
2299
2300 static void dumpException(GlobalObject* globalObject, JSValue exception)
2301 {
2302     VM& vm = globalObject->vm();
2303     auto scope = DECLARE_CATCH_SCOPE(vm);
2304
2305 #define CHECK_EXCEPTION() do { \
2306         if (scope.exception()) { \
2307             scope.clearException(); \
2308             return; \
2309         } \
2310     } while (false)
2311
2312     auto exceptionString = exception.toWTFString(globalObject->globalExec());
2313     Expected<CString, UTF8ConversionError> expectedCString = exceptionString.tryGetUtf8();
2314     if (expectedCString)
2315         printf("Exception: %s\n", expectedCString.value().data());
2316     else
2317         printf("Exception: <out of memory while extracting exception string>\n");
2318
2319     Identifier nameID = Identifier::fromString(globalObject->globalExec(), "name");
2320     CHECK_EXCEPTION();
2321     Identifier fileNameID = Identifier::fromString(globalObject->globalExec(), "sourceURL");
2322     CHECK_EXCEPTION();
2323     Identifier lineNumberID = Identifier::fromString(globalObject->globalExec(), "line");
2324     CHECK_EXCEPTION();
2325     Identifier stackID = Identifier::fromString(globalObject->globalExec(), "stack");
2326     CHECK_EXCEPTION();
2327
2328     JSValue nameValue = exception.get(globalObject->globalExec(), nameID);
2329     CHECK_EXCEPTION();
2330     JSValue fileNameValue = exception.get(globalObject->globalExec(), fileNameID);
2331     CHECK_EXCEPTION();
2332     JSValue lineNumberValue = exception.get(globalObject->globalExec(), lineNumberID);
2333     CHECK_EXCEPTION();
2334     JSValue stackValue = exception.get(globalObject->globalExec(), stackID);
2335     CHECK_EXCEPTION();
2336     
2337     if (nameValue.toWTFString(globalObject->globalExec()) == "SyntaxError"
2338         && (!fileNameValue.isUndefinedOrNull() || !lineNumberValue.isUndefinedOrNull())) {
2339         printf(
2340             "at %s:%s\n",
2341             fileNameValue.toWTFString(globalObject->globalExec()).utf8().data(),
2342             lineNumberValue.toWTFString(globalObject->globalExec()).utf8().data());
2343     }
2344     
2345     if (!stackValue.isUndefinedOrNull()) {
2346         auto stackString = stackValue.toWTFString(globalObject->globalExec());
2347         if (stackString.length())
2348             printf("%s\n", stackString.utf8().data());
2349     }
2350
2351 #undef CHECK_EXCEPTION
2352 }
2353
2354 static bool checkUncaughtException(VM& vm, GlobalObject* globalObject, JSValue exception, CommandLine& options)
2355 {
2356     const String& expectedExceptionName = options.m_uncaughtExceptionName;
2357     auto scope = DECLARE_CATCH_SCOPE(vm);
2358     scope.clearException();
2359     if (!exception) {
2360         printf("Expected uncaught exception with name '%s' but none was thrown\n", expectedExceptionName.utf8().data());
2361         return false;
2362     }
2363
2364     ExecState* exec = globalObject->globalExec();
2365     JSValue exceptionClass = globalObject->get(exec, Identifier::fromString(exec, expectedExceptionName));
2366     if (!exceptionClass.isObject() || scope.exception()) {
2367         printf("Expected uncaught exception with name '%s' but given exception class is not defined\n", expectedExceptionName.utf8().data());
2368         return false;
2369     }
2370
2371     bool isInstanceOfExpectedException = jsCast<JSObject*>(exceptionClass)->hasInstance(exec, exception);
2372     if (scope.exception()) {
2373         printf("Expected uncaught exception with name '%s' but given exception class fails performing hasInstance\n", expectedExceptionName.utf8().data());
2374         return false;
2375     }
2376     if (isInstanceOfExpectedException) {
2377         if (options.m_alwaysDumpUncaughtException)
2378             dumpException(globalObject, exception);
2379         return true;
2380     }
2381
2382     printf("Expected uncaught exception with name '%s' but exception value is not instance of this exception class\n", expectedExceptionName.utf8().data());
2383     dumpException(globalObject, exception);
2384     return false;
2385 }
2386
2387 static void checkException(ExecState* exec, GlobalObject* globalObject, bool isLastFile, bool hasException, JSValue value, CommandLine& options, bool& success)
2388 {
2389     VM& vm = globalObject->vm();
2390
2391     if (options.m_treatWatchdogExceptionAsSuccess && value.inherits<TerminatedExecutionError>(vm)) {
2392         ASSERT(hasException);
2393         return;
2394     }
2395
2396     if (!options.m_uncaughtExceptionName || !isLastFile) {
2397         success = success && !hasException;
2398         if (options.m_dump && !hasException)
2399             printf("End: %s\n", value.toWTFString(exec).utf8().data());
2400         if (hasException)
2401             dumpException(globalObject, value);
2402     } else
2403         success = success && checkUncaughtException(vm, globalObject, (hasException) ? value : JSValue(), options);
2404 }
2405
2406 static void runWithOptions(GlobalObject* globalObject, CommandLine& options, bool& success)
2407 {
2408     Vector<Script>& scripts = options.m_scripts;
2409     String fileName;
2410     Vector<char> scriptBuffer;
2411
2412     if (options.m_dump)
2413         JSC::Options::dumpGeneratedBytecodes() = true;
2414
2415     VM& vm = globalObject->vm();
2416     auto scope = DECLARE_CATCH_SCOPE(vm);
2417
2418 #if ENABLE(SAMPLING_FLAGS)
2419     SamplingFlags::start();
2420 #endif
2421
2422     for (size_t i = 0; i < scripts.size(); i++) {
2423         JSInternalPromise* promise = nullptr;
2424         bool isModule = options.m_module || scripts[i].scriptType == Script::ScriptType::Module;
2425         if (scripts[i].codeSource == Script::CodeSource::File) {
2426             fileName = scripts[i].argument;
2427             if (scripts[i].strictMode == Script::StrictMode::Strict)
2428                 scriptBuffer.append("\"use strict\";\n", strlen("\"use strict\";\n"));
2429
2430             if (isModule) {
2431                 promise = loadAndEvaluateModule(globalObject->globalExec(), fileName, jsUndefined(), jsUndefined());
2432                 scope.releaseAssertNoException();
2433             } else {
2434                 if (!fetchScriptFromLocalFileSystem(fileName, scriptBuffer)) {
2435                     success = false; // fail early so we can catch missing files
2436                     return;
2437                 }
2438             }
2439         } else {
2440             size_t commandLineLength = strlen(scripts[i].argument);
2441             scriptBuffer.resize(commandLineLength);
2442             std::copy(scripts[i].argument, scripts[i].argument + commandLineLength, scriptBuffer.begin());
2443             fileName = "[Command Line]"_s;
2444         }
2445
2446         bool isLastFile = i == scripts.size() - 1;
2447         if (isModule) {
2448             if (!promise) {
2449                 // FIXME: This should use an absolute file URL https://bugs.webkit.org/show_bug.cgi?id=193077
2450                 promise = loadAndEvaluateModule(globalObject->globalExec(), makeSource(stringFromUTF(scriptBuffer), SourceOrigin { absolutePath(fileName) }, URL({ }, fileName), TextPosition(), SourceProviderSourceType::Module), jsUndefined());
2451             }
2452             scope.clearException();
2453
2454             JSFunction* fulfillHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&success, &options, isLastFile](ExecState* exec) {
2455                 checkException(exec, jsCast<GlobalObject*>(exec->lexicalGlobalObject()), isLastFile, false, exec->argument(0), options, success);
2456                 return JSValue::encode(jsUndefined());
2457             });
2458
2459             JSFunction* rejectHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&success, &options, isLastFile](ExecState* exec) {
2460                 checkException(exec, jsCast<GlobalObject*>(exec->lexicalGlobalObject()), isLastFile, true, exec->argument(0), options, success);
2461                 return JSValue::encode(jsUndefined());
2462             });
2463
2464             promise->then(globalObject->globalExec(), fulfillHandler, rejectHandler);
2465             scope.releaseAssertNoException();
2466             vm.drainMicrotasks();
2467         } else {
2468             NakedPtr<Exception> evaluationException;
2469             JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(scriptBuffer, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
2470             scope.assertNoException();
2471             if (evaluationException)
2472                 returnValue = evaluationException->value();
2473             checkException(globalObject->globalExec(), globalObject, isLastFile, evaluationException, returnValue, options, success);
2474         }
2475
2476         scriptBuffer.clear();
2477         scope.clearException();
2478     }
2479
2480 #if ENABLE(REGEXP_TRACING)
2481     vm.dumpRegExpTrace();
2482 #endif
2483 }
2484
2485 #define RUNNING_FROM_XCODE 0
2486
2487 static void runInteractive(GlobalObject* globalObject)
2488 {
2489     VM& vm = globalObject->vm();
2490     auto scope = DECLARE_CATCH_SCOPE(vm);
2491
2492     Optional<DirectoryName> directoryName = currentWorkingDirectory();
2493     if (!directoryName)
2494         return;
2495     SourceOrigin sourceOrigin(resolvePath(directoryName.value(), ModuleName("interpreter")));
2496     
2497     bool shouldQuit = false;
2498     while (!shouldQuit) {
2499 #if HAVE(READLINE) && !RUNNING_FROM_XCODE
2500         ParserError error;
2501         String source;
2502         do {
2503             error = ParserError();
2504             char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
2505             shouldQuit = !line;
2506             if (!line)
2507                 break;
2508             source = source + String::fromUTF8(line);
2509             source = source + '\n';
2510             checkSyntax(vm, makeSource(source, sourceOrigin), error);
2511             if (!line[0]) {
2512                 free(line);
2513                 break;
2514             }
2515             add_history(line);
2516             free(line);
2517         } while (error.syntaxErrorType() == ParserError::SyntaxErrorRecoverable);
2518         
2519         if (error.isValid()) {
2520             printf("%s:%d\n", error.message().utf8().data(), error.line());
2521             continue;
2522         }
2523         
2524         
2525         NakedPtr<Exception> evaluationException;
2526         JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, sourceOrigin), JSValue(), evaluationException);
2527 #else
2528         printf("%s", interactivePrompt);
2529         Vector<char, 256> line;
2530         int c;
2531         while ((c = getchar()) != EOF) {
2532             // FIXME: Should we also break on \r? 
2533             if (c == '\n')
2534                 break;
2535             line.append(c);
2536         }
2537         if (line.isEmpty())
2538             break;
2539
2540         NakedPtr<Exception> evaluationException;
2541         JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line, sourceOrigin, sourceOrigin.string()), JSValue(), evaluationException);
2542 #endif
2543         if (evaluationException)
2544             printf("Exception: %s\n", evaluationException->value().toWTFString(globalObject->globalExec()).utf8().data());
2545         else
2546             printf("%s\n", returnValue.toWTFString(globalObject->globalExec()).utf8().data());
2547
2548         scope.clearException();
2549         vm.drainMicrotasks();
2550     }
2551     printf("\n");
2552 }
2553
2554 static NO_RETURN void printUsageStatement(bool help = false)
2555 {
2556     fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
2557     fprintf(stderr, "  -d         Dumps bytecode (debug builds only)\n");
2558     fprintf(stderr, "  -e         Evaluate argument as script code\n");
2559     fprintf(stderr, "  -f         Specifies a source file (deprecated)\n");
2560     fprintf(stderr, "  -h|--help  Prints this help message\n");
2561     fprintf(stderr, "  -i         Enables interactive mode (default if no files are specified)\n");
2562     fprintf(stderr, "  -m         Execute as a module\n");
2563 #if HAVE(SIGNAL_H)
2564     fprintf(stderr, "  -s         Installs signal handlers that exit on a crash (Unix platforms only)\n");
2565 #endif
2566     fprintf(stderr, "  -p <file>  Outputs profiling data to a file\n");
2567     fprintf(stderr, "  -x         Output exit code before terminating\n");
2568     fprintf(stderr, "\n");
2569     fprintf(stderr, "  --sample                   Collects and outputs sampling profiler data\n");
2570     fprintf(stderr, "  --test262-async            Check that some script calls the print function with the string 'Test262:AsyncTestComplete'\n");
2571     fprintf(stderr, "  --strict-file=<file>       Parse the given file as if it were in strict mode (this option may be passed more than once)\n");
2572     fprintf(stderr, "  --module-file=<file>       Parse and evaluate the given file as module (this option may be passed more than once)\n");
2573     fprintf(stderr, "  --exception=<name>         Check the last script exits with an uncaught exception with the specified name\n");
2574     fprintf(stderr, "  --watchdog-exception-ok    Uncaught watchdog exceptions exit with success\n");
2575     fprintf(stderr, "  --dumpException            Dump uncaught exception text\n");
2576     fprintf(stderr, "  --footprint                Dump memory footprint after done executing\n");
2577     fprintf(stderr, "  --options                  Dumps all JSC VM options and exits\n");
2578     fprintf(stderr, "  --dumpOptions              Dumps all non-default JSC VM options before continuing\n");
2579     fprintf(stderr, "  --<jsc VM option>=<value>  Sets the specified JSC VM option\n");
2580     fprintf(stderr, "\n");
2581     fprintf(stderr, "Files with a .mjs extension will always be evaluated as modules.\n");
2582     fprintf(stderr, "\n");
2583
2584     jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
2585 }
2586
2587 static bool isMJSFile(char *filename)
2588 {
2589     filename = strrchr(filename, '.');
2590
2591     if (filename)
2592         return !strcmp(filename, ".mjs");
2593
2594     return false;
2595 }
2596
2597 void CommandLine::parseArguments(int argc, char** argv)
2598 {
2599     Options::initialize();
2600     
2601     if (Options::dumpOptions()) {
2602         printf("Command line:");
2603 #if PLATFORM(COCOA)
2604         for (char** envp = *_NSGetEnviron(); *envp; envp++) {
2605             const char* env = *envp;
2606             if (!strncmp("JSC_", env, 4))
2607                 printf(" %s", env);
2608         }
2609 #endif // PLATFORM(COCOA)
2610         for (int i = 0; i < argc; ++i)
2611             printf(" %s", argv[i]);
2612         printf("\n");
2613     }
2614
2615     int i = 1;
2616     JSC::Options::DumpLevel dumpOptionsLevel = JSC::Options::DumpLevel::None;
2617     bool needToExit = false;
2618
2619     bool hasBadJSCOptions = false;
2620     for (; i < argc; ++i) {
2621         const char* arg = argv[i];
2622         if (!strcmp(arg, "-f")) {
2623             if (++i == argc)
2624                 printUsageStatement();
2625             m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Script, argv[i]));
2626             continue;
2627         }
2628         if (!strcmp(arg, "-e")) {
2629             if (++i == argc)
2630                 printUsageStatement();
2631             m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::CommandLine, Script::ScriptType::Script, argv[i]));
2632             continue;
2633         }
2634         if (!strcmp(arg, "-i")) {
2635             m_interactive = true;
2636             continue;
2637         }
2638         if (!strcmp(arg, "-d")) {
2639             m_dump = true;
2640             continue;
2641         }
2642         if (!strcmp(arg, "-p")) {
2643             if (++i == argc)
2644                 printUsageStatement();
2645             m_profile = true;
2646             m_profilerOutput = argv[i];
2647             continue;
2648         }
2649         if (!strcmp(arg, "-m")) {
2650             m_module = true;
2651             continue;
2652         }
2653         if (!strcmp(arg, "-s")) {
2654 #if HAVE(SIGNAL_H)
2655             signal(SIGILL, _exit);
2656             signal(SIGFPE, _exit);
2657             signal(SIGBUS, _exit);
2658             signal(SIGSEGV, _exit);
2659 #endif
2660             continue;
2661         }
2662         if (!strcmp(arg, "-x")) {
2663             m_exitCode = true;
2664             continue;
2665         }
2666         if (!strcmp(arg, "--")) {
2667             ++i;
2668             break;
2669         }
2670         if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
2671             printUsageStatement(true);
2672
2673         if (!strcmp(arg, "--options")) {
2674             dumpOptionsLevel = JSC::Options::DumpLevel::Verbose;
2675             needToExit = true;
2676             continue;
2677         }
2678         if (!strcmp(arg, "--dumpOptions")) {
2679             dumpOptionsLevel = JSC::Options::DumpLevel::Overridden;
2680             continue;
2681         }
2682         if (!strcmp(arg, "--sample")) {
2683             JSC::Options::useSamplingProfiler() = true;
2684             JSC::Options::collectSamplingProfilerDataForJSCShell() = true;
2685             m_dumpSamplingProfilerData = true;
2686             continue;
2687         }
2688
2689         static const char* timeoutMultiplierOptStr = "--timeoutMultiplier=";
2690         static const unsigned timeoutMultiplierOptStrLength = strlen(timeoutMultiplierOptStr);
2691         if (!strncmp(arg, timeoutMultiplierOptStr, timeoutMultiplierOptStrLength)) {
2692             const char* valueStr = &arg[timeoutMultiplierOptStrLength];
2693             if (sscanf(valueStr, "%lf", &s_timeoutMultiplier) != 1)
2694                 dataLog("WARNING: --timeoutMultiplier=", valueStr, " is invalid. Expects a numeric ratio.\n");
2695             continue;
2696         }
2697
2698         if (!strcmp(arg, "--test262-async")) {
2699             asyncTestExpectedPasses++;
2700             continue;
2701         }
2702
2703         if (!strcmp(arg, "--remote-debug")) {
2704             m_enableRemoteDebugging = true;
2705             continue;
2706         }
2707
2708         static const unsigned strictFileStrLength = strlen("--strict-file=");
2709         if (!strncmp(arg, "--strict-file=", strictFileStrLength)) {
2710             m_scripts.append(Script(Script::StrictMode::Strict, Script::CodeSource::File, Script::ScriptType::Script, argv[i] + strictFileStrLength));
2711             continue;
2712         }
2713
2714         static const unsigned moduleFileStrLength = strlen("--module-file=");
2715         if (!strncmp(arg, "--module-file=", moduleFileStrLength)) {
2716             m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Module, argv[i] + moduleFileStrLength));
2717             continue;
2718         }
2719
2720         if (!strcmp(arg, "--dumpException")) {
2721             m_alwaysDumpUncaughtException = true;
2722             continue;
2723         }
2724
2725         if (!strcmp(arg, "--footprint")) {
2726             m_dumpMemoryFootprint = true;
2727             continue;
2728         }
2729
2730         static const unsigned exceptionStrLength = strlen("--exception=");
2731         if (!strncmp(arg, "--exception=", exceptionStrLength)) {
2732             m_uncaughtExceptionName = String(arg + exceptionStrLength);
2733             continue;
2734         }
2735
2736         if (!strcmp(arg, "--watchdog-exception-ok")) {
2737             m_treatWatchdogExceptionAsSuccess = true;
2738             continue;
2739         }
2740
2741         // See if the -- option is a JSC VM option.
2742         if (strstr(arg, "--") == arg) {
2743             if (!JSC::Options::setOption(&arg[2])) {
2744                 hasBadJSCOptions = true;
2745                 dataLog("ERROR: invalid option: ", arg, "\n");
2746             }
2747             continue;
2748         }
2749
2750         // This arg is not recognized by the VM nor by jsc. Pass it on to the
2751         // script.
2752         Script::ScriptType scriptType = isMJSFile(argv[i]) ? Script::ScriptType::Module : Script::ScriptType::Script;
2753         m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, scriptType, argv[i]));
2754     }
2755
2756     if (hasBadJSCOptions && JSC::Options::validateOptions())
2757         CRASH();
2758
2759     if (m_scripts.isEmpty())
2760         m_interactive = true;
2761
2762     for (; i < argc; ++i)
2763         m_arguments.append(argv[i]);
2764
2765     if (dumpOptionsLevel != JSC::Options::DumpLevel::None) {
2766         const char* optionsTitle = (dumpOptionsLevel == JSC::Options::DumpLevel::Overridden)
2767             ? "Modified JSC runtime options:"
2768             : "All JSC runtime options:";
2769         JSC::Options::dumpAllOptions(stderr, dumpOptionsLevel, optionsTitle);
2770     }
2771     JSC::Options::ensureOptionsAreCoherent();
2772     if (needToExit)
2773         jscExit(EXIT_SUCCESS);
2774 }
2775
2776 template<typename Func>
2777 int runJSC(const CommandLine& options, bool isWorker, const Func& func)
2778 {
2779     Worker worker(Workers::singleton());
2780     
2781     VM& vm = VM::create(LargeHeap).leakRef();
2782     int result;
2783     bool success = true;
2784     GlobalObject* globalObject = nullptr;
2785     {
2786         JSLockHolder locker(vm);
2787
2788         if (options.m_profile && !vm.m_perBytecodeProfiler)
2789             vm.m_perBytecodeProfiler = std::make_unique<Profiler::Database>(vm);
2790
2791         globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), options.m_arguments);
2792         globalObject->setRemoteDebuggingEnabled(options.m_enableRemoteDebugging);
2793         func(vm, globalObject, success);
2794         vm.drainMicrotasks();
2795     }
2796     vm.promiseDeferredTimer->runRunLoop();
2797     {
2798         JSLockHolder locker(vm);
2799         if (options.m_interactive && success)
2800             runInteractive(globalObject);
2801     }
2802
2803     result = success && (asyncTestExpectedPasses == asyncTestPasses) ? 0 : 3;
2804
2805     if (options.m_exitCode) {
2806         printf("jsc exiting %d", result);
2807         if (asyncTestExpectedPasses != asyncTestPasses)
2808             printf(" because expected: %d async test passes but got: %d async test passes", asyncTestExpectedPasses, asyncTestPasses);
2809         printf("\n");
2810     }
2811
2812     if (options.m_profile) {
2813         JSLockHolder locker(vm);
2814         if (!vm.m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
2815             fprintf(stderr, "could not save profiler output.\n");
2816     }
2817
2818 #if ENABLE(JIT)
2819     {
2820         JSLockHolder locker(vm);
2821         if (Options::useExceptionFuzz())
2822             printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
2823         bool fireAtEnabled =
2824         Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
2825         if (Options::useExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
2826             printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks());
2827         if (Options::useOSRExitFuzz()) {
2828             printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks());
2829             printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks());
2830         }
2831
2832         
2833         auto compileTimeStats = JIT::compileTimeStats();
2834         Vector<CString> compileTimeKeys;
2835         for (auto& entry : compileTimeStats)
2836             compileTimeKeys.append(entry.key);
2837         std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
2838         for (const CString& key : compileTimeKeys)
2839             printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key).milliseconds());
2840     }
2841 #endif
2842
2843     if (Options::gcAtEnd()) {
2844         // We need to hold the API lock to do a GC.
2845         JSLockHolder locker(&vm);
2846         vm.heap.collectNow(Sync, CollectionScope::Full);
2847     }
2848
2849     if (options.m_dumpSamplingProfilerData) {
2850 #if ENABLE(SAMPLING_PROFILER)
2851         JSLockHolder locker(&vm);
2852         vm.samplingProfiler()->reportTopFunctions();
2853         vm.samplingProfiler()->reportTopBytecodes();
2854 #else
2855         dataLog("Sampling profiler is not enabled on this platform\n");
2856 #endif
2857     }
2858
2859     if (isWorker) {
2860         JSLockHolder locker(vm);
2861         // This is needed because we don't want the worker's main
2862         // thread to die before its compilation threads finish.
2863         vm.deref();
2864     }
2865
2866     return result;
2867 }
2868
2869 int jscmain(int argc, char** argv)
2870 {
2871     // Need to override and enable restricted options before we start parsing options below.
2872     Options::enableRestrictedOptions(true);
2873
2874     // Note that the options parsing can affect VM creation, and thus
2875     // comes first.
2876     CommandLine options(argc, argv);
2877
2878     processConfigFile(Options::configFile(), "jsc");
2879
2880     // Initialize JSC before getting VM.
2881     WTF::initializeMainThread();
2882     JSC::initializeThreading();
2883     startTimeoutThreadIfNeeded();
2884 #if ENABLE(WEBASSEMBLY)
2885     JSC::Wasm::enableFastMemory();
2886 #endif
2887     Gigacage::disableDisablingPrimitiveGigacageIfShouldBeEnabled();
2888
2889 #if PLATFORM(COCOA)
2890     auto& memoryPressureHandler = MemoryPressureHandler::singleton();
2891     {
2892         dispatch_queue_t queue = dispatch_queue_create("jsc shell memory pressure handler", DISPATCH_QUEUE_SERIAL);
2893         memoryPressureHandler.setDispatchQueue(queue);
2894         dispatch_release(queue);
2895     }
2896     Box<Critical> memoryPressureCriticalState = Box<Critical>::create(Critical::No);
2897     Box<Synchronous> memoryPressureSynchronousState = Box<Synchronous>::create(Synchronous::No);
2898     memoryPressureHandler.setLowMemoryHandler([=] (Critical critical, Synchronous synchronous) {
2899         // We set these racily with respect to reading them from the JS execution thread.
2900         *memoryPressureCriticalState = critical;
2901         *memoryPressureSynchronousState = synchronous;
2902     });
2903     memoryPressureHandler.setShouldLogMemoryMemoryPressureEvents(false);
2904     memoryPressureHandler.install();
2905
2906     auto onEachMicrotaskTick = [&] (VM& vm) {
2907         if (*memoryPressureCriticalState == Critical::No)
2908             return;
2909
2910         *memoryPressureCriticalState = Critical::No;
2911         bool isSynchronous = *memoryPressureSynchronousState == Synchronous::Yes;
2912
2913         WTF::releaseFastMallocFreeMemory();
2914         vm.deleteAllCode(DeleteAllCodeIfNotCollecting);
2915
2916         if (!vm.heap.isCurrentThreadBusy()) {
2917             if (isSynchronous) {
2918                 vm.heap.collectNow(Sync, CollectionScope::Full);
2919                 WTF::releaseFastMallocFreeMemory();
2920             } else
2921                 vm.heap.collectNowFullIfNotDoneRecently(Async);
2922         }
2923     };
2924 #endif
2925
2926     int result = runJSC(
2927         options, false,
2928         [&] (VM& vm, GlobalObject* globalObject, bool& success) {
2929             UNUSED_PARAM(vm);
2930 #if PLATFORM(COCOA)
2931             vm.setOnEachMicrotaskTick(WTFMove(onEachMicrotaskTick));
2932 #endif
2933             runWithOptions(globalObject, options, success);
2934         });
2935
2936     printSuperSamplerState();
2937
2938     if (options.m_dumpMemoryFootprint) {
2939         MemoryFootprint footprint = MemoryFootprint::now();
2940
2941         printf("Memory Footprint:\n    Current Footprint: %" PRIu64 "\n    Peak Footprint: %" PRIu64 "\n", footprint.current, footprint.peak);
2942     }
2943
2944     return result;
2945 }
2946
2947 #if OS(WINDOWS)
2948 extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
2949 {
2950     return main(argc, const_cast<char**>(argv));
2951 }
2952 #endif