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