aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/qdeclarativevme.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml/qdeclarativevme.cpp')
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp119
1 files changed, 100 insertions, 19 deletions
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp
index f8405be2db..bf8bd29c34 100644
--- a/src/declarative/qml/qdeclarativevme.cpp
+++ b/src/declarative/qml/qdeclarativevme.cpp
@@ -130,6 +130,7 @@ bool QDeclarativeVME::initDeferred(QObject *object)
int start = data->deferredIdx;
State initState;
+ initState.flags = State::Deferred;
initState.context = ctxt;
initState.compiledData = comp;
initState.instructionStream = comp->bytecode.constData() + start;
@@ -195,7 +196,6 @@ static void removeBindingOnProperty(QObject *o, int index)
// XXX we probably need some form of "work count" here to prevent us checking this
// for every instruction.
#define QML_BEGIN_INSTR_COMMON(I) { \
- if (interrupt.shouldInterrupt()) return 0; \
const QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::DataType &instr = QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::data(*genericInstr); \
INSTRUCTIONSTREAM += QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::Size; \
Q_UNUSED(instr);
@@ -211,6 +211,7 @@ static void removeBindingOnProperty(QObject *o, int index)
# define QML_END_INSTR(I) } \
genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM); \
+ if (interrupt.shouldInterrupt()) return 0; \
goto *genericInstr->common.code;
#else
@@ -219,7 +220,9 @@ static void removeBindingOnProperty(QObject *o, int index)
QML_BEGIN_INSTR_COMMON(I)
# define QML_NEXT_INSTR(I) break;
-# define QML_END_INSTR(I) } break;
+# define QML_END_INSTR(I) \
+ if (interrupt.shouldInterrupt()) return 0; \
+ } break;
#endif
#define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index)
@@ -1099,23 +1102,10 @@ QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
#endif
exceptionExit:
- if (!objects.isEmpty())
- delete objects.at(0); // XXX What about failures in deferred creation?
-
- // XXX does context get leaked in this case?
-
+ Q_ASSERT(!states.isEmpty());
Q_ASSERT(!errors->isEmpty());
- // Remove the QDeclarativeParserStatus and QDeclarativeAbstractBinding back pointers
- blank(parserStatus);
- blank(bindValues);
-
- objects.deallocate();
- lists.deallocate();
- states.clear();
- bindValues.deallocate();
- parserStatus.deallocate();
- finalizeCallbacks.clear();
+ reset();
return 0;
@@ -1131,6 +1121,35 @@ normalExit:
return rv;
}
+void QDeclarativeVME::reset()
+{
+ Q_ASSERT(!states.isEmpty() || objects.isEmpty());
+
+ if (!objects.isEmpty() && !(states.at(0).flags & State::Deferred))
+ delete objects.at(0);
+
+ if (!rootContext.isNull())
+ rootContext->activeVME = 0;
+
+ // Remove the QDeclarativeParserStatus and QDeclarativeAbstractBinding back pointers
+ blank(parserStatus);
+ blank(bindValues);
+
+ while (componentAttached) {
+ QDeclarativeComponentAttached *a = componentAttached;
+ a->rem();
+ }
+
+ engine = 0;
+ objects.deallocate();
+ lists.deallocate();
+ bindValues.deallocate();
+ parserStatus.deallocate();
+ finalizeCallbacks.clear();
+ states.clear();
+ rootContext = 0;
+}
+
// Must be called with a handle scope and context
void QDeclarativeScriptData::initialize(QDeclarativeEngine *engine)
{
@@ -1242,6 +1261,16 @@ void **QDeclarativeVME::instructionJumpTable()
bool QDeclarativeVME::complete(const Interrupt &interrupt)
{
+ Q_ASSERT(engine ||
+ (bindValues.isEmpty() &&
+ parserStatus.isEmpty() &&
+ componentAttached == 0 &&
+ rootContext.isNull() &&
+ finalizeCallbacks.isEmpty()));
+
+ if (!engine)
+ return true;
+
ActiveVMERestorer restore(this, QDeclarativeEnginePrivate::get(engine));
while (!bindValues.isEmpty()) {
@@ -1284,8 +1313,7 @@ bool QDeclarativeVME::complete(const Interrupt &interrupt)
return false;
}
- // XXX (what if its deleted?)
- if (rootContext)
+ if (!rootContext.isNull())
rootContext->activeVME = 0;
for (int ii = 0; ii < finalizeCallbacks.count(); ++ii) {
@@ -1298,6 +1326,8 @@ bool QDeclarativeVME::complete(const Interrupt &interrupt)
}
finalizeCallbacks.clear();
+ reset();
+
return true;
}
@@ -1317,4 +1347,55 @@ void QDeclarativeVME::blank(QFiniteStack<QDeclarativeParserStatus *> &pss)
}
}
+QDeclarativeVMEGuard::QDeclarativeVMEGuard()
+: m_objectCount(0), m_objects(0), m_contextCount(0), m_contexts(0)
+{
+}
+
+QDeclarativeVMEGuard::~QDeclarativeVMEGuard()
+{
+ clear();
+}
+
+void QDeclarativeVMEGuard::guard(QDeclarativeVME *vme)
+{
+ clear();
+
+ m_objectCount = vme->objects.count();
+ m_objects = new QDeclarativeGuard<QObject>[m_objectCount];
+ for (int ii = 0; ii < m_objectCount; ++ii)
+ m_objects[ii] = vme->objects[ii];
+
+ m_contextCount = (vme->rootContext.isNull())?0:1 + vme->states.count();
+ m_contexts = new QDeclarativeGuardedContextData[m_contextCount];
+ for (int ii = 0; ii < vme->states.count(); ++ii)
+ m_contexts[ii] = vme->states.at(ii).context;
+ if (!vme->rootContext.isNull())
+ m_contexts[m_contextCount - 1] = vme->rootContext.contextData();
+}
+
+void QDeclarativeVMEGuard::clear()
+{
+ delete [] m_objects;
+ delete [] m_contexts;
+
+ m_objectCount = 0;
+ m_objects = 0;
+ m_contextCount = 0;
+ m_contexts = 0;
+}
+
+bool QDeclarativeVMEGuard::isOK() const
+{
+ for (int ii = 0; ii < m_objectCount; ++ii)
+ if (m_objects[ii].isNull())
+ return false;
+
+ for (int ii = 0; ii < m_contextCount; ++ii)
+ if (m_contexts[ii].isNull())
+ return false;
+
+ return true;
+}
+
QT_END_NAMESPACE