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