Implement linear memory instructions in WebAssembly
[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 final : public WeakHandleOwner {
180 public:
181     virtual bool isReachableFromOpaqueRoots(JSCell& cell, void*, SlotVisitor& visitor)
182     {
183         auto& element = jsCast<Element&>(cell);
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 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 functionNoDFG(ExecState*);
477 static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
478 static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
479 static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
480 static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
481 static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
482 static NO_RETURN_DUE_TO_CRASH EncodedJSValue JSC_HOST_CALL functionAbort(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 template<typename Vector>
569 static inline String stringFromUTF(const Vector& utf8)
570 {
571     return String::fromUTF8WithLatin1Fallback(utf8.data(), utf8.size());
572 }
573
574 template<typename Vector>
575 static inline SourceCode jscSource(const Vector& utf8, const String& filename)
576 {
577     String str = stringFromUTF(utf8);
578     return makeSource(str, filename);
579 }
580
581 class GlobalObject : public JSGlobalObject {
582 private:
583     GlobalObject(VM&, Structure*);
584
585 public:
586     typedef JSGlobalObject Base;
587
588     static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
589     {
590         GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
591         object->finishCreation(vm, arguments);
592         vm.heap.addFinalizer(object, destroy);
593         return object;
594     }
595
596     static const bool needsDestruction = false;
597
598     DECLARE_INFO;
599     static const GlobalObjectMethodTable s_globalObjectMethodTable;
600
601     static Structure* createStructure(VM& vm, JSValue prototype)
602     {
603         return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
604     }
605
606     static RuntimeFlags javaScriptRuntimeFlags(const JSGlobalObject*) { return RuntimeFlags::createAllEnabled(); }
607
608 protected:
609     void finishCreation(VM& vm, const Vector<String>& arguments)
610     {
611         Base::finishCreation(vm);
612         
613         addFunction(vm, "debug", functionDebug, 1);
614         addFunction(vm, "describe", functionDescribe, 1);
615         addFunction(vm, "describeArray", functionDescribeArray, 1);
616         addFunction(vm, "print", functionPrint, 1);
617         addFunction(vm, "quit", functionQuit, 0);
618         addFunction(vm, "abort", functionAbort, 0);
619         addFunction(vm, "gc", functionGCAndSweep, 0);
620         addFunction(vm, "fullGC", functionFullGC, 0);
621         addFunction(vm, "edenGC", functionEdenGC, 0);
622         addFunction(vm, "gcHeapSize", functionHeapSize, 0);
623         addFunction(vm, "addressOf", functionAddressOf, 1);
624 #ifndef NDEBUG
625         addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
626 #endif
627         addFunction(vm, "version", functionVersion, 1);
628         addFunction(vm, "run", functionRun, 1);
629         addFunction(vm, "load", functionLoad, 1);
630         addFunction(vm, "readFile", functionReadFile, 1);
631         addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
632         addFunction(vm, "jscStack", functionJSCStack, 1);
633         addFunction(vm, "readline", functionReadline, 0);
634         addFunction(vm, "preciseTime", functionPreciseTime, 0);
635         addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
636         addFunction(vm, "noInline", functionNeverInlineFunction, 1);
637         addFunction(vm, "noDFG", functionNoDFG, 1);
638         addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
639         addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
640         addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
641         addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
642 #if ENABLE(SAMPLING_FLAGS)
643         addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
644         addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
645 #endif
646         addConstructableFunction(vm, "Root", functionCreateRoot, 0);
647         addConstructableFunction(vm, "Element", functionCreateElement, 1);
648         addFunction(vm, "getElement", functionGetElement, 1);
649         addFunction(vm, "setElementRoot", functionSetElementRoot, 2);
650         
651         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "DFGTrue"), 0, functionFalse1, DFGTrueIntrinsic, DontEnum);
652         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, DontEnum);
653         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isFinalTier"), 0, functionFalse2, IsFinalTierIntrinsic, DontEnum);
654         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, DontEnum);
655         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "isInt32"), 0, functionIsInt32, CheckInt32Intrinsic, DontEnum);
656         putDirectNativeFunction(vm, this, Identifier::fromString(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, DontEnum);
657         
658         addFunction(vm, "effectful42", functionEffectful42, 0);
659         addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
660         addFunction(vm, "hasCustomProperties", functionHasCustomProperties, 0);
661
662         addFunction(vm, "createProxy", functionCreateProxy, 1);
663         addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
664
665         addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
666         addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
667
668         addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 0);
669         addFunction(vm, "findTypeForExpression", functionFindTypeForExpression, 2);
670         addFunction(vm, "returnTypeFor", functionReturnTypeFor, 1);
671
672         addFunction(vm, "dumpBasicBlockExecutionRanges", functionDumpBasicBlockExecutionRanges , 0);
673         addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
674
675         addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
676
677         addFunction(vm, "drainMicrotasks", functionDrainMicrotasks, 0);
678
679 #if ENABLE(WEBASSEMBLY)
680         addFunction(vm, "loadWebAssembly", functionLoadWebAssembly, 3);
681 #endif
682         addFunction(vm, "loadModule", functionLoadModule, 1);
683         addFunction(vm, "checkModuleSyntax", functionCheckModuleSyntax, 1);
684
685         JSArray* array = constructEmptyArray(globalExec(), 0);
686         for (size_t i = 0; i < arguments.size(); ++i)
687             array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
688         putDirect(vm, Identifier::fromString(globalExec(), "arguments"), array);
689         
690         putDirect(vm, Identifier::fromString(globalExec(), "console"), jsUndefined());
691     }
692
693     void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
694     {
695         Identifier identifier = Identifier::fromString(&vm, name);
696         putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
697     }
698     
699     void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
700     {
701         Identifier identifier = Identifier::fromString(&vm, name);
702         putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function));
703     }
704
705     static JSInternalPromise* moduleLoaderResolve(JSGlobalObject*, ExecState*, JSValue, JSValue);
706     static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSValue);
707 };
708
709 const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, CREATE_METHOD_TABLE(GlobalObject) };
710 const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, 0, &shouldInterruptScriptBeforeTimeout, &moduleLoaderResolve, &moduleLoaderFetch, nullptr, nullptr, nullptr };
711
712
713 GlobalObject::GlobalObject(VM& vm, Structure* structure)
714     : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
715 {
716 }
717
718 static UChar pathSeparator()
719 {
720 #if OS(WINDOWS)
721     return '\\';
722 #else
723     return '/';
724 #endif
725 }
726
727 struct DirectoryName {
728     // In unix, it is "/". In Windows, it becomes a drive letter like "C:\"
729     String rootName;
730
731     // If the directory name is "/home/WebKit", this becomes "home/WebKit". If the directory name is "/", this becomes "".
732     String queryName;
733 };
734
735 struct ModuleName {
736     ModuleName(const String& moduleName);
737
738     bool startsWithRoot() const
739     {
740         return !queries.isEmpty() && queries[0].isEmpty();
741     }
742
743     Vector<String> queries;
744 };
745
746 ModuleName::ModuleName(const String& moduleName)
747 {
748     // A module name given from code is represented as the UNIX style path. Like, `./A/B.js`.
749     moduleName.split('/', true, queries);
750 }
751
752 static bool extractDirectoryName(const String& absolutePathToFile, DirectoryName& directoryName)
753 {
754     size_t firstSeparatorPosition = absolutePathToFile.find(pathSeparator());
755     if (firstSeparatorPosition == notFound)
756         return false;
757     directoryName.rootName = absolutePathToFile.substring(0, firstSeparatorPosition + 1); // Include the separator.
758     size_t lastSeparatorPosition = absolutePathToFile.reverseFind(pathSeparator());
759     ASSERT_WITH_MESSAGE(lastSeparatorPosition != notFound, "If the separator is not found, this function already returns when performing the forward search.");
760     if (firstSeparatorPosition == lastSeparatorPosition)
761         directoryName.queryName = StringImpl::empty();
762     else {
763         size_t queryStartPosition = firstSeparatorPosition + 1;
764         size_t queryLength = lastSeparatorPosition - queryStartPosition; // Not include the last separator.
765         directoryName.queryName = absolutePathToFile.substring(queryStartPosition, queryLength);
766     }
767     return true;
768 }
769
770 static bool currentWorkingDirectory(DirectoryName& directoryName)
771 {
772 #if OS(WINDOWS)
773     // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364934.aspx
774     // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
775     // The _MAX_PATH in Windows is 260. If the path of the current working directory is longer than that, _getcwd truncates the result.
776     // And other I/O functions taking a path name also truncate it. To avoid this situation,
777     //
778     // (1). When opening the file in Windows for modules, we always use the abosolute path and add "\\?\" prefix to the path name.
779     // (2). When retrieving the current working directory, use GetCurrentDirectory instead of _getcwd.
780     //
781     // In the path utility functions inside the JSC shell, we does not handle the UNC and UNCW including the network host name.
782     DWORD bufferLength = ::GetCurrentDirectoryW(0, nullptr);
783     if (!bufferLength)
784         return false;
785     // In Windows, wchar_t is the UTF-16LE.
786     // https://msdn.microsoft.com/en-us/library/dd374081.aspx
787     // https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407.aspx
788     auto buffer = std::make_unique<wchar_t[]>(bufferLength);
789     DWORD lengthNotIncludingNull = ::GetCurrentDirectoryW(bufferLength, buffer.get());
790     static_assert(sizeof(wchar_t) == sizeof(UChar), "In Windows, both are UTF-16LE");
791     String directoryString = String(reinterpret_cast<UChar*>(buffer.get()));
792     // We don't support network path like \\host\share\<path name>.
793     if (directoryString.startsWith("\\\\"))
794         return false;
795 #else
796     auto buffer = std::make_unique<char[]>(PATH_MAX);
797     if (!getcwd(buffer.get(), PATH_MAX))
798         return false;
799     String directoryString = String::fromUTF8(buffer.get());
800 #endif
801     if (directoryString.isEmpty())
802         return false;
803
804     if (directoryString[directoryString.length() - 1] == pathSeparator())
805         return extractDirectoryName(directoryString, directoryName);
806     // Append the seperator to represents the file name. extractDirectoryName only accepts the absolute file name.
807     return extractDirectoryName(makeString(directoryString, pathSeparator()), directoryName);
808 }
809
810 static String resolvePath(const DirectoryName& directoryName, const ModuleName& moduleName)
811 {
812     Vector<String> directoryPieces;
813     directoryName.queryName.split(pathSeparator(), false, directoryPieces);
814
815     // Only first '/' is recognized as the path from the root.
816     if (moduleName.startsWithRoot())
817         directoryPieces.clear();
818
819     for (const auto& query : moduleName.queries) {
820         if (query == String(ASCIILiteral(".."))) {
821             if (!directoryPieces.isEmpty())
822                 directoryPieces.removeLast();
823         } else if (!query.isEmpty() && query != String(ASCIILiteral(".")))
824             directoryPieces.append(query);
825     }
826
827     StringBuilder builder;
828     builder.append(directoryName.rootName);
829     for (size_t i = 0; i < directoryPieces.size(); ++i) {
830         builder.append(directoryPieces[i]);
831         if (i + 1 != directoryPieces.size())
832             builder.append(pathSeparator());
833     }
834     return builder.toString();
835 }
836
837 JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSValue keyValue, JSValue referrerValue)
838 {
839     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
840     const Identifier key = keyValue.toPropertyKey(exec);
841     if (exec->hadException()) {
842         JSValue exception = exec->exception();
843         exec->clearException();
844         return deferred->reject(exec, exception);
845     }
846
847     if (key.isSymbol())
848         return deferred->resolve(exec, keyValue);
849
850     DirectoryName directoryName;
851     if (referrerValue.isUndefined()) {
852         if (!currentWorkingDirectory(directoryName))
853             return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
854     } else {
855         const Identifier referrer = referrerValue.toPropertyKey(exec);
856         if (exec->hadException()) {
857             JSValue exception = exec->exception();
858             exec->clearException();
859             return deferred->reject(exec, exception);
860         }
861         if (referrer.isSymbol()) {
862             if (!currentWorkingDirectory(directoryName))
863                 return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
864         } else {
865             // If the referrer exists, we assume that the referrer is the correct absolute path.
866             if (!extractDirectoryName(referrer.impl(), directoryName))
867                 return deferred->reject(exec, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
868         }
869     }
870
871     return deferred->resolve(exec, jsString(exec, resolvePath(directoryName, ModuleName(key.impl()))));
872 }
873
874 static void convertShebangToJSComment(Vector<char>& buffer)
875 {
876     if (buffer.size() >= 2) {
877         if (buffer[0] == '#' && buffer[1] == '!')
878             buffer[0] = buffer[1] = '/';
879     }
880 }
881
882 static void fillBufferWithContentsOfFile(FILE* file, Vector<char>& buffer)
883 {
884     fseek(file, 0, SEEK_END);
885     size_t bufferCapacity = ftell(file);
886     fseek(file, 0, SEEK_SET);
887     buffer.resize(bufferCapacity);
888     fread(buffer.data(), 1, bufferCapacity, file);
889 }
890
891 static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
892 {
893     FILE* f = fopen(fileName.utf8().data(), "rb");
894     if (!f) {
895         fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
896         return false;
897     }
898
899     fillBufferWithContentsOfFile(f, buffer);
900     fclose(f);
901
902     return true;
903 }
904
905 static bool fetchScriptFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
906 {
907     if (!fillBufferWithContentsOfFile(fileName, buffer))
908         return false;
909     convertShebangToJSComment(buffer);
910     return true;
911 }
912
913 static bool fetchModuleFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
914 {
915     // We assume that fileName is always an absolute path.
916 #if OS(WINDOWS)
917     // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
918     // Use long UNC to pass the long path name to the Windows APIs.
919     String longUNCPathName = WTF::makeString("\\\\?\\", fileName);
920     static_assert(sizeof(wchar_t) == sizeof(UChar), "In Windows, both are UTF-16LE");
921     auto utf16Vector = longUNCPathName.charactersWithNullTermination();
922     FILE* f = _wfopen(reinterpret_cast<wchar_t*>(utf16Vector.data()), L"rb");
923 #else
924     FILE* f = fopen(fileName.utf8().data(), "r");
925 #endif
926     if (!f) {
927         fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
928         return false;
929     }
930
931     fillBufferWithContentsOfFile(f, buffer);
932     convertShebangToJSComment(buffer);
933     fclose(f);
934
935     return true;
936 }
937
938 JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSValue key)
939 {
940     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
941     String moduleKey = key.toString(exec)->value(exec);
942     if (exec->hadException()) {
943         JSValue exception = exec->exception();
944         exec->clearException();
945         return deferred->reject(exec, exception);
946     }
947
948     // Here, now we consider moduleKey as the fileName.
949     Vector<char> utf8;
950     if (!fetchModuleFromLocalFileSystem(moduleKey, utf8))
951         return deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'.")));
952
953     return deferred->resolve(exec, jsString(exec, stringFromUTF(utf8)));
954 }
955
956
957 EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
958 {
959     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
960         if (i)
961             putchar(' ');
962
963         printf("%s", exec->uncheckedArgument(i).toString(exec)->view(exec).get().utf8().data());
964     }
965
966     putchar('\n');
967     fflush(stdout);
968     return JSValue::encode(jsUndefined());
969 }
970
971 #ifndef NDEBUG
972 EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
973 {
974     VMEntryFrame* topVMEntryFrame = exec->vm().topVMEntryFrame;
975     ExecState* callerFrame = exec->callerFrame(topVMEntryFrame);
976     if (callerFrame)
977         exec->vm().interpreter->dumpCallFrame(callerFrame);
978     return JSValue::encode(jsUndefined());
979 }
980 #endif
981
982 EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
983 {
984     fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->view(exec).get().utf8().data());
985     return JSValue::encode(jsUndefined());
986 }
987
988 EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
989 {
990     if (exec->argumentCount() < 1)
991         return JSValue::encode(jsUndefined());
992     return JSValue::encode(jsString(exec, toString(exec->argument(0))));
993 }
994
995 EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
996 {
997     if (exec->argumentCount() < 1)
998         return JSValue::encode(jsUndefined());
999     JSObject* object = jsDynamicCast<JSObject*>(exec->argument(0));
1000     if (!object)
1001         return JSValue::encode(jsNontrivialString(exec, ASCIILiteral("<not object>")));
1002     return JSValue::encode(jsNontrivialString(exec, toString("<Public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
1003 }
1004
1005 class FunctionJSCStackFunctor {
1006 public:
1007     FunctionJSCStackFunctor(StringBuilder& trace)
1008         : m_trace(trace)
1009     {
1010     }
1011
1012     StackVisitor::Status operator()(StackVisitor& visitor)
1013     {
1014         m_trace.append(String::format("    %zu   %s\n", visitor->index(), visitor->toString().utf8().data()));
1015         return StackVisitor::Continue;
1016     }
1017
1018 private:
1019     StringBuilder& m_trace;
1020 };
1021
1022 EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
1023 {
1024     StringBuilder trace;
1025     trace.appendLiteral("--> Stack trace:\n");
1026
1027     FunctionJSCStackFunctor functor(trace);
1028     exec->iterate(functor);
1029     fprintf(stderr, "%s", trace.toString().utf8().data());
1030     return JSValue::encode(jsUndefined());
1031 }
1032
1033 EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
1034 {
1035     JSLockHolder lock(exec);
1036     return JSValue::encode(Root::create(exec->vm(), exec->lexicalGlobalObject()));
1037 }
1038
1039 EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
1040 {
1041     JSLockHolder lock(exec);
1042     JSValue arg = exec->argument(0);
1043     return JSValue::encode(Element::create(exec->vm(), exec->lexicalGlobalObject(), arg.isNull() ? nullptr : jsCast<Root*>(exec->argument(0))));
1044 }
1045
1046 EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
1047 {
1048     JSLockHolder lock(exec);
1049     Element* result = jsCast<Root*>(exec->argument(0).asCell())->element();
1050     return JSValue::encode(result ? result : jsUndefined());
1051 }
1052
1053 EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState* exec)
1054 {
1055     JSLockHolder lock(exec);
1056     Element* element = jsCast<Element*>(exec->argument(0));
1057     Root* root = jsCast<Root*>(exec->argument(1));
1058     element->setRoot(exec->vm(), root);
1059     return JSValue::encode(jsUndefined());
1060 }
1061
1062 EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState* exec)
1063 {
1064     JSLockHolder lock(exec);
1065     JSValue target = exec->argument(0);
1066     if (!target.isObject())
1067         return JSValue::encode(jsUndefined());
1068     JSObject* jsTarget = asObject(target.asCell());
1069     Structure* structure = JSProxy::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsTarget->prototype());
1070     JSProxy* proxy = JSProxy::create(exec->vm(), structure, jsTarget);
1071     return JSValue::encode(proxy);
1072 }
1073
1074 EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState* exec)
1075 {
1076     JSLockHolder lock(exec);
1077     RuntimeArray* array = RuntimeArray::create(exec);
1078     return JSValue::encode(array);
1079 }
1080
1081 EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
1082 {
1083     JSLockHolder lock(exec);
1084     JSValue target = exec->argument(0);
1085     JSObject* delegate = nullptr;
1086     if (target.isObject())
1087         delegate = asObject(target.asCell());
1088     Structure* structure = ImpureGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
1089     ImpureGetter* result = ImpureGetter::create(exec->vm(), structure, delegate);
1090     return JSValue::encode(result);
1091 }
1092
1093 EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
1094 {
1095     JSLockHolder lock(exec);
1096     JSValue base = exec->argument(0);
1097     if (!base.isObject())
1098         return JSValue::encode(jsUndefined());
1099     JSValue delegate = exec->argument(1);
1100     if (!delegate.isObject())
1101         return JSValue::encode(jsUndefined());
1102     ImpureGetter* impureGetter = jsCast<ImpureGetter*>(asObject(base.asCell()));
1103     impureGetter->setDelegate(exec->vm(), asObject(delegate.asCell()));
1104     return JSValue::encode(jsUndefined());
1105 }
1106
1107 EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
1108 {
1109     JSLockHolder lock(exec);
1110     exec->heap()->collectAllGarbage();
1111     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
1112 }
1113
1114 EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
1115 {
1116     JSLockHolder lock(exec);
1117     exec->heap()->collect(FullCollection);
1118     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
1119 }
1120
1121 EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
1122 {
1123     JSLockHolder lock(exec);
1124     exec->heap()->collect(EdenCollection);
1125     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastEdenCollection()));
1126 }
1127
1128 EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState* exec)
1129 {
1130     JSLockHolder lock(exec);
1131     return JSValue::encode(jsNumber(exec->heap()->size()));
1132 }
1133
1134 // This function is not generally very helpful in 64-bit code as the tag and payload
1135 // share a register. But in 32-bit JITed code the tag may not be checked if an
1136 // optimization removes type checking requirements, such as in ===.
1137 EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState* exec)
1138 {
1139     JSValue value = exec->argument(0);
1140     if (!value.isCell())
1141         return JSValue::encode(jsUndefined());
1142     // Need to cast to uint64_t so bitwise_cast will play along.
1143     uint64_t asNumber = reinterpret_cast<uint64_t>(value.asCell());
1144     EncodedJSValue returnValue = JSValue::encode(jsNumber(bitwise_cast<double>(asNumber)));
1145     return returnValue;
1146 }
1147
1148 EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
1149 {
1150     // We need this function for compatibility with the Mozilla JS tests but for now
1151     // we don't actually do any version-specific handling
1152     return JSValue::encode(jsUndefined());
1153 }
1154
1155 EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
1156 {
1157     String fileName = exec->argument(0).toString(exec)->value(exec);
1158     Vector<char> script;
1159     if (!fetchScriptFromLocalFileSystem(fileName, script))
1160         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1161
1162     GlobalObject* globalObject = GlobalObject::create(exec->vm(), GlobalObject::createStructure(exec->vm(), jsNull()), Vector<String>());
1163
1164     JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
1165     for (unsigned i = 1; i < exec->argumentCount(); ++i)
1166         array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
1167     globalObject->putDirect(
1168         exec->vm(), Identifier::fromString(globalObject->globalExec(), "arguments"), array);
1169
1170     NakedPtr<Exception> exception;
1171     StopWatch stopWatch;
1172     stopWatch.start();
1173     evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), exception);
1174     stopWatch.stop();
1175
1176     if (exception) {
1177         exec->vm().throwException(globalObject->globalExec(), exception);
1178         return JSValue::encode(jsUndefined());
1179     }
1180     
1181     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1182 }
1183
1184 EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
1185 {
1186     String fileName = exec->argument(0).toString(exec)->value(exec);
1187     Vector<char> script;
1188     if (!fetchScriptFromLocalFileSystem(fileName, script))
1189         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1190
1191     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1192     
1193     NakedPtr<Exception> evaluationException;
1194     JSValue result = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), evaluationException);
1195     if (evaluationException)
1196         exec->vm().throwException(exec, evaluationException);
1197     return JSValue::encode(result);
1198 }
1199
1200 EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
1201 {
1202     String fileName = exec->argument(0).toString(exec)->value(exec);
1203     Vector<char> script;
1204     if (!fillBufferWithContentsOfFile(fileName, script))
1205         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1206
1207     return JSValue::encode(jsString(exec, stringFromUTF(script)));
1208 }
1209
1210 EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
1211 {
1212     String fileName = exec->argument(0).toString(exec)->value(exec);
1213     Vector<char> script;
1214     if (!fetchScriptFromLocalFileSystem(fileName, script))
1215         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1216
1217     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1218
1219     StopWatch stopWatch;
1220     stopWatch.start();
1221
1222     JSValue syntaxException;
1223     bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script, fileName), &syntaxException);
1224     stopWatch.stop();
1225
1226     if (!validSyntax)
1227         exec->vm().throwException(exec, syntaxException);
1228     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1229 }
1230
1231 #if ENABLE(SAMPLING_FLAGS)
1232 EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
1233 {
1234     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1235         unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1236         if ((flag >= 1) && (flag <= 32))
1237             SamplingFlags::setFlag(flag);
1238     }
1239     return JSValue::encode(jsNull());
1240 }
1241
1242 EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
1243 {
1244     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
1245         unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
1246         if ((flag >= 1) && (flag <= 32))
1247             SamplingFlags::clearFlag(flag);
1248     }
1249     return JSValue::encode(jsNull());
1250 }
1251 #endif
1252
1253 EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
1254 {
1255     Vector<char, 256> line;
1256     int c;
1257     while ((c = getchar()) != EOF) {
1258         // FIXME: Should we also break on \r? 
1259         if (c == '\n')
1260             break;
1261         line.append(c);
1262     }
1263     line.append('\0');
1264     return JSValue::encode(jsString(exec, line.data()));
1265 }
1266
1267 EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
1268 {
1269     return JSValue::encode(jsNumber(currentTime()));
1270 }
1271
1272 EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState* exec)
1273 {
1274     return JSValue::encode(setNeverInline(exec));
1275 }
1276
1277 EncodedJSValue JSC_HOST_CALL functionNoDFG(ExecState* exec)
1278 {
1279     return JSValue::encode(setNeverOptimize(exec));
1280 }
1281
1282 EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
1283 {
1284     return JSValue::encode(optimizeNextInvocation(exec));
1285 }
1286
1287 EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
1288 {
1289     return JSValue::encode(numberOfDFGCompiles(exec));
1290 }
1291
1292 EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
1293 {
1294     if (exec->argumentCount() < 1)
1295         return JSValue::encode(jsUndefined());
1296     
1297     CodeBlock* block = getSomeBaselineCodeBlockForFunction(exec->argument(0));
1298     if (!block)
1299         return JSValue::encode(jsNumber(0));
1300     
1301     return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
1302 }
1303
1304 EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
1305 {
1306     if (exec->argumentCount() < 1)
1307         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Not enough arguments"))));
1308     
1309     JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(0));
1310     if (!buffer)
1311         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Expected an array buffer"))));
1312     
1313     ArrayBufferContents dummyContents;
1314     buffer->impl()->transfer(dummyContents);
1315     
1316     return JSValue::encode(jsUndefined());
1317 }
1318
1319 EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
1320 {
1321     jscExit(EXIT_SUCCESS);
1322
1323 #if COMPILER(MSVC)
1324     // Without this, Visual Studio will complain that this method does not return a value.
1325     return JSValue::encode(jsUndefined());
1326 #endif
1327 }
1328
1329 EncodedJSValue JSC_HOST_CALL functionAbort(ExecState*)
1330 {
1331     CRASH();
1332 }
1333
1334 EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1335 EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1336
1337 EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
1338 EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
1339 EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState* exec)
1340 {
1341     for (size_t i = 0; i < exec->argumentCount(); ++i) {
1342         if (!exec->argument(i).isInt32())
1343             return JSValue::encode(jsBoolean(false));
1344     }
1345     return JSValue::encode(jsBoolean(true));
1346 }
1347
1348 EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
1349
1350 EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
1351 {
1352     return JSValue::encode(jsNumber(42));
1353 }
1354
1355 EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
1356 {
1357     return JSValue::encode(Masquerader::create(exec->vm(), exec->lexicalGlobalObject()));
1358 }
1359
1360 EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState* exec)
1361 {
1362     JSValue value = exec->argument(0);
1363     if (value.isObject())
1364         return JSValue::encode(jsBoolean(asObject(value)->hasCustomProperties()));
1365     return JSValue::encode(jsBoolean(false));
1366 }
1367
1368 EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
1369 {
1370     exec->vm().dumpTypeProfilerData();
1371     return JSValue::encode(jsUndefined());
1372 }
1373
1374 EncodedJSValue JSC_HOST_CALL functionFindTypeForExpression(ExecState* exec)
1375 {
1376     RELEASE_ASSERT(exec->vm().typeProfiler());
1377     exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionFindTypeForExpression"));
1378
1379     JSValue functionValue = exec->argument(0);
1380     RELEASE_ASSERT(functionValue.isFunction());
1381     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1382
1383     RELEASE_ASSERT(exec->argument(1).isString());
1384     String substring = exec->argument(1).getString(exec);
1385     String sourceCodeText = executable->source().toString();
1386     unsigned offset = static_cast<unsigned>(sourceCodeText.find(substring) + executable->source().startOffset());
1387     
1388     String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorNormal, offset, executable->sourceID(), exec->vm());
1389     return JSValue::encode(JSONParse(exec, jsonString));
1390 }
1391
1392 EncodedJSValue JSC_HOST_CALL functionReturnTypeFor(ExecState* exec)
1393 {
1394     RELEASE_ASSERT(exec->vm().typeProfiler());
1395     exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("jsc Testing API: functionReturnTypeFor"));
1396
1397     JSValue functionValue = exec->argument(0);
1398     RELEASE_ASSERT(functionValue.isFunction());
1399     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1400
1401     unsigned offset = executable->typeProfilingStartOffset();
1402     String jsonString = exec->vm().typeProfiler()->typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorFunctionReturn, offset, executable->sourceID(), exec->vm());
1403     return JSValue::encode(JSONParse(exec, jsonString));
1404 }
1405
1406 EncodedJSValue JSC_HOST_CALL functionDumpBasicBlockExecutionRanges(ExecState* exec)
1407 {
1408     RELEASE_ASSERT(exec->vm().controlFlowProfiler());
1409     exec->vm().controlFlowProfiler()->dumpData();
1410     return JSValue::encode(jsUndefined());
1411 }
1412
1413 EncodedJSValue JSC_HOST_CALL functionHasBasicBlockExecuted(ExecState* exec)
1414 {
1415     RELEASE_ASSERT(exec->vm().controlFlowProfiler());
1416
1417     JSValue functionValue = exec->argument(0);
1418     RELEASE_ASSERT(functionValue.isFunction());
1419     FunctionExecutable* executable = (jsDynamicCast<JSFunction*>(functionValue.asCell()->getObject()))->jsExecutable();
1420
1421     RELEASE_ASSERT(exec->argument(1).isString());
1422     String substring = exec->argument(1).getString(exec);
1423     String sourceCodeText = executable->source().toString();
1424     RELEASE_ASSERT(sourceCodeText.contains(substring));
1425     int offset = sourceCodeText.find(substring) + executable->source().startOffset();
1426     
1427     bool hasExecuted = exec->vm().controlFlowProfiler()->hasBasicBlockAtTextOffsetBeenExecuted(offset, executable->sourceID(), exec->vm());
1428     return JSValue::encode(jsBoolean(hasExecuted));
1429 }
1430
1431 EncodedJSValue JSC_HOST_CALL functionEnableExceptionFuzz(ExecState*)
1432 {
1433     Options::enableExceptionFuzz() = true;
1434     return JSValue::encode(jsUndefined());
1435 }
1436
1437 EncodedJSValue JSC_HOST_CALL functionDrainMicrotasks(ExecState* exec)
1438 {
1439     exec->vm().drainMicrotasks();
1440     return JSValue::encode(jsUndefined());
1441 }
1442
1443 #if ENABLE(WEBASSEMBLY)
1444 EncodedJSValue JSC_HOST_CALL functionLoadWebAssembly(ExecState* exec)
1445 {
1446     String fileName = exec->argument(0).toString(exec)->value(exec);
1447     Vector<char> buffer;
1448     if (!fillBufferWithContentsOfFile(fileName, buffer))
1449         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1450     RefPtr<WebAssemblySourceProvider> sourceProvider = WebAssemblySourceProvider::create(reinterpret_cast<Vector<uint8_t>&>(buffer), fileName);
1451     SourceCode source(sourceProvider);
1452     JSObject* imports = exec->argument(1).getObject();
1453     JSArrayBuffer* arrayBuffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(2));
1454
1455     String errorMessage;
1456     JSWASMModule* module = parseWebAssembly(exec, source, imports, arrayBuffer, errorMessage);
1457     if (!module)
1458         return JSValue::encode(exec->vm().throwException(exec, createSyntaxError(exec, errorMessage)));
1459     return JSValue::encode(module);
1460 }
1461 #endif
1462
1463 EncodedJSValue JSC_HOST_CALL functionLoadModule(ExecState* exec)
1464 {
1465     String fileName = exec->argument(0).toString(exec)->value(exec);
1466     Vector<char> script;
1467     if (!fetchScriptFromLocalFileSystem(fileName, script))
1468         return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
1469
1470     JSInternalPromise* promise = loadAndEvaluateModule(exec, fileName);
1471     if (exec->hadException())
1472         return JSValue::encode(jsUndefined());
1473
1474     JSValue error;
1475     JSFunction* errorHandler = JSNativeStdFunction::create(exec->vm(), exec->lexicalGlobalObject(), 1, String(), [&](ExecState* exec) {
1476         error = exec->argument(0);
1477         return JSValue::encode(jsUndefined());
1478     });
1479
1480     promise->then(exec, nullptr, errorHandler);
1481     exec->vm().drainMicrotasks();
1482     if (error)
1483         return JSValue::encode(exec->vm().throwException(exec, error));
1484     return JSValue::encode(jsUndefined());
1485 }
1486
1487 EncodedJSValue JSC_HOST_CALL functionCheckModuleSyntax(ExecState* exec)
1488 {
1489     String source = exec->argument(0).toString(exec)->value(exec);
1490
1491     StopWatch stopWatch;
1492     stopWatch.start();
1493
1494     ParserError error;
1495     bool validSyntax = checkModuleSyntax(exec, makeSource(source), error);
1496     stopWatch.stop();
1497
1498     if (!validSyntax)
1499         exec->vm().throwException(exec, jsNontrivialString(exec, toString("SyntaxError: ", error.message(), ":", error.line())));
1500     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
1501 }
1502
1503 // Use SEH for Release builds only to get rid of the crash report dialog
1504 // (luckily the same tests fail in Release and Debug builds so far). Need to
1505 // be in a separate main function because the jscmain function requires object
1506 // unwinding.
1507
1508 #if COMPILER(MSVC) && !defined(_DEBUG)
1509 #define TRY       __try {
1510 #define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
1511 #else
1512 #define TRY
1513 #define EXCEPT(x)
1514 #endif
1515
1516 int jscmain(int argc, char** argv);
1517
1518 static double s_desiredTimeout;
1519
1520 static NO_RETURN_DUE_TO_CRASH void timeoutThreadMain(void*)
1521 {
1522     auto timeout = std::chrono::microseconds(static_cast<std::chrono::microseconds::rep>(s_desiredTimeout * 1000000));
1523     std::this_thread::sleep_for(timeout);
1524     
1525     dataLog("Timed out after ", s_desiredTimeout, " seconds!\n");
1526     CRASH();
1527 }
1528
1529 int main(int argc, char** argv)
1530 {
1531 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
1532     // Enabled IEEE754 denormal support.
1533     fenv_t env;
1534     fegetenv( &env );
1535     env.__fpscr &= ~0x01000000u;
1536     fesetenv( &env );
1537 #endif
1538
1539 #if OS(WINDOWS) && (defined(_M_X64) || defined(__x86_64__))
1540     // The VS2013 runtime has a bug where it mis-detects AVX-capable processors
1541     // if the feature has been disabled in firmware. This causes us to crash
1542     // in some of the math functions. For now, we disable those optimizations
1543     // because Microsoft is not going to fix the problem in VS2013.
1544     // FIXME: http://webkit.org/b/141449: Remove this workaround when we switch to VS2015+.
1545     _set_FMA3_enable(0);
1546
1547     // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
1548     // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
1549     // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
1550     ::SetErrorMode(0);
1551
1552 #if defined(_DEBUG)
1553     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
1554     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
1555     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
1556     _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
1557     _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
1558     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
1559 #endif
1560
1561     timeBeginPeriod(1);
1562 #endif
1563
1564 #if PLATFORM(EFL)
1565     ecore_init();
1566 #endif
1567
1568     // Need to initialize WTF threading before we start any threads. Cannot initialize JSC
1569     // threading yet, since that would do somethings that we'd like to defer until after we
1570     // have a chance to parse options.
1571     WTF::initializeThreading();
1572
1573     if (char* timeoutString = getenv("JSC_timeout")) {
1574         if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
1575             dataLog(
1576                 "WARNING: timeout string is malformed, got ", timeoutString,
1577                 " but expected a number. Not using a timeout.\n");
1578         } else
1579             createThread(timeoutThreadMain, 0, "jsc Timeout Thread");
1580     }
1581
1582 #if PLATFORM(IOS)
1583     Options::crashIfCantAllocateJITMemory() = true;
1584 #endif
1585
1586     // We can't use destructors in the following code because it uses Windows
1587     // Structured Exception Handling
1588     int res = 0;
1589     TRY
1590         res = jscmain(argc, argv);
1591     EXCEPT(res = 3)
1592     if (Options::logHeapStatisticsAtExit())
1593         HeapStatistics::reportSuccess();
1594
1595 #if PLATFORM(EFL)
1596     ecore_shutdown();
1597 #endif
1598
1599     jscExit(res);
1600 }
1601
1602 static void dumpException(GlobalObject* globalObject, JSValue exception)
1603 {
1604     printf("Exception: %s\n", exception.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1605     Identifier stackID = Identifier::fromString(globalObject->globalExec(), "stack");
1606     JSValue stackValue = exception.get(globalObject->globalExec(), stackID);
1607     if (!stackValue.isUndefinedOrNull())
1608         printf("%s\n", stackValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1609 }
1610
1611 static void dumpException(GlobalObject* globalObject, NakedPtr<Exception> evaluationException)
1612 {
1613     if (evaluationException)
1614         dumpException(globalObject, evaluationException->value());
1615 }
1616
1617 static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump, bool module)
1618 {
1619     String fileName;
1620     Vector<char> scriptBuffer;
1621
1622     if (dump)
1623         JSC::Options::dumpGeneratedBytecodes() = true;
1624
1625     VM& vm = globalObject->vm();
1626     bool success = true;
1627
1628     JSFunction* errorHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&](ExecState* exec) {
1629         success = false;
1630         dumpException(globalObject, exec->argument(0));
1631         return JSValue::encode(jsUndefined());
1632     });
1633
1634 #if ENABLE(SAMPLING_FLAGS)
1635     SamplingFlags::start();
1636 #endif
1637
1638     for (size_t i = 0; i < scripts.size(); i++) {
1639         JSInternalPromise* promise = nullptr;
1640         if (scripts[i].isFile) {
1641             fileName = scripts[i].argument;
1642             if (module)
1643                 promise = loadAndEvaluateModule(globalObject->globalExec(), fileName);
1644             else {
1645                 if (!fetchScriptFromLocalFileSystem(fileName, scriptBuffer))
1646                     return false; // fail early so we can catch missing files
1647             }
1648         } else {
1649             size_t commandLineLength = strlen(scripts[i].argument);
1650             scriptBuffer.resize(commandLineLength);
1651             std::copy(scripts[i].argument, scripts[i].argument + commandLineLength, scriptBuffer.begin());
1652             fileName = ASCIILiteral("[Command Line]");
1653         }
1654
1655         vm.startSampling();
1656
1657         if (module) {
1658             if (!promise)
1659                 promise = loadAndEvaluateModule(globalObject->globalExec(), jscSource(scriptBuffer, fileName));
1660             globalObject->globalExec()->clearException();
1661             promise->then(globalObject->globalExec(), nullptr, errorHandler);
1662             globalObject->vm().drainMicrotasks();
1663         } else {
1664             NakedPtr<Exception> evaluationException;
1665             JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(scriptBuffer, fileName), JSValue(), evaluationException);
1666             success = success && !evaluationException;
1667             if (dump && !evaluationException)
1668                 printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1669             dumpException(globalObject, evaluationException);
1670         }
1671
1672         vm.stopSampling();
1673         globalObject->globalExec()->clearException();
1674     }
1675
1676 #if ENABLE(SAMPLING_FLAGS)
1677     SamplingFlags::stop();
1678 #endif
1679 #if ENABLE(SAMPLING_REGIONS)
1680     SamplingRegion::dump();
1681 #endif
1682     vm.dumpSampleData(globalObject->globalExec());
1683 #if ENABLE(SAMPLING_COUNTERS)
1684     AbstractSamplingCounter::dump();
1685 #endif
1686 #if ENABLE(REGEXP_TRACING)
1687     vm.dumpRegExpTrace();
1688 #endif
1689     return success;
1690 }
1691
1692 #define RUNNING_FROM_XCODE 0
1693
1694 static void runInteractive(GlobalObject* globalObject)
1695 {
1696     String interpreterName(ASCIILiteral("Interpreter"));
1697     
1698     bool shouldQuit = false;
1699     while (!shouldQuit) {
1700 #if HAVE(READLINE) && !RUNNING_FROM_XCODE
1701         ParserError error;
1702         String source;
1703         do {
1704             error = ParserError();
1705             char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
1706             shouldQuit = !line;
1707             if (!line)
1708                 break;
1709             source = source + line;
1710             source = source + '\n';
1711             checkSyntax(globalObject->vm(), makeSource(source, interpreterName), error);
1712             if (!line[0])
1713                 break;
1714             add_history(line);
1715         } while (error.syntaxErrorType() == ParserError::SyntaxErrorRecoverable);
1716         
1717         if (error.isValid()) {
1718             printf("%s:%d\n", error.message().utf8().data(), error.line());
1719             continue;
1720         }
1721         
1722         
1723         NakedPtr<Exception> evaluationException;
1724         JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, interpreterName), JSValue(), evaluationException);
1725 #else
1726         printf("%s", interactivePrompt);
1727         Vector<char, 256> line;
1728         int c;
1729         while ((c = getchar()) != EOF) {
1730             // FIXME: Should we also break on \r? 
1731             if (c == '\n')
1732                 break;
1733             line.append(c);
1734         }
1735         if (line.isEmpty())
1736             break;
1737
1738         NakedPtr<Exception> evaluationException;
1739         JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line, interpreterName), JSValue(), evaluationException);
1740 #endif
1741         if (evaluationException)
1742             printf("Exception: %s\n", evaluationException->value().toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1743         else
1744             printf("%s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1745
1746         globalObject->globalExec()->clearException();
1747         globalObject->vm().drainMicrotasks();
1748     }
1749     printf("\n");
1750 }
1751
1752 static NO_RETURN void printUsageStatement(bool help = false)
1753 {
1754     fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
1755     fprintf(stderr, "  -d         Dumps bytecode (debug builds only)\n");
1756     fprintf(stderr, "  -e         Evaluate argument as script code\n");
1757     fprintf(stderr, "  -f         Specifies a source file (deprecated)\n");
1758     fprintf(stderr, "  -h|--help  Prints this help message\n");
1759     fprintf(stderr, "  -i         Enables interactive mode (default if no files are specified)\n");
1760     fprintf(stderr, "  -m         Execute as a module\n");
1761 #if HAVE(SIGNAL_H)
1762     fprintf(stderr, "  -s         Installs signal handlers that exit on a crash (Unix platforms only)\n");
1763 #endif
1764     fprintf(stderr, "  -p <file>  Outputs profiling data to a file\n");
1765     fprintf(stderr, "  -x         Output exit code before terminating\n");
1766     fprintf(stderr, "\n");
1767     fprintf(stderr, "  --options                  Dumps all JSC VM options and exits\n");
1768     fprintf(stderr, "  --dumpOptions              Dumps all JSC VM options before continuing\n");
1769     fprintf(stderr, "  --<jsc VM option>=<value>  Sets the specified JSC VM option\n");
1770     fprintf(stderr, "\n");
1771
1772     jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
1773 }
1774
1775 void CommandLine::parseArguments(int argc, char** argv)
1776 {
1777     Options::initialize();
1778     
1779     int i = 1;
1780     bool needToDumpOptions = false;
1781     bool needToExit = false;
1782
1783     for (; i < argc; ++i) {
1784         const char* arg = argv[i];
1785         if (!strcmp(arg, "-f")) {
1786             if (++i == argc)
1787                 printUsageStatement();
1788             m_scripts.append(Script(true, argv[i]));
1789             continue;
1790         }
1791         if (!strcmp(arg, "-e")) {
1792             if (++i == argc)
1793                 printUsageStatement();
1794             m_scripts.append(Script(false, argv[i]));
1795             continue;
1796         }
1797         if (!strcmp(arg, "-i")) {
1798             m_interactive = true;
1799             continue;
1800         }
1801         if (!strcmp(arg, "-d")) {
1802             m_dump = true;
1803             continue;
1804         }
1805         if (!strcmp(arg, "-p")) {
1806             if (++i == argc)
1807                 printUsageStatement();
1808             m_profile = true;
1809             m_profilerOutput = argv[i];
1810             continue;
1811         }
1812         if (!strcmp(arg, "-m")) {
1813             m_module = true;
1814             continue;
1815         }
1816         if (!strcmp(arg, "-s")) {
1817 #if HAVE(SIGNAL_H)
1818             signal(SIGILL, _exit);
1819             signal(SIGFPE, _exit);
1820             signal(SIGBUS, _exit);
1821             signal(SIGSEGV, _exit);
1822 #endif
1823             continue;
1824         }
1825         if (!strcmp(arg, "-x")) {
1826             m_exitCode = true;
1827             continue;
1828         }
1829         if (!strcmp(arg, "--")) {
1830             ++i;
1831             break;
1832         }
1833         if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
1834             printUsageStatement(true);
1835
1836         if (!strcmp(arg, "--options")) {
1837             needToDumpOptions = true;
1838             needToExit = true;
1839             continue;
1840         }
1841         if (!strcmp(arg, "--dumpOptions")) {
1842             needToDumpOptions = true;
1843             continue;
1844         }
1845
1846         // See if the -- option is a JSC VM option.
1847         if (strstr(arg, "--") == arg && JSC::Options::setOption(&arg[2])) {
1848             // The arg was recognized as a VM option and has been parsed.
1849             continue; // Just continue with the next arg. 
1850         }
1851
1852         // This arg is not recognized by the VM nor by jsc. Pass it on to the
1853         // script.
1854         m_scripts.append(Script(true, argv[i]));
1855     }
1856
1857     if (m_scripts.isEmpty())
1858         m_interactive = true;
1859
1860     for (; i < argc; ++i)
1861         m_arguments.append(argv[i]);
1862
1863     if (needToDumpOptions)
1864         JSC::Options::dumpAllOptions(stderr, JSC::Options::DumpLevel::Verbose, "All JSC runtime options:");
1865     JSC::Options::ensureOptionsAreCoherent();
1866     if (needToExit)
1867         jscExit(EXIT_SUCCESS);
1868 }
1869
1870 int jscmain(int argc, char** argv)
1871 {
1872     // Note that the options parsing can affect VM creation, and thus
1873     // comes first.
1874     CommandLine options(argc, argv);
1875
1876     // Initialize JSC before getting VM.
1877 #if ENABLE(SAMPLING_REGIONS)
1878     WTF::initializeMainThread();
1879 #endif
1880     JSC::initializeThreading();
1881
1882     VM* vm = &VM::create(LargeHeap).leakRef();
1883     int result;
1884     {
1885         JSLockHolder locker(vm);
1886
1887         if (options.m_profile && !vm->m_perBytecodeProfiler)
1888             vm->m_perBytecodeProfiler = std::make_unique<Profiler::Database>(*vm);
1889     
1890         GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.m_arguments);
1891         bool success = runWithScripts(globalObject, options.m_scripts, options.m_dump, options.m_module);
1892         if (options.m_interactive && success)
1893             runInteractive(globalObject);
1894
1895         result = success ? 0 : 3;
1896
1897         if (options.m_exitCode)
1898             printf("jsc exiting %d\n", result);
1899     
1900         if (options.m_profile) {
1901             if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
1902                 fprintf(stderr, "could not save profiler output.\n");
1903         }
1904         
1905 #if ENABLE(JIT)
1906         if (Options::enableExceptionFuzz())
1907             printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
1908         bool fireAtEnabled =
1909             Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
1910         if (Options::enableExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
1911             printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks());
1912         if (Options::enableOSRExitFuzz()) {
1913             printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks());
1914             printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks());
1915         }
1916 #endif
1917         auto compileTimeStats = DFG::Plan::compileTimeStats();
1918         Vector<CString> compileTimeKeys;
1919         for (auto& entry : compileTimeStats)
1920             compileTimeKeys.append(entry.key);
1921         std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
1922         for (CString key : compileTimeKeys)
1923             printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key));
1924     }
1925     
1926     return result;
1927 }
1928
1929 #if OS(WINDOWS)
1930 extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
1931 {
1932     return main(argc, const_cast<char**>(argv));
1933 }
1934 #endif