2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012, 2013 Apple Inc. All rights reserved.
4 * Copyright (C) 2006 Bjoern Graf (bjoern.graf@gmail.com)
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.
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.
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.
25 #include "ArrayPrototype.h"
26 #include "ButterflyInlines.h"
27 #include "BytecodeGenerator.h"
28 #include "Completion.h"
29 #include "CopiedSpaceInlines.h"
30 #include "ExceptionHelpers.h"
31 #include "HeapStatistics.h"
32 #include "InitializeThreading.h"
33 #include "Interpreter.h"
35 #include "JSArrayBuffer.h"
36 #include "JSCInlines.h"
37 #include "JSFunction.h"
41 #include "ProfilerDatabase.h"
42 #include "SamplingTool.h"
43 #include "StackVisitor.h"
44 #include "StructureInlines.h"
45 #include "StructureRareDataInlines.h"
46 #include "TestRunnerUtils.h"
52 #include <wtf/CurrentTime.h>
53 #include <wtf/MainThread.h>
54 #include <wtf/StringPrintStream.h>
55 #include <wtf/text/StringBuilder.h>
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
65 #include <readline/history.h>
66 #include <readline/readline.h>
78 #if COMPILER(MSVC) && !OS(WINCE)
84 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
99 class ElementHandleOwner
;
104 class Element
: public JSNonFinalObject
{
106 Element(VM
& vm
, Structure
* structure
, Root
* root
)
107 : Base(vm
, structure
)
112 typedef JSNonFinalObject Base
;
113 static const bool needsDestruction
= false;
115 Root
* root() const { return m_root
; }
116 void setRoot(Root
* root
) { m_root
= root
; }
118 static Element
* create(VM
& vm
, JSGlobalObject
* globalObject
, Root
* root
)
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
);
126 void finishCreation(VM
&);
128 static ElementHandleOwner
* handleOwner();
130 static Structure
* createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue prototype
)
132 return Structure::create(vm
, globalObject
, prototype
, TypeInfo(ObjectType
, StructureFlags
), info());
141 class ElementHandleOwner
: public WeakHandleOwner
{
143 virtual bool isReachableFromOpaqueRoots(Handle
<JSC::Unknown
> handle
, void*, SlotVisitor
& visitor
)
145 Element
* element
= jsCast
<Element
*>(handle
.slot()->asCell());
146 return visitor
.containsOpaqueRoot(element
->root());
150 class Masquerader
: public JSNonFinalObject
{
152 Masquerader(VM
& vm
, Structure
* structure
)
153 : Base(vm
, structure
)
157 typedef JSNonFinalObject Base
;
159 static Masquerader
* create(VM
& vm
, JSGlobalObject
* globalObject
)
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
);
168 static Structure
* createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue prototype
)
170 return Structure::create(vm
, globalObject
, prototype
, TypeInfo(ObjectType
, StructureFlags
), info());
176 static const unsigned StructureFlags
= JSC::MasqueradesAsUndefined
| Base::StructureFlags
;
179 class Root
: public JSDestructibleObject
{
181 Root(VM
& vm
, Structure
* structure
)
182 : Base(vm
, structure
)
188 return m_element
.get();
191 void setElement(Element
* element
)
193 Weak
<Element
> newElement(element
, Element::handleOwner());
194 m_element
.swap(newElement
);
197 static Root
* create(VM
& vm
, JSGlobalObject
* globalObject
)
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
);
205 typedef JSDestructibleObject Base
;
208 static const bool needsDestruction
= true;
210 static Structure
* createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue prototype
)
212 return Structure::create(vm
, globalObject
, prototype
, TypeInfo(ObjectType
, StructureFlags
), info());
215 static void visitChildren(JSCell
* thisObject
, SlotVisitor
& visitor
)
217 Base::visitChildren(thisObject
, visitor
);
218 visitor
.addOpaqueRoot(thisObject
);
222 Weak
<Element
> m_element
;
225 class ImpureGetter
: public JSNonFinalObject
{
227 ImpureGetter(VM
& vm
, Structure
* structure
)
228 : Base(vm
, structure
)
233 typedef JSNonFinalObject Base
;
235 static Structure
* createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue prototype
)
237 return Structure::create(vm
, globalObject
, prototype
, TypeInfo(ObjectType
, StructureFlags
), info());
240 static ImpureGetter
* create(VM
& vm
, Structure
* structure
, JSObject
* delegate
)
242 ImpureGetter
* getter
= new (NotNull
, allocateCell
<ImpureGetter
>(vm
.heap
, sizeof(ImpureGetter
))) ImpureGetter(vm
, structure
);
243 getter
->finishCreation(vm
, delegate
);
247 void finishCreation(VM
& vm
, JSObject
* delegate
)
249 Base::finishCreation(vm
);
251 m_delegate
.set(vm
, this, delegate
);
254 static const unsigned StructureFlags
= JSC::HasImpureGetOwnPropertySlot
| JSC::OverridesGetOwnPropertySlot
| JSC::OverridesVisitChildren
| Base::StructureFlags
;
256 static bool getOwnPropertySlot(JSObject
* object
, ExecState
* exec
, PropertyName name
, PropertySlot
& slot
)
258 ImpureGetter
* thisObject
= jsCast
<ImpureGetter
*>(object
);
260 if (thisObject
->m_delegate
&& thisObject
->m_delegate
->getPropertySlot(exec
, name
, slot
))
263 return Base::getOwnPropertySlot(object
, exec
, name
, slot
);
266 static void visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
268 Base::visitChildren(cell
, visitor
);
269 ImpureGetter
* thisObject
= jsCast
<ImpureGetter
*>(cell
);
270 visitor
.append(&thisObject
->m_delegate
);
273 void setDelegate(VM
& vm
, JSObject
* delegate
)
275 m_delegate
.set(vm
, this, delegate
);
279 WriteBarrier
<JSObject
> m_delegate
;
282 class RuntimeArray
: public JSArray
{
284 typedef JSArray Base
;
286 static RuntimeArray
* create(ExecState
* exec
)
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
);
299 static void destroy(JSCell
* cell
)
301 static_cast<RuntimeArray
*>(cell
)->RuntimeArray::~RuntimeArray();
304 static const bool needsDestruction
= false;
306 static bool getOwnPropertySlot(JSObject
* object
, ExecState
* exec
, PropertyName propertyName
, PropertySlot
& slot
)
308 RuntimeArray
* thisObject
= jsCast
<RuntimeArray
*>(object
);
309 if (propertyName
== exec
->propertyNames().length
) {
310 slot
.setCacheableCustom(thisObject
, DontDelete
| ReadOnly
| DontEnum
, thisObject
->lengthGetter
);
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
]));
321 return JSObject::getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
);
324 static bool getOwnPropertySlotByIndex(JSObject
* object
, ExecState
* exec
, unsigned index
, PropertySlot
& slot
)
326 RuntimeArray
* thisObject
= jsCast
<RuntimeArray
*>(object
);
327 if (index
< thisObject
->getLength()) {
328 slot
.setValue(thisObject
, DontDelete
| DontEnum
, jsNumber(thisObject
->m_vector
[index
]));
332 return JSObject::getOwnPropertySlotByIndex(thisObject
, exec
, index
, slot
);
335 static NO_RETURN_DUE_TO_CRASH
void put(JSCell
*, ExecState
*, PropertyName
, JSValue
, PutPropertySlot
&)
337 RELEASE_ASSERT_NOT_REACHED();
340 static NO_RETURN_DUE_TO_CRASH
bool deleteProperty(JSCell
*, ExecState
*, PropertyName
)
342 RELEASE_ASSERT_NOT_REACHED();
348 unsigned getLength() const { return m_vector
.size(); }
352 static ArrayPrototype
* createPrototype(VM
&, JSGlobalObject
* globalObject
)
354 return globalObject
->arrayPrototype();
357 static Structure
* createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue prototype
)
359 return Structure::create(vm
, globalObject
, prototype
, TypeInfo(ObjectType
, StructureFlags
), info(), ArrayClass
);
363 void finishCreation(ExecState
* exec
)
365 Base::finishCreation(exec
->vm());
366 ASSERT(inherits(info()));
368 for (size_t i
= 0; i
< exec
->argumentCount(); i
++)
369 m_vector
.append(exec
->argument(i
).toInt32(exec
));
372 static const unsigned StructureFlags
= OverridesGetOwnPropertySlot
| InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero
| OverridesGetPropertyNames
| JSArray::StructureFlags
;
375 RuntimeArray(ExecState
* exec
, Structure
* structure
)
376 : JSArray(exec
->vm(), structure
, 0)
380 static EncodedJSValue
lengthGetter(ExecState
* exec
, JSObject
*, EncodedJSValue thisValue
, PropertyName
)
382 RuntimeArray
* thisObject
= jsDynamicCast
<RuntimeArray
*>(JSValue::decode(thisValue
));
384 return throwVMTypeError(exec
);
385 return JSValue::encode(jsNumber(thisObject
->getLength()));
388 Vector
<int> m_vector
;
391 const ClassInfo
Element::s_info
= { "Element", &Base::s_info
, 0, 0, CREATE_METHOD_TABLE(Element
) };
392 const ClassInfo
Masquerader::s_info
= { "Masquerader", &Base::s_info
, 0, 0, CREATE_METHOD_TABLE(Masquerader
) };
393 const ClassInfo
Root::s_info
= { "Root", &Base::s_info
, 0, 0, CREATE_METHOD_TABLE(Root
) };
394 const ClassInfo
ImpureGetter::s_info
= { "ImpureGetter", &Base::s_info
, 0, 0, CREATE_METHOD_TABLE(ImpureGetter
) };
395 const ClassInfo
RuntimeArray::s_info
= { "RuntimeArray", &Base::s_info
, 0, 0, CREATE_METHOD_TABLE(RuntimeArray
) };
397 ElementHandleOwner
* Element::handleOwner()
399 static ElementHandleOwner
* owner
= 0;
401 owner
= new ElementHandleOwner();
405 void Element::finishCreation(VM
& vm
)
407 Base::finishCreation(vm
);
408 m_root
->setElement(this);
413 static bool fillBufferWithContentsOfFile(const String
& fileName
, Vector
<char>& buffer
);
415 static EncodedJSValue JSC_HOST_CALL
functionCreateProxy(ExecState
*);
416 static EncodedJSValue JSC_HOST_CALL
functionCreateRuntimeArray(ExecState
*);
417 static EncodedJSValue JSC_HOST_CALL
functionCreateImpureGetter(ExecState
*);
418 static EncodedJSValue JSC_HOST_CALL
functionSetImpureGetterDelegate(ExecState
*);
420 static EncodedJSValue JSC_HOST_CALL
functionSetElementRoot(ExecState
*);
421 static EncodedJSValue JSC_HOST_CALL
functionCreateRoot(ExecState
*);
422 static EncodedJSValue JSC_HOST_CALL
functionCreateElement(ExecState
*);
423 static EncodedJSValue JSC_HOST_CALL
functionGetElement(ExecState
*);
424 static EncodedJSValue JSC_HOST_CALL
functionPrint(ExecState
*);
425 static EncodedJSValue JSC_HOST_CALL
functionDebug(ExecState
*);
426 static EncodedJSValue JSC_HOST_CALL
functionDescribe(ExecState
*);
427 static EncodedJSValue JSC_HOST_CALL
functionDescribeArray(ExecState
*);
428 static EncodedJSValue JSC_HOST_CALL
functionJSCStack(ExecState
*);
429 static EncodedJSValue JSC_HOST_CALL
functionGCAndSweep(ExecState
*);
430 static EncodedJSValue JSC_HOST_CALL
functionFullGC(ExecState
*);
431 static EncodedJSValue JSC_HOST_CALL
functionEdenGC(ExecState
*);
432 static EncodedJSValue JSC_HOST_CALL
functionDeleteAllCompiledCode(ExecState
*);
434 static EncodedJSValue JSC_HOST_CALL
functionReleaseExecutableMemory(ExecState
*);
435 static EncodedJSValue JSC_HOST_CALL
functionDumpCallFrame(ExecState
*);
437 static EncodedJSValue JSC_HOST_CALL
functionVersion(ExecState
*);
438 static EncodedJSValue JSC_HOST_CALL
functionRun(ExecState
*);
439 static EncodedJSValue JSC_HOST_CALL
functionLoad(ExecState
*);
440 static EncodedJSValue JSC_HOST_CALL
functionReadFile(ExecState
*);
441 static EncodedJSValue JSC_HOST_CALL
functionCheckSyntax(ExecState
*);
442 static EncodedJSValue JSC_HOST_CALL
functionReadline(ExecState
*);
443 static EncodedJSValue JSC_HOST_CALL
functionPreciseTime(ExecState
*);
444 static EncodedJSValue JSC_HOST_CALL
functionNeverInlineFunction(ExecState
*);
445 static EncodedJSValue JSC_HOST_CALL
functionOptimizeNextInvocation(ExecState
*);
446 static EncodedJSValue JSC_HOST_CALL
functionNumberOfDFGCompiles(ExecState
*);
447 static EncodedJSValue JSC_HOST_CALL
functionReoptimizationRetryCount(ExecState
*);
448 static EncodedJSValue JSC_HOST_CALL
functionTransferArrayBuffer(ExecState
*);
449 static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL
functionQuit(ExecState
*);
450 static EncodedJSValue JSC_HOST_CALL
functionFalse1(ExecState
*);
451 static EncodedJSValue JSC_HOST_CALL
functionFalse2(ExecState
*);
452 static EncodedJSValue JSC_HOST_CALL
functionUndefined1(ExecState
*);
453 static EncodedJSValue JSC_HOST_CALL
functionUndefined2(ExecState
*);
454 static EncodedJSValue JSC_HOST_CALL
functionEffectful42(ExecState
*);
455 static EncodedJSValue JSC_HOST_CALL
functionIdentity(ExecState
*);
456 static EncodedJSValue JSC_HOST_CALL
functionMakeMasquerader(ExecState
*);
458 #if ENABLE(SAMPLING_FLAGS)
459 static EncodedJSValue JSC_HOST_CALL
functionSetSamplingFlags(ExecState
*);
460 static EncodedJSValue JSC_HOST_CALL
functionClearSamplingFlags(ExecState
*);
467 Script(bool isFile
, char *argument
)
476 CommandLine(int argc
, char** argv
)
477 : m_interactive(false)
482 parseArguments(argc
, argv
);
488 Vector
<Script
> m_scripts
;
489 Vector
<String
> m_arguments
;
491 String m_profilerOutput
;
493 void parseArguments(int, char**);
496 static const char interactivePrompt
[] = ">>> ";
502 long getElapsedMS(); // call stop() first
509 void StopWatch::start()
511 m_startTime
= monotonicallyIncreasingTime();
514 void StopWatch::stop()
516 m_stopTime
= monotonicallyIncreasingTime();
519 long StopWatch::getElapsedMS()
521 return static_cast<long>((m_stopTime
- m_startTime
) * 1000);
524 class GlobalObject
: public JSGlobalObject
{
526 GlobalObject(VM
&, Structure
*);
529 typedef JSGlobalObject Base
;
531 static GlobalObject
* create(VM
& vm
, Structure
* structure
, const Vector
<String
>& arguments
)
533 GlobalObject
* object
= new (NotNull
, allocateCell
<GlobalObject
>(vm
.heap
)) GlobalObject(vm
, structure
);
534 object
->finishCreation(vm
, arguments
);
535 vm
.heap
.addFinalizer(object
, destroy
);
539 static const bool needsDestruction
= false;
542 static const GlobalObjectMethodTable s_globalObjectMethodTable
;
544 static Structure
* createStructure(VM
& vm
, JSValue prototype
)
546 return Structure::create(vm
, 0, prototype
, TypeInfo(GlobalObjectType
, StructureFlags
), info());
549 static bool javaScriptExperimentsEnabled(const JSGlobalObject
*) { return true; }
552 void finishCreation(VM
& vm
, const Vector
<String
>& arguments
)
554 Base::finishCreation(vm
);
556 addFunction(vm
, "debug", functionDebug
, 1);
557 addFunction(vm
, "describe", functionDescribe
, 1);
558 addFunction(vm
, "describeArray", functionDescribeArray
, 1);
559 addFunction(vm
, "print", functionPrint
, 1);
560 addFunction(vm
, "quit", functionQuit
, 0);
561 addFunction(vm
, "gc", functionGCAndSweep
, 0);
562 addFunction(vm
, "fullGC", functionFullGC
, 0);
563 addFunction(vm
, "edenGC", functionEdenGC
, 0);
564 addFunction(vm
, "deleteAllCompiledCode", functionDeleteAllCompiledCode
, 0);
566 addFunction(vm
, "dumpCallFrame", functionDumpCallFrame
, 0);
567 addFunction(vm
, "releaseExecutableMemory", functionReleaseExecutableMemory
, 0);
569 addFunction(vm
, "version", functionVersion
, 1);
570 addFunction(vm
, "run", functionRun
, 1);
571 addFunction(vm
, "load", functionLoad
, 1);
572 addFunction(vm
, "readFile", functionReadFile
, 1);
573 addFunction(vm
, "checkSyntax", functionCheckSyntax
, 1);
574 addFunction(vm
, "jscStack", functionJSCStack
, 1);
575 addFunction(vm
, "readline", functionReadline
, 0);
576 addFunction(vm
, "preciseTime", functionPreciseTime
, 0);
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);
583 #if ENABLE(SAMPLING_FLAGS)
584 addFunction(vm
, "setSamplingFlags", functionSetSamplingFlags
, 1);
585 addFunction(vm
, "clearSamplingFlags", functionClearSamplingFlags
, 1);
587 addConstructableFunction(vm
, "Root", functionCreateRoot
, 0);
588 addConstructableFunction(vm
, "Element", functionCreateElement
, 1);
589 addFunction(vm
, "getElement", functionGetElement
, 1);
590 addFunction(vm
, "setElementRoot", functionSetElementRoot
, 2);
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
);
598 addFunction(vm
, "effectful42", functionEffectful42
, 0);
599 addFunction(vm
, "makeMasquerader", functionMakeMasquerader
, 0);
601 addFunction(vm
, "createProxy", functionCreateProxy
, 1);
602 addFunction(vm
, "createRuntimeArray", functionCreateRuntimeArray
, 0);
604 addFunction(vm
, "createImpureGetter", functionCreateImpureGetter
, 1);
605 addFunction(vm
, "setImpureGetterDelegate", functionSetImpureGetterDelegate
, 2);
607 JSArray
* array
= constructEmptyArray(globalExec(), 0);
608 for (size_t i
= 0; i
< arguments
.size(); ++i
)
609 array
->putDirectIndex(globalExec(), i
, jsString(globalExec(), arguments
[i
]));
610 putDirect(vm
, Identifier(globalExec(), "arguments"), array
);
612 putDirect(vm
, Identifier(globalExec(), "console"), jsUndefined());
615 void addFunction(VM
& vm
, const char* name
, NativeFunction function
, unsigned arguments
)
617 Identifier
identifier(&vm
, name
);
618 putDirect(vm
, identifier
, JSFunction::create(vm
, this, arguments
, identifier
.string(), function
));
621 void addConstructableFunction(VM
& vm
, const char* name
, NativeFunction function
, unsigned arguments
)
623 Identifier
identifier(&vm
, name
);
624 putDirect(vm
, identifier
, JSFunction::create(vm
, this, arguments
, identifier
.string(), function
, NoIntrinsic
, function
));
628 const ClassInfo
GlobalObject::s_info
= { "global", &JSGlobalObject::s_info
, 0, ExecState::globalObjectTable
, CREATE_METHOD_TABLE(GlobalObject
) };
629 const GlobalObjectMethodTable
GlobalObject::s_globalObjectMethodTable
= { &allowsAccessFrom
, &supportsProfiling
, &supportsRichSourceInfo
, &shouldInterruptScript
, &javaScriptExperimentsEnabled
, 0, &shouldInterruptScriptBeforeTimeout
};
632 GlobalObject::GlobalObject(VM
& vm
, Structure
* structure
)
633 : JSGlobalObject(vm
, structure
, &s_globalObjectMethodTable
)
637 static inline String
stringFromUTF(const char* utf8
)
639 // Find the the first non-ascii character, or nul.
640 const char* pos
= utf8
;
643 size_t asciiLength
= pos
- utf8
;
645 // Fast case - string is all ascii.
647 return String(utf8
, asciiLength
);
649 // Slow case - contains non-ascii characters, use fromUTF8WithLatin1Fallback.
651 ASSERT(strlen(utf8
) == asciiLength
+ strlen(pos
));
652 return String::fromUTF8WithLatin1Fallback(utf8
, asciiLength
+ strlen(pos
));
655 static inline SourceCode
jscSource(const char* utf8
, const String
& filename
)
657 String str
= stringFromUTF(utf8
);
658 return makeSource(str
, filename
);
661 EncodedJSValue JSC_HOST_CALL
functionPrint(ExecState
* exec
)
663 for (unsigned i
= 0; i
< exec
->argumentCount(); ++i
) {
667 printf("%s", exec
->uncheckedArgument(i
).toString(exec
)->value(exec
).utf8().data());
672 return JSValue::encode(jsUndefined());
676 EncodedJSValue JSC_HOST_CALL
functionDumpCallFrame(ExecState
* exec
)
678 if (!exec
->callerFrame()->isVMEntrySentinel())
679 exec
->vm().interpreter
->dumpCallFrame(exec
->callerFrame());
680 return JSValue::encode(jsUndefined());
684 EncodedJSValue JSC_HOST_CALL
functionDebug(ExecState
* exec
)
686 fprintf(stderr
, "--> %s\n", exec
->argument(0).toString(exec
)->value(exec
).utf8().data());
687 return JSValue::encode(jsUndefined());
690 EncodedJSValue JSC_HOST_CALL
functionDescribe(ExecState
* exec
)
692 if (exec
->argumentCount() < 1)
693 return JSValue::encode(jsUndefined());
694 return JSValue::encode(jsString(exec
, toString(exec
->argument(0))));
697 EncodedJSValue JSC_HOST_CALL
functionDescribeArray(ExecState
* exec
)
699 if (exec
->argumentCount() < 1)
700 return JSValue::encode(jsUndefined());
701 JSObject
* object
= jsDynamicCast
<JSObject
*>(exec
->argument(0));
703 return JSValue::encode(jsString(exec
, "<not object>"));
704 return JSValue::encode(jsString(exec
, toString("<Public length: ", object
->getArrayLength(), "; vector length: ", object
->getVectorLength(), ">")));
707 class FunctionJSCStackFunctor
{
709 FunctionJSCStackFunctor(StringBuilder
& trace
)
714 StackVisitor::Status
operator()(StackVisitor
& visitor
)
716 m_trace
.append(String::format(" %zu %s\n", visitor
->index(), visitor
->toString().utf8().data()));
717 return StackVisitor::Continue
;
721 StringBuilder
& m_trace
;
724 EncodedJSValue JSC_HOST_CALL
functionJSCStack(ExecState
* exec
)
727 trace
.appendLiteral("--> Stack trace:\n");
729 FunctionJSCStackFunctor
functor(trace
);
730 exec
->iterate(functor
);
731 fprintf(stderr
, "%s", trace
.toString().utf8().data());
732 return JSValue::encode(jsUndefined());
735 EncodedJSValue JSC_HOST_CALL
functionCreateRoot(ExecState
* exec
)
737 JSLockHolder
lock(exec
);
738 return JSValue::encode(Root::create(exec
->vm(), exec
->lexicalGlobalObject()));
741 EncodedJSValue JSC_HOST_CALL
functionCreateElement(ExecState
* exec
)
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))));
748 EncodedJSValue JSC_HOST_CALL
functionGetElement(ExecState
* exec
)
750 JSLockHolder
lock(exec
);
751 Element
* result
= jsCast
<Root
*>(exec
->argument(0).asCell())->element();
752 return JSValue::encode(result
? result
: jsUndefined());
755 EncodedJSValue JSC_HOST_CALL
functionSetElementRoot(ExecState
* exec
)
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());
764 EncodedJSValue JSC_HOST_CALL
functionCreateProxy(ExecState
* exec
)
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
);
776 EncodedJSValue JSC_HOST_CALL
functionCreateRuntimeArray(ExecState
* exec
)
778 JSLockHolder
lock(exec
);
779 RuntimeArray
* array
= RuntimeArray::create(exec
);
780 return JSValue::encode(array
);
783 EncodedJSValue JSC_HOST_CALL
functionCreateImpureGetter(ExecState
* exec
)
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
);
795 EncodedJSValue JSC_HOST_CALL
functionSetImpureGetterDelegate(ExecState
* exec
)
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());
809 EncodedJSValue JSC_HOST_CALL
functionGCAndSweep(ExecState
* exec
)
811 JSLockHolder
lock(exec
);
812 exec
->heap()->collectAllGarbage();
813 return JSValue::encode(jsUndefined());
816 EncodedJSValue JSC_HOST_CALL
functionFullGC(ExecState
* exec
)
818 JSLockHolder
lock(exec
);
819 exec
->heap()->collect(FullCollection
);
820 return JSValue::encode(jsUndefined());
823 EncodedJSValue JSC_HOST_CALL
functionEdenGC(ExecState
* exec
)
825 JSLockHolder
lock(exec
);
826 exec
->heap()->collect(EdenCollection
);
827 return JSValue::encode(jsUndefined());
830 EncodedJSValue JSC_HOST_CALL
functionDeleteAllCompiledCode(ExecState
* exec
)
832 JSLockHolder
lock(exec
);
833 exec
->heap()->deleteAllCompiledCode();
834 return JSValue::encode(jsUndefined());
838 EncodedJSValue JSC_HOST_CALL
functionReleaseExecutableMemory(ExecState
* exec
)
840 JSLockHolder
lock(exec
);
841 exec
->vm().releaseExecutableMemory();
842 return JSValue::encode(jsUndefined());
846 EncodedJSValue JSC_HOST_CALL
functionVersion(ExecState
*)
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
850 return JSValue::encode(jsUndefined());
853 EncodedJSValue JSC_HOST_CALL
functionRun(ExecState
* exec
)
855 String fileName
= exec
->argument(0).toString(exec
)->value(exec
);
857 if (!fillBufferWithContentsOfFile(fileName
, script
))
858 return JSValue::encode(exec
->vm().throwException(exec
, createError(exec
, "Could not open file.")));
860 GlobalObject
* globalObject
= GlobalObject::create(exec
->vm(), GlobalObject::createStructure(exec
->vm(), jsNull()), Vector
<String
>());
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
);
871 evaluate(globalObject
->globalExec(), jscSource(script
.data(), fileName
), JSValue(), &exception
);
875 exec
->vm().throwException(globalObject
->globalExec(), exception
);
876 return JSValue::encode(jsUndefined());
879 return JSValue::encode(jsNumber(stopWatch
.getElapsedMS()));
882 EncodedJSValue JSC_HOST_CALL
functionLoad(ExecState
* exec
)
884 String fileName
= exec
->argument(0).toString(exec
)->value(exec
);
886 if (!fillBufferWithContentsOfFile(fileName
, script
))
887 return JSValue::encode(exec
->vm().throwException(exec
, createError(exec
, "Could not open file.")));
889 JSGlobalObject
* globalObject
= exec
->lexicalGlobalObject();
891 JSValue evaluationException
;
892 JSValue result
= evaluate(globalObject
->globalExec(), jscSource(script
.data(), fileName
), JSValue(), &evaluationException
);
893 if (evaluationException
)
894 exec
->vm().throwException(exec
, evaluationException
);
895 return JSValue::encode(result
);
898 EncodedJSValue JSC_HOST_CALL
functionReadFile(ExecState
* exec
)
900 String fileName
= exec
->argument(0).toString(exec
)->value(exec
);
902 if (!fillBufferWithContentsOfFile(fileName
, script
))
903 return JSValue::encode(exec
->vm().throwException(exec
, createError(exec
, "Could not open file.")));
905 return JSValue::encode(jsString(exec
, stringFromUTF(script
.data())));
908 EncodedJSValue JSC_HOST_CALL
functionCheckSyntax(ExecState
* exec
)
910 String fileName
= exec
->argument(0).toString(exec
)->value(exec
);
912 if (!fillBufferWithContentsOfFile(fileName
, script
))
913 return JSValue::encode(exec
->vm().throwException(exec
, createError(exec
, "Could not open file.")));
915 JSGlobalObject
* globalObject
= exec
->lexicalGlobalObject();
920 JSValue syntaxException
;
921 bool validSyntax
= checkSyntax(globalObject
->globalExec(), jscSource(script
.data(), fileName
), &syntaxException
);
925 exec
->vm().throwException(exec
, syntaxException
);
926 return JSValue::encode(jsNumber(stopWatch
.getElapsedMS()));
929 #if ENABLE(SAMPLING_FLAGS)
930 EncodedJSValue JSC_HOST_CALL
functionSetSamplingFlags(ExecState
* exec
)
932 for (unsigned i
= 0; i
< exec
->argumentCount(); ++i
) {
933 unsigned flag
= static_cast<unsigned>(exec
->uncheckedArgument(i
).toNumber(exec
));
934 if ((flag
>= 1) && (flag
<= 32))
935 SamplingFlags::setFlag(flag
);
937 return JSValue::encode(jsNull());
940 EncodedJSValue JSC_HOST_CALL
functionClearSamplingFlags(ExecState
* exec
)
942 for (unsigned i
= 0; i
< exec
->argumentCount(); ++i
) {
943 unsigned flag
= static_cast<unsigned>(exec
->uncheckedArgument(i
).toNumber(exec
));
944 if ((flag
>= 1) && (flag
<= 32))
945 SamplingFlags::clearFlag(flag
);
947 return JSValue::encode(jsNull());
951 EncodedJSValue JSC_HOST_CALL
functionReadline(ExecState
* exec
)
953 Vector
<char, 256> line
;
955 while ((c
= getchar()) != EOF
) {
956 // FIXME: Should we also break on \r?
962 return JSValue::encode(jsString(exec
, line
.data()));
965 EncodedJSValue JSC_HOST_CALL
functionPreciseTime(ExecState
*)
967 return JSValue::encode(jsNumber(currentTime()));
970 EncodedJSValue JSC_HOST_CALL
functionNeverInlineFunction(ExecState
* exec
)
972 return JSValue::encode(setNeverInline(exec
));
975 EncodedJSValue JSC_HOST_CALL
functionOptimizeNextInvocation(ExecState
* exec
)
977 return JSValue::encode(optimizeNextInvocation(exec
));
980 EncodedJSValue JSC_HOST_CALL
functionNumberOfDFGCompiles(ExecState
* exec
)
982 return JSValue::encode(numberOfDFGCompiles(exec
));
985 EncodedJSValue JSC_HOST_CALL
functionReoptimizationRetryCount(ExecState
* exec
)
987 if (exec
->argumentCount() < 1)
988 return JSValue::encode(jsUndefined());
990 CodeBlock
* block
= getSomeBaselineCodeBlockForFunction(exec
->argument(0));
992 return JSValue::encode(jsNumber(0));
994 return JSValue::encode(jsNumber(block
->reoptimizationRetryCounter()));
997 EncodedJSValue JSC_HOST_CALL
functionTransferArrayBuffer(ExecState
* exec
)
999 if (exec
->argumentCount() < 1)
1000 return JSValue::encode(exec
->vm().throwException(exec
, createError(exec
, "Not enough arguments")));
1002 JSArrayBuffer
* buffer
= jsDynamicCast
<JSArrayBuffer
*>(exec
->argument(0));
1004 return JSValue::encode(exec
->vm().throwException(exec
, createError(exec
, "Expected an array buffer")));
1006 ArrayBufferContents dummyContents
;
1007 buffer
->impl()->transfer(dummyContents
);
1009 return JSValue::encode(jsUndefined());
1012 EncodedJSValue JSC_HOST_CALL
functionQuit(ExecState
*)
1016 #if COMPILER(MSVC) && OS(WINCE)
1017 // Without this, Visual Studio will complain that this method does not return a value.
1018 return JSValue::encode(jsUndefined());
1022 EncodedJSValue JSC_HOST_CALL
functionFalse1(ExecState
*) { return JSValue::encode(jsBoolean(false)); }
1023 EncodedJSValue JSC_HOST_CALL
functionFalse2(ExecState
*) { return JSValue::encode(jsBoolean(false)); }
1025 EncodedJSValue JSC_HOST_CALL
functionUndefined1(ExecState
*) { return JSValue::encode(jsUndefined()); }
1026 EncodedJSValue JSC_HOST_CALL
functionUndefined2(ExecState
*) { return JSValue::encode(jsUndefined()); }
1028 EncodedJSValue JSC_HOST_CALL
functionIdentity(ExecState
* exec
) { return JSValue::encode(exec
->argument(0)); }
1030 EncodedJSValue JSC_HOST_CALL
functionEffectful42(ExecState
*)
1032 return JSValue::encode(jsNumber(42));
1035 EncodedJSValue JSC_HOST_CALL
functionMakeMasquerader(ExecState
* exec
)
1037 return JSValue::encode(Masquerader::create(exec
->vm(), exec
->lexicalGlobalObject()));
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
1045 #if COMPILER(MSVC) && !defined(_DEBUG) && !OS(WINCE)
1047 #define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
1053 int jscmain(int argc
, char** argv
);
1055 static double s_desiredTimeout
;
1057 static NO_RETURN_DUE_TO_CRASH
void timeoutThreadMain(void*)
1059 auto timeout
= std::chrono::microseconds(static_cast<std::chrono::microseconds::rep
>(s_desiredTimeout
* 1000000));
1060 std::this_thread::sleep_for(timeout
);
1062 dataLog("Timed out after ", s_desiredTimeout
, " seconds!\n");
1066 int main(int argc
, char** argv
)
1068 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
1069 // Enabled IEEE754 denormal support.
1072 env
.__fpscr
&= ~0x01000000u
;
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>.
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
);
1100 // Initialize JSC before getting VM.
1101 #if ENABLE(SAMPLING_REGIONS)
1102 WTF::initializeMainThread();
1104 JSC::initializeThreading();
1107 if (char* timeoutString
= getenv("JSC_timeout")) {
1108 if (sscanf(timeoutString
, "%lf", &s_desiredTimeout
) != 1) {
1110 "WARNING: timeout string is malformed, got ", timeoutString
,
1111 " but expected a number. Not using a timeout.\n");
1113 createThread(timeoutThreadMain
, 0, "jsc Timeout Thread");
1118 Options::crashIfCantAllocateJITMemory() = true;
1121 // We can't use destructors in the following code because it uses Windows
1122 // Structured Exception Handling
1125 res
= jscmain(argc
, argv
);
1127 if (Options::logHeapStatisticsAtExit())
1128 HeapStatistics::reportSuccess();
1137 static bool runWithScripts(GlobalObject
* globalObject
, const Vector
<Script
>& scripts
, bool dump
)
1141 Vector
<char> scriptBuffer
;
1144 JSC::Options::dumpGeneratedBytecodes() = true;
1146 VM
& vm
= globalObject
->vm();
1148 #if ENABLE(SAMPLING_FLAGS)
1149 SamplingFlags::start();
1152 bool success
= true;
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();
1160 script
= scripts
[i
].argument
;
1161 fileName
= "[Command Line]";
1166 JSValue evaluationException
;
1167 JSValue returnValue
= evaluate(globalObject
->globalExec(), jscSource(script
, fileName
), JSValue(), &evaluationException
);
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());
1180 globalObject
->globalExec()->clearException();
1183 #if ENABLE(SAMPLING_FLAGS)
1184 SamplingFlags::stop();
1186 #if ENABLE(SAMPLING_REGIONS)
1187 SamplingRegion::dump();
1189 vm
.dumpSampleData(globalObject
->globalExec());
1190 #if ENABLE(SAMPLING_COUNTERS)
1191 AbstractSamplingCounter::dump();
1193 #if ENABLE(REGEXP_TRACING)
1194 vm
.dumpRegExpTrace();
1199 #define RUNNING_FROM_XCODE 0
1201 static void runInteractive(GlobalObject
* globalObject
)
1203 String
interpreterName("Interpreter");
1205 bool shouldQuit
= false;
1206 while (!shouldQuit
) {
1207 #if HAVE(READLINE) && !RUNNING_FROM_XCODE
1211 error
= ParserError();
1212 char* line
= readline(source
.isEmpty() ? interactivePrompt
: "... ");
1216 source
= source
+ line
;
1217 source
= source
+ '\n';
1218 checkSyntax(globalObject
->vm(), makeSource(source
, interpreterName
), error
);
1222 } while (error
.m_syntaxErrorType
== ParserError::SyntaxErrorRecoverable
);
1224 if (error
.m_type
!= ParserError::ErrorNone
) {
1225 printf("%s:%d\n", error
.m_message
.utf8().data(), error
.m_line
);
1230 JSValue evaluationException
;
1231 JSValue returnValue
= evaluate(globalObject
->globalExec(), makeSource(source
, interpreterName
), JSValue(), &evaluationException
);
1233 printf("%s", interactivePrompt
);
1234 Vector
<char, 256> line
;
1236 while ((c
= getchar()) != EOF
) {
1237 // FIXME: Should we also break on \r?
1246 JSValue evaluationException
;
1247 JSValue returnValue
= evaluate(globalObject
->globalExec(), jscSource(line
.data(), interpreterName
), JSValue(), &evaluationException
);
1249 if (evaluationException
)
1250 printf("Exception: %s\n", evaluationException
.toString(globalObject
->globalExec())->value(globalObject
->globalExec()).utf8().data());
1252 printf("%s\n", returnValue
.toString(globalObject
->globalExec())->value(globalObject
->globalExec()).utf8().data());
1254 globalObject
->globalExec()->clearException();
1259 static NO_RETURN
void printUsageStatement(bool help
= false)
1261 fprintf(stderr
, "Usage: jsc [options] [files] [-- arguments]\n");
1262 fprintf(stderr
, " -d Dumps bytecode (debug builds only)\n");
1263 fprintf(stderr
, " -e Evaluate argument as script code\n");
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");
1268 fprintf(stderr
, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
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");
1278 exit(help
? EXIT_SUCCESS
: EXIT_FAILURE
);
1281 void CommandLine::parseArguments(int argc
, char** argv
)
1284 bool needToDumpOptions
= false;
1285 bool needToExit
= false;
1287 for (; i
< argc
; ++i
) {
1288 const char* arg
= argv
[i
];
1289 if (!strcmp(arg
, "-f")) {
1291 printUsageStatement();
1292 m_scripts
.append(Script(true, argv
[i
]));
1295 if (!strcmp(arg
, "-e")) {
1297 printUsageStatement();
1298 m_scripts
.append(Script(false, argv
[i
]));
1301 if (!strcmp(arg
, "-i")) {
1302 m_interactive
= true;
1305 if (!strcmp(arg
, "-d")) {
1309 if (!strcmp(arg
, "-p")) {
1311 printUsageStatement();
1313 m_profilerOutput
= argv
[i
];
1316 if (!strcmp(arg
, "-s")) {
1318 signal(SIGILL
, _exit
);
1319 signal(SIGFPE
, _exit
);
1320 signal(SIGBUS
, _exit
);
1321 signal(SIGSEGV
, _exit
);
1325 if (!strcmp(arg
, "-x")) {
1329 if (!strcmp(arg
, "--")) {
1333 if (!strcmp(arg
, "-h") || !strcmp(arg
, "--help"))
1334 printUsageStatement(true);
1336 if (!strcmp(arg
, "--options")) {
1337 needToDumpOptions
= true;
1341 if (!strcmp(arg
, "--dumpOptions")) {
1342 needToDumpOptions
= true;
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.
1353 // This arg is not recognized by the VM nor by jsc. Pass it on to the
1355 m_scripts
.append(Script(true, argv
[i
]));
1358 if (m_scripts
.isEmpty())
1359 m_interactive
= true;
1361 for (; i
< argc
; ++i
)
1362 m_arguments
.append(argv
[i
]);
1364 if (needToDumpOptions
)
1365 JSC::Options::dumpAllOptions(stderr
);
1370 int jscmain(int argc
, char** argv
)
1372 // Note that the options parsing can affect VM creation, and thus
1374 CommandLine
options(argc
, argv
);
1375 VM
* vm
= VM::create(LargeHeap
).leakRef();
1378 JSLockHolder
locker(vm
);
1380 if (options
.m_profile
&& !vm
->m_perBytecodeProfiler
)
1381 vm
->m_perBytecodeProfiler
= adoptPtr(new Profiler::Database(*vm
));
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
);
1388 result
= success
? 0 : 3;
1390 if (options
.m_exitCode
)
1391 printf("jsc exiting %d\n", result
);
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");
1399 if (Options::enableExceptionFuzz())
1400 printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks());
1407 static bool fillBufferWithContentsOfFile(const String
& fileName
, Vector
<char>& buffer
)
1409 FILE* f
= fopen(fileName
.utf8().data(), "r");
1411 fprintf(stderr
, "Could not open file: %s\n", fileName
.utf8().data());
1415 size_t bufferSize
= 0;
1416 size_t bufferCapacity
= 1024;
1418 buffer
.resize(bufferCapacity
);
1420 while (!feof(f
) && !ferror(f
)) {
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
);
1428 buffer
[bufferSize
] = '\0';
1430 if (buffer
[0] == '#' && buffer
[1] == '!')
1431 buffer
[0] = buffer
[1] = '/';