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