2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012 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.
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 "JSCTypedArrayStubs.h"
36 #include "JSFunction.h"
40 #include "Operations.h"
41 #include "SamplingTool.h"
42 #include "StructureRareDataInlines.h"
47 #include <wtf/CurrentTime.h>
48 #include <wtf/MainThread.h>
49 #include <wtf/StringPrintStream.h>
50 #include <wtf/text/StringBuilder.h>
57 // readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
58 // We #define it to something else to avoid this conflict.
59 #define Function ReadlineFunction
60 #include <readline/history.h>
61 #include <readline/readline.h>
73 #if COMPILER(MSVC) && !OS(WINCE)
80 #include <QCoreApplication>
84 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
89 #if PLATFORM(BLACKBERRY)
90 #include <BlackBerryPlatformLog.h>
100 static bool fillBufferWithContentsOfFile(const String
& fileName
, Vector
<char>& buffer
);
102 static EncodedJSValue JSC_HOST_CALL
functionPrint(ExecState
*);
103 static EncodedJSValue JSC_HOST_CALL
functionDebug(ExecState
*);
104 static EncodedJSValue JSC_HOST_CALL
functionDescribe(ExecState
*);
105 static EncodedJSValue JSC_HOST_CALL
functionJSCStack(ExecState
*);
106 static EncodedJSValue JSC_HOST_CALL
functionGC(ExecState
*);
108 static EncodedJSValue JSC_HOST_CALL
functionReleaseExecutableMemory(ExecState
*);
109 static EncodedJSValue JSC_HOST_CALL
functionDumpCallFrame(ExecState
*);
111 static EncodedJSValue JSC_HOST_CALL
functionVersion(ExecState
*);
112 static EncodedJSValue JSC_HOST_CALL
functionRun(ExecState
*);
113 static EncodedJSValue JSC_HOST_CALL
functionLoad(ExecState
*);
114 static EncodedJSValue JSC_HOST_CALL
functionCheckSyntax(ExecState
*);
115 static EncodedJSValue JSC_HOST_CALL
functionReadline(ExecState
*);
116 static EncodedJSValue JSC_HOST_CALL
functionPreciseTime(ExecState
*);
117 static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL
functionQuit(ExecState
*);
119 #if ENABLE(SAMPLING_FLAGS)
120 static EncodedJSValue JSC_HOST_CALL
functionSetSamplingFlags(ExecState
*);
121 static EncodedJSValue JSC_HOST_CALL
functionClearSamplingFlags(ExecState
*);
128 Script(bool isFile
, char *argument
)
137 CommandLine(int argc
, char** argv
)
138 : m_interactive(false)
143 parseArguments(argc
, argv
);
149 Vector
<Script
> m_scripts
;
150 Vector
<String
> m_arguments
;
152 String m_profilerOutput
;
154 void parseArguments(int, char**);
157 static const char interactivePrompt
[] = ">>> ";
163 long getElapsedMS(); // call stop() first
170 void StopWatch::start()
172 m_startTime
= currentTime();
175 void StopWatch::stop()
177 m_stopTime
= currentTime();
180 long StopWatch::getElapsedMS()
182 return static_cast<long>((m_stopTime
- m_startTime
) * 1000);
185 class GlobalObject
: public JSGlobalObject
{
187 GlobalObject(VM
&, Structure
*);
190 typedef JSGlobalObject Base
;
192 static GlobalObject
* create(VM
& vm
, Structure
* structure
, const Vector
<String
>& arguments
)
194 GlobalObject
* object
= new (NotNull
, allocateCell
<GlobalObject
>(vm
.heap
)) GlobalObject(vm
, structure
);
195 object
->finishCreation(vm
, arguments
);
196 vm
.heap
.addFinalizer(object
, destroy
);
197 object
->setGlobalThis(vm
, JSProxy::create(vm
, JSProxy::createStructure(vm
, object
, object
->prototype()), object
));
201 static const bool needsDestruction
= false;
203 static const ClassInfo s_info
;
204 static const GlobalObjectMethodTable s_globalObjectMethodTable
;
206 static Structure
* createStructure(VM
& vm
, JSValue prototype
)
208 return Structure::create(vm
, 0, prototype
, TypeInfo(GlobalObjectType
, StructureFlags
), &s_info
);
211 static bool javaScriptExperimentsEnabled(const JSGlobalObject
*) { return true; }
214 void finishCreation(VM
& vm
, const Vector
<String
>& arguments
)
216 Base::finishCreation(vm
);
218 addFunction(vm
, "debug", functionDebug
, 1);
219 addFunction(vm
, "describe", functionDescribe
, 1);
220 addFunction(vm
, "print", functionPrint
, 1);
221 addFunction(vm
, "quit", functionQuit
, 0);
222 addFunction(vm
, "gc", functionGC
, 0);
224 addFunction(vm
, "dumpCallFrame", functionDumpCallFrame
, 0);
225 addFunction(vm
, "releaseExecutableMemory", functionReleaseExecutableMemory
, 0);
227 addFunction(vm
, "version", functionVersion
, 1);
228 addFunction(vm
, "run", functionRun
, 1);
229 addFunction(vm
, "load", functionLoad
, 1);
230 addFunction(vm
, "checkSyntax", functionCheckSyntax
, 1);
231 addFunction(vm
, "jscStack", functionJSCStack
, 1);
232 addFunction(vm
, "readline", functionReadline
, 0);
233 addFunction(vm
, "preciseTime", functionPreciseTime
, 0);
234 #if ENABLE(SAMPLING_FLAGS)
235 addFunction(vm
, "setSamplingFlags", functionSetSamplingFlags
, 1);
236 addFunction(vm
, "clearSamplingFlags", functionClearSamplingFlags
, 1);
239 addConstructableFunction(vm
, "Uint8Array", constructJSUint8Array
, 1);
240 addConstructableFunction(vm
, "Uint8ClampedArray", constructJSUint8ClampedArray
, 1);
241 addConstructableFunction(vm
, "Uint16Array", constructJSUint16Array
, 1);
242 addConstructableFunction(vm
, "Uint32Array", constructJSUint32Array
, 1);
243 addConstructableFunction(vm
, "Int8Array", constructJSInt8Array
, 1);
244 addConstructableFunction(vm
, "Int16Array", constructJSInt16Array
, 1);
245 addConstructableFunction(vm
, "Int32Array", constructJSInt32Array
, 1);
246 addConstructableFunction(vm
, "Float32Array", constructJSFloat32Array
, 1);
247 addConstructableFunction(vm
, "Float64Array", constructJSFloat64Array
, 1);
249 JSArray
* array
= constructEmptyArray(globalExec(), 0);
250 for (size_t i
= 0; i
< arguments
.size(); ++i
)
251 array
->putDirectIndex(globalExec(), i
, jsString(globalExec(), arguments
[i
]));
252 putDirect(vm
, Identifier(globalExec(), "arguments"), array
);
255 void addFunction(VM
& vm
, const char* name
, NativeFunction function
, unsigned arguments
)
257 Identifier
identifier(globalExec(), name
);
258 putDirect(vm
, identifier
, JSFunction::create(globalExec(), this, arguments
, identifier
.string(), function
));
261 void addConstructableFunction(VM
& vm
, const char* name
, NativeFunction function
, unsigned arguments
)
263 Identifier
identifier(globalExec(), name
);
264 putDirect(vm
, identifier
, JSFunction::create(globalExec(), this, arguments
, identifier
.string(), function
, NoIntrinsic
, function
));
268 COMPILE_ASSERT(!IsInteger
<GlobalObject
>::value
, WTF_IsInteger_GlobalObject_false
);
270 const ClassInfo
GlobalObject::s_info
= { "global", &JSGlobalObject::s_info
, 0, ExecState::globalObjectTable
, CREATE_METHOD_TABLE(GlobalObject
) };
271 const GlobalObjectMethodTable
GlobalObject::s_globalObjectMethodTable
= { &allowsAccessFrom
, &supportsProfiling
, &supportsRichSourceInfo
, &shouldInterruptScript
, &javaScriptExperimentsEnabled
273 , &shouldInterruptScriptBeforeTimeout
278 GlobalObject::GlobalObject(VM
& vm
, Structure
* structure
)
279 : JSGlobalObject(vm
, structure
, &s_globalObjectMethodTable
)
283 static inline String
stringFromUTF(const char* utf8
)
285 // Find the the first non-ascii character, or nul.
286 const char* pos
= utf8
;
289 size_t asciiLength
= pos
- utf8
;
291 // Fast case - string is all ascii.
293 return String(utf8
, asciiLength
);
295 // Slow case - contains non-ascii characters, use fromUTF8WithLatin1Fallback.
297 ASSERT(strlen(utf8
) == asciiLength
+ strlen(pos
));
298 return String::fromUTF8WithLatin1Fallback(utf8
, asciiLength
+ strlen(pos
));
301 static inline SourceCode
jscSource(const char* utf8
, const String
& filename
)
303 String str
= stringFromUTF(utf8
);
304 return makeSource(str
, filename
);
307 EncodedJSValue JSC_HOST_CALL
functionPrint(ExecState
* exec
)
309 for (unsigned i
= 0; i
< exec
->argumentCount(); ++i
) {
313 printf("%s", exec
->argument(i
).toString(exec
)->value(exec
).utf8().data());
318 return JSValue::encode(jsUndefined());
322 EncodedJSValue JSC_HOST_CALL
functionDumpCallFrame(ExecState
* exec
)
324 if (!exec
->callerFrame()->hasHostCallFrameFlag())
325 exec
->vm().interpreter
->dumpCallFrame(exec
->callerFrame());
326 return JSValue::encode(jsUndefined());
330 EncodedJSValue JSC_HOST_CALL
functionDebug(ExecState
* exec
)
332 fprintf(stderr
, "--> %s\n", exec
->argument(0).toString(exec
)->value(exec
).utf8().data());
333 return JSValue::encode(jsUndefined());
336 EncodedJSValue JSC_HOST_CALL
functionDescribe(ExecState
* exec
)
338 fprintf(stderr
, "--> %s\n", toCString(exec
->argument(0)).data());
339 return JSValue::encode(jsUndefined());
342 EncodedJSValue JSC_HOST_CALL
functionJSCStack(ExecState
* exec
)
345 trace
.appendLiteral("--> Stack trace:\n");
347 Vector
<StackFrame
> stackTrace
;
348 Interpreter::getStackTrace(&exec
->vm(), stackTrace
);
351 for (Vector
<StackFrame
>::iterator iter
= stackTrace
.begin(); iter
< stackTrace
.end(); iter
++) {
352 StackFrame level
= *iter
;
353 trace
.append(String::format(" %i %s\n", i
, level
.toString(exec
).utf8().data()));
356 fprintf(stderr
, "%s", trace
.toString().utf8().data());
357 return JSValue::encode(jsUndefined());
360 EncodedJSValue JSC_HOST_CALL
functionGC(ExecState
* exec
)
362 JSLockHolder
lock(exec
);
363 exec
->heap()->collectAllGarbage();
364 return JSValue::encode(jsUndefined());
368 EncodedJSValue JSC_HOST_CALL
functionReleaseExecutableMemory(ExecState
* exec
)
370 JSLockHolder
lock(exec
);
371 exec
->vm().releaseExecutableMemory();
372 return JSValue::encode(jsUndefined());
376 EncodedJSValue JSC_HOST_CALL
functionVersion(ExecState
*)
378 // We need this function for compatibility with the Mozilla JS tests but for now
379 // we don't actually do any version-specific handling
380 return JSValue::encode(jsUndefined());
383 EncodedJSValue JSC_HOST_CALL
functionRun(ExecState
* exec
)
385 String fileName
= exec
->argument(0).toString(exec
)->value(exec
);
387 if (!fillBufferWithContentsOfFile(fileName
, script
))
388 return JSValue::encode(throwError(exec
, createError(exec
, "Could not open file.")));
390 GlobalObject
* globalObject
= GlobalObject::create(exec
->vm(), GlobalObject::createStructure(exec
->vm(), jsNull()), Vector
<String
>());
395 evaluate(globalObject
->globalExec(), jscSource(script
.data(), fileName
), JSValue(), &exception
);
399 throwError(globalObject
->globalExec(), exception
);
400 return JSValue::encode(jsUndefined());
403 return JSValue::encode(jsNumber(stopWatch
.getElapsedMS()));
406 EncodedJSValue JSC_HOST_CALL
functionLoad(ExecState
* exec
)
408 String fileName
= exec
->argument(0).toString(exec
)->value(exec
);
410 if (!fillBufferWithContentsOfFile(fileName
, script
))
411 return JSValue::encode(throwError(exec
, createError(exec
, "Could not open file.")));
413 JSGlobalObject
* globalObject
= exec
->lexicalGlobalObject();
415 JSValue evaluationException
;
416 JSValue result
= evaluate(globalObject
->globalExec(), jscSource(script
.data(), fileName
), JSValue(), &evaluationException
);
417 if (evaluationException
)
418 throwError(exec
, evaluationException
);
419 return JSValue::encode(result
);
422 EncodedJSValue JSC_HOST_CALL
functionCheckSyntax(ExecState
* exec
)
424 String fileName
= exec
->argument(0).toString(exec
)->value(exec
);
426 if (!fillBufferWithContentsOfFile(fileName
, script
))
427 return JSValue::encode(throwError(exec
, createError(exec
, "Could not open file.")));
429 JSGlobalObject
* globalObject
= exec
->lexicalGlobalObject();
434 JSValue syntaxException
;
435 bool validSyntax
= checkSyntax(globalObject
->globalExec(), jscSource(script
.data(), fileName
), &syntaxException
);
439 throwError(exec
, syntaxException
);
440 return JSValue::encode(jsNumber(stopWatch
.getElapsedMS()));
443 #if ENABLE(SAMPLING_FLAGS)
444 EncodedJSValue JSC_HOST_CALL
functionSetSamplingFlags(ExecState
* exec
)
446 for (unsigned i
= 0; i
< exec
->argumentCount(); ++i
) {
447 unsigned flag
= static_cast<unsigned>(exec
->argument(i
).toNumber(exec
));
448 if ((flag
>= 1) && (flag
<= 32))
449 SamplingFlags::setFlag(flag
);
451 return JSValue::encode(jsNull());
454 EncodedJSValue JSC_HOST_CALL
functionClearSamplingFlags(ExecState
* exec
)
456 for (unsigned i
= 0; i
< exec
->argumentCount(); ++i
) {
457 unsigned flag
= static_cast<unsigned>(exec
->argument(i
).toNumber(exec
));
458 if ((flag
>= 1) && (flag
<= 32))
459 SamplingFlags::clearFlag(flag
);
461 return JSValue::encode(jsNull());
465 EncodedJSValue JSC_HOST_CALL
functionReadline(ExecState
* exec
)
467 Vector
<char, 256> line
;
469 while ((c
= getchar()) != EOF
) {
470 // FIXME: Should we also break on \r?
476 return JSValue::encode(jsString(exec
, line
.data()));
479 EncodedJSValue JSC_HOST_CALL
functionPreciseTime(ExecState
*)
481 return JSValue::encode(jsNumber(currentTime()));
484 EncodedJSValue JSC_HOST_CALL
functionQuit(ExecState
*)
488 #if COMPILER(MSVC) && OS(WINCE)
489 // Without this, Visual Studio will complain that this method does not return a value.
490 return JSValue::encode(jsUndefined());
494 // Use SEH for Release builds only to get rid of the crash report dialog
495 // (luckily the same tests fail in Release and Debug builds so far). Need to
496 // be in a separate main function because the jscmain function requires object
499 #if COMPILER(MSVC) && !COMPILER(INTEL) && !defined(_DEBUG) && !OS(WINCE)
501 #define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
507 int jscmain(int argc
, char** argv
);
509 int main(int argc
, char** argv
)
511 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
512 // Enabled IEEE754 denormal support.
515 env
.__fpscr
&= ~0x01000000u
;
521 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
522 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
523 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
528 _CrtSetReportFile(_CRT_WARN
, _CRTDBG_FILE_STDERR
);
529 _CrtSetReportMode(_CRT_WARN
, _CRTDBG_MODE_FILE
);
530 _CrtSetReportFile(_CRT_ERROR
, _CRTDBG_FILE_STDERR
);
531 _CrtSetReportMode(_CRT_ERROR
, _CRTDBG_MODE_FILE
);
532 _CrtSetReportFile(_CRT_ASSERT
, _CRTDBG_FILE_STDERR
);
533 _CrtSetReportMode(_CRT_ASSERT
, _CRTDBG_MODE_FILE
);
539 #if PLATFORM(BLACKBERRY)
540 // Write all WTF logs to the system log
541 BlackBerry::Platform::setupApplicationLogging("jsc");
545 QCoreApplication
app(argc
, argv
);
552 // Initialize JSC before getting VM.
553 WTF::initializeMainThread();
554 JSC::initializeThreading();
557 Options::crashIfCantAllocateJITMemory() = true;
560 // We can't use destructors in the following code because it uses Windows
561 // Structured Exception Handling
564 res
= jscmain(argc
, argv
);
566 if (Options::logHeapStatisticsAtExit())
567 HeapStatistics::reportSuccess();
576 static bool runWithScripts(GlobalObject
* globalObject
, const Vector
<Script
>& scripts
, bool dump
)
580 Vector
<char> scriptBuffer
;
583 JSC::Options::dumpGeneratedBytecodes() = true;
585 VM
& vm
= globalObject
->vm();
587 #if ENABLE(SAMPLING_FLAGS)
588 SamplingFlags::start();
592 for (size_t i
= 0; i
< scripts
.size(); i
++) {
593 if (scripts
[i
].isFile
) {
594 fileName
= scripts
[i
].argument
;
595 if (!fillBufferWithContentsOfFile(fileName
, scriptBuffer
))
596 return false; // fail early so we can catch missing files
597 script
= scriptBuffer
.data();
599 script
= scripts
[i
].argument
;
600 fileName
= "[Command Line]";
605 JSValue evaluationException
;
606 JSValue returnValue
= evaluate(globalObject
->globalExec(), jscSource(script
, fileName
), JSValue(), &evaluationException
);
607 success
= success
&& !evaluationException
;
608 if (dump
&& !evaluationException
)
609 printf("End: %s\n", returnValue
.toString(globalObject
->globalExec())->value(globalObject
->globalExec()).utf8().data());
610 if (evaluationException
) {
611 printf("Exception: %s\n", evaluationException
.toString(globalObject
->globalExec())->value(globalObject
->globalExec()).utf8().data());
612 Identifier
stackID(globalObject
->globalExec(), "stack");
613 JSValue stackValue
= evaluationException
.get(globalObject
->globalExec(), stackID
);
614 if (!stackValue
.isUndefinedOrNull())
615 printf("%s\n", stackValue
.toString(globalObject
->globalExec())->value(globalObject
->globalExec()).utf8().data());
619 globalObject
->globalExec()->clearException();
622 #if ENABLE(SAMPLING_FLAGS)
623 SamplingFlags::stop();
625 #if ENABLE(SAMPLING_REGIONS)
626 SamplingRegion::dump();
628 vm
.dumpSampleData(globalObject
->globalExec());
629 #if ENABLE(SAMPLING_COUNTERS)
630 AbstractSamplingCounter::dump();
632 #if ENABLE(REGEXP_TRACING)
633 vm
.dumpRegExpTrace();
638 #define RUNNING_FROM_XCODE 0
640 static void runInteractive(GlobalObject
* globalObject
)
642 String
interpreterName("Interpreter");
644 bool shouldQuit
= false;
645 while (!shouldQuit
) {
646 #if HAVE(READLINE) && !RUNNING_FROM_XCODE
650 error
= ParserError();
651 char* line
= readline(source
.isEmpty() ? interactivePrompt
: "... ");
655 source
= source
+ line
;
656 source
= source
+ '\n';
657 checkSyntax(globalObject
->vm(), makeSource(source
, interpreterName
), error
);
661 } while (error
.m_syntaxErrorType
== ParserError::SyntaxErrorRecoverable
);
663 if (error
.m_type
!= ParserError::ErrorNone
) {
664 printf("%s:%d\n", error
.m_message
.utf8().data(), error
.m_line
);
669 JSValue evaluationException
;
670 JSValue returnValue
= evaluate(globalObject
->globalExec(), makeSource(source
, interpreterName
), JSValue(), &evaluationException
);
672 printf("%s", interactivePrompt
);
673 Vector
<char, 256> line
;
675 while ((c
= getchar()) != EOF
) {
676 // FIXME: Should we also break on \r?
685 JSValue evaluationException
;
686 JSValue returnValue
= evaluate(globalObject
->globalExec(), jscSource(line
.data(), interpreterName
), JSValue(), &evaluationException
);
688 if (evaluationException
)
689 printf("Exception: %s\n", evaluationException
.toString(globalObject
->globalExec())->value(globalObject
->globalExec()).utf8().data());
691 printf("%s\n", returnValue
.toString(globalObject
->globalExec())->value(globalObject
->globalExec()).utf8().data());
693 globalObject
->globalExec()->clearException();
698 static NO_RETURN
void printUsageStatement(bool help
= false)
700 fprintf(stderr
, "Usage: jsc [options] [files] [-- arguments]\n");
701 fprintf(stderr
, " -d Dumps bytecode (debug builds only)\n");
702 fprintf(stderr
, " -e Evaluate argument as script code\n");
703 fprintf(stderr
, " -f Specifies a source file (deprecated)\n");
704 fprintf(stderr
, " -h|--help Prints this help message\n");
705 fprintf(stderr
, " -i Enables interactive mode (default if no files are specified)\n");
707 fprintf(stderr
, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
709 fprintf(stderr
, " -p <file> Outputs profiling data to a file\n");
710 fprintf(stderr
, " -x Output exit code before terminating\n");
711 fprintf(stderr
, "\n");
712 fprintf(stderr
, " --options Dumps all JSC VM options and exits\n");
713 fprintf(stderr
, " --dumpOptions Dumps all JSC VM options before continuing\n");
714 fprintf(stderr
, " --<jsc VM option>=<value> Sets the specified JSC VM option\n");
715 fprintf(stderr
, "\n");
717 exit(help
? EXIT_SUCCESS
: EXIT_FAILURE
);
720 void CommandLine::parseArguments(int argc
, char** argv
)
723 bool needToDumpOptions
= false;
724 bool needToExit
= false;
726 for (; i
< argc
; ++i
) {
727 const char* arg
= argv
[i
];
728 if (!strcmp(arg
, "-f")) {
730 printUsageStatement();
731 m_scripts
.append(Script(true, argv
[i
]));
734 if (!strcmp(arg
, "-e")) {
736 printUsageStatement();
737 m_scripts
.append(Script(false, argv
[i
]));
740 if (!strcmp(arg
, "-i")) {
741 m_interactive
= true;
744 if (!strcmp(arg
, "-d")) {
748 if (!strcmp(arg
, "-p")) {
750 printUsageStatement();
752 m_profilerOutput
= argv
[i
];
755 if (!strcmp(arg
, "-s")) {
757 signal(SIGILL
, _exit
);
758 signal(SIGFPE
, _exit
);
759 signal(SIGBUS
, _exit
);
760 signal(SIGSEGV
, _exit
);
764 if (!strcmp(arg
, "-x")) {
768 if (!strcmp(arg
, "--")) {
772 if (!strcmp(arg
, "-h") || !strcmp(arg
, "--help"))
773 printUsageStatement(true);
775 if (!strcmp(arg
, "--options")) {
776 needToDumpOptions
= true;
780 if (!strcmp(arg
, "--dumpOptions")) {
781 needToDumpOptions
= true;
785 // See if the -- option is a JSC VM option.
786 // NOTE: At this point, we know that the arg starts with "--". Skip it.
787 if (JSC::Options::setOption(&arg
[2])) {
788 // The arg was recognized as a VM option and has been parsed.
789 continue; // Just continue with the next arg.
792 // This arg is not recognized by the VM nor by jsc. Pass it on to the
794 m_scripts
.append(Script(true, argv
[i
]));
797 if (m_scripts
.isEmpty())
798 m_interactive
= true;
800 for (; i
< argc
; ++i
)
801 m_arguments
.append(argv
[i
]);
803 if (needToDumpOptions
)
804 JSC::Options::dumpAllOptions(stderr
);
809 int jscmain(int argc
, char** argv
)
811 // Note that the options parsing can affect VM creation, and thus
813 CommandLine
options(argc
, argv
);
814 VM
* vm
= VM::create(LargeHeap
).leakRef();
815 APIEntryShim
shim(vm
);
818 if (options
.m_profile
&& !vm
->m_perBytecodeProfiler
)
819 vm
->m_perBytecodeProfiler
= adoptPtr(new Profiler::Database(*vm
));
821 GlobalObject
* globalObject
= GlobalObject::create(*vm
, GlobalObject::createStructure(*vm
, jsNull()), options
.m_arguments
);
822 bool success
= runWithScripts(globalObject
, options
.m_scripts
, options
.m_dump
);
823 if (options
.m_interactive
&& success
)
824 runInteractive(globalObject
);
826 result
= success
? 0 : 3;
828 if (options
.m_exitCode
)
829 printf("jsc exiting %d\n", result
);
831 if (options
.m_profile
) {
832 if (!vm
->m_perBytecodeProfiler
->save(options
.m_profilerOutput
.utf8().data()))
833 fprintf(stderr
, "could not save profiler output.\n");
839 static bool fillBufferWithContentsOfFile(const String
& fileName
, Vector
<char>& buffer
)
841 FILE* f
= fopen(fileName
.utf8().data(), "r");
843 fprintf(stderr
, "Could not open file: %s\n", fileName
.utf8().data());
847 size_t bufferSize
= 0;
848 size_t bufferCapacity
= 1024;
850 buffer
.resize(bufferCapacity
);
852 while (!feof(f
) && !ferror(f
)) {
853 bufferSize
+= fread(buffer
.data() + bufferSize
, 1, bufferCapacity
- bufferSize
, f
);
854 if (bufferSize
== bufferCapacity
) { // guarantees space for trailing '\0'
856 buffer
.resize(bufferCapacity
);
860 buffer
[bufferSize
] = '\0';
862 if (buffer
[0] == '#' && buffer
[1] == '!')
863 buffer
[0] = buffer
[1] = '/';