diff options
author | Kent Hansen <khansen@trolltech.com> | 2009-07-08 16:15:49 (GMT) |
---|---|---|
committer | Kent Hansen <khansen@trolltech.com> | 2009-07-08 16:17:37 (GMT) |
commit | a4e0ae8af7b550117d1e9d9dbb90564d50985fe3 (patch) | |
tree | f74e6ab0ec829bca0ecea607d06a5d90aa445ecc /src/script/api/qscriptvalue.cpp | |
parent | 9fa78177eb5f31e6941b165949957f2b92b8dd0a (diff) | |
download | Qt-a4e0ae8af7b550117d1e9d9dbb90564d50985fe3.zip Qt-a4e0ae8af7b550117d1e9d9dbb90564d50985fe3.tar.gz Qt-a4e0ae8af7b550117d1e9d9dbb90564d50985fe3.tar.bz2 |
rewrite most of QScriptContext handling
Do it The right way(TM), by lazily wrapping JSC::ExecState objects.
Diffstat (limited to 'src/script/api/qscriptvalue.cpp')
-rw-r--r-- | src/script/api/qscriptvalue.cpp | 95 |
1 files changed, 90 insertions, 5 deletions
diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index b1e70b5..a120d9c 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -1877,7 +1877,7 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, } QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(d->engine); - JSC::ExecState *exec = eng_p->globalObject->globalExec(); + JSC::ExecState *exec = eng_p->currentFrame; JSC::JSValue jscThisObject = eng_p->scriptValueToJSCValue(thisObject); if (!jscThisObject || !jscThisObject.isObject()) @@ -1907,7 +1907,24 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, if (callType == JSC::CallTypeJS) { result = JSC::asFunction(callee)->call(exec, jscThisObject, jscArgs); } else if (callType == JSC::CallTypeHost) { - result = callData.native.function(exec, JSC::asObject(callee), jscThisObject, jscArgs); + JSC::ScopeChainNode* scopeChain = exec->scopeChain(); + JSC::Interpreter *interp = exec->interpreter(); + JSC::Register *oldEnd = interp->registerFile().end(); + int argc = 1 + jscArgs.size(); // implicit "this" parameter + if (!interp->registerFile().grow(oldEnd + argc + JSC::RegisterFile::CallFrameHeaderSize)) { + Q_ASSERT_X(false, Q_FUNC_INFO, "stack overflow"); + } + JSC::CallFrame* newCallFrame = JSC::CallFrame::create(oldEnd); + size_t dst = 0; + newCallFrame[0] = jscThisObject; + JSC::ArgList::const_iterator it; + for (it = jscArgs.begin(); it != jscArgs.end(); ++it) + newCallFrame[++dst] = *it; + newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize; + // ### dst? + newCallFrame->init(0, /*vPC=*/0, scopeChain, exec, dst, argc, JSC::asInternalFunction(callee)); + result = callData.native.function(newCallFrame, JSC::asObject(callee), jscThisObject, jscArgs); + interp->registerFile().shrink(oldEnd); } if (exec->hadException()) eng_p->uncaughtException = exec->exception(); @@ -1986,7 +2003,25 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, if (callType == JSC::CallTypeJS) { result = JSC::asFunction(callee)->call(exec, jscThisObject, applyArgs); } else if (callType == JSC::CallTypeHost) { - result = callData.native.function(exec, JSC::asObject(callee), jscThisObject, applyArgs); + // ### avoid copy+paste of other call() overload + JSC::ScopeChainNode* scopeChain = exec->scopeChain(); + JSC::Interpreter *interp = exec->interpreter(); + JSC::Register *oldEnd = interp->registerFile().end(); + int argc = 1 + applyArgs.size(); // implicit "this" parameter + if (!interp->registerFile().grow(oldEnd + argc + JSC::RegisterFile::CallFrameHeaderSize)) { + Q_ASSERT_X(false, Q_FUNC_INFO, "stack overflow"); + } + JSC::CallFrame* newCallFrame = JSC::CallFrame::create(oldEnd); + size_t dst = 0; + newCallFrame[0] = jscThisObject; + JSC::MarkedArgumentBuffer::const_iterator it; + for (it = applyArgs.begin(); it != applyArgs.end(); ++it) + newCallFrame[++dst] = *it; + newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize; + // ### dst? + newCallFrame->init(0, /*vPC=*/0, scopeChain, exec, dst, argc, JSC::asInternalFunction(callee)); + result = callData.native.function(newCallFrame, JSC::asObject(callee), jscThisObject, applyArgs); + interp->registerFile().shrink(oldEnd); } if (exec->hadException()) { eng_p->uncaughtException = exec->exception(); @@ -2038,7 +2073,32 @@ QScriptValue QScriptValue::construct(const QScriptValueList &args) if (constructType == JSC::ConstructTypeJS) { result = JSC::asFunction(callee)->construct(exec, jscArgs); } else if (constructType == JSC::ConstructTypeHost) { - result = constructData.native.function(exec, JSC::asObject(callee), jscArgs); + JSC::Structure* structure; + JSC::JSValue prototype = callee.get(exec, exec->propertyNames().prototype); + if (prototype.isObject()) + structure = asObject(prototype)->inheritorID(); + else + structure = exec->lexicalGlobalObject()->emptyObjectStructure(); + JSC::JSObject* thisObj = new (exec) JSC::JSObject(structure); + // ### avoid copy+paste of call() + JSC::ScopeChainNode* scopeChain = exec->scopeChain(); + JSC::Interpreter *interp = exec->interpreter(); + JSC::Register *oldEnd = interp->registerFile().end(); + int argc = 1 + jscArgs.size(); // implicit "this" parameter + if (!interp->registerFile().grow(oldEnd + argc + JSC::RegisterFile::CallFrameHeaderSize)) { + Q_ASSERT_X(false, Q_FUNC_INFO, "stack overflow"); + } + JSC::CallFrame* newCallFrame = JSC::CallFrame::create(oldEnd); + size_t dst = 0; + newCallFrame[0] = JSC::JSValue(thisObj); + JSC::ArgList::const_iterator it; + for (it = jscArgs.begin(); it != jscArgs.end(); ++it) + newCallFrame[++dst] = *it; + newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize; + // ### dst? + newCallFrame->init(0, /*vPC=*/0, scopeChain, exec, dst, argc, JSC::asInternalFunction(callee)); + result = constructData.native.function(newCallFrame, JSC::asObject(callee), jscArgs); + interp->registerFile().shrink(oldEnd); } if (exec->hadException()) eng_p->uncaughtException = exec->exception(); @@ -2095,7 +2155,32 @@ QScriptValue QScriptValue::construct(const QScriptValue &arguments) if (constructType == JSC::ConstructTypeJS) { result = JSC::asFunction(callee)->construct(exec, applyArgs); } else if (constructType == JSC::ConstructTypeHost) { - result = constructData.native.function(exec, JSC::asObject(callee), applyArgs); + JSC::Structure* structure; + JSC::JSValue prototype = callee.get(exec, exec->propertyNames().prototype); + if (prototype.isObject()) + structure = asObject(prototype)->inheritorID(); + else + structure = exec->lexicalGlobalObject()->emptyObjectStructure(); + JSC::JSObject* thisObj = new (exec) JSC::JSObject(structure); + // ### avoid copy+paste of call() + JSC::ScopeChainNode* scopeChain = exec->scopeChain(); + JSC::Interpreter *interp = exec->interpreter(); + JSC::Register *oldEnd = interp->registerFile().end(); + int argc = 1 + applyArgs.size(); // implicit "this" parameter + if (!interp->registerFile().grow(oldEnd + argc + JSC::RegisterFile::CallFrameHeaderSize)) { + Q_ASSERT_X(false, Q_FUNC_INFO, "stack overflow"); + } + JSC::CallFrame* newCallFrame = JSC::CallFrame::create(oldEnd); + size_t dst = 0; + newCallFrame[0] = JSC::JSValue(thisObj); + JSC::MarkedArgumentBuffer::const_iterator it; + for (it = applyArgs.begin(); it != applyArgs.end(); ++it) + newCallFrame[++dst] = *it; + newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize; + // ### dst? + newCallFrame->init(0, /*vPC=*/0, scopeChain, exec, dst, argc, JSC::asInternalFunction(callee)); + result = constructData.native.function(newCallFrame, JSC::asObject(callee), applyArgs); + interp->registerFile().shrink(oldEnd); } if (exec->hadException()) { eng_p->uncaughtException = exec->exception(); |