From c091f3f4b4889ac6be26e018c5e8b673adee7c47 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Mon, 18 Mar 2019 11:49:05 +0100 Subject: V4: Do not invert non-reflexive comparison binops This is only useful for the few (4) comparisons where we have specialized instructions, and it's very error-prone. Change-Id: I37efe94f54ba0adf393d9236df2d13aa6685eb46 Fixes: QTBUG-74476 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4codegen.cpp | 85 +++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 49 deletions(-) (limited to 'src/qml/compiler') diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index b0bec5b6f2..3fdba08f20 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1738,59 +1738,46 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re return Reference::fromAccumulator(this); } -static QSOperator::Op operatorForSwappedOperands(QSOperator::Op oper) -{ - switch (oper) { - case QSOperator::StrictEqual: return QSOperator::StrictEqual; - case QSOperator::StrictNotEqual: return QSOperator::StrictNotEqual; - case QSOperator::Equal: return QSOperator::Equal; - case QSOperator::NotEqual: return QSOperator::NotEqual; - case QSOperator::Gt: return QSOperator::Le; - case QSOperator::Ge: return QSOperator::Lt; - case QSOperator::Lt: return QSOperator::Ge; - case QSOperator::Le: return QSOperator::Gt; - default: Q_UNIMPLEMENTED(); return QSOperator::Invalid; - } -} - Codegen::Reference Codegen::jumpBinop(QSOperator::Op oper, Reference &left, Reference &right) { - if (left.isConstant()) { - oper = operatorForSwappedOperands(oper); - qSwap(left, right); - } + // See if we can generate specialized comparison instructions: + if (oper == QSOperator::Equal || oper == QSOperator::NotEqual) { + // Because == and != are reflexive, we can do the following: + if (left.isConstant() && !right.isConstant()) + qSwap(left, right); // null==a -> a==null - if (right.isConstant() && (oper == QSOperator::Equal || oper == QSOperator::NotEqual)) { - Value c = Value::fromReturnedValue(right.constant); - if (c.isNull() || c.isUndefined()) { - left.loadInAccumulator(); - if (oper == QSOperator::Equal) { - Instruction::CmpEqNull cmp; - bytecodeGenerator->addInstruction(cmp); - addCJump(); - return Reference(); - } else if (oper == QSOperator::NotEqual) { - Instruction::CmpNeNull cmp; - bytecodeGenerator->addInstruction(cmp); - addCJump(); - return Reference(); - } - } else if (c.isInt32()) { - left.loadInAccumulator(); - if (oper == QSOperator::Equal) { - Instruction::CmpEqInt cmp; - cmp.lhs = c.int_32(); - bytecodeGenerator->addInstruction(cmp); - addCJump(); - return Reference(); - } else if (oper == QSOperator::NotEqual) { - Instruction::CmpNeInt cmp; - cmp.lhs = c.int_32(); - bytecodeGenerator->addInstruction(cmp); - addCJump(); - return Reference(); - } + if (right.isConstant()) { + Value c = Value::fromReturnedValue(right.constant); + if (c.isNull() || c.isUndefined()) { + left.loadInAccumulator(); + if (oper == QSOperator::Equal) { + Instruction::CmpEqNull cmp; + bytecodeGenerator->addInstruction(cmp); + addCJump(); + return Reference(); + } else if (oper == QSOperator::NotEqual) { + Instruction::CmpNeNull cmp; + bytecodeGenerator->addInstruction(cmp); + addCJump(); + return Reference(); + } + } else if (c.isInt32()) { + left.loadInAccumulator(); + if (oper == QSOperator::Equal) { + Instruction::CmpEqInt cmp; + cmp.lhs = c.int_32(); + bytecodeGenerator->addInstruction(cmp); + addCJump(); + return Reference(); + } else if (oper == QSOperator::NotEqual) { + Instruction::CmpNeInt cmp; + cmp.lhs = c.int_32(); + bytecodeGenerator->addInstruction(cmp); + addCJump(); + return Reference(); + } + } } } -- cgit v1.2.3 From 497a795081b95d487f0ec33746cc2a12ffeae5a0 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 21 Mar 2019 16:25:55 +0100 Subject: Initialize TranslationData padding before writing cache files Otherwise the resulting files differ subtly. Fixes: QTBUG-74532 Change-Id: I12b4f1ba6dda781d63ad50cce87861ba24582bf7 Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmlirbuilder.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/qml/compiler') diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index ab43ea350b..868f600a10 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1108,6 +1108,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg QV4::CompiledData::TranslationData translationData; translationData.number = -1; translationData.commentIndex = 0; // empty string + translationData.padding = 0; if (!args || !args->expression) return; // no arguments, stop @@ -1148,6 +1149,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg QV4::CompiledData::TranslationData translationData; translationData.number = -1; translationData.commentIndex = 0; // empty string, but unused + translationData.padding = 0; if (!args || !args->expression) return; // no arguments, stop -- cgit v1.2.3 From 90a08b0c52fbe20ea3324f7315c04c48c95a8e61 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 22 Mar 2019 09:43:16 +0100 Subject: Fix memory "leaks" in qmlcachegen The CompilationUnit class owns the unit data. An exception was made in bootstrap builds, where it was up to the caller to free the memory. This lead to cases in qmlcachegen where we didn't free the memory. This is best fixed by unifying the behavior. This fixes the build when using an ASAN enabled build, as the runtime aborts after calling qmlcachegen due to "leaks". Change-Id: I8b55b4e302a9569a1d4e09eeb488c479368b50f0 Reviewed-by: Lars Knoll --- src/qml/compiler/qv4compileddata.cpp | 10 +++++++++- src/qml/compiler/qv4compileddata_p.h | 4 ---- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src/qml/compiler') diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 7906b3572c..9ffcb81fa2 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -98,18 +98,25 @@ CompilationUnit::CompilationUnit(const Unit *unitData, const QString &fileName, setUnitData(unitData, nullptr, fileName, finalUrlString); } -#ifndef V4_BOOTSTRAP CompilationUnit::~CompilationUnit() { +#ifndef V4_BOOTSTRAP unlink(); +#endif if (data) { if (data->qmlUnit() != qmlData) free(const_cast(qmlData)); qmlData = nullptr; +#ifndef V4_BOOTSTRAP if (!(data->flags & QV4::CompiledData::Unit::StaticData)) free(const_cast(data)); +#else + // Unconditionally free the memory. In the dev tools we create units that have + // the flag set and will be saved to disk, so intended to persist later. + free(const_cast(data)); +#endif } data = nullptr; #if Q_BYTE_ORDER == Q_BIG_ENDIAN @@ -120,6 +127,7 @@ CompilationUnit::~CompilationUnit() delete [] imports; imports = nullptr; } +#ifndef V4_BOOTSTRAP QString CompilationUnit::localCacheFilePath(const QUrl &url) { diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 1341c91e97..3fd9fdf74b 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -1079,11 +1079,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit final : public CompilationUnitBase const QmlUnit *qmlData = nullptr; public: CompilationUnit(const Unit *unitData = nullptr, const QString &fileName = QString(), const QString &finalUrlString = QString()); -#ifdef V4_BOOTSTRAP - ~CompilationUnit() {} -#else ~CompilationUnit(); -#endif void addref() { -- cgit v1.2.3