diff options
-rw-r--r-- | src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context.cpp | 76 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context_p.h | 9 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 73 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script.cpp | 34 |
6 files changed, 93 insertions, 106 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp index b2db23d78c..aed2759383 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp @@ -60,7 +60,7 @@ QV4::CallContext *QV4DataCollector::findContext(int frame) QV4::ExecutionContext *ctx = engine()->currentContext; while (ctx) { QV4::CallContext *cCtxt = ctx->asCallContext(); - if (cCtxt && cCtxt->d()->function) { + if (cCtxt && cCtxt->d()->v4Function) { if (frame < 1) return cCtxt; --frame; diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 26f2f996a6..df0ecdd5d3 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -48,6 +48,8 @@ #include "qv4errorobject_p.h" #include "qv4string_p.h" #include "qv4qmlcontext_p.h" +#include "qv4profiling_p.h" +#include <private/qqmljavascriptexpression_p.h> using namespace QV4; @@ -57,28 +59,30 @@ DEFINE_MANAGED_VTABLE(WithContext); DEFINE_MANAGED_VTABLE(CatchContext); DEFINE_MANAGED_VTABLE(GlobalContext); -Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *function, CallData *callData) -{ - Q_ASSERT(function->function()); +/* Function *f, int argc */ +#define requiredMemoryForExecutionContect(f, argc) \ + ((sizeof(CallContext::Data) + 7) & ~7) + \ + sizeof(Value) * (f->compiledFunction->nLocals + qMax((uint)argc, f->nFormals)) + sizeof(CallData) +Heap::CallContext *ExecutionContext::newCallContext(Function *function, CallData *callData) +{ Heap::CallContext *c = d()->engine->memoryManager->allocManaged<CallContext>( requiredMemoryForExecutionContect(function, callData->argc)); c->init(d()->engine, Heap::ExecutionContext::Type_CallContext); - c->function = function->d(); - c->v4Function = function->d()->function; + c->v4Function = function; - c->strictMode = function->strictMode(); - c->outer = function->scope(); + c->strictMode = function->isStrict(); + c->outer = this->d(); c->activation = 0; - c->compilationUnit = function->function()->compilationUnit; + c->compilationUnit = function->compilationUnit; c->lookups = c->compilationUnit->runtimeLookups; c->constantTable = c->compilationUnit->constants; c->locals = (Value *)((quintptr(c + 1) + 7) & ~7); - const CompiledData::Function *compiledFunction = function->function()->compiledFunction; + const CompiledData::Function *compiledFunction = function->compiledFunction; int nLocals = compiledFunction->nLocals; if (nLocals) std::fill(c->locals, c->locals + nLocals, Primitive::undefinedValue()); @@ -278,7 +282,7 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine) break; case Heap::ExecutionContext::Type_CallContext: { QV4::Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx); - Q_ASSERT(c->v4Function && c->function); + Q_ASSERT(c->v4Function); ctx->callData->thisObject.mark(engine); for (int arg = 0; arg < qMax(ctx->callData->argc, (int)c->v4Function->nFormals); ++arg) ctx->callData->args[arg].mark(engine); @@ -286,7 +290,8 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine) c->locals[local].mark(engine); if (c->activation) c->activation->mark(engine); - c->function->mark(engine); + if (c->function) + c->function->mark(engine); break; } case Heap::ExecutionContext::Type_QmlContext: { @@ -297,6 +302,51 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine) } } +// Do a standard call with this execution context as the outer scope +void ExecutionContext::call(Scope &scope, CallData *callData, Function *function, const FunctionObject *f) +{ + ExecutionContextSaver ctxSaver(scope); + + Scoped<CallContext> ctx(scope, newCallContext(function, callData)); + if (f) + ctx->d()->function = f->d(); + scope.engine->pushContext(ctx); + + scope.result = Q_V4_PROFILE(scope.engine, function); + + if (function->hasQmlDependencies) + QQmlPropertyCapture::registerQmlDependencies(function->compiledFunction, scope); +} + +// Do a simple, fast call with this execution context as the outer scope +void QV4::ExecutionContext::simpleCall(Scope &scope, CallData *callData, Function *function) +{ + Q_ASSERT(function->canUseSimpleFunction()); + + ExecutionContextSaver ctxSaver(scope); + + CallContext::Data ctx = CallContext::Data::createOnStack(scope.engine); + + ctx.strictMode = function->isStrict(); + ctx.callData = callData; + ctx.v4Function = function; + ctx.compilationUnit = function->compilationUnit; + ctx.lookups = function->compilationUnit->runtimeLookups; + ctx.constantTable = function->compilationUnit->constants; + ctx.outer = this->d(); + ctx.locals = scope.alloc(function->compiledFunction->nLocals); + for (int i = callData->argc; i < (int)function->nFormals; ++i) + callData->args[i] = Encode::undefined(); + + scope.engine->pushContext(&ctx); + Q_ASSERT(scope.engine->current == &ctx); + + scope.result = Q_V4_PROFILE(scope.engine, function); + + if (function->compiledFunction->hasQmlDependencies()) + QQmlPropertyCapture::registerQmlDependencies(function->compiledFunction, scope); +} + void ExecutionContext::setProperty(String *name, const Value &value) { Scope scope(this); @@ -425,7 +475,7 @@ ReturnedValue ExecutionContext::getProperty(String *name) if (hasProperty) return v->asReturnedValue(); } - if (c->v4Function && c->v4Function->isNamedExpression() + if (c->function && c->v4Function->isNamedExpression() && name->equals(ScopedString(scope, c->v4Function->name()))) return c->function->asReturnedValue(); break; @@ -503,7 +553,7 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base) if (hasProperty) return v->asReturnedValue(); } - if (c->v4Function && c->v4Function->isNamedExpression() + if (c->function && c->v4Function->isNamedExpression() && name->equals(ScopedString(scope, c->v4Function->name()))) return c->function->asReturnedValue(); break; diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 7bf58ab5c6..c985fdb24d 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -198,7 +198,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed ExecutionEngine *engine() const { return d()->engine; } - Heap::CallContext *newCallContext(const FunctionObject *f, CallData *callData); + Heap::CallContext *newCallContext(Function *f, CallData *callData); Heap::WithContext *newWithContext(Heap::Object *with); Heap::CatchContext *newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue); @@ -230,6 +230,9 @@ struct Q_QML_EXPORT ExecutionContext : public Managed ReturnedValue argument(int i) const { return d()->callData->argument(i); } + + void call(Scope &scope, CallData *callData, QV4::Function *function, const QV4::FunctionObject *f = 0); + void simpleCall(Scope &scope, CallData *callData, QV4::Function *function); }; struct Q_QML_EXPORT CallContext : public ExecutionContext @@ -296,10 +299,6 @@ inline Heap::CallContext Heap::CallContext::createOnStack(ExecutionEngine *v4) return ctxt; } -/* Function *f, int argc */ -#define requiredMemoryForExecutionContect(f, argc) \ - ((sizeof(CallContext::Data) + 7) & ~7) + sizeof(Value) * (f->varCount() + qMax((uint)argc, f->formalParameterCount())) + sizeof(CallData) - } // namespace QV4 QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index c438b99cf0..0520bfe216 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -866,9 +866,8 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file) ExecutionContext *c = currentContext; while (c) { CallContext *callCtx = c->asCallContext(); - if (callCtx && callCtx->d()->function) { - if (callCtx->d()->function->function) - base.setUrl(callCtx->d()->function->function->sourceFile()); + if (callCtx && callCtx->d()->v4Function) { + base.setUrl(callCtx->d()->v4Function->sourceFile()); break; } c = parentContext(c); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 21edf1d8d3..08d66bec6f 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -441,15 +441,13 @@ void ScriptFunction::construct(const Managed *that, Scope &scope, CallData *call InternalClass *ic = v4->emptyClass; ScopedObject proto(scope, f->protoForConstructor()); ScopedObject obj(scope, v4->newObject(ic, proto)); - callData->thisObject = obj.asReturnedValue(); - Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(f, callData)); - v4->pushContext(ctx); - scope.result = Q_V4_PROFILE(v4, f->function()); + QV4::Function *v4Function = f->function(); + Q_ASSERT(v4Function); - if (f->function()->hasQmlDependencies) - QQmlPropertyCapture::registerQmlDependencies(f->function()->compiledFunction, scope); + ScopedContext c(scope, f->scope()); + c->call(scope, callData, v4Function, f); if (Q_UNLIKELY(v4->hasException)) { scope.result = Encode::undefined(); @@ -467,16 +465,13 @@ void ScriptFunction::call(const Managed *that, Scope &scope, CallData *callData) } CHECK_STACK_LIMITS(v4, scope); - ExecutionContextSaver ctxSaver(scope); - Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that)); - Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(f, callData)); - v4->pushContext(ctx); - scope.result = Q_V4_PROFILE(v4, f->function()); + QV4::Function *v4Function = f->function(); + Q_ASSERT(v4Function); - if (f->function()->hasQmlDependencies) - QQmlPropertyCapture::registerQmlDependencies(f->function()->compiledFunction, scope); + ScopedContext c(scope, f->scope()); + c->call(scope, callData, v4Function, f); } DEFINE_OBJECT_VTABLE(SimpleScriptFunction); @@ -523,35 +518,17 @@ void SimpleScriptFunction::construct(const Managed *that, Scope &scope, CallData } CHECK_STACK_LIMITS(v4, scope); - ExecutionContextSaver ctxSaver(scope); - Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that)); InternalClass *ic = scope.engine->emptyClass; ScopedObject proto(scope, f->protoForConstructor()); callData->thisObject = v4->newObject(ic, proto); - CallContext::Data ctx = CallContext::Data::createOnStack(v4); - ctx.function = f->d(); - QV4::Function *ff = ctx.function->function; - ctx.v4Function = ff; - ctx.strictMode = ff->isStrict(); - ctx.callData = callData; - ctx.compilationUnit = ff->compilationUnit; - ctx.lookups = ctx.compilationUnit->runtimeLookups; - ctx.constantTable = ctx.compilationUnit->constants; - ctx.outer = ctx.function->scope; - if (unsigned varCount = f->varCount()) - ctx.locals = scope.alloc(varCount); - for (int i = callData->argc; i < static_cast<int>(ff->nFormals); ++i) - callData->args[i] = Encode::undefined(); - v4->pushContext(&ctx); - Q_ASSERT(v4->current == &ctx); + QV4::Function *v4Function = f->function(); + Q_ASSERT(v4Function); - scope.result = Q_V4_PROFILE(v4, ff); - - if (ff->hasQmlDependencies) - QQmlPropertyCapture::registerQmlDependencies(f->function()->compiledFunction, scope); + ScopedContext c(scope, f->scope()); + c->simpleCall(scope, callData, v4Function); if (Q_UNLIKELY(v4->hasException)) { scope.result = Encode::undefined(); @@ -569,31 +546,13 @@ void SimpleScriptFunction::call(const Managed *that, Scope &scope, CallData *cal } CHECK_STACK_LIMITS(v4, scope); - ExecutionContextSaver ctxSaver(scope); - Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that)); - CallContext::Data ctx = CallContext::Data::createOnStack(v4); - ctx.function = f->d(); - QV4::Function *ff = ctx.function->function; - ctx.v4Function = ff; - ctx.strictMode = ff->isStrict(); - ctx.callData = callData; - ctx.compilationUnit = ff->compilationUnit; - ctx.lookups = ctx.compilationUnit->runtimeLookups; - ctx.constantTable = ctx.compilationUnit->constants; - ctx.outer = ctx.function->scope; - if (unsigned varCount = f->varCount()) - ctx.locals = scope.alloc(varCount); - for (int i = callData->argc; i < static_cast<int>(ff->nFormals); ++i) - callData->args[i] = Encode::undefined(); - v4->pushContext(&ctx); - Q_ASSERT(v4->current == &ctx); - - scope.result = Q_V4_PROFILE(v4, ff); + QV4::Function *v4Function = f->function(); + Q_ASSERT(v4Function); - if (ff->hasQmlDependencies) - QQmlPropertyCapture::registerQmlDependencies(f->function()->compiledFunction, scope); + ScopedContext c(scope, f->scope()); + c->simpleCall(scope, callData, v4Function); } Heap::Object *SimpleScriptFunction::protoForConstructor() const diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 8c27d36f50..25089855bb 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -72,7 +72,9 @@ struct QmlBindingWrapper : FunctionObject { struct QmlBindingWrapper : FunctionObject { V4_OBJECT2(QmlBindingWrapper, FunctionObject) - static void call(const Managed *that, Scope &scope, CallData *callData); + static void call(const Managed *that, Scope &scope, CallData *callData) { + QV4::ScriptFunction::call(that, scope, callData); + } }; } @@ -94,30 +96,6 @@ void Heap::QmlBindingWrapper::init(QV4::QmlContext *scope, Function *f) function->compilationUnit->addref(); } -void QmlBindingWrapper::call(const Managed *that, Scope &scope, CallData *callData) -{ - const QmlBindingWrapper *This = static_cast<const QmlBindingWrapper *>(that); - ExecutionEngine *v4 = static_cast<const Object *>(that)->engine(); - if (v4->hasException) { - scope.result = Encode::undefined(); - return; - } - CHECK_STACK_LIMITS(v4, scope); - - ExecutionContextSaver ctxSaver(scope); - - QV4::Function *f = This->function(); - if (!f) { - scope.result = QV4::Encode::undefined(); - return; - } - - Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(This, callData)); - v4->pushContext(ctx); - - scope.result = Q_V4_PROFILE(v4, f); -} - Script::Script(ExecutionEngine *v4, QmlContext *qml, CompiledData::CompilationUnit *compilationUnit) : line(0), column(0), scope(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false) , compilationUnit(compilationUnit), vmFunction(0), parseAsBinding(true) @@ -228,10 +206,12 @@ ReturnedValue Script::run() return Q_V4_PROFILE(engine, vmFunction); } else { Scoped<QmlContext> qml(valueScope, qmlContext.value()); - ScopedFunctionObject f(valueScope, engine->memoryManager->allocObject<QmlBindingWrapper>(qml, vmFunction)); ScopedCallData callData(valueScope); callData->thisObject = Primitive::undefinedValue(); - f->call(valueScope, callData); + if (vmFunction->canUseSimpleFunction()) + qml->simpleCall(valueScope, callData, vmFunction); + else + qml->call(valueScope, callData, vmFunction); return valueScope.result.asReturnedValue(); } } |