diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2011-09-20 11:38:26 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-09-22 09:42:43 +0200 |
commit | defa339b371204788504d41bea737d05a5d53285 (patch) | |
tree | 81978150129ac7b9420fa170e3e89638569f6089 /src/declarative/qml/qdeclarativevme.cpp | |
parent | 7edf2597d15d2f913d9d59815f45170888de7f78 (diff) |
Make the QML/VME interpreter threaded
This gets rid of the two-level dispatch in the
interpreter loop, which gives a nice performance boost
when many VME instructions must be interpreted
(e.g., 40% faster for 100 StoreInteger instructions).
The threading is implemented in a similar way to the
V4 interpreter.
The way the compiler generates instructions has been
refactored, chiefly to get rid of the
QDeclarativeInstruction::setType() calls (when using
threading, we don't store the instruction type at all,
only the address).
As a nice bonus, the way instructions are defined now
(creating the specific instruction's data type, rather
than a generic (union) type) is more compact and less
error-prone.
Change-Id: If5cbd36b2526fd61b74854712711b06cd7e1ed7d
Reviewed-on: http://codereview.qt-project.org/5246
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Diffstat (limited to 'src/declarative/qml/qdeclarativevme.cpp')
-rw-r--r-- | src/declarative/qml/qdeclarativevme.cpp | 77 |
1 files changed, 66 insertions, 11 deletions
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 79ff82232a..4ed7cf4464 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -166,22 +166,55 @@ static void removeBindingOnProperty(QObject *o, int index) if (binding) binding->destroy(); } -#define QML_BEGIN_INSTR(I) \ - case QDeclarativeInstruction::I: { \ - const QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::DataType &instr = QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::data(genericInstr); \ - instructionStream += QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::Size; \ - Q_UNUSED(instr); +#define QML_BEGIN_INSTR_COMMON(I) { \ + const QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::DataType &instr = QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::data(*genericInstr); \ + instructionStream += QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::Size; \ + Q_UNUSED(instr); + +#ifdef QML_THREADED_VME_INTERPRETER +# define QML_BEGIN_INSTR(I) op_##I: \ + QML_BEGIN_INSTR_COMMON(I) + +# define QML_NEXT_INSTR(I) { \ + genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(instructionStream); \ + goto *genericInstr->common.code; \ + } + +# define QML_END_INSTR(I) } \ + genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(instructionStream); \ + goto *genericInstr->common.code; -#define QML_NEXT_INSTR(I) break; -#define QML_END_INSTR(I) } break; +#else +# define QML_BEGIN_INSTR(I) \ + case QDeclarativeInstruction::I: \ + QML_BEGIN_INSTR_COMMON(I) + +# define QML_NEXT_INSTR(I) break; +# define QML_END_INSTR(I) } break; +#endif #define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index) QObject *QDeclarativeVME::run(QDeclarativeVMEObjectStack &stack, QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp, - int start, const QBitField &bindingSkipList) + int start, const QBitField &bindingSkipList +#ifdef QML_THREADED_VME_INTERPRETER + , void ***storeJumpTable +#endif + ) { +#ifdef QML_THREADED_VME_INTERPRETER + if (storeJumpTable) { +#define QML_INSTR_ADDR(I, FMT) &&op_##I, + static void *jumpTable[] = { + FOR_EACH_QML_INSTR(QML_INSTR_ADDR) + }; +#undef QML_INSTR_ADDR + *storeJumpTable = jumpTable; + return 0; + } +#endif Q_ASSERT(comp); Q_ASSERT(ctxt); const QList<QDeclarativeCompiledData::TypeReference> &types = comp->types; @@ -205,10 +238,15 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEObjectStack &stack, const char *instructionStream = comp->bytecode.constData() + start; +#ifdef QML_THREADED_VME_INTERPRETER + const QDeclarativeInstruction *genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(instructionStream); + goto *genericInstr->common.code; +#else for (;;) { - const QDeclarativeInstruction &genericInstr = *((QDeclarativeInstruction *)instructionStream); + const QDeclarativeInstruction *genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(instructionStream); - switch(genericInstr.type()) { + switch (genericInstr->common.instructionType) { +#endif QML_BEGIN_INSTR(Init) if (instr.bindingsSize) bindValues = QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding>(instr.bindingsSize); @@ -966,11 +1004,15 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEObjectStack &stack, valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor); QML_END_INSTR(PopValueType) +#ifdef QML_THREADED_VME_INTERPRETER + // nothing to do +#else default: - qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr.type()); + qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr->common.instructionType); break; } } +#endif exceptionExit: Q_ASSERT(isError()); @@ -1109,6 +1151,19 @@ v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentC return rv; } +#ifdef QML_THREADED_VME_INTERPRETER +void **QDeclarativeVME::instructionJumpTable() +{ + static void **jumpTable = 0; + if (!jumpTable) { + QDeclarativeVME dummy; + QDeclarativeVMEObjectStack stack; + dummy.run(stack, 0, 0, 0, QBitField(), &jumpTable); + } + return jumpTable; +} +#endif + template<typename T> QDeclarativeVMEStack<T>::QDeclarativeVMEStack() : _index(-1) |