From 039432362d9c0897f4fbe4334c1d9c99aaf98be8 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 21 Jul 2011 14:47:26 +0200 Subject: [PATCH] Speedup the V4 code generation. 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 Reviewed-by: Qt Sanity Bot --- src/declarative/qml/v4/qdeclarativev4compiler.cpp | 32 ++++++++++++-------- .../qml/v4/qdeclarativev4instruction.cpp | 8 +---- .../qml/v4/qdeclarativev4instruction_p.h | 13 ++++++-- src/declarative/qml/v4/qdeclarativev4irbuilder.cpp | 29 +++++++++++++----- src/declarative/qml/v4/qdeclarativev4irbuilder_p.h | 4 ++- 5 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/declarative/qml/v4/qdeclarativev4compiler.cpp b/src/declarative/qml/v4/qdeclarativev4compiler.cpp index 4890722..c77a737 100644 --- a/src/declarative/qml/v4/qdeclarativev4compiler.cpp +++ b/src/declarative/qml/v4/qdeclarativev4compiler.cpp @@ -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 *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'); diff --git a/src/declarative/qml/v4/qdeclarativev4instruction.cpp b/src/declarative/qml/v4/qdeclarativev4instruction.cpp index a520a35..93bb206 100644 --- a/src/declarative/qml/v4/qdeclarativev4instruction.cpp +++ b/src/declarative/qml/v4/qdeclarativev4instruction.cpp @@ -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 &instrs) -{ - foreach (const Instr &i, instrs) - append(i); -} - int Bytecode::remove(int offset) { const Instr *instr = (const Instr *) (d.begin() + offset); diff --git a/src/declarative/qml/v4/qdeclarativev4instruction_p.h b/src/declarative/qml/v4/qdeclarativev4instruction_p.h index e3ac902..6efe933 100644 --- a/src/declarative/qml/v4/qdeclarativev4instruction_p.h +++ b/src/declarative/qml/v4/qdeclarativev4instruction_p.h @@ -56,6 +56,7 @@ #include #include #include +#include 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 &instrs); + + template + 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 d; #ifdef QML_THREADED_INTERPRETER void **decodeInstr; #endif diff --git a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp index 915bf5f..18a52bb 100644 --- a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp +++ b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp @@ -136,12 +136,12 @@ QDeclarativeV4IRBuilder::operator()(QDeclarativeJS::IR::Module *module, return discarded?0:function; } -bool QDeclarativeV4IRBuilder::buildName(QStringList &name, +bool QDeclarativeV4IRBuilder::buildName(QList &name, AST::Node *node, QList *nodes) { if (node->kind == AST::Node::Kind_IdentifierExpression) { - name << static_cast(node)->name.toString(); + name << static_cast(node)->name; if (nodes) *nodes << static_cast(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 names; QList 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) { diff --git a/src/declarative/qml/v4/qdeclarativev4irbuilder_p.h b/src/declarative/qml/v4/qdeclarativev4irbuilder_p.h index 69f9cba..47f5b3f 100644 --- a/src/declarative/qml/v4/qdeclarativev4irbuilder_p.h +++ b/src/declarative/qml/v4/qdeclarativev4irbuilder_p.h @@ -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 &name, QDeclarativeJS::AST::Node *node, QList *nodes); void discard(); -- 1.7.2.5