summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/jsc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/jsc.cpp')
-rw-r--r--Source/JavaScriptCore/jsc.cpp213
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;
}