diff options
author | Lars Knoll <lars.knoll@theqtcompany.com> | 2015-06-11 16:35:11 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2015-06-18 16:42:58 +0000 |
commit | f077bf13efee6d57261f76544e89a10acafb5a9c (patch) | |
tree | 9a438cd2cee32153586a477c22fea62b703199e5 | |
parent | fe9b63780da81fa8e3746e519dda320d57436503 (diff) |
Clean up ExecutionContext's for QML
Create a specialized QmlContext instead of re-using
a call context with a QQmlContextWrapper as activation
object.
This saves some memory and opens up the route to getting
rid of the context wrapper in a future commit.
Change-Id: I1591c73932a08564fddf5137ac05bbc6f31dd4d5
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
-rw-r--r-- | src/qml/jsruntime/qv4context.cpp | 300 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context_p.h | 18 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4debugging.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script.cpp | 36 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script_p.h | 5 |
8 files changed, 218 insertions, 151 deletions
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 63bde5f959..e223bc0da7 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -49,6 +49,7 @@ DEFINE_MANAGED_VTABLE(CallContext); DEFINE_MANAGED_VTABLE(WithContext); DEFINE_MANAGED_VTABLE(CatchContext); DEFINE_MANAGED_VTABLE(GlobalContext); +DEFINE_MANAGED_VTABLE(QmlContext); Heap::CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData) { @@ -91,16 +92,12 @@ Heap::CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName, return d()->engine->memoryManager->alloc<CatchContext>(d()->engine, exceptionVarName, exceptionValue); } -Heap::CallContext *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml) +Heap::QmlContext *ExecutionContext::newQmlContext(Object *qml) { - Scope scope(this); - Scoped<CallContext> c(scope, d()->engine->memoryManager->allocManaged<CallContext>(requiredMemoryForExecutionContect(f, 0))); - new (c->d()) Heap::CallContext(d()->engine, qml, f); - return c->d(); + return d()->engine->memoryManager->alloc<QmlContext>(this, qml); } - void ExecutionContext::createMutableBinding(String *name, bool deletable) { Scope scope(this); @@ -109,13 +106,23 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable) ScopedObject activation(scope, d()->engine->globalObject); ScopedContext ctx(scope, this); while (ctx) { - if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) { + switch (ctx->d()->type) { + case Heap::ExecutionContext::Type_CallContext: + case Heap::ExecutionContext::Type_SimpleCallContext: { Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d()); if (!c->activation) c->activation = scope.engine->newObject(); activation = c->activation; break; } + case Heap::ExecutionContext::Type_QmlContext: { + Heap::QmlContext *qml = static_cast<Heap::QmlContext *>(ctx->d()); + activation = qml->qml; + break; + } + default: + break; + } ctx = ctx->d()->outer; } @@ -158,30 +165,19 @@ Heap::CatchContext::CatchContext(ExecutionEngine *engine, QV4::String *exception this->exceptionValue = exceptionValue; } -Heap::CallContext::CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function) - : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_QmlContext) +Heap::QmlContext::QmlContext(QV4::ExecutionContext *outer, QV4::Object *qml) + : Heap::ExecutionContext(outer->engine(), Heap::ExecutionContext::Type_QmlContext) { - this->function = function->d(); - callData = reinterpret_cast<CallData *>(this + 1); - callData->tag = QV4::Value::_Integer_Type; - callData->argc = 0; - callData->thisObject = Primitive::undefinedValue(); - strictMode = false; - outer = function->scope(); - - activation = qml->d(); - - if (function->function()) { - compilationUnit = function->function()->compilationUnit; - lookups = compilationUnit->runtimeLookups; - } + callData = parent->callData; + this->outer = outer->d(); + lookups = parent->lookups; + compilationUnit = parent->compilationUnit; - locals = (Value *)(this + 1); - if (function->varCount()) - std::fill(locals, locals + function->varCount(), Primitive::undefinedValue()); + this->qml = qml->d(); } + Identifier * const *CallContext::formals() const { return (d()->function && d()->function->function) ? d()->function->function->internalClass->nameMap.constData() : 0; @@ -210,16 +206,28 @@ bool ExecutionContext::deleteProperty(String *name) bool hasWith = false; ScopedContext ctx(scope, this); for (; ctx; ctx = ctx->d()->outer) { - if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) { + switch (ctx->d()->type) { + case Heap::ExecutionContext::Type_CatchContext: { + Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d()); + if (c->exceptionVarName->isEqualTo(name->d())) + return false; + break; + } + case Heap::ExecutionContext::Type_WithContext: { hasWith = true; ScopedObject withObject(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject); if (withObject->hasProperty(name)) return withObject->deleteProperty(name); - } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) { - Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d()); - if (c->exceptionVarName->isEqualTo(name->d())) - return false; - } else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) { + break; + } + case Heap::ExecutionContext::Type_GlobalContext: { + ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global); + if (global->hasProperty(name)) + return global->deleteProperty(name); + break; + } + case Heap::ExecutionContext::Type_CallContext: + case Heap::ExecutionContext::Type_SimpleCallContext: { Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d()); ScopedFunctionObject f(scope, c->function); if (f->needsActivation() || hasWith) { @@ -228,13 +236,14 @@ bool ExecutionContext::deleteProperty(String *name) // ### throw in strict mode? return false; } - ScopedObject activation(scope, c->activation); - if (activation && activation->hasProperty(name)) - return activation->deleteProperty(name); - } else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) { - ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global); - if (global->hasProperty(name)) - return global->deleteProperty(name); + ScopedObject qml(scope, c->activation); + if (qml && qml->hasProperty(name)) + return qml->deleteProperty(name); + break; + } + case Heap::ExecutionContext::Type_QmlContext: + // can't delete properties on qml objects + break; } } @@ -255,7 +264,27 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine) if (ctx->outer) ctx->outer->mark(engine); - if (ctx->type >= Heap::ExecutionContext::Type_CallContext) { + switch (ctx->type) { + case Heap::ExecutionContext::Type_CatchContext: { + CatchContext::Data *c = static_cast<CatchContext::Data *>(ctx); + c->exceptionVarName->mark(engine); + c->exceptionValue.mark(engine); + break; + } + case Heap::ExecutionContext::Type_WithContext: { + WithContext::Data *w = static_cast<WithContext::Data *>(ctx); + if (w->withObject) + w->withObject->mark(engine); + break; + } + case Heap::ExecutionContext::Type_GlobalContext: { + GlobalContext::Data *g = static_cast<GlobalContext::Data *>(ctx); + g->global->mark(engine); + break; + } + case Heap::ExecutionContext::Type_SimpleCallContext: + break; + case Heap::ExecutionContext::Type_CallContext: { QV4::Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx); ctx->callData->thisObject.mark(engine); for (int arg = 0; arg < qMax(ctx->callData->argc, (int)c->function->formalParameterCount()); ++arg) @@ -265,17 +294,13 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine) if (c->activation) c->activation->mark(engine); c->function->mark(engine); - } else if (ctx->type == Heap::ExecutionContext::Type_WithContext) { - WithContext::Data *w = static_cast<WithContext::Data *>(ctx); - if (w->withObject) - w->withObject->mark(engine); - } else if (ctx->type == Heap::ExecutionContext::Type_CatchContext) { - CatchContext::Data *c = static_cast<CatchContext::Data *>(ctx); - c->exceptionVarName->mark(engine); - c->exceptionValue.mark(engine); - } else if (ctx->type == Heap::ExecutionContext::Type_GlobalContext) { - GlobalContext::Data *g = static_cast<GlobalContext::Data *>(ctx); - g->global->mark(engine); + break; + } + case Heap::ExecutionContext::Type_QmlContext: { + QmlContext::Data *g = static_cast<QmlContext::Data *>(ctx); + g->qml->mark(engine); + break; + } } } @@ -283,51 +308,65 @@ void ExecutionContext::setProperty(String *name, const Value &value) { Scope scope(this); ScopedContext ctx(scope, this); + ScopedObject activation(scope); + for (; ctx; ctx = ctx->d()->outer) { - if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) { + activation = (Object *)0; + switch (ctx->d()->type) { + case Heap::ExecutionContext::Type_CatchContext: { + Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d()); + if (c->exceptionVarName->isEqualTo(name->d())) { + c->exceptionValue = value; + return; + } + break; + } + case Heap::ExecutionContext::Type_WithContext: { ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject); if (w->hasProperty(name)) { w->put(name, value); return; } - } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext && static_cast<Heap::CatchContext *>(ctx->d())->exceptionVarName->isEqualTo(name->d())) { - static_cast<Heap::CatchContext *>(ctx->d())->exceptionValue = value; - return; - } else { - ScopedObject activation(scope, (Object *)0); - if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) { - Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d()); - if (c->function->function) { - uint index = c->function->function->internalClass->find(name); - if (index < UINT_MAX) { - if (index < c->function->formalParameterCount()) { - c->callData->args[c->function->formalParameterCount() - index - 1] = value; - } else { - index -= c->function->formalParameterCount(); - c->locals[index] = value; - } - return; + break; + } + case Heap::ExecutionContext::Type_GlobalContext: { + activation = static_cast<Heap::GlobalContext *>(ctx->d())->global; + break; + } + case Heap::ExecutionContext::Type_CallContext: + case Heap::ExecutionContext::Type_SimpleCallContext: { + Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d()); + if (c->function->function) { + uint index = c->function->function->internalClass->find(name); + if (index < UINT_MAX) { + if (index < c->function->formalParameterCount()) { + c->callData->args[c->function->formalParameterCount() - index - 1] = value; + } else { + index -= c->function->formalParameterCount(); + c->locals[index] = value; } + return; } - activation = c->activation; - } else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) { - activation = static_cast<Heap::GlobalContext *>(ctx->d())->global; } + activation = c->activation; + break; + } + case Heap::ExecutionContext::Type_QmlContext: { + activation = static_cast<Heap::QmlContext *>(ctx->d())->qml; + activation->put(name, value); + return; + } + } - if (activation) { - if (ctx->d()->type == Heap::ExecutionContext::Type_QmlContext) { - activation->put(name, value); - return; - } else { - uint member = activation->internalClass()->find(name); - if (member < UINT_MAX) { - activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value); - return; - } - } + if (activation) { + uint member = activation->internalClass()->find(name); + if (member < UINT_MAX) { + activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value); + return; } } } + if (d()->strictMode || name->equals(d()->engine->id_this())) { ScopedValue n(scope, name->asReturnedValue()); engine()->throwReferenceError(n); @@ -349,7 +388,15 @@ ReturnedValue ExecutionContext::getProperty(String *name) bool hasCatchScope = false; ScopedContext ctx(scope, this); for (; ctx; ctx = ctx->d()->outer) { - if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) { + switch (ctx->d()->type) { + case Heap::ExecutionContext::Type_CatchContext: { + hasCatchScope = true; + Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d()); + if (c->exceptionVarName->isEqualTo(name->d())) + return c->exceptionValue.asReturnedValue(); + break; + } + case Heap::ExecutionContext::Type_WithContext: { ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject); hasWith = true; bool hasProperty = false; @@ -357,17 +404,18 @@ ReturnedValue ExecutionContext::getProperty(String *name) if (hasProperty) { return v->asReturnedValue(); } - continue; + break; } - - else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) { - hasCatchScope = true; - Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d()); - if (c->exceptionVarName->isEqualTo(name->d())) - return c->exceptionValue.asReturnedValue(); + case Heap::ExecutionContext::Type_GlobalContext: { + ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global); + bool hasProperty = false; + v = global->get(name, &hasProperty); + if (hasProperty) + return v->asReturnedValue(); + break; } - - else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) { + case Heap::ExecutionContext::Type_CallContext: + case Heap::ExecutionContext::Type_SimpleCallContext: { Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d()); ScopedFunctionObject f(scope, c->function); if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) { @@ -388,14 +436,16 @@ ReturnedValue ExecutionContext::getProperty(String *name) if (f->function() && f->function()->isNamedExpression() && name->equals(ScopedString(scope, f->function()->name()))) return f.asReturnedValue(); + break; } - - else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) { - ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global); + case Heap::ExecutionContext::Type_QmlContext: { + ScopedObject qml(scope, static_cast<Heap::QmlContext *>(ctx->d())->qml); bool hasProperty = false; - v = global->get(name, &hasProperty); + v = qml->get(name, &hasProperty); if (hasProperty) return v->asReturnedValue(); + break; + } } } ScopedValue n(scope, name); @@ -416,7 +466,15 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Heap::Object ** bool hasCatchScope = false; ScopedContext ctx(scope, this); for (; ctx; ctx = ctx->d()->outer) { - if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) { + switch (ctx->d()->type) { + case Heap::ExecutionContext::Type_CatchContext: { + hasCatchScope = true; + Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d()); + if (c->exceptionVarName->isEqualTo(name->d())) + return c->exceptionValue.asReturnedValue(); + break; + } + case Heap::ExecutionContext::Type_WithContext: { ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject); hasWith = true; bool hasProperty = false; @@ -425,48 +483,50 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Heap::Object ** *base = w->d(); return v->asReturnedValue(); } - continue; + break; } - - else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) { - hasCatchScope = true; - Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d()); - if (c->exceptionVarName->isEqualTo(name->d())) - return c->exceptionValue.asReturnedValue(); + case Heap::ExecutionContext::Type_GlobalContext: { + ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global); + bool hasProperty = false; + v = global->get(name, &hasProperty); + if (hasProperty) + return v->asReturnedValue(); + break; } - - else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) { + case Heap::ExecutionContext::Type_CallContext: + case Heap::ExecutionContext::Type_SimpleCallContext: { Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d()); ScopedFunctionObject f(scope, c->function); if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) { uint index = f->function()->internalClass->find(name); if (index < UINT_MAX) { - if (index < f->formalParameterCount()) - return c->callData->args[f->formalParameterCount() - index - 1].asReturnedValue(); - return c->locals[index - f->formalParameterCount()].asReturnedValue(); + if (index < c->function->formalParameterCount()) + return c->callData->args[c->function->formalParameterCount() - index - 1].asReturnedValue(); + return c->locals[index - c->function->formalParameterCount()].asReturnedValue(); } } ScopedObject activation(scope, c->activation); if (activation) { bool hasProperty = false; v = activation->get(name, &hasProperty); - if (hasProperty) { - if (ctx->d()->type == Heap::ExecutionContext::Type_QmlContext) - *base = activation->d(); + if (hasProperty) return v->asReturnedValue(); - } } if (f->function() && f->function()->isNamedExpression() && name->equals(ScopedString(scope, f->function()->name()))) - return c->function->asReturnedValue(); + return f.asReturnedValue(); + break; } - - else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) { - ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global); + case Heap::ExecutionContext::Type_QmlContext: { + ScopedObject qml(scope, static_cast<Heap::QmlContext *>(ctx->d())->qml); bool hasProperty = false; - v = global->get(name, &hasProperty); - if (hasProperty) + v = qml->get(name, &hasProperty); + if (hasProperty) { + *base = qml->d(); return v->asReturnedValue(); + } + break; + } } } ScopedValue n(scope, name); diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index c35263ba7e..1a84097e14 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -75,9 +75,9 @@ struct ExecutionContext : Base { Type_GlobalContext = 0x1, Type_CatchContext = 0x2, Type_WithContext = 0x3, - Type_SimpleCallContext = 0x4, - Type_CallContext = 0x5, - Type_QmlContext = 0x6 + Type_QmlContext = 0x4, + Type_SimpleCallContext = 0x5, + Type_CallContext = 0x6 }; inline ExecutionContext(ExecutionEngine *engine, ContextType t); @@ -103,7 +103,6 @@ struct CallContext : ExecutionContext { locals = 0; activation = 0; } - CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function); Pointer<FunctionObject> function; Value *locals; @@ -126,6 +125,10 @@ struct WithContext : ExecutionContext { Pointer<Object> withObject; }; +struct QmlContext : ExecutionContext { + QmlContext(QV4::ExecutionContext *outer, QV4::Object *qml); + Pointer<Object> qml; +}; } @@ -143,7 +146,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed Heap::CallContext *newCallContext(FunctionObject *f, CallData *callData); Heap::WithContext *newWithContext(Object *with); Heap::CatchContext *newCatchContext(String *exceptionVarName, const Value &exceptionValue); - Heap::CallContext *newQmlContext(FunctionObject *f, Object *qml); + Heap::QmlContext *newQmlContext(Object *qml); void createMutableBinding(String *name, bool deletable); @@ -209,6 +212,11 @@ struct WithContext : public ExecutionContext V4_MANAGED(WithContext, ExecutionContext) }; +struct QmlContext : public ExecutionContext +{ + V4_MANAGED(QmlContext, ExecutionContext) +}; + inline CallContext *ExecutionContext::asCallContext() { return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<CallContext *>(this) : 0; diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp index cd9e1e3936..7bd5d49f3c 100644 --- a/src/qml/jsruntime/qv4debugging.cpp +++ b/src/qml/jsruntime/qv4debugging.cpp @@ -498,7 +498,7 @@ QVector<Heap::ExecutionContext::ContextType> Debugger::getScopeTypes(int frame) Scope scope(m_engine); Scoped<CallContext> sctxt(scope, findContext(m_engine->currentContext(), frame)); - if (!sctxt || sctxt->d()->type < Heap::ExecutionContext::Type_SimpleCallContext) + if (!sctxt || sctxt->d()->type < Heap::ExecutionContext::Type_QmlContext) return types; ScopedContext it(scope, sctxt->d()); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 2ac56f52c5..3d541e53a3 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -737,8 +737,8 @@ Heap::Object *ExecutionEngine::qmlContextObject() const if (ctx->type != Heap::ExecutionContext::Type_QmlContext) return 0; - Q_ASSERT(static_cast<Heap::CallContext *>(ctx)->activation); - return static_cast<Heap::CallContext *>(ctx)->activation; + Q_ASSERT(static_cast<Heap::QmlContext *>(ctx)->qml); + return static_cast<Heap::QmlContext *>(ctx)->qml; } QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 622610ade3..d8cdda477a 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -457,7 +457,7 @@ ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData) ScopedValue result(scope, Q_V4_PROFILE(v4, f->function())); if (f->function()->compiledFunction->hasQmlDependencies()) - QmlContextWrapper::registerQmlDependencies(ctx->d()->engine, f->function()->compiledFunction); + QmlContextWrapper::registerQmlDependencies(scope.engine, f->function()->compiledFunction); return result->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 6d7aeafb77..f794bdca6f 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1240,7 +1240,7 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value * QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionEngine *engine) { - Q_ASSERT(engine->currentContext()->type >= Heap::ExecutionContext::Type_CallContext); + Q_ASSERT(engine->currentContext()->type == Heap::ExecutionContext::Type_CallContext); Scope scope(engine); Scoped<CallContext> c(scope, static_cast<Heap::CallContext *>(engine->currentContext())); return (engine->memoryManager->alloc<ArgumentsObject>(c))->asReturnedValue(); diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 33efed8e70..c7dd28e795 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -44,6 +44,7 @@ #include <private/qqmljsparser_p.h> #include <private/qqmljsast_p.h> #include <private/qqmlengine_p.h> +#include <private/qv4profiling_p.h> #include <qv4jsir_p.h> #include <qv4codegen_p.h> #include <private/qqmlcontextwrapper_p.h> @@ -101,8 +102,7 @@ Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Functio o->defineReadonlyProperty(scope->d()->engine->id_length(), Primitive::fromInt32(1)); - ScopedContext ctx(s, s.engine->currentContext()); - o->d()->qmlContext = ctx->newQmlContext(o, qml); + o->d()->scope = ScopedContext(s, o->scope())->newQmlContext(qml); s.engine->popContext(); } @@ -117,26 +117,28 @@ Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Ob o->defineReadonlyProperty(scope->d()->engine->id_length(), Primitive::fromInt32(1)); - ScopedContext ctx(s, s.engine->currentContext()); - o->d()->qmlContext = ctx->newQmlContext(o, qml); + o->d()->scope = ScopedContext(s, o->scope())->newQmlContext(qml); s.engine->popContext(); } -ReturnedValue QmlBindingWrapper::call(const Managed *that, CallData *) +ReturnedValue QmlBindingWrapper::call(const Managed *that, CallData *callData) { - ExecutionEngine *engine = static_cast<const Object *>(that)->engine(); - CHECK_STACK_LIMITS(engine); + ExecutionEngine *v4 = static_cast<const Object *>(that)->engine(); + if (v4->hasException) + return Encode::undefined(); + CHECK_STACK_LIMITS(v4); - Scope scope(engine); - const QmlBindingWrapper *This = static_cast<const QmlBindingWrapper *>(that); - if (!This->function()) + Scope scope(v4); + Scoped<QmlBindingWrapper> This(scope, static_cast<const QmlBindingWrapper *>(that)); + QV4::Function *f = This->function(); + if (!f) return QV4::Encode::undefined(); - Scoped<CallContext> ctx(scope, This->d()->qmlContext); - std::fill(ctx->d()->locals, ctx->d()->locals + ctx->d()->function->varCount(), Primitive::undefinedValue()); - engine->pushContext(ctx); - ScopedValue result(scope, This->function()->code(engine, This->function()->codeData)); - engine->popContext(); + ScopedContext context(scope, v4->currentContext()); + Scoped<CallContext> ctx(scope, context->newCallContext(This, callData)); + + ExecutionContextSaver ctxSaver(scope, context); + ScopedValue result(scope, Q_V4_PROFILE(v4, f)); return result->asReturnedValue(); } @@ -147,8 +149,6 @@ void QmlBindingWrapper::markObjects(Heap::Base *m, ExecutionEngine *e) if (wrapper->qml) wrapper->qml->mark(e); FunctionObject::markObjects(m, e); - if (wrapper->qmlContext) - wrapper->qmlContext->mark(e); } static ReturnedValue signalParameterGetter(QV4::CallContext *ctx, uint parameterIndex) @@ -166,7 +166,7 @@ Heap::FunctionObject *QmlBindingWrapper::createQmlCallableForFunction(QQmlContex QV4::ScopedObject qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine, qmlContext, scopeObject)); ScopedContext global(valueScope, valueScope.engine->rootContext()); QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, engine->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScopeObject)); - QV4::Scoped<CallContext> wrapperContext(valueScope, wrapper->context()); + QV4::Scoped<QmlContext> wrapperContext(valueScope, wrapper->context()); if (!signalParameters.isEmpty()) { if (error) diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h index 59a589a624..4c8644e8c2 100644 --- a/src/qml/jsruntime/qv4script_p.h +++ b/src/qml/jsruntime/qv4script_p.h @@ -91,7 +91,6 @@ struct QmlBindingWrapper : Heap::FunctionObject { // Constructor for QML functions and signal handlers, resulting binding wrapper is not callable! QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Object *qml); Pointer<Object> qml; - Pointer<CallContext> qmlContext; }; } @@ -99,10 +98,10 @@ struct QmlBindingWrapper : Heap::FunctionObject { struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject { V4_OBJECT2(QmlBindingWrapper, FunctionObject) - static ReturnedValue call(const Managed *that, CallData *); + static ReturnedValue call(const Managed *that, CallData *callData); static void markObjects(Heap::Base *m, ExecutionEngine *e); - Heap::CallContext *context() const { return d()->qmlContext; } + Heap::QmlContext *context() const { return static_cast<Heap::QmlContext *>(d()->scope.ptr); } static Heap::FunctionObject *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction, const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0); |