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