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