Initial version of generator for new data structures
authorSimon Hausmann <simon.hausmann@digia.com>
Wed, 14 Aug 2013 08:17:31 +0000 (10:17 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Thu, 15 Aug 2013 07:08:35 +0000 (09:08 +0200)
Change-Id: I172a504f8b4f8284967a4a02e207bf4c0a04c2a4
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/compiler/compiler.pri
src/qml/compiler/qv4compileddata.cpp [new file with mode: 0644]
src/qml/compiler/qv4compileddata_p.h
src/qml/compiler/qv4compiler.cpp [new file with mode: 0644]
src/qml/compiler/qv4compiler_p.h [new file with mode: 0644]

index ac04d96..621cd87 100644 (file)
@@ -4,6 +4,8 @@ INCLUDEPATH += $$PWD
 INCLUDEPATH += $$OUT_PWD
 
 HEADERS += \
+    $$PWD/qv4compileddata_p.h \
+    $$PWD/qv4compiler_p.h \
     $$PWD/qv4codegen_p.h \
     $$PWD/qv4isel_masm_p.h \
     $$PWD/qv4isel_p.h \
@@ -14,6 +16,8 @@ HEADERS += \
     $$PWD/qv4ssa_p.h
 
 SOURCES += \
+    $$PWD/qv4compileddata.cpp \
+    $$PWD/qv4compiler.cpp \
     $$PWD/qv4codegen.cpp \
     $$PWD/qv4instr_moth.cpp \
     $$PWD/qv4isel_masm.cpp \
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
new file mode 100644 (file)
index 0000000..4c142f4
--- /dev/null
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4compileddata_p.h"
+#include "qv4jsir_p.h"
+
+namespace QV4 {
+
+namespace CompiledData {
+
+int Function::calculateSize(QQmlJS::V4IR::Function *f)
+{
+    return calculateSize(f->formals.size(), f->locals.size(), f->nestedFunctions.size());
+}
+
+
+}
+
+}
index 9fcae5f..47e4e48 100644 (file)
 #define QV4COMPILEDDATA_P_H
 
 #include <QtCore/qstring.h>
+#include <QVector>
+#include <QStringList>
+#include <private/qv4value_def_p.h>
 
 QT_BEGIN_NAMESPACE
 
+namespace QQmlJS {
+namespace V4IR {
+struct Function;
+}
+}
+
 namespace QV4 {
 
 struct ExecutionContext;
@@ -53,7 +62,7 @@ namespace CompiledData {
 
 static const char magic_str[] = "qv4cdata";
 
-struct Header
+struct Unit
 {
     char magic[8];
     qint16 architecture;
@@ -64,12 +73,18 @@ struct Header
         IsQml = 0x2
     };
     quint32 flags;
+    uint stringTableSize;
+    uint offsetToStringTable;
+    uint functionTableSize;
+    uint offsetToFunctionTable;
+
+    static int calculateSize(uint nStrings, uint nFunctions) { return (sizeof(Unit) + (nStrings + nFunctions) * sizeof(uint) + 7) & ~7; }
 };
 
 struct Function
 {
-    Value (*code)(ExecutionContext *, const uchar *);
-    quint32 offsetToName;
+    QV4::Value (*code)(ExecutionContext *, const uchar *);
+    quint32 nameIndex;
     qint64 flags; // strict, etc.
     quint32 nFormals;
     quint32 formalsOffset;
@@ -77,10 +92,15 @@ struct Function
     quint32 localsOffset;
     quint32 nInnerFunctions;
     quint32 innerFunctionsOffset;
-//    quint32 offsetForFormals[nFormals]
-//    quint32 offsetForLocals[nLocals]
+//    quint32 formalsIndex[nFormals]
+//    quint32 localsIndex[nLocals]
 //    quint32 offsetForInnerFunctions[nInnerFunctions]
 //    Function[nInnerFunctions]
+
+    static int calculateSize(int nFormals, int nLocals, int nInnerfunctions) {
+        return (sizeof(Function) + (nFormals + nLocals + nInnerfunctions) * sizeof(quint32) + 7) & ~0x7;
+    }
+    static int calculateSize(QQmlJS::V4IR::Function *f);
 };
 
 struct String
@@ -89,14 +109,10 @@ struct String
     quint32 flags; // isArrayIndex
     QArrayData str;
     // uint16 strdata[]
-};
-
 
-struct JSUnit
-{
-    Header header;
-    Function entry;
-    // String stringTable;
+    static int calculateSize(const QString &str) {
+        return (sizeof(String) + (str.length() + 1) * sizeof(quint16) + 7) & ~0x7;
+    }
 };
 
 
@@ -171,7 +187,7 @@ struct Imports
 
 struct QmlUnit
 {
-    Header header;
+    Unit header;
     int offsetToTypeName;
     Imports imports;
     Object object;
@@ -186,7 +202,7 @@ struct QmlUnit
 struct CompilationUnit
 {
     virtual ~CompilationUnit();
-    Header *data;
+    Unit *data;
 
     // ### runtime data
     // pointer to qml data for QML unit
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
new file mode 100644 (file)
index 0000000..b3aebbe
--- /dev/null
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qv4compiler_p.h>
+#include <qv4compileddata_p.h>
+#include <qv4isel_p.h>
+#include <qv4engine_p.h>
+
+QV4::Compiler::JSUnitGenerator::JSUnitGenerator(QV4::ExecutionEngine *engine, QQmlJS::V4IR::Module *module)
+    : irModule(module)
+    , stringDataSize(0)
+{
+    isel = engine->iselFactory->create(engine, irModule);
+}
+
+int QV4::Compiler::JSUnitGenerator::registerString(const QString &str)
+{
+    QHash<QString, int>::ConstIterator it = stringToId.find(str);
+    if (it != stringToId.end())
+        return *it;
+    stringToId.insert(str, strings.size());
+    strings.append(str);
+    stringDataSize += QV4::CompiledData::String::calculateSize(str);
+    return strings.size() - 1;
+}
+
+int QV4::Compiler::JSUnitGenerator::getStringId(const QString &string) const
+{
+    Q_ASSERT(stringToId.contains(string));
+    return stringToId.value(string);
+}
+
+QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
+{
+    foreach (QQmlJS::V4IR::Function *f, irModule->functions) {
+        registerString(*f->name);
+        for (int i = 0; i < f->formals.size(); ++i)
+            registerString(*f->formals.at(i));
+        for (int i = 0; i < f->locals.size(); ++i)
+            registerString(*f->locals.at(i));
+    }
+
+    int unitSize = QV4::CompiledData::Unit::calculateSize(strings.size(), irModule->functions.size());
+
+    uint functionDataSize = 0;
+    for (int i = 0; i < irModule->functions.size(); ++i) {
+        QQmlJS::V4IR::Function *f = irModule->functions.at(i);
+        functionOffsets.insert(f, functionDataSize + unitSize + stringDataSize);
+        functionDataSize += QV4::CompiledData::Function::calculateSize(f);
+    }
+
+    char *data = (char *)malloc(unitSize + functionDataSize + stringDataSize);
+    QV4::CompiledData::Unit *unit = (QV4::CompiledData::Unit*)data;
+
+    memcpy(unit->magic, QV4::CompiledData::magic_str, sizeof(unit->magic));
+    unit->architecture = 0; // ###
+    unit->flags = QV4::CompiledData::Unit::IsJavascript;
+    unit->version = 1;
+    unit->stringTableSize = strings.size();
+    unit->offsetToStringTable = sizeof(QV4::CompiledData::Unit);
+    unit->functionTableSize = irModule->functions.size();
+    unit->offsetToFunctionTable = unit->offsetToStringTable + unit->stringTableSize * sizeof(uint);
+
+    // write strings and string table
+    uint *stringTable = (uint *)(data + unit->offsetToStringTable);
+    char *string = data + unitSize;
+    for (int i = 0; i < strings.size(); ++i) {
+        stringTable[i] = string - data;
+        const QString &qstr = strings.at(i);
+
+        QV4::CompiledData::String *s = (QV4::CompiledData::String*)(string);
+        s->hash = QV4::String::createHashValue(qstr.constData(), qstr.length());
+        s->flags = 0; // ###
+        s->str.ref.atomic.store(-1);
+        s->str.size = qstr.length();
+        s->str.alloc = 0;
+        s->str.capacityReserved = false;
+        s->str.offset = sizeof(QArrayData);
+        memcpy(s + 1, qstr.constData(), qstr.length()*sizeof(ushort));
+
+        string += QV4::CompiledData::String::calculateSize(qstr);
+    }
+
+    // pointer to the entry function
+    uint *functionTable = (uint *)data + unit->offsetToFunctionTable;
+    char *f = data + unitSize + stringDataSize;
+    writeFunction(f, irModule->rootFunction);
+    ++functionTable;
+    f += QV4::CompiledData::Function::calculateSize(irModule->rootFunction);
+
+    for (uint i = 0; i < irModule->functions.size(); ++i) {
+        QQmlJS::V4IR::Function *function = irModule->functions.at(i);
+        if (function == irModule->rootFunction)
+            continue;
+
+        writeFunction(f, function);
+        ++functionTable;
+        f += QV4::CompiledData::Function::calculateSize(function);
+    }
+
+    return unit;
+}
+
+void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QQmlJS::V4IR::Function *irFunction)
+{
+    QV4::CompiledData::Function *function = (QV4::CompiledData::Function *)f;
+    function->nameIndex = getStringId(*irFunction->name);
+    function->flags = 0; // ###
+    function->nFormals = irFunction->formals.size();
+    function->formalsOffset = sizeof(QV4::CompiledData::Function);
+    function->nLocals = irFunction->locals.size();
+    function->localsOffset = function->formalsOffset + function->nFormals * sizeof(quint32);
+    function->nInnerFunctions = irFunction->nestedFunctions.size();
+    function->innerFunctionsOffset = function->localsOffset + function->nLocals * sizeof(quint32);
+
+    // write formals
+    quint32 *formals = (quint32 *)(f + function->formalsOffset);
+    for (int i = 0; i < irFunction->formals.size(); ++i)
+        formals[i] = getStringId(*irFunction->formals.at(i));
+
+    // write locals
+    quint32 *locals = (quint32 *)(f + function->localsOffset);
+    for (int i = 0; i < irFunction->locals.size(); ++i)
+        locals[i] = getStringId(*irFunction->locals.at(i));
+
+    // write inner functions
+    quint32 *innerFunctions = (quint32 *)(f + function->innerFunctionsOffset);
+    for (int i = 0; i < irFunction->nestedFunctions.size(); ++i)
+        innerFunctions[i] = functionOffsets.value(irFunction->nestedFunctions.at(i));
+}
+
+
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
new file mode 100644 (file)
index 0000000..c17e0dd
--- /dev/null
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4COMPILER_P_H
+#define QV4COMPILER_P_H
+
+#include <QtCore/qstring.h>
+#include "qv4jsir_p.h"
+#include <qv4isel_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+namespace CompiledData {
+struct Unit;
+}
+
+namespace Compiler {
+
+struct JSUnitGenerator {
+    JSUnitGenerator(QV4::ExecutionEngine *engine, QQmlJS::V4IR::Module *module);
+
+    QQmlJS::V4IR::Module *irModule;
+    QQmlJS::EvalInstructionSelection *isel;
+
+    int registerString(const QString &str);
+    int getStringId(const QString &string) const;
+
+    QV4::CompiledData::Unit *generateUnit();
+    void writeFunction(char *f, QQmlJS::V4IR::Function *irFunction);
+
+    QHash<QString, int> stringToId;
+    QStringList strings;
+    QHash<QQmlJS::V4IR::Function *, uint> functionOffsets;
+    int stringDataSize;
+};
+
+}
+
+}
+
+QT_END_NAMESPACE
+
+#endif