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