diff options
author | Matthew Vogt <matthew.vogt@nokia.com> | 2012-08-17 11:10:10 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-08-17 03:53:42 +0200 |
commit | 13ae2db97e6d7714fecffc4d65bb785a734fcd35 (patch) | |
tree | 6d7e69ba56068c844dac2d2c0d77e23da3a1e026 | |
parent | 625c192f54834a5ff5944ecb76f719543f901824 (diff) |
Reduce memory consumption in QV4Bindings::Binding
As with QV8Bindings::Binding, access details from the QML IR
instruction object rather than storing a copy of the values.
Change-Id: I2b629ee1b06ed74c7b38e6d047ef6a98acd45086
Reviewed-by: Martin Jones <martin.jones@nokia.com>
-rw-r--r-- | src/qml/qml/qqmlcompiler.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlvme.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4bindings.cpp | 75 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4bindings_p.h | 34 |
4 files changed, 54 insertions, 64 deletions
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp index 808e63388f..3805e98802 100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@ -3664,9 +3664,6 @@ bool QQmlCompiler::completeComponentBuild() bool needsFallback = false; int index = bindingCompiler.compile(expr, enginePrivate, &needsFallback); if (index != -1) { - // Ensure the index value fits within the available space - Q_ASSERT(index < (1 << 15)); - binding.dataType = BindingReference::V4; binding.compiledIndex = index; binding.sharedIndex = -1; @@ -3736,8 +3733,6 @@ bool QQmlCompiler::completeComponentBuild() functionArray += expression.toUtf8(); lineNumber += expression.count(QLatin1Char('\n')); - // Ensure the index value fits within the available space - Q_ASSERT(ii < (1 << 15)); reference->sharedIndex = ii; } functionArray.append("]", 1); diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index d6b60f724c..e565321eb9 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -846,9 +846,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, if (instr.isRoot && BINDINGSKIPLIST.testBit(propertyIdx)) QML_NEXT_INSTR(StoreV4Binding); - QQmlAbstractBinding *binding = - CTXT->v4bindings->configBinding(instr.value, instr.fallbackValue, target, scope, instr.property, - instr.propType, instr.line, instr.column); + QQmlAbstractBinding *binding = CTXT->v4bindings->configBinding(target, scope, &instr); bindValues.push(binding); binding->m_mePtr = &bindValues.top(); diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp index 643a6197fb..fb484546a2 100644 --- a/src/qml/qml/v4/qv4bindings.cpp +++ b/src/qml/qml/v4/qv4bindings.cpp @@ -298,21 +298,14 @@ QV4Bindings::~QV4Bindings() delete [] subscriptions; subscriptions = 0; } -QQmlAbstractBinding *QV4Bindings::configBinding(int index, int fallbackIndex, QObject *target, QObject *scope, - int property, int propType, quint16 line, quint16 column) +QQmlAbstractBinding *QV4Bindings::configBinding(QObject *target, QObject *scope, + const QQmlInstruction::instr_assignV4Binding *i) { - Q_ASSERT(propType <= std::numeric_limits<quint16>::max()); + Binding *rv = bindings + i->value; - Binding *rv = bindings + index; - - rv->index = index; - rv->fallbackIndex = fallbackIndex; - rv->property = property; - rv->propType = propType; + rv->instruction = i; rv->target = target; rv->scope = scope; - rv->line = line; - rv->column = column; rv->parent = this; addref(); // This is decremented in Binding::destroy() @@ -325,8 +318,8 @@ void QV4Bindings::Binding::setEnabled(QQmlAbstractBinding *_This, { QV4Bindings::Binding *This = static_cast<QV4Bindings::Binding *>(_This); - if (This->enabled != e) { - This->enabled = e; + if (This->enabledFlag() != e) { + This->setEnabledFlag(e); if (e) update(_This, flags); } @@ -342,7 +335,7 @@ void QV4Bindings::Binding::destroy(QQmlAbstractBinding *_This) { QV4Bindings::Binding *This = static_cast<QV4Bindings::Binding *>(_This); - This->enabled = false; + This->setEnabledFlag(false); This->removeFromObject(); This->clear(); This->removeError(); @@ -354,7 +347,7 @@ int QV4Bindings::Binding::propertyIndex(const QQmlAbstractBinding *_This) const QV4Bindings::Binding *This = static_cast<const QV4Bindings::Binding *>(_This); if (This->target.hasValue()) return This->target.constValue()->targetProperty; - else return This->property; + else return This->instruction->property; } QObject *QV4Bindings::Binding::object(const QQmlAbstractBinding *_This) @@ -402,7 +395,7 @@ void QV4Bindings::subscriptionNotify(int id) void QV4Bindings::run(Binding *binding, QQmlPropertyPrivate::WriteFlags flags) { - if (!binding->enabled) + if (!binding->enabledFlag()) return; QQmlContextData *context = QQmlAbstractExpression::context(); @@ -415,62 +408,68 @@ void QV4Bindings::run(Binding *binding, QQmlPropertyPrivate::WriteFlags flags) QQmlTrace trace("V4 Binding Update"); trace.addDetail("URL", context->url); - trace.addDetail("Line", binding->line); - trace.addDetail("Column", binding->column); + trace.addDetail("Line", binding->instruction->line); + trace.addDetail("Column", binding->instruction->column); + + QQmlBindingProfiler prof(context->urlString, binding->instruction->line, binding->instruction->column, QQmlProfilerService::V4Binding); - QQmlBindingProfiler prof(context->urlString, binding->line, binding->column, QQmlProfilerService::V4Binding); + const int propType = binding->instruction->propType; + const int property = binding->instruction->property; - if (binding->updating) { + if (binding->updatingFlag()) { QString name; - if (binding->propType) { - QQmlValueType *vt = QQmlValueTypeFactory::valueType(binding->propType); + if (propType) { + QQmlValueType *vt = QQmlValueTypeFactory::valueType(propType); Q_ASSERT(vt); - name = QLatin1String(binding->target->metaObject()->property(binding->property & 0x0000FFFF).name()); + name = QLatin1String(binding->target->metaObject()->property(property & 0x0000FFFF).name()); name.append(QLatin1Char('.')); - name.append(QLatin1String(vt->metaObject()->property(binding->property >> 16).name())); + name.append(QLatin1String(vt->metaObject()->property(property >> 16).name())); } else { - name = QLatin1String(binding->target->metaObject()->property(binding->property).name()); + name = QLatin1String(binding->target->metaObject()->property(property).name()); } qmlInfo(*binding->target) << tr("Binding loop detected for property \"%1\"").arg(name); return; } + int index = binding->instruction->value; + int fallbackIndex = binding->instruction->fallbackValue; + bool invalidated = false; - bool *inv = (binding->fallbackIndex != -1) ? &invalidated : 0; + bool *inv = (fallbackIndex != -1) ? &invalidated : 0; - binding->updating = true; - if (binding->propType) { - QQmlValueType *vt = QQmlValueTypeFactory::valueType(binding->propType); + binding->setUpdatingFlag(true); + if (propType) { + QQmlValueType *vt = QQmlValueTypeFactory::valueType(propType); Q_ASSERT(vt); - vt->read(*binding->target, binding->property & 0x0000FFFF); + vt->read(*binding->target, property & 0x0000FFFF); QObject *target = vt; - run(binding->index, binding->executedBlocks, context, binding, binding->scope, target, flags, inv); + run(index, binding->executedBlocks, context, binding, binding->scope, target, flags, inv); if (!invalidated) { - vt->write(*binding->target, binding->property & 0x0000FFFF, flags); + vt->write(*binding->target, property & 0x0000FFFF, flags); } } else { QQmlData *data = QQmlData::get(*binding->target); - QQmlPropertyData *propertyData = (data && data->propertyCache ? data->propertyCache->property(binding->property) : 0); + QQmlPropertyData *propertyData = (data && data->propertyCache ? data->propertyCache->property(property) : 0); if (propertyData && propertyData->isVarProperty()) { // We will allocate a V8 handle in this conversion/store v8::HandleScope handle_scope; v8::Context::Scope context_scope(QQmlEnginePrivate::get(context->engine)->v8engine()->context()); - run(binding->index, binding->executedBlocks, context, binding, binding->scope, *binding->target, flags, inv); + run(index, binding->executedBlocks, context, binding, binding->scope, *binding->target, flags, inv); } else { - run(binding->index, binding->executedBlocks, context, binding, binding->scope, *binding->target, flags, inv); + run(index, binding->executedBlocks, context, binding, binding->scope, *binding->target, flags, inv); } } - binding->updating = false; + binding->setUpdatingFlag(false); if (invalidated) { // This binding is no longer valid - fallback to V8 - Q_ASSERT(binding->fallbackIndex > -1); - QQmlAbstractBinding *b = QQmlPropertyPrivate::activateSharedBinding(context, binding->fallbackIndex, flags); + Q_ASSERT(fallbackIndex > -1); + QQmlAbstractBinding *b = QQmlPropertyPrivate::activateSharedBinding(context, fallbackIndex, flags); Q_ASSERT(b == binding); b->destroy(); } diff --git a/src/qml/qml/v4/qv4bindings_p.h b/src/qml/qml/v4/qv4bindings_p.h index eae5703c50..0553e575a5 100644 --- a/src/qml/qml/v4/qv4bindings_p.h +++ b/src/qml/qml/v4/qv4bindings_p.h @@ -55,6 +55,7 @@ #include "private/qqmlexpression_p.h" #include "private/qqmlbinding_p.h" +#include "private/qqmlinstruction_p.h" #include "private/qv4instruction_p.h" #include "private/qpointervaluepair_p.h" @@ -71,17 +72,16 @@ public: QV4Bindings(const char *program, QQmlContextData *context); virtual ~QV4Bindings(); - QQmlAbstractBinding *configBinding(int index, int fallbackIndex, QObject *target, - QObject *scope, int property, int propType, - quint16 line, quint16 column); + QQmlAbstractBinding *configBinding(QObject *target, QObject *scope, + const QQmlInstruction::instr_assignV4Binding *); #ifdef QML_THREADED_INTERPRETER static void **getDecodeInstrTable(); #endif struct Binding : public QQmlAbstractBinding, public QQmlDelayedError { - Binding() : QQmlAbstractBinding(V4), index(-1), fallbackIndex(-1), enabled(false), - updating(0), property(0), propType(0), scope(0), target(0), executedBlocks(0), parent(0) {} + Binding() + : QQmlAbstractBinding(V4), target(0), scope(0), instruction(0), executedBlocks(0), parent(0) {} // Inherited from QQmlAbstractBinding static void destroy(QQmlAbstractBinding *); @@ -96,23 +96,21 @@ public: int targetProperty; }; - int index:15; - int fallbackIndex:15; - bool enabled:1; - bool updating:1; + QPointerValuePair<QObject, Retarget> target; + QObject *scope; - // Encoding of property is: coreIndex | (valueTypeIndex << 16) - // propType and valueTypeIndex are only set if the property is a value type property - int property; - quint16 propType; + // To save memory, we store flags inside the instruction pointer. + // instruction.flag1: enabled + // instruction.flag2: updating + QFlagPointer<const QQmlInstruction::instr_assignV4Binding> instruction; - QObject *scope; - quint16 line; - quint16 column; - QPointerValuePair<QObject, Retarget> target; quint32 executedBlocks; - QV4Bindings *parent; + + inline bool enabledFlag() const { return instruction.flag(); } + inline void setEnabledFlag(bool v) { instruction.setFlagValue(v); } + inline bool updatingFlag() const { return instruction.flag2(); } + inline void setUpdatingFlag(bool v) { instruction.setFlag2Value(v); } }; private: |