Speed up binding evaluation
authorSimon Hausmann <simon.hausmann@theqtcompany.com>
Fri, 10 Apr 2015 10:34:36 +0000 (12:34 +0200)
committerSimon Hausmann <simon.hausmann@theqtcompany.com>
Thu, 16 Apr 2015 10:56:03 +0000 (10:56 +0000)
Don't spend any cycles of determining the location of the binding (file, line,
column) unless we really need that information. That's the case when the profiler
is active or an error happens.

Change-Id: Iae97808d500b88fed6a813e8b224aa6ebe04d3b6
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/debugger/qqmlprofiler_p.h
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4functionobject_p.h
src/qml/qml/qqmlbinding.cpp
src/qml/qml/qqmljavascriptexpression.cpp
src/qml/qml/qqmljavascriptexpression_p.h

index ba85a76277eeb6d5ee95182dfce50726ad9ca0bf..5c994b112f3b26dff249357e72b9865cc7f149ea 100644 (file)
@@ -112,11 +112,11 @@ Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
 class QQmlProfiler : public QObject, public QQmlProfilerDefinitions {
     Q_OBJECT
 public:
-    void startBinding(const QString &fileName, int line, int column)
+    void startBinding(const QQmlSourceLocation &location)
     {
         m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
                                        (1 << RangeStart | 1 << RangeLocation), 1 << Binding,
-                                       fileName, line, column));
+                                       location.sourceFile, qmlSourceCoordinate(location.line), qmlSourceCoordinate(location.column)));
     }
 
     // Have toByteArrays() construct another RangeData event from the same QString later.
@@ -201,11 +201,11 @@ struct QQmlProfilerHelper : public QQmlProfilerDefinitions {
 };
 
 struct QQmlBindingProfiler : public QQmlProfilerHelper {
-    QQmlBindingProfiler(QQmlProfiler *profiler, const QString &url, int line, int column) :
+    QQmlBindingProfiler(QQmlProfiler *profiler, const QV4::FunctionObject *function) :
         QQmlProfilerHelper(profiler)
     {
         Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileBinding, profiler,
-                      startBinding(url, line, column));
+                      startBinding(function->sourceLocation()));
     }
 
     ~QQmlBindingProfiler()
index 5be638e909e98684b761e7f024f94e583516b05a..f7433e63656798506b83abacdd6584c127baac4d 100644 (file)
@@ -210,6 +210,18 @@ bool FunctionObject::isBoundFunction() const
     return d()->vtable == BoundFunction::staticVTable();
 }
 
+QQmlSourceLocation FunctionObject::sourceLocation() const
+{
+    if (isBinding()) {
+        Q_ASSERT(as<const QV4::QQmlBindingFunction>());
+        return static_cast<QV4::Heap::QQmlBindingFunction *>(d())->bindingLocation;
+    }
+    QV4::Function *function = d()->function;
+    Q_ASSERT(function);
+
+    return QQmlSourceLocation(function->sourceFile(), function->compiledFunction->location.line, function->compiledFunction->location.column);
+}
+
 DEFINE_OBJECT_VTABLE(FunctionCtor);
 
 Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope)
index 3433e7b8ca52e95e21ea116c504f205cfd0c5800..560061a70558afbba4346cef4a27ff093086c9b4 100644 (file)
@@ -40,6 +40,8 @@
 
 QT_BEGIN_NAMESPACE
 
+struct QQmlSourceLocation;
+
 namespace QV4 {
 
 namespace Heap {
@@ -140,6 +142,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
     bool isBinding() const;
     bool isBoundFunction() const;
 
+    QQmlSourceLocation sourceLocation() const;
+
     static void markObjects(Heap::Base *that, ExecutionEngine *e);
 };
 
index ff794f5f09bed58002e470adbb14a2f5eef9e42c..0db696394cb8fe0e47955a0c7b1d90dd10ba4a98 100644 (file)
@@ -165,34 +165,13 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
     if (QQmlData::wasDeleted(object()))
         return;
 
-    QString url;
-    quint16 lineNumber;
-    quint16 columnNumber;
-
     QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
     QV4::Scope scope(ep->v4engine());
     QV4::ScopedFunctionObject f(scope, v4function.value());
     Q_ASSERT(f);
-    if (f->isBinding()) {
-        Q_ASSERT(f->as<QV4::QQmlBindingFunction>());
-        QQmlSourceLocation loc = static_cast<QV4::Heap::QQmlBindingFunction *>(f->d())->bindingLocation;
-        url = loc.sourceFile;
-        lineNumber = loc.line;
-        columnNumber = loc.column;
-    } else {
-        QV4::Function *function = f->asFunctionObject()->function();
-        Q_ASSERT(function);
-
-        url = function->sourceFile();
-        lineNumber = function->compiledFunction->location.line;
-        columnNumber = function->compiledFunction->location.column;
-    }
-
-    int lineNo = qmlSourceCoordinate(lineNumber);
-    int columnNo = qmlSourceCoordinate(columnNumber);
 
     if (!updatingFlag()) {
-        QQmlBindingProfiler prof(ep->profiler, url, lineNo, columnNo);
+        QQmlBindingProfiler prof(ep->profiler, f);
         setUpdatingFlag(true);
 
         QQmlAbstractExpression::DeleteWatcher watcher(this);
@@ -222,7 +201,7 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
             if (!watcher.wasDeleted()) {
 
                 if (needsErrorLocationData)
-                    delayedError()->setErrorLocation(QUrl(url), lineNumber, columnNumber);
+                    delayedError()->setErrorLocation(f->sourceLocation());
 
                 if (hasError()) {
                     if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine));
index 3ac0f23e4df2b983379cf894cb42b22222ff2336..02bd1c4b83fc442d479568c28c79688ba4deefab 100644 (file)
@@ -40,6 +40,7 @@
 #include <private/qv4script_p.h>
 #include <private/qv4errorobject_p.h>
 #include <private/qv4scopedvalue_p.h>
+#include <private/qqmlglobal_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -59,11 +60,11 @@ bool QQmlDelayedError::addError(QQmlEnginePrivate *e)
     return true;
 }
 
-void QQmlDelayedError::setErrorLocation(const QUrl &url, quint16 line, quint16 column)
+void QQmlDelayedError::setErrorLocation(const QQmlSourceLocation &sourceLocation)
 {
-    m_error.setUrl(url);
-    m_error.setLine(line);
-    m_error.setColumn(column);
+    m_error.setUrl(QUrl(sourceLocation.sourceFile));
+    m_error.setLine(sourceLocation.line);
+    m_error.setColumn(sourceLocation.column);
 }
 
 void QQmlDelayedError::setErrorDescription(const QString &description)
index 3f1a8c173d77c97e2c5e6e4bb6f0398d8869fbf3..cbbd88f1fcae65b5a4acb96d1b43624ada3bfb40 100644 (file)
@@ -52,6 +52,8 @@
 
 QT_BEGIN_NAMESPACE
 
+class QQmlSourceLocation;
+
 class QQmlDelayedError
 {
 public:
@@ -72,7 +74,7 @@ public:
     inline const QQmlError &error() const { return m_error; }
     inline void clearError() { m_error = QQmlError(); }
 
-    void setErrorLocation(const QUrl &url, quint16 line, quint16 column);
+    void setErrorLocation(const QQmlSourceLocation &sourceLocation);
     void setErrorDescription(const QString &description);
     void setErrorObject(QObject *object);