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