aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-06-12 14:56:03 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2017-06-19 13:34:55 +0000
commit2c0db96b0ea1b8d4daa5d0fda8b9b22270b5ab4b (patch)
tree46cdcb6f5026716a2c9fdf8c7c7047879f0c33eb /src/qml/compiler
parent74149e479ce4252c2a22638bed002985b09b8269 (diff)
Add a BytecodeGenerator class
Use the generator to store the list of instructions, labels and patches. The finalize() method can then create the final bytecode out of that list. Change-Id: If2ea3118ed6e8744545bb918ecc4bbc87d6a3ff1 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/compiler.pri2
-rw-r--r--src/qml/compiler/qv4bytecodegenerator.cpp66
-rw-r--r--src/qml/compiler/qv4bytecodegenerator_p.h113
-rw-r--r--src/qml/compiler/qv4codegen.cpp58
-rw-r--r--src/qml/compiler/qv4codegen_p.h14
5 files changed, 206 insertions, 47 deletions
diff --git a/src/qml/compiler/compiler.pri b/src/qml/compiler/compiler.pri
index d9b985e33b..dc00f9a3af 100644
--- a/src/qml/compiler/compiler.pri
+++ b/src/qml/compiler/compiler.pri
@@ -2,6 +2,7 @@ INCLUDEPATH += $$PWD
INCLUDEPATH += $$OUT_PWD
HEADERS += \
+ $$PWD/qv4bytecodegenerator_p.h \
$$PWD/qv4compileddata_p.h \
$$PWD/qv4compiler_p.h \
$$PWD/qv4codegen_p.h \
@@ -14,6 +15,7 @@ HEADERS += \
$$PWD/qv4jssimplifier_p.h
SOURCES += \
+ $$PWD/qv4bytecodegenerator.cpp \
$$PWD/qv4compileddata.cpp \
$$PWD/qv4compiler.cpp \
$$PWD/qv4codegen.cpp \
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp
new file mode 100644
index 0000000000..f00a793a0b
--- /dev/null
+++ b/src/qml/compiler/qv4bytecodegenerator.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qv4bytecodegenerator_p.h>
+#include <private/qv4jsir_p.h>
+
+QT_USE_NAMESPACE
+using namespace QV4;
+using namespace Moth;
+
+unsigned BytecodeGenerator::newTemp()
+{
+ int t = function->currentTemp++;
+ if (function->tempCount < function->currentTemp)
+ function->tempCount = function->currentTemp;
+ return t;
+}
+
+QByteArray BytecodeGenerator::finalize()
+{
+ // ### prologue
+ // ## push(tempcount)
+ // content
+ QByteArray code;
+ for (const auto &i : qAsConst(instructions)) {
+ code.append(reinterpret_cast<const char *>(&i.instr), i.size);
+ }
+
+ return code;
+}
diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h
new file mode 100644
index 0000000000..d3fe18c7c3
--- /dev/null
+++ b/src/qml/compiler/qv4bytecodegenerator_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4BYTECODEGENERATOR_P_H
+#define QV4BYTECODEGENERATOR_P_H
+
+#include <private/qv4instr_moth_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+namespace IR {
+struct Function;
+}
+namespace Moth {
+
+class BytecodeGenerator {
+public:
+ BytecodeGenerator(IR::Function *function)
+ : function(function) {}
+
+ struct CodeRef {
+ int instructionIndex;
+ };
+
+ struct Label {
+ void link(CodeRef r) {
+ linkedInstructions.append(r.instructionIndex);
+ }
+
+ int index;
+ QVector<int> linkedInstructions;
+ };
+
+ Label label() {
+ Label l;
+ l.index = labels.size();
+ return l;
+ }
+
+ template<int InstrT>
+ CodeRef addInstruction(const InstrData<InstrT> &data)
+ {
+ Instr genericInstr;
+ InstrMeta<InstrT>::setData(genericInstr, data);
+ return { addInstructionHelper(InstrMeta<InstrT>::Size, genericInstr) };
+ }
+
+ unsigned newTemp();
+
+
+ QByteArray finalize();
+
+private:
+ int addInstructionHelper(uint size, const Instr &i) {
+ int pos = instructions.size();
+ instructions.append({size, i});
+ return pos;
+ }
+
+ struct I {
+ uint size;
+ Instr instr;
+ };
+
+ QVector<I> instructions;
+
+ QVector<Label> labels;
+ IR::Function *function; // ### remove me at some point
+};
+
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 0a3d27b216..78f516c0bc 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -51,6 +51,7 @@
#include <private/qqmljsast_p.h>
#include <private/qv4string_p.h>
#include <private/qv4value_p.h>
+#include <private/qv4bytecodegenerator_p.h>
#ifndef V4_BOOTSTRAP
#include <qv4context_p.h>
@@ -2196,6 +2197,12 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
function->line = loc.startLine;
function->column = loc.startColumn;
+ QV4::Moth::BytecodeGenerator bytecode(function);
+ QV4::Moth::BytecodeGenerator *savedBytecodeGenerator;
+ savedBytecodeGenerator = bytecodeGenerator;
+ bytecodeGenerator = &bytecode;
+
+
if (function->usesArgumentsObject)
_variableEnvironment->enter(QStringLiteral("arguments"), Environment::VariableDeclaration, AST::VariableDeclaration::FunctionScope);
@@ -2296,6 +2303,8 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
leaveEnvironment();
+ bytecodeGenerator = savedBytecodeGenerator;
+
return functionIndex;
}
@@ -3124,33 +3133,6 @@ QList<QQmlJS::DiagnosticMessage> Codegen::errors() const
return _errors;
}
-ptrdiff_t Codegen::addInstructionHelper(QV4::Moth::Instr::Type type, QV4::Moth::Instr &instr)
-{
- Q_UNUSED(type);
- Q_UNUSED(instr);
- return 0;
- // ###
-// instr.common.instructionType = type;
-
-// int instructionSize = Instr::size(type);
-// if (_codeEnd - _codeNext < instructionSize) {
-// int currSize = _codeEnd - _codeStart;
-// uchar *newCode = new uchar[currSize * 2];
-// ::memset(newCode + currSize, 0, currSize);
-// ::memcpy(newCode, _codeStart, currSize);
-// _codeNext = _codeNext - _codeStart + newCode;
-// delete[] _codeStart;
-// _codeStart = newCode;
-// _codeEnd = _codeStart + currSize * 2;
-// }
-
-// ::memcpy(_codeNext, reinterpret_cast<const char *>(&instr), instructionSize);
-// ptrdiff_t ptrOffset = _codeNext - _codeStart;
-// _codeNext += instructionSize;
-
-// return ptrOffset;
-}
-
#ifndef V4_BOOTSTRAP
QList<QQmlError> Codegen::qmlErrors() const
@@ -3198,12 +3180,16 @@ Moth::Param Codegen::Reference::load() const {
Q_ASSERT(type != Invalid);
if (type <= Argument)
return base;
+ else if (type == Const)
+ return codegen->paramForConst(constant);
+
+ // need a temp to hold the value
+ tempIndex = codegen->bytecodeGenerator->newTemp();
if (type == Name) {
- tempIndex = codegen->_block->newTemp();
QV4::Moth::Instruction::LoadName load;
load.name = nameIndex;
load.result = QV4::Moth::Param::createTemp(tempIndex);
- codegen->addInstruction(load);
+ codegen->bytecodeGenerator->addInstruction(load);
} else if (type == Member) {
// if (useFastLookups) {
// Instruction::GetLookup load;
@@ -3217,15 +3203,13 @@ Moth::Param Codegen::Reference::load() const {
load.base = base;
load.name = nameIndex;
load.result = QV4::Moth::Param::createTemp(tempIndex);
- codegen->addInstruction(load);
+ codegen->bytecodeGenerator->addInstruction(load);
} else if (type == Subscript) {
QV4::Moth::Instruction::LoadElement load;
load.base = base;
load.index = subscript;
load.result = QV4::Moth::Param::createTemp(tempIndex);
- codegen->addInstruction(load);
- } else if (type == Const) {
- return codegen->paramForConst(constant);
+ codegen->bytecodeGenerator->addInstruction(load);
} else {
Q_ASSERT(false);
Q_UNREACHABLE();
@@ -3240,12 +3224,12 @@ void Codegen::Reference::store(Moth::Param &p) const {
QV4::Moth::Instruction::Move move;
move.source = p;
move.result = base;
- codegen->addInstruction(move);
+ codegen->bytecodeGenerator->addInstruction(move);
} else if (type == Name) {
QV4::Moth::Instruction::StoreName store;
store.source = p;
store.name = nameIndex;
- codegen->addInstruction(store);
+ codegen->bytecodeGenerator->addInstruction(store);
} else if (type == Member) {
// if (useFastLookups) {
// Instruction::SetLookup store;
@@ -3259,13 +3243,13 @@ void Codegen::Reference::store(Moth::Param &p) const {
store.base = base;
store.name = nameIndex;
store.source = p;
- codegen->addInstruction(store);
+ codegen->bytecodeGenerator->addInstruction(store);
} else if (type == Subscript) {
QV4::Moth::Instruction::StoreElement store;
store.base = base;
store.index = subscript;
store.source = p;
- codegen->addInstruction(store);
+ codegen->bytecodeGenerator->addInstruction(store);
} else {
Q_ASSERT(false);
Q_UNREACHABLE();
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 61d09f31d0..f6ae5ba2e9 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -69,6 +69,9 @@ namespace QV4 {
namespace Compiler {
struct JSUnitGenerator;
}
+namespace Moth {
+class BytecodeGenerator;
+}
}
namespace QQmlJS {
@@ -560,14 +563,6 @@ public:
QList<QQmlError> qmlErrors() const;
#endif
- template<int InstrT>
- ptrdiff_t addInstruction(const QV4::Moth::InstrData<InstrT> &data)
- {
- QV4::Moth::Instr genericInstr;
- QV4::Moth::InstrMeta<InstrT>::setDataNoCommon(genericInstr, data);
- return addInstructionHelper(static_cast<QV4::Moth::Instr::Type>(InstrT), genericInstr);
- }
-
protected:
Result _expr;
QString _property;
@@ -585,14 +580,13 @@ protected:
QHash<AST::FunctionExpression *, int> _functionMap;
QStack<QV4::IR::BasicBlock *> _exceptionHandlers;
QV4::Compiler::JSUnitGenerator *jsUnitGenerator;
+ QV4::Moth::BytecodeGenerator *bytecodeGenerator = 0;
bool _strictMode;
bool _fileNameIsUrl;
bool hasError;
QList<QQmlJS::DiagnosticMessage> _errors;
- ptrdiff_t addInstructionHelper(QV4::Moth::Instr::Type type, QV4::Moth::Instr &instr);
-
class ScanFunctions: protected Visitor
{