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