From e8d0ab4b01cabf31d9bff31a821928d846c2f0af Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 9 Dec 2011 12:39:23 +0000 Subject: Add a tracing API for the QML engine Change-Id: Ic03583444d586f275897d765be8e1b5e69fdd5d4 Reviewed-by: Roberto Raggi --- src/declarative/qml/ftw/ftw.pri | 2 + src/declarative/qml/ftw/qdeclarativepool_p.h | 11 + src/declarative/qml/ftw/qdeclarativetrace.cpp | 154 +++++++++++++ src/declarative/qml/ftw/qdeclarativetrace_p.h | 294 ++++++++++++++++++++++++ src/declarative/qml/qdeclarativebinding.cpp | 18 +- src/declarative/qml/qdeclarativebinding_p.h | 2 +- src/declarative/qml/qdeclarativebinding_p_p.h | 1 + src/declarative/qml/qdeclarativecompiler.cpp | 3 + src/declarative/qml/qdeclarativecomponent.cpp | 1 + src/declarative/qml/qdeclarativeinstruction_p.h | 2 + src/declarative/qml/qdeclarativevme.cpp | 60 ++++- src/declarative/qml/qdeclarativevme_p.h | 10 + src/declarative/qml/v4/qv4bindings.cpp | 14 +- src/declarative/qml/v4/qv4bindings_p.h | 4 +- src/declarative/qml/v8/qv8bindings.cpp | 12 +- src/declarative/qml/v8/qv8bindings_p.h | 3 +- 16 files changed, 577 insertions(+), 14 deletions(-) create mode 100644 src/declarative/qml/ftw/qdeclarativetrace.cpp create mode 100644 src/declarative/qml/ftw/qdeclarativetrace_p.h diff --git a/src/declarative/qml/ftw/ftw.pri b/src/declarative/qml/ftw/ftw.pri index 9df0af8146..44141223bf 100644 --- a/src/declarative/qml/ftw/ftw.pri +++ b/src/declarative/qml/ftw/ftw.pri @@ -14,6 +14,7 @@ HEADERS += \ $$PWD/qdeletewatcher_p.h \ $$PWD/qrecyclepool_p.h \ $$PWD/qflagpointer_p.h \ + $$PWD/qdeclarativetrace_p.h \ SOURCES += \ $$PWD/qintrusivelist.cpp \ @@ -21,4 +22,5 @@ SOURCES += \ $$PWD/qdeclarativepool.cpp \ $$PWD/qfastmetabuilder.cpp \ $$PWD/qdeclarativethread.cpp \ + $$PWD/qdeclarativetrace.cpp \ diff --git a/src/declarative/qml/ftw/qdeclarativepool_p.h b/src/declarative/qml/ftw/qdeclarativepool_p.h index 60ff4fa359..3a7133c7fb 100644 --- a/src/declarative/qml/ftw/qdeclarativepool_p.h +++ b/src/declarative/qml/ftw/qdeclarativepool_p.h @@ -55,6 +55,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -105,6 +106,7 @@ public: inline QString *NewString(const QString &); inline QByteArray *NewByteArray(const QByteArray &); + inline QUrl *NewUrl(const QUrl &); template struct List { @@ -145,6 +147,8 @@ private: }; struct ByteArrayClass : public QByteArray, public Class { }; + struct UrlClass : public QUrl, public Class { + }; inline void *allocate(int size); void newpage(); @@ -222,6 +226,13 @@ QByteArray *QDeclarativePool::NewByteArray(const QByteArray &s) return rv; } +QUrl *QDeclarativePool::NewUrl(const QUrl &s) +{ + QUrl *rv = New(); + *rv = s; + return rv; +} + void *QDeclarativePool::allocate(int size) { if (!_page || (_page->header.free + size) > (_page->memory + Page::pageSize)) diff --git a/src/declarative/qml/ftw/qdeclarativetrace.cpp b/src/declarative/qml/ftw/qdeclarativetrace.cpp new file mode 100644 index 0000000000..61e84075aa --- /dev/null +++ b/src/declarative/qml/ftw/qdeclarativetrace.cpp @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativetrace_p.h" + +#ifdef QML_ENABLE_TRACE +#include +#endif + +QT_BEGIN_NAMESPACE + +#ifdef QML_ENABLE_TRACE + +QDeclarativeTrace::Pool QDeclarativeTrace::logPool; +QDeclarativeTrace::Entry *QDeclarativeTrace::first = 0; +QDeclarativeTrace::Entry *QDeclarativeTrace::last = 0; + +static qint64 toNsecs(QDeclarativeTrace::TimeType time) +{ +#ifdef Q_OS_MAC + static mach_timebase_info_data_t info = {0,0}; + if (info.denom == 0) + mach_timebase_info(&info); + return time * info.numer / info.denom; +#else + qint64 rv = time.tv_sec * 1000000000 + time.tv_nsec; + return rv; +#endif +} + +QDeclarativeTrace::Pool::Pool() +{ + first = New(); + last = first; +} + +QDeclarativeTrace::Pool::~Pool() +{ + char buffer[128]; + sprintf(buffer, "qml.%d.log", ::getpid()); + FILE *out = fopen(buffer, "w"); + if (!out) { + fprintf (stderr, "QML Log: Could not open %s\n", buffer); + return; + } else { + fprintf (stderr, "QML Log: Writing log to %s\n", buffer); + } + + QDeclarativeTrace::Entry *cur = QDeclarativeTrace::first; + QByteArray indent; + int depth = -1; + + qint64 firstTime = -1; + + while (cur) { + + switch (cur->type) { + case QDeclarativeTrace::Entry::RangeStart: { + RangeStart *rs = static_cast(cur); + + qint64 nsecs = toNsecs(rs->time); + + if (firstTime == -1) + firstTime = nsecs; + + nsecs -= firstTime; + + depth++; + indent = QByteArray(depth * 4, ' '); + fprintf(out, "%s%s @%lld (%lld ns)\n", indent.constData(), + rs->description, nsecs, toNsecs(rs->end->time) - nsecs - firstTime); + } break; + case QDeclarativeTrace::Entry::RangeEnd: + depth--; + indent = QByteArray(depth * 4, ' '); + break; + case QDeclarativeTrace::Entry::Detail: + fprintf(out, "%s %s\n", indent.constData(), + static_cast(cur)->description); + break; + case QDeclarativeTrace::Entry::IntDetail: + fprintf(out, "%s %s: %d\n", indent.constData(), + static_cast(cur)->description, + static_cast(cur)->value); + break; + case QDeclarativeTrace::Entry::StringDetail: { + QByteArray vLatin1 = static_cast(cur)->value->toLatin1(); + fprintf(out, "%s %s: %s\n", indent.constData(), + static_cast(cur)->description, + vLatin1.constData()); + } break; + case QDeclarativeTrace::Entry::UrlDetail: { + QByteArray vLatin1 = static_cast(cur)->value->toString().toLatin1(); + fprintf(out, "%s %s: %s\n", indent.constData(), + static_cast(cur)->description, + vLatin1.constData()); + } break; + case QDeclarativeTrace::Entry::Event: { + Event *ev = static_cast(cur); + qint64 nsecs = toNsecs(ev->time) - firstTime; + fprintf(out, "%s + %s @%lld +%lld ns\n", indent.constData(), + ev->description, nsecs, nsecs - (toNsecs(ev->start->time) - firstTime)); + } break; + case QDeclarativeTrace::Entry::Null: + default: + break; + } + cur = cur->next; + } + fclose(out); +} + +#endif + +QT_END_NAMESPACE + diff --git a/src/declarative/qml/ftw/qdeclarativetrace_p.h b/src/declarative/qml/ftw/qdeclarativetrace_p.h new file mode 100644 index 0000000000..6fac53967a --- /dev/null +++ b/src/declarative/qml/ftw/qdeclarativetrace_p.h @@ -0,0 +1,294 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVETRACE_P_H +#define QDECLARATIVETRACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +// #define QML_ENABLE_TRACE + +#if defined(QML_ENABLE_TRACE) && defined(Q_OS_MAC) +#include +#endif + +QT_BEGIN_NAMESPACE + +class QUrl; +class QDeclarativeTrace +{ +public: + inline QDeclarativeTrace(const char *desc); + inline ~QDeclarativeTrace(); + + inline void addDetail(const char *); + inline void addDetail(const char *, int); + inline void addDetail(const char *, const QString &); + inline void addDetail(const char *, const QUrl &); + + inline void event(const char *desc); + +#ifdef QML_ENABLE_TRACE + +#ifdef Q_OS_MAC + typedef uint64_t TimeType; +#else + typedef timespec TimeType; +#endif + + struct Entry : public QDeclarativePool::POD { + enum Type { Null, RangeStart, RangeEnd, Detail, IntDetail, StringDetail, UrlDetail, Event }; + inline Entry(); + inline Entry(Type); + Type type; + Entry *next; + }; + struct RangeEnd : public Entry { + inline RangeEnd(); + TimeType time; + }; + struct RangeStart : public Entry { + inline RangeStart(); + const char *description; + TimeType time; + QDeclarativeTrace::RangeEnd *end; + }; + struct Detail : public Entry { + inline Detail(); + inline Detail(Type t); + const char *description; + }; + struct IntDetail : public Detail { + inline IntDetail(); + int value; + }; + struct StringDetail : public Detail { + inline StringDetail(); + QString *value; + }; + struct UrlDetail : public Detail { + inline UrlDetail(); + QUrl *value; + }; + struct Event : public Entry { + inline Event(); + const char *description; + TimeType time; + QDeclarativeTrace::RangeStart *start; + }; + + struct Pool : public QDeclarativePool { + Pool(); + ~Pool(); + }; + + static Pool logPool; + static Entry *first; + static Entry *last; + +private: + RangeStart *start; + + static TimeType gettime() { +#ifdef Q_OS_MAC + return mach_absolute_time(); +#else + TimeType ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts; +#endif + } +#endif +}; + +#ifdef QML_ENABLE_TRACE +QDeclarativeTrace::Entry::Entry() +: type(Null), next(0) +{ +} + +QDeclarativeTrace::Entry::Entry(Type type) +: type(type), next(0) +{ + QDeclarativeTrace::last->next = this; + QDeclarativeTrace::last = this; +} + +QDeclarativeTrace::RangeEnd::RangeEnd() +: QDeclarativeTrace::Entry(QDeclarativeTrace::Entry::RangeEnd), + time(gettime()) +{ +} + +QDeclarativeTrace::RangeStart::RangeStart() +: QDeclarativeTrace::Entry(QDeclarativeTrace::Entry::RangeStart), + description(0), time(gettime()) +{ +} + +QDeclarativeTrace::Detail::Detail() +: QDeclarativeTrace::Entry(QDeclarativeTrace::Entry::Detail), + description(0) +{ +} + +QDeclarativeTrace::Detail::Detail(Type type) +: QDeclarativeTrace::Entry(type), description(0) +{ +} + +QDeclarativeTrace::IntDetail::IntDetail() +: QDeclarativeTrace::Detail(QDeclarativeTrace::Entry::IntDetail), + value(0) +{ +} + +QDeclarativeTrace::StringDetail::StringDetail() +: QDeclarativeTrace::Detail(QDeclarativeTrace::Entry::StringDetail), + value(0) +{ +} + +QDeclarativeTrace::UrlDetail::UrlDetail() +: QDeclarativeTrace::Detail(QDeclarativeTrace::Entry::UrlDetail), + value(0) +{ +} + +QDeclarativeTrace::Event::Event() +: QDeclarativeTrace::Entry(QDeclarativeTrace::Entry::Event), + description(0), time(gettime()), start(0) +{ +} +#endif + +QDeclarativeTrace::QDeclarativeTrace(const char *desc) +{ +#ifdef QML_ENABLE_TRACE + RangeStart *e = logPool.New(); + e->description = desc; + e->end = 0; + start = e; +#else + Q_UNUSED(desc); +#endif +} + +QDeclarativeTrace::~QDeclarativeTrace() +{ +#ifdef QML_ENABLE_TRACE + RangeEnd *e = logPool.New(); + start->end = e; +#endif +} + +void QDeclarativeTrace::addDetail(const char *desc) +{ +#ifdef QML_ENABLE_TRACE + Detail *e = logPool.New(); + e->description = desc; +#else + Q_UNUSED(desc); +#endif +} + +void QDeclarativeTrace::addDetail(const char *desc, int v) +{ +#ifdef QML_ENABLE_TRACE + IntDetail *e = logPool.New(); + e->description = desc; + e->value = v; +#else + Q_UNUSED(desc); + Q_UNUSED(v); +#endif +} + +void QDeclarativeTrace::addDetail(const char *desc, const QString &v) +{ +#ifdef QML_ENABLE_TRACE + StringDetail *e = logPool.New(); + e->description = desc; + e->value = logPool.NewString(v); +#else + Q_UNUSED(desc); + Q_UNUSED(v); +#endif +} + +void QDeclarativeTrace::addDetail(const char *desc, const QUrl &v) +{ +#ifdef QML_ENABLE_TRACE + UrlDetail *e = logPool.New(); + e->description = desc; + e->value = logPool.NewUrl(v); +#else + Q_UNUSED(desc); + Q_UNUSED(v); +#endif +} + +void QDeclarativeTrace::event(const char *desc) +{ +#ifdef QML_ENABLE_TRACE + Event *e = logPool.New(); + e->start = start; + e->description = desc; +#else + Q_UNUSED(desc); +#endif +} + +QT_END_NAMESPACE + +#endif // QDECLARATIVETRACE_P_H diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index fbfba6d8d3..84b49e10a8 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -48,6 +48,7 @@ #include "qdeclarativecompiler_p.h" #include "qdeclarativedata_p.h" #include +#include #include #include @@ -215,7 +216,7 @@ void QDeclarativeBindingPrivate::refresh() } QDeclarativeBindingPrivate::QDeclarativeBindingPrivate() -: updating(false), enabled(false) +: updating(false), enabled(false), columnNumber(0) { } @@ -239,7 +240,7 @@ QDeclarativeBinding::createBinding(Identifier id, QObject *obj, QDeclarativeCont typeData = engine->typeLoader.get(ctxtdata->url); cdata = typeData->compiledData(); } - QDeclarativeBinding *rv = cdata ? new QDeclarativeBinding(cdata->primitives.at(id), true, obj, ctxtdata, url, lineNumber, parent) : 0; + QDeclarativeBinding *rv = cdata ? new QDeclarativeBinding(cdata->primitives.at(id), true, obj, ctxtdata, url, lineNumber, 0, parent) : 0; if (cdata) cdata->release(); if (typeData) @@ -265,11 +266,15 @@ QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDecl QDeclarativeBinding::QDeclarativeBinding(const QString &str, bool isRewritten, QObject *obj, QDeclarativeContextData *ctxt, - const QString &url, int lineNumber, QObject *parent) + const QString &url, int lineNumber, int columnNumber, + QObject *parent) : QDeclarativeExpression(ctxt, obj, str, isRewritten, url, lineNumber, *new QDeclarativeBindingPrivate) { + Q_D(QDeclarativeBinding); + setParent(parent); setNotifyOnValueChanged(true); + d->columnNumber = columnNumber; } /*! @@ -351,6 +356,11 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) if (!d->enabled || !d->context() || !d->context()->isValid()) return; + QDeclarativeTrace trace("General Binding Update"); + trace.addDetail("URL", d->url); + trace.addDetail("Line", d->line); + trace.addDetail("Column", d->columnNumber); + if (!d->updating) { QDeclarativeBindingProfiler prof(this); d->updating = true; @@ -379,6 +389,8 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) v8::Context::Scope scope(ep->v8engine()->context()); v8::Local result = d->v8value(0, &isUndefined); + trace.event("writing binding result"); + bool needsErrorData = false; if (!watcher.wasDeleted() && !d->error.isValid()) needsErrorData = !QDeclarativePropertyPrivate::writeBinding(d->property, d, result, diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h index 8f4c736d6a..3fcb12b6c5 100644 --- a/src/declarative/qml/qdeclarativebinding_p.h +++ b/src/declarative/qml/qdeclarativebinding_p.h @@ -153,7 +153,7 @@ public: QDeclarativeBinding(const QString &, QObject *, QDeclarativeContext *, QObject *parent=0); QDeclarativeBinding(const QString &, QObject *, QDeclarativeContextData *, QObject *parent=0); QDeclarativeBinding(const QString &, bool isRewritten, QObject *, QDeclarativeContextData *, - const QString &url, int lineNumber, QObject *parent=0); + const QString &url, int lineNumber, int columnNumber = 0, QObject *parent=0); QDeclarativeBinding(void *, QObject *, QDeclarativeContextData *, QObject *parent=0); void setTarget(const QDeclarativeProperty &); diff --git a/src/declarative/qml/qdeclarativebinding_p_p.h b/src/declarative/qml/qdeclarativebinding_p_p.h index c704919f78..d5615455bd 100644 --- a/src/declarative/qml/qdeclarativebinding_p_p.h +++ b/src/declarative/qml/qdeclarativebinding_p_p.h @@ -77,6 +77,7 @@ protected: private: bool updating:1; bool enabled:1; + int columnNumber; QDeclarativeProperty property; }; diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 5500efa42f..44f1f5901d 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -3328,6 +3328,7 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *bindi store.isRoot = (compileState->root == obj); } store.line = binding->location.start.line; + store.column = binding->location.start.column; output->addInstruction(store); } else if (ref.dataType == BindingReference::V8) { Instruction::StoreV8Binding store; @@ -3340,6 +3341,7 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *bindi store.isRoot = (compileState->root == obj); } store.line = binding->location.start.line; + store.column = binding->location.start.column; Q_ASSERT(ref.bindingContext.owner == 0 || (ref.bindingContext.owner != 0 && valueTypeProperty)); @@ -3356,6 +3358,7 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeScript::Value *bindi store.assignBinding.context = ref.bindingContext.stack; store.assignBinding.owner = ref.bindingContext.owner; store.assignBinding.line = binding->location.start.line; + store.assignBinding.column = binding->location.start.column; if (valueTypeProperty) { store.assignBinding.isRoot = (compileState->root == valueTypeProperty->parent); diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 9a7d77115c..fdecd76da9 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -814,6 +814,7 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri void QDeclarativeComponent::completeCreate() { Q_D(QDeclarativeComponent); + d->completeCreate(); } diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index b36a664443..6da2fd834f 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -241,6 +241,7 @@ union QDeclarativeInstruction short owner; bool isRoot; ushort line; + ushort column; }; struct instr_assignBinding { QML_INSTR_HEADER @@ -250,6 +251,7 @@ union QDeclarativeInstruction short owner; bool isRoot; ushort line; + ushort column; }; struct instr_fetch { QML_INSTR_HEADER diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index aa31cad4f2..4f4e57c8d2 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -121,6 +121,11 @@ void QDeclarativeVME::init(QDeclarativeContextData *ctxt, QDeclarativeCompiledDa bindValues.allocate(i->init.bindingsSize); parserStatus.allocate(i->init.parserStatusSize); +#ifdef QML_ENABLE_TRACE + parserStatusData.allocate(i->init.parserStatusSize); + rootComponent = comp; +#endif + rootContext = 0; engine = ctxt->engine; } @@ -155,6 +160,11 @@ bool QDeclarativeVME::initDeferred(QObject *object) objects.push(object); +#ifdef QML_ENABLE_TRACE + parserStatusData.allocate(i->deferInit.parserStatusSize); + rootComponent = comp; +#endif + rootContext = 0; engine = ctxt->engine; @@ -177,6 +187,11 @@ QObject *QDeclarativeVME::execute(QList *errors, const Interr { Q_ASSERT(states.count() >= 1); +#ifdef QML_ENABLE_TRACE + QDeclarativeTrace trace("VME Execute"); + trace.addDetail("URL", rootComponent->url); +#endif + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(states.at(0).context->engine); ActiveVMERestorer restore(this, ep); @@ -715,6 +730,10 @@ QObject *QDeclarativeVME::run(QList *errors, QObject *target = objects.top(); QDeclarativeParserStatus *status = reinterpret_cast(reinterpret_cast(target) + instr.castValue); parserStatus.push(status); +#ifdef QML_ENABLE_TRACE + Q_ASSERT(QObjectPrivate::get(target)->declarativeData); + parserStatusData.push(static_cast(QObjectPrivate::get(target)->declarativeData)); +#endif status->d = &parserStatus.top(); status->classBegin(); @@ -735,7 +754,8 @@ QObject *QDeclarativeVME::run(QList *errors, QML_NEXT_INSTR(StoreBinding); QDeclarativeBinding *bind = new QDeclarativeBinding(PRIMITIVES.at(instr.value), true, - context, CTXT, COMP->name, instr.line); + context, CTXT, COMP->name, instr.line, + instr.column); bindValues.push(bind); bind->m_mePtr = &bindValues.top(); bind->setTarget(target, instr.property, CTXT); @@ -753,7 +773,8 @@ QObject *QDeclarativeVME::run(QList *errors, QML_NEXT_INSTR(StoreBindingOnAlias); QDeclarativeBinding *bind = new QDeclarativeBinding(PRIMITIVES.at(instr.value), true, - context, CTXT, COMP->name, instr.line); + context, CTXT, COMP->name, instr.line, + instr.column); bindValues.push(bind); bind->m_mePtr = &bindValues.top(); bind->setTarget(target, instr.property, CTXT); @@ -776,7 +797,8 @@ QObject *QDeclarativeVME::run(QList *errors, QML_NEXT_INSTR(StoreV4Binding); QDeclarativeAbstractBinding *binding = - CTXT->v4bindings->configBinding(instr.value, target, scope, property, instr.line); + CTXT->v4bindings->configBinding(instr.value, target, scope, property, + instr.line, instr.column); bindValues.push(binding); binding->m_mePtr = &bindValues.top(); binding->addToObject(target, property); @@ -793,7 +815,8 @@ QObject *QDeclarativeVME::run(QList *errors, QDeclarativeAbstractBinding *binding = CTXT->v8bindings->configBinding(instr.value, target, scope, - instr.property, instr.line); + instr.property, instr.line, + instr.column); bindValues.push(binding); binding->m_mePtr = &bindValues.top(); binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(instr.property)); @@ -1019,6 +1042,9 @@ void QDeclarativeVME::reset() lists.deallocate(); bindValues.deallocate(); parserStatus.deallocate(); +#ifdef QML_ENABLE_TRACE + parserStatusData.deallocate(); +#endif finalizeCallbacks.clear(); states.clear(); rootContext = 0; @@ -1158,9 +1184,17 @@ QDeclarativeContextData *QDeclarativeVME::complete(const Interrupt &interrupt) if (!engine) return 0; + QDeclarativeTrace trace("VME Complete"); +#ifdef QML_ENABLE_TRACE + trace.addDetail("URL", rootComponent->url); +#endif + ActiveVMERestorer restore(this, QDeclarativeEnginePrivate::get(engine)); QRecursionWatcher watcher(this); + { + QDeclarativeTrace trace("VME Binding Enable"); + trace.event("begin binding eval"); while (!bindValues.isEmpty()) { QDeclarativeAbstractBinding *b = bindValues.pop(); @@ -1174,12 +1208,23 @@ QDeclarativeContextData *QDeclarativeVME::complete(const Interrupt &interrupt) return 0; } bindValues.deallocate(); + } + { + QDeclarativeTrace trace("VME Component Complete"); while (!parserStatus.isEmpty()) { QDeclarativeParserStatus *status = parserStatus.pop(); +#ifdef QML_ENABLE_TRACE + QDeclarativeData *data = parserStatusData.pop(); +#endif if (status && status->d) { status->d = 0; +#ifdef QML_ENABLE_TRACE + QDeclarativeTrace trace("Component complete"); + trace.addDetail("URL", data->outerContext->url); + trace.addDetail("Line", data->lineNumber); +#endif status->componentComplete(); } @@ -1187,7 +1232,10 @@ QDeclarativeContextData *QDeclarativeVME::complete(const Interrupt &interrupt) return 0; } parserStatus.deallocate(); + } + { + QDeclarativeTrace trace("VME Finalize Callbacks"); for (int ii = 0; ii < finalizeCallbacks.count(); ++ii) { QDeclarativeEnginePrivate::FinalizeCallback callback = finalizeCallbacks.at(ii); QObject *obj = callback.first; @@ -1199,7 +1247,10 @@ QDeclarativeContextData *QDeclarativeVME::complete(const Interrupt &interrupt) return 0; } finalizeCallbacks.clear(); + } + { + QDeclarativeTrace trace("VME Component.onCompleted Callbacks"); while (componentAttached) { QDeclarativeComponentAttached *a = componentAttached; a->rem(); @@ -1212,6 +1263,7 @@ QDeclarativeContextData *QDeclarativeVME::complete(const Interrupt &interrupt) if (watcher.hasRecursed() || interrupt.shouldInterrupt()) return 0; } + } QDeclarativeContextData *rv = rootContext; diff --git a/src/declarative/qml/qdeclarativevme_p.h b/src/declarative/qml/qdeclarativevme_p.h index 4edceb283a..63cb7bef85 100644 --- a/src/declarative/qml/qdeclarativevme_p.h +++ b/src/declarative/qml/qdeclarativevme_p.h @@ -67,6 +67,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE class QObject; @@ -145,11 +147,19 @@ private: QDeclarativeEngine *engine; QRecursionNode recursion; +#ifdef QML_ENABLE_TRACE + QDeclarativeCompiledData *rootComponent; +#endif + QFiniteStack objects; QFiniteStack lists; QFiniteStack bindValues; QFiniteStack parserStatus; +#ifdef QML_ENABLE_TRACE + QFiniteStack parserStatusData; +#endif + QDeclarativeGuardedContextData rootContext; QDeclarativeGuardedContextData creationContext; diff --git a/src/declarative/qml/v4/qv4bindings.cpp b/src/declarative/qml/v4/qv4bindings.cpp index 2dc812f47b..04c410c15d 100644 --- a/src/declarative/qml/v4/qv4bindings.cpp +++ b/src/declarative/qml/v4/qv4bindings.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -212,7 +213,8 @@ QV4Bindings::~QV4Bindings() } QDeclarativeAbstractBinding *QV4Bindings::configBinding(int index, QObject *target, - QObject *scope, int property, int line) + QObject *scope, int property, + int line, int column) { Binding *rv = bindings + index; @@ -221,6 +223,7 @@ QDeclarativeAbstractBinding *QV4Bindings::configBinding(int index, QObject *targ rv->target = target; rv->scope = scope; rv->line = line; + rv->column = column; rv->parent = this; addref(); // This is decremented in Binding::destroy() @@ -270,8 +273,10 @@ void QV4Bindings::subscriptionNotify(int id) QV4Program::BindingReference *bindingRef = list->bindings + ii; Binding *binding = bindings + bindingRef->binding; - if (binding->executedBlocks & bindingRef->blockMask) + + if (binding->executedBlocks & bindingRef->blockMask) { run(binding, QDeclarativePropertyPrivate::DontRemoveBinding); + } } } @@ -284,6 +289,11 @@ void QV4Bindings::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags if (!context || !context->isValid()) return; + QDeclarativeTrace trace("V4 Binding Update"); + trace.addDetail("URL", context->url); + trace.addDetail("Line", binding->line); + trace.addDetail("Column", binding->column); + if (binding->updating) { QString name; if (binding->property & 0xFFFF0000) { diff --git a/src/declarative/qml/v4/qv4bindings_p.h b/src/declarative/qml/v4/qv4bindings_p.h index b961cc53fd..b9e368599b 100644 --- a/src/declarative/qml/v4/qv4bindings_p.h +++ b/src/declarative/qml/v4/qv4bindings_p.h @@ -72,7 +72,8 @@ public: virtual ~QV4Bindings(); QDeclarativeAbstractBinding *configBinding(int index, QObject *target, - QObject *scope, int property, int line); + QObject *scope, int property, + int line, int column); #ifdef QML_THREADED_INTERPRETER static void **getDecodeInstrTable(); @@ -96,6 +97,7 @@ private: int property; QObject *scope; int line; + int column; QObject *target; quint32 executedBlocks; diff --git a/src/declarative/qml/v8/qv8bindings.cpp b/src/declarative/qml/v8/qv8bindings.cpp index 3386c5ddc8..510d6138f6 100644 --- a/src/declarative/qml/v8/qv8bindings.cpp +++ b/src/declarative/qml/v8/qv8bindings.cpp @@ -48,11 +48,12 @@ #include #include #include +#include QT_BEGIN_NAMESPACE QV8Bindings::Binding::Binding() -: index(-1), enabled(false), updating(false), line(-1), object(0), parent(0) +: index(-1), enabled(false), updating(false), line(-1), column(-1), object(0), parent(0) { } @@ -75,6 +76,11 @@ void QV8Bindings::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags) if (!enabled) return; + QDeclarativeTrace trace("V8 Binding Update"); + trace.addDetail("URL", parent->url); + trace.addDetail("Line", line); + trace.addDetail("Column", column); + QDeclarativeContextData *context = QDeclarativeAbstractExpression::context(); if (!context || !context->isValid()) return; @@ -93,6 +99,7 @@ void QV8Bindings::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags) v8::Local result = evaluate(v8::Handle::Cast(parent->functions->Get(index)), &isUndefined); + trace.event("writing V8 result"); bool needsErrorData = false; if (!watcher.wasDeleted() && !error.isValid()) { typedef QDeclarativePropertyPrivate PP; @@ -183,11 +190,12 @@ QV8Bindings::~QV8Bindings() QDeclarativeAbstractBinding *QV8Bindings::configBinding(int index, QObject *target, QObject *scope, const QDeclarativePropertyData &p, - int line) + int line, int column) { QV8Bindings::Binding *rv = bindings + index; rv->line = line; + rv->column = column; rv->index = index; rv->object = target; rv->property = p; diff --git a/src/declarative/qml/v8/qv8bindings_p.h b/src/declarative/qml/v8/qv8bindings_p.h index 904062551d..12dd5d791b 100644 --- a/src/declarative/qml/v8/qv8bindings_p.h +++ b/src/declarative/qml/v8/qv8bindings_p.h @@ -75,7 +75,7 @@ public: QDeclarativeAbstractBinding *configBinding(int index, QObject *target, QObject *scope, const QDeclarativePropertyData &prop, - int line); + int line, int column); private: Q_DISABLE_COPY(QV8Bindings) @@ -100,6 +100,7 @@ private: bool enabled:1; bool updating:1; int line; + int column; QObject *object; QDeclarativePropertyData property; QV8Bindings *parent; -- cgit v1.2.3