Speedup the V4 code generation.
authorRoberto Raggi <roberto.raggi@nokia.com>
Thu, 21 Jul 2011 12:47:26 +0000 (14:47 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 30 Aug 2011 11:18:28 +0000 (13:18 +0200)
Skip discarded code and use QVarLengthArray instead of
QByteArray to store the bytecode.

Change-Id: I4c574e7a817595bc8942ed9a927e79339a2d7b40
Reviewed-on: http://codereview.qt.nokia.com/3760
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>

src/declarative/qml/v4/qdeclarativev4compiler.cpp
src/declarative/qml/v4/qdeclarativev4instruction.cpp
src/declarative/qml/v4/qdeclarativev4instruction_p.h
src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
src/declarative/qml/v4/qdeclarativev4irbuilder_p.h

index 4890722..c77a737 100644 (file)
@@ -85,7 +85,7 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column)
     currentBlockMask = 0x00000001;
 
 
-    for (int i = 0; i < blocks.size(); ++i) {
+    for (int i = 0; !_discarded && i < blocks.size(); ++i) {
         IR::BasicBlock *block = blocks.at(i);
         IR::BasicBlock *next = i + 1 < blocks.size() ? blocks.at(i + 1) : 0;
         if (IR::Stmt *terminator = block->terminator()) {
@@ -137,8 +137,10 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column)
         blockop.block(currentBlockMask);
         gen(blockop);
 
-        foreach (IR::Stmt *s, block->statements)
-            s->accept(this);
+        foreach (IR::Stmt *s, block->statements) {
+            if (! _discarded)
+                s->accept(this);
+        }
 
         qSwap(usedSubscriptionIdsChanged, usic);
 
@@ -148,7 +150,7 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column)
                 return;
             }
             currentBlockMask <<= 1;
-        } else {
+        } else if (! _discarded) {
             const int adjust = bytecode.remove(blockopIndex);
             // Correct patches
             for (int ii = patchesCount; ii < patches.count(); ++ii) 
@@ -164,13 +166,15 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column)
 #endif
 
 
-    // back patching
-    foreach (const Patch &patch, patches) {
-        Instr &instr = bytecode[patch.offset];
-        instr.branchop.offset = patch.block->offset - patch.offset - instr.size();
-    }
+    if (! _discarded) {
+        // back patching
+        foreach (const Patch &patch, patches) {
+            Instr &instr = bytecode[patch.offset];
+            instr.branchop.offset = patch.block->offset - patch.offset - instr.size();
+        }
 
-    patches.clear();
+        patches.clear();
+    }
 }
 
 void QDeclarativeV4CompilerPrivate::trace(QVector<IR::BasicBlock *> *blocks)
@@ -1005,7 +1009,7 @@ int QDeclarativeV4CompilerPrivate::commitCompile()
     int rv = committed.count();
     committed.offsets << committed.bytecode.count();
     committed.dependencies << usedSubscriptionIds;
-    committed.bytecode += bytecode.code();
+    committed.bytecode.append(bytecode.constData(), bytecode.size());
     committed.data = data;
     committed.exceptions = exceptions;
     committed.subscriptionIds = subscriptionIds;
@@ -1280,8 +1284,10 @@ QByteArray QDeclarativeV4Compiler::program() const
         }
 
 
-        QByteArray bytecode = bc.code();
-        bytecode += d->committed.bytecode;
+        QByteArray bytecode;
+        bytecode.reserve(bc.size() + d->committed.bytecode.size());
+        bytecode.append(bc.constData(), bc.size());
+        bytecode.append(d->committed.bytecode.constData(), d->committed.bytecode.size());
 
         QByteArray data = d->committed.data;
         while (data.count() % 4) data.append('\0');
index a520a35..93bb206 100644 (file)
@@ -512,6 +512,8 @@ void Instr::block(quint32 mask)
 
 Bytecode::Bytecode()
 {
+    d.reserve(8 * 1024);
+
 #ifdef QML_THREADED_INTERPRETER
     decodeInstr = QDeclarativeV4Bindings::getDecodeInstrTable();
 #endif
@@ -530,12 +532,6 @@ void Bytecode::append(const Instr &instr)
     d.append(it, instr.size());
 }
 
