aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp334
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h30
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp106
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h31
-rw-r--r--src/qml/compiler/qv4codegen.cpp34
-rw-r--r--src/qml/compiler/qv4codegen_p.h24
-rw-r--r--src/qml/compiler/qv4compileddata.cpp42
-rw-r--r--src/qml/compiler/qv4compileddata_p.h44
-rw-r--r--src/qml/compiler/qv4compiler.cpp16
-rw-r--r--src/qml/compiler/qv4compiler_p.h14
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp14
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h14
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp24
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h14
-rw-r--r--src/qml/compiler/qv4isel_p.cpp30
-rw-r--r--src/qml/compiler/qv4isel_p.h14
-rw-r--r--src/qml/compiler/qv4isel_util_p.h14
-rw-r--r--src/qml/compiler/qv4jsir.cpp66
-rw-r--r--src/qml/compiler/qv4jsir_p.h60
-rw-r--r--src/qml/compiler/qv4ssa.cpp471
-rw-r--r--src/qml/compiler/qv4ssa_p.h16
21 files changed, 629 insertions, 783 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 339278fbe8..c645a29b15 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the tools applications of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -216,60 +216,6 @@ static void replaceWithSpace(QString &str, int idx, int n)
*data++ = space;
}
-#define CHECK_LINE if (l.tokenStartLine() != startLine) return;
-#define CHECK_TOKEN(t) if (token != QQmlJSGrammar:: t) return;
-
-static const int uriTokens[] = {
- QQmlJSGrammar::T_IDENTIFIER,
- QQmlJSGrammar::T_PROPERTY,
- QQmlJSGrammar::T_SIGNAL,
- QQmlJSGrammar::T_READONLY,
- QQmlJSGrammar::T_ON,
- QQmlJSGrammar::T_BREAK,
- QQmlJSGrammar::T_CASE,
- QQmlJSGrammar::T_CATCH,
- QQmlJSGrammar::T_CONTINUE,
- QQmlJSGrammar::T_DEFAULT,
- QQmlJSGrammar::T_DELETE,
- QQmlJSGrammar::T_DO,
- QQmlJSGrammar::T_ELSE,
- QQmlJSGrammar::T_FALSE,
- QQmlJSGrammar::T_FINALLY,
- QQmlJSGrammar::T_FOR,
- QQmlJSGrammar::T_FUNCTION,
- QQmlJSGrammar::T_IF,
- QQmlJSGrammar::T_IN,
- QQmlJSGrammar::T_INSTANCEOF,
- QQmlJSGrammar::T_NEW,
- QQmlJSGrammar::T_NULL,
- QQmlJSGrammar::T_RETURN,
- QQmlJSGrammar::T_SWITCH,
- QQmlJSGrammar::T_THIS,
- QQmlJSGrammar::T_THROW,
- QQmlJSGrammar::T_TRUE,
- QQmlJSGrammar::T_TRY,
- QQmlJSGrammar::T_TYPEOF,
- QQmlJSGrammar::T_VAR,
- QQmlJSGrammar::T_VOID,
- QQmlJSGrammar::T_WHILE,
- QQmlJSGrammar::T_CONST,
- QQmlJSGrammar::T_DEBUGGER,
- QQmlJSGrammar::T_RESERVED_WORD,
- QQmlJSGrammar::T_WITH,
-
- QQmlJSGrammar::EOF_SYMBOL
-};
-static inline bool isUriToken(int token)
-{
- const int *current = uriTokens;
- while (*current != QQmlJSGrammar::EOF_SYMBOL) {
- if (*current == token)
- return true;
- ++current;
- }
- return false;
-}
-
void Document::collectTypeReferences()
{
foreach (Object *obj, objects) {
@@ -296,198 +242,6 @@ void Document::collectTypeReferences()
}
}
-void Document::extractScriptMetaData(QString &script, QQmlJS::DiagnosticMessage *error)
-{
- Q_ASSERT(error);
-
- const QString js(QLatin1String(".js"));
- const QString library(QLatin1String("library"));
-
- QQmlJS::MemoryPool *pool = jsParserEngine.pool();
-
- QQmlJS::Lexer l(0);
- l.setCode(script, 0);
-
- int token = l.lex();
-
- while (true) {
- if (token != QQmlJSGrammar::T_DOT)
- return;
-
- int startOffset = l.tokenOffset();
- int startLine = l.tokenStartLine();
- int startColumn = l.tokenStartColumn();
-
- error->loc.startLine = startLine + 1; // 0-based, adjust to be 1-based
-
- token = l.lex();
-
- CHECK_LINE;
-
- if (token == QQmlJSGrammar::T_IMPORT) {
-
- // .import <URI> <Version> as <Identifier>
- // .import <file.js> as <Identifier>
-
- token = l.lex();
-
- CHECK_LINE;
- QV4::CompiledData::Import *import = pool->New<QV4::CompiledData::Import>();
-
- if (token == QQmlJSGrammar::T_STRING_LITERAL) {
-
- QString file = l.tokenText();
-
- if (!file.endsWith(js)) {
- error->message = QCoreApplication::translate("QQmlParser","Imported file must be a script");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- bool invalidImport = false;
-
- token = l.lex();
-
- if ((token != QQmlJSGrammar::T_AS) || (l.tokenStartLine() != startLine)) {
- invalidImport = true;
- } else {
- token = l.lex();
-
- if ((token != QQmlJSGrammar::T_IDENTIFIER) || (l.tokenStartLine() != startLine))
- invalidImport = true;
- }
-
-
- if (invalidImport) {
- error->message = QCoreApplication::translate("QQmlParser","File import requires a qualifier");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- int endOffset = l.tokenLength() + l.tokenOffset();
-
- QString importId = script.mid(l.tokenOffset(), l.tokenLength());
-
- token = l.lex();
-
- if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) {
- error->message = QCoreApplication::translate("QQmlParser","Invalid import qualifier");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- replaceWithSpace(script, startOffset, endOffset - startOffset);
-
- import->type = QV4::CompiledData::Import::ImportScript;
- import->uriIndex = registerString(file);
- import->qualifierIndex = registerString(importId);
- import->location.line = startLine;
- import->location.column = startColumn;
- imports << import;
- } else {
- // URI
- QString uri;
-
- while (true) {
- if (!isUriToken(token)) {
- error->message = QCoreApplication::translate("QQmlParser","Invalid module URI");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- uri.append(l.tokenText());
-
- token = l.lex();
- CHECK_LINE;
- if (token != QQmlJSGrammar::T_DOT)
- break;
-
- uri.append(QLatin1Char('.'));
-
- token = l.lex();
- CHECK_LINE;
- }
-
- if (token != QQmlJSGrammar::T_NUMERIC_LITERAL) {
- error->message = QCoreApplication::translate("QQmlParser","Module import requires a version");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- int vmaj, vmin;
- IRBuilder::extractVersion(QStringRef(&script, l.tokenOffset(), l.tokenLength()),
- &vmaj, &vmin);
-
- bool invalidImport = false;
-
- token = l.lex();
-
- if ((token != QQmlJSGrammar::T_AS) || (l.tokenStartLine() != startLine)) {
- invalidImport = true;
- } else {
- token = l.lex();
-
- if ((token != QQmlJSGrammar::T_IDENTIFIER) || (l.tokenStartLine() != startLine))
- invalidImport = true;
- }
-
-
- if (invalidImport) {
- error->message = QCoreApplication::translate("QQmlParser","Module import requires a qualifier");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- int endOffset = l.tokenLength() + l.tokenOffset();
-
- QString importId = script.mid(l.tokenOffset(), l.tokenLength());
-
- token = l.lex();
-
- if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) {
- error->message = QCoreApplication::translate("QQmlParser","Invalid import qualifier");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- replaceWithSpace(script, startOffset, endOffset - startOffset);
-
- import->type = QV4::CompiledData::Import::ImportLibrary;
- import->uriIndex = registerString(uri);
- import->majorVersion = vmaj;
- import->minorVersion = vmin;
- import->qualifierIndex = registerString(importId);
- import->location.line = startLine;
- import->location.column = startColumn;
- imports << import;
- }
- } else if (token == QQmlJSGrammar::T_PRAGMA) {
- token = l.lex();
-
- CHECK_TOKEN(T_IDENTIFIER);
- CHECK_LINE;
-
- QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength());
- int endOffset = l.tokenLength() + l.tokenOffset();
-
- if (pragmaValue == library) {
- unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary;
- replaceWithSpace(script, startOffset, endOffset - startOffset);
- } else {
- return;
- }
-
- token = l.lex();
- if (l.tokenStartLine() == startLine)
- return;
-
- } else {
- return;
- }
- }
- return;
-}
-
void Document::removeScriptPragmas(QString &script)
{
const QString pragma(QLatin1String("pragma"));
@@ -536,11 +290,51 @@ void Document::removeScriptPragmas(QString &script)
Document::Document(bool debugMode)
: jsModule(debugMode)
, program(0)
+ , indexOfRootObject(0)
, jsGenerator(&jsModule)
, unitFlags(0)
{
}
+ScriptDirectivesCollector::ScriptDirectivesCollector(QQmlJS::Engine *engine, QV4::Compiler::JSUnitGenerator *unitGenerator)
+ : engine(engine)
+ , jsGenerator(unitGenerator)
+ , hasPragmaLibrary(false)
+{
+}
+
+void ScriptDirectivesCollector::pragmaLibrary()
+{
+ hasPragmaLibrary = true;
+}
+
+void ScriptDirectivesCollector::importFile(const QString &jsfile, const QString &module, int lineNumber, int column)
+{
+ QV4::CompiledData::Import *import = engine->pool()->New<QV4::CompiledData::Import>();
+ import->type = QV4::CompiledData::Import::ImportScript;
+ import->uriIndex = jsGenerator->registerString(jsfile);
+ import->qualifierIndex = jsGenerator->registerString(module);
+ import->location.line = lineNumber;
+ import->location.column = column;
+ imports << import;
+}
+
+void ScriptDirectivesCollector::importModule(const QString &uri, const QString &version, const QString &module, int lineNumber, int column)
+{
+ QV4::CompiledData::Import *import = engine->pool()->New<QV4::CompiledData::Import>();
+ import->type = QV4::CompiledData::Import::ImportLibrary;
+ import->uriIndex = jsGenerator->registerString(uri);
+ int vmaj;
+ int vmin;
+ IRBuilder::extractVersion(QStringRef(&version), &vmaj, &vmin);
+ import->majorVersion = vmaj;
+ import->minorVersion = vmin;
+ import->qualifierIndex = jsGenerator->registerString(module);
+ import->location.line = lineNumber;
+ import->location.column = column;
+ imports << import;
+}
+
IRBuilder::IRBuilder(const QSet<QString> &illegalNames)
: illegalNames(illegalNames)
, _object(0)
@@ -1780,8 +1574,6 @@ QQmlPropertyData *JSCodeGen::lookupQmlCompliantProperty(QQmlPropertyCache *cache
return pd;
}
-static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject);
-
enum MetaObjectResolverFlags {
AllPropertiesAreFinal = 0x1,
LookupsIncludeEnums = 0x2,
@@ -1837,6 +1629,8 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe
static void initQmlTypeResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlType *qmlType)
{
+ Q_ASSERT(resolver);
+
resolver->resolveMember = &resolveQmlType;
resolver->data = qmlType;
resolver->extraData = 0;
@@ -1941,8 +1735,8 @@ static QV4::IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, QV4
initMetaObjectResolver(resolver, cache);
return QV4::IR::QObjectType;
}
- } else if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(property->propType)) {
- if (QQmlPropertyCache *cache = qmlEngine->cache(valueType->metaObject())) {
+ } else if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType)) {
+ if (QQmlPropertyCache *cache = qmlEngine->cache(valueTypeMetaObject)) {
initMetaObjectResolver(resolver, cache);
resolver->flags |= ResolveTypeInformationOnly;
return QV4::IR::QObjectType;
@@ -1958,10 +1752,11 @@ static QV4::IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, QV4
static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject)
{
+ Q_ASSERT(resolver);
+
resolver->resolveMember = &resolveMetaObjectProperty;
resolver->data = metaObject;
resolver->flags = 0;
- resolver->isQObjectResolver = true;
}
#endif // V4_BOOTSTRAP
@@ -1975,11 +1770,13 @@ void JSCodeGen::beginFunctionBodyHook()
#ifndef V4_BOOTSTRAP
QV4::IR::Temp *temp = _block->TEMP(_contextObjectTemp);
- initMetaObjectResolver(&temp->memberResolver, _contextObject);
+ temp->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initMetaObjectResolver(temp->memberResolver, _contextObject);
move(temp, _block->NAME(QV4::IR::Name::builtin_qml_context_object, 0, 0));
temp = _block->TEMP(_scopeObjectTemp);
- initMetaObjectResolver(&temp->memberResolver, _scopeObject);
+ temp->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initMetaObjectResolver(temp->memberResolver, _scopeObject);
move(temp, _block->NAME(QV4::IR::Name::builtin_qml_scope_object, 0, 0));
move(_block->TEMP(_importedScriptsTemp), _block->NAME(QV4::IR::Name::builtin_qml_imported_scripts_object, 0, 0));
@@ -2014,8 +1811,9 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
_block->MOVE(result, s);
result = _block->TEMP(result->index);
if (mapping.type) {
- initMetaObjectResolver(&result->memberResolver, mapping.type);
- result->memberResolver.flags |= AllPropertiesAreFinal;
+ result->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initMetaObjectResolver(result->memberResolver, mapping.type);
+ result->memberResolver->flags |= AllPropertiesAreFinal;
}
result->isReadOnly = true; // don't allow use as lvalue
return result;
@@ -2035,14 +1833,16 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
_block->MOVE(result, typeName);
result = _block->TEMP(result->index);
- initQmlTypeResolver(&result->memberResolver, r.type);
+ result->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initQmlTypeResolver(result->memberResolver, r.type);
return result;
} else {
Q_ASSERT(r.importNamespace);
QV4::IR::Name *namespaceName = _block->NAME(name, line, col);
namespaceName->freeOfSideEffects = true;
QV4::IR::Temp *result = _block->TEMP(_block->newTemp());
- initImportNamespaceResolver(&result->memberResolver, imports, r.importNamespace);
+ result->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initImportNamespaceResolver(result->memberResolver, imports, r.importNamespace);
_block->MOVE(result, namespaceName);
return _block->TEMP(result->index);
@@ -2057,7 +1857,8 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
return 0;
if (pd) {
QV4::IR::Temp *base = _block->TEMP(_scopeObjectTemp);
- initMetaObjectResolver(&base->memberResolver, _scopeObject);
+ base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initMetaObjectResolver(base->memberResolver, _scopeObject);
return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlScopeObject);
}
}
@@ -2069,7 +1870,8 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
return 0;
if (pd) {
QV4::IR::Temp *base = _block->TEMP(_contextObjectTemp);
- initMetaObjectResolver(&base->memberResolver, _contextObject);
+ base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initMetaObjectResolver(base->memberResolver, _contextObject);
return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlContextObject);
}
}
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index cc22023f8e..120de91321 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the tools applications of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -41,6 +41,7 @@
#include <private/qqmljsmemorypool_p.h>
#include <private/qv4codegen_p.h>
#include <private/qv4compiler_p.h>
+#include <private/qqmljslexer_p.h>
#include <QTextStream>
#include <QCoreApplication>
@@ -326,10 +327,23 @@ struct Q_QML_PRIVATE_EXPORT Document
int registerString(const QString &str) { return jsGenerator.registerString(str); }
QString stringAt(int index) const { return jsGenerator.stringForIndex(index); }
- void extractScriptMetaData(QString &script, QQmlJS::DiagnosticMessage *error);
static void removeScriptPragmas(QString &script);
};
+struct Q_QML_PRIVATE_EXPORT ScriptDirectivesCollector : public QQmlJS::Directives
+{
+ ScriptDirectivesCollector(QQmlJS::Engine *engine, QV4::Compiler::JSUnitGenerator *unitGenerator);
+
+ QQmlJS::Engine *engine;
+ QV4::Compiler::JSUnitGenerator *jsGenerator;
+ QList<const QV4::CompiledData::Import *> imports;
+ bool hasPragmaLibrary;
+
+ virtual void pragmaLibrary();
+ virtual void importFile(const QString &jsfile, const QString &module, int lineNumber, int column);
+ virtual void importModule(const QString &uri, const QString &version, const QString &module, int lineNumber, int column);
+};
+
struct Q_QML_PRIVATE_EXPORT IRBuilder : public QQmlJS::AST::Visitor
{
Q_DECLARE_TR_FUNCTIONS(QQmlCodeGenerator)
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 2c7414db14..21846775a3 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the tools applications of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -392,6 +392,11 @@ void QQmlTypeCompiler::setDeferredBindingsPerObject(const QHash<int, QBitArray>
compiledData->deferredBindingsPerObject = deferredBindingsPerObject;
}
+void QQmlTypeCompiler::setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData)
+{
+ compiledData->compilationUnit->bindingPropertyDataPerObject = propertyData;
+}
+
QString QQmlTypeCompiler::bindingAsString(const QmlIR::Object *object, int scriptIndex) const
{
return object->bindingAsString(document, scriptIndex);
@@ -402,7 +407,7 @@ QQmlCompilePass::QQmlCompilePass(QQmlTypeCompiler *typeCompiler)
{
}
-void QQmlCompilePass::recordError(const QV4::CompiledData::Location &location, const QString &description)
+void QQmlCompilePass::recordError(const QV4::CompiledData::Location &location, const QString &description) const
{
QQmlError error;
error.setLine(location.line);
@@ -463,8 +468,8 @@ bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int r
if (instantiatingProperty->isQObject()) {
baseTypeCache = enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType);
Q_ASSERT(baseTypeCache);
- } else if (QQmlValueType *vt = QQmlValueTypeFactory::valueType(instantiatingProperty->propType)) {
- baseTypeCache = enginePrivate->cache(vt->metaObject());
+ } else if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(instantiatingProperty->propType)) {
+ baseTypeCache = enginePrivate->cache(vtmo);
Q_ASSERT(baseTypeCache);
}
}
@@ -559,8 +564,7 @@ bool QQmlPropertyCacheCreator::ensureMetaObject(int objectIndex)
bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Object *obj, QQmlPropertyCache *baseTypeCache)
{
- QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(QQmlEnginePrivate::get(enginePrivate),
- obj->propertyCount(),
+ QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(obj->propertyCount(),
obj->functionCount() + obj->propertyCount() + obj->signalCount(),
obj->signalCount() + obj->propertyCount());
propertyCaches[objectIndex] = cache;
@@ -1630,8 +1634,8 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
notifySignal = targetProperty->notifyIndex;
if (!subProperty.isEmpty()) {
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type);
- if (!valueType) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(type);
+ if (!valueTypeMetaObject) {
recordError(p->aliasLocation, tr("Invalid alias location"));
return false;
}
@@ -1639,18 +1643,18 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
propType = type;
int valueTypeIndex =
- valueType->metaObject()->indexOfProperty(subProperty.toString().toUtf8().constData());
+ valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData());
if (valueTypeIndex == -1) {
recordError(p->aliasLocation, tr("Invalid alias location"));
return false;
}
Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
- propIdx |= (valueTypeIndex << 16);
- if (valueType->metaObject()->property(valueTypeIndex).isEnumType())
+ propIdx = QQmlPropertyData::encodeValueTypePropertyIndex(propIdx, valueTypeIndex);
+ if (valueTypeMetaObject->property(valueTypeIndex).isEnumType())
type = QVariant::Int;
else
- type = valueType->metaObject()->property(valueTypeIndex).userType();
+ type = valueTypeMetaObject->property(valueTypeIndex).userType();
} else {
if (targetProperty->isEnum()) {
@@ -1713,9 +1717,11 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler)
bool QQmlPropertyValidator::validate()
{
+ _bindingPropertyDataPerObject.resize(qmlUnit->nObjects);
if (!validateObject(qmlUnit->indexOfRootObject, /*instantiatingBinding*/0))
return false;
- compiler->setDeferredBindingsPerObject(deferredBindingsPerObject);
+ compiler->setDeferredBindingsPerObject(_deferredBindingsPerObject);
+ compiler->setBindingPropertyDataPerObject(_bindingPropertyDataPerObject);
return true;
}
@@ -1753,7 +1759,7 @@ struct BindingFinder
}
};
-bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty)
+bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty) const
{
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
if (obj->idIndex != 0)
@@ -1819,6 +1825,8 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
defaultProperty = propertyCache->defaultProperty();
}
+ QV4::CompiledData::BindingPropertyData collectedBindingPropertyData(obj->nBindings);
+
binding = obj->bindingTable();
for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
QString name = stringAt(binding->propertyNameIndex);
@@ -1838,22 +1846,6 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
}
- // Signal handlers were resolved and checked earlier in the signal handler conversion pass.
- if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
- || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
- continue;
-
- if (name.constData()->isUpper() && !binding->isAttachedProperty()) {
- QQmlType *type = 0;
- QQmlImportNamespace *typeNamespace = 0;
- compiler->imports()->resolveType(stringAt(binding->propertyNameIndex), &type, 0, 0, &typeNamespace);
- if (typeNamespace)
- recordError(binding->location, tr("Invalid use of namespace"));
- else
- recordError(binding->location, tr("Invalid attached object assignment"));
- return false;
- }
-
bool bindingToDefaultProperty = false;
bool notInRevision = false;
@@ -1883,11 +1875,25 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
bindingToDefaultProperty = true;
}
+ if (pd)
+ collectedBindingPropertyData[i] = pd;
+
+ if (name.constData()->isUpper() && !binding->isAttachedProperty()) {
+ QQmlType *type = 0;
+ QQmlImportNamespace *typeNamespace = 0;
+ compiler->imports()->resolveType(stringAt(binding->propertyNameIndex), &type, 0, 0, &typeNamespace);
+ if (typeNamespace)
+ recordError(binding->location, tr("Invalid use of namespace"));
+ else
+ recordError(binding->location, tr("Invalid attached object assignment"));
+ return false;
+ }
+
bool seenSubObjectWithId = false;
- if (binding->type >= QV4::CompiledData::Binding::Type_Object && !customParser) {
+ if (binding->type >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty())) {
qSwap(_seenObjectWithId, seenSubObjectWithId);
- const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::valueType(pd->propType));
+ const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType));
qSwap(_seenObjectWithId, seenSubObjectWithId);
if (!subObjectValid)
return false;
@@ -1903,6 +1909,11 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
deferredBindings.setBit(i);
}
+ // Signal handlers were resolved and checked earlier in the signal handler conversion pass.
+ if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
+ || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ continue;
+
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
if (instantiatingBinding && (instantiatingBinding->isAttachedProperty() || instantiatingBinding->isGroupProperty())) {
recordError(binding->location, tr("Attached properties cannot be used here"));
@@ -1961,7 +1972,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
return false;
} else if (binding->isGroupProperty()) {
if (QQmlValueTypeFactory::isValueType(pd->propType)) {
- if (QQmlValueTypeFactory::valueType(pd->propType)) {
+ if (QQmlValueTypeFactory::metaObjectForMetaType(pd->propType)) {
if (!pd->isWritable()) {
recordError(binding->location, tr("Invalid property assignment: \"%1\" is a read-only property").arg(name));
return false;
@@ -1991,6 +2002,11 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
}
+ if (obj->idIndex) {
+ bool notInRevision = false;
+ collectedBindingPropertyData << propertyResolver.property(QStringLiteral("id"), &notInRevision);
+ }
+
if (customParser && !customBindings.isEmpty()) {
customParser->clearErrors();
customParser->compiler = this;
@@ -2008,12 +2024,14 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
if (!deferredBindings.isEmpty())
- deferredBindingsPerObject.insert(objectIndex, deferredBindings);
+ _deferredBindingsPerObject.insert(objectIndex, deferredBindings);
+
+ _bindingPropertyDataPerObject[objectIndex] = collectedBindingPropertyData;
return true;
}
-bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
+bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const
{
if (property->isQList()) {
recordError(binding->valueLocation, tr("Cannot assign primitives to lists"));
@@ -2289,7 +2307,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
Returns true if from can be assigned to a (QObject) property of type
to.
*/
-bool QQmlPropertyValidator::canCoerce(int to, QQmlPropertyCache *fromMo)
+bool QQmlPropertyValidator::canCoerce(int to, QQmlPropertyCache *fromMo) const
{
QQmlPropertyCache *toMo = enginePrivate->rawPropertyCacheForType(to);
@@ -2301,7 +2319,7 @@ bool QQmlPropertyValidator::canCoerce(int to, QQmlPropertyCache *fromMo)
return false;
}
-bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding)
+bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const
{
if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Object);
@@ -2347,7 +2365,7 @@ bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, co
if (!QQmlMetaType::isInterface(listType)) {
QQmlPropertyCache *source = propertyCaches.at(binding->value.objectIndex);
if (!canCoerce(listType, source)) {
- recordError(binding->valueLocation, tr("Cannot assign object to list"));
+ recordError(binding->valueLocation, tr("Cannot assign object to list property \"%1\"").arg(propertyName));
return false;
}
}
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index eec717788f..75987af656 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the tools applications of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -93,6 +93,7 @@ public:
QStringRef newStringRef(const QString &string);
const QV4::Compiler::StringTableGenerator *stringPool() const;
void setDeferredBindingsPerObject(const QHash<int, QBitArray> &deferredBindingsPerObject);
+ void setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData);
const QHash<int, QQmlCustomParser*> &customParserCache() const { return customParsers; }
@@ -116,7 +117,7 @@ struct QQmlCompilePass
QString stringAt(int idx) const { return compiler->stringAt(idx); }
protected:
- void recordError(const QV4::CompiledData::Location &location, const QString &description);
+ void recordError(const QV4::CompiledData::Location &location, const QString &description) const;
QQmlTypeCompiler *compiler;
};
@@ -276,13 +277,13 @@ public:
virtual QString bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const;
private:
- bool validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false);
- bool validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
- bool validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding);
+ bool validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false) const;
+ bool validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const;
+ bool validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const;
bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
- bool canCoerce(int to, QQmlPropertyCache *fromMo);
+ bool canCoerce(int to, QQmlPropertyCache *fromMo) const;
QQmlEnginePrivate *enginePrivate;
const QV4::CompiledData::Unit *qmlUnit;
@@ -291,9 +292,11 @@ private:
const QVector<QQmlPropertyCache *> &propertyCaches;
const QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
QHash<int, QBitArray> *customParserBindingsPerObject;
- QHash<int, QBitArray> deferredBindingsPerObject;
- bool _seenObjectWithId;
+ // collected state variables, essentially write-only
+ mutable QHash<int, QBitArray> _deferredBindingsPerObject;
+ mutable bool _seenObjectWithId;
+ mutable QVector<QV4::CompiledData::BindingPropertyData> _bindingPropertyDataPerObject;
};
// ### merge with QtQml::JSCodeGen and operate directly on object->functionsAndExpressions once old compiler is gone.
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 260db0f0dd..9168889c8c 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -1965,7 +1965,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
// variables in global code are properties of the global context object, not locals as with other functions.
if (_env->compilationMode == FunctionCode || _env->compilationMode == QmlBinding) {
unsigned t = 0;
- for (Environment::MemberMap::iterator it = _env->members.begin(); it != _env->members.end(); ++it) {
+ for (Environment::MemberMap::iterator it = _env->members.begin(), end = _env->members.end(); it != end; ++it) {
const QString &local = it.key();
function->LOCAL(local);
(*it).index = t;
@@ -1984,7 +1984,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
}
IR::ExprList *args = 0;
- for (Environment::MemberMap::const_iterator it = _env->members.constBegin(); it != _env->members.constEnd(); ++it) {
+ for (Environment::MemberMap::const_iterator it = _env->members.constBegin(), cend = _env->members.constEnd(); it != cend; ++it) {
const QString &local = it.key();
IR::ExprList *next = function->New<IR::ExprList>();
next->expr = entryBlock->NAME(local, 0, 0);
@@ -2448,7 +2448,8 @@ bool Codegen::visit(SwitchStatement *ast)
IR::BasicBlock *switchend = _function->newBasicBlock(exceptionHandler());
if (ast->block) {
- Result lhs = expression(ast->expression);
+ int lhs = _block->newTemp();
+ move(_block->TEMP(lhs), *expression(ast->expression));
IR::BasicBlock *switchcond = _function->newBasicBlock(exceptionHandler());
_block->JUMP(switchcond);
IR::BasicBlock *previousBlock = 0;
@@ -2510,7 +2511,7 @@ bool Codegen::visit(SwitchStatement *ast)
Result rhs = expression(clause->expression);
IR::BasicBlock *iftrue = blockMap[clause];
IR::BasicBlock *iffalse = _function->newBasicBlock(exceptionHandler());
- setLocation(cjump(binop(IR::OpStrictEqual, *lhs, *rhs), iftrue, iffalse), clause->caseToken);
+ setLocation(cjump(binop(IR::OpStrictEqual, _block->TEMP(lhs), *rhs), iftrue, iffalse), clause->caseToken);
_block = iffalse;
}
@@ -2519,7 +2520,7 @@ bool Codegen::visit(SwitchStatement *ast)
Result rhs = expression(clause->expression);
IR::BasicBlock *iftrue = blockMap[clause];
IR::BasicBlock *iffalse = _function->newBasicBlock(exceptionHandler());
- setLocation(cjump(binop(IR::OpStrictEqual, *lhs, *rhs), iftrue, iffalse), clause->caseToken);
+ setLocation(cjump(binop(IR::OpStrictEqual, _block->TEMP(lhs), *rhs), iftrue, iffalse), clause->caseToken);
_block = iffalse;
}
@@ -2841,6 +2842,11 @@ QList<QQmlJS::DiagnosticMessage> Codegen::errors() const
QList<QQmlError> Codegen::qmlErrors() const
{
QList<QQmlError> qmlErrors;
+
+ // Short circuit to avoid costly (de)heap allocation of QUrl if there are no errors.
+ if (_errors.size() == 0)
+ return qmlErrors;
+
qmlErrors.reserve(_errors.size());
QUrl url(_fileNameIsUrl ? QUrl(_module->fileName) : QUrl::fromLocalFile(_module->fileName));
@@ -2861,7 +2867,7 @@ void RuntimeCodegen::throwSyntaxError(const AST::SourceLocation &loc, const QStr
if (hasError)
return;
hasError = true;
- context->throwSyntaxError(detail, _module->fileName, loc.startLine, loc.startColumn);
+ engine->throwSyntaxError(detail, _module->fileName, loc.startLine, loc.startColumn);
}
void RuntimeCodegen::throwReferenceError(const AST::SourceLocation &loc, const QString &detail)
@@ -2869,7 +2875,7 @@ void RuntimeCodegen::throwReferenceError(const AST::SourceLocation &loc, const Q
if (hasError)
return;
hasError = true;
- context->throwReferenceError(detail, _module->fileName, loc.startLine, loc.startColumn);
+ engine->throwReferenceError(detail, _module->fileName, loc.startLine, loc.startColumn);
}
#endif // V4_BOOTSTRAP
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 323cd27aa9..aec51cc19c 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -47,10 +47,6 @@
QT_BEGIN_NAMESPACE
-namespace QV4 {
-struct ExecutionContext;
-}
-
namespace QQmlJS {
namespace AST {
class UiParameterList;
@@ -526,15 +522,15 @@ protected:
class RuntimeCodegen : public Codegen
{
public:
- RuntimeCodegen(QV4::ExecutionContext *ctx, bool strict)
+ RuntimeCodegen(QV4::ExecutionEngine *engine, bool strict)
: Codegen(strict)
- , context(ctx)
+ , engine(engine)
{}
virtual void throwSyntaxError(const AST::SourceLocation &loc, const QString &detail);
virtual void throwReferenceError(const AST::SourceLocation &loc, const QString &detail);
private:
- QV4::ExecutionContext *context;
+ QV4::ExecutionEngine *engine;
};
#endif // V4_BOOTSTRAP
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index d242fb7b3a..5d954eb4fc 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -40,6 +40,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4lookup_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qqmlpropertycache_p.h>
#endif
#include <private/qqmlirbuilder_p.h>
#include <QCoreApplication>
@@ -53,6 +54,15 @@ namespace QV4 {
namespace CompiledData {
#ifndef V4_BOOTSTRAP
+CompilationUnit::CompilationUnit()
+ : data(0)
+ , engine(0)
+ , runtimeStrings(0)
+ , runtimeLookups(0)
+ , runtimeRegularExpressions(0)
+ , runtimeClasses(0)
+{}
+
CompilationUnit::~CompilationUnit()
{
unlink();
@@ -65,9 +75,9 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
Q_ASSERT(!runtimeStrings);
Q_ASSERT(data);
- runtimeStrings = (QV4::StringValue *)malloc(data->stringTableSize * sizeof(QV4::StringValue));
+ runtimeStrings = (QV4::Heap::String **)malloc(data->stringTableSize * sizeof(QV4::Heap::String*));
// memset the strings to 0 in case a GC run happens while we're within the loop below
- memset(runtimeStrings, 0, data->stringTableSize * sizeof(QV4::StringValue));
+ memset(runtimeStrings, 0, data->stringTableSize * sizeof(QV4::Heap::String*));
for (uint i = 0; i < data->stringTableSize; ++i)
runtimeStrings[i] = engine->newIdentifier(data->stringAt(i));
@@ -109,7 +119,7 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
l->classList[j] = 0;
l->level = -1;
l->index = UINT_MAX;
- l->name = runtimeStrings[compiledLookups[i].nameIndex].asString();
+ l->nameIndex = compiledLookups[i].nameIndex;
if (type == CompiledData::Lookup::Type_IndexedGetter || type == CompiledData::Lookup::Type_IndexedSetter)
l->engine = engine;
}
@@ -117,13 +127,12 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
if (data->jsClassTableSize) {
runtimeClasses = (QV4::InternalClass**)malloc(data->jsClassTableSize * sizeof(QV4::InternalClass*));
-
for (uint i = 0; i < data->jsClassTableSize; ++i) {
int memberCount = 0;
const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount);
- QV4::InternalClass *klass = engine->objectClass;
+ QV4::InternalClass *klass = engine->emptyClass;
for (int j = 0; j < memberCount; ++j, ++member)
- klass = klass->addMember(runtimeStrings[member->nameOffset].asString(), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data);
+ klass = klass->addMember(runtimeStrings[member->nameOffset]->identifier, member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data);
runtimeClasses[i] = klass;
}
@@ -166,15 +175,12 @@ void CompilationUnit::unlink()
void CompilationUnit::markObjects(QV4::ExecutionEngine *e)
{
for (uint i = 0; i < data->stringTableSize; ++i)
- runtimeStrings[i].mark(e);
+ if (runtimeStrings[i])
+ runtimeStrings[i]->mark(e);
if (runtimeRegularExpressions) {
for (uint i = 0; i < data->regexpTableSize; ++i)
runtimeRegularExpressions[i].mark(e);
}
- if (runtimeLookups) {
- for (uint i = 0; i < data->lookupTableSize; ++i)
- runtimeLookups[i].name->mark(e);
- }
}
#endif // V4_BOOTSTRAP
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 6791970461..48324fbbc4 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -37,12 +37,18 @@
#include <QVector>
#include <QStringList>
#include <QHash>
+#include <QUrl>
+
#include <private/qv4value_p.h>
#include <private/qv4executableallocator_p.h>
#include <private/qqmlrefcount_p.h>
+#include <private/qqmlnullablevalue_p.h>
QT_BEGIN_NAMESPACE
+class QQmlPropertyCache;
+class QQmlPropertyData;
+
namespace QmlIR {
struct Document;
}
@@ -53,7 +59,6 @@ struct Function;
}
struct Function;
-struct ExecutionContext;
namespace CompiledData {
@@ -130,7 +135,7 @@ struct String
// uint16 strdata[]
static int calculateSize(const QString &str) {
- return (sizeof(String) + (str.length() + 1) * sizeof(quint16) + 7) & ~0x7;
+ return (sizeof(String) + str.length() * sizeof(quint16) + 7) & ~0x7;
}
};
@@ -554,6 +559,9 @@ struct TypeReferenceMap : QHash<int, TypeReference>
}
};
+// index is per-object binding index
+typedef QVector<QQmlPropertyData*> BindingPropertyData;
+
// This is how this hooks into the existing structures:
//VM::Function
@@ -568,14 +576,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
{}
virtual ~CompilationUnit() {}
#else
- CompilationUnit()
- : data(0)
- , engine(0)
- , runtimeStrings(0)
- , runtimeLookups(0)
- , runtimeRegularExpressions(0)
- , runtimeClasses(0)
- {}
+ CompilationUnit();
virtual ~CompilationUnit();
#endif
@@ -587,12 +588,19 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
#ifndef V4_BOOTSTRAP
ExecutionEngine *engine;
QString fileName() const { return data->stringAt(data->sourceFileIndex); }
+ QUrl url() const { if (m_url.isNull) m_url = QUrl(fileName()); return m_url; }
- QV4::StringValue *runtimeStrings; // Array
+ QV4::Heap::String **runtimeStrings; // Array
QV4::Lookup *runtimeLookups;
QV4::Value *runtimeRegularExpressions;
QV4::InternalClass **runtimeClasses;
QVector<QV4::Function *> runtimeFunctions;
+ mutable QQmlNullableValue<QUrl> m_url;
+
+ // index is object index. This allows fast access to the
+ // property data when initializing bindings, avoiding expensive
+ // lookups by string (property name).
+ QVector<BindingPropertyData> bindingPropertyDataPerObject;
QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
void unlink();
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 22107c4bd1..450889c275 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -78,7 +78,7 @@ void QV4::Compiler::StringTableGenerator::serialize(CompiledData::Unit *unit)
QV4::CompiledData::String *s = (QV4::CompiledData::String*)(stringData);
s->flags = 0; // ###
s->size = qstr.length();
- memcpy(s + 1, qstr.constData(), (qstr.length() + 1)*sizeof(ushort));
+ memcpy(s + 1, qstr.constData(), qstr.length()*sizeof(ushort));
stringData += QV4::CompiledData::String::calculateSize(qstr);
}
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 7b349caaf8..3cf80a9791 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index c9a0e65b82..5d6f1a8c7f 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index e28d94b008..5c2ad45da2 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 39977375c4..eb78a0c054 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -188,15 +188,9 @@ public:
void forFunction(IR::Function *function)
{
- IR::Optimizer::showMeTheCode(function);
+ IR::Optimizer::showMeTheCode(function, "Before stack slot allocation");
_function = function;
toStackSlots(function);
-
-// QTextStream os(stdout, QIODevice::WriteOnly);
-// os << "Frame layout:" << endl;
-// foreach (int t, _stackSlotForTemp.keys()) {
-// os << "\t" << t << " -> " << _stackSlotForTemp[t] << endl;
-// }
}
protected:
@@ -364,7 +358,7 @@ void InstructionSelection::run(int functionIndex)
opt.convertOutOfSSA();
ConvertTemps().toStackSlots(_function);
}
- opt.showMeTheCode(_function);
+ opt.showMeTheCode(_function, "After stack slot allocation");
} else {
ConvertTemps().toStackSlots(_function);
}
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index 89f575c633..4ea0f1d07f 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 4bb866616d..54b184b4eb 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,14 +23,16 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
+#include <QtCore/QDebug>
+#include <QtCore/QBuffer>
#include "qv4jsir_p.h"
#include "qv4isel_p.h"
#include "qv4isel_util_p.h"
@@ -41,11 +43,6 @@
#include <QString>
-namespace {
-Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
-#define qout *qout()
-} // anonymous namespace
-
using namespace QV4;
using namespace QV4::IR;
@@ -218,8 +215,12 @@ void IRDecoder::visitMove(IR::Move *s)
// For anything else...:
Q_UNIMPLEMENTED();
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinter(&qout).print(s);
qout << endl;
+ qDebug("%s", buf.data().constData());
Q_ASSERT(!"TODO");
}
@@ -398,7 +399,10 @@ void IRDecoder::callBuiltin(IR::Call *call, Expr *result)
}
Q_UNIMPLEMENTED();
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinter(&qout).print(call); qout << endl;
- Q_ASSERT(!"TODO!");
+ qDebug("%s", buf.data().constData());
Q_UNREACHABLE();
}
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 504d255eaf..1e273df93e 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
diff --git a/src/qml/compiler/qv4isel_util_p.h b/src/qml/compiler/qv4isel_util_p.h
index e96ed3caa6..521c345228 100644
--- a/src/qml/compiler/qv4isel_util_p.h
+++ b/src/qml/compiler/qv4isel_util_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index e23ca1d516..5c9cc98ade 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -44,6 +44,8 @@
#include <QtCore/qset.h>
#include <cmath>
+#include <vector>
+
#ifdef CONST
#undef CONST
#endif
@@ -152,7 +154,7 @@ AluOp binaryOperator(int op)
struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor
{
CloneExpr clone;
- QSet<Expr *> subexpressions; // contains all the non-cloned subexpressions in the given function
+ std::vector<Expr *> subexpressions; // contains all the non-cloned subexpressions in the given function. sorted using std::lower_bound.
Expr *uniqueExpr;
RemoveSharedExpressions(): uniqueExpr(0) {}
@@ -176,18 +178,19 @@ struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor
template <typename _Expr>
_Expr *cleanup(_Expr *expr)
{
- if (subexpressions.contains(expr)) {
- // the cloned expression is unique by definition
- // so we don't need to add it to `subexpressions'.
- return clone(expr);
+ std::vector<Expr *>::iterator it = std::lower_bound(subexpressions.begin(), subexpressions.end(), expr);
+ if (it == subexpressions.end() || *it != expr) {
+ subexpressions.insert(it, expr);
+ IR::Expr *e = expr;
+ qSwap(uniqueExpr, e);
+ expr->accept(this);
+ qSwap(uniqueExpr, e);
+ return static_cast<_Expr *>(e);
}
- subexpressions.insert(expr);
- IR::Expr *e = expr;
- qSwap(uniqueExpr, e);
- expr->accept(this);
- qSwap(uniqueExpr, e);
- return static_cast<_Expr *>(e);
+ // the cloned expression is unique by definition
+ // so we don't need to add it to `subexpressions'.
+ return clone(expr);
}
// statements
@@ -508,8 +511,11 @@ void Function::setStatementCount(int cnt)
BasicBlock::~BasicBlock()
{
- foreach (Stmt *s, _statements)
- s->destroyData();
+ foreach (Stmt *s, _statements) {
+ Phi *p = s->asPhi();
+ if (p)
+ p->destroyData();
+ }
}
unsigned BasicBlock::newTemp()
@@ -763,8 +769,12 @@ void BasicBlock::setStatements(const QVector<Stmt *> &newStatements)
Q_ASSERT(newStatements.size() >= _statements.size());
// FIXME: this gets quite inefficient for large basic-blocks, so this function/case should be re-worked.
foreach (Stmt *s, _statements) {
- if (!newStatements.contains(s))
- s->destroyData();
+ Phi *p = s->asPhi();
+ if (!p)
+ continue;
+
+ if (!newStatements.contains(p))
+ p->destroyData();
}
_statements = newStatements;
}
@@ -813,21 +823,27 @@ void BasicBlock::insertStatementBeforeTerminator(Stmt *stmt)
void BasicBlock::replaceStatement(int index, Stmt *newStmt)
{
Q_ASSERT(!isRemoved());
- _statements[index]->destroyData();
+ Phi *p = _statements[index]->asPhi();
+ if (p)
+ p->destroyData();
_statements[index] = newStmt;
}
void BasicBlock::removeStatement(Stmt *stmt)
{
Q_ASSERT(!isRemoved());
- stmt->destroyData();
+ Phi *p = stmt->asPhi();
+ if (p)
+ p->destroyData();
_statements.remove(_statements.indexOf(stmt));
}
void BasicBlock::removeStatement(int idx)
{
Q_ASSERT(!isRemoved());
- _statements[idx]->destroyData();
+ Phi *p = _statements[idx]->asPhi();
+ if (p)
+ p->destroyData();
_statements.remove(idx);
}
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 66528e8bc1..8daad97e8b 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -70,10 +70,6 @@ class QQmlPropertyCache;
class QQmlEnginePrivate;
namespace QV4 {
-struct ExecutionContext;
-}
-
-namespace QV4 {
inline bool isNegative(double d)
{
@@ -230,7 +226,7 @@ struct MemberExpressionResolver
typedef Type (*ResolveFunction)(QQmlEnginePrivate *engine, MemberExpressionResolver *resolver, Member *member);
MemberExpressionResolver()
- : resolveMember(0), data(0), extraData(0), flags(0), isQObjectResolver(false) {}
+ : resolveMember(0), data(0), extraData(0), flags(0) {}
bool isValid() const { return !!resolveMember; }
void clear() { *this = MemberExpressionResolver(); }
@@ -238,8 +234,7 @@ struct MemberExpressionResolver
ResolveFunction resolveMember;
void *data; // Could be pointer to meta object, importNameSpace, etc. - depends on resolveMember implementation
void *extraData; // Could be QQmlTypeNameCache
- unsigned int flags : 31;
- unsigned int isQObjectResolver; // neede for IR dump helpers
+ unsigned int flags;
};
struct Q_AUTOTEST_EXPORT Expr {
@@ -373,23 +368,25 @@ struct Q_AUTOTEST_EXPORT Temp: Expr {
StackSlot
};
+ // Used when temp is used as base in member expression
+ MemberExpressionResolver *memberResolver;
+
unsigned index : 28;
- unsigned kind : 3;
unsigned isReadOnly : 1;
- // Used when temp is used as base in member expression
- MemberExpressionResolver memberResolver;
+ unsigned kind : 3;
Temp()
- : index((1 << 28) - 1)
- , kind(Invalid)
+ : memberResolver(0)
+ , index((1 << 28) - 1)
, isReadOnly(0)
+ , kind(Invalid)
{}
void init(unsigned kind, unsigned index)
{
- this->kind = kind;
this->index = index;
this->isReadOnly = false;
+ this->kind = kind;
}
bool isInvalid() const { return kind == Invalid; }
@@ -605,16 +602,11 @@ struct Member: Expr {
};
struct Stmt {
- struct Data {
- QVector<Expr *> incoming; // used by Phi nodes
- };
-
enum { InvalidId = -1 };
- Data *d;
QQmlJS::AST::SourceLocation location;
- explicit Stmt(int id): d(0), _id(id) {}
+ explicit Stmt(int id): _id(id) {}
virtual ~Stmt()
{
@@ -638,10 +630,6 @@ struct Stmt {
private: // For memory management in BasicBlock
friend struct BasicBlock;
- void destroyData() {
- delete d;
- d = 0;
- }
private:
friend struct Function;
@@ -738,11 +726,21 @@ struct Ret: Stmt {
struct Phi: Stmt {
Temp *targetTemp;
+ struct Data {
+ QVector<Expr *> incoming; // used by Phi nodes
+ };
- Phi(int id): Stmt(id) {}
+ Data *d;
+
+ Phi(int id): Stmt(id), d(0) {}
virtual void accept(StmtVisitor *v) { v->visitPhi(this); }
virtual Phi *asPhi() { return this; }
+
+ void destroyData() {
+ delete d;
+ d = 0;
+ }
};
struct Q_QML_PRIVATE_EXPORT Module {
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 5861138dbe..a0ed77ffc1 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -40,6 +40,7 @@
#include "qv4isel_util_p.h"
#include "qv4util_p.h"
+#include <QtCore/QBuffer>
#include <QtCore/QCoreApplication>
#include <QtCore/QStringList>
#include <QtCore/QSet>
@@ -51,9 +52,6 @@
#include <cassert>
#include <algorithm>
-#undef SHOW_SSA
-#undef DEBUG_MOVEMAPPING
-
QT_USE_NAMESPACE
using namespace QV4;
@@ -61,21 +59,25 @@ using namespace IR;
namespace {
+enum { DebugMoveMapping = 0 };
+
#ifdef QT_NO_DEBUG
enum { DoVerification = 0 };
#else
enum { DoVerification = 1 };
#endif
-Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
-#define qout *qout()
-
-void showMeTheCode(IR::Function *function)
+static void showMeTheCode(IR::Function *function, const char *marker)
{
static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
if (showCode) {
- IRPrinter(&qout).print(function);
- qout << endl;
+ qDebug() << marker;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream stream(&buf);
+ IRPrinter(&stream).print(function);
+ stream << endl;
+ qDebug("%s", buf.data().constData());
}
}
@@ -104,10 +106,9 @@ public:
class BasicBlockSet
{
- typedef std::vector<int> Numbers;
typedef std::vector<bool> Flags;
- Numbers *blockNumbers;
+ QVarLengthArray<int, 8> blockNumbers;
Flags *blockFlags;
IR::Function *function;
enum { MaxVectorCapacity = 8 };
@@ -117,7 +118,7 @@ public:
{
const BasicBlockSet &set;
// ### These two members could go into a union, but clang won't compile (https://codereview.qt-project.org/#change,74259)
- Numbers::const_iterator numberIt;
+ QVarLengthArray<int, 8>::const_iterator numberIt;
size_t flagIt;
friend class BasicBlockSet;
@@ -125,13 +126,13 @@ public:
: set(set)
{
if (end || !set.function) {
- if (set.blockNumbers)
- numberIt = set.blockNumbers->end();
+ if (!set.blockFlags)
+ numberIt = set.blockNumbers.end();
else
flagIt = set.blockFlags->size();
} else {
- if (set.blockNumbers)
- numberIt = set.blockNumbers->begin();
+ if (!set.blockFlags)
+ numberIt = set.blockNumbers.begin();
else
findNextWithFlags(0);
}
@@ -161,8 +162,7 @@ public:
public:
BasicBlock *operator*() const
{
-
- if (set.blockNumbers) {
+ if (!set.blockFlags) {
return set.function->basicBlock(*numberIt);
} else {
Q_ASSERT(flagIt <= static_cast<size_t>(set.function->basicBlockCount()));
@@ -174,7 +174,7 @@ public:
{
if (&set != &other.set)
return false;
- if (set.blockNumbers)
+ if (!set.blockFlags)
return numberIt == other.numberIt;
else
return flagIt == other.flagIt;
@@ -185,7 +185,7 @@ public:
const_iterator &operator++()
{
- if (set.blockNumbers)
+ if (!set.blockFlags)
++numberIt;
else
findNextWithFlags(flagIt + 1);
@@ -197,14 +197,14 @@ public:
friend class const_iterator;
public:
- BasicBlockSet(IR::Function *f = 0): blockNumbers(0), blockFlags(0), function(0)
+ BasicBlockSet(IR::Function *f = 0): blockFlags(0), function(0)
{
if (f)
init(f);
}
#ifdef Q_COMPILER_RVALUE_REFS
- BasicBlockSet(BasicBlockSet &&other): blockNumbers(0), blockFlags(0)
+ BasicBlockSet(BasicBlockSet &&other): blockFlags(0)
{
std::swap(blockNumbers, other.blockNumbers);
std::swap(blockFlags, other.blockFlags);
@@ -213,14 +213,12 @@ public:
#endif // Q_COMPILER_RVALUE_REFS
BasicBlockSet(const BasicBlockSet &other)
- : blockNumbers(0)
- , blockFlags(0)
+ : blockFlags(0)
, function(other.function)
{
if (other.blockFlags)
blockFlags = new Flags(*other.blockFlags);
- else if (other.blockNumbers)
- blockNumbers = new Numbers(*other.blockNumbers);
+ blockNumbers = other.blockNumbers;
}
BasicBlockSet &operator=(const BasicBlockSet &other)
@@ -228,27 +226,24 @@ public:
if (blockFlags) {
delete blockFlags;
blockFlags = 0;
- } else {
- delete blockNumbers;
- blockNumbers = 0;
}
function = other.function;
if (other.blockFlags)
blockFlags = new Flags(*other.blockFlags);
- else if (other.blockNumbers)
- blockNumbers = new Numbers(*other.blockNumbers);
+ blockNumbers = other.blockNumbers;
return *this;
}
- ~BasicBlockSet() { delete blockNumbers; delete blockFlags; }
+ ~BasicBlockSet()
+ {
+ delete blockFlags;
+ }
void init(IR::Function *f)
{
Q_ASSERT(!function);
Q_ASSERT(f);
function = f;
- blockNumbers = new Numbers;
- blockNumbers->reserve(MaxVectorCapacity);
}
bool empty() const
@@ -265,21 +260,20 @@ public:
return;
}
- for (std::vector<int>::const_iterator i = blockNumbers->begin(), ei = blockNumbers->end();
- i != ei; ++i)
- if (*i == bb->index())
+ for (int i = 0; i < blockNumbers.size(); ++i) {
+ if (blockNumbers[i] == bb->index())
return;
+ }
- if (blockNumbers->size() == MaxVectorCapacity) {
+ if (blockNumbers.size() == MaxVectorCapacity) {
blockFlags = new Flags(function->basicBlockCount(), false);
- for (std::vector<int>::const_iterator i = blockNumbers->begin(), ei = blockNumbers->end();
- i != ei; ++i)
- blockFlags->operator[](*i) = true;
- delete blockNumbers;
- blockNumbers = 0;
+ for (int i = 0; i < blockNumbers.size(); ++i) {
+ blockFlags->operator[](blockNumbers[i]) = true;
+ }
+ blockNumbers.clear();
blockFlags->operator[](bb->index()) = true;
} else {
- blockNumbers->push_back(bb->index());
+ blockNumbers.append(bb->index());
}
}
@@ -292,9 +286,9 @@ public:
return;
}
- for (std::vector<int>::iterator i = blockNumbers->begin(), ei = blockNumbers->end(); i != ei; ++i) {
- if (*i == bb->index()) {
- blockNumbers->erase(i);
+ for (int i = 0; i < blockNumbers.size(); ++i) {
+ if (blockNumbers[i] == bb->index()) {
+ blockNumbers.remove(i);
return;
}
}
@@ -318,8 +312,8 @@ public:
if (blockFlags)
return (*blockFlags)[bb->index()];
- for (std::vector<int>::const_iterator i = blockNumbers->begin(), ei = blockNumbers->end(); i != ei; ++i) {
- if (*i == bb->index())
+ for (int i = 0; i < blockNumbers.size(); ++i) {
+ if (blockNumbers[i] == bb->index())
return true;
}
@@ -402,11 +396,6 @@ class DominatorTree
todo = worklist.back();
worklist.pop_back();
}
-
-#if defined(SHOW_SSA)
- for (int i = 0; i < nodes.size(); ++i)
- qDebug("\tL%d: dfnum = %d, parent = %d", i, dfnum[i], parent[i]);
-#endif // SHOW_SSA
}
BasicBlockIndex ancestorWithLowestSemi(BasicBlockIndex v, std::vector<BasicBlockIndex> &worklist) {
@@ -592,6 +581,9 @@ public:
}
if (DebugDominatorFrontiers) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Dominator Frontiers:" << endl;
foreach (BasicBlock *n, function->basicBlocks()) {
if (n->isRemoved())
@@ -606,6 +598,7 @@ public:
}
qout << "}" << endl;
}
+ qDebug("%s", buf.data().constData());
}
if (DebugDominatorFrontiers && DebugCodeCanUseLotsOfCpu) {
@@ -624,7 +617,7 @@ public:
}
}
if (!hasDominatedSucc) {
- qout << fBlock << " in DF[" << n->index() << "] has no dominated predecessors" << endl;
+ qDebug("%d in DF[%d] has no dominated predecessors", fBlock->index(), n->index());
}
Q_ASSERT(hasDominatedSucc);
}
@@ -646,6 +639,9 @@ public:
void dumpImmediateDominators() const
{
if (DebugImmediateDominators) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Immediate dominators:" << endl;
foreach (BasicBlock *to, function->basicBlocks()) {
if (to->isRemoved())
@@ -659,6 +655,7 @@ public:
qout << "(none)";
qout << " -> " << to->index() << endl;
}
+ qDebug("%s", buf.data().constData());
}
}
@@ -687,7 +684,7 @@ public:
return;
for (size_t i = 0, ei = idom.size(); i != ei; ++i) {
if (idom[i] == dominator) {
- BasicBlock *bb = function->basicBlock(i);
+ BasicBlock *bb = function->basicBlock(int(i));
if (!bb->isRemoved())
siblings.insert(bb);
}
@@ -949,14 +946,11 @@ public:
for (int i = 0; i < function->tempCount; ++i)
_defsites[i].init(function);
nonLocals.resize(function->tempCount);
- A_orig.resize(function->basicBlockCount());
- for (int i = 0, ei = A_orig.size(); i != ei; ++i)
+ const size_t ei = function->basicBlockCount();
+ A_orig.resize(ei);
+ for (size_t i = 0; i != ei; ++i)
A_orig[i].reserve(8);
-#if defined(SHOW_SSA)
- qout << "Variables collected:" << endl;
-#endif // SHOW_SSA
-
foreach (BasicBlock *bb, function->basicBlocks()) {
if (bb->isRemoved())
continue;
@@ -966,17 +960,6 @@ public:
foreach (Stmt *s, bb->statements())
s->accept(this);
}
-
-#if defined(SHOW_SSA)
- qout << "Non-locals:" << endl;
- foreach (const Temp &nonLocal, nonLocals) {
- qout << "\t";
- nonLocal.dump(qout);
- qout << endl;
- }
-
- qout << "end collected variables." << endl;
-#endif // SHOW_SSA
}
const std::vector<Temp> &allTemps() const
@@ -1038,12 +1021,6 @@ protected:
addTemp(t);
if (isCollectable(t)) {
-#if defined(SHOW_SSA)
- qout << '\t';
- t->dump(qout);
- qout << " -> L" << currentBB->index << endl;
-#endif // SHOW_SSA
-
_defsites[t->index].insert(currentBB);
addDefInCurrentBlock(t);
@@ -1097,16 +1074,12 @@ public:
private:
std::vector<DefUse> _defUses;
- class Temps: public QVector<Temp> {
- public:
- Temps() { reserve(4); }
- };
+ typedef QVarLengthArray<Temp, 4> Temps;
std::vector<Temps> _usesPerStatement;
void ensure(Temp *newTemp)
{
if (_defUses.size() <= newTemp->index) {
- _defUses.reserve(newTemp->index + _defUses.size() / 3 + 1);
_defUses.resize(newTemp->index + 1);
}
}
@@ -1115,7 +1088,6 @@ private:
{
Q_ASSERT(s->id() >= 0);
if (static_cast<unsigned>(s->id()) >= _usesPerStatement.size()) {
- _usesPerStatement.reserve(s->id() + _usesPerStatement.size() / 3 + 1);
_usesPerStatement.resize(s->id() + 1);
}
}
@@ -1143,10 +1115,10 @@ public:
}
unsigned statementCount() const
- { return _usesPerStatement.size(); }
+ { return unsigned(_usesPerStatement.size()); }
unsigned tempCount() const
- { return _defUses.size(); }
+ { return unsigned(_defUses.size()); }
const Temp &temp(int idx) const
{ return _defUses[idx].temp; }
@@ -1161,9 +1133,10 @@ public:
defUse.blockOfStatement = defBlock;
}
- QList<UntypedTemp> defsUntyped() const
+ QVector<UntypedTemp> defsUntyped() const
{
- QList<UntypedTemp> res;
+ QVector<UntypedTemp> res;
+ res.reserve(tempCount());
foreach (const DefUse &du, _defUses)
if (du.isValid())
res.append(UntypedTemp(du.temp));
@@ -1172,8 +1145,9 @@ public:
std::vector<const Temp *> defs() const {
std::vector<const Temp *> res;
- res.reserve(_defUses.size());
- for (unsigned i = 0, ei = _defUses.size(); i != ei; ++i) {
+ const size_t ei = _defUses.size();
+ res.reserve(ei);
+ for (size_t i = 0; i != ei; ++i) {
const DefUse &du = _defUses.at(i);
if (du.isValid())
res.push_back(&du.temp);
@@ -1242,7 +1216,7 @@ public:
ensure(s);
}
- const QVector<Temp> &usedVars(Stmt *s) const
+ const Temps &usedVars(Stmt *s) const
{
Q_ASSERT(s->id() >= 0);
Q_ASSERT(static_cast<unsigned>(s->id()) < _usesPerStatement.size());
@@ -1274,6 +1248,9 @@ public:
void dump() const
{
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Defines and uses:" << endl;
foreach (const DefUse &du, _defUses) {
if (!du.isValid())
@@ -1288,24 +1265,19 @@ public:
qout << endl;
}
qout << "Uses per statement:" << endl;
- for (unsigned i = 0, ei = _usesPerStatement.size(); i != ei; ++i) {
+ for (size_t i = 0, ei = _usesPerStatement.size(); i != ei; ++i) {
qout << " " << i << ":";
foreach (const Temp &t, _usesPerStatement[i])
qout << ' ' << t.index;
qout << endl;
}
+ qDebug("%s", buf.data().constData());
}
};
void insertPhiNode(const Temp &a, BasicBlock *y, IR::Function *f) {
-#if defined(SHOW_SSA)
- qout << "-> inserted phi node for variable ";
- a.dump(qout);
- qout << " in block " << y->index << endl;
-#endif
-
Phi *phiNode = f->NewStmt<Phi>();
- phiNode->d = new Stmt::Data;
+ phiNode->d = new Phi::Data;
phiNode->targetTemp = f->New<Temp>();
phiNode->targetTemp->init(a.kind, a.index);
y->prependStatement(phiNode);
@@ -1643,22 +1615,14 @@ protected:
// see [Appel]. For the changes needed for semi-pruned SSA form, and for its advantages, see [Briggs].
void convertToSSA(IR::Function *function, const DominatorTree &df, DefUses &defUses)
{
-#if defined(SHOW_SSA)
- qout << "Converting function ";
- if (function->name)
- qout << *function->name;
- else
- qout << "<no name>";
- qout << " to SSA..." << endl;
-#endif // SHOW_SSA
-
// Collect all applicable variables:
VariableCollector variables(function);
// Prepare for phi node insertion:
std::vector<std::vector<bool> > A_phi;
- A_phi.resize(function->basicBlockCount());
- for (int i = 0, ei = A_phi.size(); i != ei; ++i)
+ const size_t ei = function->basicBlockCount();
+ A_phi.resize(ei);
+ for (size_t i = 0; i != ei; ++i)
A_phi[i].assign(function->tempCount, false);
std::vector<BasicBlock *> W;
@@ -2113,12 +2077,15 @@ protected:
struct DiscoveredType {
int type;
- MemberExpressionResolver memberResolver;
+ MemberExpressionResolver *memberResolver;
- DiscoveredType() : type(UnknownType) {}
- DiscoveredType(Type t) : type(t) { Q_ASSERT(type != QObjectType); }
- explicit DiscoveredType(int t) : type(t) { Q_ASSERT(type != QObjectType); }
- explicit DiscoveredType(MemberExpressionResolver memberResolver) : type(QObjectType), memberResolver(memberResolver) {}
+ DiscoveredType() : type(UnknownType), memberResolver(0) {}
+ DiscoveredType(Type t) : type(t), memberResolver(0) { Q_ASSERT(type != QObjectType); }
+ explicit DiscoveredType(int t) : type(t), memberResolver(0) { Q_ASSERT(type != QObjectType); }
+ explicit DiscoveredType(MemberExpressionResolver *memberResolver)
+ : type(QObjectType)
+ , memberResolver(memberResolver)
+ { Q_ASSERT(memberResolver); }
bool test(Type t) const { return type & t; }
bool isNumber() const { return (type & NumberType) && !(type & ~NumberType); }
@@ -2223,7 +2190,7 @@ class TypeInference: public StmtVisitor, public ExprVisitor
this->type = type;
fullyTyped = type.type != UnknownType;
}
- explicit TypingResult(MemberExpressionResolver memberResolver)
+ explicit TypingResult(MemberExpressionResolver *memberResolver)
: type(memberResolver)
, fullyTyped(true)
{}
@@ -2248,30 +2215,39 @@ public:
continue;
if (DebugTypeInference) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout<<"Typing stmt ";
IRPrinter(&qout).print(s);
- qout<<endl;
+ qDebug("%s", buf.data().constData());
}
if (!run(s)) {
*_worklist += s;
if (DebugTypeInference) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout<<"Pushing back stmt: ";
IRPrinter(&qout).print(s);
- qout<<endl;
+ qDebug("%s", buf.data().constData());
}
} else {
if (DebugTypeInference) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout<<"Finished: ";
IRPrinter(&qout).print(s);
- qout<<endl;
+ qDebug("%s", buf.data().constData());
}
}
}
PropagateTempTypes propagator(_defUses);
- for (unsigned i = 0, ei = _tempTypes.size(); i != ei; ++i) {
- const Temp &temp = _defUses.temp(i);
+ for (size_t i = 0, ei = _tempTypes.size(); i != ei; ++i) {
+ const Temp &temp = _defUses.temp(int(i));
if (temp.kind == Temp::Invalid)
continue;
const DiscoveredType &tempType = _tempTypes[i];
@@ -2306,9 +2282,9 @@ private:
void setType(Expr *e, DiscoveredType ty) {
if (Temp *t = e->asTemp()) {
if (DebugTypeInference)
- qout << "Setting type for temp " << t->index
- << " to " << typeName(Type(ty.type)) << " (" << ty.type << ")"
- << endl;
+ qDebug() << "Setting type for temp" << t->index
+ << " to " << typeName(Type(ty.type)) << "(" << ty.type << ")"
+ << endl;
DiscoveredType &it = _tempTypes[t->index];
if (it != ty) {
@@ -2316,9 +2292,12 @@ private:
if (DebugTypeInference) {
foreach (Stmt *s, _defUses.uses(*t)) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Pushing back dependent stmt: ";
IRPrinter(&qout).print(s);
- qout<<endl;
+ qDebug("%s", buf.data().constData());
}
}
@@ -2345,7 +2324,7 @@ protected:
virtual void visitRegExp(IR::RegExp *) { _ty = TypingResult(VarType); }
virtual void visitName(Name *) { _ty = TypingResult(VarType); }
virtual void visitTemp(Temp *e) {
- if (e->memberResolver.isValid())
+ if (e->memberResolver && e->memberResolver->isValid())
_ty = TypingResult(e->memberResolver);
else
_ty = TypingResult(_tempTypes[e->index]);
@@ -2456,9 +2435,9 @@ protected:
virtual void visitMember(Member *e) {
_ty = run(e->base);
- if (_ty.fullyTyped && _ty.type.memberResolver.isValid()) {
- MemberExpressionResolver &resolver = _ty.type.memberResolver;
- _ty.type.type = resolver.resolveMember(qmlEngine, &resolver, e);
+ if (_ty.fullyTyped && _ty.type.memberResolver && _ty.type.memberResolver->isValid()) {
+ MemberExpressionResolver *resolver = _ty.type.memberResolver;
+ _ty.type.type = resolver->resolveMember(qmlEngine, resolver, e);
} else
_ty.type = VarType;
}
@@ -2492,8 +2471,8 @@ protected:
}
_ty.type.type |= ty.type.type;
_ty.fullyTyped &= ty.fullyTyped;
- if (_ty.type.test(QObjectType))
- _ty.type.memberResolver.clear(); // ### TODO: find common ancestor meta-object
+ if (_ty.type.test(QObjectType) && _ty.type.memberResolver)
+ _ty.type.memberResolver->clear(); // ### TODO: find common ancestor meta-object
}
switch (_ty.type.type) {
@@ -2539,7 +2518,7 @@ public:
Q_UNUSED(f);
QVector<UntypedTemp> knownOk;
- QList<UntypedTemp> candidates = _defUses.defsUntyped();
+ QVector<UntypedTemp> candidates = _defUses.defsUntyped();
while (!candidates.isEmpty()) {
UntypedTemp temp = candidates.last();
candidates.removeLast();
@@ -2711,15 +2690,6 @@ class TypePropagation: public StmtVisitor, public ExprVisitor {
if (requestedType != UnknownType) {
if (e->type != requestedType) {
if (requestedType & NumberType || requestedType == BoolType) {
-#ifdef SHOW_SSA
- QTextStream os(stdout, QIODevice::WriteOnly);
- os << "adding conversion from " << typeName(e->type)
- << " to " << typeName(requestedType) << " for expression ";
- e->dump(os);
- os << " in statement ";
- _currStmt->dump(os);
- os << endl;
-#endif
if (insertConversion)
addConversion(e, requestedType);
return true;
@@ -3416,15 +3386,9 @@ public:
QHash<BasicBlock *, BasicBlock *> go()
{
- showMeTheCode(function);
+ showMeTheCode(function, "Before block scheduling");
schedule(function->basicBlock(0));
-#if defined(SHOW_SSA)
- qDebug() << "Block sequence:";
- foreach (BasicBlock *bb, sequence)
- qDebug("\tL%d", bb->index());
-#endif // SHOW_SSA
-
Q_ASSERT(function->liveBasicBlocksCount() == sequence.size());
function->setScheduledBlocks(sequence);
function->renumberBasicBlocks();
@@ -3438,8 +3402,8 @@ void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) {
if (bb && bb->out.size() > 1) {
foreach (BasicBlock *bb2, bb->out) {
if (bb2 && bb2->in.size() > 1) {
- qout << "found critical edge between block "
- << bb->index() << " and block " << bb2->index();
+ qDebug() << "found critical edge between block"
+ << bb->index() << "and block" << bb2->index();
Q_ASSERT(false);
}
}
@@ -3450,14 +3414,13 @@ void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) {
void cleanupBasicBlocks(IR::Function *function)
{
- showMeTheCode(function);
+ showMeTheCode(function, "Before basic block cleanup");
// Algorithm: this is the iterative version of a depth-first search for all blocks that are
// reachable through outgoing edges, starting with the start block and all exception handler
// blocks.
QBitArray reachableBlocks(function->basicBlockCount());
- QVector<BasicBlock *> postponed;
- postponed.reserve(16);
+ QVarLengthArray<BasicBlock *, 16> postponed;
for (int i = 0, ei = function->basicBlockCount(); i != ei; ++i) {
BasicBlock *bb = function->basicBlock(i);
if (i == 0 || bb->isExceptionHandler())
@@ -3503,7 +3466,7 @@ void cleanupBasicBlocks(IR::Function *function)
function->removeBasicBlock(bb);
}
- showMeTheCode(function);
+ showMeTheCode(function, "After basic block cleanup");
}
inline Const *isConstPhi(Phi *phi)
@@ -3784,42 +3747,42 @@ bool tryOptimizingComparison(Expr *&expr)
switch (b->op) {
case OpGt:
- leftConst->value = Runtime::compareGreaterThan(&l, &r);
+ leftConst->value = Runtime::compareGreaterThan(l, r);
leftConst->type = BoolType;
expr = leftConst;
return true;
case OpLt:
- leftConst->value = Runtime::compareLessThan(&l, &r);
+ leftConst->value = Runtime::compareLessThan(l, r);
leftConst->type = BoolType;
expr = leftConst;
return true;
case OpGe:
- leftConst->value = Runtime::compareGreaterEqual(&l, &r);
+ leftConst->value = Runtime::compareGreaterEqual(l, r);
leftConst->type = BoolType;
expr = leftConst;
return true;
case OpLe:
- leftConst->value = Runtime::compareLessEqual(&l, &r);
+ leftConst->value = Runtime::compareLessEqual(l, r);
leftConst->type = BoolType;
expr = leftConst;
return true;
case OpStrictEqual:
- leftConst->value = Runtime::compareStrictEqual(&l, &r);
+ leftConst->value = Runtime::compareStrictEqual(l, r);
leftConst->type = BoolType;
expr = leftConst;
return true;
case OpEqual:
- leftConst->value = Runtime::compareEqual(&l, &r);
+ leftConst->value = Runtime::compareEqual(l, r);
leftConst->type = BoolType;
expr = leftConst;
return true;
case OpStrictNotEqual:
- leftConst->value = Runtime::compareStrictNotEqual(&l, &r);
+ leftConst->value = Runtime::compareStrictNotEqual(l, r);
leftConst->type = BoolType;
expr = leftConst;
return true;
case OpNotEqual:
- leftConst->value = Runtime::compareNotEqual(&l, &r);
+ leftConst->value = Runtime::compareNotEqual(l, r);
leftConst->type = BoolType;
expr = leftConst;
return true;
@@ -3836,8 +3799,14 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
if (!showCode)
return;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
+
struct Util {
- static void genLoop(LoopDetection::LoopInfo *loop)
+ QTextStream &qout;
+ Util(QTextStream &qout): qout(qout) {}
+ void genLoop(LoopDetection::LoopInfo *loop)
{
qout << " subgraph \"cluster" << quint64(loop) << "\" {\n";
qout << " L" << loop->loopHeader->index() << ";\n";
@@ -3856,7 +3825,7 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
foreach (LoopDetection::LoopInfo *l, loops) {
if (l->parentLoop == 0)
- Util::genLoop(l);
+ Util(qout).genLoop(l);
}
foreach (BasicBlock *bb, f->basicBlocks()) {
@@ -3874,7 +3843,9 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
qout << " L" << idx << " -> L" << out->index() << "\n";
}
- qout << "}\n" << flush;
+ qout << "}\n";
+ buf.close();
+ qDebug("%s", buf.data().constData());
}
} // anonymous namespace
@@ -4307,6 +4278,10 @@ public:
void dump() const
{
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
+
qout << "Life ranges:" << endl;
qout << "Intervals:" << endl;
foreach (const LifeTimeInterval *range, _sortedIntervals->intervals()) {
@@ -4315,7 +4290,7 @@ public:
}
IRPrinter printer(&qout);
- for (int i = 0, ei = _liveIn.size(); i != ei; ++i) {
+ for (size_t i = 0, ei = _liveIn.size(); i != ei; ++i) {
qout << "L" << i <<" live-in: ";
QList<Temp> live = QList<Temp>::fromSet(_liveIn.at(i));
if (live.isEmpty())
@@ -4327,6 +4302,8 @@ public:
}
qout << endl;
}
+ buf.close();
+ qDebug("%s", buf.data().constData());
}
private:
@@ -4340,7 +4317,7 @@ private:
foreach (Stmt *s, successor->statements()) {
if (Phi *phi = s->asPhi()) {
- if (Temp *t = phi->d->incoming[bbIndex]->asTemp())
+ if (Temp *t = phi->d->incoming.at(bbIndex)->asTemp())
live.insert(*t);
} else {
break;
@@ -4376,7 +4353,7 @@ private:
_sortedIntervals->add(&lti);
}
//### TODO: use DefUses from the optimizer, because it already has all this information
- for (unsigned i = 0, ei = collector.inputs.size(); i != ei; ++i) {
+ for (size_t i = 0, ei = collector.inputs.size(); i != ei; ++i) {
Temp *opd = collector.inputs[i];
interval(opd).addRange(start(bb), usePosition(s));
live.insert(*opd);
@@ -4557,7 +4534,7 @@ protected:
clonedStmt = phi;
phi->targetTemp = clone(stmt->targetTemp);
- phi->d = new Stmt::Data;
+ phi->d = new Phi::Data;
foreach (Expr *in, stmt->d->incoming)
phi->d->incoming.append(clone(in));
block->appendStatement(phi);
@@ -4911,6 +4888,8 @@ void LifeTimeInterval::addRange(int from, int to) {
LifeTimeInterval LifeTimeInterval::split(int atPosition, int newStart)
{
Q_ASSERT(atPosition < newStart || newStart == InvalidPosition);
+ Q_ASSERT(atPosition <= _end);
+ Q_ASSERT(newStart <= _end || newStart == InvalidPosition);
if (_ranges.isEmpty() || atPosition < _ranges.first().start)
return LifeTimeInterval();
@@ -5074,12 +5053,7 @@ Optimizer::Optimizer(IR::Function *function)
void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool peelLoops)
{
-#if defined(SHOW_SSA)
- qout << "##### NOW IN FUNCTION " << (function->name ? qPrintable(*function->name) : "anonymous!")
- << " with " << function->basicBlocks.size() << " basic blocks." << endl << flush;
-#endif
-
-// showMeTheCode(function);
+ showMeTheCode(function, "Before running the optimizer");
cleanupBasicBlocks(function);
@@ -5093,7 +5067,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
// qout << "SSA for " << (function->name ? qPrintable(*function->name) : "<anonymous>") << endl;
ConvertArgLocals(function).toTemps();
- showMeTheCode(function);
+ showMeTheCode(function, "After converting arguments to locals");
// Calculate the dominator tree:
DominatorTree df(function);
@@ -5105,7 +5079,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
LoopDetection loopDetection(df);
loopDetection.run(function);
- showMeTheCode(function);
+ showMeTheCode(function, "After loop detection");
// cfg2dot(function, loopDetection.allLoops());
if (peelLoops) {
@@ -5113,7 +5087,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
LoopPeeling(df).run(innerLoops);
// cfg2dot(function, loopDetection.allLoops());
- showMeTheCode(function);
+ showMeTheCode(function, "After loop peeling");
if (!innerLoops.isEmpty())
verifyImmediateDominators(df, function);
}
@@ -5136,14 +5110,14 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
// qout << "Cleaning up phi nodes..." << endl;
cleanupPhis(defUses);
- showMeTheCode(function);
+ showMeTheCode(function, "After cleaning up phi-nodes");
StatementWorklist worklist(function);
if (doTypeInference) {
// qout << "Running type inference..." << endl;
TypeInference(qmlEngine, defUses).run(worklist);
- showMeTheCode(function);
+ showMeTheCode(function, "After type inference");
// qout << "Doing reverse inference..." << endl;
ReverseInference(defUses).run(function);
@@ -5160,7 +5134,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
// qout << "Running SSA optimization..." << endl;
worklist.reset();
optimizeSSA(worklist, defUses, df);
- showMeTheCode(function);
+ showMeTheCode(function, "After optimization");
verifyImmediateDominators(df, function);
verifyCFG(function);
@@ -5186,7 +5160,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
// qout << "Doing block scheduling..." << endl;
// df.dumpImmediateDominators();
startEndLoops = BlockScheduler(function, df).go();
- showMeTheCode(function);
+ showMeTheCode(function, "After basic block scheduling");
// cfg2dot(function);
#ifndef QT_NO_DEBUG
@@ -5223,16 +5197,20 @@ void Optimizer::convertOutOfSSA() {
}
}
- #if defined(DEBUG_MOVEMAPPING)
- QTextStream os(stdout, QIODevice::WriteOnly);
- os << "Move mapping for function ";
- if (function->name)
- os << *function->name;
- else
- os << (void *) function;
- os << " on basic-block L" << bb->index << ":" << endl;
- moves.dump();
- #endif // DEBUG_MOVEMAPPING
+ if (DebugMoveMapping) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
+ os << "Move mapping for function ";
+ if (function->name)
+ os << *function->name;
+ else
+ os << (void *) function;
+ os << " on basic-block L" << bb->index() << ":" << endl;
+ moves.dump();
+ buf.close();
+ qDebug("%s", buf.data().constData());
+ }
moves.order();
@@ -5288,22 +5266,12 @@ QSet<Jump *> Optimizer::calculateOptionalJumps()
reachableWithoutJump.insert(bb);
}
-#if 0
- QTextStream out(stdout, QIODevice::WriteOnly);
- out << "Jumps to ignore:" << endl;
- foreach (Jump *j, removed) {
- out << "\t" << j->id << ": ";
- j->dump(out, Stmt::MIR);
- out << endl;
- }
-#endif
-
return optional;
}
-void Optimizer::showMeTheCode(IR::Function *function)
+void Optimizer::showMeTheCode(IR::Function *function, const char *marker)
{
- ::showMeTheCode(function);
+ ::showMeTheCode(function, marker);
}
static inline bool overlappingStorage(const Temp &t1, const Temp &t2)
@@ -5345,14 +5313,18 @@ void MoveMapping::add(Expr *from, Temp *to) {
if (Temp *t = from->asTemp()) {
if (overlappingStorage(*t, *to)) {
// assignments like fp1 = fp1 or var{&1} = double{&1} can safely be skipped.
-#if defined(DEBUG_MOVEMAPPING)
- QTextStream os(stderr, QIODevice::WriteOnly);
- os << "Skipping ";
- to->dump(os);
- os << " <- ";
- from->dump(os);
- os << endl;
-#endif // DEBUG_MOVEMAPPING
+ if (DebugMoveMapping) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
+ IRPrinter printer(&os);
+ os << "Skipping ";
+ printer.print(to);
+ os << " <- ";
+ printer.print(from);
+ buf.close();
+ qDebug("%s", buf.data().constData());
+ }
return;
}
}
@@ -5403,20 +5375,24 @@ QList<IR::Move *> MoveMapping::insertMoves(BasicBlock *bb, IR::Function *functio
void MoveMapping::dump() const
{
-#if defined(DEBUG_MOVEMAPPING)
- QTextStream os(stdout, QIODevice::WriteOnly);
- os << "Move mapping has " << _moves.size() << " moves..." << endl;
- foreach (const Move &m, _moves) {
- os << "\t";
- m.to->dump(os);
- if (m.needsSwap)
- os << " <-> ";
- else
- os << " <-- ";
- m.from->dump(os);
- os << endl;
+ if (DebugMoveMapping) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
+ IRPrinter printer(&os);
+ os << "Move mapping has " << _moves.size() << " moves..." << endl;
+ foreach (const Move &m, _moves) {
+ os << "\t";
+ printer.print(m.to);
+ if (m.needsSwap)
+ os << " <-> ";
+ else
+ os << " <-- ";
+ printer.print(m.from);
+ os << endl;
+ }
+ qDebug("%s", buf.data().constData());
}
-#endif // DEBUG_MOVEMAPPING
}
MoveMapping::Action MoveMapping::schedule(const Move &m, QList<Move> &todo, QList<Move> &delayed,
@@ -5427,19 +5403,24 @@ MoveMapping::Action MoveMapping::schedule(const Move &m, QList<Move> &todo, QLis
if (!output.contains(dependency)) {
if (delayed.contains(dependency)) {
// We have a cycle! Break it by swapping instead of assigning.
-#if defined(DEBUG_MOVEMAPPING)
- delayed+=m;
- QTextStream out(stderr, QIODevice::WriteOnly);
- out<<"we have a cycle! temps:" << endl;
- foreach (const Move &m, delayed) {
- out<<"\t";
- m.to->dump(out);
- out<<" <- ";
- m.from->dump(out);
- out<<endl;
+ if (DebugMoveMapping) {
+ delayed += m;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream out(&buf);
+ IRPrinter printer(&out);
+ out<<"we have a cycle! temps:" << endl;
+ foreach (const Move &m, delayed) {
+ out<<"\t";
+ printer.print(m.to);
+ out<<" <- ";
+ printer.print(m.from);
+ out<<endl;
+ }
+ qDebug("%s", buf.data().constData());
+ delayed.removeOne(m);
}
- delayed.removeOne(m);
-#endif // DEBUG_MOVEMAPPING
+
return NeedsSwap;
} else {
delayed.append(m);
diff --git a/src/qml/compiler/qv4ssa_p.h b/src/qml/compiler/qv4ssa_p.h
index 21a5b038b6..3cfacaee27 100644
--- a/src/qml/compiler/qv4ssa_p.h
+++ b/src/qml/compiler/qv4ssa_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** 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
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -219,7 +219,7 @@ public:
QSet<IR::Jump *> calculateOptionalJumps();
- static void showMeTheCode(Function *function);
+ static void showMeTheCode(Function *function, const char *marker);
private:
Function *function;