summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@trolltech.com>2009-09-28 14:28:36 (GMT)
committerOlivier Goffart <ogoffart@trolltech.com>2009-09-28 15:38:55 (GMT)
commitffeb75fe970dadbf2b5e5a96bc63ba0a53fb6be5 (patch)
tree4b366cc9bac8e8609c71f4671b32c574e0ce4639 /src
parent4efaf156223cd12f799164a479929f78a9b5db95 (diff)
downloadQt-ffeb75fe970dadbf2b5e5a96bc63ba0a53fb6be5.zip
Qt-ffeb75fe970dadbf2b5e5a96bc63ba0a53fb6be5.tar.gz
Qt-ffeb75fe970dadbf2b5e5a96bc63ba0a53fb6be5.tar.bz2
QScript: Fix strange bugs and crashes.
I was assuming that the default return value register was always set to 0 for native calls. But this is not the case. So we must ensure this. Also be consistend in the way the stackframe grow and shrink. This expose another bug in the way the call frame is created in JSC Reviewed-by: Kent Hansen
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp14
-rw-r--r--src/script/api/qscriptengine.cpp17
-rw-r--r--src/script/api/qscriptengine_p.h3
3 files changed, 25 insertions, 9 deletions
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp
index c31216b..bfb0307 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp
@@ -3071,8 +3071,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
if (callType == CallTypeHost) {
ScopeChainNode* scopeChain = callFrame->scopeChain();
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
+#ifdef QT_BUILD_SCRIPT_LIB //we need the returnValue to be 0 as it is used as flags
+ newCallFrame->init(0, vPC + 5, scopeChain, callFrame, 0, argCount, asObject(v));
+#else
newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, asObject(v));
-
+#endif
Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
ArgList args(thisRegister + 1, argCount - 1);
@@ -3225,7 +3228,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
if (callType == CallTypeHost) {
ScopeChainNode* scopeChain = callFrame->scopeChain();
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
+#ifdef QT_BUILD_SCRIPT_LIB //we need the returnValue to be 0 as it is used as flags
+ newCallFrame->init(0, vPC + 5, scopeChain, callFrame, 0, argCount, asObject(v));
+#else
newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, asObject(v));
+#endif
+
Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
ArgList args(thisRegister + 1, argCount - 1);
@@ -3501,7 +3509,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
ScopeChainNode* scopeChain = callFrame->scopeChain();
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
+#ifdef QT_BUILD_SCRIPT_LIB //we need the returnValue to be 0 as it is used as flags
+ newCallFrame->init(0, vPC + 7, scopeChain, callFrame, 0, argCount, asObject(v));
+#else
newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, asObject(v));
+#endif
JSValue returnValue;
{
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index 78bbf5f..b27d1be 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -2353,23 +2353,25 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV
//build a frame
JSC::CallFrame *newCallFrame = exec;
if (callee == 0 //called from public QScriptEngine::pushContext
- || exec->returnPC() == 0 || (contextFlags(exec) & NativeContext) //called from native-native call
+ || exec->returnPC() == 0 || (contextFlags(exec) & NativeContext) //called from native-native call
|| (exec->codeBlock() && exec->callee() != callee)) { //the interpreter did not build a frame for us.
//We need to check if the Interpreter might have already created a frame for function called from JS.
JSC::Interpreter *interp = exec->interpreter();
JSC::Register *oldEnd = interp->registerFile().end();
int argc = args.size() + 1; //add "this"
JSC::Register *newEnd = oldEnd + argc + JSC::RegisterFile::CallFrameHeaderSize;
- if (!interp->registerFile().grow(newEnd))
+ //Without + argc + JSC::RegisterFile::CallFrameHeaderSize, it crashes.
+ //It seems that JSC is not consistant with the way the callframe is crated
+ if (!interp->registerFile().grow(newEnd + argc + JSC::RegisterFile::CallFrameHeaderSize))
return 0; //### Stack overflow
- newCallFrame = JSC::CallFrame::create(oldEnd);
+ newCallFrame = JSC::CallFrame::create(newEnd);
newCallFrame[0] = thisObject;
int dst = 0;
JSC::ArgList::const_iterator it;
for (it = args.begin(); it != args.end(); ++it)
newCallFrame[++dst] = *it;
newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize;
- newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags, argc, callee);
+ newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
} else {
setContextFlags(newCallFrame, flags);
#if ENABLE(JIT)
@@ -2411,18 +2413,19 @@ void QScriptEngine::popContext()
*/
void QScriptEnginePrivate::popContext()
{
- bool hasScope = contextFlags(currentFrame) & HasScopeContext;
- if (currentFrame->returnPC() == 0) { //normal case
+ uint flags = contextFlags(currentFrame);
+ bool hasScope = flags & HasScopeContext;
+ if (flags & ShouldRestoreCallFrame) { //normal case
JSC::RegisterFile &registerFile = currentFrame->interpreter()->registerFile();
JSC::Register *const newEnd = currentFrame->registers() - JSC::RegisterFile::CallFrameHeaderSize - currentFrame->argumentCount();
if (hasScope)
currentFrame->scopeChain()->pop()->deref();
- currentFrame = currentFrame->callerFrame();
registerFile.shrink(newEnd);
} 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();
}
+ currentFrame = currentFrame->callerFrame();
}
/*!
diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h
index c43ca61..b8b805e 100644
--- a/src/script/api/qscriptengine_p.h
+++ b/src/script/api/qscriptengine_p.h
@@ -170,7 +170,8 @@ public:
enum ContextFlags {
NativeContext = 1,
CalledAsConstructorContext = 2,
- HasScopeContext = 4
+ HasScopeContext = 4, // Specifies that the is a QScriptActivationObject
+ ShouldRestoreCallFrame = 8
};
static uint contextFlags(JSC::ExecState *);
static void setContextFlags(JSC::ExecState *, uint);