-void Bytecode::append(const QVector<Instr> &instrs)
-{
-    foreach (const Instr &i, instrs)
-        append(i);
-}
-
 int Bytecode::remove(int offset)
 {
     const Instr *instr = (const Instr *) (d.begin() + offset);
index e3ac902..6efe933 100644 (file)
@@ -56,6 +56,7 @@
 #include <QtCore/qglobal.h>
 #include <QtCore/qbytearray.h>
 #include <QtCore/qvector.h>
+#include <QtCore/qvarlengtharray.h>
 
 QT_BEGIN_HEADER
 
@@ -414,21 +415,27 @@ class Bytecode
 public:
     Bytecode();
 
-    QByteArray code() const { return d; }
     const char *constData() const { return d.constData(); }
     int size() const { return d.size(); }
     int count() const { return d.count(); }
     void clear() { d.clear(); }
     bool isEmpty() const { return d.isEmpty(); }
     void append(const Instr &instr);
-    void append(const QVector<Instr> &instrs);
+
+    template <typename _It>
+    void append(_It it, _It last)
+    {
+        for (; it != last; ++it)
+            append(*it);
+    }
+
     int remove(int index);
 
     const Instr &operator[](int offset) const;
     Instr &operator[](int offset);
 
 private:
-    QByteArray d;
+    QVarLengthArray<char, 4 * 1024> d;
 #ifdef QML_THREADED_INTERPRETER
     void **decodeInstr;
 #endif
index 915bf5f..18a52bb 100644 (file)
@@ -136,12 +136,12 @@ QDeclarativeV4IRBuilder::operator()(QDeclarativeJS::IR::Module *module,
     return discarded?0:function;
 }
 
-bool QDeclarativeV4IRBuilder::buildName(QStringList &name,
+bool QDeclarativeV4IRBuilder::buildName(QList<QStringRef> &name,
                                               AST::Node *node,
                                               QList<AST::ExpressionNode *> *nodes)
 {
     if (node->kind == AST::Node::Kind_IdentifierExpression) {
-        name << static_cast<AST::IdentifierExpression*>(node)->name.toString();
+        name << static_cast<AST::IdentifierExpression*>(node)->name;
         if (nodes) *nodes << static_cast<AST::IdentifierExpression*>(node);
     } else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
         AST::FieldMemberExpression *expr =
@@ -150,7 +150,7 @@ bool QDeclarativeV4IRBuilder::buildName(QStringList &name,
         if (!buildName(name, expr->base, nodes))
             return false;
 
-        name << expr->name.toString();
+        name << expr->name;
         if (nodes) *nodes << expr;
     } else {
         return false;
@@ -683,6 +683,11 @@ bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast)
     return false;
 }
 
+bool QDeclarativeV4IRBuilder::preVisit(AST::Node *ast)
+{
+    return ! _discard;
+}
+
 bool QDeclarativeV4IRBuilder::visit(AST::NewMemberExpression *)
 {
     return false;
@@ -695,14 +700,22 @@ bool QDeclarativeV4IRBuilder::visit(AST::NewExpression *)
 
 bool QDeclarativeV4IRBuilder::visit(AST::CallExpression *ast)
 {
-    QStringList names;
+    QList<QStringRef> names;
     QList<AST::ExpressionNode *> nameNodes;
+
+    names.reserve(4);
+    nameNodes.reserve(4);
+
     if (buildName(names, ast->base, &nameNodes)) {
         //ExprResult base = expression(ast->base);
-        const QString id = names.join(QLatin1String("."));
-        const quint32 line = nameNodes.last()->firstSourceLocation().startLine;
-        const quint32 column = nameNodes.last()->firstSourceLocation().startColumn;
-        IR::Expr *base = _block->NAME(id, line, column);
+        QString id;
+        for (int i = 0; i < names.size(); ++i) {
+            if (! i)
+                id += QLatin1Char('.');
+            id += names.at(i);
+        }
+        const AST::SourceLocation loc = nameNodes.last()->firstSourceLocation();
+        IR::Expr *base = _block->NAME(id, loc.startLine, loc.startColumn);
 
         IR::ExprList *args = 0, **argsInserter = &args;
         for (AST::ArgumentList *it = ast->arguments; it; it = it->next) {
index 69f9cba..47f5b3f 100644 (file)
@@ -115,6 +115,8 @@ protected:
 
     void implicitCvt(ExprResult &expr, QDeclarativeJS::IR::Type type);
 
+    virtual bool preVisit(QDeclarativeJS::AST::Node *ast);
+
     // QML
     virtual bool visit(QDeclarativeJS::AST::UiProgram *ast);
     virtual bool visit(QDeclarativeJS::AST::UiImportList *ast);
@@ -220,7 +222,7 @@ protected:
     virtual bool visit(QDeclarativeJS::AST::DebuggerStatement *ast);
 
 private:
-    bool buildName(QStringList &name, QDeclarativeJS::AST::Node *node, 
+    bool buildName(QList<QStringRef> &name, QDeclarativeJS::AST::Node *node,
                    QList<QDeclarativeJS::AST::ExpressionNode *> *nodes);
     void discard();