[ARM] Incorrect handling of Unicode characters
[WebKit.git] / Source / JavaScriptCore / jsc.cpp
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012, 2013 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 "ExceptionHelpers.h"
32 #include "HeapStatistics.h"
33 #include "InitializeThreading.h"
34 #include "Interpreter.h"
35 #include "JSArray.h"
36 #include "JSArrayBuffer.h"
37 #include "JSCInlines.h"
38 #include "JSFunction.h"
39 #include "JSLock.h"
40 #include "JSProxy.h"
41 #include "JSString.h"
42 #include "ProfilerDatabase.h"
43 #include "SamplingTool.h"
44 #include "StackVisitor.h"
45 #include "StructureInlines.h"
46 #include "StructureRareDataInlines.h"
47 #include "TestRunnerUtils.h"
48 #include <math.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <thread>
53 #include <wtf/CurrentTime.h>
54 #include <wtf/MainThread.h>
55 #include <wtf/StringPrintStream.h>
56 #include <wtf/text/StringBuilder.h>
57
58 #if !OS(WINDOWS)
59 #include <unistd.h>
60 #endif
61
62 #if HAVE(READLINE)
63 // readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
64 // We #define it to something else to avoid this conflict.
65 #define Function ReadlineFunction
66 #include <readline/history.h>
67 #include <readline/readline.h>
68 #undef Function
69 #endif
70
71 #if HAVE(SYS_TIME_H)
72 #include <sys/time.h>
73 #endif
74
75 #if HAVE(SIGNAL_H)
76 #include <signal.h>
77 #endif
78
79 #if COMPILER(MSVC) && !OS(WINCE)
80 #include <crtdbg.h>
81 #include <mmsystem.h>
82 #include <windows.h>
83 #endif
84
85 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
86 #include <fenv.h>
87 #include <arm/arch.h>
88 #endif
89
90 #if PLATFORM(EFL)
91 #include <Ecore.h>
92 #endif
93
94 using namespace JSC;
95 using namespace WTF;
96
97 namespace JSC {
98 WTF_IMPORT extern const struct HashTable globalObjectTable;
99 }
100
101 namespace {
102
103 NO_RETURN_WITH_VALUE static void jscExit(int status)
104 {
105 #if ENABLE(DFG_JIT)
106     if (DFG::isCrashing()) {
107         for (;;) {
108 #if OS(WINDOWS)
109             Sleep(1000);
110 #else
111             pause();
112 #endif
113         }
114     }
115 #endif // ENABLE(DFG_JIT)
116     exit(status);
117 }
118
119 class Element;
120 class ElementHandleOwner;
121 class Masuqerader;
122 class Root;
123 class RuntimeArray;
124
125 class Element : public JSNonFinalObject {
126 public:
127     Element(VM& vm, Structure* structure, Root* root)
128         : Base(vm, structure)
129         , m_root(root)
130     {
131     }
132
133     typedef JSNonFinalObject Base;
134     static const bool needsDestruction = false;
135
136     Root* root() const { return m_root; }
137     void setRoot(Root* root) { m_root = root; }
138
139     static Element* create(VM& vm, JSGlobalObject* globalObject, Root* root)
140     {
141         Structure* structure = createStructure(vm, globalObject, jsNull());
142         Element* element = new (NotNull, allocateCell<Element>(vm.heap, sizeof(Element))) Element(vm, structure, root);
143         element->finishCreation(vm);
144         return element;
145     }
146
147     void finishCreation(VM&);
148
149     static ElementHandleOwner* handleOwner();
150
151     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
152     {
153         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
154     }
155
156     DECLARE_INFO;
157
158 private:
159     Root* m_root;
160 };
161
162 class ElementHandleOwner : public WeakHandleOwner {
163 public:
164     virtual bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
165     {
166         Element* element = jsCast<Element*>(handle.slot()->asCell());
167         return visitor.containsOpaqueRoot(element->root());
168     }
169 };
170
171 class Masquerader : public JSNonFinalObject {
172 public:
173     Masquerader(VM& vm, Structure* structure)
174         : Base(vm, structure)
175     {
176     }
177
178     typedef JSNonFinalObject Base;
179
180     static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
181     {
182         globalObject->masqueradesAsUndefinedWatchpoint()->fireAll("Masquerading object allocated");
183         Structure* structure = createStructure(vm, globalObject, jsNull());
184         Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
185         result->finishCreation(vm);
186         return result;
187     }
188
189     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
190     {
191         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
192     }
193
194     DECLARE_INFO;
195
196 protected:
197     static const unsigned StructureFlags = JSC::MasqueradesAsUndefined | Base::StructureFlags;
198 };
199
200 class Root : public JSDestructibleObject {
201 public:
202     Root(VM& vm, Structure* structure)
203         : Base(vm, structure)
204     {
205     }
206
207     Element* element()
208     {
209         return m_element.get();
210     }
211
212     void setElement(Element* element)
213     {
214         Weak<Element> newElement(element, Element::handleOwner());
215         m_element.swap(newElement);
216     }
217
218     static Root* create(VM& vm, JSGlobalObject* globalObject)
219     {
220         Structure* structure = createStructure(vm, globalObject, jsNull());
221         Root* root = new (NotNull, allocateCell<Root>(vm.heap, sizeof(Root))) Root(vm, structure);
222         root->finishCreation(vm);
223         return root;
224     }
225
226     typedef JSDestructibleObject Base;
227
228     DECLARE_INFO;
229     static const bool needsDestruction = true;
230
231     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
232     {
233         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
234     }
235
236     static void visitChildren(JSCell* thisObject, SlotVisitor& visitor)
237     {
238         Base::visitChildren(thisObject, visitor);
239         visitor.addOpaqueRoot(thisObject);
240     }
241
242 private:
243     Weak<Element> m_element;
244 };
245
246 class ImpureGetter : public JSNonFinalObject {
247 public:
248     ImpureGetter(VM& vm, Structure* structure)
249         : Base(vm, structure)
250     {
251     }
252
253     DECLARE_INFO;
254     typedef JSNonFinalObject Base;
255
256     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
257     {
258         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
259     }
260
261     static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate)
262     {
263         ImpureGetter* getter = new (NotNull, allocateCell<ImpureGetter>(vm.heap, sizeof(ImpureGetter))) ImpureGetter(vm, structure);
264         getter->finishCreation(vm, delegate);
265         return getter;
266     }
267
268     void finishCreation(VM& vm, JSObject* delegate)
269     {
270         Base::finishCreation(vm);
271         if (delegate)
272             m_delegate.set(vm, this, delegate);
273     }
274
275     static const unsigned StructureFlags = JSC::HasImpureGetOwnPropertySlot | JSC::OverridesGetOwnPropertySlot | Base::StructureFlags;
276
277     static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot)
278     {
279         ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
280         
281         if (thisObject->m_delegate && thisObject->m_delegate->getPropertySlot(exec, name, slot))
282             return true;
283
284         return Base::getOwnPropertySlot(object, exec, name, slot);
285     }
286
287     static void visitChildren(JSCell* cell, SlotVisitor& visitor)
288     {
289         Base::visitChildren(cell, visitor);
290         ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
291         visitor.append(&thisObject->m_delegate);
292     }
293
294     void setDelegate(VM& vm, JSObject* delegate)
295     {
296         m_delegate.set(vm, this, delegate);
297     }
298
299 private:
300     WriteBarrier<JSObject> m_delegate;
301 };
302
303 class RuntimeArray : public JSArray {
304 public:
305     typedef JSArray Base;
306
307     static RuntimeArray* create(ExecState* exec)
308     {
309         VM& vm = exec->vm();
310         JSGlobalObject* globalObject = exec->lexicalGlobalObject();
311         Structure* structure = createStructure(vm, globalObject, createPrototype(vm, globalObject));
312         RuntimeArray* runtimeArray = new (NotNull, allocateCell<RuntimeArray>(*exec->heap())) RuntimeArray(exec, structure);
313         runtimeArray->finishCreation(exec);
314         vm.heap.addFinalizer(runtimeArray, destroy);
315         return runtimeArray;
316     }
317
318     ~RuntimeArray() { }
319
320     static void destroy(JSCell* cell)
321     {
322         static_cast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
323     }
324
325     static const bool needsDestruction = false;
326
327     static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
328     {
329         RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
330         if (propertyName == exec->propertyNames().length) {
331             slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->lengthGetter);
332             return true;
333         }
334
335         unsigned index = propertyName.asIndex();
336         if (index < thisObject->getLength()) {
337             ASSERT(index != PropertyName::NotAnIndex);
338             slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index]));
339             return true;
340         }
341
342         return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
343     }
344
345     static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
346     {
347         RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
348         if (index < thisObject->getLength()) {
349             slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index]));
350             return true;
351         }
352
353         return JSObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot);
354     }
355
356     static NO_RETURN_DUE_TO_CRASH void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&)
357     {
358         RELEASE_ASSERT_NOT_REACHED();
359     }
360
361     static NO_RETURN_DUE_TO_CRASH bool deleteProperty(JSCell*, ExecState*, PropertyName)
362     {
363         RELEASE_ASSERT_NOT_REACHED();
364 #if !COMPILER(CLANG) && !COMPILER(MSVC)
365         return true;
366 #endif
367     }
368
369     unsigned getLength() const { return m_vector.size(); }
370
371     DECLARE_INFO;
372
373     static ArrayPrototype* createPrototype(VM&, JSGlobalObject* globalObject)
374     {
375         return globalObject->arrayPrototype();
376     }
377
378     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
379     {
380         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
381     }
382
383 protected:
384     void finishCreation(ExecState* exec)
385     {
386         Base::finishCreation(exec->vm());
387         ASSERT(inherits(info()));
388
389         for (size_t i = 0; i < exec->argumentCount(); i++)
390             m_vector.append(exec->argument(i).toInt32(exec));
391     }
392
393     static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames | JSArray::StructureFlags;
394
395 private:
396     RuntimeArray(ExecState* exec, Structure* structure)
397         : JSArray(exec->vm(), structure, 0)
398     {
399     }
400
401     static EncodedJSValue lengthGetter(ExecState* exec, JSObject*, EncodedJSValue thisValue, PropertyName)
402     {
403         RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(JSValue::decode(thisValue));
404         if (!thisObject)
405             return throwVMTypeError(exec);
406         return JSValue::encode(jsNumber(thisObject->getLength()));
407     }
408
409     Vector<int> m_vector;
410 };
411
412 const ClassInfo Element::s_info = { "Element", &Base::s_info, 0, CREATE_METHOD_TABLE(Element) };
413 const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, 0, CREATE_METHOD_TABLE(Masquerader) };
414 const ClassInfo Root::s_info = { "Root", &Base::s_info, 0, CREATE_METHOD_TABLE(Root) };
415 const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(ImpureGetter) };
416 const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, 0, CREATE_METHOD_TABLE(RuntimeArray) };
417
418 ElementHandleOwner* Element::handleOwner()
419 {
420     static ElementHandleOwner* owner = 0;
421     if (!owner)
422         owner = new ElementHandleOwner();
423     return owner;
424 }
425
426 void Element::finishCreation(VM& vm)
427 {
428     Base::finishCreation(vm);
429     m_root->setElement(this);
430 }
431
432 }
433
434 static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
435
436 static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*);
437 static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState*);
438 static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
439 static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
440
441 static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*);
442 static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState*);
443 static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState*);
444 static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState*);
445 static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
446 static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
447 static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
448 static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
449 static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
450 static EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState*);
451 static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
452 static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
453 static EncodedJSValue JSC_HOST_CALL functionDeleteAllCompiledCode(ExecState*);
454 #ifndef NDEBUG
455 static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
456 static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
457 #endif
458 static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
459 static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
460 static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
461 static EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState*);
462 static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
463 static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
464 static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
465 static EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState*);
466 static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
467 static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
468 static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
469 static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
470 static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
471 static EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*);
472 static EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*);
473 static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
474 static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
475 static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
476 static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
477 static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
478 static EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState*);
479 static EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables (ExecState*);
480
481 #if ENABLE(SAMPLING_FLAGS)
482 static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
483 static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
484 #endif
485
486 struct Script {
487     bool isFile;
488     char* argument;
489
490     Script(bool isFile, char *argument)
491         : isFile(isFile)
492         , argument(argument)
493     {
494     }
495 };
496
497 class CommandLine {
498 public:
499     CommandLine(int argc, char** argv)
500         : m_interactive(false)
501         , m_dump(false)
502         , m_exitCode(false)
503         , m_profile(false)
504     {
505         parseArguments(argc, argv);
506     }
507
508     bool m_interactive;
509     bool m_dump;
510     bool m_exitCode;
511     Vector<Script> m_scripts;
512     Vector<String> m_arguments;
513     bool m_profile;
514     String m_profilerOutput;
515
516     void parseArguments(int, char**);
517 };
518
519 static const char interactivePrompt[] = ">>> ";
520
521 class StopWatch {
522 public:
523     void start();
524     void stop();
525     long getElapsedMS(); // call stop() first
526
527 private:
528     double m_startTime;
529     double m_stopTime;
530 };
531
532 void StopWatch::start()
533 {
534     m_startTime = monotonicallyIncreasingTime();
535 }
536
537 void StopWatch::stop()
538 {
539     m_stopTime = monotonicallyIncreasingTime();
540 }
541
542 long StopWatch::getElapsedMS()
543 {
544     return static_cast<long>((m_stopTime - m_startTime) * 1000);
545 }
546
547 class GlobalObject : public JSGlobalObject {
548 private:
549     GlobalObject(VM&, Structure*);
550
551 public:
552     typedef JSGlobalObject Base;
553
554     static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
555     {
556         GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
557         object->finishCreation(vm, arguments);
558         vm.heap.addFinalizer(object, destroy);
559         return object;
560     }
561
562     static const bool needsDestruction = false;
563
564     DECLARE_INFO;
565     static const GlobalObjectMethodTable s_globalObjectMethodTable;
566
567     static Structure* createStructure(VM& vm, JSValue prototype)
568     {
569         return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
570     }
571
572     static bool javaScriptExperimentsEnabled(const JSGlobalObject*) { return true; }
573
574 protected:
575     void finishCreation(VM& vm, const Vector<String>& arguments)
576     {
577         Base::finishCreation(vm);
578         
579         addFunction(vm, "debug", functionDebug, 1);
580         addFunction(vm, "describe", functionDescribe, 1);
581         addFunction(vm, "describeArray", functionDescribeArray, 1);
582         addFunction(vm, "print", functionPrint, 1);
583         addFunction(vm, "quit", functionQuit, 0);
584         addFunction(vm, "gc", functionGCAndSweep, 0);
585         addFunction(vm, "fullGC", functionFullGC, 0);
586         addFunction(vm, "edenGC", functionEdenGC, 0);
587         addFunction(vm, "deleteAllCompiledCode", functionDeleteAllCompiledCode, 0);
588 #ifndef NDEBUG
589         addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
590         addFunction(vm, "releaseExecutableMemory", functionReleaseExecutableMemory, 0);
591 #endif
592         addFunction(vm, "version", functionVersion, 1);
593         addFunction(vm, "run", functionRun, 1);
594         addFunction(vm, "load", functionLoad, 1);
595         addFunction(vm, "readFile", functionReadFile, 1);
596         addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
597         addFunction(vm, "jscStack", functionJSCStack, 1);
598         addFunction(vm, "readline", functionReadline, 0);
599         addFunction(vm, "preciseTime", functionPreciseTime, 0);
600         addFunction(vm, "neverInlineFunction", functionNeverInlineFunction, 1);
601         addFunction(vm, "noInline", functionNeverInlineFunction, 1);
602         addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
603         addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
604         addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
605         addFunction(vm, "transferArrayBuffer", functionTransferArrayBuffer, 1);
606 #if ENABLE(SAMPLING_FLAGS)
607         addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
608         addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
609 #endif
610         addConstructableFunction(vm, "Root", functionCreateRoot, 0);
611         addConstructableFunction(vm, "Element", functionCreateElement, 1);
612         addFunction(vm, "getElement", functionGetElement, 1);
613         addFunction(vm, "setElementRoot", functionSetElementRoot, 2);
614         
615         putDirectNativeFunction(vm, this, Identifier(&vm, "DFGTrue"), 0, functionFalse1, DFGTrueIntrinsic, DontEnum | JSC::Function);
616         putDirectNativeFunction(vm, this, Identifier(&vm, "OSRExit"), 0, functionUndefined1, OSRExitIntrinsic, DontEnum | JSC::Function);
617         putDirectNativeFunction(vm, this, Identifier(&vm, "isFinalTier"), 0, functionFalse2, IsFinalTierIntrinsic, DontEnum | JSC::Function);
618         putDirectNativeFunction(vm, this, Identifier(&vm, "predictInt32"), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, DontEnum | JSC::Function);
619         putDirectNativeFunction(vm, this, Identifier(&vm, "fiatInt52"), 0, functionIdentity, FiatInt52Intrinsic, DontEnum | JSC::Function);
620         
621         addFunction(vm, "effectful42", functionEffectful42, 0);
622         addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
623         addFunction(vm, "hasCustomProperties", functionHasCustomProperties, 0);
624
625         addFunction(vm, "createProxy", functionCreateProxy, 1);
626         addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
627
628         addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
629         addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
630         addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 4);
631         
632         JSArray* array = constructEmptyArray(globalExec(), 0);
633         for (size_t i = 0; i < arguments.size(); ++i)
634             array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
635         putDirect(vm, Identifier(globalExec(), "arguments"), array);
636         
637         putDirect(vm, Identifier(globalExec(), "console"), jsUndefined());
638     }
639
640     void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
641     {
642         Identifier identifier(&vm, name);
643         putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function));
644     }
645     
646     void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
647     {
648         Identifier identifier(&vm, name);
649         putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function));
650     }
651 };
652
653 const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, &globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
654 const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled, 0, &shouldInterruptScriptBeforeTimeout };
655
656
657 GlobalObject::GlobalObject(VM& vm, Structure* structure)
658     : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
659 {
660 }
661
662 static inline String stringFromUTF(const char* utf8)
663 {
664     return String::fromUTF8WithLatin1Fallback(utf8, strlen(utf8));
665 }
666
667 static inline SourceCode jscSource(const char* utf8, const String& filename)
668 {
669     String str = stringFromUTF(utf8);
670     return makeSource(str, filename);
671 }
672
673 EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
674 {
675     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
676         if (i)
677             putchar(' ');
678
679         printf("%s", exec->uncheckedArgument(i).toString(exec)->value(exec).utf8().data());
680     }
681
682     putchar('\n');
683     fflush(stdout);
684     return JSValue::encode(jsUndefined());
685 }
686
687 #ifndef NDEBUG
688 EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
689 {
690     if (!exec->callerFrame()->isVMEntrySentinel())
691         exec->vm().interpreter->dumpCallFrame(exec->callerFrame());
692     return JSValue::encode(jsUndefined());
693 }
694 #endif
695
696 EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
697 {
698     fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->value(exec).utf8().data());
699     return JSValue::encode(jsUndefined());
700 }
701
702 EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
703 {
704     if (exec->argumentCount() < 1)
705         return JSValue::encode(jsUndefined());
706     return JSValue::encode(jsString(exec, toString(exec->argument(0))));
707 }
708
709 EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState* exec)
710 {
711     if (exec->argumentCount() < 1)
712         return JSValue::encode(jsUndefined());
713     JSObject* object = jsDynamicCast<JSObject*>(exec->argument(0));
714     if (!object)
715         return JSValue::encode(jsString(exec, "<not object>"));
716     return JSValue::encode(jsString(exec, toString("<Public length: ", object->getArrayLength(), "; vector length: ", object->getVectorLength(), ">")));
717 }
718
719 class FunctionJSCStackFunctor {
720 public:
721     FunctionJSCStackFunctor(StringBuilder& trace)
722         : m_trace(trace)
723     {
724     }
725
726     StackVisitor::Status operator()(StackVisitor& visitor)
727     {
728         m_trace.append(String::format("    %zu   %s\n", visitor->index(), visitor->toString().utf8().data()));
729         return StackVisitor::Continue;
730     }
731
732 private:
733     StringBuilder& m_trace;
734 };
735
736 EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
737 {
738     StringBuilder trace;
739     trace.appendLiteral("--> Stack trace:\n");
740
741     FunctionJSCStackFunctor functor(trace);
742     exec->iterate(functor);
743     fprintf(stderr, "%s", trace.toString().utf8().data());
744     return JSValue::encode(jsUndefined());
745 }
746
747 EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState* exec)
748 {
749     JSLockHolder lock(exec);
750     return JSValue::encode(Root::create(exec->vm(), exec->lexicalGlobalObject()));
751 }
752
753 EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState* exec)
754 {
755     JSLockHolder lock(exec);
756     JSValue arg = exec->argument(0);
757     return JSValue::encode(Element::create(exec->vm(), exec->lexicalGlobalObject(), arg.isNull() ? nullptr : jsCast<Root*>(exec->argument(0))));
758 }
759
760 EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState* exec)
761 {
762     JSLockHolder lock(exec);
763     Element* result = jsCast<Root*>(exec->argument(0).asCell())->element();
764     return JSValue::encode(result ? result : jsUndefined());
765 }
766
767 EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState* exec)
768 {
769     JSLockHolder lock(exec);
770     Element* element = jsCast<Element*>(exec->argument(0));
771     Root* root = jsCast<Root*>(exec->argument(1));
772     element->setRoot(root);
773     return JSValue::encode(jsUndefined());
774 }
775
776 EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState* exec)
777 {
778     JSLockHolder lock(exec);
779     JSValue target = exec->argument(0);
780     if (!target.isObject())
781         return JSValue::encode(jsUndefined());
782     JSObject* jsTarget = asObject(target.asCell());
783     Structure* structure = JSProxy::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsTarget->prototype());
784     JSProxy* proxy = JSProxy::create(exec->vm(), structure, jsTarget);
785     return JSValue::encode(proxy);
786 }
787
788 EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState* exec)
789 {
790     JSLockHolder lock(exec);
791     RuntimeArray* array = RuntimeArray::create(exec);
792     return JSValue::encode(array);
793 }
794
795 EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
796 {
797     JSLockHolder lock(exec);
798     JSValue target = exec->argument(0);
799     JSObject* delegate = nullptr;
800     if (target.isObject())
801         delegate = asObject(target.asCell());
802     Structure* structure = ImpureGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
803     ImpureGetter* result = ImpureGetter::create(exec->vm(), structure, delegate);
804     return JSValue::encode(result);
805 }
806
807 EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
808 {
809     JSLockHolder lock(exec);
810     JSValue base = exec->argument(0);
811     if (!base.isObject())
812         return JSValue::encode(jsUndefined());
813     JSValue delegate = exec->argument(1);
814     if (!delegate.isObject())
815         return JSValue::encode(jsUndefined());
816     ImpureGetter* impureGetter = jsCast<ImpureGetter*>(asObject(base.asCell()));
817     impureGetter->setDelegate(exec->vm(), asObject(delegate.asCell()));
818     return JSValue::encode(jsUndefined());
819 }
820
821 EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
822 {
823     JSLockHolder lock(exec);
824     exec->heap()->collectAllGarbage();
825     return JSValue::encode(jsUndefined());
826 }
827
828 EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
829 {
830     JSLockHolder lock(exec);
831     exec->heap()->collect(FullCollection);
832     return JSValue::encode(jsUndefined());
833 }
834
835 EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
836 {
837     JSLockHolder lock(exec);
838     exec->heap()->collect(EdenCollection);
839     return JSValue::encode(jsUndefined());
840 }
841
842 EncodedJSValue JSC_HOST_CALL functionDeleteAllCompiledCode(ExecState* exec)
843 {
844     JSLockHolder lock(exec);
845     exec->heap()->deleteAllCompiledCode();
846     return JSValue::encode(jsUndefined());
847 }
848
849 #ifndef NDEBUG
850 EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
851 {
852     JSLockHolder lock(exec);
853     exec->vm().releaseExecutableMemory();
854     return JSValue::encode(jsUndefined());
855 }
856 #endif
857
858 EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
859 {
860     // We need this function for compatibility with the Mozilla JS tests but for now
861     // we don't actually do any version-specific handling
862     return JSValue::encode(jsUndefined());
863 }
864
865 EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
866 {
867     String fileName = exec->argument(0).toString(exec)->value(exec);
868     Vector<char> script;
869     if (!fillBufferWithContentsOfFile(fileName, script))
870         return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Could not open file.")));
871
872     GlobalObject* globalObject = GlobalObject::create(exec->vm(), GlobalObject::createStructure(exec->vm(), jsNull()), Vector<String>());
873
874     JSArray* array = constructEmptyArray(globalObject->globalExec(), 0);
875     for (unsigned i = 1; i < exec->argumentCount(); ++i)
876         array->putDirectIndex(globalObject->globalExec(), i - 1, exec->uncheckedArgument(i));
877     globalObject->putDirect(
878         exec->vm(), Identifier(globalObject->globalExec(), "arguments"), array);
879
880     JSValue exception;
881     StopWatch stopWatch;
882     stopWatch.start();
883     evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), &exception);
884     stopWatch.stop();
885
886     if (!!exception) {
887         exec->vm().throwException(globalObject->globalExec(), exception);
888         return JSValue::encode(jsUndefined());
889     }
890     
891     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
892 }
893
894 EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
895 {
896     String fileName = exec->argument(0).toString(exec)->value(exec);
897     Vector<char> script;
898     if (!fillBufferWithContentsOfFile(fileName, script))
899         return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Could not open file.")));
900
901     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
902     
903     JSValue evaluationException;
904     JSValue result = evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), &evaluationException);
905     if (evaluationException)
906         exec->vm().throwException(exec, evaluationException);
907     return JSValue::encode(result);
908 }
909
910 EncodedJSValue JSC_HOST_CALL functionReadFile(ExecState* exec)
911 {
912     String fileName = exec->argument(0).toString(exec)->value(exec);
913     Vector<char> script;
914     if (!fillBufferWithContentsOfFile(fileName, script))
915         return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Could not open file.")));
916
917     return JSValue::encode(jsString(exec, stringFromUTF(script.data())));
918 }
919
920 EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
921 {
922     String fileName = exec->argument(0).toString(exec)->value(exec);
923     Vector<char> script;
924     if (!fillBufferWithContentsOfFile(fileName, script))
925         return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Could not open file.")));
926
927     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
928
929     StopWatch stopWatch;
930     stopWatch.start();
931
932     JSValue syntaxException;
933     bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script.data(), fileName), &syntaxException);
934     stopWatch.stop();
935
936     if (!validSyntax)
937         exec->vm().throwException(exec, syntaxException);
938     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
939 }
940
941 #if ENABLE(SAMPLING_FLAGS)
942 EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
943 {
944     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
945         unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
946         if ((flag >= 1) && (flag <= 32))
947             SamplingFlags::setFlag(flag);
948     }
949     return JSValue::encode(jsNull());
950 }
951
952 EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
953 {
954     for (unsigned i = 0; i < exec->argumentCount(); ++i) {
955         unsigned flag = static_cast<unsigned>(exec->uncheckedArgument(i).toNumber(exec));
956         if ((flag >= 1) && (flag <= 32))
957             SamplingFlags::clearFlag(flag);
958     }
959     return JSValue::encode(jsNull());
960 }
961 #endif
962
963 EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
964 {
965     Vector<char, 256> line;
966     int c;
967     while ((c = getchar()) != EOF) {
968         // FIXME: Should we also break on \r? 
969         if (c == '\n')
970             break;
971         line.append(c);
972     }
973     line.append('\0');
974     return JSValue::encode(jsString(exec, line.data()));
975 }
976
977 EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
978 {
979     return JSValue::encode(jsNumber(currentTime()));
980 }
981
982 EncodedJSValue JSC_HOST_CALL functionNeverInlineFunction(ExecState* exec)
983 {
984     return JSValue::encode(setNeverInline(exec));
985 }
986
987 EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState* exec)
988 {
989     return JSValue::encode(optimizeNextInvocation(exec));
990 }
991
992 EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState* exec)
993 {
994     return JSValue::encode(numberOfDFGCompiles(exec));
995 }
996
997 EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
998 {
999     if (exec->argumentCount() < 1)
1000         return JSValue::encode(jsUndefined());
1001     
1002     CodeBlock* block = getSomeBaselineCodeBlockForFunction(exec->argument(0));
1003     if (!block)
1004         return JSValue::encode(jsNumber(0));
1005     
1006     return JSValue::encode(jsNumber(block->reoptimizationRetryCounter()));
1007 }
1008
1009 EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState* exec)
1010 {
1011     if (exec->argumentCount() < 1)
1012         return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Not enough arguments")));
1013     
1014     JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(exec->argument(0));
1015     if (!buffer)
1016         return JSValue::encode(exec->vm().throwException(exec, createError(exec, "Expected an array buffer")));
1017     
1018     ArrayBufferContents dummyContents;
1019     buffer->impl()->transfer(dummyContents);
1020     
1021     return JSValue::encode(jsUndefined());
1022 }
1023
1024 EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
1025 {
1026     jscExit(EXIT_SUCCESS);
1027
1028 #if COMPILER(MSVC)
1029     // Without this, Visual Studio will complain that this method does not return a value.
1030     return JSValue::encode(jsUndefined());
1031 #endif
1032 }
1033
1034 EncodedJSValue JSC_HOST_CALL functionFalse1(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1035 EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*) { return JSValue::encode(jsBoolean(false)); }
1036
1037 EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
1038 EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
1039
1040 EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec->argument(0)); }
1041
1042 EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
1043 {
1044     return JSValue::encode(jsNumber(42));
1045 }
1046
1047 EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
1048 {
1049     return JSValue::encode(Masquerader::create(exec->vm(), exec->lexicalGlobalObject()));
1050 }
1051
1052 EncodedJSValue JSC_HOST_CALL functionHasCustomProperties(ExecState* exec)
1053 {
1054     JSValue value = exec->argument(0);
1055     if (value.isObject())
1056         return JSValue::encode(jsBoolean(asObject(value)->hasCustomProperties()));
1057     return JSValue::encode(jsBoolean(false));
1058 }
1059
1060 EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
1061 {
1062     exec->vm().dumpHighFidelityProfilingTypes();
1063     return JSValue::encode(jsUndefined());
1064 }
1065
1066 // Use SEH for Release builds only to get rid of the crash report dialog
1067 // (luckily the same tests fail in Release and Debug builds so far). Need to
1068 // be in a separate main function because the jscmain function requires object
1069 // unwinding.
1070
1071 #if COMPILER(MSVC) && !defined(_DEBUG) && !OS(WINCE)
1072 #define TRY       __try {
1073 #define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
1074 #else
1075 #define TRY
1076 #define EXCEPT(x)
1077 #endif
1078
1079 int jscmain(int argc, char** argv);
1080
1081 static double s_desiredTimeout;
1082
1083 static NO_RETURN_DUE_TO_CRASH void timeoutThreadMain(void*)
1084 {
1085     auto timeout = std::chrono::microseconds(static_cast<std::chrono::microseconds::rep>(s_desiredTimeout * 1000000));
1086     std::this_thread::sleep_for(timeout);
1087     
1088     dataLog("Timed out after ", s_desiredTimeout, " seconds!\n");
1089     CRASH();
1090 }
1091
1092 int main(int argc, char** argv)
1093 {
1094 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
1095     // Enabled IEEE754 denormal support.
1096     fenv_t env;
1097     fegetenv( &env );
1098     env.__fpscr &= ~0x01000000u;
1099     fesetenv( &env );
1100 #endif
1101
1102 #if OS(WINDOWS)
1103 #if !OS(WINCE)
1104     // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
1105     // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
1106     // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
1107     ::SetErrorMode(0);
1108
1109 #if defined(_DEBUG)
1110     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
1111     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
1112     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
1113     _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
1114     _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
1115     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
1116 #endif
1117 #endif
1118
1119     timeBeginPeriod(1);
1120 #endif
1121
1122 #if PLATFORM(EFL)
1123     ecore_init();
1124 #endif
1125
1126     // Initialize JSC before getting VM.
1127 #if ENABLE(SAMPLING_REGIONS)
1128     WTF::initializeMainThread();
1129 #endif
1130     JSC::initializeThreading();
1131
1132 #if !OS(WINCE)
1133     if (char* timeoutString = getenv("JSC_timeout")) {
1134         if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
1135             dataLog(
1136                 "WARNING: timeout string is malformed, got ", timeoutString,
1137                 " but expected a number. Not using a timeout.\n");
1138         } else
1139             createThread(timeoutThreadMain, 0, "jsc Timeout Thread");
1140     }
1141 #endif
1142
1143 #if PLATFORM(IOS)
1144     Options::crashIfCantAllocateJITMemory() = true;
1145 #endif
1146
1147     // We can't use destructors in the following code because it uses Windows
1148     // Structured Exception Handling
1149     int res = 0;
1150     TRY
1151         res = jscmain(argc, argv);
1152     EXCEPT(res = 3)
1153     if (Options::logHeapStatisticsAtExit())
1154         HeapStatistics::reportSuccess();
1155
1156 #if PLATFORM(EFL)
1157     ecore_shutdown();
1158 #endif
1159
1160     jscExit(res);
1161 }
1162
1163 static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
1164 {
1165     const char* script;
1166     String fileName;
1167     Vector<char> scriptBuffer;
1168
1169     if (dump)
1170         JSC::Options::dumpGeneratedBytecodes() = true;
1171
1172     VM& vm = globalObject->vm();
1173
1174 #if ENABLE(SAMPLING_FLAGS)
1175     SamplingFlags::start();
1176 #endif
1177
1178     bool success = true;
1179     for (size_t i = 0; i < scripts.size(); i++) {
1180         if (scripts[i].isFile) {
1181             fileName = scripts[i].argument;
1182             if (!fillBufferWithContentsOfFile(fileName, scriptBuffer))
1183                 return false; // fail early so we can catch missing files
1184             script = scriptBuffer.data();
1185         } else {
1186             script = scripts[i].argument;
1187             fileName = "[Command Line]";
1188         }
1189
1190         vm.startSampling();
1191
1192         JSValue evaluationException;
1193         JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), &evaluationException);
1194         success = success && !evaluationException;
1195         if (dump && !evaluationException)
1196             printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1197         if (evaluationException) {
1198             printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1199             Identifier stackID(globalObject->globalExec(), "stack");
1200             JSValue stackValue = evaluationException.get(globalObject->globalExec(), stackID);
1201             if (!stackValue.isUndefinedOrNull())
1202                 printf("%s\n", stackValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1203         }
1204
1205         vm.stopSampling();
1206         globalObject->globalExec()->clearException();
1207     }
1208
1209 #if ENABLE(SAMPLING_FLAGS)
1210     SamplingFlags::stop();
1211 #endif
1212 #if ENABLE(SAMPLING_REGIONS)
1213     SamplingRegion::dump();
1214 #endif
1215     vm.dumpSampleData(globalObject->globalExec());
1216 #if ENABLE(SAMPLING_COUNTERS)
1217     AbstractSamplingCounter::dump();
1218 #endif
1219 #if ENABLE(REGEXP_TRACING)
1220     vm.dumpRegExpTrace();
1221 #endif
1222     return success;
1223 }
1224
1225 #define RUNNING_FROM_XCODE 0
1226
1227 static void runInteractive(GlobalObject* globalObject)
1228 {
1229     String interpreterName("Interpreter");
1230     
1231     bool shouldQuit = false;
1232     while (!shouldQuit) {
1233 #if HAVE(READLINE) && !RUNNING_FROM_XCODE
1234         ParserError error;
1235         String source;
1236         do {
1237             error = ParserError();
1238             char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
1239             shouldQuit = !line;
1240             if (!line)
1241                 break;
1242             source = source + line;
1243             source = source + '\n';
1244             checkSyntax(globalObject->vm(), makeSource(source, interpreterName), error);
1245             if (!line[0])
1246                 break;
1247             add_history(line);
1248         } while (error.m_syntaxErrorType == ParserError::SyntaxErrorRecoverable);
1249         
1250         if (error.m_type != ParserError::ErrorNone) {
1251             printf("%s:%d\n", error.m_message.utf8().data(), error.m_line);
1252             continue;
1253         }
1254         
1255         
1256         JSValue evaluationException;
1257         JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, interpreterName), JSValue(), &evaluationException);
1258 #else
1259         printf("%s", interactivePrompt);
1260         Vector<char, 256> line;
1261         int c;
1262         while ((c = getchar()) != EOF) {
1263             // FIXME: Should we also break on \r? 
1264             if (c == '\n')
1265                 break;
1266             line.append(c);
1267         }
1268         if (line.isEmpty())
1269             break;
1270         line.append('\0');
1271
1272         JSValue evaluationException;
1273         JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line.data(), interpreterName), JSValue(), &evaluationException);
1274 #endif
1275         if (evaluationException)
1276             printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1277         else
1278             printf("%s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
1279
1280         globalObject->globalExec()->clearException();
1281     }
1282     printf("\n");
1283 }
1284
1285 static NO_RETURN void printUsageStatement(bool help = false)
1286 {
1287     fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
1288     fprintf(stderr, "  -d         Dumps bytecode (debug builds only)\n");
1289     fprintf(stderr, "  -e         Evaluate argument as script code\n");
1290     fprintf(stderr, "  -f         Specifies a source file (deprecated)\n");
1291     fprintf(stderr, "  -h|--help  Prints this help message\n");
1292     fprintf(stderr, "  -i         Enables interactive mode (default if no files are specified)\n");
1293 #if HAVE(SIGNAL_H)
1294     fprintf(stderr, "  -s         Installs signal handlers that exit on a crash (Unix platforms only)\n");
1295 #endif
1296     fprintf(stderr, "  -p <file>  Outputs profiling data to a file\n");
1297     fprintf(stderr, "  -x         Output exit code before terminating\n");
1298     fprintf(stderr, "\n");
1299     fprintf(stderr, "  --options                  Dumps all JSC VM options and exits\n");
1300     fprintf(stderr, "  --dumpOptions              Dumps all JSC VM options before continuing\n");
1301     fprintf(stderr, "  --<jsc VM option>=<value>  Sets the specified JSC VM option\n");
1302     fprintf(stderr, "\n");
1303
1304     jscExit(help ? EXIT_SUCCESS : EXIT_FAILURE);
1305 }
1306
1307 void CommandLine::parseArguments(int argc, char** argv)
1308 {
1309     int i = 1;
1310     bool needToDumpOptions = false;
1311     bool needToExit = false;
1312
1313     for (; i < argc; ++i) {
1314         const char* arg = argv[i];
1315         if (!strcmp(arg, "-f")) {
1316             if (++i == argc)
1317                 printUsageStatement();
1318             m_scripts.append(Script(true, argv[i]));
1319             continue;
1320         }
1321         if (!strcmp(arg, "-e")) {
1322             if (++i == argc)
1323                 printUsageStatement();
1324             m_scripts.append(Script(false, argv[i]));
1325             continue;
1326         }
1327         if (!strcmp(arg, "-i")) {
1328             m_interactive = true;
1329             continue;
1330         }
1331         if (!strcmp(arg, "-d")) {
1332             m_dump = true;
1333             continue;
1334         }
1335         if (!strcmp(arg, "-p")) {
1336             if (++i == argc)
1337                 printUsageStatement();
1338             m_profile = true;
1339             m_profilerOutput = argv[i];
1340             continue;
1341         }
1342         if (!strcmp(arg, "-s")) {
1343 #if HAVE(SIGNAL_H)
1344             signal(SIGILL, _exit);
1345             signal(SIGFPE, _exit);
1346             signal(SIGBUS, _exit);
1347             signal(SIGSEGV, _exit);
1348 #endif
1349             continue;
1350         }
1351         if (!strcmp(arg, "-x")) {
1352             m_exitCode = true;
1353             continue;
1354         }
1355         if (!strcmp(arg, "--")) {
1356             ++i;
1357             break;
1358         }
1359         if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
1360             printUsageStatement(true);
1361
1362         if (!strcmp(arg, "--options")) {
1363             needToDumpOptions = true;
1364             needToExit = true;
1365             continue;
1366         }
1367         if (!strcmp(arg, "--dumpOptions")) {
1368             needToDumpOptions = true;
1369             continue;
1370         }
1371
1372         // See if the -- option is a JSC VM option.
1373         // NOTE: At this point, we know that the arg starts with "--". Skip it.
1374         if (JSC::Options::setOption(&arg[2])) {
1375             // The arg was recognized as a VM option and has been parsed.
1376             continue; // Just continue with the next arg. 
1377         }
1378
1379         // This arg is not recognized by the VM nor by jsc. Pass it on to the
1380         // script.
1381         m_scripts.append(Script(true, argv[i]));
1382     }
1383
1384     if (m_scripts.isEmpty())
1385         m_interactive = true;
1386
1387     for (; i < argc; ++i)
1388         m_arguments.append(argv[i]);
1389
1390     if (needToDumpOptions)
1391         JSC::Options::dumpAllOptions(stderr);
1392     if (needToExit)
1393         jscExit(EXIT_SUCCESS);
1394 }
1395
1396 int jscmain(int argc, char** argv)
1397 {
1398     // Note that the options parsing can affect VM creation, and thus
1399     // comes first.
1400     CommandLine options(argc, argv);
1401     VM* vm = VM::create(LargeHeap).leakRef();
1402     int result;
1403     {
1404         JSLockHolder locker(vm);
1405
1406         if (options.m_profile && !vm->m_perBytecodeProfiler)
1407             vm->m_perBytecodeProfiler = adoptPtr(new Profiler::Database(*vm));
1408     
1409         GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.m_arguments);
1410         bool success = runWithScripts(globalObject, options.m_scripts, options.m_dump);
1411         if (options.m_interactive && success)
1412             runInteractive(globalObject);
1413
1414         result = success ? 0 : 3;
1415
1416         if (options.m_exitCode)
1417             printf("jsc exiting %d\n", result);
1418     
1419         if (options.m_profile) {
1420             if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
1421                 fprintf(stderr, "could not save profiler output.\n");
1422         }
1423         
1424 #if ENABLE(JIT)
1425         if (Options::enableExceptionFuzz())
1426             printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
1427 #endif
1428     }
1429     
1430     return result;
1431 }
1432
1433 static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
1434 {
1435     FILE* f = fopen(fileName.utf8().data(), "r");
1436     if (!f) {
1437         fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
1438         return false;
1439     }
1440
1441     size_t bufferSize = 0;
1442     size_t bufferCapacity = 1024;
1443
1444     buffer.resize(bufferCapacity);
1445
1446     while (!feof(f) && !ferror(f)) {
1447         bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f);
1448         if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0'
1449             bufferCapacity *= 2;
1450             buffer.resize(bufferCapacity);
1451         }
1452     }
1453     fclose(f);
1454     buffer[bufferSize] = '\0';
1455
1456     if (buffer[0] == '#' && buffer[1] == '!')
1457         buffer[0] = buffer[1] = '/';
1458
1459     return true;
1460 }