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