diff options
-rw-r--r-- | src/qml/jsruntime/qv4referenceobject_p.h | 30 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject.cpp | 11 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper.cpp | 8 |
4 files changed, 45 insertions, 8 deletions
diff --git a/src/qml/jsruntime/qv4referenceobject_p.h b/src/qml/jsruntime/qv4referenceobject_p.h index 3dfea409db..61b8f02206 100644 --- a/src/qml/jsruntime/qv4referenceobject_p.h +++ b/src/qml/jsruntime/qv4referenceobject_p.h @@ -32,6 +32,7 @@ DECLARE_HEAP_OBJECT(ReferenceObject, Object) { NoFlag = 0, CanWriteBack = 1 << 0, IsVariant = 1 << 1, + EnforcesLocation = 1 << 2, }; Q_DECLARE_FLAGS(Flags, Flag); @@ -59,6 +60,33 @@ DECLARE_HEAP_OBJECT(ReferenceObject, Object) { void setIsVariant(bool isVariant) { setFlag(IsVariant, isVariant); } bool isVariant() const { return hasFlag(IsVariant); } + + void setEnforcesLocation(bool enforces) { setFlag(EnforcesLocation, enforces); } + bool enforcesLocation() const { return hasFlag(EnforcesLocation); } + + void setLocation(const Function *function, quint16 statement) + { + m_function = function; + m_statementIndex = statement; + } + + const Function *function() const { return m_function; } + quint16 statementIndex() const { return m_statementIndex; } + + bool isAttachedToProperty() const + { + if (enforcesLocation()) { + if (CppStackFrame *frame = internalClass->engine->currentStackFrame) { + if (frame->v4Function != function() || frame->statementNumber() != statementIndex()) + return false; + } else { + return false; + } + } + + return true; + } + bool isReference() const { return m_property >= 0; } private: @@ -74,7 +102,9 @@ private: } QV4QPointer<QObject> m_object; + const Function *m_function; int m_property; + quint16 m_statementIndex; quint8 m_flags; }; diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 2558e376b5..6aadf68c05 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -162,6 +162,8 @@ void Heap::Sequence::init( QV4::Scope scope(internalClass->engine); QV4::Scoped<QV4::Sequence> o(scope, this); o->setArrayType(Heap::ArrayData::Custom); + if (CppStackFrame *frame = scope.engine->currentStackFrame) + setLocation(frame->v4Function, frame->statementNumber()); o->loadReference(); } @@ -422,18 +424,19 @@ bool Sequence::sort(const FunctionObject *f, const Value *, const Value *argv, i void *Sequence::getRawContainerPtr() const { return d()->storagePointer(); } -void Sequence::loadReference() const +bool Sequence::loadReference() const { Q_ASSERT(d()->object()); Q_ASSERT(d()->isReference()); - QV4::ReferenceObject::readReference(d()); + // If locations are enforced we only read once + return d()->enforcesLocation() || QV4::ReferenceObject::readReference(d()); } -void Sequence::storeReference() +bool Sequence::storeReference() { Q_ASSERT(d()->object()); Q_ASSERT(d()->isReference()); - QV4::ReferenceObject::writeBack(d()); + return d()->isAttachedToProperty() && QV4::ReferenceObject::writeBack(d()); } ReturnedValue Sequence::virtualGet(const Managed *that, PropertyKey id, const Value *receiver, bool *hasProperty) diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h index 6d0a85ded6..f6055e38e3 100644 --- a/src/qml/jsruntime/qv4sequenceobject_p.h +++ b/src/qml/jsruntime/qv4sequenceobject_p.h @@ -100,8 +100,8 @@ public: bool containerIsEqualTo(Managed *other); bool sort(const FunctionObject *f, const Value *, const Value *argv, int argc); void *getRawContainerPtr() const; - void loadReference() const; - void storeReference(); + bool loadReference() const; + bool storeReference(); }; } diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 2e7eaf23f8..721917bb6d 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -109,12 +109,13 @@ void *Heap::QQmlValueTypeWrapper::storagePointer() bool Heap::QQmlValueTypeWrapper::readReference() { - return QV4::ReferenceObject::readReference(this); + // If locations are enforced we only read once + return enforcesLocation() || QV4::ReferenceObject::readReference(this); } bool Heap::QQmlValueTypeWrapper::writeBack() { - return QV4::ReferenceObject::writeBack(this); + return isAttachedToProperty() && QV4::ReferenceObject::writeBack(this); } ReturnedValue QQmlValueTypeWrapper::create( @@ -130,6 +131,7 @@ ReturnedValue QQmlValueTypeWrapper::create( r->d()->setMetaObject(cloneFrom->metaObject()); r->d()->setValueType(cloneFrom->valueType()); r->d()->setGadgetPtr(nullptr); + r->d()->setLocation(cloneFrom->function(), cloneFrom->statementIndex()); return r->asReturnedValue(); } @@ -160,6 +162,8 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj } r->d()->setValueType(valueType); r->d()->setGadgetPtr(nullptr); + if (CppStackFrame *frame = engine->currentStackFrame) + r->d()->setLocation(frame->v4Function, frame->statementNumber()); return r->asReturnedValue(); } |