summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-05-11 01:36:57 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-05-11 01:36:57 (GMT)
commit738fe5730a55279bf3c033bad7317768d81f40af (patch)
tree1b1c8df3ed26aa338008df672529d0aa228c93a0
parentac19c9a30a47bfe8b374d390525b06ebdb26b4ca (diff)
downloadQt-738fe5730a55279bf3c033bad7317768d81f40af.zip
Qt-738fe5730a55279bf3c033bad7317768d81f40af.tar.gz
Qt-738fe5730a55279bf3c033bad7317768d81f40af.tar.bz2
Handle QmlParserStatus's and QmlBindableValeus being deleted during component creation
-rw-r--r--src/declarative/qml/qmlbindablevalue.cpp5
-rw-r--r--src/declarative/qml/qmlbindablevalue_p.h2
-rw-r--r--src/declarative/qml/qmlcompiler.cpp25
-rw-r--r--src/declarative/qml/qmlcomponent.cpp40
-rw-r--r--src/declarative/qml/qmlcomponent_p.h7
-rw-r--r--src/declarative/qml/qmlengine.cpp29
-rw-r--r--src/declarative/qml/qmlengine_p.h31
-rw-r--r--src/declarative/qml/qmlinstruction_p.h2
-rw-r--r--src/declarative/qml/qmlparserstatus.cpp12
-rw-r--r--src/declarative/qml/qmlparserstatus.h7
-rw-r--r--src/declarative/qml/qmlvme.cpp35
11 files changed, 164 insertions, 31 deletions
diff --git a/src/declarative/qml/qmlbindablevalue.cpp b/src/declarative/qml/qmlbindablevalue.cpp
index 3950f82..9f4886a 100644
--- a/src/declarative/qml/qmlbindablevalue.cpp
+++ b/src/declarative/qml/qmlbindablevalue.cpp
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS);
QmlBindableValuePrivate::QmlBindableValuePrivate()
-: inited(false)
+: inited(false), mePtr(0)
{
}
@@ -75,6 +75,9 @@ QmlBindableValue::QmlBindableValue(const QString &str, QObject *obj, bool sse, Q
QmlBindableValue::~QmlBindableValue()
{
+ Q_D(QmlBindableValue);
+ if(d->mePtr)
+ *(d->mePtr) = 0;
}
void QmlBindableValue::setTarget(const QmlMetaProperty &prop)
diff --git a/src/declarative/qml/qmlbindablevalue_p.h b/src/declarative/qml/qmlbindablevalue_p.h
index b6de5b7..70c001b 100644
--- a/src/declarative/qml/qmlbindablevalue_p.h
+++ b/src/declarative/qml/qmlbindablevalue_p.h
@@ -56,6 +56,8 @@ public:
bool inited;
QmlMetaProperty property;
+
+ QmlBindableValue **mePtr;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 13fc332..5dbc5c3 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -526,6 +526,8 @@ void QmlCompiler::compileTree(Object *tree)
init.type = QmlInstruction::Init;
init.line = 0;
init.init.dataSize = 0;
+ init.init.bindingsSize = 0;
+ init.init.parserStatusSize = 0;
output->bytecode << init;
if (!compileObject(tree, 0)) // Compile failed
@@ -698,6 +700,8 @@ bool QmlCompiler::compileComponentFromRoot(Object *obj, int ctxt)
QmlInstruction init;
init.type = QmlInstruction::Init;
init.init.dataSize = 0;
+ init.init.bindingsSize = 0;
+ init.init.parserStatusSize = 0;
init.line = obj->location.start.line;
output->bytecode << init;
@@ -1378,6 +1382,8 @@ int QmlCompiler::optimizeExpressions(int start, int end, int patch)
QHash<QString, int> ids;
int saveCount = 0;
int newInstrs = 0;
+ int bindingsCount = 0;
+ int parserStatusCount = 0;
for (int ii = start; ii <= end; ++ii) {
const QmlInstruction &instr = output->bytecode.at(ii);
@@ -1400,6 +1406,17 @@ int QmlCompiler::optimizeExpressions(int start, int end, int patch)
ii += instr.createComponent.count - 1;
continue;
}
+
+ if (instr.type == QmlInstruction::AssignBinding ||
+ instr.type == QmlInstruction::AssignCompiledBinding ||
+ instr.type == QmlInstruction::StoreBinding ||
+ instr.type == QmlInstruction::StoreCompiledBinding) {
+ ++bindingsCount;
+ } else if (instr.type == QmlInstruction::TryBeginObject ||
+ instr.type == QmlInstruction::BeginObject) {
+ ++parserStatusCount;
+ }
+
if (instr.type == QmlInstruction::StoreCompiledBinding) {
QmlBasicScript s(output->datas.at(instr.assignBinding.value).constData());
@@ -1437,12 +1454,12 @@ int QmlCompiler::optimizeExpressions(int start, int end, int patch)
++newInstrs;
}
}
- }
-
+ }
}
- if (saveCount)
- output->bytecode[patch].init.dataSize = saveCount;
+ output->bytecode[patch].init.dataSize = saveCount;
+ output->bytecode[patch].init.bindingsSize = bindingsCount;
+ output->bytecode[patch].init.parserStatusSize = parserStatusCount;;
return newInstrs;
}
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
index 027c2a8..da8f26d 100644
--- a/src/declarative/qml/qmlcomponent.cpp
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -171,6 +171,11 @@ QmlComponent::~QmlComponent()
}
if (d->cc)
d->cc->release();
+
+ for(int ii = 0; ii < d->bindValues.count(); ++ii)
+ QmlEnginePrivate::clear(d->bindValues[ii]);
+ for(int ii = 0; ii < d->parserStatus.count(); ++ii)
+ QmlEnginePrivate::clear(d->parserStatus[ii]);
}
/*!
@@ -483,10 +488,10 @@ QObject *QmlComponent::beginCreate(QmlContext *context)
if (ep->rootComponent == this) {
ep->rootComponent = 0;
- d->bindValues = ep->currentBindValues;
- d->parserStatus = ep->currentParserStatus;
- ep->currentBindValues.clear();
- ep->currentParserStatus.clear();
+ d->bindValues = ep->bindValues;
+ d->parserStatus = ep->parserStatus;
+ ep->bindValues.clear();
+ ep->parserStatus.clear();
d->completePending = true;
}
} else {
@@ -511,16 +516,29 @@ void QmlComponent::completeCreate()
#ifdef Q_ENABLE_PERFORMANCE_LOG
QFxPerfTimer<QFxPerf::BindInit> bi;
#endif
- for (int ii = 0; ii < d->bindValues.count(); ++ii)
- d->bindValues.at(ii)->init();
+ for (int ii = 0; ii < d->bindValues.count(); ++ii) {
+ QmlEnginePrivate::SimpleList<QmlBindableValue> bv =
+ d->bindValues.at(ii);
+ for (int jj = 0; jj < bv.count; ++jj) {
+ if(bv.at(jj))
+ bv.at(jj)->init();
+ }
+ QmlEnginePrivate::clear(bv);
+ }
}
- QSet<QmlParserStatus *> done;
+
for (int ii = 0; ii < d->parserStatus.count(); ++ii) {
- QmlParserStatus *ps = d->parserStatus.at(ii);
- if (!done.contains(ps)) {
- done.insert(ps);
- ps->componentComplete();
+ QmlEnginePrivate::SimpleList<QmlParserStatus> ps =
+ d->parserStatus.at(ii);
+
+ for (int jj = 0; jj < ps.count; ++jj) {
+ QmlParserStatus *status = ps.at(jj);
+ if (status && status->d) {
+ status->d = 0;
+ status->componentComplete();
+ }
}
+ QmlEnginePrivate::clear(ps);
}
d->bindValues.clear();
diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h
index 6a5345e..4de47c6 100644
--- a/src/declarative/qml/qmlcomponent_p.h
+++ b/src/declarative/qml/qmlcomponent_p.h
@@ -46,6 +46,7 @@
#include <QStringList>
#include <QList>
#include "private/qobject_p.h"
+#include "private/qmlengine_p.h"
#include "private/qmlcompositetypemanager_p.h"
#include <qmlerror.h>
#include "qmlcomponent.h"
@@ -75,8 +76,10 @@ public:
int start;
int count;
QmlCompiledComponent *cc;
- QList<QmlBindableValue *> bindValues;
- QList<QmlParserStatus *> parserStatus;
+
+ QList<QmlEnginePrivate::SimpleList<QmlBindableValue> > bindValues;
+ QList<QmlEnginePrivate::SimpleList<QmlParserStatus> > parserStatus;
+
bool completePending;
QmlEngine *engine;
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 50c0981..f0ec334 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -70,6 +70,7 @@
#include <QtCore/qdir.h>
#include <qmlcomponent.h>
#include "private/qmlmetaproperty_p.h"
+#include <private/qmlbindablevalue_p.h>
QT_BEGIN_NAMESPACE
@@ -160,6 +161,34 @@ QmlEnginePrivate::~QmlEnginePrivate()
objectClass = 0;
delete networkAccessManager;
networkAccessManager = 0;
+
+ for(int ii = 0; ii < bindValues.count(); ++ii)
+ clear(bindValues[ii]);
+ for(int ii = 0; ii < parserStatus.count(); ++ii)
+ clear(parserStatus[ii]);
+}
+
+void QmlEnginePrivate::clear(SimpleList<QmlBindableValue> &bvs)
+{
+ for (int ii = 0; ii < bvs.count; ++ii) {
+ QmlBindableValue *bv = bvs.at(ii);
+ if(bv) {
+ QmlBindableValuePrivate *p =
+ static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bv));
+ p->mePtr = 0;
+ }
+ }
+ bvs.clear();
+}
+
+void QmlEnginePrivate::clear(SimpleList<QmlParserStatus> &pss)
+{
+ for (int ii = 0; ii < pss.count; ++ii) {
+ QmlParserStatus *ps = pss.at(ii);
+ if(ps)
+ ps->d = 0;
+ }
+ pss.clear();
}
void QmlEnginePrivate::init()
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 63df0ba..9402fa9 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -107,8 +107,35 @@ public:
QScriptEngine scriptEngine;
- QList<QmlBindableValue *> currentBindValues;
- QList<QmlParserStatus *> currentParserStatus;
+ template<class T>
+ struct SimpleList {
+ SimpleList()
+ : count(0), values(0) {}
+ SimpleList(int r)
+ : count(0), values(new T*[r]) {}
+
+ int count;
+ T **values;
+
+ void append(T *v) {
+ values[count++] = v;
+ }
+
+ T *at(int idx) const {
+ return values[idx];
+ }
+
+ void clear() {
+ delete [] values;
+ }
+ };
+
+ static void clear(SimpleList<QmlBindableValue> &);
+ static void clear(SimpleList<QmlParserStatus> &);
+
+ QList<SimpleList<QmlBindableValue> > bindValues;
+ QList<SimpleList<QmlParserStatus> > parserStatus;
+
QmlComponent *rootComponent;
mutable QNetworkAccessManager *networkAccessManager;
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index 02e084d..86bddf8 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -173,6 +173,8 @@ public:
union {
struct {
int dataSize;
+ int bindingsSize;
+ int parserStatusSize;
} init;
struct {
int type;
diff --git a/src/declarative/qml/qmlparserstatus.cpp b/src/declarative/qml/qmlparserstatus.cpp
index 71b7adf..fceac05 100644
--- a/src/declarative/qml/qmlparserstatus.cpp
+++ b/src/declarative/qml/qmlparserstatus.cpp
@@ -48,11 +48,17 @@ QT_BEGIN_NAMESPACE
\brief The QmlParserStatus class provides updates on the parser state.
*/
-/*!
- Destroys the parser status instance.
-*/
+/*! \internal */
+QmlParserStatus::QmlParserStatus()
+: d(0)
+{
+}
+
+/*! \internal */
QmlParserStatus::~QmlParserStatus()
{
+ if(d)
+ (*d) = 0;
}
/*!
diff --git a/src/declarative/qml/qmlparserstatus.h b/src/declarative/qml/qmlparserstatus.h
index bb3691c..0e58229 100644
--- a/src/declarative/qml/qmlparserstatus.h
+++ b/src/declarative/qml/qmlparserstatus.h
@@ -53,11 +53,18 @@ QT_MODULE(Declarative)
class Q_DECLARATIVE_EXPORT QmlParserStatus
{
public:
+ QmlParserStatus();
virtual ~QmlParserStatus();
virtual void classBegin();
virtual void classComplete();
virtual void componentComplete();
+
+private:
+ friend class QmlVME;
+ friend class QmlComponent;
+ friend class QmlEnginePrivate;
+ QmlParserStatus **d;
};
Q_DECLARE_INTERFACE(QmlParserStatus, "com.trolltech.qml.QmlParserStatus");
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index ca4f9c9..e42b2fc 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -62,6 +62,8 @@
#include <private/qmlcomponent_p.h>
#include "private/qmlvmemetaobject_p.h"
#include <QtCore/qdebug.h>
+#include <QtCore/qvarlengtharray.h>
+#include <private/qmlbindablevalue_p.h>
QT_BEGIN_NAMESPACE
Q_DECLARE_PERFORMANCE_LOG(QFxCompiler) {
@@ -219,9 +221,8 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
#ifdef Q_ENABLE_PERFORMANCE_LOG
QFxPerfTimer<QFxPerf::CompileRun> cr;
#endif
-
- QList<QmlParserStatus *> parserStatuses;
- QList<QmlBindableValue *> bindableValues;
+ QmlEnginePrivate::SimpleList<QmlBindableValue> bindValues;
+ QmlEnginePrivate::SimpleList<QmlParserStatus> parserStatus;
QStack<QObject *> stack;
QStack<ListInstance> qliststack;
@@ -252,6 +253,11 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
::memset(savedObjects, 0,
sizeof(QObject *)*instr.init.dataSize);
}
+
+ if (instr.init.bindingsSize)
+ bindValues = QmlEnginePrivate::SimpleList<QmlBindableValue>(instr.init.bindingsSize);
+ if (instr.init.parserStatusSize)
+ parserStatus = QmlEnginePrivate::SimpleList<QmlParserStatus>(instr.init.parserStatusSize);
}
break;
@@ -523,8 +529,10 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
#endif
QObject *target = stack.top();
QmlParserStatus *status = reinterpret_cast<QmlParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue);
+ parserStatus.append(status);
+ status->d = &parserStatus.values[parserStatus.count - 1];
+
status->classBegin();
- parserStatuses << status;
}
break;
@@ -634,10 +642,13 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
VME_EXCEPTION("Cannot assign a binding to read-only property" << mp.name());
QmlBindableValue *bind = new QmlBindableValue((void *)datas.at(instr.assignBinding.value).constData(), comp, context, 0);
+ bindValues.append(bind);
+ QmlBindableValuePrivate *p =
+ static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bind));
+ p->mePtr = &bindValues.values[bindValues.count - 1];
QFx_setParent_noEvent(bind, target);
bind->setTarget(mp);
- bindableValues << bind;
}
break;
@@ -656,10 +667,13 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
VME_EXCEPTION("Cannot assign a binding to read-only property" << mp.name());
QmlBindableValue *bind = new QmlBindableValue(primitives.at(instr.assignBinding.value), context, false);
+ bindValues.append(bind);
+ QmlBindableValuePrivate *p =
+ static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bind));
+ p->mePtr = &bindValues.values[bindValues.count - 1];
QFx_setParent_noEvent(bind, target);
bind->setTarget(mp);
- bindableValues << bind;
}
break;
@@ -1045,12 +1059,17 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
if (!stack.isEmpty()) {
delete stack.at(0);
}
+
+ QmlEnginePrivate::clear(bindValues);
+ QmlEnginePrivate::clear(parserStatus);
return 0;
}
QmlEnginePrivate *ep = ctxt->engine()->d_func();
- ep->currentBindValues << bindableValues;
- ep->currentParserStatus << parserStatuses;
+ if (bindValues.count)
+ ep->bindValues << bindValues;
+ if (parserStatus.count)
+ ep->parserStatus << parserStatus;
comp->dumpPost();