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