REGRESSION (r215843): ASSERTION FAILED: !m_completionTasks[0].first in JSC::Wasm...
[WebKit-https.git] / Source / JavaScriptCore / jsc.cpp
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2004-2017 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 "BuiltinExecutableCreator.h"
28 #include "BuiltinNames.h"
29 #include "ButterflyInlines.h"
30 #include "CodeBlock.h"
31 #include "Completion.h"
32 #include "ConfigFile.h"
33 #include "DOMJITGetterSetter.h"
34 #include "DOMJITPatchpoint.h"
35 #include "DOMJITPatchpointParams.h"
36 #include "Disassembler.h"
37 #include "Exception.h"
38 #include "ExceptionHelpers.h"
39 #include "GetterSetter.h"
40 #include "HeapProfiler.h"
41 #include "HeapSnapshotBuilder.h"
42 #include "InitializeThreading.h"
43 #include "Interpreter.h"
44 #include "JIT.h"
45 #include "JSArray.h"
46 #include "JSArrayBuffer.h"
47 #include "JSCInlines.h"
48 #include "JSFunction.h"
49 #include "JSInternalPromise.h"
50 #include "JSInternalPromiseDeferred.h"
51 #include "JSLock.h"
52 #include "JSModuleLoader.h"
53 #include "JSNativeStdFunction.h"
54 #include "JSONObject.h"
55 #include "JSProxy.h"
56 #include "JSSourceCode.h"
57 #include "JSString.h"
58 #include "JSTypedArrays.h"
59 #include "JSWebAssemblyInstance.h"
60 #include "JSWebAssemblyMemory.h"
61 #include "LLIntData.h"
62 #include "LLIntThunks.h"
63 #include "ObjectConstructor.h"
64 #include "ParserError.h"
65 #include "ProfilerDatabase.h"
66 #include "PromiseDeferredTimer.h"
67 #include "ProtoCallFrame.h"
68 #include "ReleaseHeapAccessScope.h"
69 #include "SamplingProfiler.h"
70 #include "ShadowChicken.h"
71 #include "StackVisitor.h"
72 #include "StructureInlines.h"
73 #include "StructureRareDataInlines.h"
74 #include "SuperSampler.h"
75 #include "TestRunnerUtils.h"
76 #include "TypeProfilerLog.h"
77 #include "WasmBBQPlanInlines.h"
78 #include "WasmCallee.h"
79 #include "WasmContext.h"
80 #include "WasmFaultSignalHandler.h"
81 #include "WasmMemory.h"
82 #include "WasmWorklist.h"
83 #include <locale.h>
84 #include <math.h>
85 #include <stdio.h>
86 #include <stdlib.h>
87 #include <string.h>
88 #include <thread>
89 #include <type_traits>
90 #include <wtf/CommaPrinter.h>
91 #include <wtf/CurrentTime.h>
92 #include <wtf/MainThread.h>
93 #include <wtf/NeverDestroyed.h>
94 #include <wtf/StringPrintStream.h>
95 #include <wtf/text/StringBuilder.h>
96
97 #if OS(WINDOWS)
98 #include <direct.h>
99 #else
100 #include <unistd.h>
101 #endif
102
103 #if HAVE(READLINE)
104 // readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
105 // We #define it to something else to avoid this conflict.
106 #define Function ReadlineFunction
107 #include <readline/history.h>
108 #include <readline/readline.h>
109 #undef Function
110 #endif
111
112 #if HAVE(SYS_TIME_H)
113 #include <sys/time.h>
114 #endif
115
116 #if HAVE(SIGNAL_H)
117 #include <signal.h>
118 #endif
119
120 #if COMPILER(MSVC)
121 #include <crtdbg.h>
122 #include <mmsystem.h>
123 #include <windows.h>
124 #endif
125
126 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
127 #include <fenv.h>
128 #include <arm/arch.h>
129 #endif
130
131 #if !defined(PATH_MAX)
132 #define PATH_MAX 4096
133 #endif
134
135 using namespace JSC;
136 using namespace WTF;
137
138 namespace {
139
140 NO_RETURN_WITH_VALUE static void jscExit(int status)
141 {
142     waitForAsynchronousDisassembly();
143     
144 #if ENABLE(DFG_JIT)
145     if (DFG::isCrashing()) {
146         for (;;) {
147 #if OS(WINDOWS)
148             Sleep(1000);
149 #else
150             pause();
151 #endif
152         }
153     }
154 #endif // ENABLE(DFG_JIT)
155     exit(status);
156 }
157
158 class Element;
159 class ElementHandleOwner;
160 class Masuqerader;
161 class Root;
162 class RuntimeArray;
163
164 class Element : public JSNonFinalObject {
165 public:
166     Element(VM& vm, Structure* structure)
167         : Base(vm, structure)
168     {
169     }
170
171     typedef JSNonFinalObject Base;
172
173     Root* root() const { return m_root.get(); }
174     void setRoot(VM& vm, Root* root) { m_root.set(vm, this, root); }
175
176     static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root)
177     {
178         Structure* structure = createStructure(vm, globalObject, jsNull());
179         Element* element = new (NotNull, allocateCell<Element>(vm.heap, sizeof(Element))) Element(vm, structure);
180         element->finishCreation(vm, root);
181         return element;
182     }
183
184     void finishCreation(VM&, Root*);
185
186     static void visitChildren(JSCell* cell, SlotVisitor& visitor)
187     {
188         Element* thisObject = jsCast<Element*>(cell);
189         ASSERT_GC_OBJECT_INHERITS(thisObject, info());
190         Base::visitChildren(thisObject, visitor);
191         visitor.append(thisObject->m_root);
192     }
193
194     static ElementHandleOwner* handleOwner();
195
196     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
197     {
198         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
199     }
200
201     DECLARE_INFO;
202
203 private:
204     WriteBarrier<Root> m_root;
205 };
206
207 class ElementHandleOwner : public WeakHandleOwner {
208 public:
209     bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor) override
210     {
211         Element* element = jsCast<Element*>(handle.slot()->asCell());
212         return visitor.containsOpaqueRoot(element->root());
213     }
214 };
215
216 class Masquerader : public JSNonFinalObject {
217 public:
218     Masquerader(VM& vm, Structure* structure)
219         : Base(vm, structure)
220     {
221     }
222
223     typedef JSNonFinalObject Base;
224     static const unsigned StructureFlags = Base::StructureFlags | JSC::MasqueradesAsUndefined;
225
226     static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
227     {
228         globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(vm, "Masquerading object allocated");
229         Structure* structure = createStructure(vm, globalObject, jsNull());
230         Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
231         result->finishCreation(vm);
232         return result;
233     }
234
235     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
236     {
237         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
238     }
239
240     DECLARE_INFO;
241 };
242
243 class Root : public JSDestructibleObject {
244 public:
245     Root(VM& vm, Structure* structure)
246         : Base(vm, structure)
247     {
248     }
249
250     Element* element()
251     {
252         return m_element.get();
253     }
254
255     void setElement(Element* element)
256     {
257         Weak<Element> newElement(element, Element::handleOwner());
258         m_element.swap(newElement);
259     }
260
261     static Root* create(VM& vm, JSGlobalObject* globalObject)
262     {
263         Structure* structure = createStructure(vm, globalObject, jsNull());
264         Root* root = new (NotNull, allocateCell<Root>(vm.heap, sizeof(Root))) Root(vm, structure);
265         root->finishCreation(vm);
266         return root;
267     }
268
269     typedef JSDestructibleObject Base;
270
271     DECLARE_INFO;
272
273     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
274     {
275         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
276     }
277
278     static void visitChildren(JSCell* thisObject, SlotVisitor& visitor)
279     {
280         Base::visitChildren(thisObject, visitor);
281         visitor.addOpaqueRoot(thisObject);
282     }
283
284 private:
285     Weak<Element> m_element;
286 };
287
288 class ImpureGetter : public JSNonFinalObject {
289 public:
290     ImpureGetter(VM& vm, Structure* structure)
291         : Base(vm, structure)
292     {
293     }
294
295     DECLARE_INFO;
296     typedef JSNonFinalObject Base;
297     static const unsigned StructureFlags = Base::StructureFlags | JSC::GetOwnPropertySlotIsImpure | JSC::OverridesGetOwnPropertySlot;
298
299     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
300     {
301         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
302     }
303
304     static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate)
305     {
306         ImpureGetter* getter = new (NotNull, allocateCell<ImpureGetter>(vm.heap, sizeof(ImpureGetter))) ImpureGetter(vm, structure);
307         getter->finishCreation(vm, delegate);
308         return getter;
309     }
310
311     void finishCreation(VM& vm, JSObject* delegate)
312     {
313         Base::finishCreation(vm);
314         if (delegate)
315             m_delegate.set(vm, this, delegate);
316     }
317
318     static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot)
319     {
320         VM& vm = exec->vm();
321         auto scope = DECLARE_THROW_SCOPE(vm);
322         ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
323         
324         if (thisObject->m_delegate) {
325             if (thisObject->m_delegate->getPropertySlot(exec, name, slot))
326                 return true;
327             RETURN_IF_EXCEPTION(scope, false);
328         }
329
330         return Base::getOwnPropertySlot(object, exec, name, slot);
331     }
332
333     static void visitChildren(JSCell* cell, SlotVisitor& visitor)
334     {
335         Base::visitChildren(cell, visitor);
336         ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
337         visitor.append(thisObject->m_delegate);
338     }
339
340     void setDelegate(VM& vm, JSObject* delegate)
341     {
342         m_delegate.set(vm, this, delegate);
343     }
344
345 private:
346     WriteBarrier<JSObject> m_delegate;
347 };
348
349 class CustomGetter : public JSNonFinalObject {
350 public:
351     CustomGetter(VM& vm, Structure* structure)
352         : Base(vm, structure)
353     {
354     }
355
356     DECLARE_INFO;
357     typedef JSNonFinalObject Base;
358     static const unsigned StructureFlags = Base::StructureFlags | JSC::OverridesGetOwnPropertySlot;
359
360     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
361     {
362         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
363     }
364
365     static CustomGetter* create(VM& vm, Structure* structure)
366     {
367         CustomGetter* getter = new (NotNull, allocateCell<CustomGetter>(vm.heap, sizeof(CustomGetter))) CustomGetter(vm, structure);
368         getter->finishCreation(vm);
369         return getter;
370     }
371
372     static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
373     {
374         CustomGetter* thisObject = jsCast<CustomGetter*>(object);
375         if (propertyName == PropertyName(Identifier::fromString(exec, "customGetter"))) {
376             slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->customGetter);
377             return true;
378         }
379         
380         if (propertyName == PropertyName(Identifier::fromString(exec, "customGetterAccessor"))) {
381             slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum | CustomAccessor, thisObject->customGetterAcessor);
382             return true;
383         }
384         
385         return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
386     }
387
388 private:
389     static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
390     {
391         VM& vm = exec->vm();
392         auto scope = DECLARE_THROW_SCOPE(vm);
393
394         CustomGetter* thisObject = jsDynamicCast<CustomGetter*>(vm, JSValue::decode(thisValue));
395         if (!thisObject)
396             return throwVMTypeError(exec, scope);
397         bool shouldThrow = thisObject->get(exec, PropertyName(Identifier::fromString(exec, "shouldThrow"))).toBoolean(exec);
398         RETURN_IF_EXCEPTION(scope, encodedJSValue());
399         if (shouldThrow)
400             return throwVMTypeError(exec, scope);
401         return JSValue::encode(jsNumber(100));
402     }
403     
404     static EncodedJSValue customGetterAcessor(ExecState* exec, EncodedJSValue thisValue, PropertyName)
405     {
406         VM& vm = exec->vm();
407         auto scope = DECLARE_THROW_SCOPE(vm);
408         
409         JSObject* thisObject = jsDynamicCast<JSObject*>(vm, JSValue::decode(thisValue));
410         if (!thisObject)
411             return throwVMTypeError(exec, scope);
412         bool shouldThrow = thisObject->get(exec, PropertyName(Identifier::fromString(exec, "shouldThrow"))).toBoolean(exec);
413         if (shouldThrow)
414             return throwVMTypeError(exec, scope);
415         return JSValue::encode(jsNumber(100));
416     }
417 };
418
419 class RuntimeArray : public JSArray {
420 public:
421     typedef JSArray Base;
422     static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames;
423
424     static RuntimeArray* create(ExecState* exec)
425     {
426         VM& vm = exec->vm();
427         JSGlobalObject* globalObject = exec->lexicalGlobalObject();
428         Structure* structure = createStructure(vm, globalObject, createPrototype(vm, globalObject));
429         RuntimeArray* runtimeArray = new (NotNull, allocateCell<RuntimeArray>(*exec->heap())) RuntimeArray(exec, structure);
430         runtimeArray->finishCreation(exec);
431         vm.heap.addFinalizer(runtimeArray, destroy);
432         return runtimeArray;
433     }
434
435     ~RuntimeArray() { }
436
437     static void destroy(JSCell* cell)
438     {
439         static_cast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
440     }
441
442     static const bool needsDestruction = false;
443
444     static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
445     {
446         RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
447         if (propertyName == exec->propertyNames().length) {
448             slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->lengthGetter);
449             return true;
450         }
451
452         std::optional<uint32_t> index = parseIndex(propertyName);
453         if (index && index.value() < thisObject->getLength()) {
454             slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index.value()]));
455             return true;
456         }
457
458         return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
459     }
460
461     static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
462     {
463         RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
464         if (index < thisObject->getLength()) {
465             slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index]));
466             return true;
467         }
468
469         return JSObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot);
470     }
471
472     static NO_RETURN_DUE_TO_CRASH bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&)
473     {
474         RELEASE_ASSERT_NOT_REACHED();
475     }
476
477     static NO_RETURN_DUE_TO_CRASH bool deleteProperty(JSCell*, ExecState*, PropertyName)
478     {
479         RELEASE_ASSERT_NOT_REACHED();
480     }
481
482     unsigned getLength() const { return m_vector.size(); }
483
484     DECLARE_INFO;
485
486     static ArrayPrototype* createPrototype(VM&, JSGlobalObject* globalObject)
487     {
488         return globalObject->arrayPrototype();
489     }
490
491     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
492     {
493         return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
494     }
495
496 protected:
497     void finishCreation(ExecState* exec)
498     {
499         VM& vm = exec->vm();
500         Base::finishCreation(vm);
501         ASSERT(inherits(vm, info()));
502
503         for (size_t i = 0; i < exec->argumentCount(); i++)
504             m_vector.append(exec->argument(i).toInt32(exec));
505     }
506
507 private:
508     RuntimeArray(ExecState* exec, Structure* structure)
509         : JSArray(exec->vm(), structure, 0)
510     {
511     }
512
513     static EncodedJSValue lengthGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
514     {
515         VM& vm = exec->vm();
516         auto scope = DECLARE_THROW_SCOPE(vm);
517
518         RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(vm, JSValue::decode(thisValue));
519         if (!thisObject)
520             return throwVMTypeError(exec, scope);
521         return JSValue::encode(jsNumber(thisObject->getLength()));
522     }
523
524     Vector<int> m_vector;
525 };
526
527 class SimpleObject : public JSNonFinalObject {
528 public:
529     SimpleObject(VM& vm, Structure* structure)
530         : Base(vm, structure)
531     {
532     }
533
534     typedef JSNonFinalObject Base;
535     static const bool needsDestruction = false;
536
537     static SimpleObject* create(VM& vm, JSGlobalObject* globalObject)
538     {
539         Structure* structure = createStructure(vm, globalObject, jsNull());
540         SimpleObject* simpleObject = new (NotNull, allocateCell<SimpleObject>(vm.heap, sizeof(SimpleObject))) SimpleObject(vm, structure);
541         simpleObject->finishCreation(vm);
542         return simpleObject;
543     }
544
545     static void visitChildren(JSCell* cell, SlotVisitor& visitor)
546     {
547         SimpleObject* thisObject = jsCast<SimpleObject*>(cell);
548         ASSERT_GC_OBJECT_INHERITS(thisObject, info());
549         Base::visitChildren(thisObject, visitor);
550         visitor.append(thisObject->m_hiddenValue);
551     }
552
553     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
554     {
555         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
556     }
557
558     JSValue hiddenValue()
559     {
560         return m_hiddenValue.get();
561     }
562
563     void setHiddenValue(VM& vm, JSValue value)
564     {
565         ASSERT(value.isCell());
566         m_hiddenValue.set(vm, this, value);
567     }
568
569     DECLARE_INFO;
570
571 private:
572     WriteBarrier<JSC::Unknown> m_hiddenValue;
573 };
574
575 class DOMJITNode : public JSNonFinalObject {
576 public:
577     DOMJITNode(VM& vm, Structure* structure)
578         : Base(vm, structure)
579     {
580     }
581
582     DECLARE_INFO;
583     typedef JSNonFinalObject Base;
584     static const unsigned StructureFlags = Base::StructureFlags;
585
586     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
587     {
588         return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
589     }
590
591 #if ENABLE(JIT)
592     static Ref<DOMJIT::Patchpoint> checkDOMJITNode()
593     {
594         Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
595         patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
596             CCallHelpers::JumpList failureCases;
597             failureCases.append(jit.branch8(
598                 CCallHelpers::NotEqual,
599                 CCallHelpers::Address(params[0].gpr(), JSCell::typeInfoTypeOffset()),
600                 CCallHelpers::TrustedImm32(JSC::JSType(LastJSCObjectType + 1))));
601             return failureCases;
602         });
603         return patchpoint;
604     }
605 #endif
606
607     static DOMJITNode* create(VM& vm, Structure* structure)
608     {
609         DOMJITNode* getter = new (NotNull, allocateCell<DOMJITNode>(vm.heap, sizeof(DOMJITNode))) DOMJITNode(vm, structure);
610         getter->finishCreation(vm);
611         return getter;
612     }
613
614     int32_t value() const
615     {
616         return m_value;
617     }
618
619     static ptrdiff_t offsetOfValue() { return OBJECT_OFFSETOF(DOMJITNode, m_value); }
620
621 private:
622     int32_t m_value { 42 };
623 };
624
625 class DOMJITGetter : public DOMJITNode {
626 public:
627     DOMJITGetter(VM& vm, Structure* structure)
628         : Base(vm, structure)
629     {
630     }
631
632     DECLARE_INFO;
633     typedef DOMJITNode Base;
634     static const unsigned StructureFlags = Base::StructureFlags;
635
636     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
637     {
638         return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
639     }
640
641     static DOMJITGetter* create(VM& vm, Structure* structure)
642     {
643         DOMJITGetter* getter = new (NotNull, allocateCell<DOMJITGetter>(vm.heap, sizeof(DOMJITGetter))) DOMJITGetter(vm, structure);
644         getter->finishCreation(vm);
645         return getter;
646     }
647
648     class DOMJITNodeDOMJIT : public DOMJIT::GetterSetter {
649     public:
650         DOMJITNodeDOMJIT()
651             : DOMJIT::GetterSetter(DOMJITGetter::customGetter, nullptr, DOMJITNode::info(), SpecInt32Only)
652         {
653         }
654
655 #if ENABLE(JIT)
656         Ref<DOMJIT::Patchpoint> checkDOM() override
657         {
658             return DOMJITNode::checkDOMJITNode();
659         }
660
661         static EncodedJSValue JIT_OPERATION slowCall(ExecState* exec, void* pointer)
662         {
663             NativeCallFrameTracer tracer(&exec->vm(), exec);
664             return JSValue::encode(jsNumber(static_cast<DOMJITGetter*>(pointer)->value()));
665         }
666
667         Ref<DOMJIT::CallDOMGetterPatchpoint> callDOMGetter() override
668         {
669             Ref<DOMJIT::CallDOMGetterPatchpoint> patchpoint = DOMJIT::CallDOMGetterPatchpoint::create();
670             patchpoint->requireGlobalObject = false;
671             patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
672                 JSValueRegs results = params[0].jsValueRegs();
673                 GPRReg dom = params[1].gpr();
674                 params.addSlowPathCall(jit.jump(), jit, slowCall, results, dom);
675                 return CCallHelpers::JumpList();
676
677             });
678             return patchpoint;
679         }
680 #endif
681     };
682
683     static DOMJIT::GetterSetter* domJITNodeGetterSetter()
684     {
685         static NeverDestroyed<DOMJITNodeDOMJIT> graph;
686         return &graph.get();
687     }
688
689 private:
690     void finishCreation(VM& vm)
691     {
692         Base::finishCreation(vm);
693         DOMJIT::GetterSetter* domJIT = domJITNodeGetterSetter();
694         CustomGetterSetter* customGetterSetter = CustomGetterSetter::create(vm, domJIT->getter(), domJIT->setter(), domJIT);
695         putDirectCustomAccessor(vm, Identifier::fromString(&vm, "customGetter"), customGetterSetter, ReadOnly | CustomAccessor);
696     }
697
698     static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
699     {
700         VM& vm = exec->vm();
701         auto scope = DECLARE_THROW_SCOPE(vm);
702
703         DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(vm, JSValue::decode(thisValue));
704         if (!thisObject)
705             return throwVMTypeError(exec, scope);
706         return JSValue::encode(jsNumber(thisObject->value()));
707     }
708 };
709
710 class DOMJITGetterComplex : public DOMJITNode {
711 public:
712     DOMJITGetterComplex(VM& vm, Structure* structure)
713         : Base(vm, structure)
714     {
715     }
716
717     DECLARE_INFO;
718     typedef DOMJITNode Base;
719     static const unsigned StructureFlags = Base::StructureFlags;
720
721     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
722     {
723         return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
724     }
725
726     static DOMJITGetterComplex* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
727     {
728         DOMJITGetterComplex* getter = new (NotNull, allocateCell<DOMJITGetterComplex>(vm.heap, sizeof(DOMJITGetterComplex))) DOMJITGetterComplex(vm, structure);
729         getter->finishCreation(vm, globalObject);
730         return getter;
731     }
732
733     class DOMJITNodeDOMJIT : public DOMJIT::GetterSetter {
734     public:
735         DOMJITNodeDOMJIT()
736             : DOMJIT::GetterSetter(DOMJITGetterComplex::customGetter, nullptr, DOMJITNode::info(), SpecInt32Only)
737         {
738         }
739
740 #if ENABLE(JIT)
741         Ref<DOMJIT::Patchpoint> checkDOM() override
742         {
743             return DOMJITNode::checkDOMJITNode();
744         }
745
746         static EncodedJSValue JIT_OPERATION slowCall(ExecState* exec, void* pointer)
747         {
748             VM& vm = exec->vm();
749             NativeCallFrameTracer tracer(&vm, exec);
750             auto scope = DECLARE_THROW_SCOPE(vm);
751             auto* object = static_cast<DOMJITNode*>(pointer);
752             auto* domjitGetterComplex = jsDynamicCast<DOMJITGetterComplex*>(vm, object);
753             if (domjitGetterComplex) {
754                 if (domjitGetterComplex->m_enableException)
755                     return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("DOMJITGetterComplex slow call exception"))));
756             }
757             return JSValue::encode(jsNumber(object->value()));
758         }
759
760         Ref<DOMJIT::CallDOMGetterPatchpoint> callDOMGetter() override
761         {
762             RefPtr<DOMJIT::CallDOMGetterPatchpoint> patchpoint = DOMJIT::CallDOMGetterPatchpoint::create();
763             static_assert(GPRInfo::numberOfRegisters >= 4, "Number of registers should be larger or equal to 4.");
764             patchpoint->numGPScratchRegisters = GPRInfo::numberOfRegisters - 4;
765             patchpoint->numFPScratchRegisters = 3;
766             patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
767                 JSValueRegs results = params[0].jsValueRegs();
768                 GPRReg domGPR = params[1].gpr();
769                 for (unsigned i = 0; i < patchpoint->numGPScratchRegisters; ++i)
770                     jit.move(CCallHelpers::TrustedImm32(42), params.gpScratch(i));
771
772                 params.addSlowPathCall(jit.jump(), jit, slowCall, results, domGPR);
773                 return CCallHelpers::JumpList();
774
775             });
776             return *patchpoint.get();
777         }
778 #endif
779     };
780
781     static DOMJIT::GetterSetter* domJITNodeGetterSetter()
782     {
783         static NeverDestroyed<DOMJITNodeDOMJIT> graph;
784         return &graph.get();
785     }
786
787 private:
788     void finishCreation(VM& vm, JSGlobalObject* globalObject)
789     {
790         Base::finishCreation(vm);
791         DOMJIT::GetterSetter* domJIT = domJITNodeGetterSetter();
792         CustomGetterSetter* customGetterSetter = CustomGetterSetter::create(vm, domJIT->getter(), domJIT->setter(), domJIT);
793         putDirectCustomAccessor(vm, Identifier::fromString(&vm, "customGetter"), customGetterSetter, ReadOnly | CustomAccessor);
794         putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "enableException"), 0, functionEnableException, NoIntrinsic, 0);
795     }
796
797     static EncodedJSValue JSC_HOST_CALL functionEnableException(ExecState* exec)
798     {
799         VM& vm = exec->vm();
800         auto* object = jsDynamicCast<DOMJITGetterComplex*>(vm, exec->thisValue());
801         if (object)
802             object->m_enableException = true;
803         return JSValue::encode(jsUndefined());
804     }
805
806     static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
807     {
808         VM& vm = exec->vm();
809         auto scope = DECLARE_THROW_SCOPE(vm);
810
811         auto* thisObject = jsDynamicCast<DOMJITNode*>(vm, JSValue::decode(thisValue));
812         if (!thisObject)
813             return throwVMTypeError(exec, scope);
814         if (auto* domjitGetterComplex = jsDynamicCast<DOMJITGetterComplex*>(vm, JSValue::decode(thisValue))) {
815             if (domjitGetterComplex->m_enableException)
816                 return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("DOMJITGetterComplex slow call exception"))));
817         }
818         return JSValue::encode(jsNumber(thisObject->value()));
819     }
820
821     bool m_enableException { false };
822 };
823
824 class DOMJITFunctionObject : public DOMJITNode {
825 public:
826     DOMJITFunctionObject(VM& vm, Structure* structure)
827         : Base(vm, structure)
828     {
829     }
830
831     DECLARE_INFO;
832     typedef DOMJITNode Base;
833     static const unsigned StructureFlags = Base::StructureFlags;
834
835
836     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
837     {
838         return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
839     }
840
841     static DOMJITFunctionObject* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
842     {
843         DOMJITFunctionObject* object = new (NotNull, allocateCell<DOMJITFunctionObject>(vm.heap, sizeof(DOMJITFunctionObject))) DOMJITFunctionObject(vm, structure);
844         object->finishCreation(vm, globalObject);
845         return object;
846     }
847
848     static EncodedJSValue JSC_HOST_CALL safeFunction(ExecState* exec)
849     {
850         VM& vm = exec->vm();
851         auto scope = DECLARE_THROW_SCOPE(vm);
852
853         DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(vm, exec->thisValue());
854         if (!thisObject)
855             return throwVMTypeError(exec, scope);
856         return JSValue::encode(jsNumber(thisObject->value()));
857     }
858
859 #if ENABLE(JIT)
860     static EncodedJSValue JIT_OPERATION unsafeFunction(ExecState* exec, DOMJITNode* node)
861     {
862         NativeCallFrameTracer tracer(&exec->vm(), exec);
863         return JSValue::encode(jsNumber(node->value()));
864     }
865
866     static Ref<DOMJIT::Patchpoint> checkDOMJITNode()
867     {
868         static const double value = 42.0;
869         Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
870         patchpoint->numFPScratchRegisters = 1;
871         patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
872             CCallHelpers::JumpList failureCases;
873             // May use scratch registers.
874             jit.loadDouble(CCallHelpers::TrustedImmPtr(&value), params.fpScratch(0));
875             failureCases.append(jit.branch8(
876                 CCallHelpers::NotEqual,
877                 CCallHelpers::Address(params[0].gpr(), JSCell::typeInfoTypeOffset()),
878                 CCallHelpers::TrustedImm32(JSC::JSType(LastJSCObjectType + 1))));
879             return failureCases;
880         });
881         return patchpoint;
882     }
883 #endif
884
885 private:
886     void finishCreation(VM&, JSGlobalObject*);
887 };
888
889 #if ENABLE(JIT)
890 static const DOMJIT::Signature DOMJITFunctionObjectSignature((uintptr_t)DOMJITFunctionObject::unsafeFunction, DOMJITFunctionObject::checkDOMJITNode, DOMJITFunctionObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
891 #endif
892
893 void DOMJITFunctionObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
894 {
895     Base::finishCreation(vm);
896 #if ENABLE(JIT)
897     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "func"), 0, safeFunction, NoIntrinsic, &DOMJITFunctionObjectSignature, ReadOnly);
898 #else
899     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "func"), 0, safeFunction, NoIntrinsic, nullptr, ReadOnly);
900 #endif
901 }
902
903
904 const ClassInfo Element::s_info = { "Element", &Base::s_info, nullptr, CREATE_METHOD_TABLE(Element) };
905 const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, nullptr, CREATE_METHOD_TABLE(Masquerader) };
906 const ClassInfo Root::s_info = { "Root", &Base::s_info, nullptr, CREATE_METHOD_TABLE(Root) };
907 const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, nullptr, CREATE_METHOD_TABLE(ImpureGetter) };
908 const ClassInfo CustomGetter::s_info = { "CustomGetter", &Base::s_info, nullptr, CREATE_METHOD_TABLE(CustomGetter) };
909 const ClassInfo DOMJITNode::s_info = { "DOMJITNode", &Base::s_info, nullptr, CREATE_METHOD_TABLE(DOMJITNode) };
910 const ClassInfo DOMJITGetter::s_info = { "DOMJITGetter", &Base::s_info, nullptr, CREATE_METHOD_TABLE(DOMJITGetter) };
911 const ClassInfo DOMJITGetterComplex::s_info = { "DOMJITGetterComplex", &Base::s_info, nullptr, CREATE_METHOD_TABLE(DOMJITGetterComplex) };
912 const ClassInfo DOMJITFunctionObject::s_info = { "DOMJITFunctionObject", &Base::s_info, nullptr, CREATE_METHOD_TABLE(DOMJITFunctionObject) };
913 const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, nullptr, CREATE_METHOD_TABLE(RuntimeArray) };
914 const ClassInfo SimpleObject::s_info = { "SimpleObject", &Base::s_info, nullptr, CREATE_METHOD_TABLE(SimpleObject) };
915 static unsigned asyncTestPasses { 0 };
916 static unsigned asyncTestExpectedPasses { 0 };
917
918 ElementHandleOwner* Element::handleOwner()
919 {
920     static ElementHandleOwner* owner = 0;
921     if (!owner)
922         owner = new ElementHandleOwner();
923     return owner;
924 }
925
926 void Element::finishCreation(VM& vm, Root* root)
927 {
928     Base::finishCreation(vm);
929     setRoot(vm, root);
930     m_root->setElement(this);
931 }
932
933 }
934
935 static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
936
937 class CommandLine;
938 class GlobalObject;
939 class Workers;
940
941 template<typename Func>
942 int runJSC(CommandLine, const Func&);
943 static void checkException(GlobalObject*, bool isLastFile, bool hasException, JSValue, const String& uncaughtExceptionName, bool alwaysDumpUncaughtException, bool dump, bool& success);
944
945 class Message : public ThreadSafeRefCounted<Message> {
946 public:
947     Message(ArrayBufferContents&&, int32_t);
948     ~Message();
949     
950     ArrayBufferContents&& releaseContents() { return WTFMove(m_contents); }
951     int32_t index() const { return m_index; }
952
953 private:
954     ArrayBufferContents m_contents;
955     int32_t m_index { 0 };
956 };
957
958 class Worker : public BasicRawSentinelNode<Worker> {
959 public:
960     Worker(Workers&);
961     ~Worker();
962     
963     void enqueue(const AbstractLocker&, RefPtr<Message>);
964     RefPtr<Message> dequeue();
965     
966     static Worker& current();
967
968 private:
969     static ThreadSpecific<Worker*>& currentWorker();
970
971     Workers& m_workers;
972     Deque<RefPtr<Message>> m_messages;
973 };
974
975 class Workers {
976 public:
977     Workers();
978     ~Workers();
979     
980     template<typename Func>
981     void broadcast(const Func&);
982     
983     void report(String);
984     String tryGetReport();
985     String getReport();
986     
987     static Workers& singleton();
988     
989 private:
990     friend class Worker;
991     
992     Lock m_lock;
993     Condition m_condition;
994     SentinelLinkedList<Worker, BasicRawSentinelNode<Worker>> m_workers;
995     Deque<String> m_reports;
996 };
997
998 static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*);
999 static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState*);
1000 static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
1001 static EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState*);
1002 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITNodeObject(ExecState*);
1003 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterObject(ExecState*);
1004 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterComplexObject(ExecState*);
1005 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITFunctionObject(ExecState*);
1006 static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState*);
1007 static EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState*);
1008 static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
1009
1010 static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*);
1011 static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState*);
1012 static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState*);
1013 static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState*);
1014 static EncodedJSValue JSC_HOST_CALL functionCreateSimpleObject(ExecState*);
1015 static EncodedJSValue JSC_HOST_CALL functionGetHiddenValue(ExecState*);
1016 static EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState*);
1017 static EncodedJSValue JSC_HOST_CALL functionPrintStdOut(ExecState*);
1018 static EncodedJSValue JSC_HOST_CALL functionPrintStdErr(ExecState*);
1019 static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
1020 static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
1021 static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
1022 static EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState*);
1023 static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
1024 static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
1025 static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
1026 static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
1027 static EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*);
1028 static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
1029 static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
1030 static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState*);
1031 #ifndef NDEBUG
1032 static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
1033 #endif
1034 static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
1035 static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
1036 static EncodedJSValue JSC_HOST_CALL functionRunString(ExecState*);
1037 static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
1038 static EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState*);
1039 static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*);
1040 static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
1041 static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
1042 static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
1043 static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*);
1044 static EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState*);
1045 static EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState*);
1046 static EncodedJSValue JSC_HOST_CALL functionNoOSRExitFuzzing(ExecState*);
1047 static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
1048 static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
1049 static EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState*);
1050 static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
1051 static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
1052 static EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState*);
1053 static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
1054 static NO_RETURN_DUE_TO_CRASH EncodedJSValue JSC_HOST_CALL functionAbort(ExecState*);
1055 static EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*);
1056 static EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*);
1057 static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
1058 static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
1059 static EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState*);
1060 static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
1061 static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
1062 static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
1063 static EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState*);
1064 static EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState*);
1065 static EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState*);
1066 static EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState*);
1067 static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState*);
1068 static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState*);
1069 static EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(ExecState*);
1070 static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*);
1071 static EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState*);
1072 static EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*);
1073 static EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState*);
1074 static EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState*);
1075 static EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*);
1076 static EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState*);
1077 static EncodedJSValue JSC_HOST_CALL functionResetSuperSamplerState(ExecState*);
1078 static EncodedJSValue JSC_HOST_CALL functionEnsureArrayStorage(ExecState*);
1079 #if ENABLE(SAMPLING_PROFILER)
1080 static EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState*);
1081 static EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState*);
1082 #endif
1083
1084 static EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*);
1085 static EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState*);
1086 static EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*);
1087
1088 #if ENABLE(WEBASSEMBLY)
1089 static EncodedJSValue JSC_HOST_CALL functionTestWasmModuleFunctions(ExecState*);
1090 static EncodedJSValue JSC_HOST_CALL functionWebAssemblyMemoryMode(ExecState*);
1091 #endif
1092
1093 #if ENABLE(SAMPLING_FLAGS)
1094 static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
1095 static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
1096 #endif
1097
1098 static EncodedJSValue JSC_HOST_CALL functionShadowChickenFunctionsOnStack(ExecState*);
1099 static EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNotThrow(ExecState*);
1100 static EncodedJSValue JSC_HOST_CALL functionGetRandomSeed(ExecState*);
1101 static EncodedJSValue JSC_HOST_CALL functionSetRandomSeed(ExecState*);
1102 static EncodedJSValue JSC_HOST_CALL functionIsRope(ExecState*);
1103 static EncodedJSValue JSC_HOST_CALL functionCallerSourceOrigin(ExecState*);
1104 static EncodedJSValue JSC_HOST_CALL functionGlobalObjectForObject(ExecState*);
1105 static EncodedJSValue JSC_HOST_CALL functionDollarCreateRealm(ExecState*);
1106 static EncodedJSValue JSC_HOST_CALL functionDollarDetachArrayBuffer(ExecState*);
1107 static EncodedJSValue JSC_HOST_CALL functionDollarEvalScript(ExecState*);
1108 static EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState*);
1109 static EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState*);
1110 static EncodedJSValue JSC_HOST_CALL functionDollarAgentReport(ExecState*);
1111 static EncodedJSValue JSC_HOST_CALL functionDollarAgentSleep(ExecState*);
1112 static EncodedJSValue JSC_HOST_CALL functionDollarAgentBroadcast(ExecState*);
1113 static EncodedJSValue JSC_HOST_CALL functionDollarAgentGetReport(ExecState*);
1114 static EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*);
1115 static EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState*);
1116 static EncodedJSValue JSC_HOST_CALL functionHeapCapacity(ExecState*);
1117 static EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState*);
1118
1119 struct Script {
1120     enum class StrictMode {
1121         Strict,
1122         Sloppy
1123     };
1124
1125     enum class ScriptType {
1126         Script,
1127         Module
1128     };
1129
1130     enum class CodeSource {
1131         File,
1132         CommandLine
1133     };
1134
1135     StrictMode strictMode;
1136     CodeSource codeSource;
1137     ScriptType scriptType;
1138     char* argument;
1139
1140     Script(StrictMode strictMode, CodeSource codeSource, ScriptType scriptType, char *argument)
1141         : strictMode(strictMode)
1142         , codeSource(codeSource)
1143         , scriptType(scriptType)
1144         , argument(argument)
1145     {
1146         if (strictMode == StrictMode::Strict)
1147             ASSERT(codeSource == CodeSource::File);
1148     }
1149 };
1150
1151 class CommandLine {
1152 public:
1153     CommandLine(int argc, char** argv)
1154     {
1155         parseArguments(argc, argv);
1156     }
1157
1158     bool m_interactive { false };
1159     bool m_dump { false };
1160     bool m_module { false };
1161     bool m_exitCode { false };
1162     Vector<Script> m_scripts;
1163     Vector<String> m_arguments;
1164     bool m_profile { false };
1165     String m_profilerOutput;
1166     String m_uncaughtExceptionName;
1167     bool m_alwaysDumpUncaughtException { false };
1168     bool m_dumpSamplingProfilerData { false };
1169     bool m_enableRemoteDebugging { false };
1170
1171     void parseArguments(int, char**);
1172 };
1173
1174 static const char interactivePrompt[] = ">>> ";
1175
1176 class StopWatch {
1177 public:
1178     void start();
1179     void stop();
1180     long getElapsedMS(); // call stop() first
1181
1182 private:
1183     double m_startTime;
1184     double m_stopTime;
1185 };
1186
1187 void StopWatch::start()
1188 {
1189     m_startTime = monotonicallyIncreasingTime();
1190 }
1191
1192 void StopWatch::stop()
1193 {
1194     m_stopTime = monotonicallyIncreasingTime();
1195 }
1196
1197 long StopWatch::getElapsedMS()
1198 {
1199     return static_cast<long>((m_stopTime - m_startTime) * 1000);
1200 }
1201
1202 template<typename Vector>
1203 static inline String stringFromUTF(const Vector& utf8)
1204 {
1205     return String::fromUTF8WithLatin1Fallback(utf8.data(), utf8.size());
1206 }
1207
1208 template<typename Vector>
1209 static inline SourceCode jscSource(const Vector& utf8, const SourceOrigin& sourceOrigin, const String& filename)
1210 {
1211     String str = stringFromUTF(utf8);
1212     return makeSource(str, sourceOrigin, filename);
1213 }
1214
1215 class GlobalObject : public JSGlobalObject {
1216 private:
1217     GlobalObject(VM&, Structure*);
1218
1219 public:
1220     typedef JSGlobalObject Base;
1221
1222     static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
1223     {
1224         GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
1225         object->finishCreation(vm, arguments);
1226         return object;
1227     }
1228
1229     static const bool needsDestruction = false;
1230
1231     DECLARE_INFO;
1232     static const GlobalObjectMethodTable s_globalObjectMethodTable;
1233
1234     static Structure* createStructure(VM& vm, JSValue prototype)
1235     {
1236         return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
1237     }
1238
1239     static RuntimeFlags javaScriptRuntimeFlags(const JSGlobalObject*) { return RuntimeFlags::createAllEnabled(); }
1240
1241 protected:
1242     void finishCreation(VM& vm, const Vector<String>& arguments)
1243     {
1244         Base::finishCreation(vm);
1245         
1246         addFunction(vm, "debug", functionDebug, 1);
1247         addFunction(vm, "describe", functionDescribe, 1);
1248         addFunction(vm, "describeArray", functionDescribeArray, 1);
1249         addFunction(vm, "print", functionPrintStdOut, 1);
1250         addFunction(vm, "printErr", functionPrintStdErr, 1);
1251         addFunction(vm, "quit", functionQuit, 0);
1252         addFunction(vm, "abort", functionAbort, 0);
1253         addFunction(vm, "gc", functionGCAndSweep, 0);
1254         addFunction(vm, "fullGC", functionFullGC, 0);
1255         addFunction(vm, "edenGC", functionEdenGC, 0);
1256         addFunction(vm, "forceGCSlowPaths", functionForceGCSlowPaths, 0);
1257         addFunction(vm, "gcHeapSize", functionHeapSize, 0);
1258         addFunction(vm, "addressOf", functionAddressOf, 1);
1259         addFunction(vm, "getGetterSetter", functionGetGetterSetter, 2);
1260 #ifndef NDEBUG
1261         addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
1262 #endif
1263         addFunction(vm, "version", functionVersion, 1);
1264         addFunction(vm, "run", functionRun, 1);
1265         addFunction(vm, "runString", functionRunString, 1);
1266         addFunction(vm, "load", functionLoad, 1);
1267         addFunction(vm, "loadString", functionLoadString, 1);
1268         addFunction(vm, "readFile", functionReadFile, 2);
1269         addFunction(vm, "read", functionReadFile, 2);
1270         addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
1271         addFunction(vm, "sleepSeconds", functionSleepSeconds, 1);
1272         addFunction(vm, "jscStack", functionJSCStack, 1);
1273         addFunction(vm, "readline", functionReadline, 0);
1274         addFunction(vm, "preciseTime", functionPreciseTime, 0);
1275         addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
1276         addFunction(vm, "noInline", functionNeverInlineFunction, 1);
1277         addFunction(vm, "noDFG", functionNoDFG, 1);
1278         addFunction(vm, "noFTL", functionNoFTL, 1);
1279         addFunction(vm, "noOSRExitFuzzing", functionNoOSRExitFuzzing, 1);
1280         addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
1281         addFunction(vm, "jscOptions", functionJSCOptions, 0);
1282         addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
1283         addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
1284         addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
1285         addFunction(vm, "failNextNewCodeBlock", functionFailNextNewCodeBlock, 1);
1286 #if ENABLE(SAMPLING_FLAGS)
1287         addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
1288         addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
1289 #endif
1290         addFunction(vm, "shadowChickenFunctionsOnStack", functionShadowChickenFunctionsOnStack, 0);
1291         addFunction(vm, "setGlobalConstRedeclarationShouldNotThrow", functionSetGlobalConstRedeclarationShouldNotThrow, 0);
1292         addConstructableFunction(vm, "Root", functionCreateRoot, 0);
1293         addConstructableFunction(vm, "Element", functionCreateElement, 1);
1294         addFunction(vm, "getElement", functionGetElement, 1);
1295         addFunction(vm, "setElementRoot", functionSetElementRoot, 2);
1296         
1297         addConstructableFunction(vm, "SimpleObject", functionCreateSimpleObject, 0);
1298         addFunction(vm, "getHiddenValue", functionGetHiddenValue, 1);
1299         addFunction(vm, "setHiddenValue", functionSetHiddenValue, 2);
1300         
1301         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "DFGTrue"), 0, functionFalse1, DFGTrueIntrinsic, DontEnum);
1302         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, DontEnum);
1303         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isFinalTier"), 0, functionFalse2, IsFinalTierIntrinsic, DontEnum);
1304         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, DontEnum);
1305         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isInt32"), 0, functionIsInt32, CheckInt32Intrinsic, DontEnum);
1306         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, DontEnum);
1307         
1308         addFunction(vm, "effectful42", functionEffectful42, 0);
1309         addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
1310         addFunction(vm, "hasCustomProperties", functionHasCustomProperties, 0);
1311
1312         addFunction(vm, "createProxy", functionCreateProxy, 1);
1313         addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
1314
1315         addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
1316         addFunction(vm, "createCustomGetterObject", functionCreateCustomGetterObject, 0);
1317         addFunction(vm, "createDOMJITNodeObject", functionCreateDOMJITNodeObject, 0);
1318         addFunction(vm, "createDOMJITGetterObject", functionCreateDOMJITGetterObject, 0);
1319         addFunction(vm, "createDOMJITGetterComplexObject", functionCreateDOMJITGetterComplexObject, 0);
1320         addFunction(vm, "createDOMJITFunctionObject", functionCreateDOMJITFunctionObject, 0);
1321         addFunction(vm, "createBuiltin", functionCreateBuiltin, 2);
1322         addFunction(vm, "createGlobalObject", functionCreateGlobalObject, 0);
1323         addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
1324
1325         addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 0);
1326         addFunction(vm, "findTypeForExpression", functionFindTypeForExpression, 2);
1327         addFunction(vm, "returnTypeFor", functionReturnTypeFor, 1);
1328
1329         addFunction(vm, "dumpBasicBlockExecutionRanges", functionDumpBasicBlockExecutionRanges , 0);
1330         addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
1331         addFunction(vm, "basicBlockExecutionCount", functionBasicBlockExecutionCount, 2);
1332
1333         addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
1334
1335         addFunction(vm, "drainMicrotasks", functionDrainMicrotasks, 0);
1336
1337         addFunction(vm, "getRandomSeed", functionGetRandomSeed, 0);
1338         addFunction(vm, "setRandomSeed", functionSetRandomSeed, 1);
1339         addFunction(vm, "isRope", functionIsRope, 1);
1340         addFunction(vm, "callerSourceOrigin", functionCallerSourceOrigin, 0);
1341
1342         addFunction(vm, "globalObjectForObject", functionGlobalObjectForObject, 1);
1343
1344         addFunction(vm, "is32BitPlatform", functionIs32BitPlatform, 0);
1345
1346         addFunction(vm, "loadModule", functionLoadModule, 1);
1347         addFunction(vm, "checkModuleSyntax", functionCheckModuleSyntax, 1);
1348
1349         addFunction(vm, "platformSupportsSamplingProfiler", functionPlatformSupportsSamplingProfiler, 0);
1350         addFunction(vm, "generateHeapSnapshot", functionGenerateHeapSnapshot, 0);
1351         addFunction(vm, "resetSuperSamplerState", functionResetSuperSamplerState, 0);
1352         addFunction(vm, "ensureArrayStorage", functionEnsureArrayStorage, 0);
1353 #if ENABLE(SAMPLING_PROFILER)
1354         addFunction(vm, "startSamplingProfiler", functionStartSamplingProfiler, 0);
1355         addFunction(vm, "samplingProfilerStackTraces", functionSamplingProfilerStackTraces, 0);
1356 #endif
1357
1358         addFunction(vm, "maxArguments", functionMaxArguments, 0);
1359
1360         addFunction(vm, "asyncTestStart", functionAsyncTestStart, 1);
1361         addFunction(vm, "asyncTestPassed", functionAsyncTestPassed, 1);
1362
1363 #if ENABLE(WEBASSEMBLY)
1364         addFunction(vm, "testWasmModuleFunctions", functionTestWasmModuleFunctions, 0);
1365         addFunction(vm, "WebAssemblyMemoryMode", functionWebAssemblyMemoryMode, 1);
1366 #endif
1367
1368         if (!arguments.isEmpty()) {
1369             JSArray* array = constructEmptyArray(globalExec(), 0);
1370             for (size_t i = 0; i < arguments.size(); ++i)
1371                 array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
1372             putDirect(vm, Identifier::fromString(globalExec(), "arguments"), array);
1373         }
1374
1375         putDirect(vm, Identifier::fromString(globalExec(), "console"), jsUndefined());
1376         
1377         Structure* plainObjectStructure = JSFinalObject::createStructure(vm, this, objectPrototype(), 0);
1378         
1379         JSObject* dollar = JSFinalObject::create(vm, plainObjectStructure);
1380         putDirect(vm, Identifier::fromString(globalExec(), "$"), dollar);
1381         
1382         addFunction(vm, dollar, "createRealm", functionDollarCreateRealm, 0);
1383         addFunction(vm, dollar, "detachArrayBuffer", functionDollarDetachArrayBuffer, 1);
1384         addFunction(vm, dollar, "evalScript", functionDollarEvalScript, 1);
1385         
1386         dollar->putDirect(vm, Identifier::fromString(globalExec(), "global"), this);
1387         
1388         JSObject* agent = JSFinalObject::create(vm, plainObjectStructure);
1389         dollar->putDirect(vm, Identifier::fromString(globalExec(), "agent"), agent);
1390         
1391         // The test262 INTERPRETING.md document says that some of these functions are just in the main
1392         // thread and some are in the other threads. We just put them in all threads.
1393         addFunction(vm, agent, "start", functionDollarAgentStart, 1);
1394         addFunction(vm, agent, "receiveBroadcast", functionDollarAgentReceiveBroadcast, 1);
1395         addFunction(vm, agent, "report", functionDollarAgentReport, 1);
1396         addFunction(vm, agent, "sleep", functionDollarAgentSleep, 1);
1397         addFunction(vm, agent, "broadcast", functionDollarAgentBroadcast, 1);
1398         addFunction(vm, agent, "getReport", functionDollarAgentGetReport, 0);
1399         addFunction(vm, agent, "leaving", functionDollarAgentLeaving, 0);
1400         
1401         addFunction(vm, "waitForReport", functionWaitForReport, 0);
1402
1403         addFunction(vm, "heapCapacity", functionHeapCapacity, 0);
1404         addFunction(vm, "flashHeapAccess", functionFlashHeapAccess, 0);
1405     }
1406     
1407     void addFunction(VM& vm, JSObject* object, const char* name, NativeFunction function, unsigned arguments)
1408     {
1409         Identifier identifier = Identifier::fromString(&vm, name);
1410         object->putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
1411     }
1412
1413     void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
1414     {
1415         addFunction(vm, this, name, function, arguments);
1416     }
1417     
1418     void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
1419     {
1420         Identifier identifier = Identifier::fromString(&vm, name);
1421         putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function));
1422     }
1423
1424     static JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, ExecState*, JSModuleLoader*, JSString*, const SourceOrigin&);
1425     static JSInternalPromise* moduleLoaderResolve(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
1426     static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue);
1427 };
1428
1429 const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
1430 const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = {
1431     &supportsRichSourceInfo,
1432     &shouldInterruptScript,
1433     &javaScriptRuntimeFlags,
1434     nullptr,
1435     &shouldInterruptScriptBeforeTimeout,
1436     &moduleLoaderImportModule,
1437     &moduleLoaderResolve,
1438     &moduleLoaderFetch,
1439     nullptr,
1440     nullptr,
1441     nullptr
1442 };
1443
1444 GlobalObject::GlobalObject(VM& vm, Structure* structure)
1445     : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
1446 {
1447 }
1448
1449 static UChar pathSeparator()
1450 {
1451 #if OS(WINDOWS)
1452     return '\\';
1453 #else
1454     return '/';
1455 #endif
1456 }
1457
1458 struct DirectoryName {
1459     // In unix, it is "/". In Windows, it becomes a drive letter like "C:\"
1460     String rootName;
1461
1462     // If the directory name is "/home/WebKit", this becomes "home/WebKit". If the directory name is "/", this becomes "".
1463     String queryName;
1464 };
1465
1466 struct ModuleName {
1467     ModuleName(const String& moduleName);
1468
1469     bool startsWithRoot() const
1470     {
1471         return !queries.isEmpty() && queries[0].isEmpty();
1472     }
1473
1474     Vector<String> queries;
1475 };
1476
1477 ModuleName::ModuleName(const String& moduleName)
1478 {
1479     // A module name given from code is represented as the UNIX style path. Like, `./A/B.js`.
1480     moduleName.split('/', true, queries);
1481 }
1482
1483 static std::optional<DirectoryName> extractDirectoryName(const String& absolutePathToFile)
1484 {
1485     size_t firstSeparatorPosition = absolutePathToFile.find(pathSeparator());
1486     if (firstSeparatorPosition == notFound)
1487         return std::nullopt;
1488     DirectoryName directoryName;
1489     directoryName.rootName = absolutePathToFile.substring(0, firstSeparatorPosition + 1); // Include the separator.
1490     size_t lastSeparatorPosition = absolutePathToFile.reverseFind(pathSeparator());
1491     ASSERT_WITH_MESSAGE(lastSeparatorPosition != notFound, "If the separator is not found, this function already returns when performing the forward search.");
1492     if (firstSeparatorPosition == lastSeparatorPosition)
1493         directoryName.queryName = StringImpl::empty();
1494     else {
1495         size_t queryStartPosition = firstSeparatorPosition + 1;
1496         size_t queryLength = lastSeparatorPosition - queryStartPosition; // Not include the last separator.
1497         directoryName.queryName = absolutePathToFile.substring(queryStartPosition, queryLength);
1498     }
1499     return directoryName;
1500 }
1501
1502 static std::optional<DirectoryName> currentWorkingDirectory()
1503 {
1504 #if OS(WINDOWS)
1505     // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364934.aspx
1506     // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
1507     // The _MAX_PATH in Windows is 260. If the path of the current working directory is longer than that, _getcwd truncates the result.
1508     // And other I/O functions taking a path name also truncate it. To avoid this situation,
1509     //
1510     // (1). When opening the file in Windows for modules, we always use the abosolute path and add "\\?\" prefix to the path name.
1511     // (2). When retrieving the current working directory, use GetCurrentDirectory instead of _getcwd.
1512     //
1513     // In the path utility functions inside the JSC shell, we does not handle the UNC and UNCW including the network host name.
1514     DWORD bufferLength = ::GetCurrentDirectoryW(0, nullptr);
1515     if (!bufferLength)
1516         return std::nullopt;
1517     // In Windows, wchar_t is the UTF-16LE.
1518     // https://msdn.microsoft.com/en-us/library/dd374081.aspx
1519     // https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407.aspx
1520     auto buffer = std::make_unique<wchar_t[]>(bufferLength);
1521     DWORD lengthNotIncludingNull = ::GetCurrentDirectoryW(bufferLength, buffer.get());
1522     static_assert(sizeof(wchar_t) == sizeof(UChar), "In Windows, both are UTF-16LE");
1523     String directoryString = String(reinterpret_cast<UChar*>(buffer.get()));
1524     // We don't support network path like \\host\share\<path name>.
1525     if (directoryString.startsWith("\\\\"))
1526         return std::nullopt;
1527 #else
1528     auto buffer = std::make_unique<char[]>(PATH_MAX);
1529     if (!getcwd(buffer.get(), PATH_MAX))
1530         return std::nullopt;
1531     String directoryString = String::fromUTF8(buffer.get());
1532 #endif
1533     if (directoryString.isEmpty())
1534         return std::nullopt;
1535
1536     if (directoryString[directoryString.length() - 1] == pathSeparator())
1537         return extractDirectoryName(directoryString);
1538     // Append the seperator to represents the file name. extractDirectoryName only accepts the absolute file name.
1539     return extractDirectoryName(makeString(directoryString, pathSeparator()));
1540 }
1541
1542 static String resolvePath(const DirectoryName& directoryName, const ModuleName& moduleName)
1543 {
1544     Vector<String> directoryPieces;
1545     directoryName.queryName.split(pathSeparator(), false, directoryPieces);
1546
1547     // Only first '/' is recognized as the path from the root.
1548     if (moduleName.startsWithRoot())
1549         directoryPieces.clear();
1550
1551     for (const auto& query : moduleName.queries) {
1552         if (query == String(ASCIILiteral(".."))) {
1553             if (!directoryPieces.isEmpty())
1554                 directoryPieces.removeLast();
1555         } else if (!query.isEmpty() && query != String(ASCIILiteral(".")))
1556             directoryPieces.append(query);
1557     }
1558
1559     StringBuilder builder;
1560     builder.append(directoryName.rootName);
1561     for (size_t i = 0; i < directoryPieces.size(); ++i) {
1562         builder.append(directoryPieces[i]);
1563         if (i + 1 != directoryPieces.size())
1564             builder.append(pathSeparator());
1565     }
1566     return builder.toString();
1567 }
1568
1569 static String absolutePath(const String& fileName)
1570 {
1571     auto directoryName = currentWorkingDirectory();
1572     if (!directoryName)
1573         return fileName;
1574     return resolvePath(directoryName.value(), ModuleName(fileName.impl()));
1575 }
1576
1577 JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSString* moduleNameValue, const SourceOrigin& sourceOrigin)
1578 {
1579     VM& vm = globalObject->vm();
1580     auto scope = DECLARE_CATCH_SCOPE(vm);
1581
1582     auto rejectPromise = [&] (JSValue error) {
1583         return JSInternalPromiseDeferred::create(exec, globalObject)->reject(exec, error);
1584     };
1585
1586     if (sourceOrigin.isNull())
1587         return rejectPromise(createError(exec, ASCIILiteral("Could not resolve the module specifier.")));
1588
1589     auto referrer = sourceOrigin.string();
1590     auto moduleName = moduleNameValue->value(exec);
1591     if (UNLIKELY(scope.exception())) {
1592         JSValue exception = scope.exception();
1593         scope.clearException();
1594         return rejectPromise(exception);
1595     }
1596
1597     auto directoryName = extractDirectoryName(referrer.impl());
1598     if (!directoryName)
1599         return rejectPromise(createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
1600
1601     return JSC::importModule(exec, Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(moduleName))), jsUndefined());
1602 }
1603
1604 JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue)
1605 {
1606     VM& vm = globalObject->vm();
1607     auto scope = DECLARE_CATCH_SCOPE(vm);
1608
1609     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
1610     RELEASE_ASSERT(!scope.exception());
1611     const Identifier key = keyValue.toPropertyKey(exec);
1612     if (UNLIKELY(scope.exception())) {
1613         JSValue exception = scope.exception();
1614         scope.clearException();
1615         return deferred->reject(exec, exception);
1616     }
1617
1618     if (key.isSymbol())
1619         return deferred->resolve(exec, keyValue);
1620
1621     if (referrerValue.isUndefined()) {
1622         auto directoryName = currentWorkingDirectory();
1623         if (!directoryName)
1624             return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
1625         return deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
1626     }
1627
1628     const Identifier referrer = referrerValue.toPropertyKey(exec);
1629     if (UNLIKELY(scope.exception())) {
1630         JSValue exception = scope.exception();
1631         scope.clearException();
1632         return deferred->reject(exec, exception);
1633     }
1634
1635     if (referrer.isSymbol()) {
1636         auto directoryName = currentWorkingDirectory();
1637         if (!directoryName)
1638             return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
1639         return deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
1640     }
1641
1642     // If the referrer exists, we assume that the referrer is the correct absolute path.
1643     auto directoryName = extractDirectoryName(referrer.impl());
1644     if (!directoryName)
1645         return deferred->reject(exec, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
1646     auto result = deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
1647     RELEASE_ASSERT(!scope.exception());
1648     return result;
1649 }
1650
1651 static void convertShebangToJSComment(Vector<char>& buffer)
1652 {
1653     if (buffer.size() >= 2) {
1654         if (buffer[0] == '#' && buffer[1] == '!')
1655             buffer[0] = buffer[1] = '/';
1656     }
1657 }
1658
1659 static bool fillBufferWithContentsOfFile(FILE* file, Vector<char>& buffer)
1660 {
1661     // We might have injected "use strict"; at the top.
1662     size_t initialSize = buffer.size();
1663     fseek(file, 0, SEEK_END);
1664     size_t bufferCapacity = ftell(file);
1665     fseek(file, 0, SEEK_SET);
1666     buffer.resize(bufferCapacity + initialSize);
1667     size_t readSize = fread(buffer.data() + initialSize, 1, buffer.size(), file);
1668     return readSize == buffer.size() - initialSize;
1669 }
1670
1671 static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
1672 {
1673     FILE* f = fopen(fileName.utf8().data(), "rb");
1674     if (!f) {
1675         fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1676         return false;
1677     }
1678
1679     bool result = fillBufferWithContentsOfFile(f, buffer);
1680     fclose(f);
1681
1682     return result;
1683 }
1684
1685 static bool fetchScriptFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
1686 {
1687     if (!fillBufferWithContentsOfFile(fileName, buffer))
1688         return false;
1689     convertShebangToJSComment(buffer);
1690     return true;
1691 }
1692
1693 static bool fetchModuleFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
1694 {
1695     // We assume that fileName is always an absolute path.
1696 #if OS(WINDOWS)
1697     // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
1698     // Use long UNC to pass the long path name to the Windows APIs.
1699     String longUNCPathName = WTF::makeString("\\\\?\\", fileName);
1700     static_assert(sizeof(wchar_t) == sizeof(UChar), "In Windows, both are UTF-16LE");
1701     auto utf16Vector = longUNCPathName.charactersWithNullTermination();
1702     FILE* f = _wfopen(reinterpret_cast<wchar_t*>(utf16Vector.data()), L"rb");
1703 #else
1704     FILE* f = fopen(fileName.utf8().data(), "r");
1705 #endif
1706     if (!f) {
1707         fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1708         return false;
1709     }
1710
1711     bool result = fillBufferWithContentsOfFile(f, buffer);
1712     if (result)
1713         convertShebangToJSComment(buffer);
1714     fclose(f);
1715
1716     return result;
1717 }
1718
1719 JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSValue)
1720 {
1721     VM& vm = globalObject->vm();
1722     auto scope = DECLARE_CATCH_SCOPE(vm);
1723     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
1724     String moduleKey = key.toWTFString(exec);
1725     if (UNLIKELY(scope.exception())) {
1726         JSValue exception = scope.exception();
1727         scope.clearException();
1728         return deferred->reject(exec, exception);
1729     }
1730
1731     // Here, now we consider moduleKey as the fileName.
1732     Vector<char> utf8;
1733     if (!fetchModuleFromLocalFileSystem(moduleKey, utf8))
1734         return deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'.")));
1735
1736     auto result = deferred->resolve(exec, JSSourceCode::create(exec->vm(), makeSource(stringFromUTF(utf8), SourceOrigin { moduleKey }, moduleKey, TextPosition(), SourceProviderSourceType::Module)));
1737     RELEASE_ASSERT(!scope.exception());
1738     return result;
1739 }
1740
1741
1742 static EncodedJSValue printInternal(ExecState* exec, FILE* out)
1743 {
1744     VM& vm = exec->vm();
1745     auto scope = DECLARE_THROW_SCOPE(vm);
1746
1747     if (asyncTestExpectedPasses) {
1748         JSValue value = exec->argument(0);
1749         if (value.isString() && WTF::equal(asString(value)->value(exec).impl(), "Test262:AsyncTestComplete")) {
1750             asyncTestPasses++;
1751             return JSValue::encode(jsUndefined());
1752         }
1753     }
1754
1755     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1756         if (i)
1757             if (EOF == fputc(' ', out))
1758                 goto fail;
1759
1760         auto viewWithString = exec->uncheckedArgument(i).toString(exec)->viewWithUnderlyingString(*exec);
1761         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1762         if (fprintf(out, "%s", viewWithString.view.utf8().data()) < 0)
1763             goto fail;
1764     }
1765
1766     fputc('\n', out);
1767 fail:
1768     fflush(out);
1769     return JSValue::encode(jsUndefined());
1770 }
1771
1772 EncodedJSValue JSC_HOST_CALL functionPrintStdOut(ExecState* exec) { return printInternal(exec, stdout); }
1773 EncodedJSValue JSC_HOST_CALL functionPrintStdErr(ExecState* exec) { return printInternal(exec, stderr); }
1774
1775 #ifndef NDEBUG
1776 EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
1777 {
1778     VMEntryFrame* topVMEntryFrame = exec->vm().topVMEntryFrame;
1779     ExecState* callerFrame = exec->callerFrame(topVMEntryFrame);
1780     if (callerFrame)
1781         exec->vm().interpreter->dumpCallFrame(callerFrame);
1782     return JSValue::encode(jsUndefined());
1783 }
1784 #endif
1785
1786 EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
1787 {
1788     VM& vm = exec->vm();
1789     auto scope = DECLARE_THROW_SCOPE(vm);
1790     auto viewWithString = exec->argument(0).toString(exec)->viewWithUnderlyingString(*exec);
1791     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1792     fprintf(stderr, "--> %s\n", viewWithString.view.utf8().data());
1793     return JSValue::encode(jsUndefined());
1794 }
1795
1796 EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
1797 {
1798     if (exec->argumentCount() < 1)
1799         return JSValue::encode(jsUndefined());
1800     return JSValue::encode(jsString(exec, toString(exec->argument(0))));
1801 }
1802
1803 EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
1804 {
1805     if (exec->argumentCount() < 1)
1806         return JSValue::encode(jsUndefined());
1807     VM& vm = exec->vm();
1808     JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(0));
1809     if (!object)
1810         return JSValue::encode(jsNontrivialString(exec, ASCIILiteral("<not object>")));
1811     return JSValue::encode(jsNontrivialString(exec, toString("<Butterfly: ", RawPointer(object->butterfly()), "; public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
1812 }
1813
1814 EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState* exec)
1815 {
1816     VM& vm = exec->vm();
1817     auto scope = DECLARE_THROW_SCOPE(vm);
1818
1819     if (exec->argumentCount() >= 1) {
1820         Seconds seconds = Seconds(exec->argument(0).toNumber(exec));
1821         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1822         sleep(seconds);
1823     }
1824     
1825     return JSValue::encode(jsUndefined());
1826 }
1827
1828 class FunctionJSCStackFunctor {
1829 public:
1830     FunctionJSCStackFunctor(StringBuilder& trace)
1831         : m_trace(trace)
1832     {
1833     }
1834
1835     StackVisitor::Status operator()(StackVisitor& visitor) const
1836     {
1837         m_trace.append(String::format("    %zu   %s\n", visitor->index(), visitor->toString().utf8().data()));
1838         return StackVisitor::Continue;
1839     }
1840
1841 private:
1842     StringBuilder& m_trace;
1843 };
1844
1845 EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
1846 {
1847     StringBuilder trace;
1848     trace.appendLiteral("--> Stack trace:\n");
1849
1850     FunctionJSCStackFunctor functor(trace);
1851     exec->iterate(functor);
1852     fprintf(stderr, "%s", trace.toString().utf8().data());
1853     return JSValue::encode(jsUndefined());
1854 }
1855
1856 EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
1857 {
1858     JSLockHolder lock(exec);
1859     return JSValue::encode(Root::create(exec->vm(), exec->lexicalGlobalObject()));
1860 }
1861
1862 EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
1863 {
1864     VM& vm = exec->vm();
1865     JSLockHolder lock(vm);
1866     auto scope = DECLARE_THROW_SCOPE(vm);
1867
1868     Root* root = jsDynamicCast<Root*>(vm, exec->argument(0));
1869     if (!root)
1870         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Cannot create Element without a Root."))));
1871     return JSValue::encode(Element::create(vm, exec->lexicalGlobalObject(), root));
1872 }
1873
1874 EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
1875 {
1876     JSLockHolder lock(exec);
1877     VM& vm = exec->vm();
1878     Root* root = jsDynamicCast<Root*>(vm, exec->argument(0));
1879     if (!root)
1880         return JSValue::encode(jsUndefined());
1881     Element* result = root->element();
1882     return JSValue::encode(result ? result : jsUndefined());
1883 }
1884
1885 EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState* exec)
1886 {
1887     JSLockHolder lock(exec);
1888     VM& vm = exec->vm();
1889     Element* element = jsDynamicCast<Element*>(vm, exec->argument(0));
1890     Root* root = jsDynamicCast<Root*>(vm, exec->argument(1));
1891     if (element && root)
1892         element->setRoot(exec->vm(), root);
1893     return JSValue::encode(jsUndefined());
1894 }
1895
1896 EncodedJSValue JSC_HOST_CALL functionCreateSimpleObject(ExecState* exec)
1897 {
1898     JSLockHolder lock(exec);
1899     return JSValue::encode(SimpleObject::create(exec->vm(), exec->lexicalGlobalObject()));
1900 }
1901
1902 EncodedJSValue JSC_HOST_CALL functionGetHiddenValue(ExecState* exec)
1903 {
1904     VM& vm = exec->vm();
1905     JSLockHolder lock(vm);
1906     auto scope = DECLARE_THROW_SCOPE(vm);
1907
1908     SimpleObject* simpleObject = jsDynamicCast<SimpleObject*>(vm, exec->argument(0));
1909     if (UNLIKELY(!simpleObject)) {
1910         throwTypeError(exec, scope, ASCIILiteral("Invalid use of getHiddenValue test function"));
1911         return encodedJSValue();
1912     }
1913     return JSValue::encode(simpleObject->hiddenValue());
1914 }
1915
1916 EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState* exec)
1917 {
1918     VM& vm = exec->vm();
1919     JSLockHolder lock(vm);
1920     auto scope = DECLARE_THROW_SCOPE(vm);
1921
1922     SimpleObject* simpleObject = jsDynamicCast<SimpleObject*>(vm, exec->argument(0));
1923     if (UNLIKELY(!simpleObject)) {
1924         throwTypeError(exec, scope, ASCIILiteral("Invalid use of setHiddenValue test function"));
1925         return encodedJSValue();
1926     }
1927     JSValue value = exec->argument(1);
1928     simpleObject->setHiddenValue(exec->vm(), value);
1929     return JSValue::encode(jsUndefined());
1930 }
1931
1932 EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState* exec)
1933 {
1934     JSLockHolder lock(exec);
1935     JSValue target = exec->argument(0);
1936     if (!target.isObject())
1937         return JSValue::encode(jsUndefined());
1938     JSObject* jsTarget = asObject(target.asCell());
1939     Structure* structure = JSProxy::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsTarget->getPrototypeDirect(), ImpureProxyType);
1940     JSProxy* proxy = JSProxy::create(exec->vm(), structure, jsTarget);
1941     return JSValue::encode(proxy);
1942 }
1943
1944 EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState* exec)
1945 {
1946     JSLockHolder lock(exec);
1947     RuntimeArray* array = RuntimeArray::create(exec);
1948     return JSValue::encode(array);
1949 }
1950
1951 EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
1952 {
1953     JSLockHolder lock(exec);
1954     JSValue target = exec->argument(0);
1955     JSObject* delegate = nullptr;
1956     if (target.isObject())
1957         delegate = asObject(target.asCell());
1958     Structure* structure = ImpureGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
1959     ImpureGetter* result = ImpureGetter::create(exec->vm(), structure, delegate);
1960     return JSValue::encode(result);
1961 }
1962
1963 EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState* exec)
1964 {
1965     JSLockHolder lock(exec);
1966     Structure* structure = CustomGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
1967     CustomGetter* result = CustomGetter::create(exec->vm(), structure);
1968     return JSValue::encode(result);
1969 }
1970
1971 EncodedJSValue JSC_HOST_CALL functionCreateDOMJITNodeObject(ExecState* exec)
1972 {
1973     JSLockHolder lock(exec);
1974     Structure* structure = DOMJITNode::createStructure(exec->vm(), exec->lexicalGlobalObject(), DOMJITGetter::create(exec->vm(), DOMJITGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull())));
1975     DOMJITNode* result = DOMJITNode::create(exec->vm(), structure);
1976     return JSValue::encode(result);
1977 }
1978
1979 EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterObject(ExecState* exec)
1980 {
1981     JSLockHolder lock(exec);
1982     Structure* structure = DOMJITGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
1983     DOMJITGetter* result = DOMJITGetter::create(exec->vm(), structure);
1984     return JSValue::encode(result);
1985 }
1986
1987 EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterComplexObject(ExecState* exec)
1988 {
1989     JSLockHolder lock(exec);
1990     Structure* structure = DOMJITGetterComplex::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
1991     DOMJITGetterComplex* result = DOMJITGetterComplex::create(exec->vm(), exec->lexicalGlobalObject(), structure);
1992     return JSValue::encode(result);
1993 }
1994
1995 EncodedJSValue JSC_HOST_CALL functionCreateDOMJITFunctionObject(ExecState* exec)
1996 {
1997     JSLockHolder lock(exec);
1998     Structure* structure = DOMJITFunctionObject::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
1999     DOMJITFunctionObject* result = DOMJITFunctionObject::create(exec->vm(), exec->lexicalGlobalObject(), structure);
2000     return JSValue::encode(result);
2001 }
2002
2003 EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
2004 {
2005     VM& vm = exec->vm();
2006     JSLockHolder lock(vm);
2007     auto scope = DECLARE_THROW_SCOPE(vm);
2008
2009     JSValue base = exec->argument(0);
2010     if (!base.isObject())
2011         return JSValue::encode(jsUndefined());
2012     JSValue delegate = exec->argument(1);
2013     if (!delegate.isObject())
2014         return JSValue::encode(jsUndefined());
2015     ImpureGetter* impureGetter = jsDynamicCast<ImpureGetter*>(vm, asObject(base.asCell()));
2016     if (UNLIKELY(!impureGetter)) {
2017         throwTypeError(exec, scope, ASCIILiteral("argument is not an ImpureGetter"));
2018         return encodedJSValue();
2019     }
2020     impureGetter->setDelegate(vm, asObject(delegate.asCell()));
2021     return JSValue::encode(jsUndefined());
2022 }
2023
2024 EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
2025 {
2026     JSLockHolder lock(exec);
2027     exec->heap()->collectAllGarbage();
2028     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
2029 }
2030
2031 EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
2032 {
2033     JSLockHolder lock(exec);
2034     exec->heap()->collectSync(CollectionScope::Full);
2035     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
2036 }
2037
2038 EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
2039 {
2040     JSLockHolder lock(exec);
2041     exec->heap()->collectSync(CollectionScope::Eden);
2042     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastEdenCollection()));
2043 }
2044
2045 EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*)
2046 {
2047     // It's best for this to be the first thing called in the 
2048     // JS program so the option is set to true before we JIT.
2049     Options::forceGCSlowPaths() = true;
2050     return JSValue::encode(jsUndefined());
2051 }
2052
2053 EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState* exec)
2054 {
2055     JSLockHolder lock(exec);
2056     return JSValue::encode(jsNumber(exec->heap()->size()));
2057 }
2058
2059 // This function is not generally very helpful in 64-bit code as the tag and payload
2060 // share a register. But in 32-bit JITed code the tag may not be checked if an
2061 // optimization removes type checking requirements, such as in ===.
2062 EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState* exec)
2063 {
2064     JSValue value = exec->argument(0);
2065     if (!value.isCell())
2066         return JSValue::encode(jsUndefined());
2067     // Need to cast to uint64_t so bitwise_cast will play along.
2068     uint64_t asNumber = reinterpret_cast<uint64_t>(value.asCell());
2069     EncodedJSValue returnValue = JSValue::encode(jsNumber(bitwise_cast<double>(asNumber)));
2070     return returnValue;
2071 }
2072
2073 static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState* exec)
2074 {
2075     JSValue value = exec->argument(0);
2076     if (!value.isObject())
2077         return JSValue::encode(jsUndefined());
2078
2079     JSValue property = exec->argument(1);
2080     if (!property.isString())
2081         return JSValue::encode(jsUndefined());
2082
2083     PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry);
2084     value.getPropertySlot(exec, asString(property)->toIdentifier(exec), slot);
2085
2086     JSValue result;
2087     if (slot.isCacheableGetter())
2088         result = slot.getterSetter();
2089     else
2090         result = jsNull();
2091
2092     return JSValue::encode(result);
2093 }
2094
2095 EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
2096 {
2097     // We need this function for compatibility with the Mozilla JS tests but for now
2098     // we don't actually do any version-specific handling
2099     return JSValue::encode(jsUndefined());
2100 }
2101
2102 EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
2103 {
2104     VM& vm = exec->vm();
2105     auto scope = DECLARE_THROW_SCOPE(vm);
2106
2107     String fileName = exec->argument(0).toWTFString(exec);
2108     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2109     Vector<char> script;
2110     if (!fetchScriptFromLocalFileSystem(fileName, script))
2111         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Could not open file."))));
2112
2113     GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
2114
2115     JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
2116     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2117     for (unsigned i = 1; i < exec->argumentCount(); ++i) {
2118         array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
2119         RETURN_IF_EXCEPTION(scope, encodedJSValue());
2120     }
2121     globalObject->putDirect(
2122         vm, Identifier::fromString(globalObject->globalExec(), "arguments"), array);
2123
2124     NakedPtr<Exception> exception;
2125     StopWatch stopWatch;
2126     stopWatch.start();
2127     evaluate(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), exception);
2128     stopWatch.stop();
2129
2130     if (exception) {
2131         throwException(globalObject->globalExec(), scope, exception);
2132         return JSValue::encode(jsUndefined());
2133     }
2134     
2135     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
2136 }
2137
2138 EncodedJSValue JSC_HOST_CALL functionRunString(ExecState* exec)
2139 {
2140     VM& vm = exec->vm();
2141     auto scope = DECLARE_THROW_SCOPE(vm);
2142
2143     String source = exec->argument(0).toWTFString(exec);
2144     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2145
2146     GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
2147
2148     JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
2149     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2150     for (unsigned i = 1; i < exec->argumentCount(); ++i) {
2151         array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
2152         RETURN_IF_EXCEPTION(scope, encodedJSValue());
2153     }
2154     globalObject->putDirect(
2155         vm, Identifier::fromString(globalObject->globalExec(), "arguments"), array);
2156
2157     NakedPtr<Exception> exception;
2158     evaluate(globalObject->globalExec(), makeSource(source, exec->callerSourceOrigin()), JSValue(), exception);
2159
2160     if (exception) {
2161         scope.throwException(globalObject->globalExec(), exception);
2162         return JSValue::encode(jsUndefined());
2163     }
2164     
2165     return JSValue::encode(globalObject);
2166 }
2167
2168 EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
2169 {
2170     VM& vm = exec->vm();
2171     auto scope = DECLARE_THROW_SCOPE(vm);
2172
2173     String fileName = exec->argument(0).toWTFString(exec);
2174     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2175     Vector<char> script;
2176     if (!fetchScriptFromLocalFileSystem(fileName, script))
2177         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Could not open file."))));
2178
2179     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2180     
2181     NakedPtr<Exception> evaluationException;
2182     JSValue result = evaluate(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
2183     if (evaluationException)
2184         throwException(exec, scope, evaluationException);
2185     return JSValue::encode(result);
2186 }
2187
2188 EncodedJSValue JSC_HOST_CALL functionLoadString(ExecState* exec)
2189 {
2190     VM& vm = exec->vm();
2191     auto scope = DECLARE_THROW_SCOPE(vm);
2192
2193     String sourceCode = exec->argument(0).toWTFString(exec);
2194     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2195     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2196
2197     NakedPtr<Exception> evaluationException;
2198     JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode, exec->callerSourceOrigin()), JSValue(), evaluationException);
2199     if (evaluationException)
2200         throwException(exec, scope, evaluationException);
2201     return JSValue::encode(result);
2202 }
2203
2204 EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
2205 {
2206     VM& vm = exec->vm();
2207     auto scope = DECLARE_THROW_SCOPE(vm);
2208
2209     String fileName = exec->argument(0).toWTFString(exec);
2210     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2211
2212     bool isBinary = false;
2213     if (exec->argumentCount() > 1) {
2214         String type = exec->argument(1).toWTFString(exec);
2215         RETURN_IF_EXCEPTION(scope, encodedJSValue());
2216         if (type != "binary")
2217             return throwVMError(exec, scope, "Expected 'binary' as second argument.");
2218         isBinary = true;
2219     }
2220
2221     Vector<char> content;
2222     if (!fillBufferWithContentsOfFile(fileName, content))
2223         return throwVMError(exec, scope, "Could not open file.");
2224
2225     if (!isBinary)
2226         return JSValue::encode(jsString(exec, stringFromUTF(content)));
2227
2228     Structure* structure = exec->lexicalGlobalObject()->typedArrayStructure(TypeUint8);
2229     auto length = content.size();
2230     JSObject* result = createUint8TypedArray(exec, structure, ArrayBuffer::createFromBytes(content.releaseBuffer().leakPtr(), length, [] (void* p) { fastFree(p); }), 0, length);
2231     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2232
2233     return JSValue::encode(result);
2234 }
2235
2236 EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
2237 {
2238     VM& vm = exec->vm();
2239     auto scope = DECLARE_THROW_SCOPE(vm);
2240
2241     String fileName = exec->argument(0).toWTFString(exec);
2242     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2243     Vector<char> script;
2244     if (!fetchScriptFromLocalFileSystem(fileName, script))
2245         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Could not open file."))));
2246
2247     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2248
2249     StopWatch stopWatch;
2250     stopWatch.start();
2251
2252     JSValue syntaxException;
2253     bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), &syntaxException);
2254     stopWatch.stop();
2255
2256     if (!validSyntax)
2257         throwException(exec, scope, syntaxException);
2258     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
2259 }
2260
2261 #if ENABLE(SAMPLING_FLAGS)
2262 EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
2263 {
2264     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
2265         unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
2266         if ((flag >= 1) && (flag <= 32))
2267             SamplingFlags::setFlag(flag);
2268     }
2269     return JSValue::encode(jsNull());
2270 }
2271
2272 EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
2273 {
2274     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
2275         unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
2276         if ((flag >= 1) && (flag <= 32))
2277             SamplingFlags::clearFlag(flag);
2278     }
2279     return JSValue::encode(jsNull());
2280 }
2281 #endif
2282
2283 EncodedJSValue JSC_HOST_CALL functionShadowChickenFunctionsOnStack(ExecState* exec)
2284 {
2285     return JSValue::encode(exec->vm().shadowChicken().functionsOnStack(exec));
2286 }
2287
2288 EncodedJSValue JSC_HOST_CALL functionSetGlobalConstRedeclarationShouldNotThrow(ExecState* exec)
2289 {
2290     exec->vm().setGlobalConstRedeclarationShouldThrow(false);
2291     return JSValue::encode(jsUndefined());
2292 }
2293
2294 EncodedJSValue JSC_HOST_CALL functionGetRandomSeed(ExecState* exec)
2295 {
2296     return JSValue::encode(jsNumber(exec->lexicalGlobalObject()->weakRandom().seed()));
2297 }
2298
2299 EncodedJSValue JSC_HOST_CALL functionSetRandomSeed(ExecState* exec)
2300 {
2301     VM& vm = exec->vm();
2302     auto scope = DECLARE_THROW_SCOPE(vm);
2303
2304     unsigned seed = exec->argument(0).toUInt32(exec);
2305     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2306     exec->lexicalGlobalObject()->weakRandom().setSeed(seed);
2307     return JSValue::encode(jsUndefined());
2308 }
2309
2310 EncodedJSValue JSC_HOST_CALL functionIsRope(ExecState* exec)
2311 {
2312     JSValue argument = exec->argument(0);
2313     if (!argument.isString())
2314         return JSValue::encode(jsBoolean(false));
2315     const StringImpl* impl = asString(argument)->tryGetValueImpl();
2316     return JSValue::encode(jsBoolean(!impl));
2317 }
2318
2319 EncodedJSValue JSC_HOST_CALL functionCallerSourceOrigin(ExecState* state)
2320 {
2321     SourceOrigin sourceOrigin = state->callerSourceOrigin();
2322     if (sourceOrigin.isNull())
2323         return JSValue::encode(jsNull());
2324     return JSValue::encode(jsString(state, sourceOrigin.string()));
2325 }
2326
2327 EncodedJSValue JSC_HOST_CALL functionGlobalObjectForObject(ExecState* exec)
2328 {
2329     JSValue value = exec->argument(0);
2330     RELEASE_ASSERT(value.isObject());
2331     JSGlobalObject* globalObject = jsCast<JSObject*>(value)->globalObject();
2332     RELEASE_ASSERT(globalObject);
2333     return JSValue::encode(globalObject);
2334 }
2335
2336 EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
2337 {
2338     Vector<char, 256> line;
2339     int c;
2340     while ((c = getchar()) != EOF) {
2341         // FIXME: Should we also break on \r? 
2342         if (c == '\n')
2343             break;
2344         line.append(c);
2345     }
2346     line.append('\0');
2347     return JSValue::encode(jsString(exec, line.data()));
2348 }
2349
2350 EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
2351 {
2352     return JSValue::encode(jsNumber(currentTime()));
2353 }
2354
2355 EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState* exec)
2356 {
2357     return JSValue::encode(setNeverInline(exec));
2358 }
2359
2360 EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState* exec)
2361 {
2362     return JSValue::encode(setNeverOptimize(exec));
2363 }
2364
2365 EncodedJSValue JSC_HOST_CALL functionNoFTL(ExecState* exec)
2366 {
2367     VM& vm = exec->vm();
2368     if (JSFunction* function = jsDynamicCast<JSFunction*>(vm, exec->argument(0))) {
2369         FunctionExecutable* executable = function->jsExecutable();
2370         executable->setNeverFTLOptimize(true);
2371     }
2372
2373     return JSValue::encode(jsUndefined());
2374 }
2375
2376 EncodedJSValue JSC_HOST_CALL functionNoOSRExitFuzzing(ExecState* exec)
2377 {
2378     return JSValue::encode(setCannotUseOSRExitFuzzing(exec));
2379 }
2380
2381 EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
2382 {
2383     return JSValue::encode(optimizeNextInvocation(exec));
2384 }
2385
2386 EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
2387 {
2388     return JSValue::encode(numberOfDFGCompiles(exec));
2389 }
2390
2391 Message::Message(ArrayBufferContents&& contents, int32_t index)
2392     : m_contents(WTFMove(contents))
2393     , m_index(index)
2394 {
2395 }
2396
2397 Message::~Message()
2398 {
2399 }
2400
2401 Worker::Worker(Workers& workers)
2402     : m_workers(workers)
2403 {
2404     auto locker = holdLock(m_workers.m_lock);
2405     m_workers.m_workers.append(this);
2406     
2407     *currentWorker() = this;
2408 }
2409
2410 Worker::~Worker()
2411 {
2412     auto locker = holdLock(m_workers.m_lock);
2413     RELEASE_ASSERT(isOnList());
2414     remove();
2415 }
2416
2417 void Worker::enqueue(const AbstractLocker&, RefPtr<Message> message)
2418 {
2419     m_messages.append(message);
2420 }
2421
2422 RefPtr<Message> Worker::dequeue()
2423 {
2424     auto locker = holdLock(m_workers.m_lock);
2425     while (m_messages.isEmpty())
2426         m_workers.m_condition.wait(m_workers.m_lock);
2427     return m_messages.takeFirst();
2428 }
2429
2430 Worker& Worker::current()
2431 {
2432     return **currentWorker();
2433 }
2434
2435 ThreadSpecific<Worker*>& Worker::currentWorker()
2436 {
2437     static ThreadSpecific<Worker*>* result;
2438     static std::once_flag flag;
2439     std::call_once(
2440         flag,
2441         [] () {
2442             result = new ThreadSpecific<Worker*>();
2443         });
2444     return *result;
2445 }
2446
2447 Workers::Workers()
2448 {
2449 }
2450
2451 Workers::~Workers()
2452 {
2453     UNREACHABLE_FOR_PLATFORM();
2454 }
2455
2456 template<typename Func>
2457 void Workers::broadcast(const Func& func)
2458 {
2459     auto locker = holdLock(m_lock);
2460     for (Worker* worker = m_workers.begin(); worker != m_workers.end(); worker = worker->next()) {
2461         if (worker != &Worker::current())
2462             func(locker, *worker);
2463     }
2464     m_condition.notifyAll();
2465 }
2466
2467 void Workers::report(String string)
2468 {
2469     auto locker = holdLock(m_lock);
2470     m_reports.append(string.isolatedCopy());
2471     m_condition.notifyAll();
2472 }
2473
2474 String Workers::tryGetReport()
2475 {
2476     auto locker = holdLock(m_lock);
2477     if (m_reports.isEmpty())
2478         return String();
2479     return m_reports.takeFirst();
2480 }
2481
2482 String Workers::getReport()
2483 {
2484     auto locker = holdLock(m_lock);
2485     while (m_reports.isEmpty())
2486         m_condition.wait(m_lock);
2487     return m_reports.takeFirst();
2488 }
2489
2490 Workers& Workers::singleton()
2491 {
2492     static Workers* result;
2493     static std::once_flag flag;
2494     std::call_once(
2495         flag,
2496         [] {
2497             result = new Workers();
2498         });
2499     return *result;
2500 }
2501
2502 EncodedJSValue JSC_HOST_CALL functionDollarCreateRealm(ExecState* exec)
2503 {
2504     VM& vm = exec->vm();
2505     GlobalObject* result = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>());
2506     return JSValue::encode(result->getDirect(vm, Identifier::fromString(exec, "$")));
2507 }
2508
2509 EncodedJSValue JSC_HOST_CALL functionDollarDetachArrayBuffer(ExecState* exec)
2510 {
2511     return functionTransferArrayBuffer(exec);
2512 }
2513
2514 EncodedJSValue JSC_HOST_CALL functionDollarEvalScript(ExecState* exec)
2515 {
2516     VM& vm = exec->vm();
2517     auto scope = DECLARE_THROW_SCOPE(vm);
2518
2519     String sourceCode = exec->argument(0).toWTFString(exec);
2520     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2521     
2522     GlobalObject* globalObject = jsDynamicCast<GlobalObject*>(vm,
2523         exec->thisValue().get(exec, Identifier::fromString(exec, "global")));
2524     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2525     if (!globalObject)
2526         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected global to point to a global object"))));
2527     
2528     NakedPtr<Exception> evaluationException;
2529     JSValue result = evaluate(globalObject->globalExec(), makeSource(sourceCode, exec->callerSourceOrigin()), JSValue(), evaluationException);
2530     if (evaluationException)
2531         throwException(exec, scope, evaluationException);
2532     return JSValue::encode(result);
2533 }
2534
2535 EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState* exec)
2536 {
2537     VM& vm = exec->vm();
2538     auto scope = DECLARE_THROW_SCOPE(vm);
2539
2540     String sourceCode = exec->argument(0).toWTFString(exec).isolatedCopy();
2541     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2542     
2543     Lock didStartLock;
2544     Condition didStartCondition;
2545     bool didStart = false;
2546     
2547     RefPtr<Thread> thread = Thread::create(
2548         "JSC Agent",
2549         [sourceCode, &didStartLock, &didStartCondition, &didStart] () {
2550             CommandLine commandLine(0, nullptr);
2551             commandLine.m_interactive = false;
2552             runJSC(
2553                 commandLine,
2554                 [&] (VM&, GlobalObject* globalObject) {
2555                     // Notify the thread that started us that we have registered a worker.
2556                     {
2557                         auto locker = holdLock(didStartLock);
2558                         didStart = true;
2559                         didStartCondition.notifyOne();
2560                     }
2561                     
2562                     NakedPtr<Exception> evaluationException;
2563                     bool success = true;
2564                     JSValue result;
2565                     result = evaluate(globalObject->globalExec(), makeSource(sourceCode, SourceOrigin(ASCIILiteral("worker"))), JSValue(), evaluationException);
2566                     if (evaluationException)
2567                         result = evaluationException->value();
2568                     checkException(globalObject, true, evaluationException, result, String(), false, false, success);
2569                     if (!success)
2570                         exit(1);
2571                     return success;
2572                 });
2573         });
2574     thread->detach();
2575     
2576     {
2577         auto locker = holdLock(didStartLock);
2578         while (!didStart)
2579             didStartCondition.wait(didStartLock);
2580     }
2581     
2582     return JSValue::encode(jsUndefined());
2583 }
2584
2585 EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState* exec)
2586 {
2587     VM& vm = exec->vm();
2588     auto scope = DECLARE_THROW_SCOPE(vm);
2589
2590     JSValue callback = exec->argument(0);
2591     CallData callData;
2592     CallType callType = getCallData(callback, callData);
2593     if (callType == CallType::None)
2594         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected callback"))));
2595     
2596     RefPtr<Message> message;
2597     {
2598         ReleaseHeapAccessScope releaseAccess(vm.heap);
2599         message = Worker::current().dequeue();
2600     }
2601     
2602     RefPtr<ArrayBuffer> nativeBuffer = ArrayBuffer::create(message->releaseContents());
2603     ArrayBufferSharingMode sharingMode = nativeBuffer->sharingMode();
2604     JSArrayBuffer* jsBuffer = JSArrayBuffer::create(vm, exec->lexicalGlobalObject()->arrayBufferStructure(sharingMode), WTFMove(nativeBuffer));
2605     
2606     MarkedArgumentBuffer args;
2607     args.append(jsBuffer);
2608     args.append(jsNumber(message->index()));
2609     return JSValue::encode(call(exec, callback, callType, callData, jsNull(), args));
2610 }
2611
2612 EncodedJSValue JSC_HOST_CALL functionDollarAgentReport(ExecState* exec)
2613 {
2614     VM& vm = exec->vm();
2615     auto scope = DECLARE_THROW_SCOPE(vm);
2616
2617     String report = exec->argument(0).toWTFString(exec);
2618     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2619     
2620     Workers::singleton().report(report);
2621     
2622     return JSValue::encode(jsUndefined());
2623 }
2624
2625 EncodedJSValue JSC_HOST_CALL functionDollarAgentSleep(ExecState* exec)
2626 {
2627     VM& vm = exec->vm();
2628     auto scope = DECLARE_THROW_SCOPE(vm);
2629
2630     if (exec->argumentCount() >= 1) {
2631         Seconds seconds = Seconds::fromMilliseconds(exec->argument(0).toNumber(exec));
2632         RETURN_IF_EXCEPTION(scope, encodedJSValue());
2633         sleep(seconds);
2634     }
2635     return JSValue::encode(jsUndefined());
2636 }
2637
2638 EncodedJSValue JSC_HOST_CALL functionDollarAgentBroadcast(ExecState* exec)
2639 {
2640     VM& vm = exec->vm();
2641     auto scope = DECLARE_THROW_SCOPE(vm);
2642
2643     JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(vm, exec->argument(0));
2644     if (!jsBuffer || !jsBuffer->isShared())
2645         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected SharedArrayBuffer"))));
2646     
2647     int32_t index = exec->argument(1).toInt32(exec);
2648     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2649     
2650     Workers::singleton().broadcast(
2651         [&] (const AbstractLocker& locker, Worker& worker) {
2652             ArrayBuffer* nativeBuffer = jsBuffer->impl();
2653             ArrayBufferContents contents;
2654             nativeBuffer->transferTo(vm, contents); // "transferTo" means "share" if the buffer is shared.
2655             RefPtr<Message> message = adoptRef(new Message(WTFMove(contents), index));
2656             worker.enqueue(locker, message);
2657         });
2658     
2659     return JSValue::encode(jsUndefined());
2660 }
2661
2662 EncodedJSValue JSC_HOST_CALL functionDollarAgentGetReport(ExecState* exec)
2663 {
2664     VM& vm = exec->vm();
2665
2666     String string = Workers::singleton().tryGetReport();
2667     if (!string)
2668         return JSValue::encode(jsNull());
2669     
2670     return JSValue::encode(jsString(&vm, string));
2671 }
2672
2673 EncodedJSValue JSC_HOST_CALL functionDollarAgentLeaving(ExecState*)
2674 {
2675     return JSValue::encode(jsUndefined());
2676 }
2677
2678 EncodedJSValue JSC_HOST_CALL functionWaitForReport(ExecState* exec)
2679 {
2680     VM& vm = exec->vm();
2681
2682     String string;
2683     {
2684         ReleaseHeapAccessScope releaseAccess(vm.heap);
2685         string = Workers::singleton().getReport();
2686     }
2687     if (!string)
2688         return JSValue::encode(jsNull());
2689     
2690     return JSValue::encode(jsString(&vm, string));
2691 }
2692
2693 EncodedJSValue JSC_HOST_CALL functionHeapCapacity(ExecState* exec)
2694 {
2695     VM& vm = exec->vm();
2696     return JSValue::encode(jsNumber(vm.heap.capacity()));
2697 }
2698
2699 EncodedJSValue JSC_HOST_CALL functionFlashHeapAccess(ExecState* exec)
2700 {
2701     VM& vm = exec->vm();
2702     auto scope = DECLARE_THROW_SCOPE(vm);
2703     
2704     vm.heap.releaseAccess();
2705     if (exec->argumentCount() >= 1) {
2706         double ms = exec->argument(0).toNumber(exec);
2707         RETURN_IF_EXCEPTION(scope, encodedJSValue());
2708         sleep(Seconds::fromMilliseconds(ms));
2709     }
2710     vm.heap.acquireAccess();
2711     return JSValue::encode(jsUndefined());
2712 }
2713
2714 template<typename ValueType>
2715 typename std::enable_if<!std::is_fundamental<ValueType>::value>::type addOption(VM&, JSObject*, Identifier, ValueType) { }
2716
2717 template<typename ValueType>
2718 typename std::enable_if<std::is_fundamental<ValueType>::value>::type addOption(VM& vm, JSObject* optionsObject, Identifier identifier, ValueType value)
2719 {
2720     optionsObject->putDirect(vm, identifier, JSValue(value));
2721 }
2722
2723 EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState* exec)
2724 {
2725     JSObject* optionsObject = constructEmptyObject(exec);
2726 #define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
2727     addOption(exec->vm(), optionsObject, Identifier::fromString(exec, #name_), Options::name_());
2728     JSC_OPTIONS(FOR_EACH_OPTION)
2729 #undef FOR_EACH_OPTION
2730     return JSValue::encode(optionsObject);
2731 }
2732
2733 EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
2734 {
2735     if (exec->argumentCount() < 1)
2736         return JSValue::encode(jsUndefined());
2737     
2738     CodeBlock* block = getSomeBaselineCodeBlockForFunction(exec->argument(0));
2739     if (!block)
2740         return JSValue::encode(jsNumber(0));
2741     
2742     return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
2743 }
2744
2745 EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
2746 {
2747     VM& vm = exec->vm();
2748     auto scope = DECLARE_THROW_SCOPE(vm);
2749
2750     if (exec->argumentCount() < 1)
2751         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Not enough arguments"))));
2752     
2753     JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(vm, exec->argument(0));
2754     if (!buffer)
2755         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Expected an array buffer"))));
2756     
2757     ArrayBufferContents dummyContents;
2758     buffer->impl()->transferTo(vm, dummyContents);
2759     
2760     return JSValue::encode(jsUndefined());
2761 }
2762
2763 EncodedJSValue JSC_HOST_CALL functionFailNextNewCodeBlock(ExecState* exec)
2764 {
2765     exec->vm().setFailNextNewCodeBlock();
2766     return JSValue::encode(jsUndefined());
2767 }
2768
2769 EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
2770 {
2771     jscExit(EXIT_SUCCESS);
2772
2773 #if COMPILER(MSVC)
2774     // Without this, Visual Studio will complain that this method does not return a value.
2775     return JSValue::encode(jsUndefined());
2776 #endif
2777 }
2778
2779 EncodedJSValue JSC_HOST_CALL functionAbort(ExecState*)
2780 {
2781     CRASH();
2782 }
2783
2784 EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*) { return JSValue::encode(jsBoolean(false)); }
2785 EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*) { return JSValue::encode(jsBoolean(false)); }
2786
2787 EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
2788 EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
2789 EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState* exec)
2790 {
2791     for (size_t i = 0; i < exec->argumentCount(); ++i) {
2792         if (!exec->argument(i).isInt32())
2793             return JSValue::encode(jsBoolean(false));
2794     }
2795     return JSValue::encode(jsBoolean(true));
2796 }
2797
2798 EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
2799
2800 EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
2801 {
2802     return JSValue::encode(jsNumber(42));
2803 }
2804
2805 EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
2806 {
2807     return JSValue::encode(Masquerader::create(exec->vm(), exec->lexicalGlobalObject()));
2808 }
2809
2810 EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState* exec)
2811 {
2812     JSValue value = exec->argument(0);
2813     if (value.isObject())
2814         return JSValue::encode(jsBoolean(asObject(value)->hasCustomProperties()));
2815     return JSValue::encode(jsBoolean(false));
2816 }
2817
2818 EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
2819 {
2820     exec->vm().dumpTypeProfilerData();
2821     return JSValue::encode(jsUndefined());
2822 }
2823
2824 EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState* exec)
2825 {
2826     VM& vm = exec->vm();
2827     RELEASE_ASSERT(exec->vm().typeProfiler());
2828     vm.typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionFindTypeForExpression"));
2829
2830     JSValue functionValue = exec->argument(0);
2831     RELEASE_ASSERT(functionValue.isFunction());
2832     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
2833
2834     RELEASE_ASSERT(exec->argument(1).isString());
2835     String substring = asString(exec->argument(1))->value(exec);
2836     String sourceCodeText = executable->source().view().toString();
2837     unsigned offset = static_cast<unsigned>(sourceCodeText.find(substring) + executable->source().startOffset());
2838     
2839     String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorNormal, offset, executable->sourceID(), exec->vm());
2840     return JSValue::encode(JSONParse(exec, jsonString));
2841 }
2842
2843 EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState* exec)
2844 {
2845     VM& vm = exec->vm();
2846     RELEASE_ASSERT(exec->vm().typeProfiler());
2847     vm.typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionReturnTypeFor"));
2848
2849     JSValue functionValue = exec->argument(0);
2850     RELEASE_ASSERT(functionValue.isFunction());
2851     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
2852
2853     unsigned offset = executable->typeProfilingStartOffset();
2854     String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorFunctionReturn, offset, executable->sourceID(), exec->vm());
2855     return JSValue::encode(JSONParse(exec, jsonString));
2856 }
2857
2858 EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState* exec)
2859 {
2860     RELEASE_ASSERT(exec->vm().controlFlowProfiler());
2861     exec->vm().controlFlowProfiler()->dumpData();
2862     return JSValue::encode(jsUndefined());
2863 }
2864
2865 EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState* exec)
2866 {
2867     VM& vm = exec->vm();
2868     RELEASE_ASSERT(vm.controlFlowProfiler());
2869
2870     JSValue functionValue = exec->argument(0);
2871     RELEASE_ASSERT(functionValue.isFunction());
2872     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
2873
2874     RELEASE_ASSERT(exec->argument(1).isString());
2875     String substring = asString(exec->argument(1))->value(exec);
2876     String sourceCodeText = executable->source().view().toString();
2877     RELEASE_ASSERT(sourceCodeText.contains(substring));
2878     int offset = sourceCodeText.find(substring) + executable->source().startOffset();
2879     
2880     bool hasExecuted = vm.controlFlowProfiler()->hasBasicBlockAtTextOffsetBeenExecuted(offset, executable->sourceID(), vm);
2881     return JSValue::encode(jsBoolean(hasExecuted));
2882 }
2883
2884 EncodedJSValue JSC_HOST_CALL functionBasicBlockExecutionCount(ExecState* exec)
2885 {
2886     VM& vm = exec->vm();
2887     RELEASE_ASSERT(vm.controlFlowProfiler());
2888
2889     JSValue functionValue = exec->argument(0);
2890     RELEASE_ASSERT(functionValue.isFunction());
2891     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(vm, functionValue.asCell()->getObject()))->jsExecutable();
2892
2893     RELEASE_ASSERT(exec->argument(1).isString());
2894     String substring = asString(exec->argument(1))->value(exec);
2895     String sourceCodeText = executable->source().view().toString();
2896     RELEASE_ASSERT(sourceCodeText.contains(substring));
2897     int offset = sourceCodeText.find(substring) + executable->source().startOffset();
2898     
2899     size_t executionCount = vm.controlFlowProfiler()->basicBlockExecutionCountAtTextOffset(offset, executable->sourceID(), exec->vm());
2900     return JSValue::encode(JSValue(executionCount));
2901 }
2902
2903 EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*)
2904 {
2905     Options::useExceptionFuzz() = true;
2906     return JSValue::encode(jsUndefined());
2907 }
2908
2909 EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState* exec)
2910 {
2911     exec->vm().drainMicrotasks();
2912     return JSValue::encode(jsUndefined());
2913 }
2914
2915 EncodedJSValue JSC_HOST_CALL functionIs32BitPlatform(ExecState*)
2916 {
2917 #if USE(JSVALUE64)
2918     return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
2919 #else
2920     return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
2921 #endif
2922 }
2923
2924 EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState* exec)
2925 {
2926     VM& vm = exec->vm();
2927     auto scope = DECLARE_THROW_SCOPE(vm);
2928
2929     String fileName = exec->argument(0).toWTFString(exec);
2930     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2931     Vector<char> script;
2932     if (!fetchScriptFromLocalFileSystem(fileName, script))
2933         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Could not open file."))));
2934
2935     JSInternalPromise* promise = loadAndEvaluateModule(exec, fileName);
2936     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2937
2938     JSValue error;
2939     JSFunction* errorHandler = JSNativeStdFunction::create(vm, exec->lexicalGlobalObject(), 1, String(), [&](ExecState* exec) {
2940         error = exec->argument(0);
2941         return JSValue::encode(jsUndefined());
2942     });
2943
2944     promise->then(exec, nullptr, errorHandler);
2945     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2946     vm.drainMicrotasks();
2947     if (error)
2948         return JSValue::encode(throwException(exec, scope, error));
2949     return JSValue::encode(jsUndefined());
2950 }
2951
2952 EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState* exec)
2953 {
2954     VM& vm = exec->vm();
2955     auto scope = DECLARE_THROW_SCOPE(vm);
2956
2957     if (exec->argumentCount() < 1 || !exec->argument(0).isString())
2958         return JSValue::encode(jsUndefined());
2959
2960     String functionText = asString(exec->argument(0))->value(exec);
2961     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2962
2963     const SourceCode& source = makeSource(functionText, { });
2964     JSFunction* func = JSFunction::createBuiltinFunction(vm, createBuiltinExecutable(vm, source, Identifier::fromString(&vm, "foo"), ConstructorKind::None, ConstructAbility::CannotConstruct)->link(vm, source), exec->lexicalGlobalObject());
2965
2966     return JSValue::encode(func);
2967 }
2968
2969 EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState* exec)
2970 {
2971     VM& vm = exec->vm();
2972     return JSValue::encode(GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), Vector<String>()));
2973 }
2974
2975 EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState* exec)
2976 {
2977     VM& vm = exec->vm();
2978     auto scope = DECLARE_THROW_SCOPE(vm);
2979
2980     String source = exec->argument(0).toWTFString(exec);
2981     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2982
2983     StopWatch stopWatch;
2984     stopWatch.start();
2985
2986     ParserError error;
2987     bool validSyntax = checkModuleSyntax(exec, makeSource(source, { }, String(), TextPosition(), SourceProviderSourceType::Module), error);
2988     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2989     stopWatch.stop();
2990
2991     if (!validSyntax)
2992         throwException(exec, scope, jsNontrivialString(exec, toString("SyntaxError: ", error.message(), ":", error.line())));
2993     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
2994 }
2995
2996 EncodedJSValue JSC_HOST_CALL functionPlatformSupportsSamplingProfiler(ExecState*)
2997 {
2998 #if ENABLE(SAMPLING_PROFILER)
2999     return JSValue::encode(JSValue(JSC::JSValue::JSTrue));
3000 #else
3001     return JSValue::encode(JSValue(JSC::JSValue::JSFalse));
3002 #endif
3003 }
3004
3005 EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState* exec)
3006 {
3007     VM& vm = exec->vm();
3008     JSLockHolder lock(vm);
3009     auto scope = DECLARE_THROW_SCOPE(vm);
3010
3011     HeapSnapshotBuilder snapshotBuilder(exec->vm().ensureHeapProfiler());
3012     snapshotBuilder.buildSnapshot();
3013
3014     String jsonString = snapshotBuilder.json();
3015     EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
3016     RELEASE_ASSERT(!scope.exception());
3017     return result;
3018 }
3019
3020 EncodedJSValue JSC_HOST_CALL functionResetSuperSamplerState(ExecState*)
3021 {
3022     resetSuperSamplerState();
3023     return JSValue::encode(jsUndefined());
3024 }
3025
3026 EncodedJSValue JSC_HOST_CALL functionEnsureArrayStorage(ExecState* exec)
3027 {
3028     VM& vm = exec->vm();
3029     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
3030         if (JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(0)))
3031             object->ensureArrayStorage(exec->vm());
3032     }
3033     return JSValue::encode(jsUndefined());
3034 }
3035
3036 #if ENABLE(SAMPLING_PROFILER)
3037 EncodedJSValue JSC_HOST_CALL functionStartSamplingProfiler(ExecState* exec)
3038 {
3039     SamplingProfiler& samplingProfiler = exec->vm().ensureSamplingProfiler(WTF::Stopwatch::create());
3040     samplingProfiler.noticeCurrentThreadAsJSCExecutionThread();
3041     samplingProfiler.start();
3042     return JSValue::encode(jsUndefined());
3043 }
3044
3045 EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState* exec)
3046 {
3047     VM& vm = exec->vm();
3048     auto scope = DECLARE_THROW_SCOPE(vm);
3049
3050     if (!vm.samplingProfiler())
3051         return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("Sampling profiler was never started"))));
3052
3053     String jsonString = vm.samplingProfiler()->stackTracesAsJSON();
3054     EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
3055     RELEASE_ASSERT(!scope.exception());
3056     return result;
3057 }
3058 #endif // ENABLE(SAMPLING_PROFILER)
3059
3060 EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*)
3061 {
3062     return JSValue::encode(jsNumber(JSC::maxArguments));
3063 }
3064
3065 EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState* exec)
3066 {
3067     VM& vm = exec->vm();
3068     auto scope = DECLARE_THROW_SCOPE(vm);
3069
3070     JSValue numberOfAsyncPasses = exec->argument(0);
3071     if (!numberOfAsyncPasses.isUInt32())
3072         return throwVMError(exec, scope, ASCIILiteral("Expected first argument to a uint32"));
3073
3074     asyncTestExpectedPasses += numberOfAsyncPasses.asUInt32();
3075     return encodedJSUndefined();
3076 }
3077
3078 EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*)
3079 {
3080     asyncTestPasses++;
3081     return encodedJSUndefined();
3082 }
3083
3084 #if ENABLE(WEBASSEMBLY)
3085
3086 static CString valueWithTypeOfWasmValue(ExecState* exec, VM& vm, JSValue value, JSValue wasmValue)
3087 {
3088     JSString* type = asString(wasmValue.get(exec, makeIdentifier(vm, "type")));
3089
3090     const String& typeString = type->value(exec);
3091     if (typeString == "i64" || typeString == "i32")
3092         return toCString(typeString, " ", RawPointer(bitwise_cast<void*>(value)));
3093     if (typeString == "f32")
3094         return toCString(typeString, " hex: ", RawPointer(bitwise_cast<void*>(value)), ", float: ", bitwise_cast<float>(static_cast<uint32_t>(JSValue::encode(value))));
3095     return toCString(typeString, " hex: ", RawPointer(bitwise_cast<void*>(value)), ", double: ", bitwise_cast<double>(value));
3096 }
3097
3098 static JSValue box(ExecState* exec, VM& vm, JSValue wasmValue)
3099 {
3100     auto scope = DECLARE_CATCH_SCOPE(vm);
3101
3102     JSString* type = asString(wasmValue.get(exec, makeIdentifier(vm, "type")));
3103     ASSERT_UNUSED(scope, !scope.exception());
3104     JSValue value = wasmValue.get(exec, makeIdentifier(vm, "value"));
3105     ASSERT(!scope.exception());
3106
3107     auto unboxString = [&] (const char* hexFormat, const char* decFormat, auto& result) {
3108         if (!value.isString())
3109             return false;
3110
3111         const char* str = toCString(asString(value)->value(exec)).data();
3112         int scanResult;
3113         int length = std::strlen(str);
3114         if ((length > 2 && (str[0] == '0' && str[1] == 'x'))
3115             || (length > 3 && (str[0] == '-' && str[1] == '0' && str[2] == 'x')))
3116 #if COMPILER(CLANG)
3117 #pragma clang diagnostic push
3118 #pragma clang diagnostic ignored "-Wformat-nonliteral"
3119 #endif
3120             scanResult = sscanf(str, hexFormat, &result);
3121         else
3122             scanResult = sscanf(str, decFormat, &result);
3123 #if COMPILER(CLANG)
3124 #pragma clang diagnostic pop
3125 #endif
3126         RELEASE_ASSERT(scanResult != EOF);
3127         return true;
3128     };
3129
3130     const String& typeString = type->value(exec);
3131     if (typeString == "i64") {
3132         int64_t result;
3133         if (!unboxString("%llx", "%lld", result))
3134             CRASH();
3135         return JSValue::decode(result);
3136     }
3137
3138     if (typeString == "i32") {
3139         int32_t result;
3140         if (!unboxString("%x", "%d", result))
3141             result = value.asInt32();
3142         return JSValue::decode(static_cast<uint32_t>(result));
3143     }
3144
3145     if (typeString == "f32") {
3146         float result;
3147         if (!unboxString("%a", "%f", result))
3148             result = value.toFloat(exec);
3149         return JSValue::decode(bitwise_cast<uint32_t>(result));
3150     }
3151
3152     RELEASE_ASSERT(typeString == "f64");
3153     double result;
3154     if (!unboxString("%la", "%lf", result))
3155         result = value.asNumber();
3156     return JSValue::decode(bitwise_cast<uint64_t>(result));
3157 }
3158
3159 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=168582.
3160 static JSValue callWasmFunction(VM* vm, JSGlobalObject* globalObject, Wasm::Callee* wasmCallee, const ArgList& boxedArgs)
3161 {
3162     JSValue firstArgument;
3163     int argCount = 1;
3164     JSValue* remainingArgs = nullptr;
3165     if (boxedArgs.size()) {
3166         remainingArgs = boxedArgs.data();
3167         firstArgument = *remainingArgs;
3168         remainingArgs++;
3169         argCount = boxedArgs.size();
3170     }
3171
3172     ProtoCallFrame protoCallFrame;
3173     protoCallFrame.init(nullptr, globalObject->globalExec()->jsCallee(), firstArgument, argCount, remainingArgs);
3174
3175     return JSValue::decode(vmEntryToWasm(wasmCallee->entrypoint(), vm, &protoCallFrame));
3176 }
3177
3178 // testWasmModule(JSArrayBufferView source, number functionCount, ...[[WasmValue, [WasmValue]]]) where the ith copy of [[result, [args]]] is a list
3179 // of arguments to be passed to the ith wasm function as well as the expected result. WasmValue is an object with "type" and "value" properties.
3180 static EncodedJSValue JSC_HOST_CALL functionTestWasmModuleFunctions(ExecState* exec)
3181 {
3182     VM& vm = exec->vm();
3183     auto scope = DECLARE_THROW_SCOPE(vm);
3184
3185     if (!Options::useWebAssembly())
3186         return throwVMTypeError(exec, scope, ASCIILiteral("testWasmModule should only be called if the useWebAssembly option is set"));
3187
3188     JSArrayBufferView* source = jsCast<JSArrayBufferView*>(exec->argument(0));
3189     uint32_t functionCount = exec->argument(1).toUInt32(exec);
3190
3191     if (exec->argumentCount() != functionCount + 2)
3192         CRASH();
3193
3194     Ref<Wasm::BBQPlan> plan = adoptRef(*new Wasm::BBQPlan(nullptr, static_cast<uint8_t*>(source->vector()), source->length(), Wasm::BBQPlan::FullCompile, Wasm::Plan::dontFinalize()));
3195     Wasm::ensureWorklist().enqueue(plan.copyRef());
3196     Wasm::ensureWorklist().completePlanSynchronously(plan.get());
3197     if (plan->failed()) {
3198         dataLogLn("failed to parse module: ", plan->errorMessage());
3199         CRASH();
3200     }
3201
3202     if (plan->internalFunctionCount() != functionCount)
3203         CRASH();
3204
3205     Vector<Ref<Wasm::Callee>> jsEntrypointCallees;
3206     Vector<Ref<Wasm::Callee>> wasmEntrypointCallees;
3207     {
3208         unsigned lastIndex = UINT_MAX;
3209         plan->initializeCallees(
3210             [&] (unsigned calleeIndex, Ref<Wasm::Callee>&& jsEntrypointCallee, Ref<Wasm::Callee>&& wasmEntrypointCallee) {
3211                 RELEASE_ASSERT(!calleeIndex || (calleeIndex - 1 == lastIndex));
3212                 jsEntrypointCallees.append(WTFMove(jsEntrypointCallee));
3213                 wasmEntrypointCallees.append(WTFMove(wasmEntrypointCallee));
3214                 lastIndex = calleeIndex;
3215             });
3216     }
3217     Ref<Wasm::ModuleInformation> moduleInformation = plan->takeModuleInformation();
3218     RELEASE_ASSERT(!moduleInformation->memory);
3219
3220     for (uint32_t i = 0; i < functionCount; ++i) {
3221         JSArray* testCases = jsCast<JSArray*>(exec->argument(i + 2));
3222         for (unsigned testIndex = 0; testIndex < testCases->length(); ++testIndex) {
3223             JSArray* test = jsCast<JSArray*>(testCases->getIndexQuickly(testIndex));
3224             JSObject* result = jsCast<JSObject*>(test->getIndexQuickly(0));
3225             JSArray* arguments = jsCast<JSArray*>(test->getIndexQuickly(1));
3226
3227             MarkedArgumentBuffer boxedArgs;
3228             if (!Wasm::useFastTLSForContext()) {
3229                 // When not using fast TLS, the code we emit expects Wasm::Context*
3230                 // as the first argument. These tests that this API supports don't ever
3231                 // use a Context. So this is just a hack to get it to not barf.
3232                 // We really need to remove this API.
3233                 boxedArgs.append(jsNumber(0xbadbeef));
3234             }
3235             for (unsigned argIndex = 0; argIndex < arguments->length(); ++argIndex)
3236                 boxedArgs.append(box(exec, vm, arguments->getIndexQuickly(argIndex)));
3237
3238             JSValue callResult;
3239             {
3240                 auto scope = DECLARE_THROW_SCOPE(vm);
3241                 callResult = callWasmFunction(&vm, exec->lexicalGlobalObject(), jsEntrypointCallees[i].ptr(), boxedArgs);
3242                 RETURN_IF_EXCEPTION(scope, { });
3243             }
3244             JSValue expected = box(exec, vm, result);
3245             if (callResult != expected) {
3246                 dataLog("Arguments: ");
3247                 CommaPrinter comma(", ");
3248                 for (unsigned argIndex = 0; argIndex < arguments->length(); ++argIndex)
3249                     dataLog(comma, valueWithTypeOfWasmValue(exec, vm, boxedArgs.at(argIndex), arguments->getIndexQuickly(argIndex)));
3250                 dataLogLn();
3251
3252                 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, toCString(" (callResult == ", valueWithTypeOfWasmValue(exec, vm, callResult, result), ", expected == ", valueWithTypeOfWasmValue(exec, vm, expected, result), ")").data());
3253                 CRASH();
3254             }
3255         }
3256     }
3257
3258     return encodedJSUndefined();
3259 }
3260
3261 static EncodedJSValue JSC_HOST_CALL functionWebAssemblyMemoryMode(ExecState* exec)
3262 {
3263     VM& vm = exec->vm();
3264     auto scope = DECLARE_THROW_SCOPE(vm);
3265     
3266     if (!Options::useWebAssembly())
3267         return throwVMTypeError(exec, scope, ASCIILiteral("WebAssemblyMemoryMode should only be called if the useWebAssembly option is set"));
3268
3269     if (JSObject* object = exec->argument(0).getObject()) {
3270         if (auto* memory = jsDynamicCast<JSWebAssemblyMemory*>(vm, object))
3271             return JSValue::encode(jsString(&vm, makeString(memory->memory().mode())));
3272         if (auto* instance = jsDynamicCast<JSWebAssemblyInstance*>(vm, object))
3273             return JSValue::encode(jsString(&vm, makeString(instance->memoryMode())));
3274     }
3275
3276     return throwVMTypeError(exec, scope, ASCIILiteral("WebAssemblyMemoryMode expects either a WebAssembly.Memory or WebAssembly.Instance"));
3277 }
3278
3279 #endif // ENABLE(WEBASSEBLY)
3280
3281 // Use SEH for Release builds only to get rid of the crash report dialog
3282 // (luckily the same tests fail in Release and Debug builds so far). Need to
3283 // be in a separate main function because the jscmain function requires object
3284 // unwinding.
3285
3286 #if COMPILER(MSVC) && !defined(_DEBUG)
3287 #define TRY       __try {
3288 #define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
3289 #else
3290 #define TRY
3291 #define EXCEPT(x)
3292 #endif
3293
3294 int jscmain(int argc, char** argv);
3295
3296 static double s_desiredTimeout;
3297 static double s_timeoutMultiplier = 1.0;
3298
3299 static NO_RETURN_DUE_TO_CRASH void timeoutThreadMain(void*)
3300 {
3301     Seconds timeoutDuration(s_desiredTimeout * s_timeoutMultiplier);
3302     sleep(timeoutDuration);
3303     dataLog("Timed out after ", timeoutDuration, " seconds!\n");
3304     CRASH();
3305 }
3306
3307 static void startTimeoutThreadIfNeeded()
3308 {
3309     if (char* timeoutString = getenv("JSCTEST_timeout")) {
3310         if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
3311             dataLog("WARNING: timeout string is malformed, got ", timeoutString,
3312                 " but expected a number. Not using a timeout.\n");
3313         } else
3314             Thread::create(timeoutThreadMain, 0, "jsc Timeout Thread");
3315     }
3316 }
3317
3318 int main(int argc, char** argv)
3319 {
3320 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
3321     // Enabled IEEE754 denormal support.
3322     fenv_t env;
3323     fegetenv( &env );
3324     env.__fpscr &= ~0x01000000u;
3325     fesetenv( &env );
3326 #endif
3327
3328 #if OS(WINDOWS)
3329     // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
3330     // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
3331     // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
3332     ::SetErrorMode(0);
3333
3334 #if defined(_DEBUG)
3335     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3336     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
3337     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3338     _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
3339     _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3340     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
3341 #endif
3342
3343     timeBeginPeriod(1);
3344 #endif
3345
3346 #if PLATFORM(GTK)
3347     if (!setlocale(LC_ALL, ""))
3348         WTFLogAlways("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
3349 #endif
3350
3351     // Need to initialize WTF threading before we start any threads. Cannot initialize JSC
3352     // threading yet, since that would do somethings that we'd like to defer until after we
3353     // have a chance to parse options.
3354     WTF::initializeThreading();
3355
3356 #if PLATFORM(IOS)
3357     Options::crashIfCantAllocateJITMemory() = true;
3358 #endif
3359
3360     // We can't use destructors in the following code because it uses Windows
3361     // Structured Exception Handling
3362     int res = 0;
3363     TRY
3364         res = jscmain(argc, argv);
3365     EXCEPT(res = 3)
3366     finalizeStatsAtEndOfTesting();
3367
3368     jscExit(res);
3369 }
3370
3371 static void dumpException(GlobalObject* globalObject, JSValue exception)
3372 {
3373     VM& vm = globalObject->vm();
3374     auto scope = DECLARE_CATCH_SCOPE(vm);
3375
3376 #define CHECK_EXCEPTION() do { \
3377         if (scope.exception()) { \
3378             scope.clearException(); \
3379             return; \
3380         } \
3381     } while (false)
3382
3383     printf("Exception: %s\n", exception.toWTFString(globalObject->globalExec()).utf8().data());
3384
3385     Identifier nameID = Identifier::fromString(globalObject->globalExec(), "name");
3386     CHECK_EXCEPTION();
3387     Identifier fileNameID = Identifier::fromString(globalObject->globalExec(), "sourceURL");
3388     CHECK_EXCEPTION();
3389     Identifier lineNumberID = Identifier::fromString(globalObject->globalExec(), "line");
3390     CHECK_EXCEPTION();
3391     Identifier stackID = Identifier::fromString(globalObject->globalExec(), "stack");
3392     CHECK_EXCEPTION();
3393
3394     JSValue nameValue = exception.get(globalObject->globalExec(), nameID);
3395     CHECK_EXCEPTION();
3396     JSValue fileNameValue = exception.get(globalObject->globalExec(), fileNameID);
3397     CHECK_EXCEPTION();
3398     JSValue lineNumberValue = exception.get(globalObject->globalExec(), lineNumberID);
3399     CHECK_EXCEPTION();
3400     JSValue stackValue = exception.get(globalObject->globalExec(), stackID);
3401     CHECK_EXCEPTION();
3402     
3403     if (nameValue.toWTFString(globalObject->globalExec()) == "SyntaxError"
3404         && (!fileNameValue.isUndefinedOrNull() || !lineNumberValue.isUndefinedOrNull())) {
3405         printf(
3406             "at %s:%s\n",
3407             fileNameValue.toWTFString(globalObject->globalExec()).utf8().data(),
3408             lineNumberValue.toWTFString(globalObject->globalExec()).utf8().data());
3409     }
3410     
3411     if (!stackValue.isUndefinedOrNull()) {
3412         auto stackString = stackValue.toWTFString(globalObject->globalExec());
3413         if (stackString.length())
3414             printf("%s\n", stackString.utf8().data());
3415     }
3416
3417 #undef CHECK_EXCEPTION
3418 }
3419
3420 static bool checkUncaughtException(VM& vm, GlobalObject* globalObject, JSValue exception, const String& expectedExceptionName, bool alwaysDumpException)
3421 {
3422     auto scope = DECLARE_CATCH_SCOPE(vm);
3423     scope.clearException();
3424     if (!exception) {
3425         printf("Expected uncaught exception with name '%s' but none was thrown\n", expectedExceptionName.utf8().data());
3426         return false;
3427     }
3428
3429     ExecState* exec = globalObject->globalExec();
3430     JSValue exceptionClass = globalObject->get(exec, Identifier::fromString(exec, expectedExceptionName));
3431     if (!exceptionClass.isObject() || scope.exception()) {
3432         printf("Expected uncaught exception with name '%s' but given exception class is not defined\n", expectedExceptionName.utf8().data());
3433         return false;
3434     }
3435
3436     bool isInstanceOfExpectedException = jsCast<JSObject*>(exceptionClass)->hasInstance(exec, exception);
3437     if (scope.exception()) {
3438         printf("Expected uncaught exception with name '%s' but given exception class fails performing hasInstance\n", expectedExceptionName.utf8().data());
3439         return false;
3440     }
3441     if (isInstanceOfExpectedException) {
3442         if (alwaysDumpException)
3443             dumpException(globalObject, exception);
3444         return true;
3445     }
3446
3447     printf("Expected uncaught exception with name '%s' but exception value is not instance of this exception class\n", expectedExceptionName.utf8().data());
3448     dumpException(globalObject, exception);
3449     return false;
3450 }
3451
3452 static void checkException(GlobalObject* globalObject, bool isLastFile, bool hasException, JSValue value, const String& uncaughtExceptionName, bool alwaysDumpUncaughtException, bool dump, bool& success)
3453 {
3454     VM& vm = globalObject->vm();
3455     if (!uncaughtExceptionName || !isLastFile) {
3456         success = success && !hasException;
3457         if (dump && !hasException)
3458             printf("End: %s\n", value.toWTFString(globalObject->globalExec()).utf8().data());
3459         if (hasException)
3460             dumpException(globalObject, value);
3461     } else
3462         success = success && checkUncaughtException(vm, globalObject, (hasException) ? value : JSValue(), uncaughtExceptionName, alwaysDumpUncaughtException);
3463 }
3464
3465 static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, const String& uncaughtExceptionName, bool alwaysDumpUncaughtException, bool dump, bool module)
3466 {
3467     String fileName;
3468     Vector<char> scriptBuffer;
3469
3470     if (dump)
3471         JSC::Options::dumpGeneratedBytecodes() = true;
3472
3473     VM& vm = globalObject->vm();
3474     auto scope = DECLARE_CATCH_SCOPE(vm);
3475     bool success = true;
3476
3477 #if ENABLE(SAMPLING_FLAGS)
3478     SamplingFlags::start();
3479 #endif
3480
3481     for (size_t i = 0; i < scripts.size(); i++) {
3482         JSInternalPromise* promise = nullptr;
3483         bool isModule = module || scripts[i].scriptType == Script::ScriptType::Module;
3484         if (scripts[i].codeSource == Script::CodeSource::File) {
3485             fileName = scripts[i].argument;
3486             if (scripts[i].strictMode == Script::StrictMode::Strict)
3487                 scriptBuffer.append("\"use strict\";\n", strlen("\"use strict\";\n"));
3488
3489             if (isModule) {
3490                 promise = loadAndEvaluateModule(globalObject->globalExec(), fileName);
3491                 RELEASE_ASSERT(!scope.exception());
3492             } else {
3493                 if (!fetchScriptFromLocalFileSystem(fileName, scriptBuffer))
3494                     return false; // fail early so we can catch missing files
3495             }
3496         } else {
3497             size_t commandLineLength = strlen(scripts[i].argument);
3498             scriptBuffer.resize(commandLineLength);
3499             std::copy(scripts[i].argument, scripts[i].argument + commandLineLength, scriptBuffer.begin());
3500             fileName = ASCIILiteral("[Command Line]");
3501         }
3502
3503         bool isLastFile = i == scripts.size() - 1;
3504         if (isModule) {
3505             if (!promise)
3506                 promise = loadAndEvaluateModule(globalObject->globalExec(), makeSource(stringFromUTF(scriptBuffer), SourceOrigin { absolutePath(fileName) }, fileName, TextPosition(), SourceProviderSourceType::Module));
3507             scope.clearException();
3508
3509             JSFunction* fulfillHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
3510                 checkException(globalObject, isLastFile, false, exec->argument(0), uncaughtExceptionName, alwaysDumpUncaughtException, dump, success);
3511                 return JSValue::encode(jsUndefined());
3512             });
3513
3514             JSFunction* rejectHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
3515                 checkException(globalObject, isLastFile, true, exec->argument(0), uncaughtExceptionName, alwaysDumpUncaughtException, dump, success);
3516                 return JSValue::encode(jsUndefined());
3517             });
3518
3519             promise->then(globalObject->globalExec(), fulfillHandler, rejectHandler);
3520             RELEASE_ASSERT(!scope.exception());
3521             vm.drainMicrotasks();
3522         } else {
3523             NakedPtr<Exception> evaluationException;
3524             JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(scriptBuffer, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
3525             ASSERT(!scope.exception());
3526             if (evaluationException)
3527                 returnValue = evaluationException->value();
3528             checkException(globalObject, isLastFile, evaluationException, returnValue, uncaughtExceptionName, alwaysDumpUncaughtException, dump, success);
3529         }
3530
3531         scriptBuffer.clear();
3532         scope.clearException();
3533     }
3534
3535 #if ENABLE(REGEXP_TRACING)
3536     vm.dumpRegExpTrace();
3537 #endif
3538     return success;
3539 }
3540
3541 #define RUNNING_FROM_XCODE 0
3542
3543 static void runInteractive(GlobalObject* globalObject)
3544 {
3545     VM& vm = globalObject->vm();
3546     auto scope = DECLARE_CATCH_SCOPE(vm);
3547
3548     std::optional<DirectoryName> directoryName = currentWorkingDirectory();
3549     if (!directoryName)
3550         return;
3551     SourceOrigin sourceOrigin(resolvePath(directoryName.value(), ModuleName("interpreter")));
3552     
3553     bool shouldQuit = false;
3554     while (!shouldQuit) {
3555 #if HAVE(READLINE) && !RUNNING_FROM_XCODE
3556         ParserError error;
3557         String source;
3558         do {
3559             error = ParserError();
3560             char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
3561             shouldQuit = !line;
3562             if (!line)
3563                 break;
3564             source = source + line;
3565             source = source + '\n';
3566             checkSyntax(globalObject->vm(), makeSource(source, sourceOrigin), error);
3567             if (!line[0]) {
3568                 free(line);
3569                 break;
3570             }
3571             add_history(line);
3572             free(line);
3573         } while (error.syntaxErrorType() == ParserError::SyntaxErrorRecoverable);
3574         
3575         if (error.isValid()) {
3576             printf("%s:%d\n", error.message().utf8().data(), error.line());
3577             continue;
3578         }
3579         
3580         
3581         NakedPtr<Exception> evaluationException;
3582         JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, sourceOrigin), JSValue(), evaluationException);
3583 #else
3584         printf("%s", interactivePrompt);
3585         Vector<char, 256> line;
3586         int c;
3587         while ((c = getchar()) != EOF) {
3588             // FIXME: Should we also break on \r? 
3589             if (c == '\n')
3590                 break;
3591             line.append(c);
3592         }
3593         if (line.isEmpty())
3594             break;
3595
3596         NakedPtr<Exception> evaluationException;
3597         JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line, sourceOrigin, sourceOrigin.string()), JSValue(), evaluationException);
3598 #endif
3599         if (evaluationException)
3600             printf("Exception: %s\n", evaluationException->value().toWTFString(globalObject->globalExec()).utf8().data());
3601         else
3602             printf("%s\n", returnValue.toWTFString(globalObject->globalExec()).utf8().data());
3603
3604         scope.clearException();
3605         globalObject->vm().drainMicrotasks();
3606     }
3607     printf("\n");
3608 }
3609
3610 static NO_RETURN void printUsageStatement(bool help = false)
3611 {
3612     fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
3613     fprintf(stderr, "  -d         Dumps bytecode (debug builds only)\n");
3614     fprintf(stderr, "  -e         Evaluate argument as script code\n");
3615     fprintf(stderr, "  -f         Specifies a source file (deprecated)\n");
3616     fprintf(stderr, "  -h|--help  Prints this help message\n");
3617     fprintf(stderr, "  -i         Enables interactive mode (default if no files are specified)\n");
3618     fprintf(stderr, "  -m         Execute as a module\n");
3619 #if HAVE(SIGNAL_H)
3620     fprintf(stderr, "  -s         Installs signal handlers that exit on a crash (Unix platforms only)\n");
3621 #endif
3622     fprintf(stderr, "  -p <file>  Outputs profiling data to a file\n");
3623     fprintf(stderr, "  -x         Output exit code before terminating\n");
3624     fprintf(stderr, "\n");
3625     fprintf(stderr, "  --sample                   Collects and outputs sampling profiler data\n");
3626     fprintf(stderr, "  --test262-async            Check that some script calls the print function with the string 'Test262:AsyncTestComplete'\n");
3627     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");
3628     fprintf(stderr, "  --module-file=<file>       Parse and evaluate the given file as module (this option may be passed more than once)\n");
3629     fprintf(stderr, "  --exception=<name>         Check the last script exits with an uncaught exception with the specified name\n");
3630     fprintf(stderr, "  --dumpException            Dump uncaught exception text\n");
3631     fprintf(stderr, "  --options                  Dumps all JSC VM options and exits\n");
3632     fprintf(stderr, "  --dumpOptions              Dumps all non-default JSC VM options before continuing\n");
3633     fprintf(stderr, "  --<jsc VM option>=<value>  Sets the specified JSC VM option\n");
3634     fprintf(stderr, "\n");
3635
3636     jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
3637 }
3638
3639 void CommandLine::parseArguments(int argc, char** argv)
3640 {
3641     Options::initialize();
3642     
3643     int i = 1;
3644     JSC::Options::DumpLevel dumpOptionsLevel = JSC::Options::DumpLevel::None;
3645     bool needToExit = false;
3646
3647     bool hasBadJSCOptions = false;
3648     for (; i < argc; ++i) {
3649         const char* arg = argv[i];
3650         if (!strcmp(arg, "-f")) {
3651             if (++i == argc)
3652                 printUsageStatement();
3653             m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Script, argv[i]));
3654             continue;
3655         }
3656         if (!strcmp(arg, "-e")) {
3657             if (++i == argc)
3658                 printUsageStatement();
3659             m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::CommandLine, Script::ScriptType::Script, argv[i]));
3660             continue;
3661         }
3662         if (!strcmp(arg, "-i")) {
3663             m_interactive = true;
3664             continue;
3665         }
3666         if (!strcmp(arg, "-d")) {
3667             m_dump = true;
3668             continue;
3669         }
3670         if (!strcmp(arg, "-p")) {
3671             if (++i == argc)
3672                 printUsageStatement();
3673             m_profile = true;
3674             m_profilerOutput = argv[i];
3675             continue;
3676         }
3677         if (!strcmp(arg, "-m")) {
3678             m_module = true;
3679             continue;
3680         }
3681         if (!strcmp(arg, "-s")) {
3682 #if HAVE(SIGNAL_H)
3683             signal(SIGILL, _exit);
3684             signal(SIGFPE, _exit);
3685             signal(SIGBUS, _exit);
3686             signal(SIGSEGV, _exit);
3687 #endif
3688             continue;
3689         }
3690         if (!strcmp(arg, "-x")) {
3691             m_exitCode = true;
3692             continue;
3693         }
3694         if (!strcmp(arg, "--")) {
3695             ++i;
3696             break;
3697         }
3698         if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
3699             printUsageStatement(true);
3700
3701         if (!strcmp(arg, "--options")) {
3702             dumpOptionsLevel = JSC::Options::DumpLevel::Verbose;
3703             needToExit = true;
3704             continue;
3705         }
3706         if (!strcmp(arg, "--dumpOptions")) {
3707             dumpOptionsLevel = JSC::Options::DumpLevel::Overridden;
3708             continue;
3709         }
3710         if (!strcmp(arg, "--sample")) {
3711             JSC::Options::useSamplingProfiler() = true;
3712             JSC::Options::collectSamplingProfilerDataForJSCShell() = true;
3713             m_dumpSamplingProfilerData = true;
3714             continue;
3715         }
3716
3717         static const char* timeoutMultiplierOptStr = "--timeoutMultiplier=";
3718         static const unsigned timeoutMultiplierOptStrLength = strlen(timeoutMultiplierOptStr);
3719         if (!strncmp(arg, timeoutMultiplierOptStr, timeoutMultiplierOptStrLength)) {
3720             const char* valueStr = &arg[timeoutMultiplierOptStrLength];
3721             if (sscanf(valueStr, "%lf", &s_timeoutMultiplier) != 1)
3722                 dataLog("WARNING: --timeoutMultiplier=", valueStr, " is invalid. Expects a numeric ratio.\n");
3723             continue;
3724         }
3725
3726         if (!strcmp(arg, "--test262-async")) {
3727             asyncTestExpectedPasses++;
3728             continue;
3729         }
3730
3731         if (!strcmp(arg, "--remote-debug")) {
3732             m_enableRemoteDebugging = true;
3733             continue;
3734         }
3735
3736         static const unsigned strictFileStrLength = strlen("--strict-file=");
3737         if (!strncmp(arg, "--strict-file=", strictFileStrLength)) {
3738             m_scripts.append(Script(Script::StrictMode::Strict, Script::CodeSource::File, Script::ScriptType::Script, argv[i] + strictFileStrLength));
3739             continue;
3740         }
3741
3742         static const unsigned moduleFileStrLength = strlen("--module-file=");
3743         if (!strncmp(arg, "--module-file=", moduleFileStrLength)) {
3744             m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Module, argv[i] + moduleFileStrLength));
3745             continue;
3746         }
3747
3748         if (!strcmp(arg, "--dumpException")) {
3749             m_alwaysDumpUncaughtException = true;
3750             continue;
3751         }
3752
3753         static const unsigned exceptionStrLength = strlen("--exception=");
3754         if (!strncmp(arg, "--exception=", exceptionStrLength)) {
3755             m_uncaughtExceptionName = String(arg + exceptionStrLength);
3756             continue;
3757         }
3758
3759         // See if the -- option is a JSC VM option.
3760         if (strstr(arg, "--") == arg) {
3761             if (!JSC::Options::setOption(&arg[2])) {
3762                 hasBadJSCOptions = true;
3763                 dataLog("ERROR: invalid option: ", arg, "\n");
3764             }
3765             continue;
3766         }
3767
3768         // This arg is not recognized by the VM nor by jsc. Pass it on to the
3769         // script.
3770         m_scripts.append(Script(Script::StrictMode::Sloppy, Script::CodeSource::File, Script::ScriptType::Script, argv[i]));
3771     }
3772
3773     if (hasBadJSCOptions && JSC::Options::validateOptions())
3774         CRASH();
3775
3776     if (m_scripts.isEmpty())
3777         m_interactive = true;
3778
3779     for (; i < argc; ++i)
3780         m_arguments.append(argv[i]);
3781
3782     if (dumpOptionsLevel != JSC::Options::DumpLevel::None) {
3783         const char* optionsTitle = (dumpOptionsLevel == JSC::Options::DumpLevel::Overridden)
3784             ? "Modified JSC runtime options:"
3785             : "All JSC runtime options:";
3786         JSC::Options::dumpAllOptions(stderr, dumpOptionsLevel, optionsTitle);
3787     }
3788     JSC::Options::ensureOptionsAreCoherent();
3789     if (needToExit)
3790         jscExit(EXIT_SUCCESS);
3791 }
3792
3793 template<typename Func>
3794 int runJSC(CommandLine options, const Func& func)
3795 {
3796     Worker worker(Workers::singleton());
3797     
3798     VM& vm = VM::create(LargeHeap).leakRef();
3799     int result;
3800     bool success;
3801     {
3802         JSLockHolder locker(vm);
3803
3804         if (options.m_profile && !vm.m_perBytecodeProfiler)
3805             vm.m_perBytecodeProfiler = std::make_unique<Profiler::Database>(vm);
3806
3807         GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), options.m_arguments);
3808         globalObject->setRemoteDebuggingEnabled(options.m_enableRemoteDebugging);
3809         success = func(vm, globalObject);
3810         if (options.m_interactive && success)
3811             runInteractive(globalObject);
3812
3813         vm.drainMicrotasks();
3814     }
3815     vm.promiseDeferredTimer->runRunLoop();
3816
3817     result = success && (asyncTestExpectedPasses == asyncTestPasses) ? 0 : 3;
3818
3819     if (options.m_exitCode) {
3820         printf("jsc exiting %d", result);
3821         if (asyncTestExpectedPasses != asyncTestPasses)
3822             printf(" because expected: %d async test passes but got: %d async test passes", asyncTestExpectedPasses, asyncTestPasses);
3823         printf("\n");
3824     }
3825
3826     if (options.m_profile) {
3827         JSLockHolder locker(vm);
3828         if (!vm.m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
3829             fprintf(stderr, "could not save profiler output.\n");
3830     }
3831
3832 #if ENABLE(JIT)
3833     {
3834         JSLockHolder locker(vm);
3835         if (Options::useExceptionFuzz())
3836             printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
3837         bool fireAtEnabled =
3838         Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
3839         if (Options::useExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
3840             printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks());
3841         if (Options::useOSRExitFuzz()) {
3842             printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks());
3843             printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks());
3844         }
3845
3846         
3847         auto compileTimeStats = JIT::compileTimeStats();
3848         Vector<CString> compileTimeKeys;
3849         for (auto& entry : compileTimeStats)
3850             compileTimeKeys.append(entry.key);
3851         std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
3852         for (CString key : compileTimeKeys)
3853             printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key));
3854     }
3855 #endif
3856
3857     if (Options::gcAtEnd()) {
3858         // We need to hold the API lock to do a GC.
3859         JSLockHolder locker(&vm);
3860         vm.heap.collectAllGarbage();
3861     }
3862
3863     if (options.m_dumpSamplingProfilerData) {
3864 #if ENABLE(SAMPLING_PROFILER)
3865         JSLockHolder locker(&vm);
3866         vm.samplingProfiler()->reportTopFunctions();
3867         vm.samplingProfiler()->reportTopBytecodes();
3868 #else
3869         dataLog("Sampling profiler is not enabled on this platform\n");
3870 #endif
3871     }
3872
3873     return result;
3874 }
3875
3876 int jscmain(int argc, char** argv)
3877 {
3878     // Need to override and enable restricted options before we start parsing options below.
3879     Options::enableRestrictedOptions(true);
3880
3881     // Note that the options parsing can affect VM creation, and thus
3882     // comes first.
3883     CommandLine options(argc, argv);
3884
3885     processConfigFile(Options::configFile(), "jsc");
3886
3887     // Initialize JSC before getting VM.
3888     WTF::initializeMainThread();
3889     JSC::initializeThreading();
3890     startTimeoutThreadIfNeeded();
3891 #if ENABLE(WEBASSEMBLY)
3892     JSC::Wasm::enableFastMemory();
3893 #endif
3894
3895     int result;
3896     result = runJSC(
3897         options,
3898         [&] (VM&, GlobalObject* globalObject) {
3899             return runWithScripts(globalObject, options.m_scripts, options.m_uncaughtExceptionName, options.m_alwaysDumpUncaughtException, options.m_dump, options.m_module);
3900         });
3901
3902     printSuperSamplerState();
3903
3904     return result;
3905 }
3906
3907 #if OS(WINDOWS)
3908 extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
3909 {
3910     return main(argc, const_cast<char**>(argv));
3911 }
3912 #endif