aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-08-20 16:54:29 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2013-08-20 16:54:29 +0200
commit461892e492e0bef399714557498380703b3e029b (patch)
treead82e1ae8286bbe650b2ee19ad393a4ab8996bb1 /src/qml/compiler
parenta71e35a95c9f352db91fb82d8a564d01ba961341 (diff)
parent90aaff37be419ca1f1da40df64424c0d88bfaf19 (diff)
Merge branch 'wip/v4' of ssh://codereview.qt-project.org/qt/qtdeclarative into dev
Conflicts: src/qml/compiler/qv4codegen.cpp src/qml/compiler/qv4codegen_p.h src/qml/compiler/qv4isel_moth.cpp src/qml/jsruntime/qv4context_p.h src/qml/jsruntime/qv4functionobject.cpp src/qml/jsruntime/qv4runtime.cpp src/qml/jsruntime/qv4runtime_p.h src/qml/jsruntime/qv4script.cpp sync.profile Change-Id: I1d785e2134bffac9553a1c16eed12816cbd1ad2c
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/compiler.pri4
-rw-r--r--src/qml/compiler/qv4codegen.cpp14
-rw-r--r--src/qml/compiler/qv4codegen_p.h1
-rw-r--r--src/qml/compiler/qv4compileddata.cpp157
-rw-r--r--src/qml/compiler/qv4compileddata_p.h354
-rw-r--r--src/qml/compiler/qv4compiler.cpp313
-rw-r--r--src/qml/compiler/qv4compiler_p.h99
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h62
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp247
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h62
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp139
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h27
-rw-r--r--src/qml/compiler/qv4isel_p.cpp50
-rw-r--r--src/qml/compiler/qv4isel_p.h21
-rw-r--r--src/qml/compiler/qv4jsir.cpp9
-rw-r--r--src/qml/compiler/qv4jsir_p.h5
16 files changed, 1252 insertions, 312 deletions
diff --git a/src/qml/compiler/compiler.pri b/src/qml/compiler/compiler.pri
index a19bf70a7a..51a7270598 100644
--- a/src/qml/compiler/compiler.pri
+++ b/src/qml/compiler/compiler.pri
@@ -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 \
@@ -15,6 +17,8 @@ HEADERS += \
$$PWD/qv4regalloc_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/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index b91e3ccd26..6c913a6dc4 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -470,10 +470,11 @@ V4IR::Function *Codegen::operator()(const QString &fileName,
{
assert(node);
- _fileName = fileName;
_module = module;
_env = 0;
+ _module->setFileName(fileName);
+
ScanFunctions scan(this, sourceCode);
scan(node);
@@ -490,8 +491,8 @@ V4IR::Function *Codegen::operator()(const QString &fileName,
AST::FunctionExpression *ast,
V4IR::Module *module)
{
- _fileName = fileName;
_module = module;
+ _module->setFileName(fileName);
_env = 0;
ScanFunctions scan(this, sourceCode);
@@ -1794,7 +1795,6 @@ V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
enterEnvironment(ast);
V4IR::Function *function = _module->newFunction(name, _function);
- function->sourceFile = _fileName;
V4IR::BasicBlock *entryBlock = function->newBasicBlock(groupStartBlock());
V4IR::BasicBlock *exitBlock = function->newBasicBlock(groupStartBlock(), V4IR::Function::DontInsertBlock);
@@ -2575,7 +2575,7 @@ void Codegen::throwSyntaxErrorOnEvalOrArgumentsInStrictMode(V4IR::Expr *expr, co
void Codegen::throwSyntaxError(const SourceLocation &loc, const QString &detail)
{
QQmlError error;
- error.setUrl(QUrl::fromLocalFile(_fileName));
+ error.setUrl(QUrl::fromLocalFile(_module->fileName));
error.setDescription(detail);
error.setLine(loc.startLine);
error.setColumn(loc.startColumn);
@@ -2585,7 +2585,7 @@ void Codegen::throwSyntaxError(const SourceLocation &loc, const QString &detail)
void Codegen::throwReferenceError(const SourceLocation &loc, const QString &detail)
{
QQmlError error;
- error.setUrl(QUrl::fromLocalFile(_fileName));
+ error.setUrl(QUrl::fromLocalFile(_module->fileName));
error.setDescription(detail);
error.setLine(loc.startLine);
error.setColumn(loc.startColumn);
@@ -2594,10 +2594,10 @@ void Codegen::throwReferenceError(const SourceLocation &loc, const QString &deta
void RuntimeCodegen::throwSyntaxError(const AST::SourceLocation &loc, const QString &detail)
{
- context->throwSyntaxError(detail, _fileName, loc.startLine, loc.startColumn);
+ context->throwSyntaxError(detail, _module->fileName, loc.startLine, loc.startColumn);
}
void RuntimeCodegen::throwReferenceError(const AST::SourceLocation &loc, const QString &detail)
{
- context->throwReferenceError(detail, _fileName, loc.startLine, loc.startColumn);
+ context->throwReferenceError(detail, _module->fileName, loc.startLine, loc.startColumn);
}
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index c55a45b107..85c38d8d8c 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -413,7 +413,6 @@ protected:
QList<QQmlError> errors();
protected:
- QString _fileName;
Result _expr;
QString _property;
UiMember _uiMember;
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
new file mode 100644
index 0000000000..a434f6c0dc
--- /dev/null
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** 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"
+#include <private/qv4engine_p.h>
+#include <private/qv4function_p.h>
+#include <private/qv4lookup_p.h>
+#include <private/qv4regexpobject_p.h>
+#include <private/qv4unwindhelper_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+namespace CompiledData {
+
+namespace {
+ bool functionSortHelper(QV4::Function *lhs, QV4::Function *rhs)
+ {
+ return reinterpret_cast<quintptr>(lhs->code) < reinterpret_cast<quintptr>(rhs->code);
+ }
+}
+
+CompilationUnit::~CompilationUnit()
+{
+ engine->compilationUnits.erase(engine->compilationUnits.find(this));
+ free(data);
+ free(runtimeStrings);
+ delete [] runtimeLookups;
+ delete [] runtimeRegularExpressions;
+ free(runtimeClasses);
+ qDeleteAll(runtimeFunctions);
+}
+
+QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
+{
+ this->engine = engine;
+ engine->compilationUnits.insert(this);
+
+ assert(!runtimeStrings);
+ assert(data);
+ runtimeStrings = (QV4::String**)malloc(data->stringTableSize * sizeof(QV4::String*));
+ for (int i = 0; i < data->stringTableSize; ++i)
+ runtimeStrings[i] = engine->newIdentifier(data->stringAt(i));
+
+ runtimeRegularExpressions = new QV4::Value[data->regexpTableSize];
+ for (int i = 0; i < data->regexpTableSize; ++i) {
+ const CompiledData::RegExp *re = data->regexpAt(i);
+ int flags = 0;
+ if (re->flags & CompiledData::RegExp::RegExp_Global)
+ flags |= QQmlJS::V4IR::RegExp::RegExp_Global;
+ if (re->flags & CompiledData::RegExp::RegExp_IgnoreCase)
+ flags |= QQmlJS::V4IR::RegExp::RegExp_IgnoreCase;
+ if (re->flags & CompiledData::RegExp::RegExp_Multiline)
+ flags |= QQmlJS::V4IR::RegExp::RegExp_Multiline;
+ QV4::RegExpObject *obj = engine->newRegExpObject(data->stringAt(re->stringIndex), flags);
+ runtimeRegularExpressions[i] = QV4::Value::fromObject(obj);
+ }
+
+ if (data->lookupTableSize) {
+ runtimeLookups = new QV4::Lookup[data->lookupTableSize];
+ const CompiledData::Lookup *compiledLookups = data->lookupTable();
+ for (uint i = 0; i < data->lookupTableSize; ++i) {
+ QV4::Lookup *l = runtimeLookups + i;
+
+ if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_Getter)
+ l->getter = QV4::Lookup::getterGeneric;
+ else if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_Setter)
+ l->setter = QV4::Lookup::setterGeneric;
+ else if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_GlobalGetter)
+ l->globalGetter = QV4::Lookup::globalGetterGeneric;
+
+ for (int i = 0; i < QV4::Lookup::Size; ++i)
+ l->classList[i] = 0;
+ l->level = -1;
+ l->index = UINT_MAX;
+ l->name = runtimeStrings[compiledLookups[i].nameIndex];
+ }
+ }
+
+ if (data->jsClassTableSize) {
+ runtimeClasses = (QV4::InternalClass**)malloc(data->jsClassTableSize * sizeof(QV4::InternalClass*));
+
+ for (int i = 0; i < data->jsClassTableSize; ++i) {
+ int memberCount = 0;
+ const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount);
+ QV4::InternalClass *klass = engine->emptyClass;
+ for (int j = 0; j < memberCount; ++j, ++member)
+ klass = klass->addMember(runtimeStrings[member->nameOffset], member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data);
+
+ runtimeClasses[i] = klass;
+ }
+ }
+
+ linkBackendToEngine(engine);
+
+ runtimeFunctionsSortedByAddress.resize(runtimeFunctions.size());
+ memcpy(runtimeFunctionsSortedByAddress.data(), runtimeFunctions.data(), runtimeFunctions.size() * sizeof(QV4::Function*));
+ qSort(runtimeFunctionsSortedByAddress.begin(), runtimeFunctionsSortedByAddress.end(), functionSortHelper);
+
+ return runtimeFunctions[data->indexOfRootFunction];
+}
+
+void CompilationUnit::markObjects()
+{
+ for (int i = 0; i < data->stringTableSize; ++i)
+ runtimeStrings[i]->mark();
+ for (int i = 0; i < data->regexpTableSize; ++i)
+ runtimeRegularExpressions[i].mark();
+ for (int i = 0; i < runtimeFunctions.count(); ++i)
+ runtimeFunctions[i]->mark();
+}
+
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
new file mode 100644
index 0000000000..854df1185b
--- /dev/null
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -0,0 +1,354 @@
+/****************************************************************************
+**
+** 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 QV4COMPILEDDATA_P_H
+#define QV4COMPILEDDATA_P_H
+
+#include <QtCore/qstring.h>
+#include <QVector>
+#include <QStringList>
+#include <private/qv4value_def_p.h>
+#include <private/qv4executableallocator_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QQmlJS {
+namespace V4IR {
+struct Function;
+}
+}
+
+namespace QV4 {
+
+struct Function;
+struct ExecutionContext;
+
+namespace CompiledData {
+
+struct String;
+struct Function;
+struct Lookup;
+struct RegExp;
+
+struct RegExp
+{
+ enum Flags {
+ RegExp_Global = 0x01,
+ RegExp_IgnoreCase = 0x02,
+ RegExp_Multiline = 0x04
+ };
+ quint32 flags;
+ quint32 stringIndex;
+
+ static int calculateSize() { return sizeof(RegExp); }
+};
+
+struct Lookup
+{
+ enum Type {
+ Type_Getter = 0x0,
+ Type_Setter = 0x1,
+ Type_GlobalGetter = 2
+ };
+
+ quint32 type_and_flags;
+ quint32 nameIndex;
+
+ static int calculateSize() { return sizeof(Lookup); }
+};
+
+struct JSClassMember
+{
+ uint nameOffset : 31;
+ uint isAccessor : 1;
+};
+
+struct JSClass
+{
+ uint nMembers;
+ // JSClassMember[nMembers]
+
+ static int calculateSize(int nMembers) { return (sizeof(JSClass) + nMembers * sizeof(JSClassMember) + 7) & ~7; }
+};
+
+struct String
+{
+ quint32 hash;
+ quint32 flags; // isArrayIndex
+ QArrayData str;
+ // uint16 strdata[]
+
+ static int calculateSize(const QString &str) {
+ return (sizeof(String) + (str.length() + 1) * sizeof(quint16) + 7) & ~0x7;
+ }
+};
+
+static const char magic_str[] = "qv4cdata";
+
+struct Unit
+{
+ char magic[8];
+ qint16 architecture;
+ qint16 version;
+
+ enum {
+ IsJavascript = 0x1,
+ IsQml = 0x2,
+ StaticData = 0x4 // Unit data persistent in memory?
+ };
+ quint32 flags;
+ uint stringTableSize;
+ uint offsetToStringTable;
+ uint functionTableSize;
+ uint offsetToFunctionTable;
+ uint lookupTableSize;
+ uint offsetToLookupTable;
+ uint regexpTableSize;
+ uint offsetToRegexpTable;
+ uint jsClassTableSize;
+ uint offsetToJSClassTable;
+ uint indexOfRootFunction;
+ quint32 sourceFileIndex;
+
+ QString stringAt(int idx) const {
+ const uint *offsetTable = reinterpret_cast<const uint*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
+ const uint offset = offsetTable[idx];
+ const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset);
+ QStringDataPtr holder = { const_cast<QStringData *>(static_cast<const QStringData*>(&str->str)) };
+ QString qstr(holder);
+ if (flags & StaticData)
+ return qstr;
+ return QString(qstr.constData(), qstr.length());
+ }
+
+ const Function *functionAt(int idx) const {
+ const uint *offsetTable = reinterpret_cast<const uint*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable);
+ const uint offset = offsetTable[idx];
+ return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(this) + offset);
+ }
+
+ const Lookup *lookupTable() const { return reinterpret_cast<const Lookup*>(reinterpret_cast<const char *>(this) + offsetToLookupTable); }
+ const RegExp *regexpAt(int index) const {
+ return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
+ }
+
+ const JSClassMember *jsClassAt(int idx, int *nMembers) const {
+ const uint *offsetTable = reinterpret_cast<const uint *>(reinterpret_cast<const char *>(this) + offsetToJSClassTable);
+ const uint offset = offsetTable[idx];
+ const char *ptr = reinterpret_cast<const char *>(this) + offset;
+ const JSClass *klass = reinterpret_cast<const JSClass *>(ptr);
+ *nMembers = klass->nMembers;
+ return reinterpret_cast<const JSClassMember*>(ptr + sizeof(JSClass));
+ }
+
+ static int calculateSize(uint nStrings, uint nFunctions, uint nRegExps,
+ uint nLookups, uint nClasses) {
+ return (sizeof(Unit)
+ + (nStrings + nFunctions + nClasses) * sizeof(uint)
+ + nRegExps * RegExp::calculateSize()
+ + nLookups * Lookup::calculateSize()
+ + 7) & ~7; }
+};
+
+struct Function
+{
+ enum Flags {
+ HasDirectEval = 0x1,
+ UsesArgumentsObject = 0x2,
+ IsStrict = 0x4,
+ IsNamedExpression = 0x8
+ };
+
+ quint32 index; // in CompilationUnit's function table
+ quint32 nameIndex;
+ qint64 flags;
+ quint32 nFormals;
+ quint32 formalsOffset;
+ quint32 nLocals;
+ quint32 localsOffset;
+ quint32 nLineNumberMappingEntries;
+ quint32 lineNumberMappingOffset; // Array of uint pairs (offset and line number)
+ quint32 nInnerFunctions;
+ quint32 innerFunctionsOffset;
+// quint32 formalsIndex[nFormals]
+// quint32 localsIndex[nLocals]
+// quint32 offsetForInnerFunctions[nInnerFunctions]
+// Function[nInnerFunctions]
+
+ const quint32 *formalsTable() const { return reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(this) + formalsOffset); }
+ const quint32 *localsTable() const { return reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(this) + localsOffset); }
+ const quint32 *lineNumberMapping() const { return reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(this) + lineNumberMappingOffset); }
+
+ static int calculateSize(int nFormals, int nLocals, int nInnerfunctions, int lineNumberMappings) {
+ return (sizeof(Function) + (nFormals + nLocals + nInnerfunctions + 2 * lineNumberMappings) * sizeof(quint32) + 7) & ~0x7;
+ }
+};
+
+// Qml data structures
+
+struct Value
+{
+ quint32 type; // Invalid, Boolean, Number, String, Function, Object, ListOfObjects
+ union {
+ bool b;
+ int i;
+ double d;
+ quint32 offsetToString;
+ quint32 offsetToFunction;
+ quint32 offsetToObject;
+ };
+};
+
+struct Binding
+{
+ quint32 offsetToPropertyName;
+ Value value;
+};
+
+struct Parameter
+{
+ quint32 offsetToName;
+ quint32 type;
+ quint32 offsetToCustomTypeName;
+ quint32 reserved;
+};
+
+struct Signal
+{
+ quint32 offsetToName;
+ quint32 nParameters;
+ Parameter parameters[1];
+};
+
+struct Property
+{
+ quint32 offsetToName;
+ quint32 type;
+ quint32 offsetToCustomTypeName;
+ quint32 flags; // default, readonly
+ Value value;
+};
+
+struct Object
+{
+ quint32 offsetToInheritedTypeName;
+ quint32 offsetToId;
+ quint32 offsetToDefaultProperty;
+ quint32 nFunctions;
+ quint32 offsetToFunctions;
+ quint32 nProperties;
+ quint32 offsetToProperties;
+ quint32 nSignals;
+ quint32 offsetToSignals;
+ quint32 nBindings;
+ quint32 offsetToBindings;
+// Function[]
+// Property[]
+// Signal[]
+// Binding[]
+};
+
+struct Imports
+{
+};
+
+
+struct QmlUnit
+{
+ Unit header;
+ int offsetToTypeName;
+ Imports imports;
+ Object object;
+};
+
+// This is how this hooks into the existing structures:
+
+//VM::Function
+// CompilationUnit * (for functions that need to clean up)
+// CompiledData::Function *compiledFunction
+
+struct CompilationUnit
+{
+ CompilationUnit()
+ : refCount(0)
+ , engine(0)
+ , data(0)
+ , runtimeStrings(0)
+ , runtimeLookups(0)
+ , runtimeClasses(0)
+ {}
+ virtual ~CompilationUnit();
+
+ void ref() { ++refCount; }
+ void deref() { if (!--refCount) delete this; }
+
+ int refCount;
+ ExecutionEngine *engine;
+ Unit *data;
+
+ QString fileName() const { return data->stringAt(data->sourceFileIndex); }
+
+ QV4::String **runtimeStrings; // Array
+ QV4::Lookup *runtimeLookups;
+ QV4::Value *runtimeRegularExpressions;
+ QV4::InternalClass **runtimeClasses;
+ QVector<QV4::Function *> runtimeFunctions;
+ QVector<QV4::Function *> runtimeFunctionsSortedByAddress;
+
+ QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
+
+ virtual QV4::ExecutableAllocator::ChunkOfPages *chunkForFunction(int /*functionIndex*/) { return 0; }
+
+ // ### runtime data
+ // pointer to qml data for QML unit
+
+ void markObjects();
+
+protected:
+ virtual void linkBackendToEngine(QV4::ExecutionEngine *engine) = 0;
+};
+
+}
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
new file mode 100644
index 0000000000..322a39932a
--- /dev/null
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** 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(QQmlJS::V4IR::Module *module)
+ : irModule(module)
+ , stringDataSize(0)
+ , jsClassDataSize(0)
+{
+}
+
+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);
+}
+
+uint QV4::Compiler::JSUnitGenerator::registerGetterLookup(const QString &name)
+{
+ CompiledData::Lookup l;
+ l.type_and_flags = CompiledData::Lookup::Type_Getter;
+ l.nameIndex = registerString(name);
+ lookups << l;
+ return lookups.size() - 1;
+}
+
+uint QV4::Compiler::JSUnitGenerator::registerSetterLookup(const QString &name)
+{
+ CompiledData::Lookup l;
+ l.type_and_flags = CompiledData::Lookup::Type_Setter;
+ l.nameIndex = registerString(name);
+ lookups << l;
+ return lookups.size() - 1;
+}
+
+uint QV4::Compiler::JSUnitGenerator::registerGlobalGetterLookup(const QString &name)
+{
+ CompiledData::Lookup l;
+ l.type_and_flags = CompiledData::Lookup::Type_GlobalGetter;
+ l.nameIndex = registerString(name);
+ lookups << l;
+ return lookups.size() - 1;
+}
+
+int QV4::Compiler::JSUnitGenerator::registerRegExp(QQmlJS::V4IR::RegExp *regexp)
+{
+ CompiledData::RegExp re;
+ re.stringIndex = registerString(*regexp->value);
+
+ re.flags = 0;
+ if (regexp->flags & QQmlJS::V4IR::RegExp::RegExp_Global)
+ re.flags |= CompiledData::RegExp::RegExp_Global;
+ if (regexp->flags & QQmlJS::V4IR::RegExp::RegExp_IgnoreCase)
+ re.flags |= CompiledData::RegExp::RegExp_IgnoreCase;
+ if (regexp->flags & QQmlJS::V4IR::RegExp::RegExp_Multiline)
+ re.flags |= CompiledData::RegExp::RegExp_Multiline;
+
+ regexps.append(re);
+ return regexps.size() - 1;
+}
+
+void QV4::Compiler::JSUnitGenerator::registerLineNumberMapping(QQmlJS::V4IR::Function *function, const QVector<uint> &mappings)
+{
+ lineNumberMappingsPerFunction.insert(function, mappings);
+}
+
+int QV4::Compiler::JSUnitGenerator::registerJSClass(QQmlJS::V4IR::ExprList *args)
+{
+ // ### re-use existing class definitions.
+
+ QList<CompiledData::JSClassMember> members;
+
+ QQmlJS::V4IR::ExprList *it = args;
+ while (it) {
+ CompiledData::JSClassMember member;
+
+ QQmlJS::V4IR::Name *name = it->expr->asName();
+ it = it->next;
+
+ const bool isData = it->expr->asConst()->value;
+ it = it->next;
+
+ member.nameOffset = registerString(*name->id);
+ member.isAccessor = !isData;
+ members << member;
+
+ if (!isData)
+ it = it->next;
+
+ it = it->next;
+ }
+
+ jsClasses << members;
+ jsClassDataSize += CompiledData::JSClass::calculateSize(members.count());
+ return jsClasses.size() - 1;
+}
+
+QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
+{
+ registerString(irModule->fileName);
+ 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(), regexps.size(), lookups.size(), jsClasses.count());
+
+ 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);
+
+ int lineNumberMappingCount = 0;
+ QHash<QQmlJS::V4IR::Function *, QVector<uint> >::ConstIterator lineNumberMapping = lineNumberMappingsPerFunction.find(f);
+ if (lineNumberMapping != lineNumberMappingsPerFunction.constEnd())
+ lineNumberMappingCount = lineNumberMapping->count() / 2;
+
+ functionDataSize += QV4::CompiledData::Function::calculateSize(f->formals.size(), f->locals.size(), f->nestedFunctions.size(), lineNumberMappingCount);
+ }
+
+ char *data = (char *)malloc(unitSize + functionDataSize + stringDataSize + jsClassDataSize);
+ 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);
+ unit->lookupTableSize = lookups.count();
+ unit->offsetToLookupTable = unit->offsetToFunctionTable + unit->functionTableSize * sizeof(uint);
+ unit->regexpTableSize = regexps.size();
+ unit->offsetToRegexpTable = unit->offsetToLookupTable + unit->lookupTableSize * CompiledData::Lookup::calculateSize();
+ unit->jsClassTableSize = jsClasses.count();
+ unit->offsetToJSClassTable = unit->offsetToRegexpTable + unit->regexpTableSize * CompiledData::RegExp::calculateSize();
+ unit->sourceFileIndex = getStringId(irModule->fileName);
+
+ // 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() + 1)*sizeof(ushort));
+
+ string += QV4::CompiledData::String::calculateSize(qstr);
+ }
+
+ uint *functionTable = (uint *)(data + unit->offsetToFunctionTable);
+ for (uint i = 0; i < irModule->functions.size(); ++i)
+ functionTable[i] = functionOffsets.value(irModule->functions.at(i));
+
+ char *f = data + unitSize + stringDataSize;
+ for (uint i = 0; i < irModule->functions.size(); ++i) {
+ QQmlJS::V4IR::Function *function = irModule->functions.at(i);
+ if (function == irModule->rootFunction)
+ unit->indexOfRootFunction = i;
+
+ const int bytes = writeFunction(f, i, function);
+ f += bytes;
+ }
+
+ CompiledData::Lookup *lookupsToWrite = (CompiledData::Lookup*)(data + unit->offsetToLookupTable);
+ foreach (const CompiledData::Lookup &l, lookups)
+ *lookupsToWrite++ = l;
+
+ CompiledData::RegExp *regexpTable = (CompiledData::RegExp *)(data + unit->offsetToRegexpTable);
+ memcpy(regexpTable, regexps.constData(), regexps.size() * sizeof(*regexpTable));
+
+ // write js classes and js class lookup table
+ uint *jsClassTable = (uint*)(data + unit->offsetToJSClassTable);
+ char *jsClass = data + unitSize + stringDataSize + functionDataSize;
+ for (int i = 0; i < jsClasses.count(); ++i) {
+ jsClassTable[i] = jsClass - data;
+
+ const QList<CompiledData::JSClassMember> members = jsClasses.at(i);
+
+ CompiledData::JSClass *c = reinterpret_cast<CompiledData::JSClass*>(jsClass);
+ c->nMembers = members.count();
+
+ CompiledData::JSClassMember *memberToWrite = reinterpret_cast<CompiledData::JSClassMember*>(jsClass + sizeof(CompiledData::JSClass));
+ foreach (const CompiledData::JSClassMember &member, members)
+ *memberToWrite++ = member;
+
+ jsClass += CompiledData::JSClass::calculateSize(members.count());
+ }
+
+ return unit;
+}
+
+int QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QQmlJS::V4IR::Function *irFunction)
+{
+ QV4::CompiledData::Function *function = (QV4::CompiledData::Function *)f;
+
+ QHash<QQmlJS::V4IR::Function *, QVector<uint> >::ConstIterator lineNumberMapping = lineNumberMappingsPerFunction.find(irFunction);
+
+ function->index = index;
+ function->nameIndex = getStringId(*irFunction->name);
+ function->flags = 0;
+ if (irFunction->hasDirectEval)
+ function->flags |= CompiledData::Function::HasDirectEval;
+ if (irFunction->usesArgumentsObject)
+ function->flags |= CompiledData::Function::UsesArgumentsObject;
+ if (irFunction->isStrict)
+ function->flags |= CompiledData::Function::IsStrict;
+ if (irFunction->isNamedExpression)
+ function->flags |= CompiledData::Function::IsNamedExpression;
+ 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->nLineNumberMappingEntries = 0;
+ if (lineNumberMapping != lineNumberMappingsPerFunction.constEnd()) {
+ function->nLineNumberMappingEntries = lineNumberMapping->count() / 2;
+ }
+ function->lineNumberMappingOffset = function->localsOffset + function->nLocals * sizeof(quint32);
+
+ function->nInnerFunctions = irFunction->nestedFunctions.size();
+ function->innerFunctionsOffset = function->lineNumberMappingOffset + function->nLineNumberMappingEntries * 2 * 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 line number mappings
+ if (function->nLineNumberMappingEntries) {
+ quint32 *mappingsToWrite = (quint32*)(f + function->lineNumberMappingOffset);
+ memcpy(mappingsToWrite, lineNumberMapping->constData(), 2 * function->nLineNumberMappingEntries * sizeof(quint32));
+ }
+
+ // 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));
+
+ return CompiledData::Function::calculateSize(function->nFormals, function->nLocals, function->nInnerFunctions, function->nLineNumberMappingEntries);
+}
+
+
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
new file mode 100644
index 0000000000..6c50073a24
--- /dev/null
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** 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"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+namespace CompiledData {
+struct Unit;
+struct Lookup;
+struct RegExp;
+struct JSClassMember;
+}
+
+namespace Compiler {
+
+struct JSUnitGenerator {
+ JSUnitGenerator(QQmlJS::V4IR::Module *module);
+
+ QQmlJS::V4IR::Module *irModule;
+
+ int registerString(const QString &str);
+ int getStringId(const QString &string) const;
+
+ uint registerGetterLookup(const QString &name);
+ uint registerSetterLookup(const QString &name);
+ uint registerGlobalGetterLookup(const QString &name);
+
+ int registerRegExp(QQmlJS::V4IR::RegExp *regexp);
+
+ void registerLineNumberMapping(QQmlJS::V4IR::Function *function, const QVector<uint> &mappings);
+
+ int registerJSClass(QQmlJS::V4IR::ExprList *args);
+
+ QV4::CompiledData::Unit *generateUnit();
+ // Returns bytes written
+ int writeFunction(char *f, int index, QQmlJS::V4IR::Function *irFunction);
+
+ QHash<QString, int> stringToId;
+ QStringList strings;
+ int stringDataSize;
+ QHash<QQmlJS::V4IR::Function *, uint> functionOffsets;
+ QList<CompiledData::Lookup> lookups;
+ QVector<CompiledData::RegExp> regexps;
+ QHash<QQmlJS::V4IR::Function *, QVector<uint> > lineNumberMappingsPerFunction;
+ QList<QList<CompiledData::JSClassMember> > jsClasses;
+ int jsClassDataSize;
+};
+
+}
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 5e1fb6f441..8164e439f0 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -52,6 +52,8 @@ QT_BEGIN_NAMESPACE
#define FOR_EACH_MOTH_INSTR(F) \
F(Ret, ret) \
F(LoadValue, loadValue) \
+ F(LoadRuntimeString, loadRuntimeString) \
+ F(LoadRegExp, loadRegExp) \
F(LoadClosure, loadClosure) \
F(MoveTemp, moveTemp) \
F(LoadName, loadName) \
@@ -219,6 +221,16 @@ union Instr
Param value;
Param result;
};
+ struct instr_loadRuntimeString {
+ MOTH_INSTR_HEADER
+ int stringId;
+ Param result;
+ };
+ struct instr_loadRegExp {
+ MOTH_INSTR_HEADER
+ int regExpId;
+ Param result;
+ };
struct instr_moveTemp {
MOTH_INSTR_HEADER
Param source;
@@ -226,28 +238,28 @@ union Instr
};
struct instr_loadClosure {
MOTH_INSTR_HEADER
- QV4::Function *value;
+ int value;
Param result;
};
struct instr_loadName {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
Param result;
};
struct instr_storeName {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
Param source;
};
struct instr_loadProperty {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
Param base;
Param result;
};
struct instr_storeProperty {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
Param base;
Param source;
};
@@ -271,7 +283,7 @@ union Instr
MOTH_INSTR_HEADER
ptrdiff_t tryOffset;
ptrdiff_t catchOffset;
- QV4::String *exceptionVarName;
+ int exceptionVarName;
Param exceptionVar;
};
struct instr_callValue {
@@ -283,7 +295,7 @@ union Instr
};
struct instr_callProperty {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
quint32 argc;
quint32 args;
Param base;
@@ -299,7 +311,7 @@ union Instr
};
struct instr_callActivationProperty {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
quint32 argc;
quint32 args;
Param result;
@@ -330,7 +342,7 @@ union Instr
};
struct instr_callBuiltinDeleteMember {
MOTH_INSTR_HEADER
- QV4::String *member;
+ int member;
Param base;
Param result;
};
@@ -342,12 +354,12 @@ union Instr
};
struct instr_callBuiltinDeleteName {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
Param result;
};
struct instr_callBuiltinTypeofMember {
MOTH_INSTR_HEADER
- QV4::String *member;
+ int member;
Param base;
Param result;
};
@@ -359,7 +371,7 @@ union Instr
};
struct instr_callBuiltinTypeofName {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
Param result;
};
struct instr_callBuiltinTypeofValue {
@@ -370,7 +382,7 @@ union Instr
struct instr_callBuiltinPostIncMember {
MOTH_INSTR_HEADER
Param base;
- QV4::String *member;
+ int member;
Param result;
};
struct instr_callBuiltinPostIncSubscript {
@@ -381,7 +393,7 @@ union Instr
};
struct instr_callBuiltinPostIncName {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
Param result;
};
struct instr_callBuiltinPostIncValue {
@@ -392,7 +404,7 @@ union Instr
struct instr_callBuiltinPostDecMember {
MOTH_INSTR_HEADER
Param base;
- QV4::String *member;
+ int member;
Param result;
};
struct instr_callBuiltinPostDecSubscript {
@@ -403,7 +415,7 @@ union Instr
};
struct instr_callBuiltinPostDecName {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
Param result;
};
struct instr_callBuiltinPostDecValue {
@@ -413,19 +425,19 @@ union Instr
};
struct instr_callBuiltinDeclareVar {
MOTH_INSTR_HEADER
- QV4::String *varName;
+ int varName;
bool isDeletable;
};
struct instr_callBuiltinDefineGetterSetter {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
Param object;
Param getter;
Param setter;
};
struct instr_callBuiltinDefineProperty {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
Param object;
Param value;
};
@@ -437,7 +449,7 @@ union Instr
};
struct instr_callBuiltinDefineObjectLiteral {
MOTH_INSTR_HEADER
- QV4::InternalClass *internalClass;
+ int internalClassId;
quint32 args;
Param result;
};
@@ -454,7 +466,7 @@ union Instr
};
struct instr_createProperty {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
quint32 argc;
quint32 args;
Param base;
@@ -462,7 +474,7 @@ union Instr
};
struct instr_createActivationProperty {
MOTH_INSTR_HEADER
- QV4::String *name;
+ int name;
quint32 argc;
quint32 args;
Param result;
@@ -528,20 +540,22 @@ union Instr
struct instr_inplaceMemberOp {
MOTH_INSTR_HEADER
QV4::InplaceBinOpMember alu;
- QV4::String *member;
+ int member;
Param base;
Param source;
};
struct instr_inplaceNameOp {
MOTH_INSTR_HEADER
QV4::InplaceBinOpName alu;
- QV4::String *name;
+ int name;
Param source;
};
instr_common common;
instr_ret ret;
instr_loadValue loadValue;
+ instr_loadRuntimeString loadRuntimeString;
+ instr_loadRegExp loadRegExp;
instr_moveTemp moveTemp;
instr_loadClosure loadClosure;
instr_loadName loadName;
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index 5c66e7f00c..1da78b5788 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -65,6 +65,36 @@ using namespace QQmlJS;
using namespace QQmlJS::MASM;
using namespace QV4;
+CompilationUnit::~CompilationUnit()
+{
+ UnwindHelper::deregisterFunctions(runtimeFunctions);
+}
+
+void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine)
+{
+ runtimeFunctions.resize(data->functionTableSize);
+ for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
+ const CompiledData::Function *compiledFunction = data->functionAt(i);
+
+ QV4::Function *runtimeFunction = new QV4::Function(engine, this, compiledFunction,
+ (Value (*)(QV4::ExecutionContext *, const uchar *)) codeRefs[i].code().executableAddress(),
+ codeRefs[i].size());
+ runtimeFunctions[i] = runtimeFunction;
+ }
+
+ UnwindHelper::registerFunctions(runtimeFunctions);
+}
+
+QV4::ExecutableAllocator::ChunkOfPages *CompilationUnit::chunkForFunction(int functionIndex)
+{
+ if (functionIndex < 0 || functionIndex >= codeRefs.count())
+ return 0;
+ JSC::ExecutableMemoryHandle *handle = codeRefs[functionIndex].executableMemory();
+ if (!handle)
+ return 0;
+ return handle->chunk();
+}
+
namespace {
class ConvertTemps: protected V4IR::StmtVisitor, protected V4IR::ExprVisitor
{
@@ -178,8 +208,8 @@ const int Assembler::calleeSavedRegisterCount = sizeof(calleeSavedRegisters) / s
const Assembler::VoidType Assembler::Void;
-Assembler::Assembler(V4IR::Function* function, QV4::Function *vmFunction, QV4::ExecutionEngine *engine)
- : _function(function), _vmFunction(vmFunction), _engine(engine), _nextBlock(0)
+Assembler::Assembler(InstructionSelection *isel, V4IR::Function* function, QV4::ExecutableAllocator *executableAllocator)
+ : _function(function), _isel(isel), _executableAllocator(executableAllocator), _nextBlock(0)
{
}
@@ -251,6 +281,13 @@ Assembler::Pointer Assembler::loadTempAddress(RegisterID reg, V4IR::Temp *t)
return Pointer(reg, offset);
}
+Assembler::Pointer Assembler::loadStringAddress(RegisterID reg, const QString &string)
+{
+ loadPtr(Address(Assembler::ContextRegister, offsetof(QV4::ExecutionContext, runtimeStrings)), reg);
+ const int id = _isel->registerString(string);
+ return Pointer(reg, id * sizeof(QV4::String*));
+}
+
template <typename Result, typename Source>
void Assembler::copyValue(Result result, Source source)
{
@@ -494,8 +531,7 @@ void Assembler::generateBinOp(V4IR::AluOp operation, V4IR::Temp* target, V4IR::T
binOpFinished.link(this);
}
#if OS(LINUX) || OS(MAC_OS_X)
-static void printDisassembledOutputWithCalls(const char* output, const QHash<void*, const char*>& functions,
- const QVector<String*> &identifiers)
+static void printDisassembledOutputWithCalls(const char* output, const QHash<void*, const char*>& functions)
{
QByteArray processedOutput(output);
for (QHash<void*, const char*>::ConstIterator it = functions.begin(), end = functions.end();
@@ -504,13 +540,6 @@ static void printDisassembledOutputWithCalls(const char* output, const QHash<voi
ptrString.prepend("0x");
processedOutput = processedOutput.replace(ptrString, it.value());
}
- for (QVector<String*>::ConstIterator it = identifiers.begin(), end = identifiers.end();
- it != end; ++it) {
- QByteArray ptrString = QByteArray::number(quintptr(*it), 16);
- ptrString.prepend("0x");
- QByteArray replacement = "\"" + (*it)->toQString().toUtf8() + "\"";
- processedOutput = processedOutput.replace(ptrString, replacement);
- }
fprintf(stderr, "%s\n", processedOutput.constData());
}
#endif
@@ -524,10 +553,10 @@ void Assembler::recordLineNumber(int lineNumber)
}
-void Assembler::link(QV4::Function *vmFunc)
+JSC::MacroAssemblerCodeRef Assembler::link()
{
- Label endOfCode = label();
#if defined(Q_PROCESSOR_ARM) && !defined(Q_OS_IOS)
+ Label endOfCode = label();
// Let the ARM exception table follow right after that
for (int i = 0, nops = UnwindHelper::unwindInfoSize() / 2; i < nops; ++i)
nop();
@@ -545,17 +574,16 @@ void Assembler::link(QV4::Function *vmFunc)
}
}
- JSC::JSGlobalData dummy(_engine->executableAllocator);
+ JSC::JSGlobalData dummy(_executableAllocator);
JSC::LinkBuffer linkBuffer(dummy, this, 0);
- vmFunc->codeSize = linkBuffer.offsetOf(endOfCode);
- vmFunc->lineNumberMappings.resize(codeLineNumberMappings.count());
+ QVector<uint> lineNumberMapping(codeLineNumberMappings.count() * 2);
+
for (int i = 0; i < codeLineNumberMappings.count(); ++i) {
- QV4::LineNumberMapping mapping;
- mapping.codeOffset = linkBuffer.offsetOf(codeLineNumberMappings.at(i).location);
- mapping.lineNumber = codeLineNumberMappings.at(i).lineNumber;
- vmFunc->lineNumberMappings[i] = mapping;
+ lineNumberMapping[i * 2] = linkBuffer.offsetOf(codeLineNumberMappings.at(i).location);
+ lineNumberMapping[i * 2 + 1] = codeLineNumberMappings.at(i).lineNumber;
}
+ _isel->registerLineNumberMapping(_function, lineNumberMapping);
QHash<void*, const char*> functions;
foreach (CallToLink ctl, _callsToLink) {
@@ -582,6 +610,8 @@ void Assembler::link(QV4::Function *vmFunc)
UnwindHelper::writeARMUnwindInfo(linkBuffer.debugAddress(), linkBuffer.offsetOf(endOfCode));
#endif
+ JSC::MacroAssemblerCodeRef codeRef;
+
static bool showCode = !qgetenv("SHOW_CODE").isNull();
if (showCode) {
#if OS(LINUX) && !defined(Q_OS_ANDROID)
@@ -610,7 +640,7 @@ void Assembler::link(QV4::Function *vmFunc)
name.prepend("IR::Function(0x");
name.append(")");
}
- vmFunc->codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data());
+ codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data());
WTF::setDataFile(stderr);
#if (OS(LINUX) && !defined(Q_OS_ANDROID)) || OS(MAC_OS_X)
@@ -620,27 +650,27 @@ void Assembler::link(QV4::Function *vmFunc)
# endif
# if CPU(X86) || CPU(X86_64)
QHash<void*, String*> idents;
- printDisassembledOutputWithCalls(disasmOutput, functions, _vmFunction->identifiers);
+ printDisassembledOutputWithCalls(disasmOutput, functions);
# endif
# if OS(LINUX)
free(disasmOutput);
# endif
#endif
} else {
- vmFunc->codeRef = linkBuffer.finalizeCodeWithoutDisassembly();
+ codeRef = linkBuffer.finalizeCodeWithoutDisassembly();
}
- vmFunc->code = (Value (*)(QV4::ExecutionContext *, const uchar *)) vmFunc->codeRef.code().executableAddress();
+ return codeRef;
}
-InstructionSelection::InstructionSelection(QV4::ExecutionEngine *engine, V4IR::Module *module)
- : EvalInstructionSelection(engine, module)
+InstructionSelection::InstructionSelection(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module)
+ : EvalInstructionSelection(execAllocator, module)
, _block(0)
, _function(0)
- , _vmFunction(0)
, _as(0)
, _locals(0)
{
+ compilationUnit = new CompilationUnit;
}
InstructionSelection::~InstructionSelection()
@@ -648,16 +678,14 @@ InstructionSelection::~InstructionSelection()
delete _as;
}
-void InstructionSelection::run(QV4::Function *vmFunction, V4IR::Function *function)
+void InstructionSelection::run(V4IR::Function *function)
{
QVector<Lookup> lookups;
QSet<V4IR::BasicBlock*> reentryBlocks;
qSwap(_function, function);
- qSwap(_vmFunction, vmFunction);
- qSwap(_lookups, lookups);
qSwap(_reentryBlocks, reentryBlocks);
Assembler* oldAssembler = _as;
- _as = new Assembler(_function, _vmFunction, engine());
+ _as = new Assembler(this, _function, executableAllocator);
V4IR::Optimizer opt(_function);
opt.run();
@@ -731,31 +759,32 @@ void InstructionSelection::run(QV4::Function *vmFunction, V4IR::Function *functi
}
}
- _as->link(_vmFunction);
+ JSC::MacroAssemblerCodeRef codeRef =_as->link();
+ codeRefs[_function] = codeRef;
- if (_lookups.size()) {
- _vmFunction->lookups = new Lookup[_lookups.size()];
- memcpy(_vmFunction->lookups, _lookups.constData(), _lookups.size()*sizeof(Lookup));
- }
-
- UnwindHelper::registerFunction(_vmFunction);
-
- qSwap(_vmFunction, vmFunction);
qSwap(_function, function);
- qSwap(_lookups, lookups);
qSwap(_reentryBlocks, reentryBlocks);
qSwap(_locals, locals);
delete _as;
_as = oldAssembler;
}
+QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
+{
+ compilationUnit->data = generateUnit();
+ compilationUnit->codeRefs.resize(irModule->functions.size());
+ int i = 0;
+ foreach (V4IR::Function *irFunction, irModule->functions)
+ compilationUnit->codeRefs[i++] = codeRefs[irFunction];
+ return compilationUnit;
+}
+
void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
{
int argc = prepareVariableArguments(args);
- QV4::String *s = identifier(*func->id);
if (useFastLookups && func->global) {
- uint index = addGlobalLookup(s);
+ uint index = registerGlobalGetterLookup(*func->id);
generateFunctionCall(Assembler::Void, __qmljs_call_global_lookup,
Assembler::ContextRegister, Assembler::PointerToValue(result),
Assembler::TrustedImm32(index),
@@ -764,7 +793,7 @@ void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *
} else {
generateFunctionCall(Assembler::Void, __qmljs_call_activation_property,
Assembler::ContextRegister, Assembler::PointerToValue(result),
- s,
+ Assembler::PointerToString(*func->id),
baseAddressForCallArguments(),
Assembler::TrustedImm32(argc));
}
@@ -773,7 +802,7 @@ void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *
void InstructionSelection::callBuiltinTypeofMember(V4IR::Temp *base, const QString &name, V4IR::Temp *result)
{
generateFunctionCall(Assembler::Void, __qmljs_builtin_typeof_member, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::Reference(base), identifier(name));
+ Assembler::PointerToValue(result), Assembler::Reference(base), Assembler::PointerToString(name));
}
void InstructionSelection::callBuiltinTypeofSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::Temp *result)
@@ -785,7 +814,7 @@ void InstructionSelection::callBuiltinTypeofSubscript(V4IR::Temp *base, V4IR::Te
void InstructionSelection::callBuiltinTypeofName(const QString &name, V4IR::Temp *result)
{
- generateFunctionCall(Assembler::Void, __qmljs_builtin_typeof_name, Assembler::ContextRegister, Assembler::PointerToValue(result), identifier(name));
+ generateFunctionCall(Assembler::Void, __qmljs_builtin_typeof_name, Assembler::ContextRegister, Assembler::PointerToValue(result), Assembler::PointerToString(name));
}
void InstructionSelection::callBuiltinTypeofValue(V4IR::Temp *value, V4IR::Temp *result)
@@ -797,7 +826,7 @@ void InstructionSelection::callBuiltinTypeofValue(V4IR::Temp *value, V4IR::Temp
void InstructionSelection::callBuiltinDeleteMember(V4IR::Temp *base, const QString &name, V4IR::Temp *result)
{
generateFunctionCall(Assembler::Void, __qmljs_delete_member, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::Reference(base), identifier(name));
+ Assembler::PointerToValue(result), Assembler::Reference(base), Assembler::PointerToString(name));
}
void InstructionSelection::callBuiltinDeleteSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::Temp *result)
@@ -808,7 +837,7 @@ void InstructionSelection::callBuiltinDeleteSubscript(V4IR::Temp *base, V4IR::Te
void InstructionSelection::callBuiltinDeleteName(const QString &name, V4IR::Temp *result)
{
- generateFunctionCall(Assembler::Void, __qmljs_delete_name, Assembler::ContextRegister, Assembler::PointerToValue(result), identifier(name));
+ generateFunctionCall(Assembler::Void, __qmljs_delete_name, Assembler::ContextRegister, Assembler::PointerToValue(result), Assembler::PointerToString(name));
}
void InstructionSelection::callBuiltinDeleteValue(V4IR::Temp *result)
@@ -819,7 +848,7 @@ void InstructionSelection::callBuiltinDeleteValue(V4IR::Temp *result)
void InstructionSelection::callBuiltinPostIncrementMember(V4IR::Temp *base, const QString &name, V4IR::Temp *result)
{
generateFunctionCall(Assembler::Void, __qmljs_builtin_post_increment_member, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::PointerToValue(base), identifier(name));
+ Assembler::PointerToValue(result), Assembler::PointerToValue(base), Assembler::PointerToString(name));
}
void InstructionSelection::callBuiltinPostIncrementSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::Temp *result)
@@ -831,7 +860,7 @@ void InstructionSelection::callBuiltinPostIncrementSubscript(V4IR::Temp *base, V
void InstructionSelection::callBuiltinPostIncrementName(const QString &name, V4IR::Temp *result)
{
generateFunctionCall(Assembler::Void, __qmljs_builtin_post_increment_name, Assembler::ContextRegister,
- Assembler::PointerToValue(result), identifier(name));
+ Assembler::PointerToValue(result), Assembler::PointerToString(name));
}
void InstructionSelection::callBuiltinPostIncrementValue(V4IR::Temp *value, V4IR::Temp *result)
@@ -843,7 +872,7 @@ void InstructionSelection::callBuiltinPostIncrementValue(V4IR::Temp *value, V4IR
void InstructionSelection::callBuiltinPostDecrementMember(V4IR::Temp *base, const QString &name, V4IR::Temp *result)
{
generateFunctionCall(Assembler::Void, __qmljs_builtin_post_decrement_member, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::Reference(base), identifier(name));
+ Assembler::PointerToValue(result), Assembler::Reference(base), Assembler::PointerToString(name));
}
void InstructionSelection::callBuiltinPostDecrementSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::Temp *result)
@@ -856,7 +885,7 @@ void InstructionSelection::callBuiltinPostDecrementSubscript(V4IR::Temp *base, V
void InstructionSelection::callBuiltinPostDecrementName(const QString &name, V4IR::Temp *result)
{
generateFunctionCall(Assembler::Void, __qmljs_builtin_post_decrement_name, Assembler::ContextRegister,
- Assembler::PointerToValue(result), identifier(name));
+ Assembler::PointerToValue(result), Assembler::PointerToString(name));
}
void InstructionSelection::callBuiltinPostDecrementValue(V4IR::Temp *value, V4IR::Temp *result)
@@ -905,7 +934,7 @@ void InstructionSelection::visitTry(V4IR::Try *t)
generateFunctionCall(Assembler::ReturnValueRegister, tryWrapper, Assembler::ContextRegister, Assembler::LocalsRegister,
Assembler::ReentryBlock(t->tryBlock), Assembler::ReentryBlock(t->catchBlock),
- identifier(*t->exceptionVarName), Assembler::PointerToValue(t->exceptionVar));
+ Assembler::PointerToString(*t->exceptionVarName), Assembler::PointerToValue(t->exceptionVar));
_as->jump(Assembler::ReturnValueRegister);
}
@@ -942,19 +971,19 @@ void InstructionSelection::callBuiltinPopScope()
void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &name)
{
generateFunctionCall(Assembler::Void, __qmljs_builtin_declare_var, Assembler::ContextRegister,
- Assembler::TrustedImm32(deletable), identifier(name));
+ Assembler::TrustedImm32(deletable), Assembler::PointerToString(name));
}
void InstructionSelection::callBuiltinDefineGetterSetter(V4IR::Temp *object, const QString &name, V4IR::Temp *getter, V4IR::Temp *setter)
{
generateFunctionCall(Assembler::Void, __qmljs_builtin_define_getter_setter, Assembler::ContextRegister,
- Assembler::Reference(object), identifier(name), Assembler::PointerToValue(getter), Assembler::PointerToValue(setter));
+ Assembler::Reference(object), Assembler::PointerToString(name), Assembler::PointerToValue(getter), Assembler::PointerToValue(setter));
}
void InstructionSelection::callBuiltinDefineProperty(V4IR::Temp *object, const QString &name, V4IR::Temp *value)
{
generateFunctionCall(Assembler::Void, __qmljs_builtin_define_property, Assembler::ContextRegister,
- Assembler::Reference(object), identifier(name), Assembler::PointerToValue(value));
+ Assembler::Reference(object), Assembler::PointerToString(name), Assembler::PointerToValue(value));
}
void InstructionSelection::callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args)
@@ -969,15 +998,14 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4
{
int argc = 0;
- InternalClass *klass = engine()->emptyClass;
+ const int classId = registerJSClass(args);
+
V4IR::ExprList *it = args;
while (it) {
- V4IR::Name *name = it->expr->asName();
it = it->next;
bool isData = it->expr->asConst()->value;
it = it->next;
- klass = klass->addMember(identifier(*name->id), isData ? QV4::Attr_Data : QV4::Attr_Accessor);
_as->copyValue(argumentAddressForCall(argc++), it->expr);
@@ -991,7 +1019,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4
generateFunctionCall(Assembler::Void, __qmljs_builtin_define_object_literal, Assembler::ContextRegister,
Assembler::PointerToValue(result), baseAddressForCallArguments(),
- Assembler::TrustedImmPtr(klass));
+ Assembler::TrustedImm32(classId));
}
void InstructionSelection::callBuiltinSetupArgumentObject(V4IR::Temp *result)
@@ -1026,66 +1054,58 @@ void InstructionSelection::loadConst(V4IR::Const *sourceConst, V4IR::Temp *targe
void InstructionSelection::loadString(const QString &str, V4IR::Temp *targetTemp)
{
- Value v = Value::fromString(identifier(str));
- _as->storeValue(v, targetTemp);
+ generateFunctionCall(Assembler::Void, __qmljs_value_from_string, Assembler::PointerToValue(targetTemp), Assembler::PointerToString(str));
}
void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp)
{
- Value v = Value::fromObject(engine()->newRegExpObject(*sourceRegexp->value,
- sourceRegexp->flags));
- _vmFunction->generatedValues.append(v);
- _as->storeValue(v, targetTemp);
+ int id = registerRegExp(sourceRegexp);
+ generateFunctionCall(Assembler::Void, __qmljs_lookup_runtime_regexp, Assembler::ContextRegister, Assembler::PointerToValue(targetTemp), Assembler::TrustedImm32(id));
}
void InstructionSelection::getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp)
{
- String *propertyName = identifier(*name->id);
if (useFastLookups && name->global) {
- uint index = addGlobalLookup(propertyName);
+ uint index = registerGlobalGetterLookup(*name->id);
generateLookupCall(index, offsetof(QV4::Lookup, globalGetter), Assembler::ContextRegister, Assembler::PointerToValue(temp));
return;
}
- generateFunctionCall(Assembler::Void, __qmljs_get_activation_property, Assembler::ContextRegister, Assembler::PointerToValue(temp), propertyName);
+ generateFunctionCall(Assembler::Void, __qmljs_get_activation_property, Assembler::ContextRegister, Assembler::PointerToValue(temp), Assembler::PointerToString(*name->id));
}
void InstructionSelection::setActivationProperty(V4IR::Temp *source, const QString &targetName)
{
- String *propertyName = identifier(targetName);
generateFunctionCall(Assembler::Void, __qmljs_set_activation_property,
- Assembler::ContextRegister, propertyName, Assembler::Reference(source));
+ Assembler::ContextRegister, Assembler::PointerToString(targetName), Assembler::Reference(source));
}
void InstructionSelection::initClosure(V4IR::Closure *closure, V4IR::Temp *target)
{
- QV4::Function *vmFunc = vmFunction(closure->value);
- assert(vmFunc);
- generateFunctionCall(Assembler::Void, __qmljs_init_closure, Assembler::ContextRegister, Assembler::PointerToValue(target), Assembler::TrustedImmPtr(vmFunc));
+ int id = irModule->functions.indexOf(closure->value);
+ generateFunctionCall(Assembler::Void, __qmljs_init_closure, Assembler::ContextRegister, Assembler::PointerToValue(target), Assembler::TrustedImm32(id));
}
void InstructionSelection::getProperty(V4IR::Temp *base, const QString &name, V4IR::Temp *target)
{
if (useFastLookups) {
- QV4::String *s = identifier(name);
- uint index = addLookup(s);
+ uint index = registerGetterLookup(name);
generateLookupCall(index, offsetof(QV4::Lookup, getter), Assembler::PointerToValue(target),
Assembler::Reference(base));
} else {
generateFunctionCall(Assembler::Void, __qmljs_get_property, Assembler::ContextRegister, Assembler::PointerToValue(target),
- Assembler::Reference(base), identifier(name));
+ Assembler::Reference(base), Assembler::PointerToString(name));
}
}
void InstructionSelection::setProperty(V4IR::Temp *source, V4IR::Temp *targetBase, const QString &targetName)
{
if (useFastLookups) {
- QV4::String *s = identifier(targetName);
- uint index = addSetterLookup(s);
+ uint index = registerSetterLookup(targetName);
generateLookupCall(index, offsetof(QV4::Lookup, setter), Assembler::Reference(targetBase), Assembler::Reference(source));
} else {
generateFunctionCall(Assembler::Void, __qmljs_set_property, Assembler::ContextRegister,
Assembler::Reference(targetBase),
- identifier(targetName), Assembler::Reference(source));
+ Assembler::PointerToString(targetName), Assembler::Reference(source));
}
}
@@ -1161,7 +1181,7 @@ void InstructionSelection::inplaceNameOp(V4IR::AluOp oper, V4IR::Temp *rightSour
}
if (op) {
_as->generateFunctionCallImp(Assembler::Void, opName, op, Assembler::ContextRegister,
- identifier(targetName), Assembler::Reference(rightSource));
+ Assembler::PointerToString(targetName), Assembler::Reference(rightSource));
}
}
@@ -1215,9 +1235,8 @@ void InstructionSelection::inplaceMemberOp(V4IR::AluOp oper, V4IR::Temp *source,
}
if (op) {
- String* member = identifier(targetName);
_as->generateFunctionCallImp(Assembler::Void, opName, op, Assembler::ContextRegister,
- Assembler::Reference(targetBase), identifier(targetName),
+ Assembler::Reference(targetBase), Assembler::PointerToString(targetName),
Assembler::Reference(source));
}
}
@@ -1228,10 +1247,9 @@ void InstructionSelection::callProperty(V4IR::Temp *base, const QString &name,
assert(base != 0);
int argc = prepareVariableArguments(args);
- QV4::String *s = identifier(name);
if (useFastLookups) {
- uint index = addLookup(s);
+ uint index = registerGetterLookup(name);
generateFunctionCall(Assembler::Void, __qmljs_call_property_lookup,
Assembler::ContextRegister, Assembler::PointerToValue(result),
Assembler::Reference(base), Assembler::TrustedImm32(index),
@@ -1240,7 +1258,7 @@ void InstructionSelection::callProperty(V4IR::Temp *base, const QString &name,
} else {
generateFunctionCall(Assembler::Void, __qmljs_call_property,
Assembler::ContextRegister, Assembler::PointerToValue(result),
- Assembler::Reference(base), s,
+ Assembler::Reference(base), Assembler::PointerToString(name),
baseAddressForCallArguments(),
Assembler::TrustedImm32(argc));
}
@@ -1267,22 +1285,13 @@ void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
copyValue(source, target);
}
-String *InstructionSelection::identifier(const QString &s)
-{
- String *str = engine()->newIdentifier(s);
- _vmFunction->identifiers.append(str);
- return str;
-}
-
void InstructionSelection::constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
{
assert(func != 0);
if (useFastLookups && func->global) {
int argc = prepareVariableArguments(args);
- QV4::String *s = identifier(*func->id);
-
- uint index = addGlobalLookup(s);
+ uint index = registerGlobalGetterLookup(*func->id);
generateFunctionCall(Assembler::Void, __qmljs_construct_global_lookup,
Assembler::ContextRegister, Assembler::PointerToValue(result),
Assembler::TrustedImm32(index),
@@ -1298,7 +1307,7 @@ void InstructionSelection::constructProperty(V4IR::Temp *base, const QString &na
{
int argc = prepareVariableArguments(args);
generateFunctionCall(Assembler::Void, __qmljs_construct_property, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::Reference(base), identifier(name), baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::Reference(base), Assembler::PointerToString(name), baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
}
void InstructionSelection::constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
@@ -1441,49 +1450,7 @@ void InstructionSelection::callRuntimeMethodImp(V4IR::Temp *result, const char*
int argc = prepareVariableArguments(args);
_as->generateFunctionCallImp(Assembler::Void, name, method, Assembler::ContextRegister, Assembler::PointerToValue(result),
- identifier(*baseName->id), baseAddressForCallArguments(),
+ Assembler::PointerToString(*baseName->id), baseAddressForCallArguments(),
Assembler::TrustedImm32(argc));
}
-
-uint InstructionSelection::addLookup(QV4::String *name)
-{
- uint index = (uint)_lookups.size();
- QV4::Lookup l;
- l.getter = Lookup::getterGeneric;
- for (int i = 0; i < Lookup::Size; ++i)
- l.classList[i] = 0;
- l.level = -1;
- l.index = UINT_MAX;
- l.name = name;
- _lookups.append(l);
- return index;
-}
-
-uint InstructionSelection::addSetterLookup(QV4::String *name)
-{
- uint index = (uint)_lookups.size();
- QV4::Lookup l;
- l.setter = Lookup::setterGeneric;
- for (int i = 0; i < Lookup::Size; ++i)
- l.classList[i] = 0;
- l.level = -1;
- l.index = UINT_MAX;
- l.name = name;
- _lookups.append(l);
- return index;
-}
-
-uint InstructionSelection::addGlobalLookup(QV4::String *name)
-{
- uint index = (uint)_lookups.size();
- QV4::Lookup l;
- l.globalGetter = Lookup::globalGetterGeneric;
- for (int i = 0; i < Lookup::Size; ++i)
- l.classList[i] = 0;
- l.level = -1;
- l.index = UINT_MAX;
- l.name = name;
- _lookups.append(l);
- return index;
-}
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index 9c91bfb014..84ceb2be4b 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -52,16 +52,32 @@
#include <config.h>
#include <wtf/Vector.h>
#include <assembler/MacroAssembler.h>
+#include <assembler/MacroAssemblerCodeRef.h>
QT_BEGIN_NAMESPACE
namespace QQmlJS {
namespace MASM {
+class InstructionSelection;
+
+struct CompilationUnit : public QV4::CompiledData::CompilationUnit
+{
+ virtual ~CompilationUnit();
+
+ virtual void linkBackendToEngine(QV4::ExecutionEngine *engine);
+
+ virtual QV4::ExecutableAllocator::ChunkOfPages *chunkForFunction(int functionIndex);
+
+ // Coderef + execution engine
+
+ QVector<JSC::MacroAssemblerCodeRef> codeRefs;
+};
+
class Assembler : public JSC::MacroAssembler
{
public:
- Assembler(V4IR::Function* function, QV4::Function *vmFunction, QV4::ExecutionEngine *engine);
+ Assembler(InstructionSelection *isel, V4IR::Function* function, QV4::ExecutableAllocator *executableAllocator);
#if CPU(X86)
#undef VALUE_FITS_IN_REGISTER
@@ -245,6 +261,10 @@ public:
PointerToValue(V4IR::Temp *value) : value(value) {}
V4IR::Temp *value;
};
+ struct PointerToString {
+ explicit PointerToString(const QString &string) : string(string) {}
+ QString string;
+ };
struct Reference {
Reference(V4IR::Temp *value) : value(value) {}
V4IR::Temp *value;
@@ -274,6 +294,7 @@ public:
void addPatch(DataLabelPtr patch, V4IR::BasicBlock *target);
Pointer loadTempAddress(RegisterID reg, V4IR::Temp *t);
+ Pointer loadStringAddress(RegisterID reg, const QString &string);
void loadArgumentInRegister(RegisterID source, RegisterID dest)
{
@@ -299,6 +320,11 @@ public:
loadArgumentInRegister(addr, dest);
}
}
+ void loadArgumentInRegister(PointerToString temp, RegisterID dest)
+ {
+ Pointer addr = loadStringAddress(dest, temp.string);
+ loadPtr(addr, dest);
+ }
void loadArgumentInRegister(Reference temp, RegisterID dest)
{
@@ -419,6 +445,14 @@ public:
}
template <int StackSlot>
+ void loadArgumentOnStack(PointerToString temp)
+ {
+ Pointer ptr = loadStringAddress(ScratchRegister, temp.string);
+ loadPtr(ptr, ScratchRegister);
+ poke(ScratchRegister, StackSlot);
+ }
+
+ template <int StackSlot>
void loadArgumentOnStack(Reference temp)
{
assert (temp.value);
@@ -746,13 +780,12 @@ public:
return Jump();
}
- void link(QV4::Function *vmFunc);
+ JSC::MacroAssemblerCodeRef link();
void recordLineNumber(int lineNumber);
private:
V4IR::Function *_function;
- QV4::Function *_vmFunction;
QHash<V4IR::BasicBlock *, Label> _addrs;
QHash<V4IR::BasicBlock *, QVector<Jump> > _patches;
QList<CallToLink> _callsToLink;
@@ -766,7 +799,8 @@ private:
QHash<V4IR::BasicBlock *, QVector<DataLabelPtr> > _labelPatches;
V4IR::BasicBlock *_nextBlock;
- QV4::ExecutionEngine *_engine;
+ QV4::ExecutableAllocator *_executableAllocator;
+ InstructionSelection *_isel;
struct CodeLineNumerMapping
{
@@ -781,12 +815,14 @@ class Q_QML_EXPORT InstructionSelection:
public EvalInstructionSelection
{
public:
- InstructionSelection(QV4::ExecutionEngine *engine, V4IR::Module *module);
+ InstructionSelection(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module);
~InstructionSelection();
- virtual void run(QV4::Function *vmFunction, V4IR::Function *function);
+ virtual void run(V4IR::Function *function);
protected:
+ virtual QV4::CompiledData::CompilationUnit *backendCompileStep();
+
virtual void callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result);
virtual void callBuiltinTypeofMember(V4IR::Temp *base, const QString &name, V4IR::Temp *result);
virtual void callBuiltinTypeofSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::Temp *result);
@@ -864,7 +900,6 @@ protected:
return argumentAddressForCall(0);
}
- QV4::String *identifier(const QString &s);
virtual void constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result);
virtual void constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
virtual void constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
@@ -888,10 +923,6 @@ private:
#define callRuntimeMethod(result, function, ...) \
callRuntimeMethodImp(result, isel_stringIfy(function), function, __VA_ARGS__)
- uint addLookup(QV4::String *name);
- uint addSetterLookup(QV4::String *name);
- uint addGlobalLookup(QV4::String *name);
-
template <typename Arg1, typename Arg2>
void generateLookupCall(uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2)
{
@@ -914,19 +945,20 @@ private:
V4IR::BasicBlock *_block;
V4IR::Function* _function;
- QV4::Function* _vmFunction;
- QVector<QV4::Lookup> _lookups;
Assembler* _as;
QSet<V4IR::BasicBlock*> _reentryBlocks;
int _locals;
+
+ CompilationUnit *compilationUnit;
+ QHash<V4IR::Function*, JSC::MacroAssemblerCodeRef> codeRefs;
};
class Q_QML_EXPORT ISelFactory: public EvalISelFactory
{
public:
virtual ~ISelFactory() {}
- virtual EvalInstructionSelection *create(QV4::ExecutionEngine *engine, V4IR::Module *module)
- { return new InstructionSelection(engine, module); }
+ virtual EvalInstructionSelection *create(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module)
+ { return new InstructionSelection(execAllocator, module); }
virtual bool jitCompileRegexps() const
{ return true; }
};
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 813acdecec..807f35ad7d 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -46,6 +46,7 @@
#include <private/qv4debugging_p.h>
#include <private/qv4function_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qv4compileddata_p.h>
#undef USE_TYPE_INFO
@@ -187,10 +188,9 @@ private:
}
};
-InstructionSelection::InstructionSelection(QV4::ExecutionEngine *engine, V4IR::Module *module)
- : EvalInstructionSelection(engine, module)
+InstructionSelection::InstructionSelection(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module)
+ : EvalInstructionSelection(execAllocator, module)
, _function(0)
- , _vmFunction(0)
, _block(0)
, _codeStart(0)
, _codeNext(0)
@@ -198,13 +198,14 @@ InstructionSelection::InstructionSelection(QV4::ExecutionEngine *engine, V4IR::M
, _stackSlotAllocator(0)
, _currentStatement(0)
{
+ compilationUnit = new CompilationUnit;
}
InstructionSelection::~InstructionSelection()
{
}
-void InstructionSelection::run(QV4::Function *vmFunction, V4IR::Function *function)
+void InstructionSelection::run(V4IR::Function *function)
{
V4IR::BasicBlock *block = 0, *nextBlock = 0;
@@ -218,7 +219,6 @@ void InstructionSelection::run(QV4::Function *vmFunction, V4IR::Function *functi
uchar *codeEnd = codeStart + codeSize;
qSwap(_function, function);
- qSwap(_vmFunction, vmFunction);
qSwap(block, _block);
qSwap(nextBlock, _nextBlock);
qSwap(patches, _patches);
@@ -243,18 +243,17 @@ void InstructionSelection::run(QV4::Function *vmFunction, V4IR::Function *functi
push.value = quint32(locals);
addInstruction(push);
+ QVector<uint> lineNumberMappings;
+ lineNumberMappings.reserve(_function->basicBlocks.size() * 2);
+
for (int i = 0, ei = _function->basicBlocks.size(); i != ei; ++i) {
_block = _function->basicBlocks[i];
_nextBlock = (i < ei - 1) ? _function->basicBlocks[i + 1] : 0;
_addrs.insert(_block, _codeNext - _codeStart);
foreach (V4IR::Stmt *s, _block->statements) {
- if (s->location.isValid()) {
- QV4::LineNumberMapping mapping;
- mapping.codeOffset = _codeNext - _codeStart;
- mapping.lineNumber = s->location.startLine;
- _vmFunction->lineNumberMappings.append(mapping);
- }
+ if (s->location.isValid())
+ lineNumberMappings << _codeNext - _codeStart << s->location.startLine;
if (opt.isInSSA() && s->asTerminator()) {
foreach (const V4IR::Optimizer::SSADeconstructionMove &move,
@@ -272,20 +271,17 @@ void InstructionSelection::run(QV4::Function *vmFunction, V4IR::Function *functi
}
}
+ registerLineNumberMapping(_function, lineNumberMappings);
+
// TODO: patch stack size (the push instruction)
patchJumpAddresses();
- _vmFunction->code = VME::exec;
- _vmFunction->codeData = squeezeCode();
-
- if (QV4::Debugging::Debugger *debugger = engine()->debugger)
- debugger->setPendingBreakpoints(_vmFunction);
+ codeRefs.insert(_function, squeezeCode());
qSwap(_currentStatement, cs);
qSwap(_stackSlotAllocator, stackSlotAllocator);
delete stackSlotAllocator;
qSwap(_function, function);
- qSwap(_vmFunction, vmFunction);
qSwap(block, _block);
qSwap(nextBlock, _nextBlock);
qSwap(patches, _patches);
@@ -297,6 +293,16 @@ void InstructionSelection::run(QV4::Function *vmFunction, V4IR::Function *functi
delete[] codeStart;
}
+QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
+{
+ compilationUnit->data = generateUnit();
+ compilationUnit->codeRefs.resize(irModule->functions.size());
+ int i = 0;
+ foreach (V4IR::Function *irFunction, irModule->functions)
+ compilationUnit->codeRefs[i++] = codeRefs[irFunction];
+ return compilationUnit;
+}
+
void InstructionSelection::callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
{
Instruction::CallValue call;
@@ -311,7 +317,7 @@ void InstructionSelection::callProperty(V4IR::Temp *base, const QString &name, V
// call the property on the loaded base
Instruction::CallProperty call;
call.base = getParam(base);
- call.name = identifier(name);
+ call.name = registerString(name);
prepareCallArgs(args, call.argc, call.args);
call.result = getResultParam(result);
addInstruction(call);
@@ -342,7 +348,7 @@ void InstructionSelection::constructActivationProperty(V4IR::Name *func,
V4IR::Temp *result)
{
Instruction::CreateActivationProperty create;
- create.name = identifier(*func->id);
+ create.name = registerString(*func->id);
prepareCallArgs(args, create.argc, create.args);
create.result = getResultParam(result);
addInstruction(create);
@@ -352,7 +358,7 @@ void InstructionSelection::constructProperty(V4IR::Temp *base, const QString &na
{
Instruction::CreateProperty create;
create.base = getParam(base);
- create.name = identifier(name);
+ create.name = registerString(name);
prepareCallArgs(args, create.argc, create.args);
create.result = getResultParam(result);
addInstruction(create);
@@ -386,21 +392,16 @@ void InstructionSelection::loadConst(V4IR::Const *sourceConst, V4IR::Temp *targe
void InstructionSelection::loadString(const QString &str, V4IR::Temp *targetTemp)
{
- Instruction::LoadValue load;
- load.value = Param::createValue(QV4::Value::fromString(identifier(str)));
+ Instruction::LoadRuntimeString load;
+ load.stringId = registerString(str);
load.result = getResultParam(targetTemp);
addInstruction(load);
}
void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp)
{
- QV4::Value v = QV4::Value::fromObject(engine()->newRegExpObject(
- *sourceRegexp->value,
- sourceRegexp->flags));
- _vmFunction->generatedValues.append(v);
-
- Instruction::LoadValue load;
- load.value = Param::createValue(v);
+ Instruction::LoadRegExp load;
+ load.regExpId = registerRegExp(sourceRegexp);
load.result = getResultParam(targetTemp);
addInstruction(load);
}
@@ -408,7 +409,7 @@ void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *ta
void InstructionSelection::getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp)
{
Instruction::LoadName load;
- load.name = identifier(*name->id);
+ load.name = registerString(*name->id);
load.result = getResultParam(temp);
addInstruction(load);
}
@@ -417,16 +418,15 @@ void InstructionSelection::setActivationProperty(V4IR::Temp *source, const QStri
{
Instruction::StoreName store;
store.source = getParam(source);
- store.name = identifier(targetName);
+ store.name = registerString(targetName);
addInstruction(store);
}
void InstructionSelection::initClosure(V4IR::Closure *closure, V4IR::Temp *target)
{
- QV4::Function *vmFunc = vmFunction(closure->value);
- assert(vmFunc);
+ int id = irModule->functions.indexOf(closure->value);
Instruction::LoadClosure load;
- load.value = vmFunc;
+ load.value = id;
load.result = getResultParam(target);
addInstruction(load);
}
@@ -435,7 +435,7 @@ void InstructionSelection::getProperty(V4IR::Temp *base, const QString &name, V4
{
Instruction::LoadProperty load;
load.base = getParam(base);
- load.name = identifier(name);
+ load.name = registerString(name);
load.result = getResultParam(target);
addInstruction(load);
}
@@ -444,7 +444,7 @@ void InstructionSelection::setProperty(V4IR::Temp *source, V4IR::Temp *targetBas
{
Instruction::StoreProperty store;
store.base = getParam(targetBase);
- store.name = identifier(targetName);
+ store.name = registerString(targetName);
store.source = getParam(source);
addInstruction(store);
}
@@ -591,7 +591,7 @@ void InstructionSelection::inplaceNameOp(V4IR::AluOp oper, V4IR::Temp *rightSour
if (op) {
Instruction::InplaceNameOp ieo;
ieo.alu = op;
- ieo.name = identifier(targetName);
+ ieo.name = registerString(targetName);
ieo.source = getParam(rightSource);
addInstruction(ieo);
}
@@ -644,7 +644,7 @@ void InstructionSelection::inplaceMemberOp(V4IR::AluOp oper, V4IR::Temp *source,
Instruction::InplaceMemberOp imo;
imo.alu = op;
imo.base = getParam(targetBase);
- imo.member = identifier(targetName);
+ imo.member = registerString(targetName);
imo.source = getParam(source);
addInstruction(imo);
}
@@ -730,7 +730,7 @@ void InstructionSelection::visitTry(V4IR::Try *t)
Instruction::EnterTry enterTry;
enterTry.tryOffset = 0;
enterTry.catchOffset = 0;
- enterTry.exceptionVarName = identifier(*t->exceptionVarName);
+ enterTry.exceptionVarName = registerString(*t->exceptionVarName);
enterTry.exceptionVar = getParam(t->exceptionVar);
ptrdiff_t enterTryLoc = addInstruction(enterTry);
@@ -744,7 +744,7 @@ void InstructionSelection::visitTry(V4IR::Try *t)
void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
{
Instruction::CallActivationProperty call;
- call.name = identifier(*func->id);
+ call.name = registerString(*func->id);
prepareCallArgs(args, call.argc, call.args);
call.result = getResultParam(result);
addInstruction(call);
@@ -754,7 +754,7 @@ void InstructionSelection::callBuiltinTypeofMember(V4IR::Temp *base, const QStri
{
Instruction::CallBuiltinTypeofMember call;
call.base = getParam(base);
- call.member = identifier(name);
+ call.member = registerString(name);
call.result = getResultParam(result);
addInstruction(call);
}
@@ -771,7 +771,7 @@ void InstructionSelection::callBuiltinTypeofSubscript(V4IR::Temp *base, V4IR::Te
void InstructionSelection::callBuiltinTypeofName(const QString &name, V4IR::Temp *result)
{
Instruction::CallBuiltinTypeofName call;
- call.name = identifier(name);
+ call.name = registerString(name);
call.result = getResultParam(result);
addInstruction(call);
}
@@ -788,7 +788,7 @@ void InstructionSelection::callBuiltinDeleteMember(V4IR::Temp *base, const QStri
{
Instruction::CallBuiltinDeleteMember call;
call.base = getParam(base);
- call.member = identifier(name);
+ call.member = registerString(name);
call.result = getResultParam(result);
addInstruction(call);
}
@@ -805,7 +805,7 @@ void InstructionSelection::callBuiltinDeleteSubscript(V4IR::Temp *base, V4IR::Te
void InstructionSelection::callBuiltinDeleteName(const QString &name, V4IR::Temp *result)
{
Instruction::CallBuiltinDeleteName call;
- call.name = identifier(name);
+ call.name = registerString(name);
call.result = getResultParam(result);
addInstruction(call);
}
@@ -822,7 +822,7 @@ void InstructionSelection::callBuiltinPostDecrementMember(V4IR::Temp *base, cons
{
Instruction::CallBuiltinPostDecMember call;
call.base = getParam(base);
- call.member = identifier(name);
+ call.member = registerString(name);
call.result = getResultParam(result);
addInstruction(call);
}
@@ -839,7 +839,7 @@ void InstructionSelection::callBuiltinPostDecrementSubscript(V4IR::Temp *base, V
void InstructionSelection::callBuiltinPostDecrementName(const QString &name, V4IR::Temp *result)
{
Instruction::CallBuiltinPostDecName call;
- call.name = identifier(name);
+ call.name = registerString(name);
call.result = getResultParam(result);
addInstruction(call);
}
@@ -856,7 +856,7 @@ void InstructionSelection::callBuiltinPostIncrementMember(V4IR::Temp *base, cons
{
Instruction::CallBuiltinPostIncMember call;
call.base = getParam(base);
- call.member = identifier(name);
+ call.member = registerString(name);
call.result = getResultParam(result);
addInstruction(call);
}
@@ -873,7 +873,7 @@ void InstructionSelection::callBuiltinPostIncrementSubscript(V4IR::Temp *base, V
void InstructionSelection::callBuiltinPostIncrementName(const QString &name, V4IR::Temp *result)
{
Instruction::CallBuiltinPostIncName call;
- call.name = identifier(name);
+ call.name = registerString(name);
call.result = getResultParam(result);
addInstruction(call);
}
@@ -932,7 +932,7 @@ void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &
{
Instruction::CallBuiltinDeclareVar call;
call.isDeletable = deletable;
- call.varName = identifier(name);
+ call.varName = registerString(name);
addInstruction(call);
}
@@ -940,7 +940,7 @@ void InstructionSelection::callBuiltinDefineGetterSetter(V4IR::Temp *object, con
{
Instruction::CallBuiltinDefineGetterSetter call;
call.object = getParam(object);
- call.name = identifier(name);
+ call.name = registerString(name);
call.getter = getParam(getter);
call.setter = getParam(setter);
addInstruction(call);
@@ -950,7 +950,7 @@ void InstructionSelection::callBuiltinDefineProperty(V4IR::Temp *object, const Q
{
Instruction::CallBuiltinDefineProperty call;
call.object = getParam(object);
- call.name = identifier(name);
+ call.name = registerString(name);
call.value = getParam(value);
addInstruction(call);
}
@@ -967,15 +967,13 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4
{
int argLocation = outgoingArgumentTempStart();
- QV4::InternalClass *klass = engine()->emptyClass;
+ const int classId = registerJSClass(args);
V4IR::ExprList *it = args;
while (it) {
- V4IR::Name *name = it->expr->asName();
it = it->next;
bool isData = it->expr->asConst()->value;
it = it->next;
- klass = klass->addMember(identifier(*name->id), isData ? QV4::Attr_Data : QV4::Attr_Accessor);
Instruction::MoveTemp move;
move.source = getParam(it->expr);
@@ -997,7 +995,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4
}
Instruction::CallBuiltinDefineObjectLiteral call;
- call.internalClass = klass;
+ call.internalClassId = classId;
call.args = outgoingArgumentTempStart();
call.result = getResultParam(result);
addInstruction(call);
@@ -1057,21 +1055,15 @@ void InstructionSelection::patchJumpAddresses()
_addrs.clear();
}
-uchar *InstructionSelection::squeezeCode() const
+QByteArray InstructionSelection::squeezeCode() const
{
int codeSize = _codeNext - _codeStart;
- uchar *squeezed = new uchar[codeSize];
- ::memcpy(squeezed, _codeStart, codeSize);
+ QByteArray squeezed;
+ squeezed.resize(codeSize);
+ ::memcpy(squeezed.data(), _codeStart, codeSize);
return squeezed;
}
-QV4::String *InstructionSelection::identifier(const QString &s)
-{
- QV4::String *str = engine()->newIdentifier(s);
- _vmFunction->identifiers.append(str);
- return str;
-}
-
Param InstructionSelection::getParam(V4IR::Expr *e) {
typedef Param Param;
assert(e);
@@ -1096,3 +1088,20 @@ Param InstructionSelection::getParam(V4IR::Expr *e) {
return Param();
}
}
+
+
+void CompilationUnit::linkBackendToEngine(QV4::ExecutionEngine *engine)
+{
+ runtimeFunctions.resize(data->functionTableSize);
+ for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
+ const QV4::CompiledData::Function *compiledFunction = data->functionAt(i);
+
+ QV4::Function *runtimeFunction = new QV4::Function(engine, this, compiledFunction,
+ &VME::exec, /*size - doesn't matter for moth*/0);
+ runtimeFunction->codeData = reinterpret_cast<const uchar *>(codeRefs.at(i).constData());
+ runtimeFunctions[i] = runtimeFunction;
+
+ if (QV4::Debugging::Debugger *debugger = engine->debugger)
+ debugger->setPendingBreakpoints(runtimeFunction);
+ }
+}
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index b6e4b43582..c88db6f759 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -56,17 +56,28 @@ namespace Moth {
class StackSlotAllocator;
+struct CompilationUnit : public QV4::CompiledData::CompilationUnit
+{
+ virtual void linkBackendToEngine(QV4::ExecutionEngine *engine);
+
+ QVector<QByteArray> codeRefs;
+
+};
+
+
class Q_QML_EXPORT InstructionSelection:
public V4IR::IRDecoder,
public EvalInstructionSelection
{
public:
- InstructionSelection(QV4::ExecutionEngine *engine, V4IR::Module *module);
+ InstructionSelection(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module);
~InstructionSelection();
- virtual void run(QV4::Function *vmFunction, V4IR::Function *function);
+ virtual void run(V4IR::Function *function);
protected:
+ virtual QV4::CompiledData::CompilationUnit *backendCompileStep();
+
virtual void visitJump(V4IR::Jump *);
virtual void visitCJump(V4IR::CJump *);
virtual void visitRet(V4IR::Ret *);
@@ -158,12 +169,9 @@ private:
inline ptrdiff_t addInstruction(const InstrData<Instr> &data);
ptrdiff_t addInstructionHelper(Instr::Type type, Instr &instr);
void patchJumpAddresses();
- uchar *squeezeCode() const;
-
- QV4::String *identifier(const QString &s);
+ QByteArray squeezeCode() const;
V4IR::Function *_function;
- QV4::Function *_vmFunction;
V4IR::BasicBlock *_block;
V4IR::BasicBlock *_nextBlock;
@@ -176,14 +184,17 @@ private:
StackSlotAllocator *_stackSlotAllocator;
V4IR::Stmt *_currentStatement;
+
+ CompilationUnit *compilationUnit;
+ QHash<V4IR::Function *, QByteArray> codeRefs;
};
class Q_QML_EXPORT ISelFactory: public EvalISelFactory
{
public:
virtual ~ISelFactory() {}
- virtual EvalInstructionSelection *create(QV4::ExecutionEngine *engine, V4IR::Module *module)
- { return new InstructionSelection(engine, module); }
+ virtual EvalInstructionSelection *create(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module)
+ { return new InstructionSelection(execAllocator, module); }
virtual bool jitCompileRegexps() const
{ return false; }
};
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 7194473849..96199b59d2 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -58,17 +58,13 @@ QTextStream qout(stderr, QIODevice::WriteOnly);
using namespace QQmlJS;
using namespace QQmlJS::V4IR;
-EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutionEngine *engine, Module *module)
- : _engine(engine)
+EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, Module *module)
+ : QV4::Compiler::JSUnitGenerator(module)
, useFastLookups(true)
+ , executableAllocator(execAllocator)
{
- assert(engine);
+ assert(execAllocator);
assert(module);
-
- createFunctionMapping(0, module->rootFunction);
- foreach (V4IR::Function *f, module->functions) {
- assert(_irToVM.contains(f));
- }
}
EvalInstructionSelection::~EvalInstructionSelection()
@@ -77,39 +73,15 @@ EvalInstructionSelection::~EvalInstructionSelection()
EvalISelFactory::~EvalISelFactory()
{}
-QV4::Function *EvalInstructionSelection::createFunctionMapping(QV4::Function *outer, Function *irFunction)
+QV4::CompiledData::CompilationUnit *EvalInstructionSelection::compile()
{
- QV4::Function *vmFunction = _engine->newFunction(irFunction->name ? *irFunction->name : QString());
- _irToVM.insert(irFunction, vmFunction);
-
- vmFunction->hasDirectEval = irFunction->hasDirectEval;
- vmFunction->usesArgumentsObject = irFunction->usesArgumentsObject;
- vmFunction->hasNestedFunctions = !irFunction->nestedFunctions.isEmpty();
- vmFunction->isStrict = irFunction->isStrict;
- vmFunction->isNamedExpression = irFunction->isNamedExpression;
- vmFunction->sourceFile = irFunction->sourceFile;
-
- if (outer)
- outer->addNestedFunction(vmFunction);
-
- foreach (const QString *formal, irFunction->formals)
- if (formal)
- vmFunction->formals.append(_engine->newString(*formal));
- foreach (const QString *local, irFunction->locals)
- if (local)
- vmFunction->locals.append(_engine->newString(*local));
-
- foreach (V4IR::Function *function, irFunction->nestedFunctions)
- createFunctionMapping(vmFunction, function);
-
- return vmFunction;
-}
+ Function *rootFunction = irModule->rootFunction;
+ if (!rootFunction)
+ return 0;
+ foreach (V4IR::Function *f, irModule->functions)
+ run(f);
-QV4::Function *EvalInstructionSelection::vmFunction(Function *f) {
- QV4::Function *function = _irToVM[f];
- if (!function->code)
- run(function, f);
- return function;
+ return backendCompileStep();
}
void IRDecoder::visitMove(V4IR::Move *s)
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 947583a907..6f4b042a09 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -44,6 +44,8 @@
#include "private/qv4global_p.h"
#include "qv4jsir_p.h"
+#include <private/qv4compileddata_p.h>
+#include <private/qv4compiler_p.h>
#include <qglobal.h>
#include <QHash>
@@ -51,39 +53,36 @@
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct ExecutionEngine;
+class ExecutableAllocator;
struct Function;
}
namespace QQmlJS {
-class Q_QML_EXPORT EvalInstructionSelection
+class Q_QML_EXPORT EvalInstructionSelection : public QV4::Compiler::JSUnitGenerator
{
public:
- EvalInstructionSelection(QV4::ExecutionEngine *engine, V4IR::Module *module);
+ EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module);
virtual ~EvalInstructionSelection() = 0;
- QV4::Function *vmFunction(V4IR::Function *f);
+ QV4::CompiledData::CompilationUnit *compile();
void setUseFastLookups(bool b) { useFastLookups = b; }
protected:
- QV4::Function *createFunctionMapping(QV4::Function *outer, V4IR::Function *irFunction);
- QV4::ExecutionEngine *engine() const { return _engine; }
- virtual void run(QV4::Function *vmFunction, V4IR::Function *function) = 0;
+ virtual void run(V4IR::Function *function) = 0;
+ virtual QV4::CompiledData::CompilationUnit *backendCompileStep() = 0;
-private:
- QV4::ExecutionEngine *_engine;
- QHash<V4IR::Function *, QV4::Function *> _irToVM;
protected:
bool useFastLookups;
+ QV4::ExecutableAllocator *executableAllocator;
};
class Q_QML_EXPORT EvalISelFactory
{
public:
virtual ~EvalISelFactory() = 0;
- virtual EvalInstructionSelection *create(QV4::ExecutionEngine *engine, V4IR::Module *module) = 0;
+ virtual EvalInstructionSelection *create(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module) = 0;
virtual bool jitCompileRegexps() const = 0;
};
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index 23b299cbad..74445cc2c8 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -627,6 +627,15 @@ Module::~Module()
}
}
+void Module::setFileName(const QString &name)
+{
+ if (fileName.isEmpty())
+ fileName = name;
+ else {
+ Q_ASSERT(fileName == name);
+ }
+}
+
Function::~Function()
{
// destroy the Stmt::Data blocks manually, because memory pool cleanup won't
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 2d2e11ffda..14daff0fb6 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -672,11 +672,14 @@ struct Q_QML_EXPORT Module {
MemoryPool pool;
QVector<Function *> functions;
Function *rootFunction;
+ QString fileName;
Function *newFunction(const QString &name, Function *outer);
Module() : rootFunction(0) {}
~Module();
+
+ void setFileName(const QString &name);
};
struct Function {
@@ -692,8 +695,6 @@ struct Function {
QVector<Function *> nestedFunctions;
Function *outer;
- QString sourceFile;
-
int insideWithOrCatch;
uint hasDirectEval: 1;