aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlvme.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmlvme.cpp')
-rw-r--r--src/qml/qml/qqmlvme.cpp142
1 files changed, 73 insertions, 69 deletions
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index dfc184b9f7..54c70feecc 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -173,9 +173,9 @@ bool QQmlVME::initDeferred(QObject *object)
}
namespace {
-struct ActiveVMERestorer
+struct ActiveVMERestorer
{
- ActiveVMERestorer(QQmlVME *me, QQmlEnginePrivate *ep)
+ ActiveVMERestorer(QQmlVME *me, QQmlEnginePrivate *ep)
: ep(ep), oldVME(ep->activeVME) { ep->activeVME = me; }
~ActiveVMERestorer() { ep->activeVME = oldVME; }
@@ -184,7 +184,7 @@ struct ActiveVMERestorer
};
}
-QObject *QQmlVME::execute(QList<QQmlError> *errors, const Interrupt &interrupt)
+QObject *QQmlVME::execute(QList<QQmlError> *errors, const QQmlInstantiationInterrupt &interrupt)
{
Q_ASSERT(states.count() >= 1);
@@ -202,7 +202,7 @@ QObject *QQmlVME::execute(QList<QQmlError> *errors, const Interrupt &interrupt)
return rv;
}
-inline bool fastHasBinding(QObject *o, int index)
+inline bool fastHasBinding(QObject *o, int index)
{
if (QQmlData *ddata = static_cast<QQmlData *>(QObjectPrivate::get(o)->declarativeData)) {
int coreIndex = index & 0x0000FFFF;
@@ -226,7 +226,7 @@ static QVariant variantFromString(const QString &string)
return QQmlStringConverters::variantFromString(string);
}
-static QV4::ExecutionContext *qmlBindingContext(QQmlEngine *engine, QV4::ExecutionEngine *v4, QV4::SafeValue *qmlBindingWrappers, QQmlContextData *context, QObject *scope, int objIdx)
+static QV4::ExecutionContext *qmlBindingContext(QQmlEngine *engine, QV4::ExecutionEngine *v4, QV4::Value *qmlBindingWrappers, QQmlContextData *context, QObject *scope, int objIdx)
{
QV4::Scope valueScope(v4);
QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, qmlBindingWrappers[objIdx]);
@@ -238,7 +238,7 @@ static QV4::ExecutionContext *qmlBindingContext(QQmlEngine *engine, QV4::Executi
return wrapper->context();
}
-// XXX we probably need some form of "work count" here to prevent us checking this
+// XXX we probably need some form of "work count" here to prevent us checking this
// for every instruction.
#define QML_BEGIN_INSTR_COMMON(I) { \
const QQmlInstructionMeta<(int)QQmlInstruction::I>::DataType &instr = QQmlInstructionMeta<(int)QQmlInstruction::I>::data(*genericInstr); \
@@ -330,7 +330,7 @@ static QV4::ExecutionContext *qmlBindingContext(QQmlEngine *engine, QV4::Executi
removeBindingOnProperty(o, index)
QObject *QQmlVME::run(QList<QQmlError> *errors,
- const Interrupt &interrupt
+ const QQmlInstantiationInterrupt &interrupt
#ifdef QML_THREADED_VME_INTERPRETER
, void * const **storeJumpTable
#endif
@@ -355,7 +355,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QV4::ExecutionEngine *v4 = ep->v4engine();
QV4::Scope valueScope(v4);
QV4::ScopedValue tmpValue(valueScope);
- QV4::SafeValue *qmlBindingWrappers = valueScope.alloc(objects.capacity());
+ QV4::Value *qmlBindingWrappers = valueScope.alloc(objects.capacity());
std::fill(qmlBindingWrappers, qmlBindingWrappers + objects.capacity(), QV4::Primitive::undefinedValue());
int status = -1; // needed for dbus
@@ -461,7 +461,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
CTXT->imports = COMP->importCache;
CTXT->imports->addref();
CTXT->setParent(parentCtxt);
- if (instr.contextCache != -1)
+ if (instr.contextCache != -1)
CTXT->setIdPropertyData(COMP->contextCaches.at(instr.contextCache));
if (states.count() == 1) {
rootContext = CTXT;
@@ -469,7 +469,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
rootContext->isRootObjectInCreation = true;
}
if (states.count() == 1 && !creationContext.isNull()) {
- // A component that is logically created within another component instance shares the
+ // A component that is logically created within another component instance shares the
// same instances of script imports. For example:
//
// import QtQuick 2.0
@@ -482,7 +482,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
// }
//
// Has the same "Test" instance. To implement this, we simply copy the v8 handles into
- // the inner context. We have to create a fresh persistent handle for each to prevent
+ // the inner context. We have to create a fresh persistent handle for each to prevent
// double dispose. It is possible we could do this more efficiently using some form of
// referencing instead.
CTXT->importedScripts = creationContext->importedScripts;
@@ -503,10 +503,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type);
Q_ASSERT(type.component);
- if (profiler.start()) {
- profiler.updateTypeName(type.component->name);
- profiler.background();
- }
+ Q_QML_VME_PROFILE(profiler.startBackground(type.component->name));
states.push(State());
@@ -529,8 +526,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(CreateQMLObject)
QML_BEGIN_INSTR(CompleteQMLObject)
- if (profiler.foreground())
- profiler.updateLocation(CTXT->url, instr.line, instr.column);
+ Q_QML_VME_PROFILE(profiler.foreground(CTXT->url, instr.line, instr.column));
QObject *o = objects.top();
Q_ASSERT(o);
@@ -574,10 +570,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_BEGIN_INSTR(CreateCppObject)
const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type);
Q_ASSERT(type.type);
- if (profiler.start()) {
- profiler.updateLocation(CTXT->url, instr.line, instr.column);
- profiler.updateTypeName(type.type->qmlTypeName());
- }
+ Q_QML_VME_PROFILE(profiler.start(type.type->qmlTypeName(), CTXT->url, instr.line, instr.column));
QObject *o = 0;
void *memory = 0;
@@ -637,9 +630,9 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
if (!objects.isEmpty()) {
QObject *parent = objects.at(objects.count() - 1 - (instr.parentToSuper?1:0));
#if 0 // ### refactor
- if (o->isWidgetType() && parent->isWidgetType())
+ if (o->isWidgetType() && parent->isWidgetType())
static_cast<QWidget*>(o)->setParent(static_cast<QWidget*>(parent));
- else
+ else
#endif
QQml_setParent_noEvent(o, parent);
ddata->parentFrozen = true;
@@ -650,11 +643,8 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_BEGIN_INSTR(CreateSimpleObject)
const QQmlCompiledData::TypeReference &ref = TYPES.at(instr.type);
- if (profiler.start()) {
- profiler.updateLocation(CTXT->url, instr.line, instr.column);
- profiler.updateTypeName(ref.type->qmlTypeName());
- }
- QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QQmlData));
+ Q_QML_VME_PROFILE(profiler.start(ref.type->qmlTypeName(), CTXT->url, instr.line, instr.column));
+ QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QQmlData));
::memset(static_cast<void *>(o), 0, instr.typeSize + sizeof(QQmlData));
instr.create(o);
@@ -666,16 +656,16 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
ddata->lineNumber = instr.line;
ddata->columnNumber = instr.column;
- QObjectPrivate::get(o)->declarativeData = ddata;
+ QObjectPrivate::get(o)->declarativeData = ddata;
ddata->context = ddata->outerContext = CTXT;
- ddata->nextContextObject = CTXT->contextObjects;
- if (ddata->nextContextObject)
- ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
- ddata->prevContextObject = &CTXT->contextObjects;
- CTXT->contextObjects = ddata;
+ ddata->nextContextObject = CTXT->contextObjects;
+ if (ddata->nextContextObject)
+ ddata->nextContextObject->prevContextObject = &ddata->nextContextObject;
+ ddata->prevContextObject = &CTXT->contextObjects;
+ CTXT->contextObjects = ddata;
QObject *parent = objects.at(objects.count() - 1 - (instr.parentToSuper?1:0));
- QQml_setParent_noEvent(o, parent);
+ QQml_setParent_noEvent(o, parent);
ddata->parentFrozen = true;
objects.push(o);
@@ -692,7 +682,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(SetDefault)
QML_BEGIN_INSTR(CreateComponent)
- QQmlComponent *qcomp =
+ QQmlComponent *qcomp =
new QQmlComponent(CTXT->engine, COMP, INSTRUCTIONSTREAM - COMP->bytecode.constData(),
objects.isEmpty() ? 0 : objects.top());
@@ -727,7 +717,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QQmlPropertyCache *propertyCache = PROPERTYCACHES.at(instr.propertyCache);
- const QQmlVMEMetaData *data =
+ const QQmlVMEMetaData *data =
(const QQmlVMEMetaData *)DATAS.at(instr.aliasData).constData();
QV4::ExecutionContext *qmlContext = qmlBindingContext(engine, QV8Engine::getV4(engine), qmlBindingWrappers, CTXT, target, objects.count() - 1);
@@ -749,13 +739,13 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(type);
QVariant v = (*converter)(primitive);
- QMetaProperty prop =
+ QMetaProperty prop =
target->metaObject()->property(instr.propertyIndex);
- if (v.isNull() || ((int)prop.type() != type && prop.userType() != type))
+ if (v.isNull() || ((int)prop.type() != type && prop.userType() != type))
VME_EXCEPTION(tr("Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
void *a[] = { (void *)v.data(), 0, &status, &flags };
- QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.propertyIndex, a);
QML_END_INSTR(AssignCustomType)
@@ -828,12 +818,12 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
ss.d.data()->numberValue = instr.numberValue;
void *a[] = { &ss, 0, &status, &flags };
- QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.propertyIndex, a);
QML_END_INSTR(StoreScriptString)
QML_BEGIN_INSTR(BeginObject)
- profiler.push();
+ Q_QML_VME_PROFILE(profiler.push());
QObject *target = objects.top();
QQmlParserStatus *status = reinterpret_cast<QQmlParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
parserStatus.push(status);
@@ -847,9 +837,9 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(BeginObject)
QML_BEGIN_INSTR(StoreBinding)
- QObject *target =
+ QObject *target =
objects.at(objects.count() - 1 - instr.owner);
- QObject *context =
+ QObject *context =
objects.at(objects.count() - 1 - instr.context);
if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex))
@@ -901,7 +891,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QObject *obj = objects.pop();
QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
QObject *target = obj->parent();
- QQmlProperty prop =
+ QQmlProperty prop =
QQmlPropertyPrivate::restore(target, instr.property, CTXT);
vi->setTarget(prop);
QQmlVMEMetaObject *mo = QQmlVMEMetaObject::get(target);
@@ -929,9 +919,9 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
void *ptr = 0;
const char *iid = QQmlMetaType::interfaceIId(type);
- if (iid)
+ if (iid)
ptr = assign->qt_metacast(iid);
- if (!ptr)
+ if (!ptr)
VME_EXCEPTION(tr("Cannot assign object to list"), instr.line);
if (list.qListProperty.append)
@@ -954,17 +944,17 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
void *ptr = assign->qt_metacast(iid);
if (ptr) {
void *a[] = { &ptr, 0, &status, &flags };
- QMetaObject::metacall(target,
+ QMetaObject::metacall(target,
QMetaObject::WriteProperty,
coreIdx, a);
ok = true;
}
- }
+ }
- if (!ok)
+ if (!ok)
VME_EXCEPTION(tr("Cannot assign object to interface property"), instr.line);
QML_END_INSTR(StoreInterface)
-
+
QML_BEGIN_INSTR(FetchAttached)
QObject *target = objects.top();
@@ -984,7 +974,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
void *a[1];
a[0] = (void *)&(lists.top().qListProperty);
- QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
instr.property, a);
QML_END_INSTR(FetchQList)
@@ -992,11 +982,11 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QObject *target = objects.top();
QObject *obj = 0;
- // NOTE: This assumes a cast to QObject does not alter the
+ // NOTE: This assumes a cast to QObject does not alter the
// object pointer
void *a[1];
a[0] = &obj;
- QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
instr.property, a);
if (!obj)
@@ -1042,14 +1032,14 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
// Possibly need to clear bindings
QQmlData *targetData = QQmlData::get(target);
if (targetData) {
- QQmlAbstractBinding *binding =
+ QQmlAbstractBinding *binding =
QQmlPropertyPrivate::binding(target, instr.property, -1);
if (binding && binding->bindingType() != QQmlAbstractBinding::ValueTypeProxy) {
QQmlPropertyPrivate::setBinding(target, instr.property, -1, 0);
binding->destroy();
} else if (binding) {
- QQmlValueTypeProxyBinding *proxy =
+ QQmlValueTypeProxyBinding *proxy =
static_cast<QQmlValueTypeProxyBinding *>(binding);
proxy->removeBindings(instr.bindingSkipList);
}
@@ -1064,7 +1054,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(FetchValueType)
QML_BEGIN_INSTR(PopValueType)
- QQmlValueType *valueHandler =
+ QQmlValueType *valueHandler =
static_cast<QQmlValueType *>(objects.pop());
QObject *target = objects.top();
valueHandler->write(target, instr.property, QQmlPropertyPrivate::BypassInterceptor);
@@ -1097,7 +1087,7 @@ normalExit:
objects.deallocate();
lists.deallocate();
states.clear();
- profiler.stop();
+ Q_QML_VME_PROFILE(profiler.stop());
return rv;
}
@@ -1109,9 +1099,9 @@ void QQmlVME::reset()
QRecursionWatcher<QQmlVME, &QQmlVME::recursion> watcher(this);
if (!objects.isEmpty() && !(states.at(0).flags & State::Deferred))
- delete objects.at(0);
-
- if (!rootContext.isNull())
+ delete objects.at(0);
+
+ if (!rootContext.isNull())
rootContext->activeVMEData = 0;
// Remove the QQmlParserStatus and QQmlAbstractBinding back pointers
@@ -1122,7 +1112,7 @@ void QQmlVME::reset()
QQmlComponentAttached *a = componentAttached;
a->rem();
}
-
+
engine = 0;
objects.deallocate();
lists.deallocate();
@@ -1135,7 +1125,13 @@ void QQmlVME::reset()
states.clear();
rootContext = 0;
creationContext = 0;
- profiler.clear();
+
+ // If profiling is switched off during a VME run and then switched back on
+ // before or during the next run background ranges from the first run will
+ // be reported in the second run because we don't clear() here. We accept
+ // that as the collected data will be incomplete anyway and because not
+ // calling clear() here is benefitial for the non-profiling case.
+ Q_QML_VME_PROFILE(profiler.clear());
}
#ifdef QML_THREADED_VME_INTERPRETER
@@ -1144,14 +1140,14 @@ void *const *QQmlVME::instructionJumpTable()
static void * const *jumpTable = 0;
if (!jumpTable) {
QQmlVME dummy;
- QQmlVME::Interrupt i;
+ QQmlInstantiationInterrupt i;
dummy.run(0, i, &jumpTable);
}
return jumpTable;
}
#endif
-QQmlContextData *QQmlVME::complete(const Interrupt &interrupt)
+QQmlContextData *QQmlVME::complete(const QQmlInstantiationInterrupt &interrupt)
{
Q_ASSERT(engine ||
(bindValues.isEmpty() &&
@@ -1195,7 +1191,7 @@ QQmlContextData *QQmlVME::complete(const Interrupt &interrupt)
if (componentCompleteEnabled()) { // the qml designer does the component complete later
QQmlTrace trace("VME Component Complete");
while (!parserStatus.isEmpty()) {
- profiler.pop();
+ Q_QML_VME_PROFILE(profiler.pop());
QQmlParserStatus *status = parserStatus.pop();
#ifdef QML_ENABLE_TRACE
QQmlData *data = parserStatusData.pop();
@@ -1215,7 +1211,7 @@ QQmlContextData *QQmlVME::complete(const Interrupt &interrupt)
return 0;
}
parserStatus.deallocate();
- profiler.clear();
+ Q_QML_VME_PROFILE(profiler.clear());
}
{
@@ -1303,7 +1299,7 @@ QQmlVMEGuard::~QQmlVMEGuard()
void QQmlVMEGuard::guard(QQmlVME *vme)
{
clear();
-
+
m_objectCount = vme->objects.count();
m_objects = new QPointer<QObject>[m_objectCount];
for (int ii = 0; ii < m_objectCount; ++ii)
@@ -1311,12 +1307,20 @@ void QQmlVMEGuard::guard(QQmlVME *vme)
m_contextCount = (vme->rootContext.isNull()?0:1) + vme->states.count();
m_contexts = new QQmlGuardedContextData[m_contextCount];
- for (int ii = 0; ii < vme->states.count(); ++ii)
+ 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 QQmlVMEGuard::guard(QmlObjectCreator *creator)
+{
+ clear();
+ m_contextCount = 1;
+ m_contexts = new QQmlGuardedContextData[m_contextCount];
+ m_contexts[0] = creator->parentContextData();
+}
+
void QQmlVMEGuard::clear()
{
delete [] m_objects;