diff options
Diffstat (limited to 'Source/JavaScriptCore/jsc.cpp')
-rw-r--r-- | Source/JavaScriptCore/jsc.cpp | 213 |
1 files changed, 140 insertions, 73 deletions
diff --git a/Source/JavaScriptCore/jsc.cpp b/Source/JavaScriptCore/jsc.cpp index 9db4eba86..4404faa9e 100644 --- a/Source/JavaScriptCore/jsc.cpp +++ b/Source/JavaScriptCore/jsc.cpp @@ -22,6 +22,7 @@ #include "config.h" +#include "APIShims.h" #include "ButterflyInlines.h" #include "BytecodeGenerator.h" #include "Completion.h" @@ -36,13 +37,16 @@ #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) @@ -82,6 +86,14 @@ #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; @@ -126,6 +138,7 @@ public: : m_interactive(false) , m_dump(false) , m_exitCode(false) + , m_profile(false) { parseArguments(argc, argv); } @@ -135,11 +148,13 @@ public: 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[] = "> "; +static const char interactivePrompt[] = ">>> "; class StopWatch { public: @@ -169,17 +184,17 @@ long StopWatch::getElapsedMS() class GlobalObject : public JSGlobalObject { private: - GlobalObject(JSGlobalData&, Structure*); + GlobalObject(VM&, Structure*); public: typedef JSGlobalObject Base; - static GlobalObject* create(JSGlobalData& globalData, Structure* structure, const Vector<String>& arguments) + static GlobalObject* create(VM& vm, Structure* structure, const Vector<String>& arguments) { - GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(globalData.heap)) GlobalObject(globalData, structure); - object->finishCreation(globalData, arguments); - globalData.heap.addFinalizer(object, destroy); - object->setGlobalThis(globalData, JSProxy::create(globalData, JSProxy::createStructure(globalData, object, object->prototype()), object)); + 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; } @@ -188,65 +203,65 @@ public: static const ClassInfo s_info; static const GlobalObjectMethodTable s_globalObjectMethodTable; - static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(VM& vm, JSValue prototype) { - return Structure::create(globalData, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info); + return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info); } static bool javaScriptExperimentsEnabled(const JSGlobalObject*) { return true; } protected: - void finishCreation(JSGlobalData& globalData, const Vector<String>& arguments) + void finishCreation(VM& vm, const Vector<String>& arguments) { - Base::finishCreation(globalData); + Base::finishCreation(vm); - addFunction(globalData, "debug", functionDebug, 1); - addFunction(globalData, "describe", functionDescribe, 1); - addFunction(globalData, "print", functionPrint, 1); - addFunction(globalData, "quit", functionQuit, 0); - addFunction(globalData, "gc", functionGC, 0); + 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(globalData, "dumpCallFrame", functionDumpCallFrame, 0); - addFunction(globalData, "releaseExecutableMemory", functionReleaseExecutableMemory, 0); -#endif - addFunction(globalData, "version", functionVersion, 1); - addFunction(globalData, "run", functionRun, 1); - addFunction(globalData, "load", functionLoad, 1); - addFunction(globalData, "checkSyntax", functionCheckSyntax, 1); - addFunction(globalData, "jscStack", functionJSCStack, 1); - addFunction(globalData, "readline", functionReadline, 0); - addFunction(globalData, "preciseTime", functionPreciseTime, 0); + 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(globalData, "setSamplingFlags", functionSetSamplingFlags, 1); - addFunction(globalData, "clearSamplingFlags", functionClearSamplingFlags, 1); + addFunction(vm, "setSamplingFlags", functionSetSamplingFlags, 1); + addFunction(vm, "clearSamplingFlags", functionClearSamplingFlags, 1); #endif - addConstructableFunction(globalData, "Uint8Array", constructJSUint8Array, 1); - addConstructableFunction(globalData, "Uint8ClampedArray", constructJSUint8ClampedArray, 1); - addConstructableFunction(globalData, "Uint16Array", constructJSUint16Array, 1); - addConstructableFunction(globalData, "Uint32Array", constructJSUint32Array, 1); - addConstructableFunction(globalData, "Int8Array", constructJSInt8Array, 1); - addConstructableFunction(globalData, "Int16Array", constructJSInt16Array, 1); - addConstructableFunction(globalData, "Int32Array", constructJSInt32Array, 1); - addConstructableFunction(globalData, "Float32Array", constructJSFloat32Array, 1); - addConstructableFunction(globalData, "Float64Array", constructJSFloat64Array, 1); + 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(globalData, Identifier(globalExec(), "arguments"), array); + putDirect(vm, Identifier(globalExec(), "arguments"), array); } - void addFunction(JSGlobalData& globalData, const char* name, NativeFunction function, unsigned arguments) + void addFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments) { Identifier identifier(globalExec(), name); - putDirect(globalData, identifier, JSFunction::create(globalExec(), this, arguments, identifier.string(), function)); + putDirect(vm, identifier, JSFunction::create(globalExec(), this, arguments, identifier.string(), function)); } - void addConstructableFunction(JSGlobalData& globalData, const char* name, NativeFunction function, unsigned arguments) + void addConstructableFunction(VM& vm, const char* name, NativeFunction function, unsigned arguments) { Identifier identifier(globalExec(), name); - putDirect(globalData, identifier, JSFunction::create(globalExec(), this, arguments, identifier.string(), function, NoIntrinsic, function)); + putDirect(vm, identifier, JSFunction::create(globalExec(), this, arguments, identifier.string(), function, NoIntrinsic, function)); } }; @@ -256,28 +271,33 @@ const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, 0, E const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled }; -GlobalObject::GlobalObject(JSGlobalData& globalData, Structure* structure) - : JSGlobalObject(globalData, structure, &s_globalObjectMethodTable) +GlobalObject::GlobalObject(VM& vm, Structure* structure) + : JSGlobalObject(vm, structure, &s_globalObjectMethodTable) { } -static inline SourceCode jscSource(const char* utf8, const String& filename) +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 makeSource(String(utf8, asciiLength), filename); - + return String(utf8, asciiLength); + // Slow case - contains non-ascii characters, use fromUTF8WithLatin1Fallback. ASSERT(*pos < 0); ASSERT(strlen(utf8) == asciiLength + strlen(pos)); - String source = String::fromUTF8WithLatin1Fallback(utf8, asciiLength + strlen(pos)); - return makeSource(source.impl(), filename); + 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) @@ -298,7 +318,7 @@ EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec) EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec) { if (!exec->callerFrame()->hasHostCallFrameFlag()) - exec->globalData().interpreter->dumpCallFrame(exec->callerFrame()); + exec->vm().interpreter->dumpCallFrame(exec->callerFrame()); return JSValue::encode(jsUndefined()); } #endif @@ -311,7 +331,7 @@ EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec) EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec) { - fprintf(stderr, "--> %s\n", exec->argument(0).description()); + fprintf(stderr, "--> %s\n", toCString(exec->argument(0)).data()); return JSValue::encode(jsUndefined()); } @@ -321,7 +341,7 @@ EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec) trace.appendLiteral("--> Stack trace:\n"); Vector<StackFrame> stackTrace; - Interpreter::getStackTrace(&exec->globalData(), stackTrace); + Interpreter::getStackTrace(&exec->vm(), stackTrace); int i = 0; for (Vector<StackFrame>::iterator iter = stackTrace.begin(); iter < stackTrace.end(); iter++) { @@ -344,7 +364,7 @@ EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec) EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec) { JSLockHolder lock(exec); - exec->globalData().releaseExecutableMemory(); + exec->vm().releaseExecutableMemory(); return JSValue::encode(jsUndefined()); } #endif @@ -363,7 +383,7 @@ EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec) if (!fillBufferWithContentsOfFile(fileName, script)) return JSValue::encode(throwError(exec, createError(exec, "Could not open file."))); - GlobalObject* globalObject = GlobalObject::create(exec->globalData(), GlobalObject::createStructure(exec->globalData(), jsNull()), Vector<String>()); + GlobalObject* globalObject = GlobalObject::create(exec->vm(), GlobalObject::createStructure(exec->vm(), jsNull()), Vector<String>()); JSValue exception; StopWatch stopWatch; @@ -512,11 +532,20 @@ int main(int argc, char** argv) 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 - // Initialize JSC before getting JSGlobalData. +#if PLATFORM(EFL) + ecore_init(); +#endif + + // Initialize JSC before getting VM. #if ENABLE(SAMPLING_REGIONS) WTF::initializeMainThread(); #endif @@ -530,6 +559,11 @@ int main(int argc, char** argv) EXCEPT(res = 3) if (Options::logHeapStatisticsAtExit()) HeapStatistics::reportSuccess(); + +#if PLATFORM(EFL) + ecore_shutdown(); +#endif + return res; } @@ -542,7 +576,7 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr if (dump) JSC::Options::dumpGeneratedBytecodes() = true; - JSGlobalData& globalData = globalObject->globalData(); + VM& vm = globalObject->vm(); #if ENABLE(SAMPLING_FLAGS) SamplingFlags::start(); @@ -560,7 +594,7 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr fileName = "[Command Line]"; } - globalData.startSampling(); + vm.startSampling(); JSValue evaluationException; JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), &evaluationException); @@ -575,7 +609,7 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr printf("%s\n", stackValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data()); } - globalData.stopSampling(); + vm.stopSampling(); globalObject->globalExec()->clearException(); } @@ -585,12 +619,12 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr #if ENABLE(SAMPLING_REGIONS) SamplingRegion::dump(); #endif - globalData.dumpSampleData(globalObject->globalExec()); + vm.dumpSampleData(globalObject->globalExec()); #if ENABLE(SAMPLING_COUNTERS) AbstractSamplingCounter::dump(); #endif #if ENABLE(REGEXP_TRACING) - globalData.dumpRegExpTrace(); + vm.dumpRegExpTrace(); #endif return success; } @@ -600,17 +634,34 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr static void runInteractive(GlobalObject* globalObject) { String interpreterName("Interpreter"); - - while (true) { + + bool shouldQuit = false; + while (!shouldQuit) { #if HAVE(READLINE) && !RUNNING_FROM_XCODE - char* line = readline(interactivePrompt); - if (!line) - break; - if (line[0]) + 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(), jscSource(line, interpreterName), JSValue(), &evaluationException); - free(line); + JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, interpreterName), JSValue(), &evaluationException); #else printf("%s", interactivePrompt); Vector<char, 256> line; @@ -649,6 +700,7 @@ static NO_RETURN void printUsageStatement(bool help = false) #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"); @@ -687,6 +739,13 @@ void CommandLine::parseArguments(int argc, char** argv) 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); @@ -743,14 +802,17 @@ void CommandLine::parseArguments(int argc, char** argv) int jscmain(int argc, char** argv) { - // Note that the options parsing can affect JSGlobalData creation, and thus + // Note that the options parsing can affect VM creation, and thus // comes first. CommandLine options(argc, argv); - RefPtr<JSGlobalData> globalData = JSGlobalData::create(LargeHeap); - JSLockHolder lock(globalData.get()); + VM* vm = VM::create(LargeHeap).leakRef(); + APIEntryShim shim(vm); int result; - GlobalObject* globalObject = GlobalObject::create(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.m_arguments); + if (options.m_profile && !vm->m_perBytecodeProfiler) + vm->m_perBytecodeProfiler = adoptPtr(new Profiler::Database(*vm)); + + 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); @@ -759,6 +821,11 @@ int jscmain(int argc, char** argv) if (options.m_exitCode) printf("jsc exiting %d\n", result); + + if (options.m_profile) { + if (!vm->m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data())) + fprintf(stderr, "could not save profiler output.\n"); + } return result; } |