diff options
Diffstat (limited to 'src/script/api')
-rw-r--r-- | src/script/api/qscriptcontext.cpp | 9 | ||||
-rw-r--r-- | src/script/api/qscriptcontextinfo.cpp | 7 | ||||
-rw-r--r-- | src/script/api/qscriptengine.cpp | 34 | ||||
-rw-r--r-- | src/script/api/qscriptengine_p.h | 36 | ||||
-rw-r--r-- | src/script/api/qscriptprogram.cpp | 21 | ||||
-rw-r--r-- | src/script/api/qscriptprogram_p.h | 1 |
6 files changed, 84 insertions, 24 deletions
diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index 59ea52d..2468a46 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -299,6 +299,12 @@ QScriptValue QScriptContext::argumentsObject() const //for a js function if (frame->codeBlock() && frame->callee()) { + if (!QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { + // We have a built-in JS host call. + // codeBlock is needed by retrieveArguments(), but since it + // contains junk, we would crash. Return an invalid value for now. + return QScriptValue(); + } JSC::JSValue result = frame->interpreter()->retrieveArguments(frame, JSC::asFunction(frame->callee())); return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result); } @@ -309,7 +315,8 @@ QScriptValue QScriptContext::argumentsObject() const } //for a native function - if (!frame->optionalCalleeArguments()) { + if (!frame->optionalCalleeArguments() + && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { // Make sure we don't go here for host JSFunctions Q_ASSERT(frame->argumentCount() > 0); //we need at least 'this' otherwise we'll crash later JSC::Arguments* arguments = new (&frame->globalData())JSC::Arguments(frame, JSC::Arguments::NoParameters); frame->setCalleeArguments(arguments); diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp index db6b2d7..0f9de1d 100644 --- a/src/script/api/qscriptcontextinfo.cpp +++ b/src/script/api/qscriptcontextinfo.cpp @@ -157,7 +157,7 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte JSC::Instruction *returnPC = rewindContext->returnPC(); JSC::CodeBlock *codeBlock = frame->codeBlock(); - if (returnPC && codeBlock) { + if (returnPC && codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { #if ENABLE(JIT) unsigned bytecodeOffset = codeBlock->getBytecodeIndex(frame, JSC::ReturnAddressPtr(returnPC)); #else @@ -171,7 +171,7 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte // Get the filename and the scriptId: JSC::CodeBlock *codeBlock = frame->codeBlock(); - if (codeBlock) { + if (codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { JSC::SourceProvider *source = codeBlock->source(); scriptId = source->asID(); fileName = source->url(); @@ -181,7 +181,8 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte JSC::JSObject *callee = frame->callee(); if (callee && callee->inherits(&JSC::InternalFunction::info)) functionName = JSC::asInternalFunction(callee)->name(frame); - if (callee && callee->inherits(&JSC::JSFunction::info)) { + if (callee && callee->inherits(&JSC::JSFunction::info) + && !JSC::asFunction(callee)->isHostFunction()) { functionType = QScriptContextInfo::ScriptFunction; JSC::FunctionExecutable *body = JSC::asFunction(callee)->jsExecutable(); functionStartLineNumber = body->lineNo(); diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 004e3a5..14ab2eb 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -858,7 +858,8 @@ JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState *exec, JSC::JSObject*, JS { JSC::ExecState *frame = exec->callerFrame()->removeHostCallFrameFlag(); while (frame) { - if (frame->codeBlock() && frame->codeBlock()->source() + if (frame->codeBlock() && QScriptEnginePrivate::hasValidCodeBlockRegister(frame) + && frame->codeBlock()->source() && !frame->codeBlock()->source()->url().isEmpty()) { context = engine->translationContextFromUrl(frame->codeBlock()->source()->url()); break; @@ -1022,6 +1023,7 @@ QScriptEnginePrivate::~QScriptEnginePrivate() while (!ownedAgents.isEmpty()) delete ownedAgents.takeFirst(); + detachAllRegisteredScriptPrograms(); detachAllRegisteredScriptValues(); detachAllRegisteredScriptStrings(); qDeleteAll(m_qobjectData); @@ -1576,6 +1578,14 @@ bool QScriptEnginePrivate::scriptDisconnect(JSC::JSValue signal, JSC::JSValue re #endif +void QScriptEnginePrivate::detachAllRegisteredScriptPrograms() +{ + QSet<QScriptProgramPrivate*>::const_iterator it; + for (it = registeredScriptPrograms.constBegin(); it != registeredScriptPrograms.constEnd(); ++it) + (*it)->detachFromEngine(); + registeredScriptPrograms.clear(); +} + void QScriptEnginePrivate::detachAllRegisteredScriptValues() { QScriptValuePrivate *it; @@ -2078,10 +2088,10 @@ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, JSC::ExecState* exec = d->currentFrame; JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun); QScriptValue result = d->scriptValueFromJSCValue(function); - result.setProperty(QLatin1String("prototype"), prototype, QScriptValue::Undeletable); + result.setProperty(QLatin1String("prototype"), prototype, + QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); const_cast<QScriptValue&>(prototype) - .setProperty(QLatin1String("constructor"), result, - QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + .setProperty(QLatin1String("constructor"), result, QScriptValue::SkipInEnumeration); return result; } @@ -2347,9 +2357,9 @@ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, in JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun); QScriptValue result = d->scriptValueFromJSCValue(function); QScriptValue proto = newObject(); - result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable); - proto.setProperty(QLatin1String("constructor"), result, - QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + result.setProperty(QLatin1String("prototype"), proto, + QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + proto.setProperty(QLatin1String("constructor"), result, QScriptValue::SkipInEnumeration); return result; } @@ -2365,9 +2375,9 @@ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature JSC::JSValue function = new (exec)QScript::FunctionWithArgWrapper(exec, /*length=*/0, JSC::Identifier(exec, ""), fun, arg); QScriptValue result = d->scriptValueFromJSCValue(function); QScriptValue proto = newObject(); - result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable); - proto.setProperty(QLatin1String("constructor"), result, - QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + result.setProperty(QLatin1String("prototype"), proto, + QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + proto.setProperty(QLatin1String("constructor"), result, QScriptValue::SkipInEnumeration); return result; } @@ -2753,9 +2763,7 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV if (!clearScopeChain) { newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); } else { - JSC::JSObject *jscObject = originalGlobalObject(); - JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), exec->lexicalGlobalObject(), jscObject); - newCallFrame->init(0, /*vPC=*/0, scn, exec, flags | ShouldRestoreCallFrame, argc, callee); + newCallFrame->init(0, /*vPC=*/0, globalExec()->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); } } else { setContextFlags(newCallFrame, flags); diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index 05a8901..94d195e 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -56,6 +56,7 @@ #include "Debugger.h" #include "ErrorInstance.h" #include "JSArray.h" +#include "Executable.h" #include "Lexer.h" #include "RefPtr.h" #include "RegExpConstructor.h" @@ -87,6 +88,7 @@ class QScriptEngineAgent; class QScriptEnginePrivate; class QScriptSyntaxCheckResult; class QScriptEngine; +class QScriptProgramPrivate; namespace QScript { @@ -230,6 +232,8 @@ public: static inline JSC::ExecState *frameForContext(QScriptContext *context); static inline const JSC::ExecState *frameForContext(const QScriptContext *context); + static inline bool hasValidCodeBlockRegister(JSC::ExecState *frame); + JSC::JSGlobalObject *originalGlobalObject() const; JSC::JSObject *getOriginalGlobalObjectProxy(); JSC::JSObject *customGlobalObject() const; @@ -273,6 +277,10 @@ public: static QScriptSyntaxCheckResult checkSyntax(const QString &program); static bool canEvaluate(const QString &program); + inline void registerScriptProgram(QScriptProgramPrivate *program); + inline void unregisterScriptProgram(QScriptProgramPrivate *program); + void detachAllRegisteredScriptPrograms(); + inline QScriptValuePrivate *allocateScriptValuePrivate(size_t); inline void freeScriptValuePrivate(QScriptValuePrivate *p); @@ -368,6 +376,7 @@ public: static const int maxFreeScriptValues = 256; int freeScriptValuesCount; QScriptStringPrivate *registeredScriptStrings; + QSet<QScriptProgramPrivate*> registeredScriptPrograms; QHash<int, QScriptTypeInfo*> m_typeInfos; int processEventsInterval; QScriptValue abortResult; @@ -566,6 +575,18 @@ inline QByteArray convertToLatin1(const JSC::UString &str) } // namespace QScript +inline void QScriptEnginePrivate::registerScriptProgram(QScriptProgramPrivate *program) +{ + Q_ASSERT(!registeredScriptPrograms.contains(program)); + registeredScriptPrograms.insert(program); +} + +inline void QScriptEnginePrivate::unregisterScriptProgram(QScriptProgramPrivate *program) +{ + Q_ASSERT(registeredScriptPrograms.contains(program)); + registeredScriptPrograms.remove(program); +} + inline QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(size_t size) { if (freeScriptValues) { @@ -844,6 +865,21 @@ inline const JSC::ExecState *QScriptEnginePrivate::frameForContext(const QScript return reinterpret_cast<const JSC::ExecState*>(context); } +inline bool QScriptEnginePrivate::hasValidCodeBlockRegister(JSC::ExecState *frame) +{ +#if ENABLE(JIT) + // Frames created by the VM don't have their CodeBlock register + // initialized. We can detect such frames by checking if the + // callee is a host JSFunction. + JSC::JSObject *callee = frame->callee(); + return !(callee && callee->inherits(&JSC::JSFunction::info) + && JSC::asFunction(callee)->isHostFunction()); +#else + Q_UNUSED(frame); + return true; +#endif +} + inline JSC::ExecState *QScriptEnginePrivate::globalExec() const { return originalGlobalObject()->globalExec(); diff --git a/src/script/api/qscriptprogram.cpp b/src/script/api/qscriptprogram.cpp index da103bb..31af9a0 100644 --- a/src/script/api/qscriptprogram.cpp +++ b/src/script/api/qscriptprogram.cpp @@ -64,6 +64,7 @@ QScriptProgramPrivate::~QScriptProgramPrivate() if (engine) { QScript::APIShim shim(engine); _executable.clear(); + engine->unregisterScriptProgram(this); } } @@ -78,7 +79,10 @@ JSC::EvalExecutable *QScriptProgramPrivate::executable(JSC::ExecState *exec, if (_executable) { if (eng == engine) return _executable.get(); - _executable = 0; + // "Migrating" to another engine; clean up old state + QScript::APIShim shim(engine); + _executable.clear(); + engine->unregisterScriptProgram(this); } WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider = QScript::UStringSourceProviderWithFeedback::create(sourceCode, fileName, firstLineNumber, eng); @@ -86,10 +90,19 @@ JSC::EvalExecutable *QScriptProgramPrivate::executable(JSC::ExecState *exec, JSC::SourceCode source(provider, firstLineNumber); //after construction of SourceCode provider variable will be null. _executable = JSC::EvalExecutable::create(exec, source); engine = eng; + engine->registerScriptProgram(this); isCompiled = false; return _executable.get(); } +void QScriptProgramPrivate::detachFromEngine() +{ + _executable.clear(); + sourceId = -1; + isCompiled = false; + engine = 0; +} + /*! Constructs a null QScriptProgram. */ @@ -122,9 +135,6 @@ QScriptProgram::QScriptProgram(const QScriptProgram &other) */ QScriptProgram::~QScriptProgram() { - // Q_D(QScriptProgram); - // if (d->engine && (d->ref == 1)) - // d->engine->unregisterScriptProgram(d); } /*! @@ -132,9 +142,6 @@ QScriptProgram::~QScriptProgram() */ QScriptProgram &QScriptProgram::operator=(const QScriptProgram &other) { - // if (d_func() && d_func()->engine && (d_func()->ref == 1)) - // d_func()->engine->unregisterScriptProgram(d_func()); - // } d_ptr = other.d_ptr; return *this; } diff --git a/src/script/api/qscriptprogram_p.h b/src/script/api/qscriptprogram_p.h index d2fd234..e7809ab 100644 --- a/src/script/api/qscriptprogram_p.h +++ b/src/script/api/qscriptprogram_p.h @@ -61,6 +61,7 @@ public: JSC::EvalExecutable *executable(JSC::ExecState *exec, QScriptEnginePrivate *engine); + void detachFromEngine(); QBasicAtomicInt ref; |