aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-05-10 09:42:18 +0200
committerLars Knoll <lars.knoll@qt.io>2017-05-19 06:23:01 +0000
commit7ed93899e9305ccd538361ee58baa4bf15ff8a41 (patch)
treee5de061ca2b93cb5d9673bb0d5ffbcab1c5607d2 /src/qml
parent2affe19182b99d8d1c9655fa0c58c8af3e0b9506 (diff)
Optimizations to the generated byte code
Cut the size of the generated byte code in half, by storing parameters in a more compact form and always storing the instruction type in the instruction. We can still used computed goto's for a fast interpreter, by looking up the jump point for the next instruction in the jump table. Another advantage is that the byte code is now platform independent (modulo endianness). The change comes with a 3% performance impact on x86_64, which is acceptable considering the size savings on the bytecode. Change-Id: I37de3e1f94611987a85e65ea86536583aa965d6d Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h10
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp55
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp32
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h10
4 files changed, 10 insertions, 97 deletions
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index fbd6ac8f99..dabda7bae8 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -170,11 +170,7 @@ QT_BEGIN_NAMESPACE
#define MOTH_INSTR_ALIGN_MASK (Q_ALIGNOF(QV4::Moth::Instr) - 1)
-#ifdef MOTH_THREADED_INTERPRETER
-# define MOTH_INSTR_HEADER union { quint32 instructionType; void *code; };
-#else
-# define MOTH_INSTR_HEADER quint32 instructionType;
-#endif
+#define MOTH_INSTR_HEADER quint32 instructionType;
#define MOTH_INSTR_ENUM(I, FMT) I,
#define MOTH_INSTR_SIZE(I, FMT) ((sizeof(QV4::Moth::Instr::instr_##FMT) + MOTH_INSTR_ALIGN_MASK) & ~MOTH_INSTR_ALIGN_MASK)
@@ -194,8 +190,8 @@ struct Param {
// Arg(outer): 4
// Local(outer): 5
// ...
- unsigned scope;
- unsigned index;
+ unsigned scope : 12;
+ unsigned index : 20;
bool isConstant() const { return !scope; }
bool isArgument() const { return scope >= 2 && !(scope &1); }
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index dc6fe317e5..fb805dce02 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -1436,29 +1436,6 @@ CompilationUnit::~CompilationUnit()
void CompilationUnit::linkBackendToEngine(QV4::ExecutionEngine *engine)
{
-#ifdef MOTH_THREADED_INTERPRETER
- // link byte code against addresses of instructions
- for (int i = 0; i < codeRefs.count(); ++i) {
- QByteArray &codeRef = codeRefs[i];
- char *code = codeRef.data();
- int index = 0;
- while (index < codeRef.size()) {
- Instr *genericInstr = reinterpret_cast<Instr *>(code + index);
-
- switch (genericInstr->common.instructionType) {
-#define LINK_INSTRUCTION(InstructionType, Member) \
- case Instr::InstructionType: \
- genericInstr->common.code = VME::instructionJumpTable()[static_cast<int>(genericInstr->common.instructionType)]; \
- index += InstrMeta<(int)Instr::InstructionType>::Size; \
- break;
-
- FOR_EACH_MOTH_INSTR(LINK_INSTRUCTION)
-
- }
- }
- }
-#endif
-
runtimeFunctions.resize(data->functionTableSize);
runtimeFunctions.fill(0);
for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
@@ -1516,17 +1493,6 @@ bool CompilationUnit::saveCodeToDisk(QIODevice *device, const CompiledData::Unit
QByteArray padding;
-#if defined(MOTH_THREADED_INTERPRETER) && !defined(V4_BOOTSTRAP)
- // Map from instruction label back to instruction type. Only needed when persisting
- // already linked compilation units;
- QHash<void*, int> reverseInstructionMapping;
- if (engine) {
- void **instructions = VME::instructionJumpTable();
- for (int i = 0; i < Instr::LastInstruction; ++i)
- reverseInstructionMapping.insert(instructions[i], i);
- }
-#endif
-
for (int i = 0; i < codeRefs.size(); ++i) {
const CompiledData::Function *compiledFunction = unit->functionAt(i);
@@ -1545,27 +1511,6 @@ bool CompilationUnit::saveCodeToDisk(QIODevice *device, const CompiledData::Unit
QByteArray code = codeRefs.at(i);
-#if defined(MOTH_THREADED_INTERPRETER) && !defined(V4_BOOTSTRAP)
- if (!reverseInstructionMapping.isEmpty()) {
- char *codePtr = code.data(); // detaches
- int index = 0;
- while (index < code.size()) {
- Instr *genericInstr = reinterpret_cast<Instr *>(codePtr + index);
-
- genericInstr->common.instructionType = reverseInstructionMapping.value(genericInstr->common.code);
-
- switch (genericInstr->common.instructionType) {
- #define REVERSE_INSTRUCTION(InstructionType, Member) \
- case Instr::InstructionType: \
- index += InstrMeta<(int)Instr::InstructionType>::Size; \
- break;
-
- FOR_EACH_MOTH_INSTR(REVERSE_INSTRUCTION)
- }
- }
- }
-#endif
-
written = device->write(code.constData(), compiledFunction->codeSize);
if (written != qint64(compiledFunction->codeSize)) {
*errorString = device->errorString();
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index a74016ab0c..2288d9ef0a 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -304,7 +304,7 @@ using namespace QV4::Moth;
# define MOTH_END_INSTR(I) } \
genericInstr = reinterpret_cast<const Instr *>(code); \
- goto *genericInstr->common.code; \
+ goto *jumpTable[genericInstr->common.instructionType]; \
#else
@@ -356,11 +356,7 @@ Param traceParam(const Param &param)
if (engine->hasException) \
goto catchException
-QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
-#ifdef MOTH_THREADED_INTERPRETER
- , void ***storeJumpTable
-#endif
- )
+QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code)
{
#ifdef DO_TRACE_INSTR
qDebug("Starting VME with context=%p and code=%p", context, code);
@@ -369,15 +365,11 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
qt_v4ResolvePendingBreakpointsHook();
#ifdef MOTH_THREADED_INTERPRETER
- if (storeJumpTable) {
#define MOTH_INSTR_ADDR(I, FMT) &&op_##I,
- static void *jumpTable[] = {
- FOR_EACH_MOTH_INSTR(MOTH_INSTR_ADDR)
- };
+ static void *jumpTable[] = {
+ FOR_EACH_MOTH_INSTR(MOTH_INSTR_ADDR)
+ };
#undef MOTH_INSTR_ADDR
- *storeJumpTable = jumpTable;
- return QV4::Primitive::undefinedValue().asReturnedValue();
- }
#endif
QV4::Value *stack = 0;
@@ -428,7 +420,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
for (;;) {
const Instr *genericInstr = reinterpret_cast<const Instr *>(code);
#ifdef MOTH_THREADED_INTERPRETER
- goto *genericInstr->common.code;
+ goto *jumpTable[genericInstr->common.instructionType];
#else
switch (genericInstr->common.instructionType) {
#endif
@@ -960,18 +952,6 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
}
}
-#ifdef MOTH_THREADED_INTERPRETER
-void **VME::instructionJumpTable()
-{
- static void **jumpTable = 0;
- if (!jumpTable) {
- const uchar *code = 0;
- VME().run(0, code, &jumpTable);
- }
- return jumpTable;
-}
-#endif
-
QV4::ReturnedValue VME::exec(ExecutionEngine *engine, const uchar *code)
{
VME vme;
diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h
index f8893509d9..8d46207f2b 100644
--- a/src/qml/jsruntime/qv4vme_moth_p.h
+++ b/src/qml/jsruntime/qv4vme_moth_p.h
@@ -67,16 +67,8 @@ class VME
public:
static QV4::ReturnedValue exec(QV4::ExecutionEngine *, const uchar *);
-#ifdef MOTH_THREADED_INTERPRETER
- static void **instructionJumpTable();
-#endif
-
private:
- QV4::ReturnedValue run(QV4::ExecutionEngine *, const uchar *code
-#ifdef MOTH_THREADED_INTERPRETER
- , void ***storeJumpTable = 0
-#endif
- );
+ QV4::ReturnedValue run(QV4::ExecutionEngine *, const uchar *code);
};
} // namespace Moth