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