123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876 |
- /*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Bjoern Graf (bjoern.graf@gmail.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
- #include "config.h"
- #include "APIShims.h"
- #include "ButterflyInlines.h"
- #include "BytecodeGenerator.h"
- #include "Completion.h"
- #include "CopiedSpaceInlines.h"
- #include "ExceptionHelpers.h"
- #include "HeapStatistics.h"
- #include "InitializeThreading.h"
- #include "Interpreter.h"
- #include "JSArray.h"
- #include "JSCTypedArrayStubs.h"
- #include "JSFunction.h"
- #include "JSLock.h"
- #include "JSProxy.h"
- #include "JSString.h"
- #include "Operations.h"
- #include "SamplingTool.h"
- #include "StructureRareDataInlines.h"
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <wtf/CurrentTime.h>
- #include <wtf/MainThread.h>
- #include <wtf/StringPrintStream.h>
- #include <wtf/text/StringBuilder.h>
- #if !OS(WINDOWS)
- #include <unistd.h>
- #endif
- #if HAVE(READLINE)
- // readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
- // We #define it to something else to avoid this conflict.
- #define Function ReadlineFunction
- #include <readline/history.h>
- #include <readline/readline.h>
- #undef Function
- #endif
- #if HAVE(SYS_TIME_H)
- #include <sys/time.h>
- #endif
- #if HAVE(SIGNAL_H)
- #include <signal.h>
- #endif
- #if COMPILER(MSVC) && !OS(WINCE)
- #include <crtdbg.h>
- #include <mmsystem.h>
- #include <windows.h>
- #endif
- #if PLATFORM(QT)
- #include <QCoreApplication>
- #include <QDateTime>
- #endif
- #if PLATFORM(IOS)
- #include <fenv.h>
- #include <arm/arch.h>
- #endif
- #if PLATFORM(BLACKBERRY)
- #include <BlackBerryPlatformLog.h>
- #endif
- #if PLATFORM(EFL)
- #include <Ecore.h>
- #endif
- using namespace JSC;
- using namespace WTF;
- static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
- static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
- static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
- static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
- static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
- static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
- #ifndef NDEBUG
- static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
- static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
- #endif
- static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
- static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
- static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
- static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
- static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
- static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
- static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
- #if ENABLE(SAMPLING_FLAGS)
- static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
- static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
- #endif
- struct Script {
- bool isFile;
- char* argument;
- Script(bool isFile, char *argument)
- : isFile(isFile)
- , argument(argument)
- {
- }
- };
- class CommandLine {
- public:
- CommandLine(int argc, char** argv)
- : m_interactive(false)
- , m_dump(false)
- , m_exitCode(false)
- , m_profile(false)
- {
- parseArguments(argc, argv);
- }
- bool m_interactive;
- bool m_dump;
- bool m_exitCode;
- Vector<Script> m_scripts;
- Vector<String> m_arguments;
- bool m_profile;
- String m_profilerOutput;
- void parseArguments(int, char**);
- };
- static const char interactivePrompt[] = ">>> ";
- class StopWatch {
- public:
- void start();
- void stop();
- long getElapsedMS(); // call stop() first
- private:
- double m_startTime;
- double m_stopTime;
- };
- void StopWatch::start()
- {
- m_startTime = currentTime();
- }
- void StopWatch::stop()
- {
- m_stopTime = currentTime();
- }
- long StopWatch::getElapsedMS()
- {
- return static_cast<long>((m_stopTime - m_startTime) * 1000);
- }
- class GlobalObject : public JSGlobalObject {
- private:
- GlobalObject(VM&, Structure*);
- public:
- typedef JSGlobalObject Base;
- static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments)
- {
- GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(vm.heap)) GlobalObject(vm, structure);
- object->finishCreation(vm, arguments);
- vm.heap.addFinalizer(object, destroy);
- object->setGlobalThis(vm, JSProxy::create(vm, JSProxy::createStructure(vm, object, object->prototype()), object));
- return object;
- }
- static const bool needsDestruction = false;
- static const ClassInfo s_info;
- static const GlobalObjectMethodTable s_globalObjectMethodTable;
- static Structure* createStructure(VM& vm, JSValue prototype)
- {
- return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
- }
- static bool javaScriptExperimentsEnabled(const JSGlobalObject*) { return true; }
- protected:
- void finishCreation(VM& vm, const Vector<String>& arguments)
- {
- Base::finishCreation(vm);
-
- addFunction(vm, "debug", functionDebug, 1);
- addFunction(vm, "describe", functionDescribe, 1);
- addFunction(vm, "print", functionPrint, 1);
- addFunction(vm, "quit", functionQuit, 0);
- addFunction(vm, "gc", functionGC, 0);
- #ifndef NDEBUG
- addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0);
- addFunction(vm, "releaseExecutableMemory", functionReleaseExecutableMemory, 0);
- #endif
- addFunction(vm, "version", functionVersion, 1);
- addFunction(vm, "run", functionRun, 1);
- addFunction(vm, "load", functionLoad, 1);
- addFunction(vm, "checkSyntax", functionCheckSyntax, 1);
- addFunction(vm, "jscStack", functionJSCStack, 1);
- addFunction(vm, "readline", functionReadline, 0);
- addFunction(vm, "preciseTime", functionPreciseTime, 0);
- #if ENABLE(SAMPLING_FLAGS)
- addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1);
- addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1);
- #endif
-
- addConstructableFunction(vm, "Uint8Array", constructJSUint8Array, 1);
- addConstructableFunction(vm, "Uint8ClampedArray", constructJSUint8ClampedArray, 1);
- addConstructableFunction(vm, "Uint16Array", constructJSUint16Array, 1);
- addConstructableFunction(vm, "Uint32Array", constructJSUint32Array, 1);
- addConstructableFunction(vm, "Int8Array", constructJSInt8Array, 1);
- addConstructableFunction(vm, "Int16Array", constructJSInt16Array, 1);
- addConstructableFunction(vm, "Int32Array", constructJSInt32Array, 1);
- addConstructableFunction(vm, "Float32Array", constructJSFloat32Array, 1);
- addConstructableFunction(vm, "Float64Array", constructJSFloat64Array, 1);
- JSArray* array = constructEmptyArray(globalExec(), 0);
- for (size_t i = 0; i < arguments.size(); ++i)
- array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
- putDirect(vm, Identifier(globalExec(), "arguments"), array);
- }
- void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
- {
- Identifier identifier(globalExec(), name);
- putDirect(vm, identifier, JSFunction::create(globalExec(), this, arguments, identifier.string(), function));
- }
-
- void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments)
- {
- Identifier identifier(globalExec(), name);
- putDirect(vm, identifier, JSFunction::create(globalExec(), this, arguments, identifier.string(), function, NoIntrinsic, function));
- }
- };
- COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
- const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
- const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled };
- GlobalObject::GlobalObject(VM& vm, Structure* structure)
- : JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
- {
- }
- static inline String stringFromUTF(const char* utf8)
- {
- // Find the the first non-ascii character, or nul.
- const char* pos = utf8;
- while (*pos > 0)
- pos++;
- size_t asciiLength = pos - utf8;
-
- // Fast case - string is all ascii.
- if (!*pos)
- return String(utf8, asciiLength);
-
- // Slow case - contains non-ascii characters, use fromUTF8WithLatin1Fallback.
- ASSERT(*pos < 0);
- ASSERT(strlen(utf8) == asciiLength + strlen(pos));
- return String::fromUTF8WithLatin1Fallback(utf8, asciiLength + strlen(pos));
- }
- static inline SourceCode jscSource(const char* utf8, const String& filename)
- {
- String str = stringFromUTF(utf8);
- return makeSource(str, filename);
- }
- EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
- {
- char const * newline = "\n";
- char const * space = " ";
- for (unsigned i = 0; i < exec->argumentCount(); ++i) {
- if (i)
- printf("%s", space);
- printf("%s", exec->argument(i).toString(exec)->value(exec).utf8().data());
- }
- printf("%s", newline);
- fflush(stdout);
- return JSValue::encode(jsUndefined());
- }
- #ifndef NDEBUG
- EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
- {
- if (!exec->callerFrame()->hasHostCallFrameFlag())
- exec->vm().interpreter->dumpCallFrame(exec->callerFrame());
- return JSValue::encode(jsUndefined());
- }
- #endif
- EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
- {
- fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->value(exec).utf8().data());
- return JSValue::encode(jsUndefined());
- }
- EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
- {
- fprintf(stderr, "--> %s\n", toCString(exec->argument(0)).data());
- return JSValue::encode(jsUndefined());
- }
- EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
- {
- StringBuilder trace;
- trace.appendLiteral("--> Stack trace:\n");
- Vector<StackFrame> stackTrace;
- Interpreter::getStackTrace(&exec->vm(), stackTrace);
- int i = 0;
- for (Vector<StackFrame>::iterator iter = stackTrace.begin(); iter < stackTrace.end(); iter++) {
- StackFrame level = *iter;
- trace.append(String::format(" %i %s\n", i, level.toString(exec).utf8().data()));
- i++;
- }
- fprintf(stderr, "%s", trace.toString().utf8().data());
- return JSValue::encode(jsUndefined());
- }
- EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
- {
- JSLockHolder lock(exec);
- exec->heap()->collectAllGarbage();
- return JSValue::encode(jsUndefined());
- }
- #ifndef NDEBUG
- EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
- {
- JSLockHolder lock(exec);
- exec->vm().releaseExecutableMemory();
- return JSValue::encode(jsUndefined());
- }
- #endif
- EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
- {
- // We need this function for compatibility with the Mozilla JS tests but for now
- // we don't actually do any version-specific handling
- return JSValue::encode(jsUndefined());
- }
- EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
- {
- String fileName = exec->argument(0).toString(exec)->value(exec);
- Vector<char> script;
- if (!fillBufferWithContentsOfFile(fileName, script))
- return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
- GlobalObject* globalObject = GlobalObject::create(exec->vm(), GlobalObject::createStructure(exec->vm(), jsNull()), Vector<String>());
- JSValue exception;
- StopWatch stopWatch;
- stopWatch.start();
- evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), &exception);
- stopWatch.stop();
- if (!!exception) {
- throwError(globalObject->globalExec(), exception);
- return JSValue::encode(jsUndefined());
- }
-
- return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
- }
- EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
- {
- String fileName = exec->argument(0).toString(exec)->value(exec);
- Vector<char> script;
- if (!fillBufferWithContentsOfFile(fileName, script))
- return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
- JSGlobalObject* globalObject = exec->lexicalGlobalObject();
-
- JSValue evaluationException;
- JSValue result = evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), &evaluationException);
- if (evaluationException)
- throwError(exec, evaluationException);
- return JSValue::encode(result);
- }
- EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
- {
- String fileName = exec->argument(0).toString(exec)->value(exec);
- Vector<char> script;
- if (!fillBufferWithContentsOfFile(fileName, script))
- return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
- JSGlobalObject* globalObject = exec->lexicalGlobalObject();
- StopWatch stopWatch;
- stopWatch.start();
- JSValue syntaxException;
- bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script.data(), fileName), &syntaxException);
- stopWatch.stop();
- if (!validSyntax)
- throwError(exec, syntaxException);
- return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
- }
- #if ENABLE(SAMPLING_FLAGS)
- EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
- {
- for (unsigned i = 0; i < exec->argumentCount(); ++i) {
- unsigned flag = static_cast<unsigned>(exec->argument(i).toNumber(exec));
- if ((flag >= 1) && (flag <= 32))
- SamplingFlags::setFlag(flag);
- }
- return JSValue::encode(jsNull());
- }
- EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
- {
- for (unsigned i = 0; i < exec->argumentCount(); ++i) {
- unsigned flag = static_cast<unsigned>(exec->argument(i).toNumber(exec));
- if ((flag >= 1) && (flag <= 32))
- SamplingFlags::clearFlag(flag);
- }
- return JSValue::encode(jsNull());
- }
- #endif
- EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
- {
- Vector<char, 256> line;
- int c;
- while ((c = getchar()) != EOF) {
- // FIXME: Should we also break on \r?
- if (c == '\n')
- break;
- line.append(c);
- }
- line.append('\0');
- return JSValue::encode(jsString(exec, line.data()));
- }
- EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
- {
- return JSValue::encode(jsNumber(currentTime()));
- }
- EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
- {
- exit(EXIT_SUCCESS);
- #if COMPILER(MSVC) && OS(WINCE)
- // Without this, Visual Studio will complain that this method does not return a value.
- return JSValue::encode(jsUndefined());
- #endif
- }
- // Use SEH for Release builds only to get rid of the crash report dialog
- // (luckily the same tests fail in Release and Debug builds so far). Need to
- // be in a separate main function because the jscmain function requires object
- // unwinding.
- #if COMPILER(MSVC) && !COMPILER(INTEL) && !defined(_DEBUG) && !OS(WINCE)
- #define TRY __try {
- #define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
- #else
- #define TRY
- #define EXCEPT(x)
- #endif
- int jscmain(int argc, char** argv);
- int main(int argc, char** argv)
- {
- #if PLATFORM(IOS)
- // Enabled IEEE754 denormal support.
- fenv_t env;
- fegetenv( &env );
- env.__fpscr &= ~0x01000000u;
- fesetenv( &env );
- #endif
- #if OS(WINDOWS)
- #if !OS(WINCE)
- // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
- // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
- // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
- ::SetErrorMode(0);
- #endif
- #if defined(_DEBUG)
- _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
- #endif
- timeBeginPeriod(1);
- #endif
- #if PLATFORM(BLACKBERRY)
- // Write all WTF logs to the system log
- BlackBerry::Platform::setupApplicationLogging("jsc");
- #endif
- #if PLATFORM(QT)
- QCoreApplication app(argc, argv);
- #endif
- #if PLATFORM(EFL)
- ecore_init();
- #endif
- // Initialize JSC before getting VM.
- #if ENABLE(SAMPLING_REGIONS)
- WTF::initializeMainThread();
- #endif
- JSC::initializeThreading();
- // We can't use destructors in the following code because it uses Windows
- // Structured Exception Handling
- int res = 0;
- TRY
- res = jscmain(argc, argv);
- EXCEPT(res = 3)
- if (Options::logHeapStatisticsAtExit())
- HeapStatistics::reportSuccess();
- #if PLATFORM(EFL)
- ecore_shutdown();
- #endif
- return res;
- }
- static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
- {
- const char* script;
- String fileName;
- Vector<char> scriptBuffer;
- if (dump)
- JSC::Options::dumpGeneratedBytecodes() = true;
- VM& vm = globalObject->vm();
- #if ENABLE(SAMPLING_FLAGS)
- SamplingFlags::start();
- #endif
- bool success = true;
- for (size_t i = 0; i < scripts.size(); i++) {
- if (scripts[i].isFile) {
- fileName = scripts[i].argument;
- if (!fillBufferWithContentsOfFile(fileName, scriptBuffer))
- return false; // fail early so we can catch missing files
- script = scriptBuffer.data();
- } else {
- script = scripts[i].argument;
- fileName = "[Command Line]";
- }
- vm.startSampling();
- JSValue evaluationException;
- JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), &evaluationException);
- success = success && !evaluationException;
- if (dump && !evaluationException)
- printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
- if (evaluationException) {
- printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
- Identifier stackID(globalObject->globalExec(), "stack");
- JSValue stackValue = evaluationException.get(globalObject->globalExec(), stackID);
- if (!stackValue.isUndefinedOrNull())
- printf(" %s\n", stackValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
- }
- vm.stopSampling();
- globalObject->globalExec()->clearException();
- }
- #if ENABLE(SAMPLING_FLAGS)
- SamplingFlags::stop();
- #endif
- #if ENABLE(SAMPLING_REGIONS)
- SamplingRegion::dump();
- #endif
- vm.dumpSampleData(globalObject->globalExec());
- #if ENABLE(SAMPLING_COUNTERS)
- AbstractSamplingCounter::dump();
- #endif
- #if ENABLE(REGEXP_TRACING)
- vm.dumpRegExpTrace();
- #endif
- return success;
- }
- #define RUNNING_FROM_XCODE 0
- static void runInteractive(GlobalObject* globalObject)
- {
- String interpreterName("Interpreter");
-
- bool shouldQuit = false;
- while (!shouldQuit) {
- #if HAVE(READLINE) && !RUNNING_FROM_XCODE
- ParserError error;
- String source;
- do {
- error = ParserError();
- char* line = readline(source.isEmpty() ? interactivePrompt : "... ");
- shouldQuit = !line;
- if (!line)
- break;
- source = source + line;
- source = source + '\n';
- checkSyntax(globalObject->vm(), makeSource(source, interpreterName), error);
- if (!line[0])
- break;
- add_history(line);
- } while (error.m_syntaxErrorType == ParserError::SyntaxErrorRecoverable);
-
- if (error.m_type != ParserError::ErrorNone) {
- printf("%s:%d\n", error.m_message.utf8().data(), error.m_line);
- continue;
- }
-
-
- JSValue evaluationException;
- JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, interpreterName), JSValue(), &evaluationException);
- #else
- printf("%s", interactivePrompt);
- Vector<char, 256> line;
- int c;
- while ((c = getchar()) != EOF) {
- // FIXME: Should we also break on \r?
- if (c == '\n')
- break;
- line.append(c);
- }
- if (line.isEmpty())
- break;
- line.append('\0');
- JSValue evaluationException;
- JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line.data(), interpreterName), JSValue(), &evaluationException);
- #endif
- if (evaluationException)
- printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
- else
- printf("%s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
- globalObject->globalExec()->clearException();
- }
- printf("\n");
- }
- static NO_RETURN void printUsageStatement(bool help = false)
- {
- fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
- fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
- fprintf(stderr, " -e Evaluate argument as script code\n");
- fprintf(stderr, " -f Specifies a source file (deprecated)\n");
- fprintf(stderr, " -h|--help Prints this help message\n");
- fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
- #if HAVE(SIGNAL_H)
- fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
- #endif
- fprintf(stderr, " -p <file> Outputs profiling data to a file\n");
- fprintf(stderr, " -x Output exit code before terminating\n");
- fprintf(stderr, "\n");
- fprintf(stderr, " --options Dumps all JSC VM options and exits\n");
- fprintf(stderr, " --dumpOptions Dumps all JSC VM options before continuing\n");
- fprintf(stderr, " --<jsc VM option>=<value> Sets the specified JSC VM option\n");
- fprintf(stderr, "\n");
- exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
- }
- void CommandLine::parseArguments(int argc, char** argv)
- {
- int i = 1;
- bool needToDumpOptions = false;
- bool needToExit = false;
- for (; i < argc; ++i) {
- const char* arg = argv[i];
- if (!strcmp(arg, "-f")) {
- if (++i == argc)
- printUsageStatement();
- m_scripts.append(Script(true, argv[i]));
- continue;
- }
- if (!strcmp(arg, "-e")) {
- if (++i == argc)
- printUsageStatement();
- m_scripts.append(Script(false, argv[i]));
- continue;
- }
- if (!strcmp(arg, "-i")) {
- m_interactive = true;
- continue;
- }
- if (!strcmp(arg, "-d")) {
- m_dump = true;
- continue;
- }
- if (!strcmp(arg, "-p")) {
- if (++i == argc)
- printUsageStatement();
- m_profile = true;
- m_profilerOutput = argv[i];
- continue;
- }
- if (!strcmp(arg, "-s")) {
- #if HAVE(SIGNAL_H)
- signal(SIGILL, _exit);
- signal(SIGFPE, _exit);
- signal(SIGBUS, _exit);
- signal(SIGSEGV, _exit);
- #endif
- continue;
- }
- if (!strcmp(arg, "-x")) {
- m_exitCode = true;
- continue;
- }
- if (!strcmp(arg, "--")) {
- ++i;
- break;
- }
- if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
- printUsageStatement(true);
- if (!strcmp(arg, "--options")) {
- needToDumpOptions = true;
- needToExit = true;
- continue;
- }
- if (!strcmp(arg, "--dumpOptions")) {
- needToDumpOptions = true;
- continue;
- }
- // See if the -- option is a JSC VM option.
- // NOTE: At this point, we know that the arg starts with "--". Skip it.
- if (JSC::Options::setOption(&arg[2])) {
- // The arg was recognized as a VM option and has been parsed.
- continue; // Just continue with the next arg.
- }
- // This arg is not recognized by the VM nor by jsc. Pass it on to the
- // script.
- m_scripts.append(Script(true, argv[i]));
- }
- if (m_scripts.isEmpty())
- m_interactive = true;
- for (; i < argc; ++i)
- m_arguments.append(argv[i]);
- if (needToDumpOptions)
- JSC::Options::dumpAllOptions(stderr);
- if (needToExit)
- exit(EXIT_SUCCESS);
- }
- int jscmain(int argc, char** argv)
- {
- // Note that the options parsing can affect VM creation, and thus
- // comes first.
- CommandLine options(argc, argv);
- RefPtr<VM> vm = VM::create(LargeHeap);
- int result;
- {
- APIEntryShim shim(vm.get());
- #if ENABLE(DETACHED_JIT)
- #pragma message "[SECURE JSCORE] profiling disabled"
- #else
- if (options.m_profile && !vm->m_perBytecodeProfiler)
- vm->m_perBytecodeProfiler = adoptPtr(new Profiler::Database(*vm));
- #endif
- GlobalObject* globalObject = GlobalObject::create(*vm, GlobalObject::createStructure(*vm, jsNull()), options.m_arguments);
- bool success = runWithScripts(globalObject, options.m_scripts, options.m_dump);
- if (options.m_interactive && success)
- runInteractive(globalObject);
- result = success ? 0 : 3;
- if (options.m_exitCode)
- printf("jsc exiting %d\n", result);
-
- #if ENABLE(DETACHED_JIT)
- #pragma message "[SECURE JSCORE] profiling disabled"
- #else
- if (options.m_profile) {
- if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data()))
- fprintf(stderr, "could not save profiler output.\n");
- }
- #endif
- }
-
- JSLockHolder lock(*vm);
- vm.clear();
-
- return result;
- }
- static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
- {
- FILE* f = fopen(fileName.utf8().data(), "r");
- if (!f) {
- fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
- return false;
- }
- size_t bufferSize = 0;
- size_t bufferCapacity = 1024;
- buffer.resize(bufferCapacity);
- while (!feof(f) && !ferror(f)) {
- bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f);
- if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0'
- bufferCapacity *= 2;
- buffer.resize(bufferCapacity);
- }
- }
- fclose(f);
- buffer[bufferSize] = '\0';
- if (buffer[0] == '#' && buffer[1] == '!')
- buffer[0] = buffer[1] = '/';
- return true;
- }
|