diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-06-12 14:56:03 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2017-06-19 13:34:55 +0000 |
commit | 2c0db96b0ea1b8d4daa5d0fda8b9b22270b5ab4b (patch) | |
tree | 46cdcb6f5026716a2c9fdf8c7c7047879f0c33eb /src/qml/compiler | |
parent | 74149e479ce4252c2a22638bed002985b09b8269 (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.pri | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator.cpp | 66 | ||||
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator_p.h | 113 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 58 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 14 |
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 { |