Add module loader "resolve" hook for local file system to test the loader in JSC...
[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 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 "ArrayPrototype.h"
26 #include "ButterflyInlines.h"
27 #include "BytecodeGenerator.h"
28 #include "CodeBlock.h"
29 #include "Completion.h"
30 #include "CopiedSpaceInlines.h"
31 #include "DFGPlan.h"
32 #include "Disassembler.h"
33 #include "Exception.h"
34 #include "ExceptionHelpers.h"
35 #include "HeapStatistics.h"
36 #include "InitializeThreading.h"
37 #include "Interpreter.h"
38 #include "JSArray.h"
39 #include "JSArrayBuffer.h"
40 #include "JSCInlines.h"
41 #include "JSFunction.h"
42 #include "JSInternalPromise.h"
43 #include "JSInternalPromiseDeferred.h"
44 #include "JSLock.h"
45 #include "JSONObject.h"
46 #include "JSProxy.h"
47 #include "JSString.h"
48 #include "JSWASMModule.h"
49 #include "ProfilerDatabase.h"
50 #include "SamplingTool.h"
51 #include "StackVisitor.h"
52 #include "StructureInlines.h"
53 #include "StructureRareDataInlines.h"
54 #include "TestRunnerUtils.h"
55 #include "TypeProfilerLog.h"
56 #include "WASMModuleParser.h"
57 #include <math.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <thread>
62 #include <wtf/CurrentTime.h>
63 #include <wtf/MainThread.h>
64 #include <wtf/StringPrintStream.h>
65 #include <wtf/text/StringBuilder.h>
66
67 #if OS(WINDOWS)
68 #include <direct.h>
69 #else
70 #include <unistd.h>
71 #endif
72
73 #if HAVE(READLINE)
74 // readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
75 // We #define it to something else to avoid this conflict.
76 #define Function ReadlineFunction
77 #include <readline/history.h>
78 #include <readline/readline.h>
79 #undef Function
80 #endif
81
82 #if HAVE(SYS_TIME_H)
83 #include <sys/time.h>
84 #endif
85
86 #if HAVE(SIGNAL_H)
87 #include <signal.h>
88 #endif
89
90 #if COMPILER(MSVC)
91 #include <crtdbg.h>
92 #include <mmsystem.h>
93 #include <windows.h>
94 #endif
95
96 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
97 #include <fenv.h>
98 #include <arm/arch.h>
99 #endif
100
101 #if PLATFORM(EFL)
102 #include <Ecore.h>
103 #endif
104
105 using namespace JSC;
106 using namespace WTF;
107
108 namespace {
109
110 NO_RETURN_WITH_VALUE static void jscExit(int status)
111 {
112     waitForAsynchronousDisassembly();
113     
114 #if ENABLE(DFG_JIT)
115     if (DFG::isCrashing()) {
116         for (;;) {
117 #if OS(WINDOWS)
118             Sleep(1000);
119 #else
120             pause();
121 #endif
122         }
123     }
124 #endif // ENABLE(DFG_JIT)
125     exit(status);
126 }
127
128 class Element;
129 class ElementHandleOwner;
130 class Masuqerader;
131 class Root;
132 class RuntimeArray;
133
134 class Element : public JSNonFinalObject {
135 public:
136     Element(VM& vm, Structure* structure)
137         : Base(vm, structure)
138     {
139     }
140
141     typedef JSNonFinalObject Base;
142     static const bool needsDestruction = false;
143
144     Root* root() const { return m_root.get(); }
145     void setRoot(VM& vm, Root* root) { m_root.set(vm, this, root); }
146
147     static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root)
148     {
149         Structure* structure = createStructure(vm, globalObject, jsNull());
150         Element* element = new (NotNull, allocateCell<Element>(vm.heap, sizeof(Element))) Element(vm, structure);
151         element->finishCreation(vm, root);
152         return element;
153     }
154
155     void finishCreation(VM&, Root*);
156
157     static void visitChildren(JSCell* cell, SlotVisitor& visitor)
158     {
159         Element* thisObject = jsCast<Element*>(cell);
160         ASSERT_GC_OBJECT_INHERITS(thisObject, info());
161         Base::visitChildren(thisObject, visitor);
162         visitor.append(&thisObject->m_root);
163     }
164
165     static ElementHandleOwner* handleOwner();
166
167     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
168     {
169         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
170     }
171
172     DECLARE_INFO;
173
174 private:
175     WriteBarrier<Root> m_root;
176 };
177
178 class ElementHandleOwner : public WeakHandleOwner {
179 public:
180     virtual bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
181     {
182         Element* element = jsCast<Element*>(handle.slot()->asCell());
183         return visitor.containsOpaqueRoot(element->root());
184     }
185 };
186
187 class Masquerader : public JSNonFinalObject {
188 public:
189     Masquerader(VM& vm, Structure* structure)
190         : Base(vm, structure)
191     {
192     }
193
194     typedef JSNonFinalObject Base;
195     static const unsigned StructureFlags = Base::StructureFlags | JSC::MasqueradesAsUndefined;
196
197     static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
198     {
199         globalObject->masqueradesAsUndefinedWatchpoint()->fireAll("Masquerading object allocated");
200         Structure* structure = createStructure(vm, globalObject, jsNull());
201         Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
202         result->finishCreation(vm);
203         return result;
204     }
205
206     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
207     {
208         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
209     }
210
211     DECLARE_INFO;
212 };
213
214 class Root : public JSDestructibleObject {
215 public:
216     Root(VM& vm, Structure* structure)
217         : Base(vm, structure)
218     {
219     }
220
221     Element* element()
222     {
223         return m_element.get();
224     }
225
226     void setElement(Element* element)
227     {
228         Weak<Element> newElement(element, Element::handleOwner());
229         m_element.swap(newElement);
230     }
231
232     static Root* create(VM& vm, JSGlobalObject* globalObject)
233     {
234         Structure* structure = createStructure(vm, globalObject, jsNull());
235         Root* root = new (NotNull, allocateCell<Root>(vm.heap, sizeof(Root))) Root(vm, structure);
236         root->finishCreation(vm);
237         return root;
238     }
239
240     typedef JSDestructibleObject Base;
241
242     DECLARE_INFO;
243     static const bool needsDestruction = true;
244
245     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
246     {
247         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
248     }
249
250     static void visitChildren(JSCell* thisObject, SlotVisitor& visitor)
251     {
252         Base::visitChildren(thisObject, visitor);
253         visitor.addOpaqueRoot(thisObject);
254     }
255
256 private:
257     Weak<Element> m_element;
258 };
259
260 class ImpureGetter : public JSNonFinalObject {
261 public:
262     ImpureGetter(VM& vm, Structure* structure)
263         : Base(vm, structure)
264     {
265     }
266
267     DECLARE_INFO;
268     typedef JSNonFinalObject Base;
269     static const unsigned StructureFlags = Base::StructureFlags | JSC::HasImpureGetOwnPropertySlot | JSC::OverridesGetOwnPropertySlot;
270
271     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
272     {
273         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
274     }
275
276     static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate)
277     {
278         ImpureGetter* getter = new (NotNull, allocateCell<ImpureGetter>(vm.heap, sizeof(ImpureGetter))) ImpureGetter(vm, structure);
279         getter->finishCreation(vm, delegate);
280         return getter;
281     }
282
283     void finishCreation(VM& vm, JSObject* delegate)
284     {
285         Base::finishCreation(vm);
286         if (delegate)
287             m_delegate.set(vm, this, delegate);
288     }
289
290     static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot)
291     {
292         ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
293         
294         if (thisObject->m_delegate && thisObject->m_delegate->getPropertySlot(exec, name, slot))
295             return true;
296
297         return Base::getOwnPropertySlot(object, exec, name, slot);
298     }
299
300     static void visitChildren(JSCell* cell, SlotVisitor& visitor)
301     {
302         Base::visitChildren(cell, visitor);
303         ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
304         visitor.append(&thisObject->m_delegate);
305     }
306
307     void setDelegate(VM& vm, JSObject* delegate)
308     {
309         m_delegate.set(vm, this, delegate);
310     }
311
312 private:
313     WriteBarrier<JSObject> m_delegate;
314 };
315
316 class RuntimeArray : public JSArray {
317 public:
318     typedef JSArray Base;
319     static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames;
320
321     static RuntimeArray* create(ExecState* exec)
322     {
323         VM& vm = exec->vm();
324         JSGlobalObject* globalObject = exec->lexicalGlobalObject();
325         Structure* structure = createStructure(vm, globalObject, createPrototype(vm, globalObject));
326         RuntimeArray* runtimeArray = new (NotNull, allocateCell<RuntimeArray>(*exec->heap())) RuntimeArray(exec, structure);
327         runtimeArray->finishCreation(exec);
328         vm.heap.addFinalizer(runtimeArray, destroy);
329         return runtimeArray;
330     }
331
332     ~RuntimeArray() { }
333
334     static void destroy(JSCell* cell)
335     {
336         static_cast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
337     }
338
339     static const bool needsDestruction = false;
340
341     static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
342     {
343         RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
344         if (propertyName == exec->propertyNames().length) {
345             slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->lengthGetter);
346             return true;
347         }
348
349         Optional<uint32_t> index = parseIndex(propertyName);
350         if (index && index.value() < thisObject->getLength()) {
351             slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index.value()]));
352             return true;
353         }
354
355         return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
356     }
357
358     static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
359     {
360         RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
361         if (index < thisObject->getLength()) {
362             slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index]));
363             return true;
364         }
365
366         return JSObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot);
367     }
368
369     static NO_RETURN_DUE_TO_CRASH void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&)
370     {
371         RELEASE_ASSERT_NOT_REACHED();
372     }
373
374     static NO_RETURN_DUE_TO_CRASH bool deleteProperty(JSCell*, ExecState*, PropertyName)
375     {
376         RELEASE_ASSERT_NOT_REACHED();
377     }
378
379     unsigned getLength() const { return m_vector.size(); }
380
381     DECLARE_INFO;
382
383     static ArrayPrototype* createPrototype(VM&, JSGlobalObject* globalObject)
384     {
385         return globalObject->arrayPrototype();
386     }
387
388     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
389     {
390         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
391     }
392
393 protected:
394     void finishCreation(ExecState* exec)
395     {
396         Base::finishCreation(exec->vm());
397         ASSERT(inherits(info()));
398
399         for (size_t i = 0; i < exec->argumentCount(); i++)
400             m_vector.append(exec->argument(i).toInt32(exec));
401     }
402
403 private:
404     RuntimeArray(ExecState* exec, Structure* structure)
405         : JSArray(exec->vm(), structure, 0)
406     {
407     }
408
409     static EncodedJSValue lengthGetter(ExecState* exec, JSObject*, EncodedJSValue thisValue, PropertyName)
410     {
411         RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(JSValue::decode(thisValue));
412         if (!thisObject)
413             return throwVMTypeError(exec);
414         return JSValue::encode(jsNumber(thisObject->getLength()));
415     }
416
417     Vector<int> m_vector;
418 };
419
420 const ClassInfo Element::s_info = { "Element", &Base::s_info, 0, CREATE_METHOD_TABLE(Element) };
421 const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, 0, CREATE_METHOD_TABLE(Masquerader) };
422 const ClassInfo Root::s_info = { "Root", &Base::s_info, 0, CREATE_METHOD_TABLE(Root) };
423 const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(ImpureGetter) };
424 const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, 0, CREATE_METHOD_TABLE(RuntimeArray) };
425
426 ElementHandleOwner* Element::handleOwner()
427 {
428     static ElementHandleOwner* owner = 0;
429     if (!owner)
430         owner = new ElementHandleOwner();
431     return owner;
432 }
433
434 void Element::finishCreation(VM& vm, Root* root)
435 {
436     Base::finishCreation(vm);
437     setRoot(vm, root);
438     m_root->setElement(this);
439 }
440
441 }
442
443 static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
444
445 static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*);
446 static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState*);
447 static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
448 static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
449
450 static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*);
451 static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState*);
452 static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState*);
453 static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState*);
454 static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
455 static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
456 static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
457 static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
458 static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
459 static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
460 static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
461 static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
462 static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
463 static EncodedJSValue JSC_HOST_CALL functionDeleteAllCompiledCode(ExecState*);
464 static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
465 #ifndef NDEBUG
466 static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
467 #endif
468 static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
469 static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
470 static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
471 static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*);
472 static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
473 static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
474 static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
475 static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*);
476 static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
477 static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
478 static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
479 static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
480 static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
481 static EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*);
482 static EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*);
483 static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
484 static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
485 static EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState*);
486 static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
487 static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
488 static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
489 static EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState*);
490 static EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState*);
491 static EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState*);
492 static EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState*);
493 static EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState*);
494 static EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState*);
495 static EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*);
496 static EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState*);
497 #if ENABLE(WEBASSEMBLY)
498 static EncodedJSValue JSC_HOST_CALL functionLoadWebAssembly(ExecState*);
499 #endif
500 #if ENABLE(ES6_MODULES)
501 static EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState*);
502 #endif
503
504 #if ENABLE(SAMPLING_FLAGS)
505 static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
506 static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
507 #endif
508
509 struct Script {
510     bool isFile;
511     char* argument;
512
513     Script(bool isFile, char *argument)
514         : isFile(isFile)
515         , argument(argument)
516     {
517     }
518 };
519
520 class CommandLine {
521 public:
522     CommandLine(int argc, char** argv)
523     {
524         parseArguments(argc, argv);
525     }
526
527     bool m_interactive { false };
528     bool m_dump { false };
529     bool m_module { false };
530     bool m_exitCode { false };
531     Vector<Script> m_scripts;
532     Vector<String> m_arguments;
533     bool m_profile { false };
534     String m_profilerOutput;
535
536     void parseArguments(int, char**);
537 };
538
539 static const char interactivePrompt[] = ">>> ";
540
541 class StopWatch {
542 public:
543     void start();
544     void stop();
545     long getElapsedMS(); // call stop() first
546
547 private:
548     double m_startTime;
549     double m_stopTime;
550 };
551
552 void StopWatch::start()
553 {
554     m_startTime = monotonicallyIncreasingTime();
555 }
556
557 void StopWatch::stop()
558 {
559     m_stopTime = monotonicallyIncreasingTime();
560 }
561
562 long StopWatch::getElapsedMS()
563 {
564     return static_cast<long>((m_stopTime - m_startTime) * 1000);
565 }
566
567 static inline String stringFromUTF(const char* utf8)
568 {
569     return String::fromUTF8WithLatin1Fallback(utf8, strlen(utf8));
570 }
571
572 static inline SourceCode jscSource(const char* utf8, const String& filename)
573 {
574     String str = stringFromUTF(utf8);
575     return makeSource(str, filename);
576 }
577
578 class GlobalObject : public JSGlobalObject {
579 private:
580     GlobalObject(VM&, Structure*);
581
582 public:
583     typedef JSGlobalObject Base;
584
585     static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
586     {
587         GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
588         object->finishCreation(vm, arguments);
589         vm.heap.addFinalizer(object, destroy);
590         return object;
591     }
592
593     static const bool needsDestruction = false;
594
595     DECLARE_INFO;
596     static const GlobalObjectMethodTable s_globalObjectMethodTable;
597
598     static Structure* createStructure(VM& vm, JSValue prototype)
599     {
600         return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
601     }
602
603     static RuntimeFlags javaScriptRuntimeFlags(const JSGlobalObject*) { return RuntimeFlags::createAllEnabled(); }
604
605 protected:
606     void finishCreation(VM& vm, const Vector<String>& arguments)
607     {
608         Base::finishCreation(vm);
609         
610         addFunction(vm, "debug", functionDebug, 1);
611         addFunction(vm, "describe", functionDescribe, 1);
612         addFunction(vm, "describeArray", functionDescribeArray, 1);
613         addFunction(vm, "print", functionPrint, 1);
614         addFunction(vm, "quit", functionQuit, 0);
615         addFunction(vm, "gc", functionGCAndSweep, 0);
616         addFunction(vm, "fullGC", functionFullGC, 0);
617         addFunction(vm, "edenGC", functionEdenGC, 0);
618         addFunction(vm, "gcHeapSize", functionHeapSize, 0);
619         addFunction(vm, "deleteAllCompiledCode", functionDeleteAllCompiledCode, 0);
620         addFunction(vm, "addressOf", functionAddressOf, 1);
621 #ifndef NDEBUG
622         addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
623 #endif
624         addFunction(vm, "version", functionVersion, 1);
625         addFunction(vm, "run", functionRun, 1);
626         addFunction(vm, "load", functionLoad, 1);
627         addFunction(vm, "readFile", functionReadFile, 1);
628         addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
629         addFunction(vm, "jscStack", functionJSCStack, 1);
630         addFunction(vm, "readline", functionReadline, 0);
631         addFunction(vm, "preciseTime", functionPreciseTime, 0);
632         addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
633         addFunction(vm, "noInline", functionNeverInlineFunction, 1);
634         addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
635         addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
636         addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
637         addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
638 #if ENABLE(SAMPLING_FLAGS)
639         addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
640         addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
641 #endif
642         addConstructableFunction(vm, "Root", functionCreateRoot, 0);
643         addConstructableFunction(vm, "Element", functionCreateElement, 1);
644         addFunction(vm, "getElement", functionGetElement, 1);
645         addFunction(vm, "setElementRoot", functionSetElementRoot, 2);
646         
647         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "DFGTrue"), 0, functionFalse1, DFGTrueIntrinsic, DontEnum | JSC::Function);
648         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, DontEnum | JSC::Function);
649         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isFinalTier"), 0, functionFalse2, IsFinalTierIntrinsic, DontEnum | JSC::Function);
650         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, DontEnum | JSC::Function);
651         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isInt32"), 0, functionIsInt32, CheckInt32Intrinsic, DontEnum | JSC::Function);
652         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, DontEnum | JSC::Function);
653         
654         addFunction(vm, "effectful42", functionEffectful42, 0);
655         addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
656         addFunction(vm, "hasCustomProperties", functionHasCustomProperties, 0);
657
658         addFunction(vm, "createProxy", functionCreateProxy, 1);
659         addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
660
661         addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
662         addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
663
664         addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 0);
665         addFunction(vm, "findTypeForExpression", functionFindTypeForExpression, 2);
666         addFunction(vm, "returnTypeFor", functionReturnTypeFor, 1);
667
668         addFunction(vm, "dumpBasicBlockExecutionRanges", functionDumpBasicBlockExecutionRanges , 0);
669         addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
670
671         addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
672
673         addFunction(vm, "drainMicrotasks", functionDrainMicrotasks, 0);
674
675 #if ENABLE(WEBASSEMBLY)
676         addFunction(vm, "loadWebAssembly", functionLoadWebAssembly, 1);
677 #endif
678 #if ENABLE(ES6_MODULES)
679         addFunction(vm, "checkModuleSyntax", functionCheckModuleSyntax, 1);
680 #endif
681
682         JSArray* array = constructEmptyArray(globalExec(), 0);
683         for (size_t i = 0; i < arguments.size(); ++i)
684             array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
685         putDirect(vm, Identifier::fromString(globalExec(), "arguments"), array);
686         
687         putDirect(vm, Identifier::fromString(globalExec(), "console"), jsUndefined());
688     }
689
690     void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
691     {
692         Identifier identifier = Identifier::fromString(&vm, name);
693         putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
694     }
695     
696     void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
697     {
698         Identifier identifier = Identifier::fromString(&vm, name);
699         putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function));
700     }
701
702     static JSInternalPromise* moduleLoaderResolve(JSGlobalObject*, ExecState*, JSValue, JSValue);
703
704     static JSInternalPromise* moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSValue key)
705     {
706         JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
707         String moduleKey = key.toString(exec)->value(exec);
708         if (exec->hadException()) {
709             JSValue exception = exec->exception();
710             exec->clearException();
711             return deferred->reject(exec, exception);
712         }
713
714         // Here, now we consider moduleKey as the fileName.
715         Vector<char> utf8;
716         if (!fillBufferWithContentsOfFile(moduleKey, utf8))
717             return deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'.")));
718
719         return deferred->resolve(exec, jsString(exec, stringFromUTF(utf8.data())));
720     }
721 };
722
723 const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
724 const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, 0, &shouldInterruptScriptBeforeTimeout, &moduleLoaderResolve, &moduleLoaderFetch, nullptr, nullptr };
725
726
727 GlobalObject::GlobalObject(VM& vm, Structure* structure)
728     : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
729 {
730 }
731
732 static UChar pathSeparator()
733 {
734 #if OS(WINDOWS)
735     return '\\';
736 #else
737     return '/';
738 #endif
739 }
740
741 struct DirectoryName {
742     // In unix, it is "/". In Windows, it becomes a drive letter like "C:\"
743     String rootName;
744
745     // If the directory name is "/home/WebKit", this becomes "home/WebKit". If the directory name is "/", this becomes "".
746     String queryName;
747 };
748
749 static bool extractDirectoryName(const String& absolutePathToFile, DirectoryName& directoryName)
750 {
751     size_t firstSeparatorPosition = absolutePathToFile.find(pathSeparator());
752     if (firstSeparatorPosition == notFound)
753         return false;
754     directoryName.rootName = absolutePathToFile.substring(0, firstSeparatorPosition + 1); // Include the separator.
755     size_t lastSeparatorPosition = absolutePathToFile.reverseFind(pathSeparator());
756     ASSERT_WITH_MESSAGE(lastSeparatorPosition != notFound, "If the separator is not found, this function already returns when performing the forward search.");
757     if (firstSeparatorPosition == lastSeparatorPosition)
758         directoryName.queryName = StringImpl::empty();
759     else
760         directoryName.queryName = absolutePathToFile.substring(firstSeparatorPosition + 1, lastSeparatorPosition); // Not include the separator.
761     return true;
762 }
763
764 static bool currentWorkingDirectory(DirectoryName& directoryName)
765 {
766 #if OS(WINDOWS)
767     // https://msdn.microsoft.com/en-us/library/sf98bd4y.aspx
768     char* buffer = nullptr;
769     if (!(buffer = _getcwd(nullptr, 0)))
770         return false;
771     String directoryString = String::fromUTF8(buffer);
772     free(buffer);
773 #else
774     auto buffer = std::make_unique<char[]>(PATH_MAX);
775     if (!getcwd(buffer.get(), PATH_MAX))
776         return false;
777     String directoryString = String::fromUTF8(buffer.get());
778 #endif
779     if (directoryString.isEmpty())
780         return false;
781
782     if (directoryString[directoryString.length() - 1] == pathSeparator())
783         return extractDirectoryName(directoryString, directoryName);
784     // Append the seperator to represents the file name. extractDirectoryName only accepts the absolute file name.
785     return extractDirectoryName(makeString(directoryString, pathSeparator()), directoryName);
786 }
787
788 static String resolvePath(const DirectoryName& directoryName, const String& query)
789 {
790     Vector<String> directoryPieces;
791     directoryName.queryName.split(pathSeparator(), false, directoryPieces);
792
793     Vector<String> queryPieces;
794     query.split(pathSeparator(), true, queryPieces);
795
796     // Only first '/' is recognized as the path from the root.
797     if (!queryPieces.isEmpty() && queryPieces[0].isEmpty())
798         directoryPieces.clear();
799
800     for (const auto& query : queryPieces) {
801         if (query == String(ASCIILiteral(".."))) {
802             if (!directoryPieces.isEmpty())
803                 directoryPieces.removeLast();
804         } else if (!query.isEmpty() && query != String(ASCIILiteral(".")))
805             directoryPieces.append(query);
806     }
807
808     StringBuilder builder;
809     builder.append(directoryName.rootName);
810     for (size_t i = 0; i < directoryPieces.size(); ++i) {
811         builder.append(directoryPieces[i]);
812         if (i + 1 != directoryPieces.size())
813             builder.append(pathSeparator());
814     }
815     return builder.toString();
816 }
817
818 JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSValue keyValue, JSValue referrerValue)
819 {
820     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
821     const Identifier key = keyValue.toPropertyKey(exec);
822     if (exec->hadException()) {
823         JSValue exception = exec->exception();
824         exec->clearException();
825         return deferred->reject(exec, exception);
826     }
827
828     if (key.isSymbol())
829         return deferred->resolve(exec, keyValue);
830
831     DirectoryName directoryName;
832     if (referrerValue.isUndefined()) {
833         if (!currentWorkingDirectory(directoryName))
834             return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
835     } else {
836         const Identifier referrer = referrerValue.toPropertyKey(exec);
837         if (exec->hadException()) {
838             JSValue exception = exec->exception();
839             exec->clearException();
840             return deferred->reject(exec, exception);
841         }
842         if (referrer.isSymbol()) {
843             if (!currentWorkingDirectory(directoryName))
844                 return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
845         } else {
846             // If the referrer exists, we assume that the referrer is the correct absolute path.
847             if (!extractDirectoryName(referrer.impl(), directoryName))
848                 return deferred->reject(exec, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
849         }
850     }
851
852     return deferred->resolve(exec, jsString(exec, resolvePath(directoryName, key.impl())));
853 }
854
855 EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
856 {
857     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
858         if (i)
859             putchar(' ');
860
861         printf("%s", exec->uncheckedArgument(i).toString(exec)->view(exec).get().utf8().data());
862     }
863
864     putchar('\n');
865     fflush(stdout);
866     return JSValue::encode(jsUndefined());
867 }
868
869 #ifndef NDEBUG
870 EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
871 {
872     VMEntryFrame* topVMEntryFrame = exec->vm().topVMEntryFrame;
873     ExecState* callerFrame = exec->callerFrame(topVMEntryFrame);
874     if (callerFrame)
875         exec->vm().interpreter->dumpCallFrame(callerFrame);
876     return JSValue::encode(jsUndefined());
877 }
878 #endif
879
880 EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
881 {
882     fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->view(exec).get().utf8().data());
883     return JSValue::encode(jsUndefined());
884 }
885
886 EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
887 {
888     if (exec->argumentCount() < 1)
889         return JSValue::encode(jsUndefined());
890     return JSValue::encode(jsString(exec, toString(exec->argument(0))));
891 }
892
893 EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
894 {
895     if (exec->argumentCount() < 1)
896         return JSValue::encode(jsUndefined());
897     JSObject* object = jsDynamicCast<JSObject*>(exec->argument(0));
898     if (!object)
899         return JSValue::encode(jsNontrivialString(exec, ASCIILiteral("<not object>")));
900     return JSValue::encode(jsNontrivialString(exec, toString("<Public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
901 }
902
903 class FunctionJSCStackFunctor {
904 public:
905     FunctionJSCStackFunctor(StringBuilder& trace)
906         : m_trace(trace)
907     {
908     }
909
910     StackVisitor::Status operator()(StackVisitor& visitor)
911     {
912         m_trace.append(String::format("    %zu   %s\n", visitor->index(), visitor->toString().utf8().data()));
913         return StackVisitor::Continue;
914     }
915
916 private:
917     StringBuilder& m_trace;
918 };
919
920 EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
921 {
922     StringBuilder trace;
923     trace.appendLiteral("--> Stack trace:\n");
924
925     FunctionJSCStackFunctor functor(trace);
926     exec->iterate(functor);
927     fprintf(stderr, "%s", trace.toString().utf8().data());
928     return JSValue::encode(jsUndefined());
929 }
930
931 EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
932 {
933     JSLockHolder lock(exec);
934     return JSValue::encode(Root::create(exec->vm(), exec->lexicalGlobalObject()));
935 }
936
937 EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
938 {
939     JSLockHolder lock(exec);
940     JSValue arg = exec->argument(0);
941     return JSValue::encode(Element::create(exec->vm(), exec->lexicalGlobalObject(), arg.isNull() ? nullptr : jsCast<Root*>(exec->argument(0))));
942 }
943
944 EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
945 {
946     JSLockHolder lock(exec);
947     Element* result = jsCast<Root*>(exec->argument(0).asCell())->element();
948     return JSValue::encode(result ? result : jsUndefined());
949 }
950
951 EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState* exec)
952 {
953     JSLockHolder lock(exec);
954     Element* element = jsCast<Element*>(exec->argument(0));
955     Root* root = jsCast<Root*>(exec->argument(1));
956     element->setRoot(exec->vm(), root);
957     return JSValue::encode(jsUndefined());
958 }
959
960 EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState* exec)
961 {
962     JSLockHolder lock(exec);
963     JSValue target = exec->argument(0);
964     if (!target.isObject())
965         return JSValue::encode(jsUndefined());
966     JSObject* jsTarget = asObject(target.asCell());
967     Structure* structure = JSProxy::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsTarget->prototype());
968     JSProxy* proxy = JSProxy::create(exec->vm(), structure, jsTarget);
969     return JSValue::encode(proxy);
970 }
971
972 EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState* exec)
973 {
974     JSLockHolder lock(exec);
975     RuntimeArray* array = RuntimeArray::create(exec);
976     return JSValue::encode(array);
977 }
978
979 EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
980 {
981     JSLockHolder lock(exec);
982     JSValue target = exec->argument(0);
983     JSObject* delegate = nullptr;
984     if (target.isObject())
985         delegate = asObject(target.asCell());
986     Structure* structure = ImpureGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
987     ImpureGetter* result = ImpureGetter::create(exec->vm(), structure, delegate);
988     return JSValue::encode(result);
989 }
990
991 EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
992 {
993     JSLockHolder lock(exec);
994     JSValue base = exec->argument(0);
995     if (!base.isObject())
996         return JSValue::encode(jsUndefined());
997     JSValue delegate = exec->argument(1);
998     if (!delegate.isObject())
999         return JSValue::encode(jsUndefined());
1000     ImpureGetter* impureGetter = jsCast<ImpureGetter*>(asObject(base.asCell()));
1001     impureGetter->setDelegate(exec->vm(), asObject(delegate.asCell()));
1002     return JSValue::encode(jsUndefined());
1003 }
1004
1005 EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
1006 {
1007     JSLockHolder lock(exec);
1008     exec->heap()->collectAllGarbage();
1009     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
1010 }
1011
1012 EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
1013 {
1014     JSLockHolder lock(exec);
1015     exec->heap()->collect(FullCollection);
1016     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
1017 }
1018
1019 EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
1020 {
1021     JSLockHolder lock(exec);
1022     exec->heap()->collect(EdenCollection);
1023     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastEdenCollection()));
1024 }
1025
1026 EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState* exec)
1027 {
1028     JSLockHolder lock(exec);
1029     return JSValue::encode(jsNumber(exec->heap()->size()));
1030 }
1031
1032 EncodedJSValue JSC_HOST_CALL functionDeleteAllCompiledCode(ExecState* exec)
1033 {
1034     JSLockHolder lock(exec);
1035     exec->heap()->deleteAllCodeBlocks();
1036     return JSValue::encode(jsUndefined());
1037 }
1038
1039 // This function is not generally very helpful in 64-bit code as the tag and payload
1040 // share a register. But in 32-bit JITed code the tag may not be checked if an
1041 // optimization removes type checking requirements, such as in ===.
1042 EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState* exec)
1043 {
1044     JSValue value = exec->argument(0);
1045     if (!value.isCell())
1046         return JSValue::encode(jsUndefined());
1047     // Need to cast to uint64_t so bitwise_cast will play along.
1048     uint64_t asNumber = reinterpret_cast<uint64_t>(value.asCell());
1049     EncodedJSValue returnValue = JSValue::encode(jsNumber(bitwise_cast<double>(asNumber)));
1050     return returnValue;
1051 }
1052
1053 EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
1054 {
1055     // We need this function for compatibility with the Mozilla JS tests but for now
1056     // we don't actually do any version-specific handling
1057     return JSValue::encode(jsUndefined());
1058 }
1059
1060 EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
1061 {
1062     String fileName = exec->argument(0).toString(exec)->value(exec);
1063     Vector<char> script;
1064     if (!fillBufferWithContentsOfFile(fileName, script))
1065         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1066
1067     GlobalObject* globalObject = GlobalObject::create(exec->vm(), GlobalObject::createStructure(exec->vm(), jsNull()), Vector<String>());
1068
1069     JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
1070     for (unsigned i = 1; i < exec->argumentCount(); ++i)
1071         array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
1072     globalObject->putDirect(
1073         exec->vm(), Identifier::fromString(globalObject->globalExec(), "arguments"), array);
1074
1075     NakedPtr<Exception> exception;
1076     StopWatch stopWatch;
1077     stopWatch.start();
1078     evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), exception);
1079     stopWatch.stop();
1080
1081     if (exception) {
1082         exec->vm().throwException(globalObject->globalExec(), exception);
1083         return JSValue::encode(jsUndefined());
1084     }
1085     
1086     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1087 }
1088
1089 EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
1090 {
1091     String fileName = exec->argument(0).toString(exec)->value(exec);
1092     Vector<char> script;
1093     if (!fillBufferWithContentsOfFile(fileName, script))
1094         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1095
1096     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1097     
1098     NakedPtr<Exception> evaluationException;
1099     JSValue result = evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), evaluationException);
1100     if (evaluationException)
1101         exec->vm().throwException(exec, evaluationException);
1102     return JSValue::encode(result);
1103 }
1104
1105 EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
1106 {
1107     String fileName = exec->argument(0).toString(exec)->value(exec);
1108     Vector<char> script;
1109     if (!fillBufferWithContentsOfFile(fileName, script))
1110         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1111
1112     return JSValue::encode(jsString(exec, stringFromUTF(script.data())));
1113 }
1114
1115 EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
1116 {
1117     String fileName = exec->argument(0).toString(exec)->value(exec);
1118     Vector<char> script;
1119     if (!fillBufferWithContentsOfFile(fileName, script))
1120         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1121
1122     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1123
1124     StopWatch stopWatch;
1125     stopWatch.start();
1126
1127     JSValue syntaxException;
1128     bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script.data(), fileName), &syntaxException);
1129     stopWatch.stop();
1130
1131     if (!validSyntax)
1132         exec->vm().throwException(exec, syntaxException);
1133     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1134 }
1135
1136 #if ENABLE(SAMPLING_FLAGS)
1137 EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
1138 {
1139     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1140         unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1141         if ((flag >= 1) && (flag <= 32))
1142             SamplingFlags::setFlag(flag);
1143     }
1144     return JSValue::encode(jsNull());
1145 }
1146
1147 EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
1148 {
1149     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1150         unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1151         if ((flag >= 1) && (flag <= 32))
1152             SamplingFlags::clearFlag(flag);
1153     }
1154     return JSValue::encode(jsNull());
1155 }
1156 #endif
1157
1158 EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
1159 {
1160     Vector<char, 256> line;
1161     int c;
1162     while ((c = getchar()) != EOF) {
1163         // FIXME: Should we also break on \r? 
1164         if (c == '\n')
1165             break;
1166         line.append(c);
1167     }
1168     line.append('\0');
1169     return JSValue::encode(jsString(exec, line.data()));
1170 }
1171
1172 EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
1173 {
1174     return JSValue::encode(jsNumber(currentTime()));
1175 }
1176
1177 EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState* exec)
1178 {
1179     return JSValue::encode(setNeverInline(exec));
1180 }
1181
1182 EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
1183 {
1184     return JSValue::encode(optimizeNextInvocation(exec));
1185 }
1186
1187 EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
1188 {
1189     return JSValue::encode(numberOfDFGCompiles(exec));
1190 }
1191
1192 EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
1193 {
1194     if (exec->argumentCount() < 1)
1195         return JSValue::encode(jsUndefined());
1196     
1197     CodeBlock* block = getSomeBaselineCodeBlockForFunction(exec->argument(0));
1198     if (!block)
1199         return JSValue::encode(jsNumber(0));
1200     
1201     return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
1202 }
1203
1204 EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
1205 {
1206     if (exec->argumentCount() < 1)
1207         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Not enough arguments"))));
1208     
1209     JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(0));
1210     if (!buffer)
1211         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Expected an array buffer"))));
1212     
1213     ArrayBufferContents dummyContents;
1214     buffer->impl()->transfer(dummyContents);
1215     
1216     return JSValue::encode(jsUndefined());
1217 }
1218
1219 EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
1220 {
1221     jscExit(EXIT_SUCCESS);
1222
1223 #if COMPILER(MSVC)
1224     // Without this, Visual Studio will complain that this method does not return a value.
1225     return JSValue::encode(jsUndefined());
1226 #endif
1227 }
1228
1229 EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1230 EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1231
1232 EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
1233 EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
1234 EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState* exec)
1235 {
1236     for (size_t i = 0; i < exec->argumentCount(); ++i) {
1237         if (!exec->argument(i).isInt32())
1238             return JSValue::encode(jsBoolean(false));
1239     }
1240     return JSValue::encode(jsBoolean(true));
1241 }
1242
1243 EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
1244
1245 EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
1246 {
1247     return JSValue::encode(jsNumber(42));
1248 }
1249
1250 EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
1251 {
1252     return JSValue::encode(Masquerader::create(exec->vm(), exec->lexicalGlobalObject()));
1253 }
1254
1255 EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState* exec)
1256 {
1257     JSValue value = exec->argument(0);
1258     if (value.isObject())
1259         return JSValue::encode(jsBoolean(asObject(value)->hasCustomProperties()));
1260     return JSValue::encode(jsBoolean(false));
1261 }
1262
1263 EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
1264 {
1265     exec->vm().dumpTypeProfilerData();
1266     return JSValue::encode(jsUndefined());
1267 }
1268
1269 EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState* exec)
1270 {
1271     RELEASE_ASSERT(exec->vm().typeProfiler());
1272     exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionFindTypeForExpression"));
1273
1274     JSValue functionValue = exec->argument(0);
1275     RELEASE_ASSERT(functionValue.isFunction());
1276     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1277
1278     RELEASE_ASSERT(exec->argument(1).isString());
1279     String substring = exec->argument(1).getString(exec);
1280     String sourceCodeText = executable->source().toString();
1281     unsigned offset = static_cast<unsigned>(sourceCodeText.find(substring) + executable->source().startOffset());
1282     
1283     String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorNormal, offset, executable->sourceID(), exec->vm());
1284     return JSValue::encode(JSONParse(exec, jsonString));
1285 }
1286
1287 EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState* exec)
1288 {
1289     RELEASE_ASSERT(exec->vm().typeProfiler());
1290     exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionReturnTypeFor"));
1291
1292     JSValue functionValue = exec->argument(0);
1293     RELEASE_ASSERT(functionValue.isFunction());
1294     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1295
1296     unsigned offset = executable->typeProfilingStartOffset();
1297     String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorFunctionReturn, offset, executable->sourceID(), exec->vm());
1298     return JSValue::encode(JSONParse(exec, jsonString));
1299 }
1300
1301 EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState* exec)
1302 {
1303     RELEASE_ASSERT(exec->vm().controlFlowProfiler());
1304     exec->vm().controlFlowProfiler()->dumpData();
1305     return JSValue::encode(jsUndefined());
1306 }
1307
1308 EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState* exec)
1309 {
1310     RELEASE_ASSERT(exec->vm().controlFlowProfiler());
1311
1312     JSValue functionValue = exec->argument(0);
1313     RELEASE_ASSERT(functionValue.isFunction());
1314     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1315
1316     RELEASE_ASSERT(exec->argument(1).isString());
1317     String substring = exec->argument(1).getString(exec);
1318     String sourceCodeText = executable->source().toString();
1319     RELEASE_ASSERT(sourceCodeText.contains(substring));
1320     int offset = sourceCodeText.find(substring) + executable->source().startOffset();
1321     
1322     bool hasExecuted = exec->vm().controlFlowProfiler()->hasBasicBlockAtTextOffsetBeenExecuted(offset, executable->sourceID(), exec->vm());
1323     return JSValue::encode(jsBoolean(hasExecuted));
1324 }
1325
1326 EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*)
1327 {
1328     Options::enableExceptionFuzz() = true;
1329     return JSValue::encode(jsUndefined());
1330 }
1331
1332 EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState* exec)
1333 {
1334     exec->vm().drainMicrotasks();
1335     return JSValue::encode(jsUndefined());
1336 }
1337
1338 #if ENABLE(WEBASSEMBLY)
1339 EncodedJSValue JSC_HOST_CALL functionLoadWebAssembly(ExecState* exec)
1340 {
1341     String fileName = exec->argument(0).toString(exec)->value(exec);
1342     Vector<char> buffer;
1343     if (!fillBufferWithContentsOfFile(fileName, buffer))
1344         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1345     RefPtr<WebAssemblySourceProvider> sourceProvider = WebAssemblySourceProvider::create(reinterpret_cast<Vector<uint8_t>&>(buffer), fileName);
1346     SourceCode source(sourceProvider);
1347     String errorMessage;
1348     JSWASMModule* module = parseWebAssembly(exec, source, errorMessage);
1349     if (!module)
1350         return JSValue::encode(exec->vm().throwException(exec, createSyntaxError(exec, errorMessage)));
1351     return JSValue::encode(module);
1352 }
1353 #endif
1354
1355 #if ENABLE(ES6_MODULES)
1356 EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState* exec)
1357 {
1358     String source = exec->argument(0).toString(exec)->value(exec);
1359
1360     StopWatch stopWatch;
1361     stopWatch.start();
1362
1363     ParserError error;
1364     bool validSyntax = checkModuleSyntax(exec, makeSource(source), error);
1365     stopWatch.stop();
1366
1367     if (!validSyntax)
1368         exec->vm().throwException(exec, jsNontrivialString(exec, toString("SyntaxError: ", error.message(), ":", error.line())));
1369     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1370 }
1371 #endif
1372
1373 // Use SEH for Release builds only to get rid of the crash report dialog
1374 // (luckily the same tests fail in Release and Debug builds so far). Need to
1375 // be in a separate main function because the jscmain function requires object
1376 // unwinding.
1377
1378 #if COMPILER(MSVC) && !defined(_DEBUG)
1379 #define TRY       __try {
1380 #define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
1381 #else
1382 #define TRY
1383 #define EXCEPT(x)
1384 #endif
1385
1386 int jscmain(int argc, char** argv);
1387
1388 static double s_desiredTimeout;
1389
1390 static NO_RETURN_DUE_TO_CRASH void timeoutThreadMain(void*)
1391 {
1392     auto timeout = std::chrono::microseconds(static_cast<std::chrono::microseconds::rep>(s_desiredTimeout * 1000000));
1393     std::this_thread::sleep_for(timeout);
1394     
1395     dataLog("Timed out after ", s_desiredTimeout, " seconds!\n");
1396     CRASH();
1397 }
1398
1399 int main(int argc, char** argv)
1400 {
1401 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
1402     // Enabled IEEE754 denormal support.
1403     fenv_t env;
1404     fegetenv( &env );
1405     env.__fpscr &= ~0x01000000u;
1406     fesetenv( &env );
1407 #endif
1408
1409 #if OS(WINDOWS) && (defined(_M_X64) || defined(__x86_64__))
1410     // The VS2013 runtime has a bug where it mis-detects AVX-capable processors
1411     // if the feature has been disabled in firmware. This causes us to crash
1412     // in some of the math functions. For now, we disable those optimizations
1413     // because Microsoft is not going to fix the problem in VS2013.
1414     // FIXME: http://webkit.org/b/141449: Remove this workaround when we switch to VS2015+.
1415     _set_FMA3_enable(0);
1416
1417     // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
1418     // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
1419     // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
1420     ::SetErrorMode(0);
1421
1422 #if defined(_DEBUG)
1423     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
1424     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
1425     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
1426     _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
1427     _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
1428     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
1429 #endif
1430
1431     timeBeginPeriod(1);
1432 #endif
1433
1434 #if PLATFORM(EFL)
1435     ecore_init();
1436 #endif
1437
1438     // Need to initialize WTF threading before we start any threads. Cannot initialize JSC
1439     // threading yet, since that would do somethings that we'd like to defer until after we
1440     // have a chance to parse options.
1441     WTF::initializeThreading();
1442
1443     if (char* timeoutString = getenv("JSC_timeout")) {
1444         if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
1445             dataLog(
1446                 "WARNING: timeout string is malformed, got ", timeoutString,
1447                 " but expected a number. Not using a timeout.\n");
1448         } else
1449             createThread(timeoutThreadMain, 0, "jsc Timeout Thread");
1450     }
1451
1452 #if PLATFORM(IOS)
1453     Options::crashIfCantAllocateJITMemory() = true;
1454 #endif
1455
1456     // We can't use destructors in the following code because it uses Windows
1457     // Structured Exception Handling
1458     int res = 0;
1459     TRY
1460         res = jscmain(argc, argv);
1461     EXCEPT(res = 3)
1462     if (Options::logHeapStatisticsAtExit())
1463         HeapStatistics::reportSuccess();
1464
1465 #if PLATFORM(EFL)
1466     ecore_shutdown();
1467 #endif
1468
1469     jscExit(res);
1470 }
1471
1472 static void dumpException(GlobalObject* globalObject, JSValue exception)
1473 {
1474     printf("Exception: %s\n", exception.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1475     Identifier stackID = Identifier::fromString(globalObject->globalExec(), "stack");
1476     JSValue stackValue = exception.get(globalObject->globalExec(), stackID);
1477     if (!stackValue.isUndefinedOrNull())
1478         printf("%s\n", stackValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1479 }
1480
1481 static void dumpException(GlobalObject* globalObject, NakedPtr<Exception> evaluationException)
1482 {
1483     if (evaluationException)
1484         dumpException(globalObject, evaluationException->value());
1485 }
1486
1487 static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump, bool module)
1488 {
1489     const char* script;
1490     String fileName;
1491     Vector<char> scriptBuffer;
1492
1493     if (dump)
1494         JSC::Options::dumpGeneratedBytecodes() = true;
1495
1496     VM& vm = globalObject->vm();
1497     bool success = true;
1498
1499 #if ENABLE(ES6_MODULES)
1500     JSFunction* errorHandler = JSFunction::create(vm, globalObject, 1, String(), [&](ExecState* exec) {
1501         success = false;
1502         dumpException(globalObject, exec->argument(0));
1503         return JSValue::encode(jsUndefined());
1504     });
1505 #endif
1506
1507 #if ENABLE(SAMPLING_FLAGS)
1508     SamplingFlags::start();
1509 #endif
1510
1511     for (size_t i = 0; i < scripts.size(); i++) {
1512 #if ENABLE(ES6_MODULES)
1513         JSInternalPromise* promise = nullptr;
1514 #endif
1515         if (scripts[i].isFile) {
1516             fileName = scripts[i].argument;
1517             if (module) {
1518 #if ENABLE(ES6_MODULES)
1519                 promise = evaluateModule(globalObject->globalExec(), fileName);
1520 #else
1521                 RELEASE_ASSERT_NOT_REACHED();
1522 #endif
1523             } else {
1524                 if (!fillBufferWithContentsOfFile(fileName, scriptBuffer))
1525                     return false; // fail early so we can catch missing files
1526                 script = scriptBuffer.data();
1527             }
1528         } else {
1529             script = scripts[i].argument;
1530             fileName = ASCIILiteral("[Command Line]");
1531         }
1532
1533         vm.startSampling();
1534
1535         if (module) {
1536 #if ENABLE(ES6_MODULES)
1537             if (!promise)
1538                 promise = evaluateModule(globalObject->globalExec(), jscSource(script, fileName));
1539             globalObject->globalExec()->clearException();
1540             promise->then(globalObject->globalExec(), nullptr, errorHandler);
1541             globalObject->vm().drainMicrotasks();
1542 #else
1543             RELEASE_ASSERT_NOT_REACHED();
1544 #endif
1545         } else {
1546             NakedPtr<Exception> evaluationException;
1547             JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), evaluationException);
1548             success = success && !evaluationException;
1549             if (dump && !evaluationException)
1550                 printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1551             dumpException(globalObject, evaluationException);
1552         }
1553
1554         vm.stopSampling();
1555         globalObject->globalExec()->clearException();
1556     }
1557
1558 #if ENABLE(SAMPLING_FLAGS)
1559     SamplingFlags::stop();
1560 #endif
1561 #if ENABLE(SAMPLING_REGIONS)
1562     SamplingRegion::dump();
1563 #endif
1564     vm.dumpSampleData(globalObject->globalExec());
1565 #if ENABLE(SAMPLING_COUNTERS)
1566     AbstractSamplingCounter::dump();
1567 #endif
1568 #if ENABLE(REGEXP_TRACING)
1569     vm.dumpRegExpTrace();
1570 #endif
1571     return success;
1572 }
1573
1574 #define RUNNING_FROM_XCODE 0
1575
1576 static void runInteractive(GlobalObject* globalObject)
1577 {
1578     String interpreterName(ASCIILiteral("Interpreter"));
1579     
1580     bool shouldQuit = false;
1581     while (!shouldQuit) {
1582 #if HAVE(READLINE) && !RUNNING_FROM_XCODE
1583         ParserError error;
1584         String source;
1585         do {
1586             error = ParserError();
1587             char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
1588             shouldQuit = !line;
1589             if (!line)
1590                 break;
1591             source = source + line;
1592             source = source + '\n';
1593             checkSyntax(globalObject->vm(), makeSource(source, interpreterName), error);
1594             if (!line[0])
1595                 break;
1596             add_history(line);
1597         } while (error.syntaxErrorType() == ParserError::SyntaxErrorRecoverable);
1598         
1599         if (error.isValid()) {
1600             printf("%s:%d\n", error.message().utf8().data(), error.line());
1601             continue;
1602         }
1603         
1604         
1605         NakedPtr<Exception> evaluationException;
1606         JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, interpreterName), JSValue(), evaluationException);
1607 #else
1608         printf("%s", interactivePrompt);
1609         Vector<char, 256> line;
1610         int c;
1611         while ((c = getchar()) != EOF) {
1612             // FIXME: Should we also break on \r? 
1613             if (c == '\n')
1614                 break;
1615             line.append(c);
1616         }
1617         if (line.isEmpty())
1618             break;
1619         line.append('\0');
1620
1621         NakedPtr<Exception> evaluationException;
1622         JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line.data(), interpreterName), JSValue(), evaluationException);
1623 #endif
1624         if (evaluationException)
1625             printf("Exception: %s\n", evaluationException->value().toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1626         else
1627             printf("%s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1628
1629         globalObject->globalExec()->clearException();
1630         globalObject->vm().drainMicrotasks();
1631     }
1632     printf("\n");
1633 }
1634
1635 static NO_RETURN void printUsageStatement(bool help = false)
1636 {
1637     fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
1638     fprintf(stderr, "  -d         Dumps bytecode (debug builds only)\n");
1639     fprintf(stderr, "  -e         Evaluate argument as script code\n");
1640     fprintf(stderr, "  -f         Specifies a source file (deprecated)\n");
1641     fprintf(stderr, "  -h|--help  Prints this help message\n");
1642     fprintf(stderr, "  -i         Enables interactive mode (default if no files are specified)\n");
1643 #if ENABLE(ES6_MODULES)
1644     fprintf(stderr, "  -m         Execute as a module\n");
1645 #endif
1646 #if HAVE(SIGNAL_H)
1647     fprintf(stderr, "  -s         Installs signal handlers that exit on a crash (Unix platforms only)\n");
1648 #endif
1649     fprintf(stderr, "  -p <file>  Outputs profiling data to a file\n");
1650     fprintf(stderr, "  -x         Output exit code before terminating\n");
1651     fprintf(stderr, "\n");
1652     fprintf(stderr, "  --options                  Dumps all JSC VM options and exits\n");
1653     fprintf(stderr, "  --dumpOptions              Dumps all JSC VM options before continuing\n");
1654     fprintf(stderr, "  --<jsc VM option>=<value>  Sets the specified JSC VM option\n");
1655     fprintf(stderr, "\n");
1656
1657     jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
1658 }
1659
1660 void CommandLine::parseArguments(int argc, char** argv)
1661 {
1662     Options::initialize();
1663     
1664     int i = 1;
1665     bool needToDumpOptions = false;
1666     bool needToExit = false;
1667
1668     for (; i < argc; ++i) {
1669         const char* arg = argv[i];
1670         if (!strcmp(arg, "-f")) {
1671             if (++i == argc)
1672                 printUsageStatement();
1673             m_scripts.append(Script(true, argv[i]));
1674             continue;
1675         }
1676         if (!strcmp(arg, "-e")) {
1677             if (++i == argc)
1678                 printUsageStatement();
1679             m_scripts.append(Script(false, argv[i]));
1680             continue;
1681         }
1682         if (!strcmp(arg, "-i")) {
1683             m_interactive = true;
1684             continue;
1685         }
1686         if (!strcmp(arg, "-d")) {
1687             m_dump = true;
1688             continue;
1689         }
1690         if (!strcmp(arg, "-p")) {
1691             if (++i == argc)
1692                 printUsageStatement();
1693             m_profile = true;
1694             m_profilerOutput = argv[i];
1695             continue;
1696         }
1697 #if ENABLE(ES6_MODULES)
1698         if (!strcmp(arg, "-m")) {
1699             m_module = true;
1700             continue;
1701         }
1702 #endif
1703         if (!strcmp(arg, "-s")) {
1704 #if HAVE(SIGNAL_H)
1705             signal(SIGILL, _exit);
1706             signal(SIGFPE, _exit);
1707             signal(SIGBUS, _exit);
1708             signal(SIGSEGV, _exit);
1709 #endif
1710             continue;
1711         }
1712         if (!strcmp(arg, "-x")) {
1713             m_exitCode = true;
1714             continue;
1715         }
1716         if (!strcmp(arg, "--")) {
1717             ++i;
1718             break;
1719         }
1720         if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
1721             printUsageStatement(true);
1722
1723         if (!strcmp(arg, "--options")) {
1724             needToDumpOptions = true;
1725             needToExit = true;
1726             continue;
1727         }
1728         if (!strcmp(arg, "--dumpOptions")) {
1729             needToDumpOptions = true;
1730             continue;
1731         }
1732
1733         // See if the -- option is a JSC VM option.
1734         if (strstr(arg, "--") == arg && JSC::Options::setOption(&arg[2])) {
1735             // The arg was recognized as a VM option and has been parsed.
1736             continue; // Just continue with the next arg. 
1737         }
1738
1739         // This arg is not recognized by the VM nor by jsc. Pass it on to the
1740         // script.
1741         m_scripts.append(Script(true, argv[i]));
1742     }
1743
1744     if (m_scripts.isEmpty())
1745         m_interactive = true;
1746
1747     for (; i < argc; ++i)
1748         m_arguments.append(argv[i]);
1749
1750     if (needToDumpOptions)
1751         JSC::Options::dumpAllOptions(stderr, JSC::Options::DumpLevel::Verbose, "All JSC runtime options:");
1752     JSC::Options::ensureOptionsAreCoherent();
1753     if (needToExit)
1754         jscExit(EXIT_SUCCESS);
1755 }
1756
1757 int jscmain(int argc, char** argv)
1758 {
1759     // Note that the options parsing can affect VM creation, and thus
1760     // comes first.
1761     CommandLine options(argc, argv);
1762
1763     // Initialize JSC before getting VM.
1764 #if ENABLE(SAMPLING_REGIONS)
1765     WTF::initializeMainThread();
1766 #endif
1767     JSC::initializeThreading();
1768
1769     VM* vm = &VM::create(LargeHeap).leakRef();
1770     int result;
1771     {
1772         JSLockHolder locker(vm);
1773
1774         if (options.m_profile && !vm->m_perBytecodeProfiler)
1775             vm->m_perBytecodeProfiler = std::make_unique<Profiler::Database>(*vm);
1776     
1777         GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.m_arguments);
1778         bool success = runWithScripts(globalObject, options.m_scripts, options.m_dump, options.m_module);
1779         if (options.m_interactive && success)
1780             runInteractive(globalObject);
1781
1782         result = success ? 0 : 3;
1783
1784         if (options.m_exitCode)
1785             printf("jsc exiting %d\n", result);
1786     
1787         if (options.m_profile) {
1788             if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
1789                 fprintf(stderr, "could not save profiler output.\n");
1790         }
1791         
1792 #if ENABLE(JIT)
1793         if (Options::enableExceptionFuzz())
1794             printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
1795         bool fireAtEnabled =
1796             Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
1797         if (Options::enableExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
1798             printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks());
1799         if (Options::enableOSRExitFuzz()) {
1800             printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks());
1801             printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks());
1802         }
1803 #endif
1804         auto compileTimeStats = DFG::Plan::compileTimeStats();
1805         Vector<CString> compileTimeKeys;
1806         for (auto& entry : compileTimeStats)
1807             compileTimeKeys.append(entry.key);
1808         std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
1809         for (CString key : compileTimeKeys)
1810             printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key));
1811     }
1812     
1813     return result;
1814 }
1815
1816 static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
1817 {
1818     FILE* f = fopen(fileName.utf8().data(), "r");
1819     if (!f) {
1820         fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1821         return false;
1822     }
1823
1824     size_t bufferSize = 0;
1825     size_t bufferCapacity = 1024;
1826
1827     buffer.resize(bufferCapacity);
1828
1829     while (!feof(f) && !ferror(f)) {
1830         bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f);
1831         if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0'
1832             bufferCapacity *= 2;
1833             buffer.resize(bufferCapacity);
1834         }
1835     }
1836     fclose(f);
1837     buffer[bufferSize] = '\0';
1838
1839     if (buffer[0] == '#' && buffer[1] == '!')
1840         buffer[0] = buffer[1] = '/';
1841
1842     return true;
1843 }
1844
1845 #if OS(WINDOWS)
1846 extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
1847 {
1848     return main(argc, const_cast<char**>(argv));
1849 }
1850 #endif