diff options
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 334 | ||||
-rw-r--r-- | src/qml/compiler/qqmlirbuilder_p.h | 30 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 106 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler_p.h | 31 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 34 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 24 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 42 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 44 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 16 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler_p.h | 14 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 14 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 14 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth.cpp | 24 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth_p.h | 14 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.cpp | 30 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.h | 14 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_util_p.h | 14 | ||||
-rw-r--r-- | src/qml/compiler/qv4jsir.cpp | 66 | ||||
-rw-r--r-- | src/qml/compiler/qv4jsir_p.h | 60 | ||||
-rw-r--r-- | src/qml/compiler/qv4ssa.cpp | 471 | ||||
-rw-r--r-- | src/qml/compiler/qv4ssa_p.h | 16 |
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"), ¬InRevision); + } + 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(<i); } //### 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; |