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