summaryrefslogtreecommitdiffstats
path: root/src/script/api/qscriptengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/api/qscriptengine.cpp')
-rw-r--r--src/script/api/qscriptengine.cpp54
1 files changed, 42 insertions, 12 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index e8ea222..daf97d5 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -1114,6 +1114,30 @@ JSC::JSValue QScriptEnginePrivate::thisForContext(JSC::ExecState *frame)
}
}
+/*! \internal
+ For native context, we use the ReturnValueRegister entry in the stackframe header to store flags.
+ We can do that because this header is not used as the native function return their value thought C++
+
+ when setting flags, NativeContext should always be set
+
+ contextFlags returns 0 for non native context
+ */
+uint QScriptEnginePrivate::contextFlags(JSC::ExecState *exec)
+{
+ if (exec->codeBlock())
+ return 0; //js function doesn't have flags
+
+ return exec->returnValueRegister();
+}
+
+void QScriptEnginePrivate::setContextFlags(JSC::ExecState *exec, uint flags)
+{
+ Q_ASSERT(!exec->codeBlock());
+ quintptr flag_ptr = flags;
+ exec->registers()[JSC::RegisterFile::ReturnValueRegister] = JSC::JSValue(reinterpret_cast<JSC::JSObject*>(flag_ptr));
+}
+
+
void QScriptEnginePrivate::mark()
{
if (!originalGlobalObject()->marked())
@@ -2126,6 +2150,7 @@ QScriptValue QScriptEngine::evaluate(const QString &program, const QString &file
Q_D(QScriptEngine);
JSC::JSLock lock(false); // ### hmmm
+ currentContext()->activationObject(); //force the creation of a context for native function;
JSC::UString jscProgram = QScript::qtStringToJSCUString(program);
JSC::UString jscFileName = QScript::qtStringToJSCUString(fileName);
@@ -2269,6 +2294,10 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, const JS
thisObject = new (exec) QScriptObject(structure);
}
+ int flags = NativeContext;
+ if (calledAsConstructor)
+ flags |= CalledAsConstructorContext;
+
JSC::CallFrame *newCallFrame = exec;
if (callee == 0 || !(exec->callee() == callee && exec->returnPC() != 0)) {
//We need to check if the Interpreter might have already created a frame for function called from JS.
@@ -2285,16 +2314,16 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, const JS
for (it = args.begin(); it != args.end(); ++it)
newCallFrame[++dst] = *it;
newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize;
- newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, 0, argc, callee);
- } else if (calledAsConstructor) {
- //update the new created this
- JSC::Register* thisRegister = newCallFrame->registers() - JSC::RegisterFile::CallFrameHeaderSize - newCallFrame->argumentCount();
- *thisRegister = thisObject;
+ newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags, argc, callee);
+ } else {
+ setContextFlags(newCallFrame, flags);
+ if (calledAsConstructor) {
+ //update the new created this
+ JSC::Register* thisRegister = newCallFrame->registers() - JSC::RegisterFile::CallFrameHeaderSize - newCallFrame->argumentCount();
+ *thisRegister = thisObject;
+ }
}
currentFrame = newCallFrame;
- QScript::QScriptActivationObject *scope = new (newCallFrame) QScript::QScriptActivationObject(newCallFrame);
- scope->d_ptr()->calledAsConstructor = calledAsConstructor;
- newCallFrame->setScopeChain(newCallFrame->scopeChain()->copy()->push(scope));
return newCallFrame;
}
@@ -2311,7 +2340,7 @@ void QScriptEngine::popContext()
agent()->contextPop();
Q_D(QScriptEngine);
if (d->currentFrame->returnPC() != 0 || d->currentFrame->codeBlock() != 0
- || d->currentFrame->returnValueRegister() != 0 || !currentContext()->parentContext()) {
+ || !currentContext()->parentContext()) {
qWarning("QScriptEngine::popContext() doesn't match with pushContext()");
return;
}
@@ -2324,17 +2353,18 @@ void QScriptEngine::popContext()
*/
void QScriptEnginePrivate::popContext()
{
+ bool hasScope = contextFlags(currentFrame) & HasScopeContext;
if (currentFrame->returnPC() == 0) { //normal case
JSC::RegisterFile &registerFile = currentFrame->interpreter()->registerFile();
JSC::Register *const newEnd = currentFrame->registers() - JSC::RegisterFile::CallFrameHeaderSize - currentFrame->argumentCount();
- currentFrame->scopeChain()->pop()->deref();
+ if (hasScope)
+ currentFrame->scopeChain()->pop()->deref();
currentFrame = currentFrame->callerFrame();
registerFile.shrink(newEnd);
- } else { //the stack frame was created by the Interpreter, we don't need to rewind it.
+ } else if(hasScope) { //the stack frame was created by the Interpreter, we don't need to rewind it.
currentFrame->setScopeChain(currentFrame->scopeChain()->pop());
currentFrame->scopeChain()->deref();
}
-
}
/*!