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