From 12d8004874c3f69ddd5aa7622da309c46930336b Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 26 Aug 2016 16:11:38 +0200 Subject: Fix binding dependencies when used in together with functions When a function called from a binding would access a scope or context property, we would end up registering those dependencies as permanent dependencies in the expression and set m_permanentDependenciesRegistered to true. Then after the binding evaluation itself, we would not end up registering the real binding's permanent dependencies. Change-Id: I3b6c1c181aa064d535362c736b5b2bbc4f576ba9 Done-with: Erik Task-number: QTBUG-54394 Reviewed-by: Erik Verbruggen --- src/qml/compiler/qv4instr_moth_p.h | 2 ++ src/qml/compiler/qv4isel_moth.cpp | 4 +++- src/qml/compiler/qv4isel_moth_p.h | 2 +- src/qml/compiler/qv4isel_p.cpp | 6 +++--- src/qml/compiler/qv4isel_p.h | 2 +- src/qml/jit/qv4isel_masm.cpp | 6 +++--- src/qml/jit/qv4isel_masm_p.h | 2 +- src/qml/jit/qv4regalloc.cpp | 2 +- src/qml/jsruntime/qv4runtime.cpp | 16 ++++++++-------- src/qml/jsruntime/qv4runtimeapi_p.h | 4 ++-- src/qml/jsruntime/qv4vme_moth.cpp | 4 ++-- 11 files changed, 27 insertions(+), 23 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 20b871c4e8..beb43376ee 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -335,12 +335,14 @@ union Instr int propertyIndex; Param base; Param result; + bool captureRequired; }; struct instr_loadContextObjectProperty { MOTH_INSTR_HEADER int propertyIndex; Param base; Param result; + bool captureRequired; }; struct instr_loadIdObject { MOTH_INSTR_HEADER diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index fda5b4cdd0..cd47f22205 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -579,18 +579,20 @@ void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *target addInstruction(store); } -void InstructionSelection::getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target) +void InstructionSelection::getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, bool captureRequired, IR::Expr *target) { if (kind == IR::Member::MemberOfQmlScopeObject) { Instruction::LoadScopeObjectProperty load; load.base = getParam(source); load.propertyIndex = index; + load.captureRequired = captureRequired; load.result = getResultParam(target); addInstruction(load); } else if (kind == IR::Member::MemberOfQmlContextObject) { Instruction::LoadContextObjectProperty load; load.base = getParam(source); load.propertyIndex = index; + load.captureRequired = captureRequired; load.result = getResultParam(target); addInstruction(load); } else if (kind == IR::Member::MemberOfIdObjectsArray) { diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h index 2d2bb91228..c304284cbc 100644 --- a/src/qml/compiler/qv4isel_moth_p.h +++ b/src/qml/compiler/qv4isel_moth_p.h @@ -137,7 +137,7 @@ protected: virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName); virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex); virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex); - virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target); + virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, bool captureRequired, IR::Expr *target); virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target); virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target); virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex); diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp index 72e6c276a9..efcfb9bd77 100644 --- a/src/qml/compiler/qv4isel_p.cpp +++ b/src/qml/compiler/qv4isel_p.cpp @@ -147,7 +147,7 @@ void IRDecoder::visitMove(IR::Move *s) const int attachedPropertiesId = m->attachedPropertiesId; const bool isSingletonProperty = m->kind == IR::Member::MemberOfSingletonObject; - if (_function && attachedPropertiesId == 0 && !m->property->isConstant()) { + if (_function && attachedPropertiesId == 0 && !m->property->isConstant() && _function->isQmlBinding) { if (m->kind == IR::Member::MemberOfQmlContextObject) { _function->contextObjectPropertyDependencies.insert(m->property->coreIndex(), m->property->notifyIndex()); captureRequired = false; @@ -157,14 +157,14 @@ void IRDecoder::visitMove(IR::Move *s) } } if (m->kind == IR::Member::MemberOfQmlScopeObject || m->kind == IR::Member::MemberOfQmlContextObject) { - getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex(), s->target); + getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex(), captureRequired, s->target); return; } getQObjectProperty(m->base, m->property->coreIndex(), captureRequired, isSingletonProperty, attachedPropertiesId, s->target); #endif // V4_BOOTSTRAP return; } else if (m->kind == IR::Member::MemberOfIdObjectsArray) { - getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->idIndex, s->target); + getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->idIndex, /*captureRequired*/false, s->target); return; } else if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) { getProperty(m->base, *m->name, s->target); diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h index a3fa80b6f0..037c02e5ea 100644 --- a/src/qml/compiler/qv4isel_p.h +++ b/src/qml/compiler/qv4isel_p.h @@ -188,7 +188,7 @@ public: // to implement by subclasses: virtual void initClosure(IR::Closure *closure, IR::Expr *target) = 0; virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target) = 0; virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) = 0; - virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target) = 0; + virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, bool captureRequired, IR::Expr *target) = 0; virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName) = 0; virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex) = 0; virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) = 0; diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index 737ff389fa..d06d6907e5 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -737,12 +737,12 @@ void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR:: } } -void InstructionSelection::getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int index, IR::Expr *target) +void InstructionSelection::getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int index, bool captureRequired, IR::Expr *target) { if (kind == IR::Member::MemberOfQmlScopeObject) - generateRuntimeCall(target, getQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index)); + generateRuntimeCall(target, getQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index), Assembler::TrustedImm32(captureRequired)); else if (kind == IR::Member::MemberOfQmlContextObject) - generateRuntimeCall(target, getQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index)); + generateRuntimeCall(target, getQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index), Assembler::TrustedImm32(captureRequired)); else if (kind == IR::Member::MemberOfIdObjectsArray) generateRuntimeCall(target, getQmlIdObject, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index)); else diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index 5bca879a77..88241bd503 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -123,7 +123,7 @@ protected: virtual void setActivationProperty(IR::Expr *source, const QString &targetName); virtual void initClosure(IR::Closure *closure, IR::Expr *target); virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target); - virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target); + virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, bool captureRequired, IR::Expr *target); virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target); virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName); virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex); diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index 350ab7e0c6..406b9096ea 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -528,7 +528,7 @@ protected: // IRDecoder addCall(); } - virtual void getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int /*index*/, IR::Expr *target) + virtual void getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int /*index*/, bool /*captureRequired*/, IR::Expr *target) { addDef(target); addUses(base->asTemp(), Use::CouldHaveRegister); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 9032503fdf..b7a4c4f643 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -988,7 +988,7 @@ ReturnedValue Runtime::method_callActivationProperty(ExecutionEngine *engine, in ReturnedValue Runtime::method_callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData) { Scope scope(engine); - ScopedFunctionObject o(scope, method_getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex)); + ScopedFunctionObject o(scope, method_getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex, /*captureRequired*/true)); if (!o) { QString error = QStringLiteral("Property '%1' of scope object is not a function").arg(propertyIndex); return engine->throwTypeError(error); @@ -1001,7 +1001,7 @@ ReturnedValue Runtime::method_callQmlScopeObjectProperty(ExecutionEngine *engine ReturnedValue Runtime::method_callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData) { Scope scope(engine); - ScopedFunctionObject o(scope, method_getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex)); + ScopedFunctionObject o(scope, method_getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex, /*captureRequired*/true)); if (!o) { QString error = QStringLiteral("Property '%1' of context object is not a function").arg(propertyIndex); return engine->throwTypeError(error); @@ -1209,7 +1209,7 @@ QV4::ReturnedValue Runtime::method_typeofName(ExecutionEngine *engine, int nameI ReturnedValue Runtime::method_typeofScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) { Scope scope(engine); - ScopedValue prop(scope, method_getQmlScopeObjectProperty(engine, context, propertyIndex)); + ScopedValue prop(scope, method_getQmlScopeObjectProperty(engine, context, propertyIndex, /*captureRequired*/true)); if (scope.engine->hasException) return Encode::undefined(); return method_typeofValue(engine, prop); @@ -1218,7 +1218,7 @@ ReturnedValue Runtime::method_typeofScopeObjectProperty(ExecutionEngine *engine, ReturnedValue Runtime::method_typeofContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) { Scope scope(engine); - ScopedValue prop(scope, method_getQmlContextObjectProperty(engine, context, propertyIndex)); + ScopedValue prop(scope, method_getQmlContextObjectProperty(engine, context, propertyIndex, /*captureRequired*/true)); if (scope.engine->hasException) return Encode::undefined(); return method_typeofValue(engine, prop); @@ -1453,16 +1453,16 @@ QV4::ReturnedValue Runtime::method_getQmlAttachedProperty(ExecutionEngine *engin return QV4::QObjectWrapper::getProperty(engine, attachedObject, propertyIndex, /*captureRequired*/true); } -ReturnedValue Runtime::method_getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) +ReturnedValue Runtime::method_getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired) { const QmlContext &c = static_cast(context); - return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->scopeObject, propertyIndex, false); + return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->scopeObject, propertyIndex, captureRequired); } -ReturnedValue Runtime::method_getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) +ReturnedValue Runtime::method_getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired) { const QmlContext &c = static_cast(context); - return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->context->contextObject, propertyIndex, false); + return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->context->contextObject, propertyIndex, captureRequired); } ReturnedValue Runtime::method_getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h index 582cdcf4e9..040a545b83 100644 --- a/src/qml/jsruntime/qv4runtimeapi_p.h +++ b/src/qml/jsruntime/qv4runtimeapi_p.h @@ -327,8 +327,8 @@ struct Q_QML_PRIVATE_EXPORT Runtime { RUNTIME_METHOD(ReturnedValue, getQmlImportedScripts, (NoThrowEngine *engine)); RUNTIME_METHOD(ReturnedValue, getQmlSingleton, (NoThrowEngine *engine, int nameIndex)); RUNTIME_METHOD(ReturnedValue, getQmlAttachedProperty, (ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex)); - RUNTIME_METHOD(ReturnedValue, getQmlScopeObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex)); - RUNTIME_METHOD(ReturnedValue, getQmlContextObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex)); + RUNTIME_METHOD(ReturnedValue, getQmlScopeObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)); + RUNTIME_METHOD(ReturnedValue, getQmlContextObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)); RUNTIME_METHOD(ReturnedValue, getQmlQObjectProperty, (ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)); RUNTIME_METHOD(ReturnedValue, getQmlSingletonQObjectProperty, (ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)); RUNTIME_METHOD(ReturnedValue, getQmlIdObject, (ExecutionEngine *engine, const Value &context, uint index)); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 420abd1458..9d18713253 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -527,7 +527,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(StoreScopeObjectProperty) MOTH_BEGIN_INSTR(LoadScopeObjectProperty) - STOREVALUE(instr.result, engine->runtime.getQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex)); + STOREVALUE(instr.result, engine->runtime.getQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired)); MOTH_END_INSTR(LoadScopeObjectProperty) MOTH_BEGIN_INSTR(StoreContextObjectProperty) @@ -536,7 +536,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(StoreContextObjectProperty) MOTH_BEGIN_INSTR(LoadContextObjectProperty) - STOREVALUE(instr.result, engine->runtime.getQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex)); + STOREVALUE(instr.result, engine->runtime.getQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired)); MOTH_END_INSTR(LoadContextObjectProperty) MOTH_BEGIN_INSTR(LoadIdObject) -- cgit v1.2.3