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